feat(hero): 新增英雄职业定位系统,优化编队站位逻辑
1. 新增HRole枚举与角色定位配置,解耦成长类型与阵容职能 2. 重构移动系统的编队优先级计算,基于职业定位重新排序站位 3. 重写单行编队站位算法,根据队伍人数自动适配紧凑/松散排布 4. 为所有预设英雄配置对应职业定位
This commit is contained in:
@@ -128,6 +128,29 @@ export const HERO_GROW_COEF: Record<HGrowType, { hp: number; ap: number }> = {
|
||||
[HGrowType.Support]: { hp: 1.1, ap: 0.7 },
|
||||
};
|
||||
|
||||
/**
|
||||
* 英雄位置类型(职业定位)。
|
||||
* Why: grow_type 仅驱动数值成长曲线,无法表达"这个英雄在阵容里干什么";
|
||||
* role 面向 UI 展示与阵容推荐(如 HeroComboSet 的铁三角校验),与成长解耦。
|
||||
*/
|
||||
export enum HRole {
|
||||
Tank = 0, // 坦克:前排承伤,受击发动机
|
||||
Warrior = 1, // 战士:前排输出/献祭位
|
||||
Assassin = 2, // 刺客:近战爆发主C
|
||||
Archer = 3, // 射手:远程物理主C
|
||||
Mage = 4, // 法师:远程先手增益
|
||||
Support = 5, // 辅助:光环/治疗
|
||||
}
|
||||
|
||||
export const HRoleName: Record<HRole, string> = {
|
||||
[HRole.Tank]: "坦克",
|
||||
[HRole.Warrior]: "战士",
|
||||
[HRole.Assassin]: "刺客",
|
||||
[HRole.Archer]: "射手",
|
||||
[HRole.Mage]: "法师",
|
||||
[HRole.Support]: "辅助",
|
||||
};
|
||||
|
||||
/**
|
||||
* 计算英雄在目标等级下的累计属性成长增量(线性:每级加一份"基础属性×系数")。
|
||||
* 公式:累计 = 基础属性 × 类型系数 × (lv - 1)。
|
||||
@@ -282,6 +305,7 @@ export interface heroInfo {
|
||||
card_lv?: number; // 卡牌等级(驱动 bg_node 颜色:1=green 2=blue 3=purple 4=red 5=yellow)
|
||||
type: HType; // 攻击定位(近战/中程/远程)
|
||||
grow_type?: HGrowType; // 成长类型(决定每级 hp/ap 标准增量,默认 Warrior)
|
||||
role?: HRole; // 位置类型/职业定位(英雄专用,怪物用 monType 表达)
|
||||
monType?: MonType; // 怪物专属类型
|
||||
hp: number; // 生命值上限
|
||||
ap: number; // 攻击力
|
||||
@@ -378,7 +402,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
|
||||
// 5001 铁壁战士 — atked 护盾(标杆,原5011)
|
||||
5001: {
|
||||
uuid: 5001, name: "铁壁战士", path: "hk1", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, hp: 300, ap: 28,
|
||||
uuid: 5001, name: "铁壁战士", path: "hk1", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, role: HRole.Tank, hp: 300, ap: 28,
|
||||
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
|
||||
atked: {
|
||||
6301: [
|
||||
@@ -391,7 +415,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
// 5002 影袭刺客 — atking 自身攻击
|
||||
5002: {
|
||||
uuid: 5002, name: "影袭刺客", path: "hc1", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Melee, grow_type: HGrowType.Assassin, hp: 300, ap: 28,
|
||||
uuid: 5002, name: "影袭刺客", path: "hc1", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Melee, grow_type: HGrowType.Assassin, role: HRole.Assassin, hp: 300, ap: 28,
|
||||
skills: { 6003: { uuid: 6003, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Fast2].cd, ccd: 0 } },
|
||||
atking: {
|
||||
6401: [
|
||||
@@ -404,7 +428,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
// 5003 遗志将军 — dead 全队攻击
|
||||
5003: {
|
||||
uuid: 5003, name: "遗志将军", path: "hk2", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Melee, grow_type: HGrowType.Warrior, hp: 300, ap: 28,
|
||||
uuid: 5003, name: "遗志将军", path: "hk2", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Melee, grow_type: HGrowType.Warrior, role: HRole.Warrior, hp: 300, ap: 28,
|
||||
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
|
||||
dead: {
|
||||
6401: [
|
||||
@@ -417,7 +441,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
// 5004 破晓先知 — fstart 全队攻击
|
||||
5004: {
|
||||
uuid: 5004, name: "破晓先知", path: "hm1", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, hp: 143, ap: 40,
|
||||
uuid: 5004, name: "破晓先知", path: "hm1", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, role: HRole.Mage, hp: 143, ap: 40,
|
||||
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid3].cd, ccd: 0 } },
|
||||
fstart: {
|
||||
6401: [
|
||||
@@ -430,7 +454,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
// 5005 战歌法师 — field 攻击光环
|
||||
5005: {
|
||||
uuid: 5005, name: "战歌法师", path: "hm2", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, hp: 143, ap: 40,
|
||||
uuid: 5005, name: "战歌法师", path: "hm2", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, role: HRole.Support, hp: 143, ap: 40,
|
||||
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid3].cd, ccd: 0 } },
|
||||
field: [
|
||||
{ lv: 1, uuids: [{ uuid: 7002, value: 0.1 }] },
|
||||
@@ -444,7 +468,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
|
||||
// 5101 不死斗士 — atked 回血(更高数值)
|
||||
5101: {
|
||||
uuid: 5101, name: "不死斗士", path: "hk3", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, hp: 600, ap: 57,
|
||||
uuid: 5101, name: "不死斗士", path: "hk3", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, role: HRole.Tank, hp: 600, ap: 57,
|
||||
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
|
||||
atked: {
|
||||
6302: [
|
||||
@@ -457,7 +481,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
// 5102 致命杀手 — atking 暴击(更高数值)
|
||||
5102: {
|
||||
uuid: 5102, name: "致命杀手", path: "hc2", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Melee, grow_type: HGrowType.Assassin, hp: 600, ap: 57,
|
||||
uuid: 5102, name: "致命杀手", path: "hc2", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Melee, grow_type: HGrowType.Assassin, role: HRole.Assassin, hp: 600, ap: 57,
|
||||
skills: { 6003: { uuid: 6003, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Fast2].cd, ccd: 0 } },
|
||||
atking: {
|
||||
6403: [
|
||||
@@ -470,7 +494,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
// 5103 殉道勇士 — dead 全队护盾(更高数值)
|
||||
5103: {
|
||||
uuid: 5103, name: "殉道勇士", path: "hk4", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Melee, grow_type: HGrowType.Warrior, hp: 600, ap: 57,
|
||||
uuid: 5103, name: "殉道勇士", path: "hk4", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Melee, grow_type: HGrowType.Warrior, role: HRole.Warrior, hp: 600, ap: 57,
|
||||
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
|
||||
dead: {
|
||||
6301: [
|
||||
@@ -483,7 +507,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
// 5104 圣光祭司 — fstart 全队护盾(更高数值)
|
||||
5104: {
|
||||
uuid: 5104, name: "圣光祭司", path: "hm3", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, hp: 287, ap: 80,
|
||||
uuid: 5104, name: "圣光祭司", path: "hm3", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, role: HRole.Mage, hp: 287, ap: 80,
|
||||
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow1].cd, ccd: 0 } },
|
||||
fstart: {
|
||||
6301: [
|
||||
@@ -496,7 +520,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
// 5105 风怒先知 — field 攻速光环
|
||||
5105: {
|
||||
uuid: 5105, name: "风怒先知", path: "hm1", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, hp: 287, ap: 80,
|
||||
uuid: 5105, name: "风怒先知", path: "hm1", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, role: HRole.Support, hp: 287, ap: 80,
|
||||
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } },
|
||||
field: [
|
||||
{ lv: 1, uuids: [{ uuid: 7006, value: 0.1 }] },
|
||||
@@ -507,7 +531,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
// 5106 破甲射手 — atking 自身穿透伤害(计时buff增强)
|
||||
5106: {
|
||||
uuid: 5106, name: "破甲射手", path: "ha1", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Long, grow_type: HGrowType.Assassin, hp: 287, ap: 80,
|
||||
uuid: 5106, name: "破甲射手", path: "ha1", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Long, grow_type: HGrowType.Assassin, role: HRole.Archer, hp: 287, ap: 80,
|
||||
skills: { 6008: { uuid: 6008, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } },
|
||||
atking: {
|
||||
6512: [
|
||||
@@ -523,7 +547,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
|
||||
// 5201 怒血勇士 — atked 全队攻击(范围扩大)
|
||||
5201: {
|
||||
uuid: 5201, name: "怒血勇士", path: "hk5", fac: FacSet.HERO, card_lv: 3, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, hp: 900, ap: 85,
|
||||
uuid: 5201, name: "怒血勇士", path: "hk5", fac: FacSet.HERO, card_lv: 3, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, role: HRole.Tank, hp: 900, ap: 85,
|
||||
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
|
||||
atked: {
|
||||
6401: [
|
||||
@@ -536,7 +560,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
// 5202 援护射手 — atking 队友攻击(范围扩大)
|
||||
5202: {
|
||||
uuid: 5202, name: "援护射手", path: "ha1", fac: FacSet.HERO, card_lv: 3, lv: 1, type: HType.Long, grow_type: HGrowType.Assassin, hp: 430, ap: 120,
|
||||
uuid: 5202, name: "援护射手", path: "ha1", fac: FacSet.HERO, card_lv: 3, lv: 1, type: HType.Long, grow_type: HGrowType.Assassin, role: HRole.Archer, hp: 430, ap: 120,
|
||||
skills: { 6008: { uuid: 6008, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Normal2].cd, ccd: 0 } },
|
||||
atking: {
|
||||
6401: [
|
||||
@@ -549,7 +573,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
// 5203 传承卫士 — dead 全队生命(范围扩大)
|
||||
5203: {
|
||||
uuid: 5203, name: "传承卫士", path: "hk1", fac: FacSet.HERO, card_lv: 3, lv: 1, type: HType.Melee, grow_type: HGrowType.Warrior, hp: 900, ap: 85,
|
||||
uuid: 5203, name: "传承卫士", path: "hk1", fac: FacSet.HERO, card_lv: 3, lv: 1, type: HType.Melee, grow_type: HGrowType.Warrior, role: HRole.Warrior, hp: 900, ap: 85,
|
||||
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
|
||||
dead: {
|
||||
6402: [
|
||||
@@ -562,7 +586,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
// 5204 晨光贤者 — fstart 全队暴击(范围扩大)
|
||||
5204: {
|
||||
uuid: 5204, name: "晨光贤者", path: "hm2", fac: FacSet.HERO, card_lv: 3, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, hp: 430, ap: 120,
|
||||
uuid: 5204, name: "晨光贤者", path: "hm2", fac: FacSet.HERO, card_lv: 3, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, role: HRole.Mage, hp: 430, ap: 120,
|
||||
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid3].cd, ccd: 0 } },
|
||||
fstart: {
|
||||
6403: [
|
||||
@@ -575,7 +599,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
// 5205 精准术士 — field 暴击光环(范围扩大)
|
||||
5205: {
|
||||
uuid: 5205, name: "精准术士", path: "hm3", fac: FacSet.HERO, card_lv: 3, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, hp: 430, ap: 120,
|
||||
uuid: 5205, name: "精准术士", path: "hm3", fac: FacSet.HERO, card_lv: 3, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, role: HRole.Support, hp: 430, ap: 120,
|
||||
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } },
|
||||
field: [
|
||||
{ lv: 1, uuids: [{ uuid: 7004, value: 0.1 }] },
|
||||
@@ -589,7 +613,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
|
||||
// 5301 复仇守护者 — atked 全队暴击(范围+数值)
|
||||
5301: {
|
||||
uuid: 5301, name: "复仇守护者", path: "hk2", fac: FacSet.HERO, card_lv: 4, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, hp: 1200, ap: 113,
|
||||
uuid: 5301, name: "复仇守护者", path: "hk2", fac: FacSet.HERO, card_lv: 4, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, role: HRole.Tank, hp: 1200, ap: 113,
|
||||
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow1].cd, ccd: 0 } },
|
||||
atked: {
|
||||
6403: [
|
||||
@@ -602,7 +626,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
// 5302 破灭游侠 — atking 队友暴伤(范围+数值)
|
||||
5302: {
|
||||
uuid: 5302, name: "破灭游侠", path: "ha2", fac: FacSet.HERO, card_lv: 4, lv: 1, type: HType.Long, grow_type: HGrowType.Assassin, hp: 573, ap: 160,
|
||||
uuid: 5302, name: "破灭游侠", path: "ha2", fac: FacSet.HERO, card_lv: 4, lv: 1, type: HType.Long, grow_type: HGrowType.Assassin, role: HRole.Archer, hp: 573, ap: 160,
|
||||
skills: { 6008: { uuid: 6008, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Normal1].cd, ccd: 0 } },
|
||||
atking: {
|
||||
6404: [
|
||||
@@ -615,7 +639,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
// 5303 亡语刺客 — dead 全队暴击+暴伤(双效果)
|
||||
5303: {
|
||||
uuid: 5303, name: "亡语刺客", path: "hc3", fac: FacSet.HERO, card_lv: 4, lv: 1, type: HType.Melee, grow_type: HGrowType.Assassin, hp: 1200, ap: 113,
|
||||
uuid: 5303, name: "亡语刺客", path: "hc3", fac: FacSet.HERO, card_lv: 4, lv: 1, type: HType.Melee, grow_type: HGrowType.Assassin, role: HRole.Assassin, hp: 1200, ap: 113,
|
||||
skills: { 6003: { uuid: 6003, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Fast3].cd, ccd: 0 } },
|
||||
dead: {
|
||||
6403: [
|
||||
@@ -633,7 +657,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
// 5304 战吼术士 — fstart 全队攻击+生命(双效果)
|
||||
5304: {
|
||||
uuid: 5304, name: "战吼术士", path: "hm1", fac: FacSet.HERO, card_lv: 4, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, hp: 573, ap: 160,
|
||||
uuid: 5304, name: "战吼术士", path: "hm1", fac: FacSet.HERO, card_lv: 4, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, role: HRole.Mage, hp: 573, ap: 160,
|
||||
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid1].cd, ccd: 0 } },
|
||||
fstart: {
|
||||
6401: [
|
||||
@@ -651,7 +675,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
// 5305 领域贤者 — field 暴伤+攻速光环(双效果)
|
||||
5305: {
|
||||
uuid: 5305, name: "领域贤者", path: "hm2", fac: FacSet.HERO, card_lv: 4, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, hp: 573, ap: 160,
|
||||
uuid: 5305, name: "领域贤者", path: "hm2", fac: FacSet.HERO, card_lv: 4, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, role: HRole.Support, hp: 573, ap: 160,
|
||||
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } },
|
||||
field: [
|
||||
{ lv: 1, uuids: [{ uuid: 7005, value: 0.2 }, { uuid: 7006, value: 0.1 }] },
|
||||
@@ -665,7 +689,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
|
||||
// 5401 不灭战魂 — atked 攻击 + revive(双技能)
|
||||
5401: {
|
||||
uuid: 5401, name: "不灭战魂", path: "hk3", fac: FacSet.HERO, card_lv: 5, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, hp: 1500, ap: 142,
|
||||
uuid: 5401, name: "不灭战魂", path: "hk3", fac: FacSet.HERO, card_lv: 5, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, role: HRole.Tank, hp: 1500, ap: 142,
|
||||
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
|
||||
atked: {
|
||||
6401: [
|
||||
@@ -683,7 +707,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
// 5402 战歌游侠 — atking 攻击 + field 攻速光环(双技能)
|
||||
5402: {
|
||||
uuid: 5402, name: "战歌游侠", path: "ha3", fac: FacSet.HERO, card_lv: 5, lv: 1, type: HType.Long, grow_type: HGrowType.Assassin, hp: 717, ap: 200,
|
||||
uuid: 5402, name: "战歌游侠", path: "ha3", fac: FacSet.HERO, card_lv: 5, lv: 1, type: HType.Long, grow_type: HGrowType.Assassin, role: HRole.Archer, hp: 717, ap: 200,
|
||||
skills: { 6008: { uuid: 6008, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Fast3].cd, ccd: 0 } },
|
||||
atking: {
|
||||
6401: [
|
||||
@@ -701,7 +725,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
// 5403 凤凰祭司 — dead 攻击+护盾 + revive(双技能)
|
||||
5403: {
|
||||
uuid: 5403, name: "凤凰祭司", path: "hk4", fac: FacSet.HERO, card_lv: 5, lv: 1, type: HType.Melee, grow_type: HGrowType.Warrior, hp: 1500, ap: 142,
|
||||
uuid: 5403, name: "凤凰祭司", path: "hk4", fac: FacSet.HERO, card_lv: 5, lv: 1, type: HType.Melee, grow_type: HGrowType.Warrior, role: HRole.Warrior, hp: 1500, ap: 142,
|
||||
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
|
||||
dead: {
|
||||
6401: [
|
||||
@@ -724,7 +748,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
// 5404 涅槃贤者 — fstart 护盾+攻击 + revive(双技能)
|
||||
5404: {
|
||||
uuid: 5404, name: "涅槃贤者", path: "hm3", fac: FacSet.HERO, card_lv: 5, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, hp: 717, ap: 200,
|
||||
uuid: 5404, name: "涅槃贤者", path: "hm3", fac: FacSet.HERO, card_lv: 5, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, role: HRole.Mage, hp: 717, ap: 200,
|
||||
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Normal3].cd, ccd: 0 } },
|
||||
fstart: {
|
||||
6301: [
|
||||
@@ -747,7 +771,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
// 5405 圣言诗人 — atking 治疗 + field 生命光环(双技能)
|
||||
5405: {
|
||||
uuid: 5405, name: "圣言诗人", path: "hh1", fac: FacSet.HERO, card_lv: 5, lv: 1, type: HType.Long, grow_type: HGrowType.Support, hp: 717, ap: 200,
|
||||
uuid: 5405, name: "圣言诗人", path: "hh1", fac: FacSet.HERO, card_lv: 5, lv: 1, type: HType.Long, grow_type: HGrowType.Support, role: HRole.Support, hp: 717, ap: 200,
|
||||
skills: { 6015: { uuid: 6015, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Normal2].cd, ccd: 0 } },
|
||||
atking: {
|
||||
6302: [
|
||||
|
||||
@@ -120,6 +120,7 @@ export class Hero extends ecs.Entity {
|
||||
model.base_card_lv = hero.card_lv ?? 1;
|
||||
model.type = hero.type;
|
||||
model.grow_type = hero.grow_type;
|
||||
model.role = hero.role;
|
||||
model.fac = FacSet.HERO;
|
||||
model.dis = hero.dis ?? 720;
|
||||
model.posIndex = posIndex;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { HeroDisVal, HeroInfo, HSkillInfo, HType, SkillTriggerType, TriggerGrouped, LvFieldEntry, LvReviveEntry, LvBonusEntry, FieldEntry } from "../common/config/heroSet";
|
||||
import { HeroDisVal, HeroInfo, HSkillInfo, HType, SkillTriggerType, TriggerGrouped, LvFieldEntry, LvReviveEntry, LvBonusEntry, FieldEntry, HRole } from "../common/config/heroSet";
|
||||
import { mLogger } from "../common/Logger";
|
||||
import { FacSet, FightSet } from "../common/config/GameSet";
|
||||
import { FieldSkillSet, FieldSkillType, SkillOverrides } from "../common/config/SkillSet";
|
||||
@@ -29,6 +29,7 @@ export class HeroAttrsComp extends ecs.Comp {
|
||||
type: number = 0; // 0近战 1远程 2辅助
|
||||
fac: number = 0; // 0:hero 1:monster
|
||||
grow_type?: number; // 成长类型(HGrowType),驱动每级 hp/ap 线性成长
|
||||
role?: HRole; // 位置类型/职业定位(驱动编队站位优先级)
|
||||
// ==================== 基础属性(有初始值) ====================
|
||||
base_ap: number = 0; // 原始基础攻击(无任何加成)
|
||||
base_hp: number = 0; // 原始基础血量(无任何加成)
|
||||
@@ -563,6 +564,8 @@ export class HeroAttrsComp extends ecs.Comp {
|
||||
this.lv = 1;
|
||||
this.type = 0;
|
||||
this.fac = 0;
|
||||
this.grow_type = undefined;
|
||||
this.role = undefined;
|
||||
this.base_ap = 0;
|
||||
this.base_hp = 0;
|
||||
this.ap = 0;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { HeroViewComp } from "./HeroViewComp";
|
||||
import { HeroAttrsComp } from "./HeroAttrsComp";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
import { BoxSet, FacSet } from "../common/config/GameSet";
|
||||
import { HeroDisVal, HType } from "../common/config/heroSet";
|
||||
import { HeroDisVal, HType, HRole } from "../common/config/heroSet";
|
||||
import { BoxCollider2D, Node } from "cc";
|
||||
import { MonMoveComp } from "./MonMoveComp";
|
||||
|
||||
@@ -46,8 +46,6 @@ interface MoveFacConfig {
|
||||
retreatBackX: number;
|
||||
}
|
||||
|
||||
import { MissionHeroComp } from "../map/MissionHeroComp";
|
||||
|
||||
@ecs.register('MoveSystem')
|
||||
export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
||||
private readonly heroFrontAnchorX = -200;
|
||||
@@ -106,7 +104,7 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
update(e: ecs.Entity) {
|
||||
/** 战斗未开始/暂停时不驱动移动 */
|
||||
if (!smc.mission.play || smc.mission.pause) return;
|
||||
|
||||
|
||||
const model = e.get(HeroAttrsComp);
|
||||
const move = e.get(MoveComp);
|
||||
const view = e.get(HeroViewComp);
|
||||
@@ -125,55 +123,37 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
move.baseY = slot.targetY;
|
||||
move.targetX = slot.targetX;
|
||||
|
||||
// 战斗阶段不移动
|
||||
const canMove = !smc.mission.in_fight;
|
||||
|
||||
// 2. 平滑 Y 轴换路
|
||||
// 2. 平滑 Y 轴换路(不分阶段,立即响应编队变化)
|
||||
let isChangingLane = false;
|
||||
if (canMove) {
|
||||
if (Math.abs(view.node.position.y - move.baseY) > 2) {
|
||||
const currentY = view.node.position.y;
|
||||
const deltaY = move.baseY - currentY;
|
||||
const step = 400 * this.dt; // 换路速度
|
||||
const newY = currentY + Math.sign(deltaY) * Math.min(Math.abs(deltaY), step);
|
||||
view.node.setPosition(view.node.position.x, newY, 0);
|
||||
isChangingLane = true;
|
||||
} else {
|
||||
view.node.setPosition(view.node.position.x, move.baseY, 0);
|
||||
}
|
||||
if (Math.abs(view.node.position.y - move.baseY) > 2) {
|
||||
const currentY = view.node.position.y;
|
||||
const deltaY = move.baseY - currentY;
|
||||
const step = 400 * this.dt; // 换路速度
|
||||
const newY = currentY + Math.sign(deltaY) * Math.min(Math.abs(deltaY), step);
|
||||
view.node.setPosition(view.node.position.x, newY, 0);
|
||||
isChangingLane = true;
|
||||
} else {
|
||||
view.node.setPosition(view.node.position.x, move.baseY, 0);
|
||||
}
|
||||
|
||||
|
||||
// 渲染层级重排
|
||||
this.updateRenderOrder();
|
||||
|
||||
const nearestEnemy = this.findNearestEnemy(e);
|
||||
if (nearestEnemy) {
|
||||
/** 有敌人:进入战斗位移逻辑 */
|
||||
if (canMove) {
|
||||
this.processCombatLogic(e, move, view, model, nearestEnemy);
|
||||
} else {
|
||||
model.is_atking = true; // 战斗中不移动,但保持攻击状态
|
||||
}
|
||||
/** 有敌人:进入战斗位移逻辑(立即向编队目标移动) */
|
||||
this.processCombatLogic(e, move, view, model, nearestEnemy);
|
||||
this.syncCombatTarget(model, view, nearestEnemy);
|
||||
} else {
|
||||
/** 无敌人:清目标并回归编队站位 */
|
||||
this.clearCombatTarget(model);
|
||||
if (canMove) {
|
||||
this.moveToSlot(view, move, model, move.targetX);
|
||||
}
|
||||
this.moveToSlot(view, move, model, move.targetX);
|
||||
model.is_atking = false;
|
||||
}
|
||||
|
||||
if (canMove) {
|
||||
// 如果只在 Y 轴移动,也要播放 move 动画
|
||||
if (isChangingLane && view.status !== "move" && view.status !== "atk") {
|
||||
view.status_change("move");
|
||||
}
|
||||
} else {
|
||||
// 战斗阶段如果不移动,确保不在攻击时恢复 idle 状态
|
||||
if (!model.is_atking && view.status === "move") {
|
||||
view.status_change("idle");
|
||||
}
|
||||
// 如果只在 Y 轴移动,也要播放 move 动画
|
||||
if (isChangingLane && view.status !== "move" && view.status !== "atk") {
|
||||
view.status_change("move");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,14 +232,10 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
allAllies.sort((a, b) => {
|
||||
const attrsA = a.get(HeroAttrsComp);
|
||||
const attrsB = b.get(HeroAttrsComp);
|
||||
const priorityA = attrsA ? this.getCombatPriority(attrsA) : 0;
|
||||
const priorityB = attrsB ? this.getCombatPriority(attrsB) : 0;
|
||||
const priorityA = attrsA ? this.getFormationPriority(attrsA) : 0;
|
||||
const priorityB = attrsB ? this.getFormationPriority(attrsB) : 0;
|
||||
if (priorityA !== priorityB) return priorityB - priorityA;
|
||||
|
||||
const deadA = (attrsA?.dead && attrsA.dead.length > 0) ? 1 : 0;
|
||||
const deadB = (attrsB?.dead && attrsB.dead.length > 0) ? 1 : 0;
|
||||
if (deadA !== deadB) return deadB - deadA;
|
||||
|
||||
const lvA = attrsA?.lv ?? 1;
|
||||
const lvB = attrsB?.lv ?? 1;
|
||||
if (lvA !== lvB) return lvB - lvA;
|
||||
@@ -271,20 +247,48 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
return a.eid - b.eid;
|
||||
});
|
||||
|
||||
const slotIndex = Math.max(0, allAllies.findIndex(entity => entity === self));
|
||||
|
||||
// 优先中前(1) -> 上前(0) -> 下前(2) -> 中后(4) -> 上后(3) -> 下后(5)
|
||||
const slotPriority = [1, 0, 2, 4, 3, 5];
|
||||
const posIndex = slotPriority[slotIndex % 6];
|
||||
const pos = MissionHeroComp.HERO_POSITIONS[posIndex];
|
||||
|
||||
return { targetX: pos.x, targetY: pos.y };
|
||||
// allAllies 按优先级降序(索引 0 = 最高优先级 = 最靠右/最先接敌),
|
||||
// 反转为"从左侧起的排位"后再分配 X:最高优先级 → 最右
|
||||
const priorityRank = Math.max(0, allAllies.findIndex(entity => entity === self));
|
||||
const rankFromLeft = allAllies.length - 1 - priorityRank;
|
||||
const targetX = this.calcSlotX(rankFromLeft, allAllies.length);
|
||||
|
||||
return { targetX, targetY: BoxSet.GAME_LINE };
|
||||
}
|
||||
|
||||
// ==================== 编队站位(方案 A:单行横向分布) ====================
|
||||
/** 编队左端起点(最靠后/最后接敌) */
|
||||
private static readonly FORMATION_LEFT_X = -320;
|
||||
/** 编队右端终点(最靠前/最先接敌) */
|
||||
private static readonly FORMATION_RIGHT_X = 100;
|
||||
/** 固定步进间距(人数较少时按此从左侧逐位右排) */
|
||||
private static readonly FORMATION_STEP_X = 60;
|
||||
|
||||
/**
|
||||
* 计算某个槽位的目标 X。
|
||||
* Why: 单行站位避免横版拥挤——人少时按 60 固定步进从 -320 起步逐位右排(保持松散),
|
||||
* 人多到 60 步进装不下时,改为在 [-320, 100] 区间均分(利用全宽)。
|
||||
* @param rankFromLeft 从左侧起的排位(0=最靠左/最后,越大越靠右/越先接敌)
|
||||
* @param total 当前存活英雄总数
|
||||
*/
|
||||
private calcSlotX(rankFromLeft: number, total: number): number {
|
||||
const left = MoveSystem.FORMATION_LEFT_X;
|
||||
const right = MoveSystem.FORMATION_RIGHT_X;
|
||||
const step = MoveSystem.FORMATION_STEP_X;
|
||||
if (total <= 1) return left;
|
||||
// 固定步进能容纳的最大人数:相邻 60,且最右不超过 right
|
||||
const maxStepCount = Math.floor((right - left) / step) + 1;
|
||||
if (total <= maxStepCount) {
|
||||
return left + rankFromLeft * step;
|
||||
}
|
||||
// 超出后均分整段区间(含左右端点)
|
||||
return left + (right - left) * (rankFromLeft / (total - 1));
|
||||
}
|
||||
|
||||
private moveToSlot(view: HeroViewComp, move: MoveComp, model: HeroAttrsComp, targetX: number) {
|
||||
const currentX = view.node.position.x;
|
||||
const currentY = view.node.position.y;
|
||||
|
||||
|
||||
// 当 X 和 Y 都到达目标时,才算真正到达
|
||||
if (Math.abs(currentX - targetX) <= 2 && Math.abs(currentY - move.baseY) <= 2) {
|
||||
view.node.setPosition(targetX, move.baseY, 0);
|
||||
@@ -307,7 +311,7 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
const moveMaxX = Math.max(cfg.moveBackX, cfg.moveFrontX);
|
||||
const currentX = view.node.position.x;
|
||||
const currentY = view.node.position.y;
|
||||
|
||||
|
||||
const delta = speed * this.dt * direction;
|
||||
let newX = view.node.position.x + delta;
|
||||
if (currentX < moveMinX && direction < 0) {
|
||||
@@ -345,12 +349,30 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
view.status_change("move");
|
||||
}
|
||||
|
||||
private getCombatPriority(model: HeroAttrsComp): number {
|
||||
/** 数值越大越靠前:近战 > 中程 > 远程 */
|
||||
/**
|
||||
* 编队站位优先级(数值越大越靠前/越靠右)。
|
||||
* Why: 阵容职能决定承伤顺序——死亡触发英雄需最先阵亡以触发遗志,
|
||||
* 其次坦克承伤,再次战士/刺客,远程射手/法师/辅助依次靠后保护。
|
||||
* 排序档位:死亡触发 > 坦克 > 战士 > 刺客 > 射手 > 法师 > 辅助
|
||||
*/
|
||||
private getFormationPriority(model: HeroAttrsComp): number {
|
||||
// 死亡触发英雄最高优先:需要先死以发动遗志/献祭
|
||||
if (model.dead && Object.keys(model.dead).length > 0) return 100;
|
||||
if (model.role !== undefined) {
|
||||
switch (model.role) {
|
||||
case HRole.Tank: return 90;
|
||||
case HRole.Warrior: return 80;
|
||||
case HRole.Assassin: return 70;
|
||||
case HRole.Archer: return 60;
|
||||
case HRole.Mage: return 50;
|
||||
case HRole.Support: return 40;
|
||||
}
|
||||
}
|
||||
// 兜底:未配置 role 时按攻击定位(近战 > 中程 > 远程)
|
||||
const rangeType = model.type as HType.Melee | HType.Mid | HType.Long;
|
||||
if (rangeType === HType.Melee) return 3;
|
||||
if (rangeType === HType.Mid) return 2;
|
||||
return 1;
|
||||
if (rangeType === HType.Melee) return 30;
|
||||
if (rangeType === HType.Mid) return 20;
|
||||
return 10;
|
||||
}
|
||||
|
||||
private resolveCombatRange(model: HeroAttrsComp, defaultMin: number, defaultMax: number): [number, number] {
|
||||
@@ -364,13 +386,13 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
private findNearestEnemy(entity: ecs.Entity): HeroViewComp | null {
|
||||
const currentView = entity.get(HeroViewComp);
|
||||
if (!currentView?.node) return null;
|
||||
|
||||
|
||||
const currentPos = currentView.node.position;
|
||||
const myFac = entity.get(HeroAttrsComp).fac;
|
||||
|
||||
|
||||
let nearest: HeroViewComp | null = null;
|
||||
let minDis = Infinity;
|
||||
|
||||
|
||||
/** 遍历筛出最近敌人:以 X 轴距离为主,Y 轴距离作为同排的决胜权重,使角色优先攻击同路的敌人 */
|
||||
ecs.query(this.getHeroViewMatcher()).forEach(e => {
|
||||
const m = e.get(HeroAttrsComp);
|
||||
@@ -405,7 +427,7 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
const actorView = e.get(HeroViewComp);
|
||||
if (!attrs || !actorView?.node || attrs.is_dead) return;
|
||||
if (attrs.fac !== FacSet.HERO && attrs.fac !== FacSet.MON) return;
|
||||
|
||||
|
||||
if (actorView.node.parent !== actorRoot) {
|
||||
actorView.node.parent = actorRoot;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user