feat(field-skill): 新增驻场技能卡牌支持与属性计算逻辑
为CardConfig接口新增field字段用于配置驻场技能UUID数组 新增两个示例驻场光环卡牌 优化FieldSkillHelper统计场上技能卡牌的属性加成 调整SkillBoxComp逻辑:驻场技能隐藏剩余次数、跳过定期触发
This commit is contained in:
@@ -65,6 +65,7 @@ export interface CardConfig {
|
|||||||
t_inv?: number // 触发间隔(秒)
|
t_inv?: number // 触发间隔(秒)
|
||||||
keep_waves?: number // 维持的波次数(-1表示持续到战斗结束,0或undefined表示仅本波次)
|
keep_waves?: number // 维持的波次数(-1表示持续到战斗结束,0或undefined表示仅本波次)
|
||||||
overrides?: SkillOverrides // 技能参数覆写(如自定义伤害ap、buff值、金币数等)
|
overrides?: SkillOverrides // 技能参数覆写(如自定义伤害ap、buff值、金币数等)
|
||||||
|
field?: number[] // 驻场技能 UUID 数组,表示该卡牌提供驻场属性加成
|
||||||
}
|
}
|
||||||
export const CardsUpSet: Record<number, number> = {
|
export const CardsUpSet: Record<number, number> = {
|
||||||
1: 50,
|
1: 50,
|
||||||
@@ -141,7 +142,18 @@ CardPoolList.push(
|
|||||||
{
|
{
|
||||||
uuid: 6101, type: CardType.Skill, cost: 0, weight: 10, pool_lv: 1, wave: 1, kind: CKind.Skill, card_lv: 1,
|
uuid: 6101, type: CardType.Skill, cost: 0, weight: 10, pool_lv: 1, wave: 1, kind: CKind.Skill, card_lv: 1,
|
||||||
name: "持续天降火球", info: "战斗中每隔3秒释放一个火球,造成300%伤害,持续2波次",
|
name: "持续天降火球", info: "战斗中每隔3秒释放一个火球,造成300%伤害,持续2波次",
|
||||||
is_inst: false, t_times: 999, t_inv: 3, keep_waves: 15, overrides: { TGroup: TGroup.Enemy, ap: 300, hit_count: 2 }
|
is_inst: false, t_times: 999, t_inv: 3, keep_waves: 2, overrides: { TGroup: TGroup.Enemy, ap: 300, hit_count: 2 }
|
||||||
|
},
|
||||||
|
// 驻场技能示例卡牌
|
||||||
|
{
|
||||||
|
uuid: 6501, type: CardType.Skill, cost: 0, weight: 10, pool_lv: 1, wave: 1, kind: CKind.Skill, card_lv: 1,
|
||||||
|
name: "全体攻击光环", info: "全体英雄攻击力增加20%,只要此卡在场就生效",
|
||||||
|
is_inst: false, t_times: 999, t_inv: 0, keep_waves: -1, field: [7008] // 对应 FieldSkillSet[7008] HeroAtk +20%
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uuid: 6502, type: CardType.Skill, cost: 0, weight: 10, pool_lv: 1, wave: 1, kind: CKind.Skill, card_lv: 1,
|
||||||
|
name: "全体生命光环", info: "全体英雄最大生命增加10%,只要此卡在场就生效",
|
||||||
|
is_inst: false, t_times: 999, t_inv: 0, keep_waves: -1, field: [7016] // 对应 FieldSkillSet[7016] HeroHp +10%
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { FacSet } from "../common/config/GameSet";
|
|||||||
import { HeroInfo } from "../common/config/heroSet";
|
import { HeroInfo } from "../common/config/heroSet";
|
||||||
import { FieldSkillSet, FieldSkillType } from "../common/config/SkillSet";
|
import { FieldSkillSet, FieldSkillType } from "../common/config/SkillSet";
|
||||||
import { HeroAttrsComp } from "./HeroAttrsComp";
|
import { HeroAttrsComp } from "./HeroAttrsComp";
|
||||||
|
import { SkillBoxComp } from "../map/SkillBoxComp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 驻场技能(光环属性)计算辅助类
|
* 驻场技能(光环属性)计算辅助类
|
||||||
@@ -12,9 +13,11 @@ import { HeroAttrsComp } from "./HeroAttrsComp";
|
|||||||
* 解耦原先写在 HeroAttrsComp 中的静态计算逻辑,符合单一职责原则。
|
* 解耦原先写在 HeroAttrsComp 中的静态计算逻辑,符合单一职责原则。
|
||||||
*/
|
*/
|
||||||
export class FieldSkillHelper {
|
export class FieldSkillHelper {
|
||||||
/** 获取指定驻场技能类型的总加成值(只计算存活的友方英雄) */
|
/** 获取指定驻场技能类型的总加成值(计算存活的友方英雄 + 场上的驻场技能卡) */
|
||||||
public static getFieldSkillTotalValue(type: FieldSkillType): number {
|
public static getFieldSkillTotalValue(type: FieldSkillType): number {
|
||||||
let total = 0;
|
let total = 0;
|
||||||
|
|
||||||
|
// 1. 统计英雄带来的驻场技能加成
|
||||||
ecs.query(ecs.allOf(HeroAttrsComp)).forEach((entity: ecs.Entity) => {
|
ecs.query(ecs.allOf(HeroAttrsComp)).forEach((entity: ecs.Entity) => {
|
||||||
const model = entity.get(HeroAttrsComp);
|
const model = entity.get(HeroAttrsComp);
|
||||||
if (!model || model.is_dead || model.fac !== FacSet.HERO) return;
|
if (!model || model.is_dead || model.fac !== FacSet.HERO) return;
|
||||||
@@ -28,6 +31,20 @@ export class FieldSkillHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 2. 统计技能盒子(技能卡)带来的驻场技能加成
|
||||||
|
ecs.query(ecs.allOf(SkillBoxComp)).forEach((entity: ecs.Entity) => {
|
||||||
|
const skillBox = entity.get(SkillBoxComp);
|
||||||
|
if (!skillBox || !skillBox.field || skillBox.field.length === 0) return;
|
||||||
|
|
||||||
|
for (const skillUuid of skillBox.field) {
|
||||||
|
const skillConfig = FieldSkillSet[skillUuid];
|
||||||
|
if (skillConfig && skillConfig.type === type) {
|
||||||
|
total += skillConfig.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ export class SkillBoxComp extends CCComp {
|
|||||||
private keep_waves: number = 0;
|
private keep_waves: number = 0;
|
||||||
/** 技能覆写参数(自定义伤害、Buff等) */
|
/** 技能覆写参数(自定义伤害、Buff等) */
|
||||||
private overrides?: SkillOverrides;
|
private overrides?: SkillOverrides;
|
||||||
|
/** 驻场技能 UUID 列表 */
|
||||||
|
public field: number[] = [];
|
||||||
|
|
||||||
// ======================== 运行时状态 ========================
|
// ======================== 运行时状态 ========================
|
||||||
|
|
||||||
@@ -131,6 +133,7 @@ export class SkillBoxComp extends CCComp {
|
|||||||
this.trigger_interval = config.t_inv ?? 0;
|
this.trigger_interval = config.t_inv ?? 0;
|
||||||
this.keep_waves = config.keep_waves ?? 0;
|
this.keep_waves = config.keep_waves ?? 0;
|
||||||
this.overrides = config.overrides;
|
this.overrides = config.overrides;
|
||||||
|
this.field = config.field || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.current_trigger_times = 0;
|
this.current_trigger_times = 0;
|
||||||
@@ -177,8 +180,12 @@ export class SkillBoxComp extends CCComp {
|
|||||||
// 更新剩余次数标签
|
// 更新剩余次数标签
|
||||||
if (this.info_label) {
|
if (this.info_label) {
|
||||||
if (!this.is_instant) {
|
if (!this.is_instant) {
|
||||||
|
if (this.trigger_interval <= 0 && this.field && this.field.length > 0) {
|
||||||
|
this.info_label.string = ""; // 纯驻场技能不显示剩余次数
|
||||||
|
} else {
|
||||||
const remain = Math.max(0, this.trigger_times - this.current_trigger_times);
|
const remain = Math.max(0, this.trigger_times - this.current_trigger_times);
|
||||||
this.info_label.string = `${remain}`;
|
this.info_label.string = `${remain}`;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.info_label.string = "";
|
this.info_label.string = "";
|
||||||
}
|
}
|
||||||
@@ -189,7 +196,7 @@ export class SkillBoxComp extends CCComp {
|
|||||||
let sprite = this.cd_mask.getComponent(Sprite);
|
let sprite = this.cd_mask.getComponent(Sprite);
|
||||||
if (sprite) {
|
if (sprite) {
|
||||||
if (this.is_instant || this.trigger_interval <= 0) {
|
if (this.is_instant || this.trigger_interval <= 0) {
|
||||||
sprite.fillRange = 0; // 无需冷却,直接归 0
|
sprite.fillRange = 0; // 无需冷却(包括驻场光环卡),直接归 0
|
||||||
} else {
|
} else {
|
||||||
sprite.fillRange = Math.max(0, 1 - (this.timer / this.trigger_interval));
|
sprite.fillRange = Math.max(0, 1 - (this.timer / this.trigger_interval));
|
||||||
}
|
}
|
||||||
@@ -284,6 +291,11 @@ export class SkillBoxComp extends CCComp {
|
|||||||
if (!this.initialized || !this.in_combat || this.is_instant) return;
|
if (!this.initialized || !this.in_combat || this.is_instant) return;
|
||||||
if (!smc.mission.play || smc.mission.pause) return;
|
if (!smc.mission.play || smc.mission.pause) return;
|
||||||
|
|
||||||
|
// 如果是纯驻场光环技能且无触发间隔,则不执行定期触发逻辑
|
||||||
|
if (this.trigger_interval <= 0 && this.field && this.field.length > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.current_trigger_times < this.trigger_times) {
|
if (this.current_trigger_times < this.trigger_times) {
|
||||||
this.timer += dt;
|
this.timer += dt;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user