import { _decorator, Collider, Enum, Node, RigidBody, SkeletalAnimation, Vec3 } from 'cc'; import { BaseExp } from '../core/base/BaseExp'; import { PoolManager } from '../core/manager/PoolManager'; import { userIns } from '../data/UserData'; import { autoBind } from '../extend/AutoBind'; import { Logger } from '../extend/Logger'; import { ResUtil } from '../utils/ResUtil'; import { Game } from './Game'; import { Enemy, EPartType } from './Enemy'; import { audioMgr } from '../core/manager/AudioManager'; import { Constants } from '../data/Constants'; import MsgHints from '../utils/MsgHints'; const { ccclass, property } = _decorator; /** * 战场障碍物类型 */ export enum ObstacleType { /** 沙袋堆 */ SANDBAG_PILE = "沙袋堆", /** 油桶 */ OIL_BARREL = "油桶", /** 军车 */ MILITARY_TRUCK = "军车", /** 小沙袋 */ SMALL_SANDBAG = "小沙袋" } /** * 杂物建筑物类 */ @ccclass('Sundries') export class Sundries extends BaseExp { @property({ type: Enum(ObstacleType), tooltip: "SANDBAG_PILE: 沙袋堆 OIL_BARREL: 油桶 MILITARY_TRUCK: 军车 SMALL_SANDBAG: 小沙袋 ", displayName: "障碍物类型"}) public obstacleType: ObstacleType = ObstacleType.SANDBAG_PILE; @autoBind({type: SkeletalAnimation,tooltip: "杂物动画节点"}) public skeletal: SkeletalAnimation = null!; //杂物信息数据 public data: any = null; //杂物是否被打报废 private isDead: boolean = false; //杂物当前的总血量 private totalHp: number = 0; //杂物身上的Collider public collider: Collider = null!; start() { this.collider = this.node.getComponent(Collider); if(this.collider){ this.collider["args"] = [EPartType.sundries,this]; } //根据障碍物类型设置总血量 let sundrie_id: number = -1; switch (this.obstacleType) { case ObstacleType.SANDBAG_PILE: sundrie_id = 11001; break; case ObstacleType.OIL_BARREL: sundrie_id = 11002; break; case ObstacleType.MILITARY_TRUCK: sundrie_id = 11003; break; case ObstacleType.SMALL_SANDBAG: sundrie_id = 11004; break; } if(sundrie_id !== -1){ const data: any = userIns.sundriesTable.find(e=>e.id == sundrie_id); this.data = data; this.totalHp = data.hp; }else{ Logger.log('未找到对应的杂物信息'); } } /** * 杂物被打掉血 * @param hp 血 * @param pData 玩家数据 */ public subHP(hp: number, pData:any){ if(Game.I.isPause ||this.isDead ||hp == null ||this.totalHp <= 0){ return; } MsgHints.show(`${this.node.name} HP:`+hp) this.totalHp -= hp; //杂物打打死报废 if(this.totalHp <= 0 && !this.isDead){ this.isDead = true; this.scrap(); } } /** * 杂物被打报废 */ public scrap(){ switch (this.obstacleType) { case ObstacleType.SANDBAG_PILE:{//沙袋堆 if(this.skeletal)return; //沙袋掀开的动画 this.skeletal.play('take'); this.scheduleOnce(this.recycle.bind(this), 1.5); } break; case ObstacleType.OIL_BARREL:{//油桶 //油漆桶爆炸动画 audioMgr.playOneShot(Constants.audios.Oildrum_explosion); //爆炸后生成爆炸特效 粒子路径、自动回收时间、外部设置回调 ResUtil.playParticle( `effects/Prefabs/OilBoom`, 4, (particle) => { particle.position = new Vec3(0.1,0.1, 0.1); particle.children.forEach((c) => { c.position = new Vec3(0.1, 0.1, 0.1); }); particle.parent = Game.I.map.node; particle.worldPosition = this.node.worldPosition.clone(); particle.active = true; this.recycle(); //爆炸后生成爆炸伤害 this.explosionDamage(); } ); } break; case ObstacleType.MILITARY_TRUCK:{//军车 //加载报废的军车 ResUtil.loadRes(`enemy/sundries/scrap_car`, this.node) .then((military: Node | null) => { if(!military)return; military.active = true; military.parent = Game.I.map.node; military.worldPosition = this.node.worldPosition.clone(); //回收原有的军车 this.recycle(); //播放爆炸过后的浓烟 ResUtil.playParticle( `effects/Prefabs/HeavySmoke`, 4, (particle) => { particle.parent = Game.I.map.node; particle.worldPosition = this.node.worldPosition.clone(); particle.active = true; particle.scale = new Vec3(0.5, 0.5, 0.5); //爆炸后生成爆炸伤害 this.explosionDamage(); } ); }); } break; case ObstacleType.SMALL_SANDBAG:{//小沙袋 //获取刚体组件 const rigidBody = this.node.getComponent(RigidBody); if (!rigidBody) return; //计算抛射方向 const startPos = this.node.worldPosition.clone(); const playerPos = Game.I.player.node.worldPosition.clone(); const direction = startPos.subtract(playerPos).normalize(); //随机抛射参数 水平力1500-2500N const horizontalForce = 1500 + Math.random() * 1000; //垂直力800-1500N const verticalForce = 800 + Math.random() * 700; //旋转扭矩50-150 const torqueForce = 50 + Math.random() * 100; //施加作用力 rigidBody.applyForce(new Vec3( direction.x * horizontalForce, verticalForce, direction.z * horizontalForce )); //施加旋转扭矩 rigidBody.applyTorque(new Vec3(0, torqueForce, 0)); } break; } } /** * 爆炸物产生爆炸伤害 * @returns */ public explosionDamage(){ //爆炸半径 const eRadius: number = this.data.explosion_radius; const allEnemys = Game.I.buildEnemys.allEnemys.filter(e=>!e.isDead); if(allEnemys.length <= 0)return; //爆炸伤害 const damage: number = this.data.explosion_injury; allEnemys.forEach((e: Enemy) => { const ePos: Vec3 = e.node.worldPosition; const sPos: Vec3 = this.node.worldPosition; const distance = ePos.clone().subtract(sPos).length(); if(distance <= eRadius) { e.subHP(damage, this.data); } }) } /** * 杂物回收 */ public recycle(){ if(this.node.parent){ this.isDead = true; PoolManager.putNode(this.node); } } }