伤害系统有问题,打算放弃

This commit is contained in:
2025-02-03 15:03:45 +08:00
parent 8f2612bda2
commit 060046a6a6
18 changed files with 549 additions and 112 deletions

View File

@@ -0,0 +1,24 @@
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { BattleState } from "./BattleStateComp";
import { DamageResult } from "../damage/DamageComp";
@ecs.register('BattleEndSystem')
export class BattleEndSystem extends ecs.ComblockSystem {
filter(): ecs.IMatcher {
return ecs.allOf(BattleState);
}
update(e: ecs.Entity) {
const state = e.get(BattleState);
if (state.isEnded) {
// 清理所有残留伤害组件
ecs.query(ecs.allOf(DamageResult)).forEach(entity => {
entity.remove(DamageResult);
});
// 重置战斗状态
state.isEnded = false;
}
}
}

View File

@@ -3,7 +3,6 @@ import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ec
import { BattleState } from "./BattleStateComp";
import { smc } from "../common/SingletonModuleComp";
import { GameEvent } from "../common/config/GameEvent";
import { DamageResult } from "../damage/DamageComp";
@ecs.register('BattleManager')
export class BattleManager extends ecs.Entity {
@@ -72,12 +71,6 @@ export class BattleManagerSystem extends ecs.ComblockSystem {
private onBattleEnd(entity: ecs.Entity) {
// 发放奖励、保存进度等
const state = entity.get(BattleState); // 清理所有残留伤害组件
ecs.query(ecs.allOf(DamageResult)).forEach(entity => {
entity.remove(DamageResult);
});
// 重置战斗状态
state.isEnded = false;
entity.destroy();
}
}

View File

@@ -1,3 +1,4 @@
import { Vec3 } from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
export enum DamageType {
@@ -15,6 +16,7 @@ export class DamageRequest extends ecs.Comp {
damageType: number = 1; // 伤害类型
canCrit: boolean = true; // 是否可暴击
ignoreDefense: boolean = false; // 是否忽略防御
delay: number = 0; // 新增延迟时间属性
reset() {
this.source = null!;
@@ -23,19 +25,24 @@ export class DamageRequest extends ecs.Comp {
this.damageType = 1;
this.canCrit = true;
this.ignoreDefense = false;
this.delay = 0;
}
}
/** 伤害结果组件 */
/** 伤害结果组件 */
@ecs.register('DamageResult')
export class DamageResult extends ecs.Comp {
finalDamage: number = 0;
isCrit: boolean = false;
isDodged: boolean = false;
value: number = 0; // 伤害数值
isCrit: boolean = false; // 是否暴击
isDodged: boolean = false; // 是否闪避
delay: number = 0; // 显示延迟(秒)
position: Vec3 = new Vec3();// 显示位置
reset(finalDamage: number = 0, isCrit: boolean = false, isDodged: boolean = false) {
this.finalDamage = finalDamage;
this.isCrit = isCrit;
this.isDodged = isDodged;
reset() {
this.value = 0;
this.isCrit = false;
this.isDodged = false;
this.delay = 0;
this.position.set(0, 0, 0);
}
}

View File

@@ -1,21 +1,96 @@
import { _decorator, NodePool, Node, Label, Color, tween, Vec3, instantiate, Prefab, resources } from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { HeroViewComp } from "../hero/HeroViewComp";
import { DamageResult } from "./DamageComp";
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
import { DamageText } from "./DamageText";
@ecs.register('DamageShowSystem')
export class DamageShowSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
export class DamageShowSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate{
private _pool: NodePool = new NodePool();
private _timers: Set<number> = new Set();
private _prefab: Prefab | null = null;
init() {
// 使用原生资源加载
resources.load("game/skills/damageText", Prefab, (err, prefab) => {
if (err) {
console.error("预制体加载失败:", err);
return;
}
this._prefab = prefab;
console.log("预制体加载成功:", this._prefab);
// 初始化对象池
for (let i = 0; i < 10; i++) {
const node = instantiate(this._prefab!);
this._pool.put(node);
}
});
}
filter(): ecs.IMatcher {
return ecs.allOf(DamageResult, HeroViewComp);
return ecs.allOf(DamageResult);
}
update(e: ecs.Entity) {
const res = e.get(DamageResult);
const view = e.get(HeroViewComp);
// 显示伤害数字
view.showDamage(res.finalDamage, res.isCrit);
// 移除已处理的伤害结果组件
this.scheduleShow(res);
e.remove(DamageResult);
}
private scheduleShow(res: DamageResult) {
const timer = setTimeout(() => {
let node = this._pool.get();
if (!node || !node.isValid) {
node = instantiate(this._prefab);
}
const damageText = node.getComponent(DamageText);
if (!damageText) {
console.error("Damage text prefab must have DamageText component!");
return;
}
this.setupText(node, res);
this.playAnimation(node, res.position);
this._timers.delete(timer);
}, res.delay * 1000);
this._timers.add(timer);
}
private setupText(node: Node, res: DamageResult) {
const damageText = node.getComponent(DamageText)!;
const label = damageText.label;
if (res.isDodged) {
label.string = "Miss";
label.color = Color.GRAY;
return;
}
label.string = Math.round(res.value).toString();
label.color = res.isCrit ? Color.RED : Color.WHITE;
damageText.playEffect(res.isCrit);
}
private playAnimation(node: Node, position: Vec3) {
node.setPosition(position);
tween(node)
.by(0.5, { position: new Vec3(0, 100, 0) })
.call(() => {
if (this._pool.size() < 20) { // 控制最大缓存数量
this._pool.put(node);
} else {
node.destroy();
}
})
.start();
}
onDestroy() {
this._timers.forEach(clearTimeout);
this._pool.clear();
}
}

View File

@@ -2,7 +2,7 @@
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "a9a6c37c-d5c7-4811-bc7a-471c8ed7b022",
"uuid": "9c86e3d7-f8da-4e74-b180-76fe3f1fda90",
"files": [],
"subMetas": {},
"userData": {}

View File

@@ -5,15 +5,17 @@ import { DamageRequest, DamageResult } from "./DamageComp";
@ecs.register('DamageSystem')
export class DamageSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
private _timers: { [key: string]: number } = {};
filter(): ecs.IMatcher {
return ecs.allOf(DamageRequest);
}
update(entity: ecs.Entity) {
const req = entity.get(DamageRequest);
update(e: ecs.Entity) {
const req = e.get(DamageRequest);
const result = this.calculateDamage(req);
this.applyDamage(req.target, result);
entity.remove(DamageRequest);
e.remove(DamageRequest);
}
private calculateDamage(req: DamageRequest): DamageResult {
@@ -24,7 +26,6 @@ export class DamageSystem extends ecs.ComblockSystem implements ecs.ISystemUpdat
// 闪避判定
if (Math.random() < targetView.dodge) {
const result = new DamageResult();
result.finalDamage = 0;
result.isDodged = true;
return result;
}
@@ -45,25 +46,28 @@ export class DamageSystem extends ecs.ComblockSystem implements ecs.ISystemUpdat
}
const result = new DamageResult();
result.finalDamage = Math.max(0, final);
result.value = Math.max(0, final);
result.isCrit = isCrit;
result.position = req.target.get(HeroViewComp).node.position;
result.delay = req.delay;
return result;
}
private applyDamage(target: ecs.Entity, result: DamageResult) {
const view = target.get(HeroViewComp);
view.hp -= result.finalDamage;
view.hp -= result.value;
// 添加伤害结果组件
const comp = target.add(DamageResult);
comp.finalDamage = result.finalDamage;
comp.value = result.value;
comp.isCrit = result.isCrit;
comp.position = result.position;
comp.delay = result.delay;
comp.isDodged = result.isDodged;
// 触发伤害事件
oops.message.dispatchEvent("OnDamage", {
target,
damage: result.finalDamage,
damage: result.value,
isCrit: result.isCrit
});
}

View File

@@ -0,0 +1,17 @@
import { _decorator, Component, Label, ParticleSystem } from "cc";
const { ccclass, property } = _decorator;
@ccclass('DamageText')
export class DamageText extends Component {
@property(Label)
label: Label = null!;
@property(ParticleSystem)
critEffect: ParticleSystem = null!;
playEffect(isCrit: boolean) {
if (isCrit && this.critEffect) {
this.critEffect.play();
}
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "96d1637a-2dfb-4c34-b60c-44144656c616",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -193,7 +193,7 @@ export class HeroViewComp extends CCComp {
}
this.hp_less(l_hp,is_crit);
}
hp_less(hp: number,is_crit:boolean=false){
hp_less(hp: number,is_crit:boolean=false,delay:number=0){
if(this.is_dead) return
hp=Math.floor(hp)
this.hp -= hp
@@ -211,17 +211,7 @@ export class HeroViewComp extends CCComp {
this.is_dead = true;
}
}
check_less(ap:number,is_crit:boolean,crit_add:number=0){
let d=this.def/ap
if(d > 1) d = 1
let l_hp=ap*(1-d*GameSet.DEF_RATE) //防御最高减免伤害比率计算
if(is_crit){
l_hp = l_hp * (150+crit_add)/100
}
let luck = RandomManager.instance.getRandomInt(-10,10)
l_hp=l_hp*(100+luck)/100
return Math.ceil(l_hp)
}
/**
* 检查并处理英雄受到的减益效果debuff
* 根据技能的不同减益类型,执行相应的逻辑,如冰冻、燃烧等。

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "3748c53e-6b9b-479f-aba0-87fc123ce161",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -1,12 +1,16 @@
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { HeroSkillSystem } from "./HeroSkillSystem";
import { DamageSystem } from "../damage/DamageSystem";
import { BattleManagerSystem } from "../battle/BattleManager";
import { BattleEndSystem } from "../battle/BattleEndSystem";
export class EcsSkillSystem extends ecs.System {
constructor() {
super();
this.add(new HeroSkillSystem());
this.add(new DamageSystem());
this.add(new BattleManagerSystem());
this.add(new BattleEndSystem());
}

View File

@@ -206,6 +206,7 @@ export class HeroSkillSystem extends ecs.ComblockSystem implements ecs.ISystemUp
req.source = caster;
req.target = target;
req.baseValue = caster.get(HeroViewComp).ap * (config.ap / 100);
req.delay = config.hited; // 添加命中延迟时间(秒)用于同步动画与伤害
// 播放技能特效
caster.get(HeroViewComp).playSkillEffect(config.uuid);