import { _decorator, Component, Node, v3, Vec3 } from 'cc'; import { Skill } from './Skill'; import { GBundle } from '../../../game/ConfigRes'; import { WeaponType } from '../../../manager/WeaponDataManager'; import { GEvent } from 'db://assets/mx/module/event/GEvent'; const { ccclass, property } = _decorator; @ccclass('iceWeaponSchedule') export class iceWeaponSchedule extends Component { @property({ type: Node, tooltip: "技能效果层上" }) skillLayerTop: Node = null; //武器初始个数 冰棒 private bgWeaponCount: number = 0 private binggunNodeArray: Node[] = [] //所有的冰棒武器 // 缓存主角的发射点,避免 update 内反复 getChildByName/clone private _weaponLaunchNode: Node | null = null; private _tmpIceConePos: Vec3 = v3(0, 0, 0); //冰棍转转转 specialSkillInfo = []; rotateSpeed: number = 1; rotateVolume: number = 1; isCreateBinggun: boolean = false; specialTimeFix = 1 specialTimeAdd = 0 binggunAllAtk: number = 0; isBinggunCrit: boolean = false; addRateAtk: number = 1; getBgWeaponCount() { return this.bgWeaponCount } setBgWeaponCount(count: number) { this.bgWeaponCount = count } setGameData(rotateVolume, rotateSpeed, specialSkillInfo, binggunAllAtk, isBinggunCrit, specialTimeFix) { this.rotateVolume = rotateVolume this.rotateSpeed = rotateSpeed this.specialSkillInfo = specialSkillInfo this.binggunAllAtk = binggunAllAtk this.isBinggunCrit = isBinggunCrit this.specialTimeFix = specialTimeFix this.addRateAtk = 1 } getBinggunNodeArray() { return this.binggunNodeArray } setBinggunNodeArray(arr: Node[]) { this.binggunNodeArray = arr } setIsCreateBinggun(isCreate: boolean) { this.isCreateBinggun = isCreate } start() { this.rotateSpeed = 1; this.rotateVolume = 1; this.isCreateBinggun = false; this.specialSkillInfo = []; this.specialTimeFix = 1 this.specialTimeAdd = 0 this.binggunAllAtk = 0 this.isBinggunCrit = false this.addRateAtk = 1 this.bgWeaponCount = 0 this.binggunNodeArray = [] GEvent.Ins.on(GEvent.GameRestart, this.gameRestart, this); } gameRestart() { this.rotateSpeed = 1; this.rotateVolume = 1; this.isCreateBinggun = false; this.specialSkillInfo = []; this.specialTimeFix = 1 this.specialTimeAdd = 0 this.binggunAllAtk = 0 this.bgWeaponCount = 0 this.binggunNodeArray = [] this.isBinggunCrit = false this.addRateAtk = 1 } createBinggunNodeArray(weaponProperty, weaponId, weaponState) { let radius = 100 let weaponCount = weaponProperty.weaponCount this.rotateVolume = weaponProperty.volume this.rotateSpeed = weaponProperty.rotateSpeed //转圈速率秒 if (this.rotateSpeed <= 0) { this.rotateSpeed = 0.5 } //console.log('冰棒+++武器旋转速率+++++++==',this.rotateSpeed) this.specialSkillInfo = weaponProperty.specialSkillInfo //['13,2,3'] if (this.specialSkillInfo.length > 0) { let arr = this.specialSkillInfo[0].split(',') this.specialTimeFix = Number(arr[1]) } this.binggunAllAtk = weaponProperty.allAtk this.isBinggunCrit = weaponProperty.isCrit this.addRateAtk = weaponProperty.addRateAtk if (this.bgWeaponCount != weaponCount) { if (this.specialSkillInfo.length > 0) { let arr = this.specialSkillInfo[0].split(',') this.specialTimeFix = Number(arr[1]) } this.isCreateBinggun = true //位置计算,围绕着主角旋转的 //每个节点的角度 let _angle = 360 / weaponCount for (let k = this.bgWeaponCount; k < weaponCount; k++) { this.scheduleOnce(async () => { //计算旋转角度和偏移的位置 let angle = k * _angle; let radian = angle * Math.PI / 180; let addPos = v3( Math.cos(radian) * radius, Math.sin(radian) * radius, 0 ); //gg.audio.playEffect({ name: '牙签受击',path:'sound/武器音效/'}); let weaponNode = await this.instantiateSingleWeapon(weaponId, weaponProperty.volume, addPos) if (!weaponNode) return; let skillComp = weaponNode.getComponent(Skill); // weaponNode['specialTimeAdd'] = 0 this.binggunNodeArray.push(weaponNode) //weaponNode.angle = angle; skillComp.setData(weaponState.config, v3(0, 0, 0)); skillComp.setInstanceId(100000 + k) if (k == weaponCount - 1) { for (let kk = 0; kk < this.binggunNodeArray.length; kk++) { let angle = kk * _angle; let radian = angle * Math.PI / 180; let addPos = v3( Math.cos(radian) * radius, Math.sin(radian) * radius, 0 ); const wp = gg.game.CurentBattle.PlayerController.playerNode .getChildByName('weaponLaunchNode') .worldPosition.clone() .add(addPos); this.binggunNodeArray[kk].setWorldPosition(wp); this.binggunNodeArray[kk].angle = angle; if (kk == this.binggunNodeArray.length - 1) { this.isCreateBinggun = false } } } }, 0.05) } this.bgWeaponCount = weaponCount } } /** * 实例化单个武器 * @param weaponId 武器ID * @param volume 武器缩放比例 * @param addPos 武器位置偏移 * @param index 第几个位置 */ async instantiateSingleWeapon(weaponId: number, volume: number, addPos?: Vec3, index?: number) { let weaponNode = await gg.res.getNodeAsync(`prefab/武器/`, `weapon${weaponId}`, GBundle.BattleGameWeapon) if (!weaponNode) return null; weaponNode.setParent(this.node, true); weaponNode.scale = v3(volume, volume, 1) const add = addPos ?? v3(0, 0, 0); weaponNode.worldPosition = gg.game.CurentBattle.PlayerController.playerNode .getChildByName('weaponLaunchNode') .worldPosition.clone() .add(add); return weaponNode } update(dt: number) { if (!gg.game.CurentBattle.canUpdateFrame()) { return } const scaledDt = dt * gg.game.CurentBattle.TimeScale; if (this.binggunNodeArray.length && this.isCreateBinggun == false) { let radius = 100; // 旋转半径 // 计算每秒旋转角度:360度 / 旋转一周时间 let rotateAnglePerSecond = 360 / this.rotateSpeed; // 根据实际帧间隔计算每次需要旋转的角度 let rotateAnglePerFrame = rotateAnglePerSecond * scaledDt; // 遍历所有冰棒节点,实现流畅旋转 if (!this._weaponLaunchNode || !this._weaponLaunchNode.isValid) { this._weaponLaunchNode = gg.game.CurentBattle.PlayerController.playerNode.getChildByName('weaponLaunchNode'); } const basePos = this._weaponLaunchNode!.worldPosition; const baseX = basePos.x; const baseY = basePos.y - 50; const baseZ = basePos.z; for (let index = 0; index < this.binggunNodeArray.length; index++) { const weaponNode = this.binggunNodeArray[index]; if (weaponNode && weaponNode.isValid) { weaponNode.setScale(this.rotateVolume, this.rotateVolume, 1); weaponNode.angle -= rotateAnglePerFrame; if (weaponNode.angle <= 0) weaponNode.angle += 360; // 计算新的位置偏移量(保持围绕主角旋转) const radian = weaponNode.angle * Math.PI / 180; const addX = Math.cos(radian) * radius; const addY = Math.sin(radian) * radius; weaponNode.setWorldPosition(baseX + addX, baseY + addY, baseZ); } } //有特殊技能,每把刀specialTimeFix秒释放冰锥,释放的时候刀的角度在前方,后方不释放冰锥 if (this.specialSkillInfo.length > 0) { let fixNum = 4 this.specialTimeAdd += scaledDt if (this.specialTimeAdd >= this.specialTimeFix) { this.specialTimeAdd = 0 const arr = this.specialSkillInfo[0].split(','); const atk = this.binggunAllAtk * Number(arr[2]); const scale = this.rotateVolume; const baseZ = basePos.z; const spacing = (40 + 5) * scale; // 需求保持固定向上:前方行中心点始终在玩家上方 const forwardDist = 220 * scale; const centerX = basePos.x; const centerY = basePos.y + forwardDist; const validWeapons = this.binggunNodeArray.filter(n => !!n && n.isValid); const emitCount = Math.min(fixNum, validWeapons.length); const half = (emitCount - 1) * 0.5; for (let i = 0; i < emitCount; i++) { const weaponNode = validWeapons[i]; const lateral = (i - half) * spacing; const x = centerX + lateral; const y = centerY; this._tmpIceConePos.set(x, y, baseZ); const skill = weaponNode.getComponent(Skill); if (!skill) continue; skill.playIceCone('冰棒刀冰锥', this._tmpIceConePos, scale, 80 * scale, atk, this.isBinggunCrit, this.addRateAtk, this.skillLayerTop) } } } } } onDestroy() { GEvent.Ins.off(GEvent.GameRestart, this.gameRestart, this); this.unscheduleAllCallbacks() } }