重构怪物属性系统,移除MonAttrsComp并替换为HeroAttrsComp。更新相关组件和系统以适应新属性结构,确保怪物逻辑与英雄逻辑一致。

This commit is contained in:
2025-10-30 10:45:16 +08:00
parent 2d358e450d
commit e3bdc4b238
6 changed files with 11 additions and 263 deletions

View File

@@ -4,7 +4,7 @@ import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ec
import { smc } from "../common/SingletonModuleComp"; import { smc } from "../common/SingletonModuleComp";
import { BoxSet, FacSet } from "../common/config/BoxSet"; import { BoxSet, FacSet } from "../common/config/BoxSet";
import { HeroInfo } from "../common/config/heroSet"; import { HeroInfo } from "../common/config/heroSet";
import { MonAttrsComp } from "./MonAttrsComp"; import { HeroAttrsComp } from "./HeroAttrsComp";
import { BattleMoveComp } from "../common/ecs/position/BattleMoveComp"; import { BattleMoveComp } from "../common/ecs/position/BattleMoveComp";
import { SkillConComp } from "./SkillConComp"; import { SkillConComp } from "./SkillConComp";
import { BuffConf, SkillSet } from "../common/config/SkillSet"; import { BuffConf, SkillSet } from "../common/config/SkillSet";
@@ -16,14 +16,14 @@ import { HeroViewComp } from "./HeroViewComp";
/** 角色实体 */ /** 角色实体 */
@ecs.register(`Monster`) @ecs.register(`Monster`)
export class Monster extends ecs.Entity { export class Monster extends ecs.Entity {
HeroModel!: MonAttrsComp; HeroModel!: HeroAttrsComp;
HeroView!: HeroViewComp; HeroView!: HeroViewComp;
BattleMove!: BattleMoveComp; BattleMove!: BattleMoveComp;
protected init() { protected init() {
this.addComponents<ecs.Comp>( this.addComponents<ecs.Comp>(
BattleMoveComp, BattleMoveComp,
MonAttrsComp, HeroAttrsComp,
TalComp, TalComp,
EBusComp, EBusComp,
); );
@@ -31,7 +31,7 @@ export class Monster extends ecs.Entity {
destroy(): void { destroy(): void {
this.remove(HeroViewComp); this.remove(HeroViewComp);
this.remove(MonAttrsComp); this.remove(HeroAttrsComp);
this.remove(TalComp); this.remove(TalComp);
this.remove(EBusComp); this.remove(EBusComp);
super.destroy(); super.destroy();
@@ -53,7 +53,7 @@ export class Monster extends ecs.Entity {
var view = node.getComponent(HeroViewComp)!; var view = node.getComponent(HeroViewComp)!;
const model = this.get(MonAttrsComp); const model = this.get(HeroAttrsComp);
let hero = HeroInfo[uuid]; // 共用英雄数据 let hero = HeroInfo[uuid]; // 共用英雄数据
// 设置 View 层属性(表现相关) // 设置 View 层属性(表现相关)
view.scale = scale; view.scale = scale;
@@ -116,16 +116,16 @@ export class MonLifecycleSystem extends ecs.ComblockSystem
implements ecs.IEntityEnterSystem, ecs.IEntityRemoveSystem { implements ecs.IEntityEnterSystem, ecs.IEntityRemoveSystem {
filter() { filter() {
return ecs.allOf(MonAttrsComp); return ecs.allOf(HeroAttrsComp);
} }
entityEnter(e: ecs.Entity): void { entityEnter(e: ecs.Entity): void {
// 英雄实体创建时的特殊处理 // 怪物实体创建时的特殊处理
console.log(`怪物进入世界: ${e.get(MonAttrsComp).hero_name}`); console.log(`怪物进入世界: ${e.get(HeroAttrsComp).hero_name}`);
} }
entityRemove(e: ecs.Entity): void { entityRemove(e: ecs.Entity): void {
// 英雄实体销毁时的清理工作 // 怪物实体销毁时的清理工作
console.log(`怪物离开世界: ${e.get(MonAttrsComp).hero_name}`); console.log(`怪物离开世界: ${e.get(HeroAttrsComp).hero_name}`);
} }
} }

View File

@@ -1,204 +0,0 @@
/*
* @Author: dgflash
* @Date: 2021-11-18 15:56:01
* @LastEditors: dgflash
* @LastEditTime: 2022-08-17 13:43:25
*/
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { Attrs, AttrsType, BType, NeAttrs } from "../common/config/HeroAttrs";
import { BuffConf } from "../common/config/SkillSet";
import { HeroInfo, AttrSet } from "../common/config/heroSet";
/**
* 怪物属性数据模型 - 存储纯数据,不含表现逻辑
* 简化版本只保留临时buff系统移除持久型buff
*
* 注意HeroAttrsComp 中有详细的 ECS 架构分析,迁移方案见那个文件
*/
@ecs.register('MonAttrsComp')
export class MonAttrsComp extends ecs.Comp {
// ==================== 角色基础信息 ====================
hero_uuid: number = 1001;
hero_name: string = "monster";
lv: number = 1;
type: number = 0; // 0近战 1远程 2辅助
fac: number = 1; // 0:hero 1:monster默认为怪物
// ==================== 动态属性值 ====================
hp: number = 100; // 当前血量
mp: number = 100; // 当前魔法值
shield: number = 0; // 当前护盾
Attrs: any = []; // 最终属性数组经过Buff计算后
NeAttrs: any = []; // 负面状态数组
// ==================== Buff/Debuff 系统 ====================
/** 临时型buff数组 - 按时间自动过期怪物只使用临时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 = [];
addBuff(buffConf: BuffConf) {
// 怪物只使用临时buff
const attrIndex = buffConf.buff;
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);
}
recalculateSingleAttr(attrIndex: number) {
const baseValues: Record<number, number> = {
[Attrs.HP_MAX]: this.hp, [Attrs.MP_MAX]: this.mp, [Attrs.DEF]: this.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;
let totalValue = baseVal, totalRatio = 0;
// 怪物只计算临时buff
if (this.BUFFS_TEMP[attrIndex]) {
for (const buff of this.BUFFS_TEMP[attrIndex]) {
if (buff.BType === BType.VALUE) totalValue += buff.value;
else totalRatio += buff.value;
}
}
const attrType = AttrsType[attrIndex];
this.Attrs[attrIndex] = attrType === BType.RATIO ? totalValue + totalRatio : Math.floor(totalValue * (1 + totalRatio / 100));
this.clampSingleAttr(attrIndex);
}
private clampSingleAttr(attrIndex: number) {
switch(attrIndex) {
case Attrs.HP_MAX: case Attrs.MP_MAX: 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;
}
}
updateTemporaryBuffsDebuffs(dt: number) {
const affectedAttrs = new Set<number>();
for (const attrIndex in this.BUFFS_TEMP) {
const buffs = this.BUFFS_TEMP[attrIndex];
buffs.forEach(buff => {
buff.remainTime -= dt;
if (buff.remainTime <= 0) buffs.splice(buffs.indexOf(buff), 1);
});
if (buffs.length === 0) {
delete this.BUFFS_TEMP[attrIndex];
affectedAttrs.add(parseInt(attrIndex));
}
}
for (const key in this.NeAttrs) {
this.NeAttrs[key].remainTime -= dt;
if (this.NeAttrs[key].remainTime <= 0) this.NeAttrs[key].remainTime = 0;
}
affectedAttrs.forEach(attrIndex => this.recalculateSingleAttr(attrIndex));
}
clearBuffs(attrIndex?: number, isBuff: boolean = true): void {
if (attrIndex === undefined) {
for (const idx in this.BUFFS_TEMP) this.clearBuffsForAttr(parseInt(idx), isBuff);
} else {
this.clearBuffsForAttr(attrIndex, isBuff);
}
}
private clearBuffsForAttr(attrIndex: number, isBuff: boolean): void {
if (!this.BUFFS_TEMP[attrIndex]) return;
this.BUFFS_TEMP[attrIndex] = this.BUFFS_TEMP[attrIndex].filter(buff => {
const shouldClear = isBuff ? buff.value > 0 : buff.value < 0;
return !shouldClear;
});
if (this.BUFFS_TEMP[attrIndex].length === 0) delete this.BUFFS_TEMP[attrIndex];
this.recalculateSingleAttr(attrIndex);
}
clearNeAttr(neAttrIndex: number): void {
if (this.NeAttrs[neAttrIndex]) {
this.NeAttrs[neAttrIndex].value = 0;
this.NeAttrs[neAttrIndex].time = 0;
}
}
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 = "monster";
this.lv = 1;
this.type = 0;
this.fac = 1;
this.hp = 100;
this.mp = 100;
this.shield = 0;
this.Attrs = [];
this.NeAttrs = [];
this.BUFFS_TEMP = {}; // 只重置临时buff
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 = [];
}
}
/**
* ==================== 怪物属性更新系统 ====================
*
* 与 HeroAttrSystem 类似,但针对怪物
* 可以复用相同逻辑,也可以定制不同规则
*/
export class MonAttrSystem extends ecs.ComblockSystem
implements ecs.ISystemUpdate {
filter(): ecs.IMatcher {
return ecs.allOf(MonAttrsComp);
}
update(e: ecs.Entity): void {
const model = e.get(MonAttrsComp);
if (!model || model.is_dead) return;
// 怪物的属性更新逻辑(可以与英雄不同)
model.updateTemporaryBuffsDebuffs(this.dt);
// 怪物可能没有自然回复,或者回复速度不同
// model.mp += MonUpSet.MP * this.dt;
// model.hp += MonUpSet.HP * this.dt;
}
}

View File

@@ -1,9 +0,0 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "b2b785de-2ec9-49ca-a015-b56c5fe19a50",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -1,29 +0,0 @@
import { _decorator } from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
const { ccclass, property } = _decorator;
/** 视图层对象 */
@ccclass('MonViewComp')
@ecs.register('MonView', false)
export class MonViewComp extends CCComp {
/** 视图层逻辑代码分离演示 */
start() {
// var entity = this.ent as ecs.Entity; // ecs.Entity 可转为当前模块的具体实体对象
// this.on(ModuleEvent.Cmd, this.onHandler, this);
}
/** 全局消息逻辑处理 */
// private onHandler(event: string, args: any) {
// switch (event) {
// case ModuleEvent.Cmd:
// break;
// }
// }
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
reset() {
this.node.destroy();
}
}

View File

@@ -1,9 +0,0 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "413afaac-8d90-4810-8036-a5dae3f9eea8",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -6,7 +6,6 @@ import { GameEvent } from '../common/config/GameEvent';
import { FacSet } from '../common/config/BoxSet'; import { FacSet } from '../common/config/BoxSet';
import { smc } from '../common/SingletonModuleComp'; import { smc } from '../common/SingletonModuleComp';
import { CCComp } from 'db://oops-framework/module/common/CCComp'; import { CCComp } from 'db://oops-framework/module/common/CCComp';
import { MonAttrsComp } from './MonAttrsComp';
import { HeroAttrsComp } from './HeroAttrsComp'; import { HeroAttrsComp } from './HeroAttrsComp';
import { SkillEnt } from '../skill/SkillEnt'; import { SkillEnt } from '../skill/SkillEnt';
import { Attrs } from '../common/config/HeroAttrs'; import { Attrs } from '../common/config/HeroAttrs';
@@ -107,7 +106,7 @@ export class SkillConComp extends CCComp {
check_target(){ check_target(){
if(this.HeroView.fac==FacSet.HERO){ if(this.HeroView.fac==FacSet.HERO){
return ecs.query(ecs.allOf(MonAttrsComp)) return ecs.query(ecs.allOf(HeroAttrsComp))
}else{ }else{
return ecs.query(ecs.allOf(HeroAttrsComp)) return ecs.query(ecs.allOf(HeroAttrsComp))
} }