Files
pixelheros/assets/script/game/hero/HeroAttrsComp.ts
walkpan 50936dce1d refactor(技能/英雄): 重构移动结束检测和冰冻状态逻辑
- 移除移动结束类型中的距离结束检测,仅保留碰撞结束
- 删除 HeroViewComp 中未使用的 mp_add 和 playIntervalEffect 方法
- 简化 HeroAttrsComp 中冰冻状态判断逻辑,移除 in_frost 字段
- 在 HeroBuffSystem 中添加定时器自动减少冰冻剩余时间
2026-03-19 18:49:19 +08:00

323 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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, HType } from "../common/config/heroSet";
import { mLogger } from "../common/Logger";
import { Timer } from "db://oops-framework/core/common/timer/Timer";
@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; // 最大护盾值
// ==================== 攻击属性 (补充) ====================
a_cd: number = 0; // 攻击计时
s_cd: number = 0; // 技能计时
a_cd_max: number = 0; // 攻击CD
s_cd_max: number = 0; // 技能CD
// ==================== 暴击与命中属性 ====================
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;// 无敌时间
in_frost=false
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;
atk_id:number=0; //普通攻击技能id
skill_id:number=0; //技能攻击技能id
can_atk=false
can_skill=false
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,isValue:boolean){
const oldHp = this.hp;
let addValue = value;
if(!isValue){
addValue = value * this.hp_max / 100;
}
// ✅ 数据层只负责数据修改,不调用视图层
// let heroView = this.ent.get(HeroViewComp);
// if(heroView && addValue > 0){
// heroView.health(addValue);
// }
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)}`);
}
}
add_shield(value:number,isValue:boolean){
const oldShield = this.shield;
let addValue = value;
if(!isValue){
addValue = value * this.hp_max / 100;
}
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.toFixed(1)}, ${oldShield.toFixed(1)} -> ${this.shield.toFixed(1)}`);
}
}
// ==================== BUFF 管理 ====================
/**
* 添加 buff 效果
* @param buffConf buff 配置
*/
addBuff(buffConf: BuffConf) {
this.applyAttrChange(buffConf.buff, buffConf.value);
if (this.debugMode) {
mLogger.log(this.debugMode, 'HeroAttrs', `添加属性: ${buffConf.name}, 属性:${buffConf.buff}, 值:${buffConf.value}`);
}
}
/**
* 把配置值统一转换为“可直接写入容器和结算”的数值
* - RATIO 会在写入前转换为 VALUE
* - BOOLEAN 保持原类型
*/
/**
* 通用属性修改应用
* @param attr 属性名
* @param value 变化值
*/
private applyAttrChange(attr: Attrs, value: number,) {
const mappedAttr = attr === Attrs.hp ? Attrs.hp_max : (attr === Attrs.shield ? Attrs.shield_max : attr);
if (mappedAttr !== Attrs.ap && mappedAttr !== Attrs.hp_max && mappedAttr !== Attrs.shield_max) return;
if (mappedAttr === Attrs.ap) {
this.ap = Math.max(0, this.ap + value);
return;
}
if (mappedAttr === Attrs.hp_max) {
this.hp_max = Math.max(1, this.hp_max + value);
if (this.hp > this.hp_max) this.hp = this.hp_max;
this.dirty_hp = true;
return;
}
this.shield_max = Math.max(0, this.shield_max + value);
this.shield = Math.max(0, Math.min(this.shield + value, this.shield_max));
this.dirty_shield = true;
}
//======更新cd========//
updateCD(dt: number){
if(this.atk_id !=0&&!this.can_atk){
this.a_cd+=dt
if(this.a_cd >= this.a_cd_max) this.can_atk = true
}
if(this.skill_id !=0&&!this.can_skill){
this.s_cd+=dt
if(this.s_cd >= this.s_cd_max) this.can_skill = true
}
}
isFrost(): boolean {
return this.frost_end_time > 0
}
triggerAtkCD() {
this.a_cd = 0;
this.can_atk = false;
}
triggerSkillCD() {
this.s_cd = 0;
this.can_skill = false;
}
// ==================== 技能距离缓存管理 ====================
/**
* 更新技能距离缓存
* 在技能初始化、新增技能、MP变化时调用
* @param skillsComp 技能组件
*/
public updateSkillDistanceCache(skill_id:number): void {
void skill_id;
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.a_cd = 0;
this.s_cd = 0;
this.a_cd_max = 0;
this.s_cd_max = 0;
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.atk_id = 0;
this.skill_id = 0;
this.can_atk=false
this.can_skill=false
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.2)
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.2;
if(attrsComp.frost_end_time <= 0){
attrsComp.frost_end_time = 0;
}
}
}
void e;
}
}