725 lines
22 KiB
TypeScript
725 lines
22 KiB
TypeScript
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||
import { Attrs, AttrsType, BType, NeAttrs } from "../common/config/HeroAttrs";
|
||
import { BuffConf, SkillSet } from "../common/config/SkillSet";
|
||
import { HeroInfo, AttrSet, HeroUpSet } from "../common/config/heroSet";
|
||
import { MonModelComp } from "./MonModelComp";
|
||
import { FacSet } from "../common/config/BoxSet";
|
||
import { FightSet } from "../common/config/Mission";
|
||
|
||
|
||
@ecs.register('HeroModel')
|
||
export class HeroModelComp extends ecs.Comp {
|
||
|
||
// ==================== 角色基础信息 ====================
|
||
hero_uuid: number = 1001;
|
||
hero_name: string = "hero";
|
||
lv: number = 1;
|
||
type: number = 0; // 0近战 1远程 2辅助
|
||
fac: number = 0; // 0:hero 1:monster
|
||
|
||
// ==================== 基础属性(有初始值) ====================
|
||
base_ap: number = 0; // 基础攻击
|
||
base_map: number = 0; // 基础魔法攻击
|
||
base_def: number = 5; // 基础防御
|
||
base_hp: number = 100; // 基础血量
|
||
base_mp: number = 100; // 基础魔法值
|
||
base_speed: number = 100; // 基础移动速度
|
||
base_dis: number = 100; // 基础距离
|
||
|
||
// ==================== 动态属性值 ====================
|
||
hp: number = 100; // 当前血量
|
||
mp: number = 100; // 当前魔法值
|
||
shield: number = 0; // 当前护盾
|
||
Attrs: any = []; // 最终属性数组(经过Buff计算后)
|
||
NeAttrs: any = []; // 负面状态数组
|
||
|
||
// ==================== Buff/Debuff 系统 ====================
|
||
/** 持久型buff数组 - 不会自动过期 */
|
||
BUFFS: Record<number, Array<{value: number, BType: BType}>> = {};
|
||
|
||
/** 临时型buff数组 - 按时间自动过期 */
|
||
BUFFS_TEMP: Record<number, Array<{value: number, BType: BType, remainTime: number}>> = {};
|
||
|
||
// ==================== 标记状态 ====================
|
||
is_dead: boolean = false;
|
||
is_count_dead: boolean = false;
|
||
is_boss: boolean = false;
|
||
is_big_boss: boolean = false;
|
||
is_master: boolean = false;
|
||
is_friend: boolean = false;
|
||
is_kalami: boolean = false;
|
||
|
||
// ==================== 计数统计 ====================
|
||
atk_count: number = 0; // 攻击次数
|
||
atked_count: number = 0; // 被攻击次数
|
||
|
||
// ==================== 技能配置 ====================
|
||
skills: any = [];
|
||
|
||
// ==================== BUFF 系统初始化 ====================
|
||
/**
|
||
* 初始化角色的 buff debuff
|
||
* 从 HeroInfo 读取初始配置,建立属性系统
|
||
*/
|
||
initAttrs() {
|
||
// 清空现有 buff/debuff
|
||
this.BUFFS = {};
|
||
this.BUFFS_TEMP = {};
|
||
|
||
// 获取英雄配置
|
||
const heroInfo = HeroInfo[this.hero_uuid];
|
||
if (!heroInfo) return;
|
||
|
||
// 1. 重置为基础值
|
||
this.Attrs[Attrs.HP_MAX] = this.base_hp;
|
||
this.Attrs[Attrs.MP_MAX] = this.base_mp;
|
||
this.Attrs[Attrs.DEF] = this.base_def;
|
||
this.Attrs[Attrs.AP] = this.base_ap;
|
||
this.Attrs[Attrs.MAP] = this.base_map;
|
||
this.Attrs[Attrs.SPEED] = this.base_speed;
|
||
this.Attrs[Attrs.DIS] = this.base_dis;
|
||
|
||
// 2. 初始化其他属性(无初始值的)
|
||
for (const attrKey in this.Attrs) {
|
||
const attrIndex = parseInt(attrKey);
|
||
if (
|
||
attrIndex !== Attrs.HP_MAX &&
|
||
attrIndex !== Attrs.MP_MAX &&
|
||
attrIndex !== Attrs.DEF &&
|
||
attrIndex !== Attrs.AP &&
|
||
attrIndex !== Attrs.MAP &&
|
||
attrIndex !== Attrs.SPEED &&
|
||
attrIndex !== Attrs.DIS
|
||
) {
|
||
this.Attrs[attrIndex] = 0;
|
||
}
|
||
}
|
||
|
||
// 加载初始 buff
|
||
if (heroInfo.buff && heroInfo.buff.length > 0) {
|
||
for (const buffConf of heroInfo.buff) {
|
||
this.addBuff(buffConf);
|
||
}
|
||
}
|
||
}
|
||
|
||
// ==================== BUFF 管理 ====================
|
||
/**
|
||
* 添加 buff 效果(支持多次叠加)
|
||
* @param buffConf buff 配置 (来自 SkillSet.BuffConf heroSet.buff)
|
||
*/
|
||
addBuff(buffConf: BuffConf) {
|
||
const isPermanent = buffConf.time === 0;
|
||
const attrIndex = buffConf.buff;
|
||
|
||
if (isPermanent) {
|
||
// 添加持久buff到BUFFS - 直接追加到数组
|
||
if (!this.BUFFS[attrIndex]) {
|
||
this.BUFFS[attrIndex] = [];
|
||
}
|
||
this.BUFFS[attrIndex].push({ value: buffConf.value, BType: buffConf.BType });
|
||
} else {
|
||
// 添加临时buff到BUFFS_TEMP - 直接追加到数组
|
||
if (!this.BUFFS_TEMP[attrIndex]) {
|
||
this.BUFFS_TEMP[attrIndex] = [];
|
||
}
|
||
this.BUFFS_TEMP[attrIndex].push({
|
||
value: buffConf.value,
|
||
BType: buffConf.BType,
|
||
remainTime: buffConf.time
|
||
});
|
||
}
|
||
|
||
// 重新计算受影响的属性
|
||
this.recalculateSingleAttr(attrIndex);
|
||
}
|
||
|
||
// ==================== 属性计算系统 ====================
|
||
/**
|
||
* 重新计算单个属性
|
||
* @param attrIndex 属性索引
|
||
*/
|
||
recalculateSingleAttr(attrIndex: number) {
|
||
// 1. 获取基础值
|
||
const baseValues: Record<number, number> = {
|
||
[Attrs.HP_MAX]: this.base_hp,
|
||
[Attrs.MP_MAX]: this.base_mp,
|
||
[Attrs.DEF]: this.base_def,
|
||
[Attrs.AP]: this.base_ap,
|
||
[Attrs.MAP]: this.base_map,
|
||
[Attrs.SPEED]: this.base_speed,
|
||
[Attrs.SHIELD_MAX]: 0
|
||
};
|
||
|
||
const baseVal = baseValues[attrIndex] !== undefined ? baseValues[attrIndex] : 0;
|
||
|
||
// 2. 收集所有数值型 buff/debuff
|
||
let totalValue = baseVal;
|
||
|
||
// 遍历持久buff数组
|
||
if (this.BUFFS[attrIndex] && this.BUFFS[attrIndex].length > 0) {
|
||
for (const buff of this.BUFFS[attrIndex]) {
|
||
if (buff.BType === BType.VALUE) {
|
||
totalValue += buff.value;
|
||
}
|
||
}
|
||
}
|
||
// 遍历临时buff数组
|
||
if (this.BUFFS_TEMP[attrIndex] && this.BUFFS_TEMP[attrIndex].length > 0) {
|
||
for (const buff of this.BUFFS_TEMP[attrIndex]) {
|
||
if (buff.BType === BType.VALUE) {
|
||
totalValue += buff.value;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 3. 收集所有百分比型 buff/debuff
|
||
let totalRatio = 0;
|
||
|
||
// 遍历持久buff数组
|
||
if (this.BUFFS[attrIndex] && this.BUFFS[attrIndex].length > 0) {
|
||
for (const buff of this.BUFFS[attrIndex]) {
|
||
if (buff.BType === BType.RATIO) {
|
||
totalRatio += buff.value;
|
||
}
|
||
}
|
||
}
|
||
// 遍历临时buff数组
|
||
if (this.BUFFS_TEMP[attrIndex] && this.BUFFS_TEMP[attrIndex].length > 0) {
|
||
for (const buff of this.BUFFS_TEMP[attrIndex]) {
|
||
if (buff.BType === BType.RATIO) {
|
||
totalRatio += buff.value;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 4. 根据属性类型计算最终值
|
||
const attrType = AttrsType[attrIndex];
|
||
const isRatioAttr = attrType === BType.RATIO;
|
||
|
||
if (isRatioAttr) {
|
||
// 百分比型属性:直接加减
|
||
this.Attrs[attrIndex] = totalValue + totalRatio;
|
||
} else {
|
||
// 数值型属性:(基础值+数值) × (1 + 百分比/100)
|
||
this.Attrs[attrIndex] = Math.floor(totalValue * (1 + totalRatio / 100));
|
||
}
|
||
|
||
// 5. 确保属性值合理
|
||
this.clampSingleAttr(attrIndex);
|
||
}
|
||
|
||
/**
|
||
* 确保单个属性值合理
|
||
*/
|
||
private clampSingleAttr(attrIndex: number) {
|
||
switch(attrIndex) {
|
||
case Attrs.HP_MAX:
|
||
case Attrs.MP_MAX:
|
||
this.Attrs[attrIndex] = Math.max(1, this.Attrs[attrIndex]);
|
||
break;
|
||
case Attrs.DEF:
|
||
case Attrs.AP:
|
||
case Attrs.MAP:
|
||
this.Attrs[attrIndex] = Math.max(1, this.Attrs[attrIndex]);
|
||
break;
|
||
case Attrs.CRITICAL:
|
||
case Attrs.DODGE:
|
||
case Attrs.HIT:
|
||
this.Attrs[attrIndex] = Math.max(0, Math.min(AttrSet.ATTR_MAX, this.Attrs[attrIndex]));
|
||
break;
|
||
}
|
||
}
|
||
|
||
// ==================== 临时 BUFF/DEBUFF 更新 ====================
|
||
/**
|
||
* 更新临时 buff/debuff 的剩余时间
|
||
* @param dt 时间增量
|
||
*/
|
||
updateTemporaryBuffsDebuffs(dt: number) {
|
||
const affectedAttrs = new Set<number>();
|
||
|
||
// 更新临时型buff
|
||
for (const attrIndex in this.BUFFS_TEMP) {
|
||
const buffs = this.BUFFS_TEMP[attrIndex];
|
||
buffs.forEach(buff => {
|
||
buff.remainTime -= dt;
|
||
if (buff.remainTime <= 0) {
|
||
const index = buffs.indexOf(buff);
|
||
if (index > -1) {
|
||
buffs.splice(index, 1);
|
||
}
|
||
}
|
||
});
|
||
if (buffs.length === 0) {
|
||
delete this.BUFFS_TEMP[attrIndex];
|
||
affectedAttrs.add(parseInt(attrIndex));
|
||
}
|
||
}
|
||
|
||
// 负面状态更新
|
||
for (const key in this.NeAttrs) {
|
||
const debuff = this.NeAttrs[key];
|
||
debuff.remainTime -= dt;
|
||
if (debuff.remainTime <= 0) {
|
||
debuff.remainTime = 0;
|
||
}
|
||
}
|
||
|
||
// 只重新计算受影响的属性
|
||
affectedAttrs.forEach(attrIndex => {
|
||
this.recalculateSingleAttr(attrIndex);
|
||
});
|
||
}
|
||
|
||
// ==================== BUFF 辅助方法 ====================
|
||
/**
|
||
* 清空buff
|
||
* @param attrIndex 属性索引,如果为空则清理所有buff
|
||
* @param isBuff true时清理value>0的增益buff,false时清理value<0的减益buff
|
||
*/
|
||
clearBuffs(attrIndex?: number, isBuff: boolean = true): void {
|
||
if (attrIndex === undefined) {
|
||
for (const attrIndex in this.BUFFS_TEMP) {
|
||
this.clearBuffsForAttr(parseInt(attrIndex), isBuff);
|
||
}
|
||
} else {
|
||
this.clearBuffsForAttr(attrIndex, isBuff);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 清理指定属性的buff
|
||
* @param attrIndex 属性索引
|
||
* @param isBuff true清理增益buff,false清理减益buff
|
||
*/
|
||
private clearBuffsForAttr(attrIndex: number, isBuff: boolean): void {
|
||
const buffContainer = this.BUFFS_TEMP;
|
||
|
||
if (!buffContainer[attrIndex]) return;
|
||
|
||
buffContainer[attrIndex] = buffContainer[attrIndex].filter(buff => {
|
||
const shouldClear = isBuff ? buff.value > 0 : buff.value < 0;
|
||
return !shouldClear;
|
||
});
|
||
|
||
if (buffContainer[attrIndex].length === 0) {
|
||
delete buffContainer[attrIndex];
|
||
}
|
||
|
||
this.recalculateSingleAttr(attrIndex);
|
||
}
|
||
|
||
// ==================== NeAttrs(负面状态)管理 ====================
|
||
/**
|
||
* 清理单个NeAttr(负面状态)
|
||
*/
|
||
clearNeAttr(neAttrIndex: number): void {
|
||
if (this.NeAttrs[neAttrIndex]) {
|
||
this.NeAttrs[neAttrIndex].value = 0;
|
||
this.NeAttrs[neAttrIndex].time = 0;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 清理所有NeAttrs(负面状态)
|
||
*/
|
||
clearAllNeAttrs(): void {
|
||
for (const key in this.NeAttrs) {
|
||
this.NeAttrs[key].value = 0;
|
||
this.NeAttrs[key].time = 0;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检查是否处于眩晕状态
|
||
*/
|
||
public isStun(): boolean {
|
||
return this.NeAttrs[NeAttrs.IN_STUN]?.time > 0;
|
||
}
|
||
|
||
/**
|
||
* 检查是否处于冰冻状态
|
||
*/
|
||
public isFrost(): boolean {
|
||
return this.NeAttrs[NeAttrs.IN_FROST]?.time > 0;
|
||
}
|
||
|
||
reset() {
|
||
// 重置为初始状态
|
||
this.hero_uuid = 1001;
|
||
this.hero_name = "hero";
|
||
this.lv = 1;
|
||
this.type = 0;
|
||
this.fac = 0;
|
||
this.base_ap = 0;
|
||
this.base_map = 0;
|
||
this.base_def = 5;
|
||
this.base_hp = 100;
|
||
this.base_mp = 100;
|
||
this.base_speed = 100;
|
||
this.base_dis = 100;
|
||
this.hp = 100;
|
||
this.mp = 100;
|
||
this.shield = 0;
|
||
this.Attrs = [];
|
||
this.NeAttrs = [];
|
||
this.BUFFS = {};
|
||
this.BUFFS_TEMP = {};
|
||
this.is_dead = false;
|
||
this.is_count_dead = false;
|
||
this.is_boss = false;
|
||
this.is_big_boss = false;
|
||
this.is_master = false;
|
||
this.is_friend = false;
|
||
this.is_kalami = false;
|
||
this.atk_count = 0;
|
||
this.atked_count = 0;
|
||
this.skills = [];
|
||
|
||
}
|
||
}
|
||
|
||
/**
|
||
* ==================== 英雄属性更新系统 ====================
|
||
*
|
||
* 按照 ECS 设计理念:
|
||
* - Component(HeroModelComp):存储数据
|
||
* - System(HeroAttrSystem):处理业务逻辑
|
||
*
|
||
* 系统职责:
|
||
* 1. 每帧更新临时 Buff(时间递减,过期移除)
|
||
* 2. 每帧更新 HP/MP 自然回复
|
||
* 3. 限制属性值在合理范围内
|
||
*
|
||
* 使用方式:
|
||
* 在 RootSystem 中注册此系统,它会自动每帧更新所有拥有 HeroModelComp 的实体
|
||
*/
|
||
export class HeroAttrSystem extends ecs.ComblockSystem
|
||
implements ecs.ISystemUpdate, ecs.IEntityEnterSystem, ecs.ISystemFirstUpdate {
|
||
|
||
// ==================== 调试统计(可选)====================
|
||
private entityCount: number = 0; // 本帧处理的实体数
|
||
private frameCount: number = 0; // 总帧数
|
||
private debugMode: boolean = false; // 是否启用调试模式
|
||
|
||
/**
|
||
* 过滤器:只处理拥有 HeroModelComp 的实体
|
||
*/
|
||
filter(): ecs.IMatcher {
|
||
return ecs.allOf(HeroModelComp);
|
||
}
|
||
|
||
/**
|
||
* 实体首次进入系统时调用(每个实体只调用一次)
|
||
*/
|
||
entityEnter(e: ecs.Entity): void {
|
||
const model = e.get(HeroModelComp);
|
||
if (!model) return;
|
||
|
||
console.log(`[HeroAttrSystem] 英雄进入系统: ${model.hero_name} (uuid: ${model.hero_uuid})`);
|
||
}
|
||
|
||
/**
|
||
* 系统首次更新前调用(整个系统只调用一次)
|
||
*/
|
||
firstUpdate(): void {
|
||
console.log("[HeroAttrSystem] 系统首次更新");
|
||
}
|
||
|
||
/**
|
||
* 每帧更新(为每个英雄调用一次)
|
||
*
|
||
* ⭐ 关键理解:
|
||
* - 如果有 3 个英雄,这个方法每帧会被调用 3 次
|
||
* - 每次调用处理不同的实体 e
|
||
* - 这是正确的设计,不是 bug
|
||
*/
|
||
update(e: ecs.Entity): void {
|
||
const model = e.get(HeroModelComp);
|
||
if (!model || model.is_dead) return;
|
||
|
||
// 统计:记录本帧处理的实体数
|
||
this.entityCount++;
|
||
|
||
// 调试日志(可选,调试时启用)
|
||
if (this.debugMode) {
|
||
console.log(` [${this.entityCount}] 更新英雄: ${model.hero_name}, HP: ${model.hp.toFixed(2)}`);
|
||
}
|
||
|
||
// 1. 更新临时 Buff/Debuff(时间递减,过期自动移除)
|
||
model.updateTemporaryBuffsDebuffs(this.dt);
|
||
|
||
// 2. HP/MP 自然回复(业务规则)
|
||
model.mp += HeroUpSet.MP * this.dt;
|
||
model.hp += HeroUpSet.HP * this.dt;
|
||
|
||
// 3. 限制属性值在合理范围内
|
||
if (model.mp > model.Attrs[Attrs.MP_MAX]) {
|
||
model.mp = model.Attrs[Attrs.MP_MAX];
|
||
}
|
||
if (model.hp > model.Attrs[Attrs.HP_MAX]) {
|
||
model.hp = model.Attrs[Attrs.HP_MAX];
|
||
}
|
||
|
||
// 每 60 帧输出一次统计
|
||
this.frameCount++;
|
||
if (this.frameCount % 60 === 0 && this.entityCount === 1) {
|
||
console.log(`[HeroAttrSystem] 第 ${this.frameCount} 帧,处理 ${this.entityCount} 个英雄`);
|
||
}
|
||
|
||
// 注意:显示更新由 HeroViewComp 负责,这里只处理数据
|
||
}
|
||
|
||
/**
|
||
* 启用调试模式(调试时使用)
|
||
*/
|
||
enableDebug() {
|
||
this.debugMode = true;
|
||
}
|
||
|
||
/**
|
||
* 禁用调试模式(正式运行)
|
||
*/
|
||
disableDebug() {
|
||
this.debugMode = false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* ==================== 英雄战斗系统 ====================
|
||
*
|
||
* 按照 ECS 设计理念:
|
||
* - Component(HeroModelComp):存储数据
|
||
* - System(HeroBattleSystem):处理战斗业务逻辑
|
||
*
|
||
* 系统职责:
|
||
* 1. 处理角色被攻击逻辑(伤害计算、暴击判定、闪避判定)
|
||
* 2. 处理护盾吸收逻辑
|
||
* 3. 处理角色死亡逻辑
|
||
* 4. 处理战斗状态管理
|
||
*
|
||
* 使用方式:
|
||
* 在 RootSystem 中注册此系统,它会自动处理所有拥有 HeroModelComp 的实体的战斗逻辑
|
||
*/
|
||
export class HeroBattleSystem extends ecs.ComblockSystem
|
||
implements ecs.ISystemUpdate, ecs.IEntityEnterSystem {
|
||
|
||
private debugMode: boolean = false; // 是否启用调试模式
|
||
|
||
/**
|
||
* 过滤器:只处理拥有 HeroModelComp 的实体
|
||
*/
|
||
filter(): ecs.IMatcher {
|
||
return ecs.allOf(HeroModelComp);
|
||
}
|
||
|
||
/**
|
||
* 实体首次进入系统时调用(每个实体只调用一次)
|
||
*/
|
||
entityEnter(e: ecs.Entity): void {
|
||
const model = e.get(HeroModelComp);
|
||
if (!model) return;
|
||
|
||
console.log(`[HeroBattleSystem] 英雄进入战斗系统: ${model.hero_name} (uuid: ${model.hero_uuid})`);
|
||
}
|
||
|
||
/**
|
||
* 处理角色被攻击
|
||
* @param target 被攻击的目标实体
|
||
* @param remainingDamage 基础伤害值
|
||
* @param attackerAttrs 攻击者的属性
|
||
* @param skillId 技能ID
|
||
* @returns 实际造成的伤害
|
||
*/
|
||
public doAttack(target: ecs.Entity, remainingDamage: number, attackerAttrs: any, skillId: number): number {
|
||
const targetModel = target.get(HeroModelComp);
|
||
if (!targetModel || targetModel.is_dead) return 0;
|
||
|
||
// 获取技能配置
|
||
const skillConf = SkillSet[skillId];
|
||
|
||
// 触发被攻击事件
|
||
this.onAttacked(target);
|
||
|
||
// 闪避判定
|
||
if (this.checkDodge(targetModel)) {
|
||
return 0;
|
||
}
|
||
|
||
// 暴击判定
|
||
const isCrit = this.checkCrit(attackerAttrs[Attrs.CRITICAL]);
|
||
let damage = remainingDamage;
|
||
|
||
if (isCrit) {
|
||
damage = Math.floor(damage * (1 + (FightSet.CRIT_DAMAGE + attackerAttrs[Attrs.CRITICAL_DMG]) / 100));
|
||
}
|
||
|
||
// 伤害计算(考虑易伤等debuff)
|
||
damage = this.calculateDamage(targetModel, damage);
|
||
|
||
// 护盾吸收
|
||
damage = this.absorbShield(targetModel, damage);
|
||
|
||
if (damage <= 0) return 0;
|
||
|
||
// 应用伤害
|
||
targetModel.hp -= damage;
|
||
targetModel.atked_count++;
|
||
|
||
// 检查死亡
|
||
if (targetModel.hp <= 0) {
|
||
this.doDead(target);
|
||
}
|
||
|
||
if (this.debugMode) {
|
||
console.log(`[HeroBattleSystem] ${targetModel.hero_name} 受到 ${damage} 点伤害 (暴击: ${isCrit})`);
|
||
}
|
||
|
||
return damage;
|
||
}
|
||
|
||
/**
|
||
* 处理角色死亡
|
||
*/
|
||
private doDead(entity: ecs.Entity): void {
|
||
const model = entity.get(HeroModelComp);
|
||
if (!model || model.is_dead) return;
|
||
|
||
model.is_dead = true;
|
||
|
||
// 触发死亡事件
|
||
this.onDeath(entity);
|
||
|
||
if (this.debugMode) {
|
||
console.log(`[HeroBattleSystem] ${model.hero_name} 死亡`);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 闪避判定
|
||
*/
|
||
private checkDodge(model: HeroModelComp): boolean {
|
||
if (model.Attrs[Attrs.DODGE] > 0) {
|
||
const random = Math.random() * 100;
|
||
if (random < model.Attrs[Attrs.DODGE]) {
|
||
if (this.debugMode) {
|
||
console.log(`[HeroBattleSystem] ${model.hero_name} 闪避了攻击`);
|
||
}
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 暴击判定
|
||
*/
|
||
private checkCrit(critRate: number): boolean {
|
||
if (critRate > 0) {
|
||
const random = Math.random() * 100;
|
||
return random < critRate;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 伤害计算(考虑易伤等debuff)
|
||
*/
|
||
private calculateDamage(model: HeroModelComp, baseDamage: number): number {
|
||
// 这里可以添加易伤等debuff的计算逻辑
|
||
// 例如:如果目标有易伤buff,增加受到的伤害
|
||
return baseDamage;
|
||
}
|
||
|
||
/**
|
||
* 护盾吸收伤害
|
||
*/
|
||
private absorbShield(model: HeroModelComp, damage: number): number {
|
||
if (model.shield <= 0) return damage;
|
||
|
||
if (model.shield >= damage) {
|
||
model.shield -= damage;
|
||
if (model.shield <= 0) {
|
||
model.shield = 0;
|
||
model.Attrs[Attrs.SHIELD_MAX] = 0;
|
||
}
|
||
return 0;
|
||
} else {
|
||
const remainingDamage = damage - model.shield;
|
||
model.shield = 0;
|
||
model.Attrs[Attrs.SHIELD_MAX] = 0;
|
||
return remainingDamage;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 被攻击时触发的事件
|
||
*/
|
||
private onAttacked(entity: ecs.Entity): void {
|
||
const model = entity.get(HeroModelComp);
|
||
if (!model || model.is_dead) return;
|
||
|
||
// 这里可以添加被攻击时的特殊处理逻辑
|
||
if (model.fac === FacSet.MON) return;
|
||
|
||
// 例如:触发某些天赋效果、反击逻辑等
|
||
}
|
||
|
||
/**
|
||
* 死亡时触发的事件
|
||
*/
|
||
private onDeath(entity: ecs.Entity): void {
|
||
const model = entity.get(HeroModelComp);
|
||
if (!model) return;
|
||
|
||
if (model.fac === FacSet.MON) {
|
||
// 怪物死亡处理
|
||
this.scheduleDrop(entity);
|
||
} else if (model.fac === FacSet.HERO) {
|
||
// 英雄死亡处理
|
||
this.scheduleHeroDeath(entity);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 延迟执行掉落逻辑
|
||
*/
|
||
private scheduleDrop(entity: ecs.Entity): void {
|
||
// 这里可以添加掉落逻辑
|
||
// 例如:延迟一段时间后生成掉落物品
|
||
}
|
||
|
||
/**
|
||
* 延迟执行英雄死亡逻辑
|
||
*/
|
||
private scheduleHeroDeath(entity: ecs.Entity): void {
|
||
// 这里可以添加英雄死亡的特殊处理
|
||
// 例如:触发游戏结束、复活机制等
|
||
}
|
||
|
||
/**
|
||
* 启用调试模式
|
||
*/
|
||
enableDebug() {
|
||
this.debugMode = true;
|
||
}
|
||
|
||
/**
|
||
* 禁用调试模式
|
||
*/
|
||
disableDebug() {
|
||
this.debugMode = false;
|
||
}
|
||
|
||
/**
|
||
* 系统更新(每帧调用)
|
||
* 可以在这里添加需要每帧处理的战斗逻辑
|
||
*/
|
||
update(e: ecs.Entity): void {
|
||
// 这里可以添加需要每帧处理的战斗逻辑
|
||
// 例如:持续伤害、战斗状态检查等
|
||
}
|
||
}
|
||
|