Sundries.ts 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. import { _decorator, Collider, Enum, Node, RigidBody, SkeletalAnimation, Vec3 } from 'cc';
  2. import { BaseExp } from '../core/base/BaseExp';
  3. import { PoolManager } from '../core/manager/PoolManager';
  4. import { userIns } from '../data/UserData';
  5. import { autoBind } from '../extend/AutoBind';
  6. import { Logger } from '../extend/Logger';
  7. import { ResUtil } from '../utils/ResUtil';
  8. import { Game } from './Game';
  9. import { Enemy, EPartType } from './Enemy';
  10. import { audioMgr } from '../core/manager/AudioManager';
  11. import { Constants } from '../data/Constants';
  12. import MsgHints from '../utils/MsgHints';
  13. const { ccclass, property } = _decorator;
  14. /**
  15. * 战场障碍物类型
  16. */
  17. export enum ObstacleType {
  18. /** 沙袋堆 */
  19. SANDBAG_PILE = "沙袋堆",
  20. /** 油桶 */
  21. OIL_BARREL = "油桶",
  22. /** 军车 */
  23. MILITARY_TRUCK = "军车",
  24. /** 小沙袋 */
  25. SMALL_SANDBAG = "小沙袋"
  26. }
  27. /**
  28. * 杂物建筑物类
  29. */
  30. @ccclass('Sundries')
  31. export class Sundries extends BaseExp {
  32. @property({ type: Enum(ObstacleType), tooltip: "SANDBAG_PILE: 沙袋堆 OIL_BARREL: 油桶 MILITARY_TRUCK: 军车 SMALL_SANDBAG: 小沙袋 ", displayName: "障碍物类型"})
  33. public obstacleType: ObstacleType = ObstacleType.SANDBAG_PILE;
  34. @autoBind({type: SkeletalAnimation,tooltip: "杂物动画节点"})
  35. public skeletal: SkeletalAnimation = null!;
  36. //杂物信息数据
  37. public data: any = null;
  38. //杂物是否被打报废
  39. private isDead: boolean = false;
  40. //杂物当前的总血量
  41. private totalHp: number = 0;
  42. //杂物身上的Collider
  43. public collider: Collider = null!;
  44. start() {
  45. this.collider = this.node.getComponent(Collider);
  46. if(this.collider){
  47. this.collider["args"] = [EPartType.sundries,this];
  48. }
  49. //根据障碍物类型设置总血量
  50. let sundrie_id: number = -1;
  51. switch (this.obstacleType) {
  52. case ObstacleType.SANDBAG_PILE:
  53. sundrie_id = 11001;
  54. break;
  55. case ObstacleType.OIL_BARREL:
  56. sundrie_id = 11002;
  57. break;
  58. case ObstacleType.MILITARY_TRUCK:
  59. sundrie_id = 11003;
  60. break;
  61. case ObstacleType.SMALL_SANDBAG:
  62. sundrie_id = 11004;
  63. break;
  64. }
  65. if(sundrie_id !== -1){
  66. const data: any = userIns.sundriesTable.find(e=>e.id == sundrie_id);
  67. this.data = data;
  68. this.totalHp = data.hp;
  69. }else{
  70. Logger.log('未找到对应的杂物信息');
  71. }
  72. }
  73. /**
  74. * 杂物被打掉血
  75. * @param hp 血
  76. * @param pData 玩家数据
  77. */
  78. public subHP(hp: number, pData:any){
  79. if(Game.I.isPause
  80. ||this.isDead
  81. ||hp == null
  82. ||this.totalHp <= 0){
  83. return;
  84. }
  85. MsgHints.show(`${this.node.name} HP:`+hp)
  86. this.totalHp -= hp;
  87. //杂物打打死报废
  88. if(this.totalHp <= 0
  89. && !this.isDead){
  90. this.isDead = true;
  91. this.scrap();
  92. }
  93. }
  94. /**
  95. * 杂物被打报废
  96. */
  97. public scrap(){
  98. switch (this.obstacleType) {
  99. case ObstacleType.SANDBAG_PILE:{//沙袋堆
  100. if(this.skeletal)return;
  101. //沙袋掀开的动画
  102. this.skeletal.play('take');
  103. this.scheduleOnce(this.recycle.bind(this), 1.5);
  104. }
  105. break;
  106. case ObstacleType.OIL_BARREL:{//油桶
  107. //油漆桶爆炸动画
  108. audioMgr.playOneShot(Constants.audios.Oildrum_explosion);
  109. //爆炸后生成爆炸特效 粒子路径、自动回收时间、外部设置回调
  110. ResUtil.playParticle(
  111. `effects/Prefabs/OilBoom`,
  112. 4,
  113. (particle) => {
  114. particle.position = new Vec3(0.1,0.1, 0.1);
  115. particle.children.forEach((c) => {
  116. c.position = new Vec3(0.1, 0.1, 0.1);
  117. });
  118. particle.parent = Game.I.map.node;
  119. particle.worldPosition = this.node.worldPosition.clone();
  120. particle.active = true;
  121. this.recycle();
  122. //爆炸后生成爆炸伤害
  123. this.explosionDamage();
  124. }
  125. );
  126. }
  127. break;
  128. case ObstacleType.MILITARY_TRUCK:{//军车
  129. //加载报废的军车
  130. ResUtil.loadRes(`enemy/sundries/scrap_car`, this.node)
  131. .then((military: Node | null) => {
  132. if(!military)return;
  133. military.active = true;
  134. military.parent = Game.I.map.node;
  135. military.worldPosition = this.node.worldPosition.clone();
  136. //回收原有的军车
  137. this.recycle();
  138. //播放爆炸过后的浓烟
  139. ResUtil.playParticle(
  140. `effects/Prefabs/HeavySmoke`,
  141. 4,
  142. (particle) => {
  143. particle.parent = Game.I.map.node;
  144. particle.worldPosition = this.node.worldPosition.clone();
  145. particle.active = true;
  146. particle.scale = new Vec3(0.5, 0.5, 0.5);
  147. //爆炸后生成爆炸伤害
  148. this.explosionDamage();
  149. }
  150. );
  151. });
  152. }
  153. break;
  154. case ObstacleType.SMALL_SANDBAG:{//小沙袋
  155. //获取刚体组件
  156. const rigidBody = this.node.getComponent(RigidBody);
  157. if (!rigidBody) return;
  158. //计算抛射方向
  159. const startPos = this.node.worldPosition.clone();
  160. const playerPos = Game.I.player.node.worldPosition.clone();
  161. const direction = startPos.subtract(playerPos).normalize();
  162. //随机抛射参数 水平力1500-2500N
  163. const horizontalForce = 1500 + Math.random() * 1000;
  164. //垂直力800-1500N
  165. const verticalForce = 800 + Math.random() * 700;
  166. //旋转扭矩50-150
  167. const torqueForce = 50 + Math.random() * 100;
  168. //施加作用力
  169. rigidBody.applyForce(new Vec3(
  170. direction.x * horizontalForce,
  171. verticalForce,
  172. direction.z * horizontalForce
  173. ));
  174. //施加旋转扭矩
  175. rigidBody.applyTorque(new Vec3(0, torqueForce, 0));
  176. }
  177. break;
  178. }
  179. }
  180. /**
  181. * 爆炸物产生爆炸伤害
  182. * @returns
  183. */
  184. public explosionDamage(){
  185. //爆炸半径
  186. const eRadius: number = this.data.explosion_radius;
  187. const allEnemys = Game.I.buildEnemys.allEnemys.filter(e=>!e.isDead);
  188. if(allEnemys.length <= 0)return;
  189. //爆炸伤害
  190. const damage: number = this.data.explosion_injury;
  191. allEnemys.forEach((e: Enemy) => {
  192. const ePos: Vec3 = e.node.worldPosition;
  193. const sPos: Vec3 = this.node.worldPosition;
  194. const distance = ePos.clone().subtract(sPos).length();
  195. if(distance <= eRadius) {
  196. e.subHP(damage, this.data);
  197. }
  198. })
  199. }
  200. /**
  201. * 杂物回收
  202. */
  203. public recycle(){
  204. if(this.node.parent){
  205. this.isDead = true;
  206. PoolManager.putNode(this.node);
  207. }
  208. }
  209. }