import { Collider2D, Vec3 } from 'cc'; import { _decorator, Component, Node } from 'cc'; import { UmUtil } from '../../../../cc-common/cc-util/UmUtil'; import { ColliderObject } from '../../base/ColliderObject'; import { UmLog } from '../../../../cc-common/cc-util/UmLog'; import { GameDefine, EPHYSIC_GROUP, EACTIVE_SKILL_TYPE, ENEMY_TYPE, EATTACK_TYPE } from '../../config/GameDefine'; import { BulletBase } from '../bullet/BulletBase'; import { LayoutManager } from '../LayoutManager'; import { Sprite } from 'cc'; import { Color } from 'cc'; import { ShootingBase } from '../bullet/ShootingBase'; import { GameGlobalData } from '../../global/GameGlobalData'; import { EnemyDataInfo, ShootingDataInfo } from '../../global/GameInterface'; import { ActiveSkillBase } from '../hero/ActiveSkillBase'; import { Enum } from 'cc'; import { UmClientEvent } from '../../../../cc-common/cc-util/UmOneToMultiListener'; import { RigidBody2D } from 'cc'; import { Label } from 'cc'; import { CircleCollider2D } from 'cc'; const { ccclass, property } = _decorator; @ccclass('EnemyBase') export class EnemyBase extends Component { @property(ColliderObject) colliderObject: ColliderObject = null!; @property(ColliderObject) sensor: ColliderObject = null!; @property(RigidBody2D) rigibodyComponent: RigidBody2D = null!; @property(Sprite) theme: Sprite = null!; @property(ShootingBase) shooting: ShootingBase = null!; @property({ type: Enum(ENEMY_TYPE) }) public enemyType: ENEMY_TYPE = ENEMY_TYPE.MELEE; @property({ type: Enum(EATTACK_TYPE) }) public attackType: EATTACK_TYPE = EATTACK_TYPE.MELEE @property(Label) txtName: Label = null!; isShootEnable = false; isDestroying = false; isCheckedWin = false; currentColor: Color; effectColor: Color = Color.GREEN; heroTarget: Node; dmg = 5; moveSpeed = 50; range = 5; hp = 1000; dataConfig: any = null; atkCooldown: number = 1; visualRange: number = 5; TWEEN_TAG = 1001; setEnemyData(data) { // No: data["no"], // Name_Id: data["nameid"], // Group: data["group"], // Visual_Name: data["visualname"], // Atk: data["atk"], // Hp: data["hp"], // AtkSpeed: data["atkspeed"], // Exp: data["exp"], // MoveSpeed: data["movespeed"], // AtkRange: data["atkrange"], // AtkCoolDown: data["atkcooldown"], // VisualRange: data["visualrange"], // SkillDmg: data["Skilldmg"], // SkillEffect: data["skilleffect"], this.dataConfig = data; this.enemyType = GameDefine.getEnemyType(data?.Group) || this.enemyType; this.attackType = GameDefine.getAttackType(this.enemyType) || this.attackType; this.dmg = data?.Atk || this.dmg; this.moveSpeed = data?.MoveSpeed || this.moveSpeed; this.range = data?.AtkRange || this.range; this.hp = data?.Hp || this.hp; this.atkCooldown = data?.AtkCoolDown || this.atkCooldown; this.visualRange = data?.VisualRange || this.visualRange; this.txtName.string = data?.Name_Id + "|" + this.dmg.toString(); this.updateSensorRange(); UmLog.log(JSON.stringify(data)); } updateSensorRange() { this.sensor.collider.getComponent(CircleCollider2D).radius = GameDefine.SQUARE_UNIT * this.visualRange; } protected onLoad(): void { this.setEnableRigibody(false); this.TWEEN_TAG = UmUtil.getRandomInt(100000, Number.MAX_SAFE_INTEGER); } start(): void { this.setEnableRigibody(true); this.registerColliderContact(); this.registerSensor(); // this.loadDataAndDisplay(); this.isShootEnable = true; this.currentColor = new Color(this.theme.color); } setEnableRigibody(isEnable: boolean) { if (this.rigibodyComponent) this.rigibodyComponent.enabled = isEnable; } protected registerColliderContact() { this.colliderObject.registerBeginContact(this.onBeginContact.bind(this), true); this.colliderObject.registerEndContact(null, true); } protected offColliderContact() { this.colliderObject.offContact(); } protected registerSensor() { this.sensor.registerBeginContact(this.onSensorBegin.bind(this), false); this.sensor.registerEndContact(this.onSensorEnd.bind(this), false); } protected offSensor() { this.sensor.offContact(); } loadDataAndDisplay() { LayoutManager.instance.GameUI.getBossHPBar().setMaxHPBar(100); } onBeginContact(a: Collider2D, b: Collider2D) { var bGroup = b.group; // UmLog.log("BOSS | Contact Begin = " + GameDefine.getPhysicGroupName(a.group), " vs ", GameDefine.getPhysicGroupName(bGroup)); if (bGroup == Number(EPHYSIC_GROUP.ENEMY)) return; if (bGroup == Number(EPHYSIC_GROUP.BULLET_HERO)) { this.onBulletContact(b.node); return; } if (bGroup == Number(EPHYSIC_GROUP.ACTIVE_SKILL)) { this.onHeroActiveSkillContact(b.node); return; } } onSensorBegin(a: Collider2D, b: Collider2D) { var bGroup = b.group; // UmLog.log("BOSS |onSensor Begin = " + GameDefine.getPhysicGroupName(a.group), " vs ", GameDefine.getPhysicGroupName(b.group)); if (bGroup != EPHYSIC_GROUP.HERO) return; this.heroTarget = b.node; } onSensorEnd(a: Collider2D, b: Collider2D) { var bGroup = b.group; // UmLog.log("BOSS | onSensor End = " + GameDefine.getPhysicGroupName(a.group), " vs ", GameDefine.getPhysicGroupName(b.group)); GameDefine.getPhysicGroupName(bGroup); if (bGroup != EPHYSIC_GROUP.HERO) return; this.heroTarget = null; } public destroyNode() { if (this.isDestroying) return; this.isDestroying = true; //must destroy on thread this.scheduleOnce(() => { this.setEnableRigibody(false); this.node?.destroy(); }, 0); } onBulletContact(bullet: Node) { var bulletComp = bullet.parent.getComponent(BulletBase); if (!bulletComp) return; var damage = bulletComp?.damage | 0; this.effectColor = bulletComp.getColor(); this.hitDamage(damage); bulletComp?.destroyNode(); } onHeroActiveSkillContact(skill: Node) { UmLog.log("onHeroActiveSkillContact => ", skill.name); var skillComp = skill.getComponent(ActiveSkillBase); if (!skillComp) return; if (skillComp.skillType != Number(EACTIVE_SKILL_TYPE.SKILL_2)) return; var damage = skillComp?.dmg | 0; this.effectColor = skillComp.getColor(); this.hitDamage(damage); } hitDamage(damage: number) { var hpBar = LayoutManager.instance.GameUI.getBossHPBar(); hpBar.decreaseHP(damage); if (hpBar.currentHP <= 0) { this.checkWin(); this?.destroyNode(); } this.runHitEffect(); } checkWin() { //override at extent } runHitEffect() { this.theme.color = this.effectColor; UmUtil.stopAllTweenTag(this.TWEEN_TAG); UmUtil.delay(this.node, 0.2, () => { this.theme.color = this.currentColor; }, this.TWEEN_TAG); } // shooting => { "AtkRange": 5, "AtkCoolDown": 1, "AtkSpeed": 30, "Damage": 10, "AoERange": 0, "AoEDmg": 0 } get ShootingDataConfig(): ShootingDataInfo { var shootingData: ShootingDataInfo = { AtkRange: this.dataConfig.AtkRange, AtkCoolDown: this.dataConfig.AtkCoolDown, AtkSpeed: this.dataConfig.AtkSpeed, Damage: this.dataConfig.Atk, AoERange: this.dataConfig.AoERange, AoEDmg: this.dataConfig.AoEDmg, }; return shootingData; } protected update(dt: number): void { if (!GameGlobalData.Instance.isStatePlay()) return; if (!this.isShootEnable) return; var targetShoot = this.findShootTargetPoint(); if (!targetShoot) return; this.shooting.shooting(this.node, targetShoot, this.ShootingDataConfig); } findShootTargetNode(): Node { return this.heroTarget; } findShootTargetPoint(): Vec3 { var point = this.node.worldPosition; point = UmUtil.plusTwoVector3(point, new Vec3(0, -10, 0)); return point; } }