diff --git a/src/common/Edelstein.Common.Gameplay/Constants/EXPTable.cs b/src/common/Edelstein.Common.Gameplay/Constants/EXPTable.cs new file mode 100644 index 000000000..4c00c6138 --- /dev/null +++ b/src/common/Edelstein.Common.Gameplay/Constants/EXPTable.cs @@ -0,0 +1,61 @@ +namespace Edelstein.Common.Gameplay.Constants; + +public static class EXPTable +{ + public static readonly int[] CharacterEXP; + public static readonly int[] PetTameness; + public static readonly int[] TamingMobTameness; + + static EXPTable() + { + CharacterEXP = new int[201]; + CharacterEXP[0] = 15; + CharacterEXP[1] = 15; + CharacterEXP[2] = 34; + CharacterEXP[3] = 57; + CharacterEXP[4] = 92; + CharacterEXP[5] = 135; + CharacterEXP[6] = 372; + CharacterEXP[7] = 560; + CharacterEXP[8] = 840; + CharacterEXP[9] = 1242; + + for (var i = 10; i < 15; i++) CharacterEXP[i] = CharacterEXP[i - 1]; + + for (var i = 15; i < 30; i++) + CharacterEXP[i] = (int)(CharacterEXP[i - 1] * 1.2 + 0.5); + for (var i = 30; i < 35; i++) CharacterEXP[i] = CharacterEXP[i - 1]; + + for (var i = 35; i < 40; i++) + CharacterEXP[i] = (int)(CharacterEXP[i - 1] * 1.2 + 0.5); + for (var i = 40; i < 70; i++) + CharacterEXP[i] = (int)(CharacterEXP[i - 1] * 1.08 + 0.5); + + for (var i = 70; i < 75; i++) CharacterEXP[i] = CharacterEXP[i - 1]; + + for (var i = 75; i < 120; i++) + CharacterEXP[i] = (int)(CharacterEXP[i - 1] * 1.07 + 0.5); + + for (var i = 120; i < 125; i++) CharacterEXP[i] = CharacterEXP[i - 1]; + + for (var i = 125; i < 160; i++) + CharacterEXP[i] = (int)(CharacterEXP[i - 1] * 1.07 + 0.5); + for (var i = 160; i < 200; i++) + CharacterEXP[i] = (int)(CharacterEXP[i - 1] * 1.06 + 0.5); + + CharacterEXP[200] = 0; + + PetTameness = new[] + { + 0x1, 0x3, 0x6, 0xE, 0x1F, 0x3C, 0x6C, 0x0B5, 0x11F, 0x1B2, + 0x278, 0x37B, 0x4C8, 0x66A, 0x871, 0x0AE9, 0x0DE5, 0x1173, 0x15A6, 0x1A91, + 0x2047, 0x26DE, 0x2E6A, 0x3704, 0x40C2, 0x4BBF, 0x5813, 0x65DA, 0x7530, 0x0 + }; + TamingMobTameness = new[] + { + 0x0, 0x14, 0x2D, 0x4B, 0x6F, 0x99, 0x0C9, 0x100, 0x13F, 0x185, + 0x1D3, 0x22A, 0x28B, 0x2F5, 0x36A, 0x3EB, 0x478, 0x511, 0x5B8, 0x66E, + 0x734, 0x80A, 0x8F2, 0x9ED, 0x0AFC, 0x0C21, 0x0D5C, 0x0EB0, 0x101E, 0x11A8 + }; + } +} diff --git a/src/common/Edelstein.Common.Gameplay/Models/Characters/Stats/Modify/ModifyStatContext.cs b/src/common/Edelstein.Common.Gameplay/Models/Characters/Stats/Modify/ModifyStatContext.cs index 010212d43..31a7f037f 100644 --- a/src/common/Edelstein.Common.Gameplay/Models/Characters/Stats/Modify/ModifyStatContext.cs +++ b/src/common/Edelstein.Common.Gameplay/Models/Characters/Stats/Modify/ModifyStatContext.cs @@ -169,8 +169,24 @@ public int EXP get => _character.EXP; set { + if (Level >= 200 || JobConstants.GetJobRace(Job) == 1 && Level >= 120) + { + if (_character.EXP > 0) + value = 0; + else return; + } + Flag |= ModifyStatType.EXP; _character.EXP = value; + + if (EXP < EXPTable.CharacterEXP[_character.Level]) return; + + _character.EXP = Math.Max(0, Math.Min( + EXPTable.CharacterEXP[_character.Level] - 1, + _character.EXP - EXPTable.CharacterEXP[_character.Level - 1] + )); + + LevelUp(); } } @@ -206,12 +222,64 @@ public int TempEXP public void IncExtendSP(byte jobLevel, byte amount) => SetExtendSP(jobLevel, (byte)((_character.ExtendSP[jobLevel] ?? 0) + amount)); - + public void SetExtendSP(byte jobLevel, byte amount) { Flag |= ModifyStatType.SP; _character.ExtendSP.Records[jobLevel] = amount; } + + public void LevelUp() + { + if (Level >= 200 || JobConstants.GetJobRace(Job) == 1 && Level >= 120) return; + + Level++; + + var random = new Random(); + var hpBonus = random.Next(10, 16); + var mpBonus = random.Next(10, 12); + // TODO proper values + + MaxHP = Math.Min(999999, MaxHP + hpBonus); + MaxMP = Math.Min(999999, MaxMP + mpBonus); + + if (HP < MaxHP) HP = MaxHP; + if (MP < MaxMP) MP = MaxMP; + + if (Level <= 10) return; + if (JobConstants.IsExtendSPJob(Job)) + { + byte jobLevel = 0; + + if (JobConstants.GetJobRace(Job) == 2 && JobConstants.GetJobType(Job) == 2) + { + if (Level <= 200) jobLevel = 10; + if (Level <= 160) jobLevel = 9; + if (Level <= 120) jobLevel = 8; + if (Level <= 100) jobLevel = 7; + if (Level <= 80) jobLevel = 6; + if (Level <= 60) jobLevel = 5; + if (Level <= 50) jobLevel = 4; + if (Level <= 40) jobLevel = 3; + if (Level <= 30) jobLevel = 2; + if (Level <= 20) jobLevel = 1; + } + else + { + if (Level <= 200) jobLevel = 4; + if (Level <= 120) jobLevel = 3; + if (Level <= 70) jobLevel = 2; + if (Level <= 30) jobLevel = 1; + } + + if (jobLevel > 0) IncExtendSP(jobLevel, 3); + } + else SP += 3; + AP += 5; + + if (Level >= 200 || JobConstants.GetJobRace(Job) == 1 && Level >= 120) + EXP = 0; + } public void WriteTo(IPacketWriter writer) { diff --git a/src/protocol/Edelstein.Protocol.Gameplay/Models/Characters/Stats/Modify/IModifyStatContext.cs b/src/protocol/Edelstein.Protocol.Gameplay/Models/Characters/Stats/Modify/IModifyStatContext.cs index ae873c386..c0f0ad96c 100644 --- a/src/protocol/Edelstein.Protocol.Gameplay/Models/Characters/Stats/Modify/IModifyStatContext.cs +++ b/src/protocol/Edelstein.Protocol.Gameplay/Models/Characters/Stats/Modify/IModifyStatContext.cs @@ -37,4 +37,7 @@ public interface IModifyStatContext : IPacketWritable int TempEXP { get; set; } void SetExtendSP(byte jobLevel, byte amount); + void IncExtendSP(byte jobLevel, byte amount); + + void LevelUp(); }