feat: 实现技能卡牌系统并添加相关配置

- 在 GameSet 中新增技能卡牌释放起始坐标常量
- 卡牌使用组件增加技能卡释放事件分发
- 任务英雄组件监听技能卡事件并转发给技能施放系统
- 卡牌组件支持技能卡牌的显示和等级星级
- 卡牌配置中添加技能卡牌池和对应的配置信息
- 技能施放系统扩展以支持卡牌技能的直接触发
This commit is contained in:
walkpan
2026-04-05 23:07:18 +08:00
parent 5d188bb5aa
commit dc9c6cc94a
6 changed files with 137 additions and 6 deletions

View File

@@ -7,7 +7,7 @@ import { Skill } from "../skill/Skill";
import { smc } from "../common/SingletonModuleComp";
import { HType } from "../common/config/heroSet";
import { Attrs } from "../common/config/HeroAttrs";
import { BoxSet, FightSet } from "../common/config/GameSet";
import { BoxSet, FacSet, FightSet } from "../common/config/GameSet";
import { oops } from "db://oops-framework/core/Oops";
import { GameEvent } from "../common/config/GameEvent";
@@ -40,10 +40,91 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
oops.message.off(GameEvent.TriggerSkill, this.onTriggerSkill, this);
}
private onTriggerSkill(event: string, args: { s_uuid: number, heroAttrs: HeroAttrsComp, heroView: HeroViewComp, triggerType?: string }) {
if (!args || !args.s_uuid || !args.heroAttrs || !args.heroView) return;
private onTriggerSkill(event: string, args: {
s_uuid: number,
heroAttrs?: HeroAttrsComp,
heroView?: HeroViewComp,
triggerType?: string,
isCardSkill?: boolean,
card_lv?: number,
targetPos?: Vec3
}) {
if (!args || !args.s_uuid) return;
// 卡牌技能直接触发
if (args.isCardSkill) {
this.forceCastCardSkill(args.s_uuid, args.card_lv || 1, args.targetPos || new Vec3(FightSet.CSKILL_START_X, FightSet.CSKILL_START_Y, 0));
return;
}
// 常规英雄技能触发
if (!args.heroAttrs || !args.heroView) return;
this.forceCastTriggerSkill(args.s_uuid, args.heroAttrs, args.heroView, args.triggerType);
}
/**
* 强制执行卡牌技能
* 卡牌技能没有施法者主体,直接从指定坐标释放,或者对全体/随机友方生效
*/
public forceCastCardSkill(s_uuid: number, cardLv: number, spawnPos: Vec3) {
const config = SkillSet[s_uuid];
if (!config) return;
// 如果是敌方目标,没有战斗时不释放
const isEnemyTarget = !this.isSelfSkill(config.TGroup) && !this.isFriendlySkill(config.TGroup);
if (isEnemyTarget && !smc.mission.in_fight) return;
let isFriendly = false;
let targetEids: number[] = [];
if (this.isFriendlySkill(config.TGroup) || this.isSelfSkill(config.TGroup)) {
isFriendly = true;
targetEids = this.collectFriendlyTargetEids(FacSet.HERO, undefined, true); // 获取所有英雄阵营的目标
}
const sUp = SkillUpList[s_uuid] ? SkillUpList[s_uuid] : SkillUpList[1001];
const cNum = Math.min(2, Math.max(0, Math.floor(sUp.num ?? 0)));
const castTimes = 1 + cNum;
// 构造一个模拟的 HeroAttrsComp 用于数值计算,只包含基础卡牌伤害计算所需的属性
const mockAttrs = new HeroAttrsComp();
mockAttrs.ap = 100; // 基准攻击力,可以根据设计需求调整
mockAttrs.critical = 0;
mockAttrs.freeze_chance = 0;
mockAttrs.back_chance = 0;
mockAttrs.puncture = 0;
mockAttrs.fac = FacSet.HERO;
for (let i = 0; i < castTimes; i++) {
if (isFriendly) {
const friendlyTargets = this.resolveFriendlyTargets(targetEids, FacSet.HERO);
if (friendlyTargets.length === 0) continue;
this.applyFriendlySkillEffects(s_uuid, cardLv, config, null as any, mockAttrs, friendlyTargets, null);
} else {
const enemyTargetPos = this.resolveRepeatCastTargetPos(new Vec3(spawnPos.x + 300, spawnPos.y, spawnPos.z), i);
this.createSkillEntityForCard(s_uuid, cardLv, mockAttrs, spawnPos, enemyTargetPos, i);
}
}
}
/** 专用于卡牌施放的技能实体生成 */
private createSkillEntityForCard(s_uuid: number, skillLv: number, mockAttrs: HeroAttrsComp, startPos: Vec3, targetPos: Vec3 | null, castIndex: number = 0) {
const scene = smc.map.MapView.scene;
const parent = scene.entityLayer?.node?.getChildByName("SKILL");
if (!parent || !targetPos) return;
const skill = ecs.getEntity<Skill>(Skill);
const actualStartPos = this.resolveRepeatCastStartPos(startPos, castIndex);
// 伪造一个简单的 heroView 供 Skill 初始化使用,只包含方向信息
const mockView = {
node: { scale: new Vec3(1, 1, 1), position: actualStartPos },
ent: { eid: -1 },
box_group: BoxSet.HERO
} as any;
skill.load(actualStartPos, parent, s_uuid, targetPos.clone(), mockView, mockAttrs, skillLv, 0);
}
/** 空施法计划:用于“当前无可施法技能”时的统一返回 */
private readonly emptyCastPlan = { skillId: 0, skillLv: 1, isFriendly: false, targetPos: null as Vec3 | null, targetEids: [] as number[] };
/** 近战英雄默认施法射程 */