Monster.ts 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import { _decorator, Component, Node, sp, v3, SystemEvent, ProgressBar, Sprite, Label, SpriteFrame, Prefab, instantiate, Vec3, tween, Animation } from 'cc';
  2. import { DataSystem } from '../core/data/DataSystem';
  3. import { ResourceLoader } from '../core/resourceManager/ResourceLoader';
  4. import { Sound } from '../core/sound/Sound';
  5. import { ConfigData } from '../data/ConfigData';
  6. import { GM } from '../launch/GM';
  7. import { BattleData } from './BattleData';
  8. import { Buff } from './Buff';
  9. import { MissionData } from './MissionData';
  10. import { MonsterData } from './MonsterData';
  11. import { MonsterUI } from './MonsterUI';
  12. import { TakeAWalk, WalkState } from './TakeAWalk';
  13. import { BloodLabel } from './ui/BloodLabel';
  14. const { ccclass, property } = _decorator;
  15. @ccclass('Monster')
  16. export class Monster extends Component {
  17. @property({ type: ResourceLoader, tooltip: "资源加载组件" }) res: ResourceLoader;
  18. @property({ type: sp.Skeleton, tooltip: "spine组件" }) spine: sp.Skeleton;
  19. @property({ type: Animation, tooltip: "移动结束动画" }) moveEndAnimation: Animation;
  20. @property({ type: Node, tooltip: "特效层" }) buffContainer: Node;
  21. public monsterUI: MonsterUI;
  22. public data: MonsterData;
  23. private config: any;
  24. /**音效组件 */
  25. private sound: Sound;
  26. start() {
  27. this.sound = this.getComponent(Sound);
  28. this.node.on(SystemEvent.EventType.TOUCH_END, this.onSelect, this);
  29. this.setUI();
  30. }
  31. update() {
  32. DataSystem.watch(this.data, "_hit") && this.onHit();
  33. DataSystem.watch(this.data, "id") && this.changeModel();
  34. DataSystem.watch(this.data, "isBoss") && this.setUI();
  35. // DataSystem.watch(this.data, "movePoints") && this.walk();
  36. DataSystem.watch(this.data, "_addBuff") && this.addBuff();
  37. this.checkObstruct();
  38. this.monsterUI.node.position = this.node.position;
  39. }
  40. onDestroy() {
  41. this.monsterUI.node && this.monsterUI.node.destroy();
  42. }
  43. private setUI(): void {
  44. this.node.setScale(this.data.isBoss ? v3(-0.8, 0.8, 1) : v3(-0.55, 0.55, 1));
  45. this.monsterUI.bloodGroup.setScale(this.data.isBoss ? v3(1.4, 1.4, 1) : v3(2, 2, 2));
  46. let scale = this.node.scale.clone();
  47. scale.x = scale.x * -1;
  48. this.monsterUI.node.setScale(scale);
  49. }
  50. /**当设置强制攻击目标 */
  51. private onSelect(): void {
  52. let data = DataSystem.getData(BattleData);
  53. for (let i = 0; i < data._monsters.length; i++) {
  54. if (this.data._id == data._monsters[i].data._id) {
  55. data._target = i;
  56. return;
  57. }
  58. }
  59. }
  60. /**设置怪物数据 */
  61. public async setData(data: any, monsterUI: MonsterUI) {
  62. this.getComponent(Buff).layer = this.buffContainer;
  63. this.monsterUI = monsterUI;
  64. if (!this.data) {
  65. this.data = new MonsterData();
  66. DataSystem.regeditData(this.data);
  67. }
  68. this.config = DataSystem.getData(ConfigData)["monster"];
  69. this.data.copy(data);
  70. this.monsterUI.BossGroup.active = this.data.isBoss;
  71. if (this.data.isBoss) {
  72. this.monsterUI.nameLabel.string = this.config[this.data.id]["name"];
  73. this.monsterUI.camp.spriteFrame = await this.res.load<SpriteFrame>('image/public/camp' + this.config[this.data.id]["camp"] + "/spriteFrame", SpriteFrame);
  74. }
  75. else {
  76. this.monsterUI.nameLabel.string = "";
  77. this.monsterUI.camp.spriteFrame = null;
  78. }
  79. }
  80. /**变化模型 */
  81. private async changeModel() {
  82. let spData = await this.res.load<sp.SkeletonData>("spine/hero/" + this.config[this.data.id]["resource"], sp.SkeletonData);
  83. this.spine.skeletonData = spData;
  84. this.spine.setAnimation(0, "run", true);
  85. }
  86. /**开始移动 */
  87. public walk(): void {
  88. let walk = this.node.getComponent(TakeAWalk);
  89. walk.points = this.data.movePoints.concat();
  90. walk.speed = this.data.speed;
  91. walk.walk();
  92. this.data._isWalking = true;
  93. }
  94. /**当移动到终点 */
  95. public moveEnd(): void {
  96. if (!this.node.isValid) {
  97. return;
  98. }
  99. // GM.addBattleLog(`怪物${this.data._id},移动到终点`);
  100. this.data._isWalking = false;
  101. DataSystem.getData(BattleData)._moveEndCount++;
  102. DataSystem.getData(BattleData)._deleteMonster.push(this.data._id);
  103. this.moveEndAnimation.play();
  104. this.moveEndAnimation.on(Animation.EventType.FINISHED, () => {
  105. // GM.addBattleLog(`怪物${this.data._id},移动到终点,清除节点`);
  106. this.node.isValid && this.node.destroy();
  107. }, this);
  108. }
  109. /** 当受到伤害*/
  110. private async onHit() {
  111. for (let i = 0; i < this.data._hit.length; i++) {
  112. let node = instantiate(this.monsterUI.prefab);
  113. node.setParent(this.monsterUI.bloodGroup);
  114. node.getComponent(BloodLabel).setData(this.data._hit[i]);
  115. if (!isNaN(this.data._hit[i].hit)) {
  116. if (!this.data._hit[i].isMiss) {
  117. this.data.hp -= this.data._hit[i].hit;
  118. this.monsterUI.bloodBar.progress = this.data.hp / DataSystem.getData(ConfigData)["monster"][this.data.id]["hp"];
  119. // GM.addBattleLog(`怪物${this.data._id},收到伤害:${this.data._hit[i].hit},剩余血量:${this.data.hp}`);
  120. if (this.data.hp <= 0) {
  121. this.die();
  122. // GM.addBattleLog(`怪物${this.data._id}放入删除列表`);
  123. DataSystem.getData(BattleData)._deleteMonster.indexOf(this.data._id) == -1 && DataSystem.getData(BattleData)._deleteMonster.push(this.data._id);
  124. }
  125. }
  126. } else {
  127. console.error("伤害数值出现NAN!");
  128. // GM.addBattleLog("伤害数值出现NAN!\n" + JSON.stringify(this.data._hit[i]));
  129. }
  130. }
  131. this.data._hit = [];
  132. }
  133. private isDestroy = false;
  134. /**怪物死亡 */
  135. private async die() {
  136. if (this.isDestroy) {
  137. return;
  138. }
  139. this.buffContainer.active = false;
  140. this.isDestroy = true;
  141. // GM.addBattleLog(`怪物${this.data._id}死亡`);
  142. this.data._isWalking = false;
  143. this.monsterUI.bloodNode.active = false;
  144. DataSystem.getData(BattleData)._monsterKilled.push(this.data.id);
  145. DataSystem.getData(BattleData)._monsterKilledNode.push(v3(this.node.position));
  146. this.node.getComponent(TakeAWalk).stop();
  147. this.spine.node.scale = v3(1.2, 1.2, 1);
  148. this.spine.skeletonData = this.monsterUI.dieSpine;
  149. this.spine.setAnimation(0, "animation", false);
  150. let self = this;
  151. this.spine.setCompleteListener(() => {
  152. self.node.destroy();
  153. });
  154. }
  155. /**添加buff */
  156. private addBuff(): void {
  157. this.node.getComponent(Buff).addBuff(this.data._addBuff);
  158. this.data._addBuff = [];
  159. }
  160. /**检查阻碍物 */
  161. private checkObstruct(): void {
  162. let obstruct = DataSystem.getData(BattleData)._obstruct;
  163. if (obstruct) {
  164. if (Vec3.distance(this.node.position, DataSystem.getData(BattleData)._obstruct.position) <= 50) {
  165. if (this.node.getComponent(TakeAWalk).state != WalkState.pause) {
  166. this.node.getComponent(TakeAWalk).pause();
  167. if (this.sound && !DataSystem.getData(MissionData).isInPvp) {
  168. this.sound.play();
  169. }
  170. }
  171. }
  172. } else {
  173. if (this.node.getComponent(TakeAWalk).state == WalkState.pause) {
  174. this.node.getComponent(TakeAWalk).resume();
  175. }
  176. }
  177. }
  178. }