Files
heros/assets/script/game/skill/SkillSystem.ts
2025-03-27 23:25:10 +08:00

149 lines
5.2 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 { Node, Vec3 } from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { HeroViewComp } from "../hero/HeroViewComp";
import { HeroSkillsComp } from "./heroSkillsComp";
import { endType, SkillSet, TargetGroup, TargetType } from "../common/config/SkillSet";
import { CdType } from "../common/config/SkillSet";
import { oops } from "db://oops-framework/core/Oops";
import { GameEvent } from "../common/config/GameEvent";
import { Skill } from "../skills/Skill";
import { SkillCom } from "../skills/SkillCom";
import { AnimType } from "../common/config/SkillSet";
/** 技能系统 */
@ecs.register('SkillSystem')
export class SkillSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
private _timers: { [key: string]: number } = {};
private _damageQueue: Array<{ timer: number; callback: () => void }> = [];
private readonly SKILL_RANGE_X = 10; // x轴判定范围
private readonly SKILL_RANGE_Y = 10; // y轴判定范围
init(): void {
oops.message.on(GameEvent.MissionEnd, this.clear_timer, this);
}
filter(): ecs.IMatcher {
return ecs.allOf(SkillCom);
}
update(e: ecs.Entity) {
const skill = e.get(SkillCom);
if(this.checkSkill(skill)){
if(skill.atk_count < 1){
skill.atk_count++;
// console.log("技能命中目标",skill.caster,skill.target,SkillSet[skill.s_uuid]);
this.applySkillEffect(skill.caster,skill.target,SkillSet[skill.s_uuid],e);
}
}
this.processDamageQueue();
}
private processDamageQueue() {
const delta = this.dt;
for (let i = this._damageQueue.length - 1; i >= 0; i--) {
this._damageQueue[i].timer -= delta;
if (this._damageQueue[i].timer <= 0) {
this._damageQueue[i].callback();
this._damageQueue.splice(i, 1);
}
}
}
checkSkill(skill: SkillCom) {
const targetPos = skill.target.node.position;
const target = skill.target;
const skillPos = skill.node.position;
// 根据技能配置获取判定范围
const config = SkillSet[skill.s_uuid];
const rangeX = config?.rangeX || 30; // 默认值为10
const rangeY = config?.rangeY || 40;
const distanceX = Math.abs(targetPos.x - skillPos.x);
const distanceY = Math.abs(targetPos.y+40 - skillPos.y);
const isInRange = distanceX < rangeX && distanceY < rangeY;
return isInRange;
}
/** 应用技能效果 */
private applySkillEffect(casterView:HeroViewComp, targetView: HeroViewComp, config: typeof SkillSet[keyof typeof SkillSet],e:ecs.Entity) {
// 直接计算伤害(包含防御减免)
const damageResult = this.calculateDamage(casterView, targetView, config);
// 将施法者传入applyDamage方法
this.applyDamage(targetView,damageResult);
// 播放技能特效
casterView.playSkillEffect(config.uuid);
console.log(`${casterView.hero_name}${targetView.hero_name} 造成 ${damageResult.value}伤害`);
if(config.endType === endType.collision){
e.destroy();
}
}
private calculateDamage(caster: HeroViewComp, target: HeroViewComp, config: typeof SkillSet[keyof typeof SkillSet]) {
const result = {
value: 0,
isCrit: false,
isDodged: false,
delay: 0.3, // 默认延迟
ignoreDefense: false,
canCrit: true,
}
let final = caster.ap * config.ap / 100;
// 伤害浮动±10%
const damageFloat = 0.9 + Math.random() * 0.2; // 0.9~1.1
final *= damageFloat;
final = Math.round(final);
result.value = Math.max(1, final); // 确保最小伤害为1
result.isCrit = false;
return result;
}
private applyDamage(targetView: HeroViewComp, result: any,) {;
this._damageQueue.push({
timer: 0,
callback: () => {
if (!targetView?.ent.has(HeroViewComp)) return;
let remainingDamage = result.value;
if (targetView.shield > 0) {
const shieldAbsorb = Math.min(targetView.shield, remainingDamage);
targetView.shield -= shieldAbsorb;
remainingDamage -= shieldAbsorb;
if (targetView.shield <= 0) {
targetView.BUFFCOMP.show_shield(false);
}
}
if (remainingDamage > 0) {
targetView.hp -= remainingDamage;
if(targetView.hp <= 0) {
targetView.BUFFCOMP.dead()
targetView.to_grave();
}
targetView.showDamage(result.value, true);
} else {
targetView.BUFFCOMP.tooltip(5,"*吸收*");
}
}
});
}
public clear_timer() {
console.log("clear_timer");
Object.values(this._timers).forEach(clearTimeout);
}
onDestroy() {
Object.values(this._timers).forEach(clearTimeout);
}
/** 应用负面状态 */
private applyDebuff(target: ecs.Entity, config: typeof SkillSet[keyof typeof SkillSet]) {
// 实现debuff逻辑...
}
}