diff --git a/assets/script/game/common/config/CardSet.ts b/assets/script/game/common/config/CardSet.ts index c3a144f5..b2105f28 100644 --- a/assets/script/game/common/config/CardSet.ts +++ b/assets/script/game/common/config/CardSet.ts @@ -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 = { + 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个友方单位增加攻击力和生命上限" }, +} + /** 功能卡定义表 */ diff --git a/assets/script/game/common/config/GameSet.ts b/assets/script/game/common/config/GameSet.ts index c6dbae23..051b238a 100644 --- a/assets/script/game/common/config/GameSet.ts +++ b/assets/script/game/common/config/GameSet.ts @@ -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 { diff --git a/assets/script/game/hero/SCastSystem.ts b/assets/script/game/hero/SCastSystem.ts index 48f73d44..93a6f125 100644 --- a/assets/script/game/hero/SCastSystem.ts +++ b/assets/script/game/hero/SCastSystem.ts @@ -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); + 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[] }; /** 近战英雄默认施法射程 */ diff --git a/assets/script/game/map/CardComp.ts b/assets/script/game/map/CardComp.ts index 9f05c0ee..c8471495 100644 --- a/assets/script/game/map/CardComp.ts +++ b/assets/script/game/map/CardComp.ts @@ -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] diff --git a/assets/script/game/map/CardUseComp.ts b/assets/script/game/map/CardUseComp.ts index 6f751042..8e6d4984 100644 --- a/assets/script/game/map/CardUseComp.ts +++ b/assets/script/game/map/CardUseComp.ts @@ -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: diff --git a/assets/script/game/map/MissionHeroComp.ts b/assets/script/game/map/MissionHeroComp.ts index 30392c63..b3db3d93 100644 --- a/assets/script/game/map/MissionHeroComp.ts +++ b/assets/script/game/map/MissionHeroComp.ts @@ -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() }