using System; using System.Numerics; using Spine.Unity; [Serializable] public struct MateGlobalProperty { public uint mateMaxLevel; public float mateDefaultMoveSpeed; } [Serializable] public class MatePlayerProperty { public static readonly byte _invalidSlotIndex = 0xff; public uint id; public string levelExp = "0"; public bool isUnlocked = false; public byte settedSlotIndex = _invalidSlotIndex; } public class MateData { MateProperty property; MatePlayerProperty playerProperty; public MateProperty Property => property; public uint ID => property.id; public uint Grade => property.grade; public IVMate Prefab => property.matePrefab; public SkeletonDataAsset SkeletonDataAsset => property.skeletonDataAsset; public float DefaultCastSkillDistance => property.defaultCastSkillDistance; public float DefaultMoveSpeed => MateDataGroup.Instance.GlobalProperty.mateDefaultMoveSpeed; public SkillData Skill { get; private set; } public string NameKey => FormatString.StringFormat("mate_name_{0}", ID); public string GradeLetterImgAtlasPath => GameProperty.Instance.GradeLetterIconDefaultName; public string GradeLetterImgNameInAtlas => Grade.ToString(); public string GradeImgAtlasPath => GameProperty.Instance.GradeIconAtlasName; public string GradeImgNameInAtlas => Grade.ToString(); public string Img2DPath => FormatString.StringFormat("{0}_{1}", GameProperty.Instance.Mate2DImageDefaultName, ID); public string ImgFull2DPath => FormatString.StringFormat("{0}_{1}_full", GameProperty.Instance.Mate2DImageDefaultName, ID); public string SDImgAtlasPath => GameProperty.Instance.MateSDImageAtlasName; public string SDImgNameInAtlas => ID.ToString(); public static uint MaxLevel => MateDataGroup.Instance.GlobalProperty.mateMaxLevel; public uint Level { get; private set; } public BigInteger LevelExp { get; private set; } public Nationality Nationality => property.nationality; public bool IsUnlocked { get => playerProperty.isUnlocked; set { if (playerProperty.isUnlocked == value) return; playerProperty.isUnlocked = value; } } public bool IsSetted => playerProperty.settedSlotIndex != MatePlayerProperty._invalidSlotIndex; public int SettedSlotIndex => playerProperty.settedSlotIndex; public MateData(MateProperty property, MatePlayerProperty playerProperty) { this.property = property; this.playerProperty = playerProperty; LevelExp = BigInteger.Parse(playerProperty.levelExp); Level = GetLevelByExp(LevelExp, Grade); if (SkillDataGroup.Instance.TryGetSkillData(property.skillID, out SkillData skillData)) { Skill = skillData; if(Skill.TryGetStat(StatID.SkillDamage, out var skillDamage)) { for (uint j = Level; j > 1; j--) { var vm = new ValueModifier(ValueModifier.Type.Flat, 20); vm.From = this; skillDamage.AddModifier(vm); } } } } public bool AddLevelExp(BigInteger exp) { LevelExp += exp; playerProperty.levelExp = LevelExp.ToString(); uint prevLevel = Level; Level = GetLevelByExp(LevelExp, Grade, Level); if (prevLevel != Level) { if (Skill.TryGetStat(StatID.SkillDamage, out var skillDamage)) { for (uint j = Level; j > 1; j--) { var vm = new ValueModifier(ValueModifier.Type.Flat, 20); vm.From = this; skillDamage.AddModifier(vm); } } return true; } return false; } public BigInteger GetRequireExpToNextLv() => GetTotalExpToLevel(Level + 1, Grade) - GetTotalExpToLevel(Level, Grade); public void SetSlotIndex(int slotIndex) { if (slotIndex >= GameProperty.Instance.MateMaxCount) return; playerProperty.settedSlotIndex = (byte)slotIndex; } public void RemoveSlotIndex() { playerProperty.settedSlotIndex = MatePlayerProperty._invalidSlotIndex; } public static uint GetLevelByExp(BigInteger exp, uint grade, uint offset = 2) { if (offset < 2) offset = 2; for (uint i = offset; i <= MaxLevel; i++) { if (exp < GetTotalExpToLevel(i, grade)) return i - 1; } return MaxLevel; } public static BigInteger GetTotalExpToLevel(uint level, uint grade) { //TODO : this is temp code const uint baseExp = 10000; const uint expPerLevel = 100000; if (level < 2) return 0; float mulRatePerGrade = 2.5f; if (grade <= 1) mulRatePerGrade = 1.0f; else if (grade == 2) mulRatePerGrade = 1.5f; else if (grade == 3) mulRatePerGrade = 2.0f; else if (grade == 4) mulRatePerGrade = 2.5f; else if (grade == 5) mulRatePerGrade = 3.0f; //require exp for next level //baseExp + (expPerLevel * (level - 2) * mulRatePerGrade) uint a = level - 1; uint b = a - 1; return (BigInteger)baseExp * a + (BigInteger)(Utility.PermutationAdd(b) * expPerLevel * mulRatePerGrade); } public static int CompareByID(MateData a, MateData b) => a.ID.CompareTo(b.ID); public static int CompareBySettedSlotIndex(MateData a, MateData b) => a.playerProperty.settedSlotIndex.CompareTo(b.playerProperty.settedSlotIndex); }