483 lines
14 KiB
TypeScript
483 lines
14 KiB
TypeScript
/**
|
|
* 天赋系统集成示例
|
|
* 展示如何在实际游戏系统中使用 TalSet 配置
|
|
*/
|
|
|
|
import {
|
|
TalType,
|
|
TalAttrType,
|
|
TalActionType,
|
|
ItalConf,
|
|
getTalConf,
|
|
getTalConfByType,
|
|
getAllTalIds,
|
|
talConf
|
|
} from "./TalSet";
|
|
|
|
// ========== 天赋实时数据结构 ==========
|
|
|
|
/**
|
|
* 英雄天赋实例数据
|
|
* 记录单个英雄某个天赋的实时数据
|
|
*/
|
|
export interface HeroTalentInstance {
|
|
talId: number; // 天赋ID
|
|
stackCount: number; // 当前堆叠层数
|
|
actionCounter: number; // 行为计数器(用于计数类天赋)
|
|
damageCounter: number; // 受伤计数器(用于受伤类天赋)
|
|
lastTriggerLevel: number; // 最后一次触发的等级(用于等级类天赋)
|
|
isActive: boolean; // 是否激活
|
|
}
|
|
|
|
/**
|
|
* 英雄天赋管理数据
|
|
* 记录一个英雄的所有天赋数据
|
|
*/
|
|
export interface HeroTalentManager {
|
|
heroId: number;
|
|
talents: Map<number, HeroTalentInstance>;
|
|
}
|
|
|
|
// ========== 天赋触发系统 ==========
|
|
|
|
/**
|
|
* 天赋触发管理器
|
|
* 处理天赋的所有触发逻辑
|
|
*/
|
|
export class TalentTriggerManager {
|
|
private talentInstances: Map<number, HeroTalentManager> = new Map();
|
|
|
|
/**
|
|
* 初始化英雄的天赋系统
|
|
* @param heroId 英雄ID
|
|
* @param talentIds 天赋ID数组
|
|
*/
|
|
public initHeroTalents(heroId: number, talentIds: number[]): void {
|
|
const talentManager: HeroTalentManager = {
|
|
heroId,
|
|
talents: new Map(),
|
|
};
|
|
|
|
talentIds.forEach(talId => {
|
|
const talConfig = getTalConf(talId);
|
|
if (talConfig) {
|
|
talentManager.talents.set(talId, {
|
|
talId,
|
|
stackCount: 0,
|
|
actionCounter: 0,
|
|
damageCounter: 0,
|
|
lastTriggerLevel: 0,
|
|
isActive: true,
|
|
});
|
|
}
|
|
});
|
|
|
|
this.talentInstances.set(heroId, talentManager);
|
|
}
|
|
|
|
/**
|
|
* 处理英雄等级提升事件
|
|
* @param heroId 英雄ID
|
|
* @param newLevel 新等级
|
|
*/
|
|
public onHeroLevelUp(heroId: number, newLevel: number): void {
|
|
const talentManager = this.talentInstances.get(heroId);
|
|
if (!talentManager) return;
|
|
|
|
talentManager.talents.forEach((instance, talId) => {
|
|
const talConfig = getTalConf(talId);
|
|
if (!talConfig || talConfig.talType !== TalType.LEVEL_ATTR) return;
|
|
|
|
const levelTrigger = talConfig.trigger as any;
|
|
const triggerInterval = levelTrigger.level;
|
|
|
|
// 检查是否应该触发
|
|
if (newLevel % triggerInterval === 0) {
|
|
// 检查是否还能堆叠
|
|
if (talConfig.maxStack && instance.stackCount >= talConfig.maxStack) {
|
|
console.warn(`天赋 ${talConfig.name} 已达到最大堆叠次数`);
|
|
return;
|
|
}
|
|
|
|
instance.stackCount++;
|
|
instance.lastTriggerLevel = newLevel;
|
|
|
|
console.log(`[天赋触发] ${talConfig.name}: 堆叠层数 ${instance.stackCount}`);
|
|
this.applyTalentEffect(heroId, talConfig, instance);
|
|
}
|
|
|
|
// 处理 resetPerLevel 选项
|
|
if ((talConfig.trigger as any).resetPerLevel) {
|
|
instance.actionCounter = 0;
|
|
instance.damageCounter = 0;
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 处理攻击事件
|
|
* @param heroId 英雄ID
|
|
* @param damage 造成的伤害值
|
|
*/
|
|
public onHeroAttack(heroId: number, damage: number): void {
|
|
this.handleActionCounter(heroId, TalActionType.ATTACK);
|
|
}
|
|
|
|
/**
|
|
* 处理技能释放事件
|
|
* @param heroId 英雄ID
|
|
* @param skillId 技能ID
|
|
*/
|
|
public onHeroSkillCast(heroId: number, skillId: number): void {
|
|
this.handleActionCounter(heroId, TalActionType.SKILL);
|
|
}
|
|
|
|
/**
|
|
* 处理受伤事件
|
|
* @param heroId 英雄ID
|
|
* @param damage 受到的伤害值
|
|
*/
|
|
public onHeroDamaged(heroId: number, damage: number): void {
|
|
const talentManager = this.talentInstances.get(heroId);
|
|
if (!talentManager) return;
|
|
|
|
talentManager.talents.forEach((instance, talId) => {
|
|
const talConfig = getTalConf(talId);
|
|
if (!talConfig || talConfig.talType !== TalType.DAMAGE_COUNT_ATTR) return;
|
|
|
|
const damageTrigger = talConfig.trigger as any;
|
|
instance.damageCounter++;
|
|
|
|
// 检查是否应该触发
|
|
if (instance.damageCounter % damageTrigger.count === 0) {
|
|
// 检查是否还能堆叠
|
|
if (talConfig.maxStack && instance.stackCount >= talConfig.maxStack) {
|
|
console.warn(`天赋 ${talConfig.name} 已达到最大堆叠次数`);
|
|
return;
|
|
}
|
|
|
|
instance.stackCount++;
|
|
console.log(`[天赋触发] ${talConfig.name}: 堆叠层数 ${instance.stackCount}`);
|
|
this.applyTalentEffect(heroId, talConfig, instance);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 处理行为计数
|
|
* @private
|
|
*/
|
|
private handleActionCounter(heroId: number, actionType: TalActionType): void {
|
|
const talentManager = this.talentInstances.get(heroId);
|
|
if (!talentManager) return;
|
|
|
|
talentManager.talents.forEach((instance, talId) => {
|
|
const talConfig = getTalConf(talId);
|
|
if (!talConfig || talConfig.talType !== TalType.ACTION_COUNT_ATTR) return;
|
|
|
|
const actionTrigger = talConfig.trigger as any;
|
|
if (actionTrigger.actionType !== actionType) return;
|
|
|
|
instance.actionCounter++;
|
|
|
|
// 检查是否应该触发
|
|
if (instance.actionCounter % actionTrigger.count === 0) {
|
|
// 检查是否还能堆叠
|
|
if (talConfig.maxStack && instance.stackCount >= talConfig.maxStack) {
|
|
console.warn(`天赋 ${talConfig.name} 已达到最大堆叠次数`);
|
|
return;
|
|
}
|
|
|
|
instance.stackCount++;
|
|
console.log(`[天赋触发] ${talConfig.name}: 堆叠层数 ${instance.stackCount}`);
|
|
this.applyTalentEffect(heroId, talConfig, instance);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 应用天赋效果
|
|
* @private
|
|
*/
|
|
private applyTalentEffect(
|
|
heroId: number,
|
|
talConfig: ItalConf,
|
|
instance: HeroTalentInstance
|
|
): void {
|
|
const effect = talConfig.effect;
|
|
|
|
switch (effect.type) {
|
|
case "attrModify":
|
|
this.applyAttrModify(heroId, talConfig);
|
|
break;
|
|
case "skillTrigger":
|
|
this.triggerSkill(heroId, talConfig);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 应用属性修改效果
|
|
* @private
|
|
*/
|
|
private applyAttrModify(heroId: number, talConfig: ItalConf): void {
|
|
const effect = talConfig.effect as any;
|
|
const { attr, value, percent } = effect;
|
|
|
|
console.log(
|
|
`应用属性修改: 英雄${heroId}, 属性${attr}, ` +
|
|
`${percent ? '百分比' : '固定值'}: ${value}`
|
|
);
|
|
|
|
// 这里应该调用实际的英雄属性修改系统
|
|
// 示例:
|
|
// const hero = getHeroData(heroId);
|
|
// hero.modifyAttribute(attr, value, percent);
|
|
}
|
|
|
|
/**
|
|
* 触发技能效果
|
|
* @private
|
|
*/
|
|
private triggerSkill(heroId: number, talConfig: ItalConf): void {
|
|
const effect = talConfig.effect as any;
|
|
const { skillId } = effect;
|
|
|
|
console.log(`自动释放技能: 英雄${heroId}, 技能ID: ${skillId}`);
|
|
|
|
// 这里应该调用实际的技能释放系统
|
|
// 示例:
|
|
// const hero = getHeroData(heroId);
|
|
// hero.castSkill(skillId);
|
|
}
|
|
|
|
/**
|
|
* 获取英雄的天赋实例信息
|
|
*/
|
|
public getHeroTalentInfo(heroId: number): HeroTalentManager | undefined {
|
|
return this.talentInstances.get(heroId);
|
|
}
|
|
|
|
/**
|
|
* 获取英雄特定天赋的实例数据
|
|
*/
|
|
public getHeroTalentInstance(
|
|
heroId: number,
|
|
talId: number
|
|
): HeroTalentInstance | undefined {
|
|
const talentManager = this.talentInstances.get(heroId);
|
|
return talentManager?.talents.get(talId);
|
|
}
|
|
}
|
|
|
|
// ========== 天赋查询工具 ==========
|
|
|
|
/**
|
|
* 天赋查询助手
|
|
*/
|
|
export class TalentQueryHelper {
|
|
/**
|
|
* 获取某类型英雄的所有天赋
|
|
*/
|
|
public static getTalentsByType(talType: TalType): ItalConf[] {
|
|
return getTalConfByType(talType);
|
|
}
|
|
|
|
/**
|
|
* 获取某属性的所有相关天赋
|
|
*/
|
|
public static getTalentsByAttribute(attr: TalAttrType): ItalConf[] {
|
|
return Object.values(talConf).filter(tal => {
|
|
const effect = tal.effect as any;
|
|
return effect.type === "attrModify" && effect.attr === attr;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 获取基于某行为的所有天赋
|
|
*/
|
|
public static getTalentsByAction(actionType: TalActionType): ItalConf[] {
|
|
return Object.values(talConf).filter(tal => {
|
|
const trigger = tal.trigger as any;
|
|
return (
|
|
(trigger.type === "actionCount" && trigger.actionType === actionType) ||
|
|
(trigger.type === "damageCount")
|
|
);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 获取所有可堆叠的天赋
|
|
*/
|
|
public static getStackableTalents(): ItalConf[] {
|
|
return Object.values(talConf).filter(tal => tal.stackable !== false);
|
|
}
|
|
|
|
/**
|
|
* 获取所有技能触发类天赋
|
|
*/
|
|
public static getSkillTriggerTalents(): ItalConf[] {
|
|
return getTalConfByType(TalType.ACTION_TRIGGER_SKILL);
|
|
}
|
|
|
|
/**
|
|
* 打印所有天赋信息(调试用)
|
|
*/
|
|
public static printAllTalents(): void {
|
|
console.log("========== 所有天赋配置 ==========");
|
|
|
|
Object.values(talConf).forEach(tal => {
|
|
console.log(`[${tal.talId}] ${tal.name}`);
|
|
console.log(` 类型: ${this.getTalTypeString(tal.talType)}`);
|
|
console.log(` 描述: ${tal.desc}`);
|
|
console.log(` 可堆叠: ${tal.stackable !== false ? "是" : "否"}`);
|
|
if (tal.maxStack) {
|
|
console.log(` 最大堆叠: ${tal.maxStack}`);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 获取天赋类型的字符串表示
|
|
* @private
|
|
*/
|
|
private static getTalTypeString(talType: TalType): string {
|
|
const typeMap: Record<number, string> = {
|
|
[TalType.LEVEL_ATTR]: "等级属性",
|
|
[TalType.ACTION_COUNT_ATTR]: "行为计数属性",
|
|
[TalType.DAMAGE_COUNT_ATTR]: "受伤计数属性",
|
|
[TalType.ACTION_TRIGGER_SKILL]: "技能触发",
|
|
};
|
|
return typeMap[talType] || "未知";
|
|
}
|
|
}
|
|
|
|
// ========== 使用示例 ==========
|
|
|
|
/**
|
|
* 示例:初始化和使用天赋系统
|
|
*/
|
|
export class TalentSystemExample {
|
|
private triggerManager = new TalentTriggerManager();
|
|
|
|
/**
|
|
* 示例:初始化英雄刘邦的天赋
|
|
*/
|
|
public initLiuBangTalents(): void {
|
|
const liuBangId = 5001;
|
|
const talentIds = [7001, 7202]; // 剑意提升 + 防御强化
|
|
|
|
console.log("初始化刘邦的天赋系统...");
|
|
this.triggerManager.initHeroTalents(liuBangId, talentIds);
|
|
}
|
|
|
|
/**
|
|
* 示例:模拟刘邦升级流程
|
|
*/
|
|
public simulateLevelUp(): void {
|
|
const liuBangId = 5001;
|
|
|
|
console.log("\n--- 刘邦升级模拟 ---");
|
|
for (let level = 1; level <= 20; level++) {
|
|
this.triggerManager.onHeroLevelUp(liuBangId, level);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 示例:模拟战斗中的天赋触发
|
|
*/
|
|
public simulateCombat(): void {
|
|
const liuBangId = 5001;
|
|
|
|
console.log("\n--- 战斗模拟 ---");
|
|
|
|
// 模拟攻击
|
|
for (let i = 0; i < 25; i++) {
|
|
this.triggerManager.onHeroAttack(liuBangId, 50);
|
|
}
|
|
|
|
// 模拟受伤
|
|
for (let i = 0; i < 15; i++) {
|
|
this.triggerManager.onHeroDamaged(liuBangId, 30);
|
|
}
|
|
|
|
// 查询当前天赋状态
|
|
const talentInfo = this.triggerManager.getHeroTalentInfo(liuBangId);
|
|
if (talentInfo) {
|
|
console.log("\n当前天赋状态:");
|
|
talentInfo.talents.forEach((instance, talId) => {
|
|
const talConfig = getTalConf(talId);
|
|
console.log(
|
|
`${talConfig?.name}: 堆叠 ${instance.stackCount}` +
|
|
` (计数: 行为${instance.actionCounter}, 受伤${instance.damageCounter})`
|
|
);
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 示例:查询天赋信息
|
|
*/
|
|
public queryTalentInfo(): void {
|
|
console.log("\n--- 天赋查询示例 ---");
|
|
|
|
// 查询所有等级类天赋
|
|
const levelTals = TalentQueryHelper.getTalentsByType(TalType.LEVEL_ATTR);
|
|
console.log(`\n等级类天赋 (${levelTals.length}个):`);
|
|
levelTals.forEach(tal => console.log(` - ${tal.name}`));
|
|
|
|
// 查询与攻击相关的天赋
|
|
const attackTals = TalentQueryHelper.getTalentsByAction(TalActionType.ATTACK);
|
|
console.log(`\n与攻击相关的天赋 (${attackTals.length}个):`);
|
|
attackTals.forEach(tal => console.log(` - ${tal.name}`));
|
|
|
|
// 查询所有技能触发类天赋
|
|
const skillTals = TalentQueryHelper.getSkillTriggerTalents();
|
|
console.log(`\n技能触发类天赋 (${skillTals.length}个):`);
|
|
skillTals.forEach(tal => console.log(` - ${tal.name}`));
|
|
|
|
// 打印所有天赋
|
|
TalentQueryHelper.printAllTalents();
|
|
}
|
|
}
|
|
|
|
// ========== 全局单例 ==========
|
|
|
|
/** 全局天赋触发管理器实例 */
|
|
export const globalTalentManager = new TalentTriggerManager();
|
|
|
|
/**
|
|
* 快捷函数:初始化英雄天赋
|
|
*/
|
|
export function initHeroTalents(heroId: number, talentIds: number[]): void {
|
|
globalTalentManager.initHeroTalents(heroId, talentIds);
|
|
}
|
|
|
|
/**
|
|
* 快捷函数:处理英雄升级
|
|
*/
|
|
export function onHeroLevelUp(heroId: number, newLevel: number): void {
|
|
globalTalentManager.onHeroLevelUp(heroId, newLevel);
|
|
}
|
|
|
|
/**
|
|
* 快捷函数:处理英雄攻击
|
|
*/
|
|
export function onHeroAttack(heroId: number, damage: number): void {
|
|
globalTalentManager.onHeroAttack(heroId, damage);
|
|
}
|
|
|
|
/**
|
|
* 快捷函数:处理技能释放
|
|
*/
|
|
export function onHeroSkillCast(heroId: number, skillId: number): void {
|
|
globalTalentManager.onHeroSkillCast(heroId, skillId);
|
|
}
|
|
|
|
/**
|
|
* 快捷函数:处理英雄受伤
|
|
*/
|
|
export function onHeroDamaged(heroId: number, damage: number): void {
|
|
globalTalentManager.onHeroDamaged(heroId, damage);
|
|
}
|