import { _decorator, Component, Node, sp, v3, SystemEvent, ProgressBar, Sprite, Label, SpriteFrame, Prefab, instantiate, Vec3, tween, Animation } from 'cc'; import { DataSystem } from '../core/data/DataSystem'; import { ResourceLoader } from '../core/resourceManager/ResourceLoader'; import { Sound } from '../core/sound/Sound'; import { ConfigData } from '../data/ConfigData'; import { GM } from '../launch/GM'; import { BattleData } from './BattleData'; import { Buff } from './Buff'; import { MissionData } from './MissionData'; import { MonsterData } from './MonsterData'; import { MonsterUI } from './MonsterUI'; import { TakeAWalk, WalkState } from './TakeAWalk'; import { BloodLabel } from './ui/BloodLabel'; const { ccclass, property } = _decorator; @ccclass('Monster') export class Monster extends Component { @property({ type: ResourceLoader, tooltip: "资源加载组件" }) res: ResourceLoader; @property({ type: sp.Skeleton, tooltip: "spine组件" }) spine: sp.Skeleton; @property({ type: Animation, tooltip: "移动结束动画" }) moveEndAnimation: Animation; @property({ type: Node, tooltip: "特效层" }) buffContainer: Node; public monsterUI: MonsterUI; public data: MonsterData; private config: any; /**音效组件 */ private sound: Sound; start() { this.sound = this.getComponent(Sound); this.node.on(SystemEvent.EventType.TOUCH_END, this.onSelect, this); this.setUI(); } update() { DataSystem.watch(this.data, "_hit") && this.onHit(); DataSystem.watch(this.data, "id") && this.changeModel(); DataSystem.watch(this.data, "isBoss") && this.setUI(); // DataSystem.watch(this.data, "movePoints") && this.walk(); DataSystem.watch(this.data, "_addBuff") && this.addBuff(); this.checkObstruct(); this.monsterUI.node.position = this.node.position; } onDestroy() { this.monsterUI.node && this.monsterUI.node.destroy(); } private setUI(): void { this.node.setScale(this.data.isBoss ? v3(-0.8, 0.8, 1) : v3(-0.55, 0.55, 1)); this.monsterUI.bloodGroup.setScale(this.data.isBoss ? v3(1.4, 1.4, 1) : v3(2, 2, 2)); let scale = this.node.scale.clone(); scale.x = scale.x * -1; this.monsterUI.node.setScale(scale); } /**当设置强制攻击目标 */ private onSelect(): void { let data = DataSystem.getData(BattleData); for (let i = 0; i < data._monsters.length; i++) { if (this.data._id == data._monsters[i].data._id) { data._target = i; return; } } } /**设置怪物数据 */ public async setData(data: any, monsterUI: MonsterUI) { this.getComponent(Buff).layer = this.buffContainer; this.monsterUI = monsterUI; if (!this.data) { this.data = new MonsterData(); DataSystem.regeditData(this.data); } this.config = DataSystem.getData(ConfigData)["monster"]; this.data.copy(data); this.monsterUI.BossGroup.active = this.data.isBoss; if (this.data.isBoss) { this.monsterUI.nameLabel.string = this.config[this.data.id]["name"]; this.monsterUI.camp.spriteFrame = await this.res.load('image/public/camp' + this.config[this.data.id]["camp"] + "/spriteFrame", SpriteFrame); } else { this.monsterUI.nameLabel.string = ""; this.monsterUI.camp.spriteFrame = null; } } /**变化模型 */ private async changeModel() { let spData = await this.res.load("spine/hero/" + this.config[this.data.id]["resource"], sp.SkeletonData); this.spine.skeletonData = spData; this.spine.setAnimation(0, "run", true); } /**开始移动 */ public walk(): void { let walk = this.node.getComponent(TakeAWalk); walk.points = this.data.movePoints.concat(); walk.speed = this.data.speed; walk.walk(); this.data._isWalking = true; } /**当移动到终点 */ public moveEnd(): void { if (!this.node.isValid) { return; } // GM.addBattleLog(`怪物${this.data._id},移动到终点`); this.data._isWalking = false; DataSystem.getData(BattleData)._moveEndCount++; DataSystem.getData(BattleData)._deleteMonster.push(this.data._id); this.moveEndAnimation.play(); this.moveEndAnimation.on(Animation.EventType.FINISHED, () => { // GM.addBattleLog(`怪物${this.data._id},移动到终点,清除节点`); this.node.isValid && this.node.destroy(); }, this); } /** 当受到伤害*/ private async onHit() { for (let i = 0; i < this.data._hit.length; i++) { let node = instantiate(this.monsterUI.prefab); node.setParent(this.monsterUI.bloodGroup); node.getComponent(BloodLabel).setData(this.data._hit[i]); if (!isNaN(this.data._hit[i].hit)) { if (!this.data._hit[i].isMiss) { this.data.hp -= this.data._hit[i].hit; this.monsterUI.bloodBar.progress = this.data.hp / DataSystem.getData(ConfigData)["monster"][this.data.id]["hp"]; // GM.addBattleLog(`怪物${this.data._id},收到伤害:${this.data._hit[i].hit},剩余血量:${this.data.hp}`); if (this.data.hp <= 0) { this.die(); // GM.addBattleLog(`怪物${this.data._id}放入删除列表`); DataSystem.getData(BattleData)._deleteMonster.indexOf(this.data._id) == -1 && DataSystem.getData(BattleData)._deleteMonster.push(this.data._id); } } } else { console.error("伤害数值出现NAN!"); // GM.addBattleLog("伤害数值出现NAN!\n" + JSON.stringify(this.data._hit[i])); } } this.data._hit = []; } private isDestroy = false; /**怪物死亡 */ private async die() { if (this.isDestroy) { return; } this.buffContainer.active = false; this.isDestroy = true; // GM.addBattleLog(`怪物${this.data._id}死亡`); this.data._isWalking = false; this.monsterUI.bloodNode.active = false; DataSystem.getData(BattleData)._monsterKilled.push(this.data.id); DataSystem.getData(BattleData)._monsterKilledNode.push(v3(this.node.position)); this.node.getComponent(TakeAWalk).stop(); this.spine.node.scale = v3(1.2, 1.2, 1); this.spine.skeletonData = this.monsterUI.dieSpine; this.spine.setAnimation(0, "animation", false); let self = this; this.spine.setCompleteListener(() => { self.node.destroy(); }); } /**添加buff */ private addBuff(): void { this.node.getComponent(Buff).addBuff(this.data._addBuff); this.data._addBuff = []; } /**检查阻碍物 */ private checkObstruct(): void { let obstruct = DataSystem.getData(BattleData)._obstruct; if (obstruct) { if (Vec3.distance(this.node.position, DataSystem.getData(BattleData)._obstruct.position) <= 50) { if (this.node.getComponent(TakeAWalk).state != WalkState.pause) { this.node.getComponent(TakeAWalk).pause(); if (this.sound && !DataSystem.getData(MissionData).isInPvp) { this.sound.play(); } } } } else { if (this.node.getComponent(TakeAWalk).state == WalkState.pause) { this.node.getComponent(TakeAWalk).resume(); } } } }