import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { Attrs } from "../common/config/HeroAttrs"; import { BuffConf } from "../common/config/SkillSet"; import { HeroDisVal, HSkillInfo, HType } from "../common/config/heroSet"; import { mLogger } from "../common/Logger"; import { Timer } from "db://oops-framework/core/common/timer/Timer"; import { FightSet } from "../common/config/GameSet"; @ecs.register('HeroAttrs') export class HeroAttrsComp extends ecs.Comp { public debugMode: boolean = false; Ebus:any=null! // ==================== 角色基础信息 ==================== hero_uuid: number = 1001; hero_name: string = "hero"; lv: number = 1; type: number = 0; // 0近战 1远程 2辅助 fac: number = 0; // 0:hero 1:monster // ==================== 基础属性(有初始值) ==================== ap: number = 0; // 基础攻击 hp: number = 100; // 基础血量 hp_max: number = 100; // 最大血量 speed: number = 100; // 基础移动速度 dis: number = 100; // 基础距离 shield: number = 0; // 当前护盾 shield_max: number = 0; // 最大护盾值 // ==================== 攻击属性 (补充) ==================== skills: Record = {}; // ==================== 特殊属性 ==================== critical: number = 0; // 暴击率 freeze_chance: number = 0; // 冰冻概率 back_chance: number = 0; // 击退概率 puncture: number = 0; // 穿刺次数 wfuny: number = 0; // 风怒 revive_count: number = 0; // 复活次数 revive_time: number = 0; // 复活时间 invincible_time: number = 0;// 无敌时间 frost_end_time: number = 0; boom: boolean = false; // 自爆怪 // ==================== 脏标签标记 ==================== dirty_hp: boolean = false; // 血量变更标记 dirty_shield: boolean = false; // 护盾变更标记 // ==================== 技能距离缓存 ==================== maxSkillDistance: number = 0; // 最远技能攻击距离(缓存,受MP影响) minSkillDistance: number = 0; // 最近技能攻击距离(缓存,不受MP影响,用于停止位置判断) // ==================== 标记状态 ==================== is_dead: boolean = false; is_count_dead: boolean = false; is_atking: boolean = false; // 是否正在攻击 is_stop: boolean = false; // 是否正在停止 is_boss: boolean = false; is_big_boss: boolean = false; is_master: boolean = false; is_friend: boolean = false; is_kalami: boolean = false; is_reviving: boolean = false; // 是否正在复活中 // ==================== 计数统计 ==================== atk_count: number = 0; // 攻击次数 atked_count: number = 0; // 被攻击次数 killed_count:number=0; combat_target_eid: number = -1; enemy_in_cast_range: boolean = false; start(){ } // ==================== BUFF 系统初始化 ==================== /** * 初始化角色的 buff debuff * 从 HeroInfo 读取初始配置,建立属性系统 */ initAttrs() { this.frost_end_time = 0; } /*******************基础属性管理********************/ add_hp(value:number){ const oldHp = this.hp; let addValue = value; this.hp += addValue; this.hp = Math.max(0, Math.min(this.hp, this.hp_max)); this.dirty_hp = true; // ✅ 仅标记需要更新 if (this.debugMode) { mLogger.log(this.debugMode, 'HeroAttrs', ` HP变更: ${this.hero_name}, 变化=${addValue.toFixed(1)}, ${oldHp.toFixed(1)} -> ${this.hp.toFixed(1)}`); } return addValue; } add_shield(value:number){ const oldShield = this.shield; const addValue = Math.max(0, Math.floor(value)); if (addValue <= 0) return; this.shield += addValue; this.shield_max += addValue; if (this.shield < 0) this.shield = 0; if (this.shield_max < 0) this.shield_max = 0; this.dirty_shield = true; // 标记护盾需要更新 if (this.debugMode) { mLogger.log(this.debugMode, 'HeroAttrs', ` 护盾次数变更: ${this.hero_name}, 变化=${addValue}, ${Math.floor(oldShield)} -> ${Math.floor(this.shield)}`); } } add_hp_max(value:number){ this.hp_max+=value this.hp+=value this.dirty_hp = true; // ✅ 仅标记需要更新 return value } add_ap(value:number){ this.ap +=value return value } toFrost(time: number=1) { const frostTime = FightSet.FROST_TIME * time; this.frost_end_time = Math.max(this.frost_end_time, frostTime); } updateCD(dt: number){ for (const key in this.skills) { const skill = this.skills[key]; if (!skill) continue; if (skill.cd <= 0) { skill.ccd = 0; continue; } if (skill.ccd >= skill.cd) { skill.ccd = skill.cd; continue; } skill.ccd = Math.min(skill.cd, skill.ccd + dt); } } isFrost(): boolean { return this.frost_end_time > 0 } getSkillLevel(skillId: number): number { if (!skillId) return 0; return this.skills[skillId]?.lv ?? 0; } getSkillIds(): number[] { return Object.values(this.skills).map(skill => skill.uuid); } isSkillReady(skillId: number): boolean { if (!skillId) return false; const skill = this.skills[skillId]; if (!skill) return false; if (skill.cd <= 0) return true; return skill.ccd >= skill.cd; } triggerSkillCD(skillId: number) { if (!skillId) return; const skill = this.skills[skillId]; if (!skill) return; skill.ccd = 0; } getSkillCdProgress(skillId: number): number { if (!skillId) return 1; const skill = this.skills[skillId]; if (!skill || skill.cd <= 0) return 1; return Math.max(0, Math.min(1, skill.ccd / skill.cd)); } getDisplaySkillCdProgress(): number { const skillIds = this.getSkillIds(); const displaySkillId = skillIds[1] ?? skillIds[0] ?? 0; return this.getSkillCdProgress(displaySkillId); } // ==================== 技能距离缓存管理 ==================== /** * 更新技能距离缓存 * 在技能初始化、新增技能、MP变化时调用 * @param skillsComp 技能组件 */ public updateSkillDistanceCache(): void { const rangeType = this.type as HType.Melee | HType.Mid | HType.Long; const maxRange = HeroDisVal[rangeType]; let minRange = 0; if (rangeType === HType.Mid) { minRange = HeroDisVal[HType.Melee]; } else if (rangeType === HType.Long) { minRange = HeroDisVal[HType.Mid]; } this.maxSkillDistance = maxRange; this.minSkillDistance = minRange; } /** * 获取缓存的最远技能攻击距离 * @returns 最远攻击距离 */ public getCachedMaxSkillDistance(): number { return this.maxSkillDistance; } /** * 获取缓存的最近技能攻击距离 * @returns 最近攻击距离 */ public getCachedMinSkillDistance(): number { return this.minSkillDistance; } reset() { // 重置为初始状态 this.hero_uuid = 1001; this.hero_name = "hero"; this.lv = 1; this.type = 0; this.fac = 0; this.ap = 0; this.hp = 100; this.hp_max = 100; this.speed = 100; this.dis = 100; this.shield = 0; this.shield_max = 0; // 重置新增属性 this.skills = {}; this.critical = 0; this.freeze_chance = 0; this.back_chance = 0; this.revive_count = 0; this.revive_time = 0; this.invincible_time = 0; this.puncture = 0; this.wfuny = 0; this.boom = false; this.frost_end_time = 0; // 重置技能距离缓存 this.maxSkillDistance = 0; this.minSkillDistance = 0; this.is_dead = false; this.is_count_dead = false; this.is_atking = false; this.is_stop = false; this.is_boss = false; this.is_big_boss = false; this.is_friend = false; this.is_kalami = false; this.is_reviving = false; this.atk_count = 0; this.atked_count = 0; this.killed_count =0; this.combat_target_eid = -1; this.enemy_in_cast_range = false; // 重置脏标签 this.dirty_hp = false; this.dirty_shield = false; } } @ecs.register('HeroBuffSystem') export class HeroBuffSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate { private timer =new Timer(0.1) filter(): ecs.IMatcher { return ecs.allOf(HeroAttrsComp); } update(e: ecs.Entity): void { if(this.timer.update(this.dt)){ const attrsComp = e.get(HeroAttrsComp); if(attrsComp.frost_end_time > 0){ attrsComp.frost_end_time -= 0.1; if(attrsComp.frost_end_time <= 0){ attrsComp.frost_end_time = 0; } } } void e; } }