You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1288 lines
57 KiB
1288 lines
57 KiB
|
1 week ago
|
import { _decorator, Component, find, isValid, Layers, Node, sp, UITransform, v3, Vec3 } from 'cc';
|
||
|
|
import { SpriteLoad } from '../../mx/components/SpriteLoad';
|
||
|
|
import { GBundle, GPath } from '../game/ConfigRes';
|
||
|
|
import { shootPoint } from './shootPoint';
|
||
|
|
import { GEvent } from '../../mx/module/event/GEvent';
|
||
|
|
import { SkillType } from '../ui/BattleGame/WeaponSkill/SkillTypes';
|
||
|
|
import { IWeaponProperty, SpecialSkillType } from '../ui/BattleGame/BattleDataManager';
|
||
|
|
import { Skill } from '../ui/BattleGame/WeaponSkill/Skill';
|
||
|
|
import { LaserLine } from '../ui/BattleGame/WeaponSkill/LaserLine';
|
||
|
|
import { tetriNode } from './tetriNode';
|
||
|
|
import { role } from './role';
|
||
|
|
import { WeaponType } from '../manager/WeaponDataManager';
|
||
|
|
import { BattleType } from '../manager/ChapterDataManager';
|
||
|
|
import { UILayer } from '../../mx/module/ui/UIManager';
|
||
|
|
|
||
|
|
/** 救救我鸭:场上角色初始武器 id */
|
||
|
|
export const JIUJIUWOYA_INIT_WEAPON_ID = 1;
|
||
|
|
const { ccclass, property } = _decorator;
|
||
|
|
|
||
|
|
/**方块武器载体脚本,用于绑定武器和技能
|
||
|
|
* TetriType == 1 基础武器方块,只有武器和技能
|
||
|
|
* TetriType == 5 藤蔓方块,既有武器还有其他特殊功能
|
||
|
|
*/
|
||
|
|
@ccclass('tetriWeaponCarrier')
|
||
|
|
export class tetriWeaponCarrier extends Component {
|
||
|
|
|
||
|
|
/** 攻击动画相对首个弹体/技能生成提前的秒数(先播「攻击」再发射) */
|
||
|
|
private static readonly ATK_ANIM_LEAD_SEC = 0.4;
|
||
|
|
private static readonly ATK_ANIM_LEAD_SEC2 = 0.1;
|
||
|
|
|
||
|
|
roleConfig = [
|
||
|
|
{ id: 1, name: "Tetris_att_I", mainPosi: { x: -0.308, y: -10.809 }, animSkin: '小紫', scalex: -0.25, scaley: 0.25 },
|
||
|
|
{ id: 2, name: "Tetris_att_1_1", mainPosi: { x: -1.484, y: -12.331 }, animSkin: '小紫', scalex: -0.25, scaley: 0.25 },
|
||
|
|
{ id: 3, name: "Tetris_att_J1", mainPosi: { x: -28.877, y: -25.077 }, animSkin: '小蓝', scalex: -0.25, scaley: 0.25 },
|
||
|
|
{ id: 4, name: "Tetris_att_J2", mainPosi: { x: -13.884, y: 23.864 }, animSkin: '小蓝', scalex: -0.25, scaley: 0.25 },
|
||
|
|
{ id: 5, name: "Tetris_att_J3", mainPosi: { x: 33.67, y: 5.42 }, animSkin: '小蓝', scalex: -0.25, scaley: 0.25 },
|
||
|
|
{ id: 6, name: "Tetris_att_J", mainPosi: { x: 16.683, y: -43.542 }, animSkin: '小蓝', scalex: -0.25, scaley: 0.25 },
|
||
|
|
|
||
|
|
{ id: 7, name: "Tetris_att_L1", mainPosi: { x: -29.799, y: 4.73 }, animSkin: '小橙', scalex: -0.25, scaley: 0.25 },
|
||
|
|
{ id: 8, name: "Tetris_att_L2", mainPosi: { x: 15.513, y: 21.501 }, animSkin: '小橙', scalex: -0.25, scaley: 0.25 },
|
||
|
|
{ id: 9, name: "Tetris_att_L3", mainPosi: { x: 33.276, y: -29.162 }, animSkin: '小橙', scalex: -0.25, scaley: 0.25 },
|
||
|
|
{ id: 10, name: "Tetris_att_L", mainPosi: { x: -14.952, y: -44.351 }, animSkin: '小橙', scalex: -0.25, scaley: 0.25 },
|
||
|
|
|
||
|
|
{ id: 11, name: "Tetris_att_Z1_1", mainPosi: { x: 2.397, y: -12.412 }, animSkin: '小憨', scalex: -0.25, scaley: 0.25 },
|
||
|
|
{ id: 12, name: "Tetris_att_Z1", mainPosi: { x: -0.035, y: -9.153 }, animSkin: '小憨', scalex: -0.2, scaley: 0.2 },
|
||
|
|
|
||
|
|
{ id: 13, name: "Tetris_att_Z2_1", mainPosi: { x: 16.189, y: -10.274 }, animSkin: '小红', scalex: -0.25, scaley: 0.25 },
|
||
|
|
{ id: 14, name: "Tetris_att_Z2", mainPosi: { x: -0.057, y: -12.142 }, animSkin: '小红', scalex: -0.25, scaley: 0.25 },
|
||
|
|
|
||
|
|
{ id: 15, name: "Tetris_att_凸_1", mainPosi: { x: -14.41, y: -10.235 }, animSkin: '小贱', scalex: -0.25, scaley: 0.25 },
|
||
|
|
{ id: 16, name: "Tetris_att_凸_2", mainPosi: { x: 0.131, y: 1.91 }, animSkin: '小贱', scalex: -0.25, scaley: 0.25 },
|
||
|
|
{ id: 17, name: "Tetris_att_凸_3", mainPosi: { x: 15.166, y: -13.766 }, animSkin: '小贱', scalex: -0.25, scaley: 0.25 },
|
||
|
|
{ id: 18, name: "Tetris_att_凸", mainPosi: { x: -0.001, y: -25.291 }, animSkin: '小贱', scalex: -0.25, scaley: 0.25 },
|
||
|
|
|
||
|
|
]
|
||
|
|
|
||
|
|
|
||
|
|
private _config: ITableBattleCube | null = null;
|
||
|
|
_curentWeaponId: number = 0
|
||
|
|
weaponNode: Node = null;
|
||
|
|
timeoutIndex: number = 0
|
||
|
|
animState: string;
|
||
|
|
|
||
|
|
/**初始角色朝向*/
|
||
|
|
initRoleFacing: number = 0;
|
||
|
|
initRoleFacingFix: number = 0;
|
||
|
|
private roleNode: Node | null = null;
|
||
|
|
private roleBaseAbsScaleX: number = 1;
|
||
|
|
_isBattleScene = false //是否是战斗场景相机
|
||
|
|
_isCanShoot = true //是否可以射击
|
||
|
|
|
||
|
|
setConfig(config: ITableBattleCube, isCanShoot = true, isBattleScene = false) {
|
||
|
|
this._config = config
|
||
|
|
this._isBattleScene = isBattleScene
|
||
|
|
this._isCanShoot = isCanShoot
|
||
|
|
const cubeName = config.cubename;
|
||
|
|
if (gg.game.CurentBattle.BattleType === BattleType.OrangeWeaponMode_Ya) {
|
||
|
|
this._curentWeaponId = JIUJIUWOYA_INIT_WEAPON_ID;
|
||
|
|
if (cubeName) {
|
||
|
|
gg.game.CurentBattle.TetriWeaponMap.set(cubeName, JIUJIUWOYA_INIT_WEAPON_ID);
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
const weaponId = gg.game.CurentBattle.TetriWeaponMap.get(cubeName);
|
||
|
|
this._curentWeaponId = weaponId ?? config.weaponid ?? 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
getWeapontype(): number {
|
||
|
|
return this._config?.weapontype ?? 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 救救我鸭:直接换武器(不走路径方块 / weapontype) */
|
||
|
|
applyWeaponId(weaponId: number, playReplaceEffect = false) {
|
||
|
|
if (!Number.isFinite(weaponId) || weaponId <= 0) return;
|
||
|
|
this._curentWeaponId = weaponId;
|
||
|
|
const cubeName = this._config?.cubename;
|
||
|
|
if (cubeName && gg.game?.CurentBattle) {
|
||
|
|
gg.game.CurentBattle.TetriWeaponMap.set(cubeName, weaponId);
|
||
|
|
}
|
||
|
|
this.changeWeaponConf();
|
||
|
|
if (playReplaceEffect && gg.game?.CurentBattle?.BattleType === BattleType.OrangeWeaponMode_Ya) {
|
||
|
|
this.showSkillSelectCompleteEffect(false, 0.3);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
protected onDestroy(): void {
|
||
|
|
const block = this.findCarrierTetriNode()?.node ?? this.node;
|
||
|
|
gg.game?.CurentBattle?.pruneDetachedBattleLayers?.(block);
|
||
|
|
const weapon = this.weaponNode;
|
||
|
|
const role = this.roleNode;
|
||
|
|
this.weaponNode = null;
|
||
|
|
this.roleNode = null;
|
||
|
|
// 武器挂在「角色/武器」下,先回收武器再回收角色,避免子随父一起进半销毁态
|
||
|
|
if (this.timeoutIndex) clearTimeout(this.timeoutIndex as unknown as number);
|
||
|
|
GEvent.Ins.off(GEvent.ChangeCubeWeaponConfig, this.ChangeCubeWeapon, this)
|
||
|
|
GEvent.Ins.off(GEvent.StraightWeaponShoot, this.StraightWeaponShoot, this)
|
||
|
|
GEvent.Ins.off(GEvent.StraightWeaponLaunch, this.StraightWeaponLaunch, this)
|
||
|
|
GEvent.Ins.off(GEvent.StraightWeaponShootNum, this.StraightWeaponShootNum, this)
|
||
|
|
GEvent.Ins.off(GEvent.StraightWeaponSplit, this.StraightWeaponSplit, this)
|
||
|
|
GEvent.Ins.off(GEvent.StraightWeaponPierce, this.StraightWeaponPierce, this)
|
||
|
|
GEvent.Ins.off(GEvent.ParabolaCollide, this.ParabolaCollide, this)
|
||
|
|
GEvent.Ins.off(GEvent.ParabolaNoCollide, this.ParabolaNoCollide, this)
|
||
|
|
GEvent.Ins.off(GEvent.SinglePointLaser, this.SinglePointLaser, this)
|
||
|
|
GEvent.Ins.off(GEvent.StraightTargetDamage, this.StraightTargetDamage, this)
|
||
|
|
GEvent.Ins.off(GEvent.LightningElectricity, this.LightningElectricity, this)
|
||
|
|
this.safePutPoolNode(weapon);
|
||
|
|
this.safePutPoolNode(role);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
start() {
|
||
|
|
//ChangeCubeWeaponConfig
|
||
|
|
GEvent.Ins.on(GEvent.ChangeCubeWeaponConfig, this.ChangeCubeWeapon, this)
|
||
|
|
//武器发射事件
|
||
|
|
GEvent.Ins.on(GEvent.StraightWeaponShoot, this.StraightWeaponShoot, this)//直线弹幕
|
||
|
|
GEvent.Ins.on(GEvent.StraightWeaponLaunch, this.StraightWeaponLaunch, this)//直线弹射
|
||
|
|
GEvent.Ins.on(GEvent.StraightWeaponShootNum, this.StraightWeaponShootNum, this)//直线数量
|
||
|
|
GEvent.Ins.on(GEvent.StraightWeaponSplit, this.StraightWeaponSplit, this) //直线分裂
|
||
|
|
GEvent.Ins.on(GEvent.StraightWeaponPierce, this.StraightWeaponPierce, this)//直线穿透
|
||
|
|
GEvent.Ins.on(GEvent.ParabolaCollide, this.ParabolaCollide, this)//抛物线碰撞
|
||
|
|
GEvent.Ins.on(GEvent.ParabolaNoCollide, this.ParabolaNoCollide, this)//抛物线没有碰撞
|
||
|
|
GEvent.Ins.on(GEvent.SinglePointLaser, this.SinglePointLaser, this)//单点激光
|
||
|
|
GEvent.Ins.on(GEvent.StraightTargetDamage, this.StraightTargetDamage, this)//直线目标持续伤害
|
||
|
|
GEvent.Ins.on(GEvent.LightningElectricity, this.LightningElectricity, this)//雷电电击攻击单体
|
||
|
|
|
||
|
|
if(gg.game.CurentBattle.BattleType == BattleType.OrangeWeaponMode_Ya){
|
||
|
|
//已经有角色了直接修改皮肤
|
||
|
|
this.scheduleOnce(() => {
|
||
|
|
//this.addWeapon()
|
||
|
|
this.createRoleNode2()
|
||
|
|
}, 0.02)
|
||
|
|
}else{
|
||
|
|
this.scheduleOnce(() => {
|
||
|
|
this.createRoleNode()
|
||
|
|
}, 0.02)
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
createRoleNode2(){
|
||
|
|
if (!this._config) {
|
||
|
|
console.error('[tetriWeaponCarrier] createRoleNode: _config 为空,请保证 setConfig 在 start 之前已调用');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
this.roleNode = this.node
|
||
|
|
const conf = this.roleConfig.find(item => item.name == this._config.cubename);
|
||
|
|
// console.log('conf',conf);
|
||
|
|
if (conf) {
|
||
|
|
// this.roleNode.setPosition(conf.mainPosi.x, conf.mainPosi.y);
|
||
|
|
this.roleNode.setScale(conf.scalex, conf.scaley);
|
||
|
|
const anim = this.roleNode.getChildByName('anim')?.getComponent(sp.Skeleton);
|
||
|
|
if (anim) {
|
||
|
|
anim.setAnimation(0, '待机', true);
|
||
|
|
anim.setSkin(conf.animSkin);
|
||
|
|
} else {
|
||
|
|
console.warn('[tetriWeaponCarrier] createRoleNode: 角色 prefab 缺少 anim 子节点', this._config.cubename);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
this.scheduleOnce(() => {
|
||
|
|
if (!isValid(this.node)) return;
|
||
|
|
this.setView();
|
||
|
|
}, 0.1);
|
||
|
|
|
||
|
|
this.initRoleFacing = this.roleNode.scale.x;
|
||
|
|
this.initRoleFacingFix = this.roleNode.scale.x;
|
||
|
|
const abs = Math.abs(this.initRoleFacingFix);
|
||
|
|
this.roleBaseAbsScaleX = abs > 1e-6 ? abs : 1;
|
||
|
|
}
|
||
|
|
createRoleNode() {
|
||
|
|
// 先挂角色节点,再 setView -> addWeapon(依赖子路径 角色/anim、角色/武器)
|
||
|
|
if (!this._config) {
|
||
|
|
console.error('[tetriWeaponCarrier] createRoleNode: _config 为空,请保证 setConfig 在 start 之前已调用');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
// instantiate(整块) / 参考方块拷贝会带上已有「角色」;若再从池里取会叠两个
|
||
|
|
const dupDestroy: Node[] = [];
|
||
|
|
let existingRole: Node | null = null;
|
||
|
|
for (let i = 0; i < this.node.children.length; i++) {
|
||
|
|
const c = this.node.children[i];
|
||
|
|
if (c.name === '角色') {
|
||
|
|
if (!existingRole) existingRole = c;
|
||
|
|
else dupDestroy.push(c);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
for (const d of dupDestroy) {
|
||
|
|
if (d?.isValid) d.destroy();
|
||
|
|
}
|
||
|
|
|
||
|
|
let roleNode: Node | null = existingRole?.isValid ? existingRole : null;
|
||
|
|
if (!roleNode) {
|
||
|
|
void gg.res.getNodeAsync('角色/', '角色', GBundle.tetriCards).then((loaded) => {
|
||
|
|
if (!loaded?.isValid || !this.node?.isValid) return;
|
||
|
|
this._setupRoleNode(loaded);
|
||
|
|
});
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this._setupRoleNode(roleNode);
|
||
|
|
}
|
||
|
|
|
||
|
|
private _setupRoleNode(roleNode: Node) {
|
||
|
|
roleNode.setParent(this.node);
|
||
|
|
this.roleNode = roleNode;
|
||
|
|
roleNode.active = true;
|
||
|
|
|
||
|
|
const roleComp = roleNode.getComponent(role);
|
||
|
|
roleComp?.setFollowTarget(this.findCarrierTetriNode()?.node ?? this.node);
|
||
|
|
|
||
|
|
const conf = this.roleConfig.find(item => item.name == this._config.cubename);
|
||
|
|
// console.log('conf',conf);
|
||
|
|
if (conf) {
|
||
|
|
roleNode.setPosition(conf.mainPosi.x, conf.mainPosi.y);
|
||
|
|
roleNode.setScale(conf.scalex, conf.scaley);
|
||
|
|
const anim = roleNode.getChildByName('anim')?.getComponent(sp.Skeleton);
|
||
|
|
if (anim) {
|
||
|
|
anim.setAnimation(0, '待机', true);
|
||
|
|
anim.setSkin(conf.animSkin);
|
||
|
|
} else {
|
||
|
|
console.warn('[tetriWeaponCarrier] createRoleNode: 角色 prefab 缺少 anim 子节点', this._config.cubename);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
if (this._isBattleScene) {
|
||
|
|
console.log('我是在战斗场景相机下创建角色', this.node.layer)
|
||
|
|
this.setLayerMask(roleNode, this.node.layer)
|
||
|
|
}
|
||
|
|
this.scheduleOnce(() => {
|
||
|
|
if (!isValid(this.node)) return;
|
||
|
|
this.setView();
|
||
|
|
}, 0.1);
|
||
|
|
|
||
|
|
this.initRoleFacing = this.roleNode.scale.x;
|
||
|
|
this.initRoleFacingFix = this.roleNode.scale.x;
|
||
|
|
const abs = Math.abs(this.initRoleFacingFix);
|
||
|
|
this.roleBaseAbsScaleX = abs > 1e-6 ? abs : 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**将“角色”翻转到面向目标 x(只改 scale.x,不改大小) */
|
||
|
|
private faceRoleToWorldX(targetWorldX: number) {
|
||
|
|
if (!this.roleNode || !isValid(this.roleNode)) return;
|
||
|
|
// 用载体方块作为参考坐标,更稳定(避免“角色”子节点有额外偏移)
|
||
|
|
const selfX = this.node.worldPosition.x;
|
||
|
|
const dx = targetWorldX - selfX;
|
||
|
|
if (Math.abs(dx) < 0.01) return;
|
||
|
|
|
||
|
|
// 你给的基准:初始一定是“脸朝右”,但 scale.x 可能正/负
|
||
|
|
// 所以把初始符号视为“朝右符号”,朝左时取反即可
|
||
|
|
const rightSign = this.initRoleFacingFix >= 0 ? 1 : -1;
|
||
|
|
const dir = dx >= 0 ? rightSign : -rightSign;
|
||
|
|
const s = this.roleNode.scale;
|
||
|
|
const newX = this.roleBaseAbsScaleX * dir;
|
||
|
|
if (Math.abs(s.x - newX) > 1e-6) {
|
||
|
|
this.roleNode.setScale(newX, s.y, s.z);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private faceRoleToMonster(monsterNode: Node | null) {
|
||
|
|
if(gg.game.CurentBattle.BattleType == BattleType.OrangeWeaponMode_Ya){
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (!monsterNode || !isValid(monsterNode)) return;
|
||
|
|
this.faceRoleToWorldX(monsterNode.worldPosition.x);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 回收到 gg.res 节点池。父节点被 destroy 时,子节点可能已在销毁流程中,
|
||
|
|
* 必须先脱父且 isValid 再 putNode,否则 putNode 里 getComponentsInChildren 会空引用。
|
||
|
|
*/
|
||
|
|
private safePutPoolNode(n: Node | null): void {
|
||
|
|
if (!n) return;
|
||
|
|
if (!isValid(n)) return;
|
||
|
|
try {
|
||
|
|
if (n.parent) n.destroy();
|
||
|
|
//gg.res.putNode(n);
|
||
|
|
} catch (e) {
|
||
|
|
console.warn('[tetriWeaponCarrier] safePutPoolNode failed', e);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
setView() {
|
||
|
|
const conf = gg.data.project.getWeaponData(this._curentWeaponId);
|
||
|
|
if (!conf) {
|
||
|
|
console.error('[tetriWeaponCarrier] setView: 武器表无数据 weaponId=', this._curentWeaponId, this._config?.cubename);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this.addWeapon(conf.weaponani);
|
||
|
|
//this.changeIcon(conf.typeicon);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
ChangeCubeWeapon(cubename: string, weaponid: number) {
|
||
|
|
if (gg.game?.CurentBattle?.BattleType === BattleType.OrangeWeaponMode_Ya) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (cubename == this._config?.cubename) {
|
||
|
|
this._curentWeaponId = weaponid;
|
||
|
|
this.changeWeaponConf();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 三选一完成格子效果(救救我鸭无方块时挂在角色载体上;与 tetriNode.showUpLevelEffect 一致)
|
||
|
|
* @param isUpLevel true 技能升级,false 武器替换
|
||
|
|
*/
|
||
|
|
showSkillSelectCompleteEffect(isUpLevel = true, delay = 0) {
|
||
|
|
const host = this.roleNode?.isValid ? this.roleNode : this.node;
|
||
|
|
if (!host?.isValid) return;
|
||
|
|
|
||
|
|
this.scheduleOnce(() => {
|
||
|
|
if (!host?.isValid) return;
|
||
|
|
void gg.res.getNodeAsync(GPath.Prefab, '三选一完成格子效果', GBundle.tetriGame).then((eff) => {
|
||
|
|
if (!eff?.isValid) return;
|
||
|
|
|
||
|
|
const battle = gg.game?.CurentBattle;
|
||
|
|
const ya = battle?.BattleType === BattleType.OrangeWeaponMode_Ya;
|
||
|
|
const spineLayer = ya && battle?.TopSpineLayer?.isValid ? battle.TopSpineLayer : null;
|
||
|
|
|
||
|
|
if (spineLayer) {
|
||
|
|
eff.parent = spineLayer;
|
||
|
|
eff.setWorldPosition(host.worldPosition);
|
||
|
|
battle.setLayerMask(eff, spineLayer.layer);
|
||
|
|
eff.setSiblingIndex(spineLayer.children.length - 1);
|
||
|
|
} else {
|
||
|
|
gg.ui.showNode(eff, UILayer.Anim);
|
||
|
|
eff.parent = host;
|
||
|
|
eff.setPosition(Vec3.ZERO);
|
||
|
|
}
|
||
|
|
eff.active = true;
|
||
|
|
|
||
|
|
const nReplace = eff.find('武器替换');
|
||
|
|
const nUp = eff.find('升级');
|
||
|
|
if (nReplace?.isValid) nReplace.active = !isUpLevel;
|
||
|
|
if (nUp?.isValid) nUp.active = isUpLevel;
|
||
|
|
const playSpine = (node: Node | null, animName: string) => {
|
||
|
|
const sk = node?.getComponent(sp.Skeleton);
|
||
|
|
if (!sk) return;
|
||
|
|
sk.clearTracks();
|
||
|
|
sk.setAnimation(0, animName, false);
|
||
|
|
};
|
||
|
|
if (nReplace?.active) playSpine(nReplace, 'animation');
|
||
|
|
if (nUp?.active) playSpine(nUp, '升级');
|
||
|
|
|
||
|
|
this.scheduleOnce(() => {
|
||
|
|
if (eff?.isValid) gg.res.putNode(eff);
|
||
|
|
}, 1.5);
|
||
|
|
});
|
||
|
|
}, delay);
|
||
|
|
}
|
||
|
|
changeWeaponConf() {
|
||
|
|
|
||
|
|
console.log('我改变武器啦 ++= changeWeaponConf++++++++===', this._curentWeaponId)
|
||
|
|
let conf2 = gg.data.project.getWeaponData(this._curentWeaponId)
|
||
|
|
//this.changeIcon(conf2.typeicon)
|
||
|
|
this.changeWeapon(conf2.weaponani)
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
changeWeapon(weaponani) {
|
||
|
|
const old = this.weaponNode;
|
||
|
|
this.weaponNode = null;
|
||
|
|
this.safePutPoolNode(old);
|
||
|
|
this.addWeapon(weaponani)
|
||
|
|
}
|
||
|
|
|
||
|
|
//增加武器和修改icon图片
|
||
|
|
addWeapon(weaponani) {
|
||
|
|
const anim = find('anim', this.roleNode);
|
||
|
|
const wuqiNode = find('武器', this.roleNode);
|
||
|
|
if (!anim || !wuqiNode) {
|
||
|
|
console.error('[tetriWeaponCarrier] addWeapon: 未找到 角色/anim 或 角色/武器', this._config?.cubename);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
void gg.res.getNodeAsync('prefab/', weaponani, GBundle.tetriWeapon).then((weaponNode) => {
|
||
|
|
if (!weaponNode?.isValid || !wuqiNode?.isValid) return;
|
||
|
|
this.setLayerMask(weaponNode, wuqiNode.layer);
|
||
|
|
this.weaponNode = weaponNode;
|
||
|
|
weaponNode.setParent(wuqiNode);
|
||
|
|
anim.getComponent(sp.Skeleton)?.setAnimation(0, '待机', true);
|
||
|
|
weaponNode.getComponent(sp.Skeleton)?.setAnimation(0, '待机', true);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
setLayerMask(n: Node, layerMask: number) {
|
||
|
|
n.layer = layerMask;
|
||
|
|
for (let i = 0; i < n.children.length; i++) {
|
||
|
|
if (n.children[i].isValid) {
|
||
|
|
this.setLayerMask(n.children[i], layerMask);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
changeIcon(typeicon) {
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
//播放攻击动画
|
||
|
|
playAtkAnim() {
|
||
|
|
clearTimeout(this.timeoutIndex as unknown as number);
|
||
|
|
if (!this.roleNode?.isValid) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
const animNode = find('anim', this.roleNode);
|
||
|
|
const animSk = animNode?.getComponent(sp.Skeleton);
|
||
|
|
const weaponSk = this.weaponNode?.getComponent(sp.Skeleton);
|
||
|
|
if (animSk) {
|
||
|
|
animSk.setAnimation(0, '攻击', false);
|
||
|
|
}
|
||
|
|
if (weaponSk) {
|
||
|
|
weaponSk.setAnimation(0, '攻击', false);
|
||
|
|
}
|
||
|
|
|
||
|
|
this.timeoutIndex = setTimeout(() => {
|
||
|
|
if (animSk?.isValid) {
|
||
|
|
animSk.setAnimation(0, '待机', true);
|
||
|
|
}
|
||
|
|
if (weaponSk?.isValid) {
|
||
|
|
weaponSk.setAnimation(0, '待机', true);
|
||
|
|
}
|
||
|
|
this.animState = '待机';
|
||
|
|
this.timeoutIndex = null;
|
||
|
|
}, 1000) as unknown as number;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
//获取武器的发射节点和原点
|
||
|
|
getWeaponLaunchNode(): Node {
|
||
|
|
if (!this.roleNode?.isValid) {
|
||
|
|
return this.node;
|
||
|
|
}
|
||
|
|
const wuqiNode = find('武器', this.roleNode);
|
||
|
|
if (!wuqiNode?.isValid) {
|
||
|
|
return this.roleNode;
|
||
|
|
}
|
||
|
|
const shoot = wuqiNode.getComponentInChildren(shootPoint)?.node;
|
||
|
|
if (shoot?.isValid) {
|
||
|
|
return shoot;
|
||
|
|
}
|
||
|
|
// 部分武器预制未挂 shootPoint:用武器模型节点(只要在「武器」子树下)或「武器」挂点作为发射参考
|
||
|
|
if (this.weaponNode?.isValid) {
|
||
|
|
let p: Node | null = this.weaponNode;
|
||
|
|
while (p) {
|
||
|
|
if (p === wuqiNode) {
|
||
|
|
return this.weaponNode;
|
||
|
|
}
|
||
|
|
p = p.parent;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return wuqiNode;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 载体关联方块:自身或父链上的 tetriNode(救救我鸭等直挂角色时为 null) */
|
||
|
|
findCarrierTetriNode(): tetriNode | null {
|
||
|
|
const onSelf = this.node.getComponent(tetriNode);
|
||
|
|
if (onSelf) return onSelf;
|
||
|
|
let cur: Node | null = this.node.parent;
|
||
|
|
while (cur) {
|
||
|
|
const t = cur.getComponent(tetriNode);
|
||
|
|
if (t) return t;
|
||
|
|
cur = cur.parent;
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 方块未落稳不发射;无方块载体(副本直挂等)视为可随时发射 */
|
||
|
|
isSettledForWeaponShoot(): boolean {
|
||
|
|
const tetri = this.findCarrierTetriNode();
|
||
|
|
return !tetri || tetri.isSettled;
|
||
|
|
}
|
||
|
|
|
||
|
|
getCarrierTetriLevel(): number {
|
||
|
|
return this.findCarrierTetriNode()?.getNodeLevel?.() ?? 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 战斗暂停/弹窗叠层时不发射已排队的子弹 */
|
||
|
|
private scheduleWeaponFire(delaySec: number, fn: () => void): void {
|
||
|
|
this.scheduleOnce(() => {
|
||
|
|
if (!gg.game?.CurentBattle?.canUpdateFrame()) return;
|
||
|
|
fn();
|
||
|
|
}, delaySec);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** GEvent 武器发射为全局广播,仅处理与当前发射塔绑定的武器 */
|
||
|
|
private shouldHandleWeaponLaunch(emitWeaponId: number): boolean {
|
||
|
|
return emitWeaponId > 0 && emitWeaponId === this._curentWeaponId;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**直线弹幕 */
|
||
|
|
StraightWeaponShoot(weaponProperty: IWeaponProperty, posX, xTime, launchCount, burstCount) {
|
||
|
|
if (!this.shouldHandleWeaponLaunch(weaponProperty?.weaponId)) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
//没有落稳的方块不在发射武器
|
||
|
|
//单次发射数量launchCount
|
||
|
|
// console.log('StraightWeaponShoot 单次发射数量launchCount',launchCount)
|
||
|
|
// console.log('StraightWeaponShoot burstCount',burstCount)
|
||
|
|
|
||
|
|
if (!this._isCanShoot) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if (!this.isSettledForWeaponShoot()) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
const weaponId = this._curentWeaponId;
|
||
|
|
const volume = weaponProperty.volume;
|
||
|
|
const carrierNode = this.node;
|
||
|
|
const launchNodeSnap = this.getWeaponLaunchNode();
|
||
|
|
const tetriLevel = this.getCarrierTetriLevel();
|
||
|
|
|
||
|
|
let weaponConf = gg.data.project.getWeaponData(weaponId)
|
||
|
|
if (weaponConf.flight == SkillType.直线弹幕) {
|
||
|
|
|
||
|
|
gg.game.CurentBattle?.enqueueWeaponLaunchEvent?.({
|
||
|
|
type: GEvent.StraightWeaponShoot,
|
||
|
|
run: () => {
|
||
|
|
const battle = gg.game.CurentBattle;
|
||
|
|
if (!battle?.SkillController?.node?.isValid) return;
|
||
|
|
if (!isValid(carrierNode)) return;
|
||
|
|
const carrier = carrierNode.getComponent(tetriWeaponCarrier);
|
||
|
|
if (!carrier) return;
|
||
|
|
carrier.playAtkAnim();
|
||
|
|
const lead = tetriWeaponCarrier.ATK_ANIM_LEAD_SEC / battle.TimeScale;
|
||
|
|
for (let i = 0; i < burstCount; i++) {
|
||
|
|
let t1 = lead + xTime * i;
|
||
|
|
this.scheduleWeaponFire(t1, () => {
|
||
|
|
// 面向最近怪物(角色不移动也需要左右转向)
|
||
|
|
this.faceRoleToMonster(battle.MonsterSpawner?.getAllPathDisMinMonster?.(carrierNode));
|
||
|
|
// 音效节流交给 SoundManager.shouldPlayWeaponSfx(按音效名);勿共用 audio_timeStamp
|
||
|
|
this.playEffectStraight(weaponId);
|
||
|
|
for (let j = 0; j < launchCount; j++) {
|
||
|
|
let addPos = v3(j * posX - (launchCount - 1) * posX / 2, 0, 0)
|
||
|
|
void battle.SkillController.instantiateSingleWeapon(weaponId, volume, addPos, 0, launchNodeSnap).then((weaponNode) => {
|
||
|
|
|
||
|
|
if (!weaponNode?.isValid) return;
|
||
|
|
|
||
|
|
weaponNode.getComponent(Skill)?.setData(gg.data.project.getWeaponData(weaponId), v3(0, 0, 0), false, false, j, 0, 0, 0, tetriLevel);
|
||
|
|
|
||
|
|
});
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**直线弹射 */
|
||
|
|
StraightWeaponLaunch(weaponProperty: IWeaponProperty, posX, xTime, launchCount, burstCount) {
|
||
|
|
if (!this.shouldHandleWeaponLaunch(weaponProperty?.weaponId)) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if (!this._isCanShoot) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if (!this.isSettledForWeaponShoot()) {
|
||
|
|
//console.log('没有落稳的方块不在发射武器')
|
||
|
|
return
|
||
|
|
}
|
||
|
|
const weaponId = this._curentWeaponId;
|
||
|
|
const volume = weaponProperty.volume;
|
||
|
|
const carrierNode = this.node;
|
||
|
|
const launchNodeSnap = this.getWeaponLaunchNode();
|
||
|
|
const tetriLevel = this.getCarrierTetriLevel();
|
||
|
|
|
||
|
|
let weaponConf = gg.data.project.getWeaponData(weaponId)
|
||
|
|
if (weaponConf.flight == SkillType.直线弹射) {
|
||
|
|
gg.game.CurentBattle?.enqueueWeaponLaunchEvent?.({
|
||
|
|
type: GEvent.StraightWeaponLaunch,
|
||
|
|
run: () => {
|
||
|
|
const battle = gg.game.CurentBattle;
|
||
|
|
if (!battle?.SkillController?.node?.isValid) return;
|
||
|
|
if (!isValid(carrierNode)) return;
|
||
|
|
const carrier = carrierNode.getComponent(tetriWeaponCarrier);
|
||
|
|
if (!carrier) return;
|
||
|
|
carrier.playAtkAnim();
|
||
|
|
const lead = tetriWeaponCarrier.ATK_ANIM_LEAD_SEC / battle.TimeScale;
|
||
|
|
for (let i = 0; i < burstCount; i++) {
|
||
|
|
let t1 = lead + xTime * i;
|
||
|
|
this.scheduleWeaponFire(t1, () => {
|
||
|
|
// 面向最近怪物(角色不移动也需要左右转向)
|
||
|
|
this.faceRoleToMonster(battle.MonsterSpawner?.getAllPathDisMinMonster?.(carrierNode));
|
||
|
|
this.playEffectStraightLaunch(weaponId);
|
||
|
|
for (let j = 0; j < launchCount; j++) {
|
||
|
|
let addPos = v3(j * posX - (launchCount - 1) * posX / 2, 0, 0)
|
||
|
|
void battle.SkillController.instantiateSingleWeapon(weaponId, volume, addPos, 0, launchNodeSnap).then((weaponNode) => {
|
||
|
|
if (!weaponNode?.isValid) return;
|
||
|
|
weaponNode.getComponent(Skill)?.setData(gg.data.project.getWeaponData(weaponId), v3(0, 0, 0), false, false, j, 0, 0, 0, tetriLevel);
|
||
|
|
});
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**直线数量 */
|
||
|
|
StraightWeaponShootNum(weaponProperty: IWeaponProperty, burstCount, xTime, launchCount, posX) {
|
||
|
|
if (!this.shouldHandleWeaponLaunch(weaponProperty?.weaponId)) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if (!this._isCanShoot) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if (!this.isSettledForWeaponShoot()) {
|
||
|
|
//console.log('没有落稳的方块不在发射武器')
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
const weaponId = this._curentWeaponId;
|
||
|
|
const volume = weaponProperty.volume;
|
||
|
|
const carrierNode = this.node;
|
||
|
|
const launchNodeSnap = this.getWeaponLaunchNode();
|
||
|
|
const tetriLevel = this.getCarrierTetriLevel();
|
||
|
|
|
||
|
|
let weaponConf = gg.data.project.getWeaponData(weaponId)
|
||
|
|
if (weaponConf.flight == SkillType.直线数量) {
|
||
|
|
gg.game.CurentBattle?.enqueueWeaponLaunchEvent?.({
|
||
|
|
type: GEvent.StraightWeaponShootNum,
|
||
|
|
run: () => {
|
||
|
|
const battle = gg.game.CurentBattle;
|
||
|
|
if (!battle?.SkillController?.node?.isValid) return;
|
||
|
|
if (!isValid(carrierNode)) return;
|
||
|
|
const carrier = carrierNode.getComponent(tetriWeaponCarrier);
|
||
|
|
if (!carrier) return;
|
||
|
|
carrier.playAtkAnim();
|
||
|
|
const lead = tetriWeaponCarrier.ATK_ANIM_LEAD_SEC / battle.TimeScale;
|
||
|
|
for (let i = 0; i < burstCount; i++) {
|
||
|
|
let t1 = lead + xTime * i;
|
||
|
|
this.scheduleWeaponFire(t1, () => {
|
||
|
|
// 面向最近怪物(角色不移动也需要左右转向)
|
||
|
|
this.faceRoleToMonster(battle.MonsterSpawner?.getAllPathDisMinMonster?.(carrierNode));
|
||
|
|
|
||
|
|
this.playEffectStraightNum(weaponId);
|
||
|
|
|
||
|
|
for (let j = 0; j < launchCount; j++) {
|
||
|
|
//多个子弹并排开
|
||
|
|
let addPos = v3(j * posX - (launchCount - 1) * posX / 2, 0, 0)
|
||
|
|
void battle.SkillController.instantiateSingleWeapon(weaponId, volume, addPos, 0, launchNodeSnap).then((weaponNode) => {
|
||
|
|
if (!weaponNode?.isValid) return;
|
||
|
|
weaponNode.getComponent(Skill)?.setData(gg.data.project.getWeaponData(weaponId), v3(0, 0, 0), false, false, j, 0, 0, 0, tetriLevel);
|
||
|
|
});
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**直线分裂 */
|
||
|
|
StraightWeaponSplit(weaponProperty: IWeaponProperty, burstCount, xTime, launchCount, posX) {
|
||
|
|
if (!this.shouldHandleWeaponLaunch(weaponProperty?.weaponId)) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if (!this._isCanShoot) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if (!this.isSettledForWeaponShoot()) {
|
||
|
|
//console.log('没有落稳的方块不在发射武器')
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
const weaponId = this._curentWeaponId;
|
||
|
|
const volume = weaponProperty.volume;
|
||
|
|
const carrierNode = this.node;
|
||
|
|
const launchNodeSnap = this.getWeaponLaunchNode();
|
||
|
|
const tetriLevel = this.getCarrierTetriLevel();
|
||
|
|
|
||
|
|
let weaponConf = gg.data.project.getWeaponData(weaponId)
|
||
|
|
if (weaponConf.flight == SkillType.直线分裂) {
|
||
|
|
gg.game.CurentBattle?.enqueueWeaponLaunchEvent?.({
|
||
|
|
type: GEvent.StraightWeaponSplit,
|
||
|
|
run: () => {
|
||
|
|
const battle = gg.game.CurentBattle;
|
||
|
|
if (!battle?.SkillController?.node?.isValid) return;
|
||
|
|
if (!isValid(carrierNode)) return;
|
||
|
|
const carrier = carrierNode.getComponent(tetriWeaponCarrier);
|
||
|
|
if (!carrier) return;
|
||
|
|
carrier.playAtkAnim();
|
||
|
|
const lead = tetriWeaponCarrier.ATK_ANIM_LEAD_SEC / battle.TimeScale;
|
||
|
|
for (let i = 0; i < burstCount; i++) {
|
||
|
|
let t1 = lead + xTime * i;
|
||
|
|
this.scheduleWeaponFire(t1, () => {
|
||
|
|
// 面向最近怪物(角色不移动也需要左右转向)
|
||
|
|
this.faceRoleToMonster(battle.MonsterSpawner?.getAllPathDisMinMonster?.(carrierNode));
|
||
|
|
|
||
|
|
this.playEffectStraight(weaponId);
|
||
|
|
|
||
|
|
for (let j = 0; j < launchCount; j++) {
|
||
|
|
//多个子弹并排开
|
||
|
|
let addPos = v3(j * posX - (launchCount - 1) * posX / 2, 0, 0)
|
||
|
|
void battle.SkillController.instantiateSingleWeapon(weaponId, volume, addPos, 0, launchNodeSnap).then((weaponNode) => {
|
||
|
|
if (!weaponNode?.isValid) return;
|
||
|
|
weaponNode.getComponent(Skill)?.setData(gg.data.project.getWeaponData(weaponId), v3(0, 0, 0), false, false, j, 0, 0, 0, tetriLevel);
|
||
|
|
});
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**直线穿透*/
|
||
|
|
StraightWeaponPierce(weaponProperty: IWeaponProperty, burstCount, xTime, launchCount, posX) {
|
||
|
|
if (!this.shouldHandleWeaponLaunch(weaponProperty?.weaponId)) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if (!this._isCanShoot) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if (!this.isSettledForWeaponShoot()) {
|
||
|
|
//console.log('没有落稳的方块不在发射武器')
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
const weaponId = this._curentWeaponId;
|
||
|
|
const volume = weaponProperty.volume;
|
||
|
|
const carrierNode = this.node;
|
||
|
|
const launchNodeSnap = this.getWeaponLaunchNode();
|
||
|
|
const tetriLevel = this.getCarrierTetriLevel();
|
||
|
|
|
||
|
|
let weaponConf = gg.data.project.getWeaponData(weaponId)
|
||
|
|
if (weaponConf.flight == SkillType.直线穿透) {
|
||
|
|
gg.game.CurentBattle?.enqueueWeaponLaunchEvent?.({
|
||
|
|
type: GEvent.StraightWeaponPierce,
|
||
|
|
run: () => {
|
||
|
|
const battle = gg.game.CurentBattle;
|
||
|
|
if (!battle?.SkillController?.node?.isValid) return;
|
||
|
|
if (!isValid(carrierNode)) return;
|
||
|
|
const carrier = carrierNode.getComponent(tetriWeaponCarrier);
|
||
|
|
if (!carrier) return;
|
||
|
|
carrier.playAtkAnim();
|
||
|
|
const lead = tetriWeaponCarrier.ATK_ANIM_LEAD_SEC2 / battle.TimeScale;
|
||
|
|
for (let i = 0; i < burstCount; i++) {
|
||
|
|
let t1 = lead + xTime * i;
|
||
|
|
this.scheduleWeaponFire(t1, () => {
|
||
|
|
// 面向最近怪物(角色不移动也需要左右转向)
|
||
|
|
this.faceRoleToMonster(battle.MonsterSpawner?.getAllPathDisMinMonster?.(carrierNode));
|
||
|
|
|
||
|
|
this.playEffectStraight(weaponId);
|
||
|
|
|
||
|
|
for (let j = 0; j < launchCount; j++) {
|
||
|
|
//多个子弹并排开
|
||
|
|
let addPos = v3(j * posX - (launchCount - 1) * posX / 2, 0, 0)
|
||
|
|
void battle.SkillController.instantiateSingleWeapon(weaponId, volume, addPos, 0, launchNodeSnap).then((weaponNode) => {
|
||
|
|
if (!weaponNode?.isValid) return;
|
||
|
|
weaponNode.getComponent(Skill)?.setData(gg.data.project.getWeaponData(weaponId), v3(0, 0, 0), false, false, j, 0, 0, 0, tetriLevel);
|
||
|
|
});
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**抛物线碰撞 */
|
||
|
|
ParabolaCollide(weaponProperty: IWeaponProperty, bullet_column, launchCount) {
|
||
|
|
if (!this.shouldHandleWeaponLaunch(weaponProperty?.weaponId)) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if (!this._isCanShoot) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if (!this.isSettledForWeaponShoot()) {
|
||
|
|
//console.log('没有落稳的方块不在发射武器')
|
||
|
|
return
|
||
|
|
}
|
||
|
|
const weaponId = this._curentWeaponId;
|
||
|
|
const volume = weaponProperty.volume;
|
||
|
|
const carrierNode = this.node;
|
||
|
|
const launchNodeSnap = this.getWeaponLaunchNode();
|
||
|
|
const tetriLevel = this.getCarrierTetriLevel();
|
||
|
|
let throwCount = weaponProperty.throwCount
|
||
|
|
let specialSkillInfo = weaponProperty.specialSkillInfo
|
||
|
|
|
||
|
|
let weaponConf = gg.data.project.getWeaponData(weaponId)
|
||
|
|
if (weaponConf.flight == SkillType.抛物线碰撞) {
|
||
|
|
gg.game.CurentBattle?.enqueueWeaponLaunchEvent?.({
|
||
|
|
type: GEvent.ParabolaCollide,
|
||
|
|
run: () => {
|
||
|
|
const battle = gg.game.CurentBattle;
|
||
|
|
if (!battle?.SkillController?.node?.isValid) return;
|
||
|
|
if (!isValid(carrierNode)) return;
|
||
|
|
const carrier = carrierNode.getComponent(tetriWeaponCarrier);
|
||
|
|
if (!carrier) return;
|
||
|
|
carrier.playAtkAnim();
|
||
|
|
const lead = tetriWeaponCarrier.ATK_ANIM_LEAD_SEC / battle.TimeScale;
|
||
|
|
let createSkill = async (mNode: Node) => {
|
||
|
|
if (mNode && isValid(mNode)) {
|
||
|
|
// weaponNode 挂在 SkillController.node 下,setData 的 targetPos 需要与 weaponNode 同坐标系
|
||
|
|
const parentUi = battle.SkillController.node.getComponent(UITransform);
|
||
|
|
let pos = parentUi
|
||
|
|
? parentUi.convertToNodeSpaceAR(mNode.worldPosition)
|
||
|
|
: mNode.worldPosition.clone();
|
||
|
|
void battle.SkillController.instantiateSingleWeapon(weaponId, volume, v3(0, 0, 0), 0, launchNodeSnap).then((weaponNode) => {
|
||
|
|
if (!weaponNode?.isValid) return;
|
||
|
|
weaponNode.getComponent(Skill)?.setData(gg.data.project.getWeaponData(weaponId), pos, false, false, 0, 0, 0, 0, tetriLevel);
|
||
|
|
});
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
let singleLaunchCall = () => {
|
||
|
|
//单次发射数量
|
||
|
|
this.playEffectParabolaCollide(weaponId);
|
||
|
|
let selectMonster = [];
|
||
|
|
selectMonster = gg.game.CurentBattle.MonsterSpawner.getMonsterNearestCountPar(this.node, throwCount);
|
||
|
|
if (selectMonster.length == 0) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
// 面向第一个目标怪物
|
||
|
|
this.faceRoleToMonster(selectMonster[0]);
|
||
|
|
|
||
|
|
for (let i = 0; i < throwCount; i++) {
|
||
|
|
if (i >= throwCount) break;
|
||
|
|
if (i >= selectMonster.length) break;
|
||
|
|
let m = selectMonster[i];
|
||
|
|
if (!isValid(m)) continue;
|
||
|
|
createSkill(m);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
let isBurst = false
|
||
|
|
let burstCount = 1
|
||
|
|
let xTime = bullet_column//间隔
|
||
|
|
for (let i = 0; i < specialSkillInfo.length; i++) {
|
||
|
|
let buffInfo = specialSkillInfo[i]
|
||
|
|
let arr = buffInfo.split(',')
|
||
|
|
let buffType = Number(arr[0])
|
||
|
|
if (buffType == SpecialSkillType.rateBurst) {
|
||
|
|
//概率连发
|
||
|
|
let rateNum = Number(arr[1]) / 10000//连发的概率
|
||
|
|
burstCount += Number(arr[2])//增加连发数量
|
||
|
|
isBurst = Math.random() < rateNum
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//连发
|
||
|
|
if (isBurst) {
|
||
|
|
for (let j = 0; j < burstCount; j++) {
|
||
|
|
this.scheduleWeaponFire(lead + xTime * j, () => {
|
||
|
|
singleLaunchCall();
|
||
|
|
});
|
||
|
|
}
|
||
|
|
//单发
|
||
|
|
} else {
|
||
|
|
this.scheduleWeaponFire(lead, () => {
|
||
|
|
// 多发:一次性取足目标,避免每次 random 到同一个怪
|
||
|
|
const totalNeed = Math.max(1, Math.floor(throwCount)) * Math.max(1, Math.floor(launchCount));
|
||
|
|
const selectMonsterAll = battle.MonsterSpawner.getMonsterParabolaPos(totalNeed, carrierNode);
|
||
|
|
if (selectMonsterAll.length == 0) return;
|
||
|
|
|
||
|
|
// 面向第一个目标怪物
|
||
|
|
const first = selectMonsterAll[0]?.node as Node;
|
||
|
|
if (first && isValid(first)) {
|
||
|
|
this.faceRoleToMonster(first);
|
||
|
|
}
|
||
|
|
|
||
|
|
for (let k = 0; k < totalNeed; k++) {
|
||
|
|
if (k >= selectMonsterAll.length) break;
|
||
|
|
const m = selectMonsterAll[k];
|
||
|
|
if (!m?.node || !isValid(m.node)) continue;
|
||
|
|
createSkill(m.node);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**抛物线没有碰撞 */
|
||
|
|
ParabolaNoCollide(weaponProperty: IWeaponProperty, bullet_column, launchCount) {
|
||
|
|
if (!this.shouldHandleWeaponLaunch(weaponProperty?.weaponId)) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if (!this._isCanShoot) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if (!this.isSettledForWeaponShoot()) {
|
||
|
|
//console.log('没有落稳的方块不在发射武器')
|
||
|
|
return
|
||
|
|
}
|
||
|
|
const weaponId = this._curentWeaponId;
|
||
|
|
const volume = weaponProperty.volume;
|
||
|
|
const carrierNode = this.node;
|
||
|
|
const launchNodeSnap = this.getWeaponLaunchNode();
|
||
|
|
const tetriLevel = this.getCarrierTetriLevel();
|
||
|
|
let throwCount = weaponProperty.throwCount
|
||
|
|
let specialSkillInfo = weaponProperty.specialSkillInfo
|
||
|
|
|
||
|
|
let weaponConf = gg.data.project.getWeaponData(weaponId)
|
||
|
|
if (weaponConf.flight == SkillType.抛物线没有碰撞) {
|
||
|
|
gg.game.CurentBattle?.enqueueWeaponLaunchEvent?.({
|
||
|
|
type: GEvent.ParabolaNoCollide,
|
||
|
|
run: () => {
|
||
|
|
const battle = gg.game.CurentBattle;
|
||
|
|
if (!battle?.SkillController?.node?.isValid) return;
|
||
|
|
if (!isValid(carrierNode)) return;
|
||
|
|
const carrier = carrierNode.getComponent(tetriWeaponCarrier);
|
||
|
|
if (!carrier) return;
|
||
|
|
carrier.playAtkAnim();
|
||
|
|
const lead = tetriWeaponCarrier.ATK_ANIM_LEAD_SEC / battle.TimeScale;
|
||
|
|
let createSkill = async (mNode: Node) => {
|
||
|
|
if (mNode && isValid(mNode)) {
|
||
|
|
// weaponNode 挂在 SkillController.node 下,setData 的 targetPos 需要与 weaponNode 同坐标系
|
||
|
|
const parentUi = battle.SkillController.node.getComponent(UITransform);
|
||
|
|
let pos = parentUi
|
||
|
|
? parentUi.convertToNodeSpaceAR(mNode.worldPosition)
|
||
|
|
: mNode.worldPosition.clone();
|
||
|
|
void battle.SkillController.instantiateSingleWeapon(weaponId, volume, v3(0, 0, 0), 0, launchNodeSnap).then((weaponNode) => {
|
||
|
|
if (!weaponNode?.isValid) return;
|
||
|
|
weaponNode.getComponent(Skill)?.setData(gg.data.project.getWeaponData(weaponId), pos, false, false, 0, 0, 0, 0, tetriLevel);
|
||
|
|
});
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
let singleLaunchCall = () => {
|
||
|
|
//单次发射数量
|
||
|
|
this.playEffectParabolaNoCollide(weaponId);
|
||
|
|
let selectMonster = [];
|
||
|
|
selectMonster = gg.game.CurentBattle.MonsterSpawner.getMonsterParabolaPos(throwCount, this.node);
|
||
|
|
if (selectMonster.length == 0) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
// 大炮等“抛物线没有碰撞”类型也需要左右转向(与其它发射类型保持一致)
|
||
|
|
const first = selectMonster[0]?.node as Node;
|
||
|
|
if (first && isValid(first)) {
|
||
|
|
this.faceRoleToMonster(first);
|
||
|
|
}
|
||
|
|
|
||
|
|
for (let i = 0; i < throwCount; i++) {
|
||
|
|
if (i >= throwCount) break;
|
||
|
|
if (i >= selectMonster.length) break;
|
||
|
|
let m = selectMonster[i];
|
||
|
|
if (!isValid(m.node)) continue;
|
||
|
|
createSkill(m.node);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
let isBurst = false
|
||
|
|
let burstCount = 1
|
||
|
|
let xTime = bullet_column//间隔
|
||
|
|
for (let i = 0; i < specialSkillInfo.length; i++) {
|
||
|
|
let buffInfo = specialSkillInfo[i]
|
||
|
|
let arr = buffInfo.split(',')
|
||
|
|
let buffType = Number(arr[0])
|
||
|
|
if (buffType == SpecialSkillType.rateBurst) {
|
||
|
|
//概率连发
|
||
|
|
let rateNum = Number(arr[1]) / 10000//连发的概率
|
||
|
|
burstCount += Number(arr[2])//增加连发数量
|
||
|
|
isBurst = Math.random() < rateNum
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//连发
|
||
|
|
if (isBurst) {
|
||
|
|
for (let j = 0; j < burstCount; j++) {
|
||
|
|
this.scheduleWeaponFire(lead + xTime * j, () => {
|
||
|
|
singleLaunchCall();
|
||
|
|
});
|
||
|
|
}
|
||
|
|
//单发
|
||
|
|
} else {
|
||
|
|
this.scheduleWeaponFire(lead, () => {
|
||
|
|
// 多发:一次性取足目标,避免每次 random 到同一个怪
|
||
|
|
const totalNeed = Math.max(1, Math.floor(throwCount)) * Math.max(1, Math.floor(launchCount));
|
||
|
|
const selectMonsterAll = battle.MonsterSpawner.getMonsterParabolaPos(totalNeed, carrierNode);
|
||
|
|
if (selectMonsterAll.length == 0) return;
|
||
|
|
|
||
|
|
// 面向第一个目标怪物
|
||
|
|
const first = selectMonsterAll[0]?.node as Node;
|
||
|
|
if (first && isValid(first)) {
|
||
|
|
this.faceRoleToMonster(first);
|
||
|
|
}
|
||
|
|
|
||
|
|
for (let k = 0; k < totalNeed; k++) {
|
||
|
|
if (k >= selectMonsterAll.length) break;
|
||
|
|
const m = selectMonsterAll[k];
|
||
|
|
if (!m?.node || !isValid(m.node)) continue;
|
||
|
|
createSkill(m.node);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**单点激光 */
|
||
|
|
SinglePointLaser(weaponProperty: IWeaponProperty, burstCount, launchCount) {
|
||
|
|
if (!this.shouldHandleWeaponLaunch(weaponProperty?.weaponId)) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if (!this._isCanShoot) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if (!this.isSettledForWeaponShoot()) {
|
||
|
|
//console.log('没有落稳的方块不在发射武器')
|
||
|
|
return
|
||
|
|
}
|
||
|
|
const weaponId = this._curentWeaponId;
|
||
|
|
const volume = weaponProperty.volume;
|
||
|
|
|
||
|
|
const carrierNode = this.node;
|
||
|
|
const launchNodeSnap = this.getWeaponLaunchNode();
|
||
|
|
const tetriLevel = this.getCarrierTetriLevel();
|
||
|
|
|
||
|
|
let weaponConf = gg.data.project.getWeaponData(weaponId)
|
||
|
|
if (weaponConf.flight == SkillType.单点激光) {
|
||
|
|
gg.game.CurentBattle?.enqueueWeaponLaunchEvent?.({
|
||
|
|
type: GEvent.SinglePointLaser,
|
||
|
|
run: () => {
|
||
|
|
const battle = gg.game.CurentBattle;
|
||
|
|
if (!battle?.SkillController?.node?.isValid) return;
|
||
|
|
if (!isValid(carrierNode)) return;
|
||
|
|
const carrier = carrierNode.getComponent(tetriWeaponCarrier);
|
||
|
|
if (!carrier) return;
|
||
|
|
carrier.playAtkAnim();
|
||
|
|
const lead = tetriWeaponCarrier.ATK_ANIM_LEAD_SEC2 / battle.TimeScale;
|
||
|
|
this.scheduleWeaponFire(lead, () => {
|
||
|
|
for (let i = 0; i < burstCount; i++) {
|
||
|
|
for (let j = 0; j < launchCount; j++) {
|
||
|
|
const laserIndex = i * launchCount + j;
|
||
|
|
if (i == 0 && j == 0) {
|
||
|
|
gg.audio.playEffect({ name: '激光', path: 'sound/武器音效2/' });
|
||
|
|
}
|
||
|
|
//
|
||
|
|
void battle.SkillController.instantiateSingleWeapon(weaponId, volume, v3(0, 0, 0), 0, launchNodeSnap).then((weaponNode) => {
|
||
|
|
if (!weaponNode?.isValid) return;
|
||
|
|
const skillComp = weaponNode.getComponent(Skill);
|
||
|
|
skillComp.setData(gg.data.project.getWeaponData(weaponId), v3(0, 0, 0), false, false, laserIndex, 0, 0, 0, tetriLevel);
|
||
|
|
weaponNode.getComponent(LaserLine).setData(weaponId, weaponProperty, laserIndex, tetriLevel);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**直线目标持续伤害 */
|
||
|
|
StraightTargetDamage(weaponProperty: IWeaponProperty, launchCount, xTime, posX, burstCount) {
|
||
|
|
if (!this.shouldHandleWeaponLaunch(weaponProperty?.weaponId)) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!this._isCanShoot) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if (!this.isSettledForWeaponShoot()) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
const weaponId = this._curentWeaponId;
|
||
|
|
const volume = weaponProperty.volume;
|
||
|
|
const carrierNode = this.node;
|
||
|
|
const launchNodeSnap = this.getWeaponLaunchNode();
|
||
|
|
const tetriLevel = this.getCarrierTetriLevel();
|
||
|
|
|
||
|
|
let weaponConf = gg.data.project.getWeaponData(weaponId)
|
||
|
|
if (weaponConf.flight == SkillType.直线目标持续伤害) {
|
||
|
|
|
||
|
|
gg.game.CurentBattle?.enqueueWeaponLaunchEvent?.({
|
||
|
|
type: GEvent.StraightTargetDamage,
|
||
|
|
run: () => {
|
||
|
|
const battle = gg.game.CurentBattle;
|
||
|
|
if (!battle?.SkillController?.node?.isValid) return;
|
||
|
|
if (!isValid(carrierNode)) return;
|
||
|
|
const carrier = carrierNode.getComponent(tetriWeaponCarrier);
|
||
|
|
if (!carrier) return;
|
||
|
|
carrier.playAtkAnim();
|
||
|
|
const lead = tetriWeaponCarrier.ATK_ANIM_LEAD_SEC / battle.TimeScale;
|
||
|
|
for (let i = 0; i < burstCount; i++) {
|
||
|
|
let t1 = lead + xTime * i;
|
||
|
|
this.scheduleWeaponFire(t1, () => {
|
||
|
|
// 面向最近怪物(角色不移动也需要左右转向)
|
||
|
|
this.faceRoleToMonster(battle.MonsterSpawner?.getAllPathDisMinMonster?.(carrierNode));
|
||
|
|
// 音效节流交给 SoundManager.shouldPlayWeaponSfx(按音效名);勿共用 audio_timeStamp
|
||
|
|
this.playEffectStraight(weaponId);
|
||
|
|
for (let j = 0; j < launchCount; j++) {
|
||
|
|
let addPos = v3(j * posX - (launchCount - 1) * posX / 2, 0, 0)
|
||
|
|
void battle.SkillController.instantiateSingleWeapon(weaponId, volume, addPos, 0, launchNodeSnap).then((weaponNode) => {
|
||
|
|
|
||
|
|
if (!weaponNode?.isValid) return;
|
||
|
|
|
||
|
|
weaponNode.getComponent(Skill)?.setData(gg.data.project.getWeaponData(weaponId), v3(0, 0, 0), false, false, j, 0, 0, 0, tetriLevel);
|
||
|
|
|
||
|
|
});
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
LightningElectricity(weaponProperty: IWeaponProperty, posX, xTime, launchCount, burstCount) {
|
||
|
|
if (!this.shouldHandleWeaponLaunch(weaponProperty?.weaponId)) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
//雷电武器
|
||
|
|
if (!this._isCanShoot) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if (!this.isSettledForWeaponShoot()) {
|
||
|
|
//console.log('没有落稳的方块不在发射武器')
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
const weaponId = this._curentWeaponId;
|
||
|
|
const volume = weaponProperty.volume;
|
||
|
|
const carrierNode = this.node;
|
||
|
|
const launchNodeSnap = this.getWeaponLaunchNode();
|
||
|
|
const tetriLevel = this.getCarrierTetriLevel();
|
||
|
|
|
||
|
|
let weaponConf = gg.data.project.getWeaponData(weaponId)
|
||
|
|
if (weaponConf.flight == SkillType.无弹道单体) {
|
||
|
|
gg.game.CurentBattle?.enqueueWeaponLaunchEvent?.({
|
||
|
|
type: GEvent.LightningElectricity,
|
||
|
|
run: () => {
|
||
|
|
const battle = gg.game.CurentBattle;
|
||
|
|
if (!battle?.SkillController?.node?.isValid) return;
|
||
|
|
if (!isValid(carrierNode)) return;
|
||
|
|
const carrier = carrierNode.getComponent(tetriWeaponCarrier);
|
||
|
|
if (!carrier) return;
|
||
|
|
carrier.playAtkAnim();
|
||
|
|
const lead = tetriWeaponCarrier.ATK_ANIM_LEAD_SEC / battle.TimeScale;
|
||
|
|
for (let i = 0; i < burstCount; i++) {
|
||
|
|
let t1 = lead + xTime * i;
|
||
|
|
this.scheduleWeaponFire(t1, () => {
|
||
|
|
// 面向最近怪物(角色不移动也需要左右转向)
|
||
|
|
this.faceRoleToMonster(battle.MonsterSpawner?.getAllPathDisMinMonster?.(carrierNode));
|
||
|
|
|
||
|
|
this.playEffectStraightNum(weaponId);
|
||
|
|
|
||
|
|
for (let j = 0; j < launchCount; j++) {
|
||
|
|
//多个子弹并排开
|
||
|
|
let addPos = v3(j * posX - (launchCount - 1) * posX / 2, 0, 0)
|
||
|
|
void battle.SkillController.instantiateSingleWeapon(weaponId, volume, addPos, 0, launchNodeSnap).then((weaponNode) => {
|
||
|
|
if (!weaponNode?.isValid) return;
|
||
|
|
weaponNode.getComponent(Skill)?.setData(gg.data.project.getWeaponData(weaponId), v3(0, 0, 0), false, false, j, 0, 0, 0, tetriLevel);
|
||
|
|
});
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**直线播放武器音效 */
|
||
|
|
playEffectStraight(weaponId: number) {
|
||
|
|
//1,9,14,16
|
||
|
|
if (weaponId == WeaponType.DanGong) {
|
||
|
|
gg.audio.playEffect({ name: '弹弓', path: 'sound/武器音效2/' });
|
||
|
|
} else if (weaponId == WeaponType.TuJiBuBuQiang) {
|
||
|
|
gg.audio.playEffect({ name: '突击步枪', path: 'sound/武器音效2/' });
|
||
|
|
} else if (weaponId == WeaponType.DianCiPao) {
|
||
|
|
gg.audio.playEffect({ name: '电磁炮', path: 'sound/武器音效2/' });
|
||
|
|
} else if (weaponId == WeaponType.ZhanShuZhuaDao) {
|
||
|
|
gg.audio.playEffect({ name: '战术爪刀', path: 'sound/武器音效2/' });
|
||
|
|
}else if (weaponId == WeaponType.LiSanDaoDan) {
|
||
|
|
gg.audio.playEffect({ name: '导弹', path: 'sound/武器音效2/' });
|
||
|
|
}else if (weaponId == WeaponType.LeiShenZhiChui) {
|
||
|
|
gg.audio.playEffect({ name: '雷击', path: 'sound/武器音效2/' });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**直线数量播放武器音效 */
|
||
|
|
playEffectStraightNum(weaponId: number) {
|
||
|
|
//3
|
||
|
|
if (weaponId == WeaponType.ChangGong) {
|
||
|
|
gg.audio.playEffect({ name: '射箭', path: 'sound/武器音效2/' });
|
||
|
|
}else if (weaponId == WeaponType.LeiShenZhiChui) {
|
||
|
|
gg.audio.playEffect({ name: '雷击', path: 'sound/武器音效2/' });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**直线弹射播放武器音效 */
|
||
|
|
playEffectStraightLaunch(weaponId: number) {
|
||
|
|
//5,7
|
||
|
|
if (weaponId == WeaponType.HuiXuanBiao) {
|
||
|
|
gg.audio.playEffect({ name: '回旋镖', path: 'sound/武器音效2/' });
|
||
|
|
} else if (weaponId == WeaponType.FaZhen) {
|
||
|
|
gg.audio.playEffect({ name: '法杖', path: 'sound/武器音效2/' });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**抛物线碰撞播放武器音效 */
|
||
|
|
playEffectParabolaCollide(weaponId: number) {
|
||
|
|
//2,4,6
|
||
|
|
if (weaponId == WeaponType.BiaoQiang) {
|
||
|
|
gg.audio.playEffect({ name: '长矛', path: 'sound/武器音效2/' });
|
||
|
|
} else if (weaponId == WeaponType.ShiFu) {
|
||
|
|
gg.audio.playEffect({ name: '斧头', path: 'sound/武器音效2/' });
|
||
|
|
} else if (weaponId == WeaponType.FeiJian) {
|
||
|
|
gg.audio.playEffect({ name: '飞剑', path: 'sound/武器音效2/' });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**抛物线没有碰撞播放武器音效 */
|
||
|
|
playEffectParabolaNoCollide(weaponId: number) {
|
||
|
|
|
||
|
|
//8,10,11,13,15
|
||
|
|
if (weaponId == WeaponType.FuWenTa) {
|
||
|
|
gg.audio.playEffect({ name: '符文塔', path: 'sound/武器音效2/' });
|
||
|
|
} else if (weaponId == WeaponType.DaPao) {
|
||
|
|
gg.audio.playEffect({ name: '大炮', path: 'sound/武器音效2/' });
|
||
|
|
} else if (weaponId == WeaponType.ShouLiuDan) {
|
||
|
|
gg.audio.playEffect({ name: '手榴弹', path: 'sound/武器音效2/' });
|
||
|
|
} else if (weaponId == WeaponType.ZhuiZongDaoDan) {
|
||
|
|
gg.audio.playEffect({ name: '追踪导弹', path: 'sound/武器音效2/' });
|
||
|
|
} else if (weaponId == WeaponType.BingDongShouLei) {
|
||
|
|
gg.audio.playEffect({ name: '冰冻手雷', path: 'sound/武器音效2/' });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
getCurWeaponId() {
|
||
|
|
return this._curentWeaponId
|
||
|
|
}
|
||
|
|
|
||
|
|
setIsShootCan(can: boolean) {
|
||
|
|
this._isCanShoot = can
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|