feat: 实现技能卡牌系统并添加相关配置
- 在 GameSet 中新增技能卡牌释放起始坐标常量 - 卡牌使用组件增加技能卡释放事件分发 - 任务英雄组件监听技能卡事件并转发给技能施放系统 - 卡牌组件支持技能卡牌的显示和等级星级 - 卡牌配置中添加技能卡牌池和对应的配置信息 - 技能施放系统扩展以支持卡牌技能的直接触发
This commit is contained in:
@@ -80,6 +80,13 @@ export const CardPoolList: CardConfig[] = [
|
||||
{ uuid: 5105, type: CardType.Hero, cost: 3, weight: 25, pool_lv: 5, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5304, type: CardType.Hero, cost: 3, weight: 25, pool_lv: 5, kind: CKind.Hero, hero_lv: 1 },
|
||||
|
||||
// 技能卡牌
|
||||
{ uuid: 6005, type: CardType.Skill, cost: 2, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1 },
|
||||
{ uuid: 6104, type: CardType.Skill, cost: 3, weight: 20, pool_lv: 2, kind: CKind.Skill, card_lv: 1 },
|
||||
{ uuid: 6205, type: CardType.Skill, cost: 4, weight: 20, pool_lv: 3, kind: CKind.Skill, card_lv: 1 },
|
||||
{ uuid: 6304, type: CardType.Skill, cost: 3, weight: 20, pool_lv: 2, kind: CKind.Skill, card_lv: 1 }, // 群体治疗
|
||||
{ uuid: 6406, type: CardType.Skill, cost: 4, weight: 20, pool_lv: 4, kind: CKind.Skill, card_lv: 1 }, // 群体全能
|
||||
|
||||
{ uuid: 7001, type: CardType.SpecialUpgrade, cost: 6, weight: 16, pool_lv: 1 ,kind: CKind.Card },
|
||||
{ uuid: 7002, type: CardType.SpecialUpgrade, cost: 6, weight: 14, pool_lv: 2 ,kind: CKind.Card },
|
||||
{ uuid: 7101, type: CardType.SpecialRefresh, cost: 4, weight: 14, pool_lv: 1 ,kind: CKind.Card },
|
||||
@@ -110,6 +117,20 @@ export interface SpecialRefreshCardConfig extends CardConfig {
|
||||
refreshHeroType: SpecialRefreshHeroType
|
||||
}
|
||||
|
||||
/** 技能卡牌配置补充 */
|
||||
export interface SkillCardConfig extends CardConfig {
|
||||
name: string
|
||||
info: string
|
||||
}
|
||||
|
||||
export const SkillCardList: Record<number, SkillCardConfig> = {
|
||||
6005: { uuid: 6005, type: CardType.Skill, cost: 2, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, name: "半月斩", info: "施放一道半月剑气,对触碰到的敌人造成伤害" },
|
||||
6104: { uuid: 6104, type: CardType.Skill, cost: 3, weight: 20, pool_lv: 2, kind: CKind.Skill, card_lv: 1, name: "闪光箭雨", info: "施放闪光箭雨,对多个敌人造成伤害并暴击" },
|
||||
6205: { uuid: 6205, type: CardType.Skill, cost: 4, weight: 20, pool_lv: 3, kind: CKind.Skill, card_lv: 1, name: "月光波", info: "施放月波,对触碰到的多个敌人造成高额伤害" },
|
||||
6304: { uuid: 6304, type: CardType.Skill, cost: 3, weight: 20, pool_lv: 2, kind: CKind.Skill, card_lv: 1, name: "神圣治疗", info: "恢复场上随机3个友方单位的生命值" },
|
||||
6406: { uuid: 6406, type: CardType.Skill, cost: 4, weight: 20, pool_lv: 4, kind: CKind.Skill, card_lv: 1, name: "全体鼓舞", info: "为随机3个友方单位增加攻击力和生命上限" },
|
||||
}
|
||||
|
||||
/** 功能卡定义表 */
|
||||
|
||||
|
||||
|
||||
@@ -33,8 +33,9 @@ export enum FightSet {
|
||||
FiIGHT_TIME=60*10,//战斗时间
|
||||
BACK_CHANCE=40,//击退概率
|
||||
FROST_TIME=3,//冰冻时间
|
||||
SKILL_CAST_DELAY=0.15
|
||||
|
||||
SKILL_CAST_DELAY=0.15,
|
||||
CSKILL_START_X=-340,
|
||||
CSKILL_START_Y=30,
|
||||
}
|
||||
|
||||
export enum IndexSet {
|
||||
|
||||
@@ -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[] };
|
||||
/** 近战英雄默认施法射程 */
|
||||
|
||||
@@ -2,7 +2,7 @@ import { mLogger } from "../common/Logger";
|
||||
import { _decorator, Animation, AnimationClip, EventTouch, Label, Node, NodeEventType, Sprite, SpriteAtlas, Tween, tween, UIOpacity, Vec3, resources, Light } from "cc";
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
||||
import { CardConfig, CardType, SpecialRefreshCardList, SpecialUpgradeCardList, CKind } from "../common/config/CardSet";
|
||||
import { CardConfig, CardType, SpecialRefreshCardList, SpecialUpgradeCardList, CKind, SkillCardList } from "../common/config/CardSet";
|
||||
import { CardUseComp } from "./CardUseComp";
|
||||
import { HeroInfo } from "../common/config/heroSet";
|
||||
import { SkillSet } from "../common/config/SkillSet";
|
||||
@@ -412,6 +412,15 @@ export class CardComp extends CCComp {
|
||||
this.oinfo_node.active = false;
|
||||
this.info_node.getChildByName("ap").getChildByName("val").getComponent(Label).string = `${(hero?.ap ?? 0) * heroLv}`;
|
||||
this.info_node.getChildByName("hp").getChildByName("val").getComponent(Label).string = `${(hero?.hp ?? 0) * heroLv}`;
|
||||
}else if(this.card_type===CardType.Skill){
|
||||
const skill = SkillSet[this.card_uuid];
|
||||
const skillCard = SkillCardList[this.card_uuid];
|
||||
const card_lv = Math.max(1, Math.floor(this.cardData.card_lv ?? 1));
|
||||
const spSuffix = card_lv >= 2 ? "★".repeat(card_lv - 1) : "";
|
||||
this.setLabel(this.name_node, `${spSuffix}${skillCard?.name || skill?.name || ""}${spSuffix}`);
|
||||
this.info_node.active = false;
|
||||
this.oinfo_node.active = true;
|
||||
this.oinfo_node.getChildByName("info").getComponent(Label).string = `${skillCard?.info || skill?.info || ""}`;
|
||||
}else{
|
||||
const specialCard = this.card_type === CardType.SpecialUpgrade
|
||||
? SpecialUpgradeCardList[this.card_uuid]
|
||||
|
||||
@@ -51,6 +51,7 @@ export class CardUseComp extends CCComp {
|
||||
oops.message.dispatchEvent(GameEvent.CallHero, used);
|
||||
return "hero";
|
||||
case CardType.Skill:
|
||||
oops.message.dispatchEvent(GameEvent.UseSkillCard, used);
|
||||
return "skill";
|
||||
case CardType.SpecialUpgrade:
|
||||
case CardType.SpecialRefresh:
|
||||
|
||||
@@ -49,16 +49,34 @@ export class MissionHeroCompComp extends CCComp {
|
||||
this.on(GameEvent.MissionEnd,this.clear_heros,this)
|
||||
/** 全局消息监听 */
|
||||
oops.message.on(GameEvent.CallHero,this.call_hero,this)
|
||||
oops.message.on(GameEvent.UseSkillCard,this.onUseSkillCard,this)
|
||||
}
|
||||
|
||||
onDestroy(){
|
||||
/** 清理监听,避免节点销毁后仍响应消息 */
|
||||
oops.message.off(GameEvent.CallHero,this.call_hero,this)
|
||||
oops.message.off(GameEvent.UseSkillCard,this.onUseSkillCard,this)
|
||||
oops.message.off(GameEvent.FightReady,this.fight_ready,this)
|
||||
oops.message.off(GameEvent.Zhaohuan,this.zhao_huan,this)
|
||||
oops.message.off(GameEvent.MissionEnd,this.clear_heros,this)
|
||||
}
|
||||
|
||||
/** 响应卡牌释放技能 */
|
||||
private onUseSkillCard(event: string, args: any) {
|
||||
const payload = args ?? event;
|
||||
const uuid = Number(payload?.uuid ?? 0);
|
||||
const card_lv = Math.max(1, Math.floor(Number(payload?.card_lv ?? 1)));
|
||||
if (!uuid) return;
|
||||
|
||||
// 分发给 SCastSystem 处理(使用特定的坐标 x=-340, y=30)
|
||||
oops.message.dispatchEvent(GameEvent.TriggerSkill, {
|
||||
s_uuid: uuid,
|
||||
isCardSkill: true,
|
||||
card_lv: card_lv,
|
||||
targetPos: v3(-340, 30, 0)
|
||||
});
|
||||
}
|
||||
|
||||
start() {
|
||||
// this.test_call()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user