NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Gameplay/Character/Utils/CharacterDataHelper.cs

595 lines
27 KiB
C#

using System;
using System.Collections.Generic;
using cfg.CharacterCfg;
using cfg.item;
using cfg.MonsterCfg;
using Framework;
using Gameplay.Common;
using Gameplay.Level;
using Gameplay.Level.Data;
using Gameplay.Net;
using Gameplay.Summon;
using Gameplay.Unit.Data;
using Gameplay.Utils;
using NLDPB;
using UnityEngine;
namespace Gameplay.Character.Utils
{
public static class CharacterDataHelper
{
public static CharacterDataInfo CreateCharacterInfo(int roleID)
{
var cfg = TableManager.Instance.Tables.CharacterAttri.Get(roleID);
if (cfg == null)
{
DebugUtil.LogError($"角色ID:{roleID} 无法找到对应的角色配置");
return null;
}
var info = new CharacterDataInfo(cfg);
return info;
}
public static int GetCharacterSkillId(int RoleID, int skillLevel, int breakLevel = 1)
{
var skillLevelInfo = TableManager.Instance.Tables.CharacterSkillLevel.Get(RoleID, skillLevel);
if (skillLevelInfo == null)
{
DebugUtil.LogError($"角色ID:{RoleID} 等级:{skillLevel} 无法找到对应的技能等级配置");
return 0;
}
var skillGroupId = skillLevelInfo.SkillGroupId;
//var breakLevel = characterInfo.AwakeLevel;
var skillReferInfo = TableManager.Instance.Tables.SkillReferConfig.Get(skillGroupId);
var breakLevelIndex = (int)breakLevel;
var skillId = skillReferInfo.SkillIds[^1];
if (breakLevelIndex < 0 || breakLevelIndex >= skillReferInfo.SkillIds.Count)
{
DebugUtil.LogError("技能组ID:{0} 突破等级:{1} 无法找到对应的技能ID", skillGroupId, breakLevel);
}
else
{
skillId = skillReferInfo.SkillIds[breakLevelIndex];
}
return skillId;
}
public static int GetCharacterSkillId(CharacterDataInfo characterInfo)
{
var skillLevelInfo = TableManager.Instance.Tables.CharacterSkillLevel.Get(characterInfo.Cfg.RoleID, (int)characterInfo.UltraSkillLevel);
if (skillLevelInfo == null)
{
DebugUtil.LogError($"角色ID:{characterInfo.Cfg.RoleID} 等级:{characterInfo.UltraSkillLevel} 无法找到对应的技能等级配置");
return 0;
}
var skillGroupId = skillLevelInfo.SkillGroupId;
var breakLevel = characterInfo.AwakeLevel;
var skillReferInfo = TableManager.Instance.Tables.SkillReferConfig.Get(skillGroupId);
var breakLevelIndex = (int)breakLevel;
var skillId = skillReferInfo.SkillIds[^1];
if (breakLevelIndex < 0 || breakLevelIndex >= skillReferInfo.SkillIds.Count)
{
DebugUtil.LogError("技能组ID:{0} 突破等级:{1} 无法找到对应的技能ID" , skillGroupId, breakLevel);
}
else
{
skillId = skillReferInfo.SkillIds[breakLevelIndex];
}
return skillId;
}
private static void _InitGlobalConfigBefore(CharacterConfigData configData)
{
configData.shiledRecoverDelay = GLConfig.Inst.data.FightShieldRecoverDelay;
configData.shieldRecoverFix = GLConfig.Inst.data.FightShiledRecoverValueFixed;
configData.shiledRecoverPercent = GLConfig.Inst.data.FightShiledRecoverValuePercent;
configData.hpRecoverDelay = GLConfig.Inst.data.FightHPRecoverDelay;
configData.hpRecoverFix = GLConfig.Inst.data.FightHPRecoverValueFixed;
configData.hpRecoverPercent = GLConfig.Inst.data.FightHPRecoverValuePercent;
configData.turnSpeed = GLConfig.Inst.data.FightCharacterTurnSpeed;
}
private static void _InitGlobalConfigAfter(CharacterConfigData configData)
{
configData.overflowShield = Mathf.FloorToInt(GLConfig.Inst.data.FightOverFlowShiledMaxPercent * configData.maxShield);
configData.suppressMorale = Mathf.FloorToInt(configData.maxMorale * GLConfig.Inst.data.FightSuppressMoralePercent);
configData.retreatMorale = Mathf.FloorToInt(configData.maxMorale * GLConfig.Inst.data.FightRetreateMoralePercent);
}
private static void _SetWeaponInfo(CharacterConfigData configData, int weaponId, float weaponDegree, float weaponGrasp)
{
var weaponConfig = TableManager.Instance.Tables.WeaponConfig.GetOrDefault(weaponId);
if (weaponConfig == null)
{
configData.attack = 0;
return;
}
// 熟练度影响攻击力
var weaponAttack = weaponConfig.AttackPower * Mathf.Max(0.01f, weaponDegree);
configData.attack = Mathf.CeilToInt(weaponAttack * weaponGrasp);
// 掌握度影响攻击速度, 攻击间隔
var cdScale = Mathf.Max(0.01f, weaponGrasp);
configData.attackEndTime = weaponConfig.AttackEndTime * cdScale;
configData.shootCd = 1f / weaponConfig.ShootSpeed * cdScale;
// 其他属性
configData.perReloadCount = weaponConfig.PerReloadCount;
configData.canAttackNoReloadFull = weaponConfig.AllowShootAtNoFullReload;
configData.raiseWeaponTime = weaponConfig.RaiseWeaponTime;
configData.isAttackIgnoreBlock = weaponConfig.AttackIgoreBlock;
configData.attackPowerLevel = weaponConfig.AttackPowerLevel;
}
public static CharacterConfigData CombineSelfNpcConfigData(LevelData.NPCInfo npcInfo)
{
var monsterConfig = TableManager.Instance.Tables.Monster.Get(npcInfo.id);
var npcConfig = TableManager.Instance.Tables.FightNPCConfig.GetOrDefault(monsterConfig.MonsterClassID);
var configData = new CharacterConfigData();
_InitGlobalConfigBefore(configData);
configData.cfgId = monsterConfig.MonsterClassID;
configData.localId = npcInfo.index;
configData.debugShowInfo = new DebugShowInfo();
configData.debugShowInfo.name = npcConfig.NameRead;
configData.debugShowInfo.iconPath = "";
configData.debugShowInfo.configId = "FightNPCConfig@" + npcConfig.ConfigId;
var weaponConfig = TableManager.Instance.Tables.WeaponConfig.GetOrDefault(npcConfig.WeaponId);
if (weaponConfig == null)
{
throw new Exception("己方NPC配置的武器ID无效");
}
var weaponDegree = npcConfig.WeaponDegree * monsterConfig.WeaponDegreeScale;
var weaponGrasp = npcConfig.WeaponGrasp * monsterConfig.WeaponGraspScale;
_SetWeaponInfo(configData, npcConfig.WeaponId, weaponDegree, weaponGrasp);
configData.distanceHitRate = npcConfig.ShootDistanceScale;
configData.defense = Mathf.CeilToInt(npcConfig.Defence);
configData.defenseScale = npcConfig.DefenceNoMoveScale;
configData.maxHp = Mathf.CeilToInt(npcConfig.Hp);
configData.maxShield = Mathf.CeilToInt(npcConfig.Shield);
configData.moveSpeed = npcConfig.Speed;
configData.noFightMoveSpeed = npcConfig.NoFightMoveSpeed;
configData.retreatSpeed = npcConfig.RetreatSpeed;
configData.maxMorale = npcConfig.MaxMorale;
configData.moraleRecover = (int)npcConfig.CorrageRecover;
configData.criticalRate = npcConfig.CriticalRatio;
configData.criticalScale = npcConfig.CriticalDamage;
configData.moveShootType = npcConfig.MoveShootType;
configData.skillId = npcConfig.SkillId;
configData.job = npcConfig.Job;
configData.faction = npcConfig.Fraction;
configData.boundTags = new List<int>();
configData.boundTags.Add((int)npcConfig.Fraction);
configData.rarity = 0;
configData.weaponId = npcConfig.WeaponId;
configData.crossLevel = npcConfig.MoveCrossLevel;
configData.standLevel = npcConfig.StandCrossLevel;
// 使用攻击距离作为索敌距离
configData.findEnemyRange = weaponConfig.AttackDistance;
configData.eyeBrowColor = npcConfig.EmojiEyeBowsColor;
configData.eyesColor = npcConfig.EmojiEyesColor;
configData.trackRange = npcConfig.TrackRange;
configData.nameId = npcConfig.NameId;
if (npcConfig.SubType == ENpcCharacterSubType.PlayerMan)
{
// 根据当前养成数据获得性别
var getIsMan = Actor.Instance.Base.GetIsMan();
if (!getIsMan)
{
// 女性
configData.nameId += "_1";
}
}
else if (npcConfig.SubType == ENpcCharacterSubType.PlayerWoman)
{
var getIsMan = Actor.Instance.Base.GetIsMan();
if (getIsMan)
{
// 男性
// 移除后缀
configData.nameId = configData.nameId.Substring(0, configData.nameId.Length - 2);
}
}
configData.damageCharacterScale = weaponConfig.DamageScaleForHuman;
configData.damageVehicleScale = weaponConfig.DamageScaleForVehicle;
configData.damageBuildingsScale = weaponConfig.DamageScaleForBuilding;
configData.attackShiledScale = weaponConfig.DamageScaleForShiled;
configData.attackHpScale = weaponConfig.DamageScaleForHp;
configData.moraleAttack = weaponConfig.MoraleDamage;
configData.attackLoopCount = npcConfig.AttackLoopCount;
configData.reloadTime = weaponConfig.ReloadTime;
configData.maxBulletCount = weaponConfig.MaxBulletCount;
configData.shootDistance = weaponConfig.AttackDistance;
// TODO: 目前没有怪物的被动技能
configData.breakPassiveSkillId = 0;
configData.awakePassiveSkillId = 0;
for (int i = 0; i < npcConfig.PassiveBuffIds.Count; i++)
{
var buffId = npcConfig.PassiveBuffIds[i];
configData.passiveBuffIds.Add(buffId);
}
_ApplyMonsterScale(configData, monsterConfig);
_InitGlobalConfigAfter(configData);
// 设置初始值
configData.initMorale = npcConfig.MaxMorale;
configData.canEvacuate = npcConfig.CanEvacuate;
return configData;
}
private static void _ApplyMonsterScale(CharacterConfigData configData, DataMonster monsterConfig)
{
configData.attack = Mathf.CeilToInt(configData.attack * monsterConfig.AttackFix);
configData.maxHp = Mathf.CeilToInt(configData.maxHp * monsterConfig.HPFix);
configData.maxShield = Mathf.CeilToInt(configData.maxShield * monsterConfig.ShieldFix);
configData.defense = Mathf.CeilToInt(configData.defense * monsterConfig.DefenceFix);
configData.findEnemyRange = monsterConfig.FindEnemyRange;
configData.trackRange = monsterConfig.TrackRange;
configData.level = monsterConfig.MonsterLevel;
}
public static CharacterConfigData CombineEnemyConfigData(int npcId, int localId, int npcLevel)
{
var monsterConfig = TableManager.Instance.Tables.Monster.Get(npcId);
var monsterTConfig = TableManager.Instance.Tables.MonsterClass.Get(monsterConfig.MonsterClassID);
var configData = new CharacterConfigData();
_InitGlobalConfigBefore(configData);
configData.cfgId = monsterTConfig.MonsterClassID;
configData.localId = localId;
configData.debugShowInfo = new DebugShowInfo();
configData.debugShowInfo.name = monsterTConfig.Name;
configData.debugShowInfo.iconPath = "";
configData.debugShowInfo.configId = "MonsterClass@" + monsterTConfig.MonsterClassID;
configData.level = npcLevel;
var weaponConfig = TableManager.Instance.Tables.WeaponConfig.GetOrDefault(monsterTConfig.WeaponId);
if (weaponConfig == null)
{
throw new Exception("敌人配置的武器ID无效");
}
var weaponDegree = monsterTConfig.WeaponDegree * monsterConfig.WeaponDegreeScale;
var weaponGrasp = monsterTConfig.WeaponGrasp * monsterConfig.WeaponGraspScale;
_SetWeaponInfo(configData, monsterTConfig.WeaponId, weaponDegree, weaponGrasp);
configData.distanceHitRate = monsterTConfig.ShootDistanceScale;
configData.defense = Mathf.CeilToInt(monsterTConfig.Defence);
configData.defenseScale = monsterTConfig.DefenceNoMoveScale;
configData.maxHp = Mathf.CeilToInt(monsterTConfig.Hp);
configData.maxShield = Mathf.CeilToInt(monsterTConfig.Shield);
configData.moveSpeed = monsterTConfig.Speed;
configData.noFightMoveSpeed = monsterTConfig.NoFightMoveSpeed;
configData.retreatSpeed = monsterTConfig.RetreatSpeed;
configData.maxMorale = monsterTConfig.MaxMorale;
configData.moraleRecover = (int)monsterTConfig.CorrageRecover;
configData.criticalRate = monsterTConfig.CriticalRatio;
configData.criticalScale = monsterTConfig.CriticalDamage;
configData.moveShootType = monsterTConfig.MoveShootType;
configData.skillId = monsterTConfig.SkillId;
configData.job = monsterTConfig.Job;
configData.faction = monsterTConfig.Fraction;
configData.boundTags = new List<int>();
configData.boundTags.Add((int)monsterTConfig.Fraction);
configData.rarity = 0;
// configData.modelPath = monsterTConfig.PrefabPath;
configData.weaponId = monsterTConfig.WeaponId;
configData.crossLevel = monsterTConfig.MoveCrossLevel;
configData.standLevel = monsterTConfig.StandCrossLevel;
configData.eyeBrowsType = monsterTConfig.EmojiEyeBowsType;
configData.eyeBrowColor = monsterTConfig.EmojiEyeBowsColor;
configData.eyesColor = monsterTConfig.EmojiEyesColor;
configData.nameId = monsterTConfig.NameId;
configData.damageCharacterScale = weaponConfig.DamageScaleForHuman;
configData.damageVehicleScale = weaponConfig.DamageScaleForVehicle;
configData.damageBuildingsScale = weaponConfig.DamageScaleForBuilding;
configData.attackShiledScale = weaponConfig.DamageScaleForShiled;
configData.attackHpScale = weaponConfig.DamageScaleForHp;
configData.moraleAttack = weaponConfig.MoraleDamage;
configData.attackLoopCount = monsterTConfig.AttackLoopCount;
configData.reloadTime = weaponConfig.ReloadTime;
configData.maxBulletCount = weaponConfig.MaxBulletCount;
configData.shootDistance = weaponConfig.AttackDistance;
configData.findEnemyRange = configData.shootDistance;
configData.trackRange = configData.trackRange;
// TODO: 目前没有怪物的被动技能
configData.breakPassiveSkillId = 0;
configData.awakePassiveSkillId = 0;
for (int i = 0; i < monsterTConfig.PassiveBuffIds.Count; i++)
{
var buffId = monsterTConfig.PassiveBuffIds[i];
configData.passiveBuffIds.Add(buffId);
}
_ApplyMonsterScale(configData, monsterConfig);
_InitGlobalConfigAfter(configData);
configData.initMorale = configData.maxMorale;
return configData;
}
public static CharacterConfigData CombineConfigData(CharacterDataInfo characterInfo)
{
var cId = characterInfo.Cfg.RoleID;
var characterData = TableManager.Instance.Tables.CharacterAttri.Get(cId);
if (characterData == null)
{
DebugUtil.LogError($"角色ID:{cId} 无法找到对应的角色配置");
return null;
}
var weaponId = characterInfo.WeaponId();
var weaponConfig = TableManager.Instance.Tables.WeaponConfig.GetOrDefault(weaponId);
if (weaponConfig == null)
{
DebugUtil.LogError($"角色ID:{cId} 无法找到对应的武器配置: {weaponId}");
return null;
}
var fakeLevel = (int)characterInfo.Level;
var levelIndex = fakeLevel - 1;
var defenceBase = characterData.Defence;
var hpBase = characterData.HpBase;
var shieldBase = characterData.Shield;
var CharacterLevelupTemplate = characterData.LevelUpTemplate;
if (CharacterLevelupTemplate == 0)
{
DebugUtil.LogError("没有配置该角色等级模板:{0},自动使用默认模板", characterData.RoleID);
CharacterLevelupTemplate = 1;
}
var levelCfg = TableManager.Instance.Tables.CharacterLevelUp.Get(CharacterLevelupTemplate, fakeLevel);
var levelDefence = (int)(levelCfg.Defence * defenceBase);
var levelHp = (int)(levelCfg.Hp * hpBase);//hpDataList[levelIndex];
var levelShield = (int)(levelCfg.Shield * shieldBase);
var skillId = GetCharacterSkillId(characterInfo);
var configData = new CharacterConfigData();
_InitGlobalConfigBefore(configData);
configData.cfgId = cId;
configData.level = fakeLevel;
var weaponDegree = characterInfo.WeaponDegree();
var weaponGrasp = characterInfo.WeaponGrasp();
_SetWeaponInfo(configData, weaponId, weaponDegree, weaponGrasp);
configData.distanceHitRate = characterData.ShootDistanceScale;
configData.defense = levelDefence;
configData.defenseScale = characterData.DefenceNoMoveScale;
configData.maxHp = levelHp;
configData.maxShield = levelShield;
configData.moveSpeed = characterData.Speed;
configData.noFightMoveSpeed = characterData.NoFightMoveSpeed;
configData.retreatSpeed = characterData.RetreatSpeed;
configData.initMorale = characterData.MaxMorale;
configData.maxMorale = characterData.MaxMorale;
configData.moraleRecover = (int)characterData.CorrageRecover;
configData.criticalRate = characterData.CriticalRatio;
configData.criticalScale = characterData.CriticalDamage;
configData.moveShootType = characterData.MoveShootType;
configData.skillId = skillId;
configData.job = characterData.Job;
configData.faction = CommonUtils.GetEfactionByCfg(characterData);
configData.rarity = characterData.StartStar;
var skinId = (int)characterInfo.SkinID;
var skinConfig = TableManager.Instance.Tables.SkinCfg.Get(skinId, characterData.RoleID);
if (skinConfig == null)
{
DebugUtil.LogError($"{characterData.NameRead} 无有效皮肤配置: {skinId}");
configData.nameId = characterData.NameID;
}
else
{
configData.nameId = skinConfig.NameID;
}
configData.weaponId = characterData.WeaponId;
configData.crossLevel = characterData.MoveCrossLevel;
configData.standLevel = characterData.StandCrossLevel;
configData.boundTags = new List<int>
{
(int)CommonUtils.GetEfactionByCfg(characterData)
};
configData.eyeBrowsType = characterData.EmojiEyeBowsType;
configData.eyesColor = characterData.EmojiEyesColor;
configData.eyeBrowColor = characterData.EmojiEyeBowsColor;
configData.attackHpScale = characterInfo.DamageScaleToHp();
configData.attackShiledScale = characterInfo.DamageScaleToShiled();
configData.damageCharacterScale = characterInfo.DamageScaleToHuman();
configData.damageVehicleScale = characterInfo.DamageScaleToCarrier();
configData.damageBuildingsScale = characterInfo.DamageScaleToBuilding();
configData.moraleAttack = Mathf.FloorToInt(characterInfo.YaZhi());
configData.attackLoopCount = characterInfo.AttackLoopCount();
configData.reloadTime = characterInfo.ChangeBulletTime();
configData.maxBulletCount = characterInfo.BulletCapacity();
configData.shootDistance = characterInfo.AttackDistance();
// TODO: 角色单位使用攻击距离作为索敌距离
configData.findEnemyRange = configData.shootDistance;
if (characterInfo.BreakCfg == null)
{
configData.breakPassiveSkillId = 0;
DebugUtil.LogError("角色ID:{0} 突破配置为空, 当前突破等级: {1}", cId, characterInfo.BreakLevel);
}
else
{
configData.breakPassiveSkillId = characterInfo.BreakCfg.PassiveSkillID;
}
if (characterInfo.AwakeCfg == null)
{
configData.awakePassiveSkillId = 0;
DebugUtil.LogError("角色ID:{0} 觉醒配置为空, 当前觉醒等级: {1}", cId, characterInfo.AwakeLevel);
}
else
{
configData.awakePassiveSkillId = characterInfo.AwakeCfg.PassiveSkillID;
}
configData.debugShowInfo = new DebugShowInfo();
configData.debugShowInfo.name = characterData.NameRead;
// Assets/Art/UI/Texture/Icon/HeadPic/Icon_HeadPic_A00001.png
configData.debugShowInfo.iconPath = skinConfig == null ? "Null" : skinConfig.PIcHeadPath;
configData.debugShowInfo.iconPath = $"Assets/Art/UI/Texture/Icon/HeadPic/{configData.debugShowInfo.iconPath}.png";
configData.debugShowInfo.configId = "CharacterDefault@" + cId;
configData.debugShowInfo.cacheConfigId = characterInfo.Cfg.RoleID;
_InitGlobalConfigAfter(configData);
configData.canEvacuate = true;
return configData;
}
public static cfg.CharacterCfg.DataCharacterLevelup GetLevelUpData(int TemplateID, int level)
{
var _data = TableManager.Instance.Tables.CharacterLevelUp.Get(TemplateID, level);
return _data;
}
public static Ejob ProvideJobToNormalJob(ProvideJob job)
{
return job switch
{
ProvideJob.ProvideJob_Scout => Ejob.Job_Scout,
ProvideJob.ProvideJob_Shoot => Ejob.Job_Shoot,
ProvideJob.ProvideJob_Support => Ejob.Job_Support,
ProvideJob.ProvideJob_Suppress => Ejob.Job_Suppress,
_ => Ejob.Job_Commander
};
}
public static ProvideJob NormalJobToProvideJob(Ejob job)
{
return job switch
{
Ejob.Job_Scout => ProvideJob.ProvideJob_Scout,
Ejob.Job_Shoot => ProvideJob.ProvideJob_Shoot,
Ejob.Job_Support => ProvideJob.ProvideJob_Support,
Ejob.Job_Suppress => ProvideJob.ProvideJob_Suppress,
_ => ProvideJob.ProvideJob_Unlimited
};
}
/// <summary>
/// 是否显示觉醒红点
/// </summary>
/// <param name="characterID"></param>
/// <returns></returns>
public static bool CheckCharacterCanAwake(uint characterID)
{
var mCharacterDataInfo = Actor.Instance.Character.GetCharacter(characterID);
var mCharacterAwakeCfg = TableManager.Instance.Tables.CharacterAwaking;
if (mCharacterDataInfo == null || mCharacterAwakeCfg == null)
return false;
var Storage = StorageMgr.Instance.GetStorage<CharacterAwakeCost>("Character_Awake_Cost");
Dictionary<int, int> itemCounts = new Dictionary<int, int>();
int maxLevel = GetCharacterAwakeMaxLevel(characterID);
if (Storage != null && Storage.MaxLevel.ContainsKey((int)characterID))
{
return maxLevel > Storage.MaxLevel[(int)characterID];
}
return maxLevel > (int)mCharacterDataInfo.AwakeLevel;
}
/// <summary>
/// 获取角色觉醒可达最大等级
/// </summary>
/// <param name="characterID"></param>
/// <returns></returns>
public static int GetCharacterAwakeMaxLevel(uint characterID)
{
var mCharacterDataInfo = Actor.Instance.Character.GetCharacter(characterID);
var mCharacterAwakeCfg = TableManager.Instance.Tables.CharacterAwaking;
Dictionary<int, int> itemCounts = new Dictionary<int, int>();
if (mCharacterAwakeCfg == null)
return 0;
int maxLevel = 0;
for (maxLevel = (int)mCharacterDataInfo.AwakeLevel; maxLevel < 4;)
{
DataCharacterAwaking awakeCfg = mCharacterAwakeCfg.Get((int)characterID, maxLevel + 1);
if (awakeCfg == null)
{
//未找到下一级觉醒配置,当前已经是最高级
break;
}
foreach (var item in awakeCfg.CostItems)
{
if (itemCounts.ContainsKey(item.Id))
{
itemCounts[item.Id] += item.Count;
}
else
{
itemCounts.Add(item.Id, item.Count);
}
if (CategoryManager.Instance.GetItemCount(item.Id) < itemCounts[item.Id])
{
return maxLevel;
}
}
maxLevel++;
}
return maxLevel;
}
public static bool IsNewCharacter(int characterID)
{
var data = Actor.Instance.Character.GetCharacter((uint)characterID);//CharacterDataInfoManager.Instance.GetCharacterInfo((uint)characterID);
if (data == null)
{
DebugUtil.LogWarning($"没有找到角色ID为{characterID}的角色信息");
return false;
}
return data.isCheck == 1;
}
}
}
public class CharacterAwakeCost
{
public Dictionary<int, int> MaxLevel = new Dictionary<int, int>();
public CharacterAwakeCost()
{
}
}