using System; using System.Collections.Generic; using Framework; using Gameplay.Common; using Gameplay.Unit.Data; using Gameplay.Utils; using UnityEngine; namespace Gameplay.Character.Utils { public static class CharacterDataHelper { 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.defenseScale = GLConfig.Inst.data.FightDefenceStatusPara; 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 _SetConfigAttackValue(CharacterConfigData configData, int weaponId, float weaponDegree) { var weaponConfig = TableManager.Instance.Tables.WeaponConfig.GetOrDefault(weaponId); if (weaponConfig == null) { configData.attack = 0; return; } var weaponAttack = weaponConfig.AttackPower; configData.attack = Mathf.CeilToInt(weaponAttack * weaponDegree); } public static CharacterConfigData CombineConfigData(int npcId, int localId, int npcLevel) { var monsterConfig = TableManager.Instance.Tables.Monster.Get(npcId); var monsterTConfig = TableManager.Instance.Tables.MonsterClass.Get(monsterConfig.MonsterClassID); var monsterLevelConfig = TableManager.Instance.Tables.MonsterLevelUp.Get(npcLevel); var configData = new CharacterConfigData(); _InitGlobalConfigBefore(configData); 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 weaponDegree = monsterTConfig.WeaponDegree * monsterLevelConfig.WeaponDegreeScale; var weaponConfig = TableManager.Instance.Tables.WeaponConfig.GetOrDefault(monsterTConfig.WeaponId); if (weaponConfig == null) { throw new Exception("敌人配置的武器ID无效"); } _SetConfigAttackValue(configData, monsterTConfig.WeaponId, weaponDegree); configData.defense = Mathf.CeilToInt(monsterTConfig.Defence * monsterConfig.DefenceFix * monsterLevelConfig.DefenceLevelUpTemplate); configData.maxHp = Mathf.CeilToInt(monsterTConfig.Hp * monsterConfig.HPFix * monsterLevelConfig.HpLevelUpTemplate); configData.maxShield = Mathf.CeilToInt(monsterTConfig.Shield * monsterConfig.ShieldFix * monsterLevelConfig.ShieldLevelUpTemplate); configData.moveSpeed = monsterTConfig.Speed; configData.retreatSpeed = monsterTConfig.RetreatSpeed; configData.moraleAttack = weaponConfig.MoraleDamage; configData.initMorale = monsterTConfig.MaxMorale; 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.rarity = 0; // configData.modelPath = monsterTConfig.PrefabPath; configData.weaponId = monsterTConfig.WeaponId; configData.crossLevel = monsterTConfig.MoveCrossLevel; configData.standLevel = monsterTConfig.StandCrossLevel; configData.findEnemyRange = monsterConfig.FindEnemyRange; configData.eyeBrowsType = monsterTConfig.EmojiEyeBowsType; configData.eyeBrowColor = monsterTConfig.EmojiEyeBowsColor; configData.eyesColor = monsterTConfig.EmojiEyesColor; configData.nameId = monsterTConfig.NameId; configData.damagePepoleScale = weaponConfig.DamageScaleForHuman; configData.damageCarsScale = weaponConfig.DamageScaleForVehicle; configData.damageBuildingsScale = weaponConfig.DamageScaleForBuilding; configData.attackShiledScale = weaponConfig.DamageScaleForShiled; configData.attackHpScale = weaponConfig.DamageScaleForHp; configData.attackEndTime = weaponConfig.AttackEndTime; configData.raiseWeaponTime = weaponConfig.RaiseWeaponTime; configData.attackLoopCount = weaponConfig.AttackLoopCount; configData.reloadTime = weaponConfig.ReloadTime; configData.maxBulletCount = weaponConfig.MaxBulletCount; configData.shootDistance = weaponConfig.AttackDistance; var shootCd = 1f / weaponConfig.ShootSpeed; configData.shootCD = shootCd; configData.isAttackIgnoreBlock = weaponConfig.AttackIgoreBlock; // 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); } _InitGlobalConfigAfter(configData); 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 weaponConfig = TableManager.Instance.Tables.WeaponConfig.GetOrDefault(characterInfo.WeaponId()); if (weaponConfig == null) { DebugUtil.LogError($"角色ID:{cId} 无法找到对应的武器配置: {characterInfo.WeaponId()}"); return null; } var fakeLevel = (int)characterInfo.Level; var levelIndex = fakeLevel - 1; var defenceDataList = characterData.Defence; var hpDataList = characterData.Hp; var shieldDataList = characterData.Shield; var levelDefence = defenceDataList[levelIndex]; var levelHp = hpDataList[levelIndex]; var levelShield = shieldDataList[levelIndex]; var skillId = GetCharacterSkillId(characterInfo); var configData = new CharacterConfigData(); _InitGlobalConfigBefore(configData); configData.cfgId = cId; configData.level = fakeLevel; // TODO: 等待从角色养成数据中读取 _SetConfigAttackValue(configData, characterInfo.WeaponId(), characterData.WeaponDegree); configData.defense = levelDefence; configData.maxHp = levelHp; configData.maxShield = levelShield; configData.moveSpeed = characterData.Speed; configData.retreatSpeed = characterData.RetreatSpeed; configData.moraleAttack = Mathf.FloorToInt(characterInfo.YaZhi()); 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 = characterData.Fraction; 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(); configData.boundTags.Add((int)characterData.Fraction); configData.eyeBrowsType = characterData.EmojiEyeBowsType; configData.eyesColor = characterData.EmojiEyesColor; configData.eyeBrowColor = characterData.EmojiEyeBowsColor; configData.attackHpScale = characterInfo.DamageScaleToHp(); configData.attackShiledScale = characterInfo.DamageScaleToShiled(); configData.damagePepoleScale = characterInfo.DamageScaleToHuman(); configData.damageCarsScale = characterInfo.DamageScaleToCarrier(); configData.damageBuildingsScale = characterInfo.DamageScaleToBuilding(); configData.raiseWeaponTime = weaponConfig.RaiseWeaponTime; configData.attackEndTime = weaponConfig.AttackEndTime; configData.attackLoopCount = weaponConfig.AttackLoopCount; configData.reloadTime = characterInfo.ChangeBulletTime(); configData.maxBulletCount = characterInfo.BulletCapacity(); configData.shootDistance = characterInfo.AttackDistance(); // TODO: 角色单位使用攻击距离作为索敌距离 configData.findEnemyRange = configData.shootDistance; var shootCd = 1f / characterInfo.ShootSpeed(); configData.shootCD = shootCd; configData.isAttackIgnoreBlock = weaponConfig.AttackIgoreBlock; 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); return configData; } } }