149 lines
5.2 KiB
TypeScript
149 lines
5.2 KiB
TypeScript
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逻辑...
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|