refactor(hero): 移除天赋系统和相关属性,简化英雄架构
- 删除 SCDSystem、HeroAttrSystem 等独立系统,将功能整合到现有组件 - 移除 TalComp 天赋组件及相关配置(TalSet、AttrSet、CardSet) - 清理 HeroAttrs 中未使用的属性枚举,保留核心战斗属性 - 简化 Hero 实体创建逻辑,不再为主角挂载天赋组件 - 移除 SingletonModuleComp 中与天赋、经验、收集相关的数据管理
This commit is contained in:
@@ -5,12 +5,7 @@ import { GameMap } from "../map/GameMap";
|
||||
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
||||
import { WxCloudApi } from "../wx_clound_client_api/WxCloudApi";
|
||||
import { GameEvent } from "./config/GameEvent";
|
||||
import * as exp from "constants";
|
||||
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
|
||||
import { Attrs, GameScoreStats } from "./config/HeroAttrs";
|
||||
import { count, time } from "console";
|
||||
import { getLevelExp } from "../map/RogueConfig";
|
||||
import { FightSet } from "./config/GameSet";
|
||||
import { GameScoreStats } from "./config/HeroAttrs";
|
||||
import { mLogger } from "./Logger";
|
||||
/**
|
||||
* 用远程数据覆盖本地数据(统一方法)
|
||||
@@ -107,126 +102,13 @@ export class SingletonModuleComp extends ecs.Comp {
|
||||
elite_kill_count: 0, // 精英怪击杀数量
|
||||
boss_kill_count: 0, // Boss击杀数
|
||||
} as GameScoreStats,
|
||||
hero:{
|
||||
name:'',
|
||||
path:'',
|
||||
as:0,
|
||||
type:0,
|
||||
lv:1,
|
||||
exp:0,
|
||||
exp_max:100,
|
||||
exp_pre:0,
|
||||
hp:50,
|
||||
hp_max:100,
|
||||
mp:50,
|
||||
mp_max:100,
|
||||
def:0,
|
||||
ap:0,
|
||||
crt:0,
|
||||
dodge:0,
|
||||
skills:[],
|
||||
buff:[],
|
||||
tal:[],
|
||||
info:'',
|
||||
},
|
||||
// 收集记录
|
||||
collection: {
|
||||
talents: {} as Record<number, number>,
|
||||
skill: {uuid:0,count:0},
|
||||
friend:{uuid:0,count:0},
|
||||
},
|
||||
|
||||
gold: 0, // 金币数据(MVVM绑定字段)
|
||||
};
|
||||
|
||||
|
||||
|
||||
// 全局属性加成 {attrIndex: [value, count]}
|
||||
global_attrs: Record<number, [number, number]> = {
|
||||
[Attrs.AP]: [1, 0], // 攻击力
|
||||
[Attrs.HP_MAX]: [10, 10], // 生命上限
|
||||
[Attrs.DEF]: [1, 0], // 防御
|
||||
[Attrs.DODGE]: [1, 0], // 闪避率
|
||||
[Attrs.CRITICAL]: [1, 0], // 暴击率
|
||||
[Attrs.STUN_CHANCE]: [1, 0], // 眩晕率
|
||||
[Attrs.WFUNY]: [1, 0], // 风怒率
|
||||
};
|
||||
|
||||
/** 主角实体引用 */
|
||||
// role: ecs.Entity | null = null;
|
||||
|
||||
/**
|
||||
* 记录天赋获取
|
||||
* @param id 天赋ID
|
||||
*/
|
||||
addTalentRecord(id: number) {
|
||||
if (!this.vmdata.collection.talents[id]) {
|
||||
this.vmdata.collection.talents[id] = 0;
|
||||
}
|
||||
this.vmdata.collection.talents[id]++;
|
||||
mLogger.log(this.debugMode, 'SMC', `[SMC] 记录天赋获取: ID=${id}, 次数=${this.vmdata.collection.talents[id]}`);
|
||||
oops.message.dispatchEvent(GameEvent.UpdateCollection);
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录技能获取
|
||||
* @param id 技能ID
|
||||
*/
|
||||
addSkillRecord(id: number) {
|
||||
if (!this.vmdata.collection.skill.uuid) {
|
||||
this.vmdata.collection.skill.uuid = id;
|
||||
}
|
||||
this.vmdata.collection.skill.count++;
|
||||
mLogger.log(this.debugMode, 'SMC', `[SMC] 记录技能获取: ID=${id}, 次数=${this.vmdata.collection.skill.count}`);
|
||||
oops.message.dispatchEvent(GameEvent.UpdateCollection);
|
||||
}
|
||||
/**
|
||||
* 记录好友获取
|
||||
* @param id 好友ID
|
||||
*/
|
||||
addFriendHero(id: number) {
|
||||
if (!this.vmdata.collection.friend.uuid) {
|
||||
this.vmdata.collection.friend.uuid = id;
|
||||
}
|
||||
this.vmdata.collection.friend.count++;
|
||||
mLogger.log(this.debugMode, 'SMC', `[SMC] 记录好友获取: ID=${id}, 次数=${this.vmdata.collection.friend.count}`);
|
||||
oops.message.dispatchEvent(GameEvent.UpdateCollection);
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加经验并处理升级逻辑
|
||||
* @param exp 获得的经验值
|
||||
*/
|
||||
addExp(exp: number) {
|
||||
if (exp <= 0) return;
|
||||
|
||||
const h = this.vmdata.hero;
|
||||
// 确保等级至少为1
|
||||
if (h.lv < 1) h.lv = 1;
|
||||
// 确保经验上限正确
|
||||
if (h.exp_max <= 0) h.exp_max = getLevelExp(h.lv);
|
||||
|
||||
h.exp += exp;
|
||||
|
||||
// 检查升级
|
||||
let isLevelUp = false;
|
||||
while (h.exp >= h.exp_max) {
|
||||
h.exp -= h.exp_max;
|
||||
h.lv++;
|
||||
isLevelUp = true;
|
||||
|
||||
// 更新下一级所需经验
|
||||
h.exp_max = getLevelExp(h.lv);
|
||||
|
||||
mLogger.log(this.debugMode, 'SMC', `[SMC] 升级! Lv.${h.lv - 1} -> Lv.${h.lv}, 下级所需: ${h.exp_max}`);
|
||||
}
|
||||
h.exp_pre=Math.round(h.exp/h.exp_max*100)
|
||||
if (isLevelUp) {
|
||||
mLogger.log(this.debugMode, 'SMC', `[SMC] 触发升级事件: Lv.${h.lv}`);
|
||||
// 发送升级事件
|
||||
oops.message.dispatchEvent(GameEvent.CanUpdateLv, { lv: h.lv });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
vmAdd() {
|
||||
VM.add(this.vmdata, "data");
|
||||
// mLogger.log(this.debugMode, 'SMC', "[MissionComp]局内数据初始化",smc.vmdata.mission_data)
|
||||
@@ -332,19 +214,7 @@ export class SingletonModuleComp extends ecs.Comp {
|
||||
|
||||
return true
|
||||
}
|
||||
// 设置单个出战英雄
|
||||
updateFihgtHero(heroId: number) {
|
||||
this.fight_hero = heroId;
|
||||
if(this.isWxClient()){
|
||||
let res = this.updateCloudData()
|
||||
if (res){
|
||||
return true
|
||||
}else{
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
updateGold(gold:number, is_sync: boolean = true){
|
||||
this.vmdata.gold += gold;
|
||||
if(this.isWxClient() && is_sync){
|
||||
@@ -361,56 +231,6 @@ export class SingletonModuleComp extends ecs.Comp {
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新主角英雄数据到 VM
|
||||
* @param heroAttrs 英雄属性组件
|
||||
*/
|
||||
updateHeroInfo(heroAttrs: HeroAttrsComp) {
|
||||
if (!heroAttrs || !heroAttrs.is_master) return;
|
||||
|
||||
const h = this.vmdata.hero;
|
||||
|
||||
// 基础信息
|
||||
h.name = heroAttrs.hero_name;
|
||||
h.type = heroAttrs.type;
|
||||
|
||||
// 防止 ECS 旧数据覆盖 VM 新数据 (如果 VM 里的等级更高,说明刚升级还没同步到 ECS)
|
||||
if (heroAttrs.lv > h.lv) {
|
||||
h.lv = heroAttrs.lv;
|
||||
} else if (h.lv > heroAttrs.lv) {
|
||||
// 此时应该反向同步?或者等待 CanUpdateLv 事件处理
|
||||
// 这里暂时保持 VM 的高等级,不被 ECS 覆盖
|
||||
} else {
|
||||
h.lv = heroAttrs.lv;
|
||||
}
|
||||
|
||||
// 动态属性
|
||||
h.hp = Math.floor(heroAttrs.hp);
|
||||
h.mp = Math.floor(heroAttrs.mp);
|
||||
|
||||
// 计算属性
|
||||
h.hp_max = Math.floor(heroAttrs.Attrs[Attrs.HP_MAX] || 0);
|
||||
h.mp_max = Math.floor(heroAttrs.Attrs[Attrs.MP_MAX] || 0);
|
||||
h.def = Math.floor(heroAttrs.Attrs[Attrs.DEF] || 0);
|
||||
h.ap = Math.floor(heroAttrs.Attrs[Attrs.AP] || 0);
|
||||
h.dodge = Math.floor(heroAttrs.Attrs[Attrs.DODGE] || 0);
|
||||
h.crt = Math.floor(heroAttrs.Attrs[Attrs.CRITICAL] || 0);
|
||||
h.as = Math.floor(heroAttrs.Attrs[Attrs.AS] || 0);
|
||||
|
||||
// 强制触发 VM 更新
|
||||
// 如果 VM 监听的是 smc.vmdata.hero 的属性变化,上面的赋值应该有效。
|
||||
// 但如果 UI 绑定的是 hero 整体对象,或者因为深层监听问题,可能需要手动通知。
|
||||
// 为了保险,我们可以重新赋值一次(如果是对象引用可能不会触发),或者使用 VM 提供的 set 方法
|
||||
// 这里尝试直接重新赋值整个对象属性来触发更新,或者假设 VM 已经处理好了深层监听。
|
||||
// 如果 UI 没变,可能是 VM 没有检测到深层属性变化。
|
||||
|
||||
// 尝试手动通知或重新赋值关键路径
|
||||
// 注意:Oops Framework 的 VM 通常支持对象属性修改的监听,前提是初始化时已经建立了监听。
|
||||
// 这里我们尝试显式调用 VM.modify 来通知更新(如果有这个 API),或者重新赋值给 vmdata
|
||||
|
||||
// 方案:重新设置 vmdata.hero 来触发根节点的更新通知
|
||||
this.vmdata.hero = h;
|
||||
}
|
||||
error(){
|
||||
oops.gui.toast("数据处理异常,请重试或重新登录")
|
||||
}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
import { Attrs } from "./HeroAttrs";
|
||||
|
||||
export interface AttrInfo {
|
||||
uuid: number;
|
||||
icon:string; // 属性图标
|
||||
attr: Attrs; // 属性类型
|
||||
value: number;// 属性值
|
||||
desc: string;// 属性描述
|
||||
isSpecial: boolean;// 是否为特殊属性
|
||||
name?: string;// 属性备注
|
||||
}
|
||||
export const AttrCards: Record<number, AttrInfo> = {
|
||||
//*一阶 */
|
||||
2001:{uuid:2001, icon:"1020", attr: Attrs.AP, value: 20, desc: "攻击力 +20%", isSpecial: false,name: "攻击" },
|
||||
2002:{uuid:2002, icon:"1020", attr: Attrs.HP_MAX, value: 20, desc: "生命上限 +20%", isSpecial: false,name: "生命" },
|
||||
2003:{uuid:2003, icon:"1020", attr: Attrs.DEF, value: 20, desc: "防御力 +20%", isSpecial: false,name: "防御" },
|
||||
2004:{uuid:2004, icon:"1020", attr: Attrs.AS, value: 5, desc: "攻击速度 +5%", isSpecial: false,name: "攻速" },
|
||||
2005:{uuid:2007, icon:"1020", attr: Attrs.CRITICAL_DMG, value: 10, desc: "暴击伤害 +10%", isSpecial: true,name: "爆伤" },
|
||||
2006:{uuid:2013, icon:"1020", attr: Attrs.DODGE, value: 5, desc: "闪避率 +5%", isSpecial: true,name: "闪避" },
|
||||
|
||||
}
|
||||
|
||||
export interface PotionInfo extends AttrInfo {
|
||||
duration: number; // 持续时间
|
||||
}
|
||||
|
||||
export const PotionCards: Record<number, PotionInfo> = {
|
||||
// 持续时间20秒的强力药水
|
||||
3001: { uuid: 3001, icon: "1020", attr: Attrs.AP, value: 100, desc: "15秒内攻击力 +100%", isSpecial: false,name: "狂暴药水", duration: 15 },
|
||||
3002: { uuid: 3002, icon: "1020", attr: Attrs.AS, value: 100, desc: "15秒内攻速 +100%", isSpecial: false,name: "急速药水", duration: 15 },
|
||||
3003: { uuid: 3003, icon: "1020", attr: Attrs.DEF, value: 100, desc: "15秒内防御 +100%", isSpecial: false,name: "防御药水", duration: 15 },
|
||||
3004: { uuid: 3004, icon: "1020", attr: Attrs.SPEED, value: 100, desc: "15秒内移速 +100%", isSpecial: false,name: "神行药水", duration: 15 },
|
||||
|
||||
// 持续时间60秒的普通药水
|
||||
3005: { uuid: 3005, icon: "1020", attr: Attrs.AP, value: 25, desc: "60秒内攻击力 +25%", isSpecial: false,name: "力量药剂", duration: 60 },
|
||||
3006: { uuid: 3006, icon: "1020", attr: Attrs.AS, value: 25, desc: "60秒内攻速 +25%", isSpecial: false,name: "敏捷药剂", duration: 60 },
|
||||
3007: { uuid: 3007, icon: "1020", attr: Attrs.DEF, value: 25, desc: "60秒内防御 +25%", isSpecial: false,name: "护甲药剂", duration: 60 },
|
||||
3008: { uuid: 3008, icon: "1020", attr: Attrs.SPEED, value: 25, desc: "60秒内移速 +25%", isSpecial: false,name: "轻灵药剂", duration: 60 },
|
||||
|
||||
// 闪避药水
|
||||
3009: { uuid: 3009, icon: "1020", attr: Attrs.DODGE, value: 100, desc: "20秒内闪避率 +100%", isSpecial: false,name: "残影药水", duration: 15 },
|
||||
3010: { uuid: 3010, icon: "1020", attr: Attrs.DODGE, value: 25, desc: "60秒内闪避率 +25%", isSpecial: false,name: "闪避药剂", duration: 60 },
|
||||
// 回血药水
|
||||
3011: { uuid: 3011, icon: "1020", attr: Attrs.HP_REGEN, value: 30, desc: "每5秒回血生命最大值的30%", isSpecial: false,name: "生命药水", duration: 15 },
|
||||
3012: { uuid: 3012, icon: "1020", attr: Attrs.HP_REGEN, value: 10, desc: "每5秒回血生命最大值的10%", isSpecial: false,name: "回春药剂", duration: 60 },
|
||||
};
|
||||
|
||||
export const CanSelectAttrs: Record<number, number[]> = {
|
||||
// 1阶属性
|
||||
1: [2001, 2002, 2003, 2004, 2005, 2006],
|
||||
};
|
||||
|
||||
export const CanSelectPotions: Record<number, number[]> = {
|
||||
// 全药水
|
||||
1: [3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011, 3012]
|
||||
};
|
||||
@@ -1,372 +0,0 @@
|
||||
import { AttrCards, AttrInfo, CanSelectAttrs, PotionCards, CanSelectPotions } from "./AttrSet";
|
||||
import { talConf, ItalConf, CanSelectTalents } from "./TalSet";
|
||||
import { SkillSet, SkillConfig, CanSelectSkills } from "./SkillSet";
|
||||
import { HeroInfo, heroInfo, CanSelectHeros } from "./heroSet";
|
||||
import { CardType, CardKind } from "./GameSet";
|
||||
|
||||
/**
|
||||
* 获取等级对应的奖励类型
|
||||
* @param level 当前等级
|
||||
* @returns 奖励类型 CardType
|
||||
*/
|
||||
export function getLevelRewardType(level: number): CardType {
|
||||
switch (level) {
|
||||
case 2: return CardType.Talent;
|
||||
case 3: return CardType.Attr;
|
||||
case 4: return CardType.Attr;
|
||||
case 5: return CardType.Talent;
|
||||
case 6: return CardType.Attr;
|
||||
case 7: return CardType.Attr;
|
||||
case 8: return CardType.Attr;
|
||||
case 9: return CardType.Attr;
|
||||
case 10: return CardType.Talent;
|
||||
case 11: return CardType.Attr;
|
||||
case 12: return CardType.Attr;
|
||||
case 13: return CardType.Attr;
|
||||
case 14: return CardType.Attr;
|
||||
case 15: return CardType.Talent;
|
||||
case 16: return CardType.Attr;
|
||||
case 17: return CardType.Attr;
|
||||
case 18: return CardType.Attr;
|
||||
case 19: return CardType.Attr;
|
||||
case 20: return CardType.Attr;
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一卡牌信息接口 (用于UI显示和逻辑处理)
|
||||
*/
|
||||
export interface ICardInfo {
|
||||
uuid: number;
|
||||
type: CardType;
|
||||
kind: CardKind;
|
||||
name: string;
|
||||
desc: string;
|
||||
icon: string;
|
||||
weight: number; // 抽取权重
|
||||
tag?: string; // 标签 (如 "special" 表示特殊属性)
|
||||
payload: any; // 原始配置数据
|
||||
}
|
||||
|
||||
/**
|
||||
* 具体卡牌配置项 (内部使用)
|
||||
*/
|
||||
export interface IPoolItem {
|
||||
id: number; // 卡牌UUID
|
||||
weight: number; // 该卡牌在池中的权重
|
||||
}
|
||||
|
||||
/**
|
||||
* 等级池配置项
|
||||
* 仅定义类型和权重,具体卡牌内容由各模块的 CanSelectXXX 配置决定
|
||||
*/
|
||||
export interface IPoolConfig {
|
||||
type: CardType; // 卡牌类型
|
||||
poolWeight: number; // 该类型池被选中的概率权重
|
||||
tag?: string; // 辅助筛选(从全池中筛选带tag的,如 "special")
|
||||
}
|
||||
|
||||
// 默认单卡权重
|
||||
const DEFAULT_CARD_WEIGHT = 100;
|
||||
|
||||
/**
|
||||
* 1-20 级卡牌池配置表
|
||||
* 定义每个等级可能出现的卡牌类型及其权重
|
||||
*/
|
||||
export const LevelPoolConfigs: Record<number, IPoolConfig[]> = {
|
||||
1: [{ type: CardType.Skill, poolWeight: 100 }],
|
||||
2: [{ type: CardType.Attr, poolWeight: 100 }], // 常规属性
|
||||
3: [{ type: CardType.Talent, poolWeight: 50 }, { type: CardType.Attr, poolWeight: 50, tag: "special" }], // 天赋或特殊属性
|
||||
4: [{ type: CardType.Attr, poolWeight: 100 }],
|
||||
5: [{ type: CardType.Talent, poolWeight: 100 }],
|
||||
6: [{ type: CardType.Partner, poolWeight: 100 }], // 伙伴节点
|
||||
7: [{ type: CardType.Attr, poolWeight: 80 }, { type: CardType.Skill, poolWeight: 20 }],
|
||||
8: [{ type: CardType.Attr, poolWeight: 80 }, { type: CardType.Skill, poolWeight: 20 }],
|
||||
9: [{ type: CardType.Attr, poolWeight: 50, tag: "special" }, { type: CardType.Talent, poolWeight: 50 }],
|
||||
10: [{ type: CardType.Talent, poolWeight: 100 }],
|
||||
11: [{ type: CardType.Attr, poolWeight: 70 }, { type: CardType.Skill, poolWeight: 30 }],
|
||||
12: [{ type: CardType.Attr, poolWeight: 70 }, { type: CardType.Skill, poolWeight: 30 }],
|
||||
13: [{ type: CardType.Attr, poolWeight: 100 }],
|
||||
14: [{ type: CardType.Attr, poolWeight: 50, tag: "special" }, { type: CardType.Talent, poolWeight: 50 }],
|
||||
15: [{ type: CardType.Talent, poolWeight: 100 }],
|
||||
16: [{ type: CardType.Attr, poolWeight: 60 }, { type: CardType.Skill, poolWeight: 40 }],
|
||||
17: [{ type: CardType.Attr, poolWeight: 60 }, { type: CardType.Skill, poolWeight: 40 }],
|
||||
18: [{ type: CardType.Attr, poolWeight: 50, tag: "special" }, { type: CardType.Talent, poolWeight: 50 }],
|
||||
19: [{ type: CardType.Attr, poolWeight: 100 }],
|
||||
20: [{ type: CardType.Talent, poolWeight: 100 }],
|
||||
};
|
||||
|
||||
// ========== 卡牌池构建逻辑 ==========
|
||||
|
||||
/**
|
||||
* 获取指定类型的卡牌信息(不含权重,仅基础信息)
|
||||
*/
|
||||
function getCardBaseInfo(type: CardType, uuid: number): ICardInfo | null {
|
||||
let baseInfo: any = null;
|
||||
let name = "";
|
||||
let desc = "";
|
||||
let icon = "";
|
||||
let kind = CardKind.Attr;
|
||||
let tag = undefined;
|
||||
|
||||
switch (type) {
|
||||
case CardType.Attr:
|
||||
baseInfo = AttrCards[uuid];
|
||||
if (!baseInfo) return null;
|
||||
name = baseInfo.name || "属性";
|
||||
desc = baseInfo.desc;
|
||||
icon = baseInfo.icon;
|
||||
kind = CardKind.Attr;
|
||||
tag = baseInfo.isSpecial ? "special" : undefined;
|
||||
break;
|
||||
case CardType.Talent:
|
||||
baseInfo = talConf[uuid];
|
||||
if (!baseInfo) return null;
|
||||
name = baseInfo.name;
|
||||
desc = baseInfo.desc;
|
||||
icon = baseInfo.icon;
|
||||
kind = baseInfo.kind;
|
||||
break;
|
||||
case CardType.Skill:
|
||||
baseInfo = SkillSet[uuid];
|
||||
if (!baseInfo) return null;
|
||||
name = baseInfo.name;
|
||||
desc = baseInfo.info;
|
||||
icon = baseInfo.icon;
|
||||
kind = CardKind.Skill;
|
||||
break;
|
||||
case CardType.Partner:
|
||||
baseInfo = HeroInfo[uuid];
|
||||
if (!baseInfo) return null;
|
||||
name = baseInfo.name;
|
||||
desc = baseInfo.info;
|
||||
icon = baseInfo.icon;
|
||||
kind = CardKind.Partner;
|
||||
break;
|
||||
case CardType.Potion:
|
||||
baseInfo = PotionCards[uuid];
|
||||
if (!baseInfo) return null;
|
||||
name = baseInfo.name || "药水";
|
||||
desc = baseInfo.desc;
|
||||
icon = baseInfo.icon;
|
||||
kind = CardKind.Buff; // 药水归类为 Buff 类型的卡片显示
|
||||
break;
|
||||
}
|
||||
|
||||
return {
|
||||
uuid,
|
||||
type,
|
||||
kind,
|
||||
name,
|
||||
desc,
|
||||
icon,
|
||||
weight: 0, // 基础信息不包含权重,权重由配置决定
|
||||
tag,
|
||||
payload: baseInfo
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定类型的全量池
|
||||
* 自动累加所有 <= level 的配置项
|
||||
* @param type 卡牌类型
|
||||
* @param level 当前等级
|
||||
*/
|
||||
function getDefaultPool(type: CardType, level: number = 1): IPoolItem[] {
|
||||
const items: IPoolItem[] = [];
|
||||
let configMap: Record<number, number[]> | null = null;
|
||||
let defaultWeight = 100;
|
||||
|
||||
switch (type) {
|
||||
case CardType.Attr:
|
||||
configMap = CanSelectAttrs;
|
||||
defaultWeight = 100;
|
||||
break;
|
||||
case CardType.Talent:
|
||||
configMap = CanSelectTalents;
|
||||
defaultWeight = 50;
|
||||
break;
|
||||
case CardType.Skill:
|
||||
configMap = CanSelectSkills;
|
||||
defaultWeight = 80;
|
||||
break;
|
||||
case CardType.Partner:
|
||||
configMap = CanSelectHeros;
|
||||
defaultWeight = 100;
|
||||
break;
|
||||
case CardType.Potion:
|
||||
configMap = CanSelectPotions;
|
||||
defaultWeight = 100;
|
||||
break;
|
||||
}
|
||||
|
||||
if (configMap) {
|
||||
// 1. 找到符合条件的最大等级 Key (<= level 且 != 99)
|
||||
let targetKey = -1;
|
||||
let maxLv = -1;
|
||||
|
||||
Object.keys(configMap).forEach(lvlStr => {
|
||||
const lv = parseInt(lvlStr);
|
||||
if (lv !== 99 && lv <= level) {
|
||||
if (lv > maxLv) {
|
||||
maxLv = lv;
|
||||
targetKey = lv;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 2. 如果找到了目标等级配置,则使用该配置
|
||||
if (targetKey !== -1 && configMap[targetKey]) {
|
||||
const ids = configMap[targetKey];
|
||||
ids.forEach(id => {
|
||||
items.push({ id, weight: defaultWeight });
|
||||
});
|
||||
}
|
||||
// 3. 如果没找到(等级过低),且存在 99 号默认配置,则使用 99 号配置
|
||||
else if (configMap[99]) {
|
||||
configMap[99].forEach(id => {
|
||||
items.push({ id, weight: defaultWeight });
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// 兜底逻辑:如果该类型没有配置表 (理论上不应发生,除非新增类型未配置)
|
||||
// 这里保留原有的全量兜底逻辑作为最后的防线
|
||||
switch (type) {
|
||||
case CardType.Attr:
|
||||
Object.keys(AttrCards).forEach(key => items.push({ id: Number(key), weight: 100 }));
|
||||
break;
|
||||
case CardType.Talent:
|
||||
Object.keys(talConf).forEach(key => items.push({ id: Number(key), weight: 50 }));
|
||||
break;
|
||||
case CardType.Skill:
|
||||
Object.keys(SkillSet).forEach(key => items.push({ id: Number(key), weight: 80 }));
|
||||
break;
|
||||
case CardType.Partner:
|
||||
Object.keys(HeroInfo).forEach(key => {
|
||||
const id = Number(key);
|
||||
if (id < 5200) items.push({ id, weight: 100 });
|
||||
});
|
||||
break;
|
||||
case CardType.Potion:
|
||||
Object.keys(PotionCards).forEach(key => items.push({ id: Number(key), weight: 100 }));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据等级获取随机卡牌选项
|
||||
* @param level 当前等级
|
||||
* @param count 选项数量 (默认3个)
|
||||
* @param excludeUuids 排除的卡牌UUID列表 (用于去重或排除已拥有)
|
||||
* @param forcedType 强制指定卡牌类型 (用于特殊获取,如商店、技能书等)
|
||||
* @param preferredAttrs 偏好的属性类型列表 (用于增加权重)
|
||||
*/
|
||||
export function getCardOptions(level: number, count: number = 3, excludeUuids: number[] = [], forcedType?: CardType, preferredAttrs: number[] = []): ICardInfo[] {
|
||||
// 1. 确定类型:强制指定 > 默认为属性
|
||||
const type = forcedType !== undefined ? forcedType : CardType.Attr;
|
||||
|
||||
const result: ICardInfo[] = [];
|
||||
const excludeSet = new Set(excludeUuids);
|
||||
|
||||
// 2. 获取该类型的候选池
|
||||
const rawItems = getDefaultPool(type, level);
|
||||
|
||||
// 3. 构建候选列表(包含完整信息)
|
||||
const candidates: ICardInfo[] = [];
|
||||
for (const item of rawItems) {
|
||||
if (excludeSet.has(item.id)) continue;
|
||||
|
||||
const info = getCardBaseInfo(type, item.id);
|
||||
if (info) {
|
||||
info.weight = item.weight;
|
||||
|
||||
// 如果是属性卡,且该属性在偏好列表中,增加权重
|
||||
if (type === CardType.Attr && preferredAttrs.length > 0) {
|
||||
// AttrCards 的 payload 就是 AttrInfo,包含 attr 字段
|
||||
if (info.payload && preferredAttrs.includes(info.payload.attr)) {
|
||||
// 增加权重,这里设置为 2 倍
|
||||
info.weight *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
candidates.push(info);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 抽取
|
||||
for (let i = 0; i < count; i++) {
|
||||
if (candidates.length === 0) break;
|
||||
|
||||
const card = weightedRandomCard(candidates);
|
||||
if (card) {
|
||||
result.push(card);
|
||||
// 移除已选,防止重复
|
||||
const idx = candidates.indexOf(card);
|
||||
if (idx > -1) candidates.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 兜底逻辑:如果数量不足,且当前类型不是属性,则用属性卡补齐
|
||||
if (result.length < count && type !== CardType.Attr) {
|
||||
const attrItems = getDefaultPool(CardType.Attr); // 兜底可以用全量属性池
|
||||
for (const item of attrItems) {
|
||||
if (result.length >= count) break;
|
||||
|
||||
// 检查是否已存在(ID去重)
|
||||
if (excludeSet.has(item.id) || result.some(r => r.uuid === item.id)) continue;
|
||||
|
||||
const info = getCardBaseInfo(CardType.Attr, item.id);
|
||||
if (info) {
|
||||
info.weight = 100;
|
||||
result.push(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shuffleArray(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// ========== 工具函数 ==========
|
||||
|
||||
function weightedRandomPool(configs: IPoolConfig[]): IPoolConfig | null {
|
||||
if (!configs || configs.length === 0) return null;
|
||||
|
||||
const totalWeight = configs.reduce((sum, item) => sum + item.poolWeight, 0);
|
||||
let randomVal = Math.random() * totalWeight;
|
||||
|
||||
for (const config of configs) {
|
||||
randomVal -= config.poolWeight;
|
||||
if (randomVal <= 0) {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
return configs[configs.length - 1];
|
||||
}
|
||||
|
||||
function weightedRandomCard(cards: ICardInfo[]): ICardInfo | null {
|
||||
if (!cards || cards.length === 0) return null;
|
||||
|
||||
const totalWeight = cards.reduce((sum, item) => sum + item.weight, 0);
|
||||
let randomVal = Math.random() * totalWeight;
|
||||
|
||||
for (const card of cards) {
|
||||
randomVal -= card.weight;
|
||||
if (randomVal <= 0) {
|
||||
return card;
|
||||
}
|
||||
}
|
||||
return cards[cards.length - 1];
|
||||
}
|
||||
|
||||
function shuffleArray(array: any[]) {
|
||||
for (let i = array.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[array[i], array[j]] = [array[j], array[i]];
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,6 @@ export enum BType {
|
||||
export enum NeAttrs {
|
||||
IN_FROST = 0, // 冰冻状态
|
||||
IN_STUN = 1, // 眩晕状态
|
||||
IN_BURN = 2, // 灼烧状态
|
||||
IN_POISON = 3, // 中毒状态
|
||||
}
|
||||
|
||||
// ========== 属性枚举 ==========
|
||||
@@ -26,53 +24,27 @@ export enum NeAttrs {
|
||||
export enum Attrs {
|
||||
// ========== 基础生存属性 (0-9) ==========
|
||||
HP_MAX = 0, // 最大生命值
|
||||
MP_MAX = 1, // 最大魔法值
|
||||
SHIELD_MAX = 2, // 最大护盾值
|
||||
HP_REGEN = 3, // 生命回复
|
||||
MP_REGEN = 4, // 魔法回复
|
||||
LUCK = 5, // 幸运值
|
||||
SPEED = 3, // 移动速度
|
||||
|
||||
// ========== 攻击属性 (10-19) ==========
|
||||
AP = 10, // 攻击力
|
||||
DIS = 12, // 攻击距离
|
||||
AS = 13, // 攻击速度(减少技能skills[0]CD)
|
||||
SS = 14, // 技能速度 (减少skills[0] 以外的cd)
|
||||
SKILL_DURATION = 15, // 技能持续时间
|
||||
AREA_OF_EFFECT = 16, // 作用范围
|
||||
|
||||
// ========== 防御属性 (20-29) ==========
|
||||
DEF = 20, // 防御 伤害减免
|
||||
DODGE = 22, // 闪避率
|
||||
THORNS = 25, // 反伤
|
||||
CRITICAL_RES = 26, // 暴击抗性
|
||||
CON_RES = 27, // 控制抗性
|
||||
|
||||
// ========== 暴击与命中属性 (30-39) ==========
|
||||
CRITICAL = 30, // 暴击率
|
||||
CRITICAL_DMG = 31, // 暴击伤害
|
||||
HIT = 32, // 命中率
|
||||
|
||||
|
||||
// ========== 特殊效果属性 (50-59) ==========
|
||||
LIFESTEAL = 50, // 吸血比率
|
||||
MANASTEAL = 51, // 吸蓝比率
|
||||
FREEZE_CHANCE = 52, // 冰冻概率
|
||||
BURN_CHANCE = 53, // 燃烧概率
|
||||
STUN_CHANCE = 54, // 眩晕概率
|
||||
BACK_CHANCE = 55, // 击退概率
|
||||
SLOW_CHANCE = 56, // 减速概率
|
||||
POISON_CHANCE = 57, // 中毒概率
|
||||
SILENCE_CHANCE = 58, // 沉默概率
|
||||
EXPLOSION_CHANCE = 59, // 爆炸概率
|
||||
|
||||
// ========== 增益效果属性 (60-69) ==========
|
||||
BUFF_UP = 60, // Buff效果提升
|
||||
DBUFF_UP = 61, // Debuff效果提升
|
||||
SHIELD_UP = 62, // 护盾效果提升
|
||||
SPEED = 63, // 移动速度加成
|
||||
EXP_GAIN = 64, // 经验获取
|
||||
GOLD_GAIN = 65, // 金币获取
|
||||
DROP_CHANCE = 66, // 掉落率
|
||||
REVIVE_COUNT = 67, // 复活次数
|
||||
REVIVE_TIME = 68, // 复活时间
|
||||
INVINCIBLE_TIME = 69, // 无敌时间
|
||||
@@ -80,23 +52,14 @@ export enum Attrs {
|
||||
// ========== 武器进化相关 (70-79) ==========
|
||||
PUNCTURE = 70, // 穿刺次数
|
||||
PUNCTURE_DMG = 71, // 穿刺伤害
|
||||
MOVE_SPEED = 74, // 移动速度
|
||||
BURN = 75, // 易伤效果
|
||||
WFUNY = 77, // 风怒
|
||||
|
||||
// ========== 负面状态相关 (80-89) ==========
|
||||
DMG_INVUL = 80, //易伤
|
||||
// ========== 怪物特殊属性 (90-99)==========
|
||||
ATK_TRI_RESET = 90, // 英雄攻击触发计数重置
|
||||
DMG_TRI_RESET = 91, // 英雄伤害触发计数重置
|
||||
BOOM = 92, // 自爆怪
|
||||
|
||||
}
|
||||
|
||||
export const defaultAttrs = {
|
||||
[Attrs.BACK_CHANCE]:0,
|
||||
[Attrs.DODGE]:0,
|
||||
[Attrs.CON_RES]:0,
|
||||
}
|
||||
/**
|
||||
* 初始化英雄属性对象
|
||||
@@ -136,55 +99,27 @@ export const getNeAttrs = () => {
|
||||
export const AttrsType: Record<Attrs, BType> = {
|
||||
// ========== 基础生存属性(数值型) ==========
|
||||
[Attrs.HP_MAX]: BType.VALUE, // 最大生命值 - 数值型
|
||||
[Attrs.MP_MAX]: BType.VALUE, // 最大魔法值 - 数值型
|
||||
[Attrs.SHIELD_MAX]: BType.VALUE, // 最大护盾值 - 数值型
|
||||
[Attrs.HP_REGEN]: BType.RATIO, // 生命回复 - 百分比型
|
||||
[Attrs.MP_REGEN]: BType.VALUE, // 魔法回复 - 数值型
|
||||
[Attrs.LUCK]: BType.VALUE, // 幸运 - 数值型
|
||||
|
||||
// ========== 攻击属性(数值型) ==========
|
||||
[Attrs.AP]: BType.VALUE, // 攻击力 - 数值型
|
||||
[Attrs.DIS]: BType.VALUE, // 攻击距离 - 数值型
|
||||
[Attrs.AS]: BType.RATIO, // 攻击速度 - 百分比型
|
||||
[Attrs.SS]: BType.RATIO, // 技能速度 - 百分比型
|
||||
[Attrs.SKILL_DURATION]: BType.RATIO, // 技能持续时间 - 百分比型
|
||||
[Attrs.AREA_OF_EFFECT]: BType.VALUE, // 作用范围 - 数值型
|
||||
|
||||
// ========== 防御属性(混合类型) ==========
|
||||
[Attrs.DEF]: BType.VALUE, // 物理防御 - 数值型
|
||||
[Attrs.DODGE]: BType.RATIO, // 闪避率 - 百分比型
|
||||
[Attrs.THORNS]: BType.RATIO, // 反伤 - 百分比型
|
||||
|
||||
// ========== 暴击与命中属性(百分比型) ==========
|
||||
[Attrs.CRITICAL]: BType.RATIO, // 暴击率 - 百分比型
|
||||
[Attrs.CRITICAL_DMG]: BType.RATIO, // 暴击伤害 - 百分比型
|
||||
[Attrs.HIT]: BType.RATIO, // 命中率 - 百分比型
|
||||
[Attrs.CRITICAL_RES]: BType.RATIO, // 暴击抗性 - 百分比型
|
||||
[Attrs.CON_RES]: BType.RATIO, // 控制抗性 - 百分比型
|
||||
|
||||
|
||||
|
||||
|
||||
// ========== 特殊效果属性(百分比型) ==========
|
||||
[Attrs.LIFESTEAL]: BType.RATIO, // 吸血比率 - 百分比型
|
||||
[Attrs.MANASTEAL]: BType.RATIO, // 吸蓝 - 百分比型
|
||||
[Attrs.FREEZE_CHANCE]: BType.RATIO, // 冰冻概率 - 百分比型
|
||||
[Attrs.BURN_CHANCE]: BType.RATIO, // 燃烧概率 - 百分比型
|
||||
[Attrs.STUN_CHANCE]: BType.RATIO, // 眩晕概率 - 百分比型
|
||||
[Attrs.BACK_CHANCE]: BType.RATIO, // 击退概率 - 百分比型
|
||||
[Attrs.SLOW_CHANCE]: BType.RATIO, // 减速概率 - 百分比型
|
||||
[Attrs.POISON_CHANCE]: BType.RATIO, // 中毒概率 - 百分比型
|
||||
[Attrs.SILENCE_CHANCE]: BType.RATIO, // 沉默概率 - 百分比型
|
||||
[Attrs.EXPLOSION_CHANCE]: BType.RATIO, // 爆炸概率 - 百分比型
|
||||
|
||||
// ========== 增益效果属性(百分比型) ==========
|
||||
[Attrs.BUFF_UP]: BType.RATIO, // Buff效果提升 - 百分比型
|
||||
[Attrs.DBUFF_UP]: BType.RATIO, // Debuff效果提升 - 百分比型
|
||||
[Attrs.SHIELD_UP]: BType.RATIO, // 护盾效果提升 - 百分比型
|
||||
[Attrs.SPEED]: BType.RATIO, // 移动速度加成 - 百分比型
|
||||
[Attrs.EXP_GAIN]: BType.RATIO, // 经验获取 - 百分比型
|
||||
[Attrs.GOLD_GAIN]: BType.RATIO, // 金币获取 - 百分比型
|
||||
[Attrs.DROP_CHANCE]: BType.RATIO, // 掉落率 - 百分比型
|
||||
[Attrs.REVIVE_COUNT]: BType.VALUE, // 复活次数 - 数值型
|
||||
[Attrs.REVIVE_TIME]: BType.RATIO, // 复活时间 - 百分比型
|
||||
[Attrs.INVINCIBLE_TIME]: BType.RATIO, // 无敌时间 - 百分比型
|
||||
@@ -192,17 +127,7 @@ export const AttrsType: Record<Attrs, BType> = {
|
||||
// ========== 武器进化相关(混合类型) ==========
|
||||
[Attrs.PUNCTURE]: BType.VALUE, // 穿刺次数 - 数值型
|
||||
[Attrs.PUNCTURE_DMG]: BType.RATIO, // 穿刺伤害 - 百分比型
|
||||
[Attrs.MOVE_SPEED]: BType.VALUE, // 移动速度 - 数值型
|
||||
[Attrs.BURN]: BType.RATIO, // 易伤效果 - 百分比型
|
||||
[Attrs.WFUNY]: BType.RATIO, // 未知特殊属性 - 百分比型
|
||||
|
||||
|
||||
// ========== 负面状态相关(混合类型) ==========
|
||||
[Attrs.DMG_INVUL]: BType.RATIO, //易伤
|
||||
|
||||
// ========== 怪物独有特殊属性 (90-99)==========
|
||||
[Attrs.ATK_TRI_RESET]: BType.BOOLEAN, // 英雄攻击触发计数重置
|
||||
[Attrs.DMG_TRI_RESET]: BType.BOOLEAN, // 英雄伤害触发计数重置
|
||||
[Attrs.BOOM]: BType.BOOLEAN, // 自爆怪
|
||||
|
||||
};
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
import { count } from "console";
|
||||
import { Attrs, BType } from "./HeroAttrs";
|
||||
import { CardKind } from "./GameSet";
|
||||
|
||||
/**
|
||||
* 天赋类型枚举,也是触发条件
|
||||
*/
|
||||
export enum TriType {
|
||||
ATK = 1, // 等级升触发
|
||||
DMG = 2, //普通攻击触发
|
||||
ATKED=3,
|
||||
SKILL = 4, // 技能触发
|
||||
HPL = 6, // 失去生命值触发
|
||||
HPA = 7, // 获得生命值触发
|
||||
INIT = 8, // 初始触发,如:多1个技能
|
||||
DEAD = 9, // 基于死亡触发
|
||||
}
|
||||
|
||||
|
||||
|
||||
export enum TalEffet {
|
||||
ATK_DMG=1, // 伤害 次数+伤害加成,如额外5次 伤害+20%
|
||||
SKILL_DMG=2, // 技能伤害 次数+伤害加成,如额外5次 伤害+20%
|
||||
DEF=10, // 减伤 次数+减伤加成,如额外5次 伤害-20%
|
||||
THORNS=14, //反伤 百分比 次数+反伤加成,如额外5次 反伤-20%
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
HP=3, // 回血 百分比 直接触发,回血20%
|
||||
SHIELD=9, // 护盾 直接触发,获得20%的生命值护盾
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
BUFF = 5, // 数值叠加 触发后清零: 暴击率,闪避率等,触发后效果取消
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ATTR=6, // 属性 永久添加
|
||||
|
||||
WFUNY=7, // 风怒 次数 叠加 ,如额外5次 风怒
|
||||
D_SKILL=8, //两次技能 次数 叠加,如额外5次 两次技能
|
||||
C_MSKILL=11, // 必杀技能必暴 次数 叠加 ,如额外5次 必杀技能必暴
|
||||
C_ATK=12, // 普工必爆 次数 叠加 ,如额外5次 普工必爆
|
||||
C_SKILL=13, // 一般技能必暴 次数 叠加 ,如额外5次 一般技能必暴
|
||||
}
|
||||
|
||||
|
||||
export enum TalTarget {
|
||||
SELF = 1, // 自己触发
|
||||
ENEMY = 2, // 敌人触发
|
||||
}
|
||||
|
||||
export enum TalAttrs {
|
||||
NON=0,
|
||||
FREEZE_CHANCE=Attrs.FREEZE_CHANCE, // 冰冻概率
|
||||
STUN_CHANCE=Attrs.STUN_CHANCE, // 冰冻概率
|
||||
BACK_CHANCE=Attrs.BACK_CHANCE, // 击退概率
|
||||
SILENCE_CHANCE=Attrs.SILENCE_CHANCE, // 沉默概率
|
||||
CRITICAL=Attrs.CRITICAL, // 暴击率
|
||||
AP=Attrs.AP, // 攻击力
|
||||
HP_MAX=Attrs.HP_MAX, // 最大生命值
|
||||
THORNS=Attrs.THORNS, //反伤 百分比
|
||||
REVIVE_COUNT=Attrs.REVIVE_COUNT, // 复活次数
|
||||
WFUNY=Attrs.WFUNY, // 风怒
|
||||
}
|
||||
|
||||
/**
|
||||
* 天赋配置接口
|
||||
* 定义一个完整的天赋效果
|
||||
*/
|
||||
|
||||
export interface ItalConf {
|
||||
uuid: number; // 天赋ID
|
||||
name: string; // 天赋名称
|
||||
icon:string; // 天赋图标
|
||||
kind:CardKind; // 天赋类型
|
||||
triType: TriType; // 天赋触发类型
|
||||
target: TalTarget; // 天赋触发目标
|
||||
effet: TalEffet; // 天赋触发效果
|
||||
vType:BType; //数值型还是百分比型
|
||||
value: number; // 触发的效果值(如增加10%攻击力, 触发的技能uuid,增加1个技能uuid)
|
||||
attrs?:TalAttrs //触发的attrs效果的对应attrs
|
||||
Trigger:number //触发值
|
||||
Pts:number //添加的天赋点数
|
||||
CPts:number //消耗的天赋点数
|
||||
desc: string; // 天赋描述(说明触发条件和效果)
|
||||
count:number //执行次数,及可以触发的次数
|
||||
}
|
||||
|
||||
// ========== 天赋配置表 ==========
|
||||
|
||||
/**
|
||||
* 天赋配置表 - 2行紧凑格式
|
||||
* 每个天赋配置压缩为2行:注释行 + 配置对象行
|
||||
*
|
||||
* 格式说明:
|
||||
* 第1行:// 天赋名称 - 英雄专属/通用 | 触发条件 | 效果描述
|
||||
* 第2行:{uuid, name, desc, type, triggerType, chance, t_value, e_value, e_name, e_type, e_scaling, e_count, stackable, maxStack}
|
||||
*
|
||||
* 使用说明:
|
||||
* 1. 等级类天赋:当英雄升级到指定等级时,每次都会触发效果
|
||||
* 2. 行为计数类:当特定行为累计达到阈值时触发,支持是否重置计数
|
||||
* 3. 受伤计数类:当受伤累计达到阈值时触发,支持是否重置计数
|
||||
* 4. 技能触发类:当特定条件满足时自动触发指定技能
|
||||
*/
|
||||
export const talConf: Record<number, ItalConf> = {
|
||||
/*** 普通攻击触发 ***/
|
||||
7001:{uuid:7001,name:"风怒",icon:"7001",kind:CardKind.Atk,triType:TriType.ATK,Trigger:3,count:1,target:TalTarget.ENEMY,effet:TalEffet.WFUNY,vType:BType.RATIO, value:50,attrs:TalAttrs.NON,
|
||||
Pts:2,CPts:0,desc:"普通攻击3次后, 立即给与目标150%伤害的额外打击"},
|
||||
7003:{uuid:7003,name:"回血",icon:"7001",kind:CardKind.Atk,triType:TriType.ATK,Trigger:3,count:1,target:TalTarget.SELF,effet:TalEffet.HP,vType:BType.RATIO, value:1,attrs:TalAttrs.NON,
|
||||
Pts:2,CPts:0,desc:"普通攻击3次后, 会回复1%的生命值"},
|
||||
7004:{uuid:7004,name:"回血(大)",icon:"7001",kind:CardKind.Atk,triType:TriType.ATK,Trigger:3,count:1,target:TalTarget.SELF,effet:TalEffet.HP,vType:BType.RATIO, value:2,attrs:TalAttrs.NON,
|
||||
Pts:2,CPts:0,desc:"普通攻击5次后, 会回复2%的生命值"},
|
||||
7005:{uuid:7005,name:"冰冻",icon:"7001",kind:CardKind.Atk,triType:TriType.ATK,Trigger:3,count:1,target:TalTarget.ENEMY,effet:TalEffet.BUFF,vType:BType.RATIO, value:100,attrs:TalAttrs.FREEZE_CHANCE,
|
||||
Pts:2,CPts:0,desc:"普通攻击3次后, 下一次攻击必定冻结目标"},
|
||||
7006:{uuid:7006,name:"沉默",icon:"7001",kind:CardKind.Atk,triType:TriType.ATK,Trigger:3,count:1,target:TalTarget.ENEMY,effet:TalEffet.BUFF,vType:BType.RATIO, value:100,attrs:TalAttrs.SILENCE_CHANCE,
|
||||
Pts:2,CPts:0,desc:"普通攻击3次后, 下一次攻击必定沉默目标"},
|
||||
7007:{uuid:7007,name:"击退",icon:"7001",kind:CardKind.Atk,triType:TriType.ATK,Trigger:3,count:1,target:TalTarget.ENEMY,effet:TalEffet.BUFF,vType:BType.RATIO, value:100,attrs:TalAttrs.BACK_CHANCE,
|
||||
Pts:2,CPts:0,desc:"普通攻击3次后, 下一次攻击必定击退目标"},
|
||||
7008:{uuid:7008,name:"会心",icon:"7001",kind:CardKind.Atk,triType:TriType.ATK,Trigger:3,count:1,target:TalTarget.SELF,effet:TalEffet.BUFF,vType:BType.RATIO, value:100,attrs:TalAttrs.CRITICAL,
|
||||
Pts:2,CPts:0,desc:"普通攻击3次后, 下一次攻击必定获得100%的暴击率"},
|
||||
7009:{uuid:7009,name:"眩晕",icon:"7001",kind:CardKind.Atk,triType:TriType.ATK,Trigger:3,count:1,target:TalTarget.ENEMY,effet:TalEffet.BUFF,vType:BType.RATIO, value:100,attrs:TalAttrs.STUN_CHANCE,
|
||||
Pts:2,CPts:0,desc:"普通攻击3次后, 下一次攻击必定获得100%的眩晕率"},
|
||||
7010:{uuid:7010,name:"熟练",icon:"7001",kind:CardKind.Atk,triType:TriType.ATK,Trigger:10,count:1,target:TalTarget.SELF,effet:TalEffet.D_SKILL,vType:BType.RATIO, value:0,attrs:TalAttrs.NON,
|
||||
Pts:2,CPts:0,desc:"普通攻击10次后, 下次一般技能额外释放1次,伤害100%"},
|
||||
|
||||
/*** 受伤触发 ***/
|
||||
7101:{uuid:7101,name:"反击",icon:"7001",kind:CardKind.Atted,triType:TriType.ATKED,Trigger:3,count:1,target:TalTarget.ENEMY,effet:TalEffet.ATK_DMG,vType:BType.RATIO, value:50,attrs:TalAttrs.NON,
|
||||
Pts:2,CPts:0,desc:"被攻击3次后, 给于目标50%的伤害"},
|
||||
7102:{uuid:7102,name:"护盾",icon:"7001",kind:CardKind.Atted,triType:TriType.ATKED,Trigger:30,count:1,target:TalTarget.SELF,effet:TalEffet.SHIELD,vType:BType.RATIO, value:20,attrs:TalAttrs.NON,
|
||||
Pts:2,CPts:0,desc:"被攻击30次后, 获得20%的生命值护盾"},
|
||||
7103:{uuid:7103,name:"减伤",icon:"7001",kind:CardKind.Atted,triType:TriType.ATKED,Trigger:3,count:1,target:TalTarget.ENEMY,effet:TalEffet.DEF,vType:BType.RATIO, value:50,attrs:TalAttrs.NON,
|
||||
Pts:2,CPts:0,desc:"被攻击3次后, 下1次伤害减50%"},
|
||||
7104:{uuid:7104,name:"复苏",icon:"7001",kind:CardKind.Atted,triType:TriType.ATKED,Trigger:100,count:1,target:TalTarget.SELF,effet:TalEffet.BUFF,vType:BType.VALUE, value:1,attrs:TalAttrs.REVIVE_COUNT,
|
||||
Pts:2,CPts:0,desc:"被攻击100次后, 获得1次复活"},
|
||||
|
||||
/*** 失去血量触发 ***/
|
||||
7201:{uuid:7201,name:"背水",icon:"7001",kind:CardKind.Hp,triType:TriType.HPL,Trigger:50,count:10,target:TalTarget.SELF,effet:TalEffet.C_ATK,vType:BType.VALUE, value:0,attrs:TalAttrs.NON,
|
||||
Pts:2,CPts:0,desc:"每失去50%生命值,获得下10次普通攻击暴击"},
|
||||
|
||||
|
||||
|
||||
/*** 7400 回血量触发 ***/
|
||||
/** 7500 一击必杀触发 */
|
||||
};
|
||||
export const CanSelectTalents: Record<number, number[]> = {
|
||||
// 3级开放攻击类天赋
|
||||
3: [7001, 7003, 7005, 7008],
|
||||
// 5级必出防御类
|
||||
5: [7101, 7102, 7103],
|
||||
// 9级混合
|
||||
9: [7001, 7003, 7005, 7008, 7101, 7102, 7103],
|
||||
// 20级终极天赋
|
||||
20: [7301, 7302],
|
||||
// 默认全开
|
||||
99: [7001, 7003, 7004, 7005, 7006, 7007, 7008, 7009, 7010, 7101, 7102, 7103, 7104, 7201, 7301, 7302]
|
||||
};
|
||||
|
||||
// ========== 工具函数 ==========
|
||||
@@ -3,7 +3,6 @@ import { BoxSet, FacSet } from "./GameSet"
|
||||
import { smc } from "../SingletonModuleComp"
|
||||
import { BuffConf, SkillRange } from "./SkillSet"
|
||||
import { Interface } from "readline"
|
||||
import { TriType } from "./TalSet"
|
||||
|
||||
export enum AttrSet {
|
||||
ATTR_MAX = 85,
|
||||
@@ -94,11 +93,6 @@ export enum HRegen {
|
||||
HP=0.5
|
||||
}
|
||||
|
||||
export interface ITalPts {
|
||||
TriType: TriType; //触发添加天赋点数类型
|
||||
TriVal: number; //触发添加天赋点需求数值
|
||||
TalPts: number; //添加天赋点数值
|
||||
}
|
||||
/**
|
||||
* 不同职业升级属性加成配置
|
||||
* 战士:高血量成长,低攻击成长
|
||||
@@ -137,8 +131,6 @@ export interface heroInfo {
|
||||
speed: number; // 移动速度(像素/秒)
|
||||
skills: number[]; // 携带技能ID列表
|
||||
buff: BuffConf[]; // 自带buff配置(通常为空,由技能动态添加)
|
||||
tal: number[]; // 天赋ID列表
|
||||
talPts?: ITalPts[]; // 天赋触发配置
|
||||
info: string; // 描述文案
|
||||
}
|
||||
|
||||
@@ -159,37 +151,37 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
5001:{uuid:5001,name:"盾战士",icon:"1001",path:"hk1", fac:FacSet.HERO, kind:1,as:1,
|
||||
type:HType.warrior,lv:1,hp:300,mp:200,def:5,ap:25,speed:120,skills:[6001,6004],
|
||||
rangeType: SkillRange.Melee,
|
||||
buff:[],tal:[],talPts:[{TriType:TriType.ATK,TriVal:1,TalPts:1}],info:"盾战士"},
|
||||
buff:[],info:"盾战士"},
|
||||
|
||||
5002:{uuid:5002,name:"奥术法师",icon:"1001",path:"hm2", fac:FacSet.HERO, kind:2,as:1,
|
||||
type:HType.mage,lv:1,hp:150,mp:135,def:0,ap:40,speed:95,skills:[6003,6101],
|
||||
rangeType: SkillRange.Long,
|
||||
buff:[],tal:[],info:"奥术法师"},
|
||||
buff:[],info:"奥术法师"},
|
||||
|
||||
5003:{uuid:5003,name:"射手",icon:"1001",path:"ha1", fac:FacSet.HERO, kind:2,as:1,
|
||||
type:HType.remote,lv:1,hp:180,mp:80,def:0,ap:30,speed:140,skills:[6002,6100],
|
||||
rangeType: SkillRange.Long,
|
||||
buff:[],tal:[],info:"射手"},
|
||||
buff:[],info:"射手"},
|
||||
|
||||
5005:{uuid:5005,name:"牧师",icon:"1001",path:"hh1", fac:FacSet.HERO, kind:2,as:1,
|
||||
type:HType.mage,lv:1,hp:160,mp:135,def:0,ap:25,speed:100,skills:[6003,6100],
|
||||
rangeType: SkillRange.Mid,
|
||||
buff:[],tal:[],info:"牧师"},
|
||||
buff:[],info:"牧师"},
|
||||
|
||||
5004:{uuid:5004,name:"火焰法师",icon:"1001",path:"hm1", fac:FacSet.HERO, kind:2,as:1,
|
||||
type:HType.mage,lv:1,hp:150,mp:140,def:0,ap:45,speed:90,skills:[6003,6101],
|
||||
rangeType: SkillRange.Mid,
|
||||
buff:[],tal:[],info:"火焰法师"},
|
||||
buff:[],info:"火焰法师"},
|
||||
|
||||
5006:{uuid:5006,name:"召唤法师",icon:"1001",path:"hz1", fac:FacSet.HERO, kind:2,as:1,
|
||||
type:HType.support,lv:1,hp:200,mp:145,def:0,ap:20,speed:105,skills:[6003,6101],
|
||||
rangeType: SkillRange.Mid,
|
||||
buff:[],tal:[],info:"召唤法师"},
|
||||
buff:[],info:"召唤法师"},
|
||||
|
||||
5007:{uuid:5007,name:"刺客",icon:"1001",path:"hc1", fac:FacSet.HERO, kind:1,as:1,
|
||||
type:HType.assassin,lv:1,hp:140,mp:60,def:0,ap:50,speed:180,skills:[6001,6004],
|
||||
rangeType: SkillRange.Melee,
|
||||
buff:[],tal:[],info:"刺客"},
|
||||
buff:[],info:"刺客"},
|
||||
|
||||
|
||||
|
||||
@@ -198,48 +190,48 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
5201:{uuid:5201,name:"兽人战士",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,
|
||||
type:HType.warrior,lv:1,hp:60,mp:100,def:0,ap:8,speed:180,skills:[6003],
|
||||
rangeType: SkillRange.Long,
|
||||
buff:[],tal:[],info:"标准炮灰:确保英雄能完成3次普攻积累天赋计数"},
|
||||
buff:[],info:"标准炮灰:确保英雄能完成3次普攻积累天赋计数"},
|
||||
// 2. 快速突击型
|
||||
5301:{uuid:5301,name:"兽人斥候",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:1.2,
|
||||
type:HType.assassin,lv:1,hp:40,mp:100,def:0,ap:12,speed:400,skills:[6003],
|
||||
rangeType: SkillRange.Long,
|
||||
buff:[],tal:[],info:"快速突击:极高移速贴脸,检测护盾(7102)刷新率"},
|
||||
buff:[],info:"快速突击:极高移速贴脸,检测护盾(7102)刷新率"},
|
||||
// 3. 重型坦克型
|
||||
5401:{uuid:5401,name:"兽人卫士",icon:"1001",path:"mo3", fac:FacSet.MON, kind:1,as:5.0,
|
||||
type:HType.warrior,lv:1,hp:200,mp:100,def:5,ap:15,speed:60,skills:[6003],
|
||||
rangeType: SkillRange.Long,
|
||||
buff:[],tal:[],info:"重型坦克:数值墙,检测玩家破甲(7008)与持续输出"},
|
||||
buff:[],info:"重型坦克:数值墙,检测玩家破甲(7008)与持续输出"},
|
||||
|
||||
// 4. 远程骚扰型
|
||||
5501:{uuid:5501,name:"兽人射手",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,
|
||||
type:HType.remote,lv:1,hp:50,mp:100,def:0,ap:10,speed:90,skills:[6203],
|
||||
rangeType: SkillRange.Long,
|
||||
buff:[],tal:[],info:"远程骚扰:跨屏打击,迫使阵地分散或移动英雄"},
|
||||
buff:[],info:"远程骚扰:跨屏打击,迫使阵地分散或移动英雄"},
|
||||
|
||||
// 5. 特殊机制型
|
||||
5601:{uuid:5601,name:"兽人自爆兵",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,
|
||||
type:HType.assassin,lv:1,hp:80,mp:100,def:0,ap:200,speed:220,skills:[6003],
|
||||
rangeType: SkillRange.Long,
|
||||
buff:[],tal:[],info:"特殊机制:极端伤害,漏怪即秒杀,检测减伤(7103)"},
|
||||
buff:[],info:"特殊机制:极端伤害,漏怪即秒杀,检测减伤(7103)"},
|
||||
// 召唤师:持续召唤小怪(后续可在技能系统中实现 SType.zhaohuan)
|
||||
5602:{uuid:5602,name:"兽人召唤师",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,
|
||||
type:HType.mage,lv:1,hp:150,mp:300,def:5,ap:10,speed:100,skills:[6003],
|
||||
rangeType: SkillRange.Long,
|
||||
buff:[],tal:[],info:"战术目标:持续召唤小怪,检测英雄大招清场频率"},
|
||||
buff:[],info:"战术目标:持续召唤小怪,检测英雄大招清场频率"},
|
||||
// 治疗者:为周围怪物回血(此处以提升治疗效果和生命回复为基础被动)
|
||||
5603:{uuid:5603,name:"兽人祭司",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,
|
||||
type:HType.support,lv:1,hp:150,mp:300,def:5,ap:10,speed:105,skills:[6003],
|
||||
rangeType: SkillRange.Long,
|
||||
buff:[],tal:[],info:"战术目标:为怪群回血,检测玩家沉默(7006)覆盖率"},
|
||||
buff:[],info:"战术目标:为怪群回血,检测玩家沉默(7006)覆盖率"},
|
||||
// 光环怪:为周围怪物提供增益(此处以Buff效果提升与移动速度提升为基础被动)
|
||||
// Attrs.BUFF_UP=60 (RATIO=1),Attrs.SPEED=63 (RATIO=1)
|
||||
5604:{uuid:5604,name:"兽人图腾师",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,
|
||||
type:HType.support,lv:1,hp:150,mp:250,def:5,ap:10,speed:110,skills:[6003],
|
||||
rangeType: SkillRange.Long,
|
||||
buff:[],tal:[],info:"战术目标:提供加速光环,改变怪群推进节奏"},
|
||||
buff:[],info:"战术目标:提供加速光环,改变怪群推进节奏"},
|
||||
// 6. 精英/BOSS型
|
||||
5701:{uuid:5701,name:"兽人首领(BOSS)",icon:"1001",path:"mo4", fac:FacSet.MON, kind:1,as:2.5,
|
||||
type:HType.warrior,lv:3,hp:2000,mp:500,def:10,ap:60,speed:120,skills:[6003],
|
||||
rangeType: SkillRange.Long,
|
||||
buff:[],tal:[],info:"终极考验:极高HP,检测大招重置与辐射协同输出"},
|
||||
buff:[],info:"终极考验:极高HP,检测大招重置与辐射协同输出"},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user