CocosCyberpunk/assets/scripts/logic/actor/actor-equipment.ts

227 lines
9.0 KiB
TypeScript
Raw Normal View History

2023-02-22 09:50:51 +08:00
/*
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
import { _decorator, Node, game, math } from 'cc';
import { Msg } from "../../core/msg/msg";
import { Res } from '../../core/res/res';
import { ResCache } from '../../core/res/res-cache';
import { UtilNode } from '../../core/util/util';
import { Actor } from "./actor";
import { BagItem } from './actor-bag';
import { fun } from '../../core/util/fun';
import { ActorEquipBase } from './actor-equip-base';
export class ActorEquipment {
// The character object to which the current equipment belongs.
_actor:Actor;
// A pool of cached equipment objects.
//The purpose is to avoid the creation and destruction of objects at runtime.
equipPool:{ [key:string]:Node } = {};
// Dictionary of weapon skeleton nodes for mounted equipment.
equipBoneNode: { [key:string]:Node } = {};
// Current equipment node.
currentEquipNode:Node | undefined;
// bag information of current equipment.
currentEquipItem:BagItem | undefined;
// The component object of the current weapon.
currentEquip:ActorEquipBase | undefined;
// The stability value of the equipment.
// The purpose is to describe the stability value of the shot.
// This value affects the size of the aiming area of the shot.
stableValue = 1;
constructor(actor:Actor) {
// Initialize the Actor object corresponding to the equipment manager passed in.
this._actor = actor;
// Get all node maps with the name 'weapon_root'.
this.equipBoneNode = UtilNode.getChildrenByNameBlur(this._actor.node, 'weapon_root');
// Initialize the cache pool for the equipment list.
const equipmentList = this._actor._data.cache_equipment_list;
// Get the length of the equipment list.
const length = equipmentList.length;
for(let i = 0; i < length; i++) {
// Get the equipment name from the current index.
const weaponName = equipmentList[i];
// Get the prefab of the equipment from the resource buffer pool.
const prefab = ResCache.Instance.getPrefab(weaponName + '_tps');
// Get the bone node of the equipment.
const bindNode = this.equipBoneNode[this._actor._data.weapon_bone];
// Instantiate the game object and set the parent node to the bone node.
const nodePrefab = Res.inst(prefab, bindNode);
// Set the object pool key to map to this instantiated weapon object.
this.equipPool[weaponName] = nodePrefab;
// Set the activity of this cache object to false.
nodePrefab.active = false;
}
// Equip the default weapon.
this.equip(actor._data.default_equip_index);
}
public equip(replaceEquipmentIndex:number):boolean {
// Get the current bag equipment index.
const currentEquipmentIndex = this._actor._data.current_equipment_index;
// If the current bag index is the same as the updated bag index,
// true is no need to switch weapons, false is need to switch weapons.
if (currentEquipmentIndex !== replaceEquipmentIndex) {
// Get bag equipment name list from player data.
const equipment_name_list = this._actor._data.equipment_name_list;
// Get the name of the equipment name to be switched from the equipment list.
const changeEquipmentName = equipment_name_list[replaceEquipmentIndex];
// Return false if the equipment does not exist or is not empty to cancel switching equipment.
if(!changeEquipmentName || changeEquipmentName.length <= 0) return false;
// Uninstall current equipment.
this.unEquip();
// Replace new equipment data and models.
// Here you need to do a time delay with the animation.
const self = this;
fun.delay(()=>{
const items = self._actor._data.items;
self.currentEquipNode = self.equipPool[changeEquipmentName];
self.currentEquipItem = items[changeEquipmentName];
self.currentEquipNode!.active = true;
self.currentEquipNode!.emit('init',this.currentEquipItem);
self.currentEquipNode!.emit('do', 'take_out');
self._actor._data.current_equipment_index = replaceEquipmentIndex;
self.currentEquip = self.currentEquipNode?.getComponent(ActorEquipBase)!;
if(this._actor.isPlayer) {
//const mainCamera = CameraSetting.main?.camera;
//if(mainCamera) mainCamera.fov = this.currentEquipItem!.fov;
Msg.emit('msg_change_equip');
Msg.emit('msg_update_equip_info');
}
}, 0.3)
return true;
}else{
return false;
}
}
/**
* Uninstall current equipment.
*/
public unEquip() {
//Get the index of the current equipment.s
const currentEquipmentIndex = this._actor._data.current_equipment_index;
// Compare whether the current equipment index value is -1.
// An index of -1 means no current equipment, skip setting.
if (currentEquipmentIndex !== -1) {
// Get a list of equipment names.
const equipment_name_list = this._actor._data.equipment_name_list;
// Get the current equipment name.
const currentEquipmentName = equipment_name_list[currentEquipmentIndex];
// Whether the current equipment name exists.
// false means it does not exist, the return function does not uninstall the equipment
if(!currentEquipmentName) {
console.warn(`The equipment index that does not exist, the index id is ${currentEquipmentIndex}, the object is ${this._actor?.node.name}`)
return;
}
// Get the current equipment object node from the equipment object pool.
const currentEquipmentNode = this.equipPool[currentEquipmentName];
//Whether the object pool contains equipment objects.
if (currentEquipmentNode) {
// Notify the equipment node to perform recovery behavior.
currentEquipmentNode.emit('do', 'take_back');
}else{
console.warn(``);
}
}
}
/**
* Execution equipment action.
* @param action Name of the execution action.
*/
public do(action:string) {
// Execute the current equipment action.
this.currentEquipNode?.emit('do', action);
}
/**
* Update to set the range of Aim.
* @param normalizeCharacterMoveSpeed Normalized character movement speed.
* @param toMax The aim range is set to the maximum value: true is set, false is not set.
*/
public updateAim(normalizeCharacterMoveSpeed:number, toMax = false) {
if (this.currentEquipItem === undefined) {
if (this.stableValue !== 0){
this.stableValue = 0;
if(this._actor.isPlayer) Msg.emit('msg_update_aim', this.stableValue);
}
}else{
const equipData = this.currentEquipItem.data;
const equipStable = equipData.stable_max_value;
let currentStable = 0;
if(toMax) {
this.stableValue = equipData.stable_max_value;
currentStable = equipData.stable_max_value;
}else{
if (equipStable !== 0) {
currentStable = Math.abs(normalizeCharacterMoveSpeed) <= 0.001 ? equipData.stable_min_value : equipData.stable_max_value * normalizeCharacterMoveSpeed;
currentStable = Math.max(equipData.stable_min_value, currentStable);
}
this.stableValue = math.lerp(this.stableValue, currentStable, game.deltaTime * equipData.stable_smooth);
}
if(this._actor.isPlayer) Msg.emit('msg_update_aim', this.stableValue);
}
}
}