character level up 💪🏻

This commit is contained in:
rfi 2023-11-26 21:08:59 +07:00
parent 11b470e77f
commit e3acdede67
4 changed files with 1130 additions and 3 deletions

View File

@ -5,14 +5,24 @@ using AscNet.Table.share.character;
using AscNet.Table.share.character.skill; using AscNet.Table.share.character.skill;
using AscNet.Common.MsgPack; using AscNet.Common.MsgPack;
using AscNet.Common.Util; using AscNet.Common.Util;
using Newtonsoft.Json;
namespace AscNet.Common.Database namespace AscNet.Common.Database
{ {
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
public class Character public class Character
{ {
public static readonly List<CharacterLevelUpTemplate> levelUpTemplates;
public static readonly IMongoCollection<Character> collection = Common.db.GetCollection<Character>("characters"); public static readonly IMongoCollection<Character> collection = Common.db.GetCollection<Character>("characters");
static Character()
{
if (File.Exists("Data/CharacterLevelUpTemplate.json"))
levelUpTemplates = JsonConvert.DeserializeObject<List<CharacterLevelUpTemplate>>(File.ReadAllText("Data/CharacterLevelUpTemplate.json")) ?? new();
else
levelUpTemplates = new();
}
private uint NextEquipId => Equips.MaxBy(x => x.Id)?.Id + 1 ?? 1; private uint NextEquipId => Equips.MaxBy(x => x.Id)?.Id + 1 ?? 1;
public static Character FromUid(long uid) public static Character FromUid(long uid)
@ -84,7 +94,39 @@ namespace AscNet.Common.Database
Characters.Add(characterData); Characters.Add(characterData);
} }
public UpgradeCharacterResult UpgradeCharacterSkillGroup(uint skillGroupId, int count) public NotifyCharacterDataList.NotifyCharacterDataListCharacterData? AddCharacterExp(int characterId, int exp, int maxLvl = 0)
{
var characterData = TableReaderV2.Parse<Table.V2.share.character.CharacterTable>().FirstOrDefault(x => x.Id == characterId);
var character = Characters.FirstOrDefault(x => x.Id == characterId);
if (character is not null && characterData is not null)
{
levelCheck:
CharacterLevelUpTemplate? levelUpTemplate = levelUpTemplates.FirstOrDefault(x => x.Level == character.Level && x.Type == characterData.Type);
if (levelUpTemplate is not null)
{
if (levelUpTemplate.Exp > exp)
{
character.Exp += (uint)Math.Max(0, exp);
}
else if (maxLvl > 0 && character.Level == maxLvl)
{
character.Exp = (uint)Math.Max(0, levelUpTemplate.Exp);
}
else
{
character.Level++;
exp -= (int)(levelUpTemplate.Exp - character.Exp);
character.Exp = 0;
goto levelCheck;
}
}
}
return character;
}
public UpgradeCharacterSkillResult UpgradeCharacterSkillGroup(uint skillGroupId, int count)
{ {
List<uint> affectedCharacters = new(); List<uint> affectedCharacters = new();
int totalCoinCost = 0; int totalCoinCost = 0;
@ -111,7 +153,7 @@ namespace AscNet.Common.Database
} }
} }
return new UpgradeCharacterResult() return new UpgradeCharacterSkillResult()
{ {
AffectedCharacters = affectedCharacters, AffectedCharacters = affectedCharacters,
CoinCost = totalCoinCost, CoinCost = totalCoinCost,
@ -165,10 +207,25 @@ namespace AscNet.Common.Database
public List<FashionList> Fashions { get; set; } public List<FashionList> Fashions { get; set; }
} }
public struct UpgradeCharacterResult public struct UpgradeCharacterSkillResult
{ {
public int CoinCost { get; init; } public int CoinCost { get; init; }
public int SkillPointCost { get; init; } public int SkillPointCost { get; init; }
public List<uint> AffectedCharacters { get; init; } public List<uint> AffectedCharacters { get; init; }
} }
public partial class CharacterLevelUpTemplate
{
[JsonProperty("Level")]
public int Level { get; set; }
[JsonProperty("Exp")]
public int Exp { get; set; }
[JsonProperty("AllExp")]
public int AllExp { get; set; }
[JsonProperty("Type")]
public int Type { get; set; }
}
} }

View File

@ -0,0 +1,49 @@
using AscNet.Table.V2.share.item;
namespace AscNet.Common
{
public static class TableExtensions
{
public static int GetCharacterExp(this ItemTable item, int cardType)
{
if (item.ItemType == (int)ItemType.CardExp && item.SubTypeParams.Count >= 3)
{
int upType = item.SubTypeParams[0];
int exp = item.SubTypeParams[1];
int upPercentage = item.SubTypeParams[2] / 100 - 100;
int upMultiple = item.SubTypeParams[2] / 10000;
if (cardType == upType)
return (int)MathF.Round(exp * upMultiple);
return exp;
}
return 0;
}
}
enum ItemType
{
Assert = 1 << 0,
Money = 1 << 1 | 1 << 0,
Material = 1 << 2,
Fragment = 1 << 3,
Gift = 1 << 4,
WeaponFashion = 1 << 5,
CardExp = 1 << 11 | 1 << 2,
EquipExp = 1 << 12 | 1 << 2,
EquipExpNotInBag = 1 << 12 | 1 << 3,
EquipResonanace = 1 << 13 | 1 << 2,
FurnitureItem = 1 << 14 | 1 << 2,
ExchangeMoney = 1 << 16 | 1 << 2,
SpExchangeMoney = 1 << 17 | 1 << 2,
UnShow = 1 << 18 | 1 << 2,
FavorGift = 1 << 19 | 1 << 2,
ActiveMoney = 1 << 20 | 1 << 2,
PlayingMoney = 1 << 21 | 1 << 2,
PlayingItem = 1 << 22 | 1 << 2,
TRPGItem = 1 << 23 | 1 << 2,
PartnerExp = 1 << 25 | 1 << 2
}
}

View File

@ -1,8 +1,30 @@
using AscNet.Common.Database; using AscNet.Common.Database;
using AscNet.Common.MsgPack; using AscNet.Common.MsgPack;
using AscNet.Common.Util;
using AscNet.Table.V2.share.item;
using AscNet.Table.V2.share.character;
using MessagePack;
using AscNet.Common;
namespace AscNet.GameServer.Handlers namespace AscNet.GameServer.Handlers
{ {
#region MsgPackScheme
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
[MessagePackObject(true)]
public class CharacterLevelUpRequest
{
public uint TemplateId;
public Dictionary<int, int> UseItems;
}
[MessagePackObject(true)]
public class CharacterLevelUpResponse
{
public int Code;
}
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
#endregion
internal class CharacterModule internal class CharacterModule
{ {
[RequestPacketHandler("CharacterUpgradeSkillGroupRequest")] [RequestPacketHandler("CharacterUpgradeSkillGroupRequest")]
@ -26,5 +48,42 @@ namespace AscNet.GameServer.Handlers
session.SendResponse(new CharacterUpgradeSkillGroupResponse(), packet.Id); session.SendResponse(new CharacterUpgradeSkillGroupResponse(), packet.Id);
} }
[RequestPacketHandler("CharacterLevelUpRequest")]
public static void CharacterLevelUpRequestHandler(Session session, Packet.Request packet)
{
CharacterLevelUpRequest request = packet.Deserialize<CharacterLevelUpRequest>();
CharacterTable? characterData = TableReaderV2.Parse<CharacterTable>().FirstOrDefault(x => x.Id == request.TemplateId);
if (characterData is null || !session.character.Characters.Any(x => x.Id == characterData.Id))
{
// CharacterManagerGetCharacterTemplateNotFound
session.SendResponse(new CharacterLevelUpResponse() { Code = 20009001 }, packet.Id);
return;
}
NotifyItemDataList notifyItemData = new();
int totalExp = 0;
foreach (var item in request.UseItems)
{
ItemTable? itemTable = TableReaderV2.Parse<ItemTable>().FirstOrDefault(x => x.Id == item.Key);
if (itemTable is not null)
{
totalExp += itemTable.GetCharacterExp(characterData.Type) * item.Value;
notifyItemData.ItemDataList.Add(session.inventory.Do(item.Key, item.Value * -1));
}
}
session.SendPush(notifyItemData);
var characterUp = session.character.AddCharacterExp(characterData.Id, totalExp, (int)session.player.PlayerData.Level);
if (characterUp is not null)
{
NotifyCharacterDataList notifyCharacterData = new();
notifyCharacterData.CharacterDataList.Add(characterUp);
session.SendPush(notifyCharacterData);
}
session.SendResponse(new CharacterLevelUpResponse(), packet.Id);
}
} }
} }

View File

@ -0,0 +1,962 @@
[
{
"Level": 1,
"Exp": 20,
"AllExp": 0,
"Type": 1
},
{
"Level": 2,
"Exp": 40,
"AllExp": 0,
"Type": 1
},
{
"Level": 3,
"Exp": 60,
"AllExp": 0,
"Type": 1
},
{
"Level": 4,
"Exp": 80,
"AllExp": 0,
"Type": 1
},
{
"Level": 5,
"Exp": 100,
"AllExp": 0,
"Type": 1
},
{
"Level": 6,
"Exp": 120,
"AllExp": 0,
"Type": 1
},
{
"Level": 7,
"Exp": 140,
"AllExp": 0,
"Type": 1
},
{
"Level": 8,
"Exp": 160,
"AllExp": 0,
"Type": 1
},
{
"Level": 9,
"Exp": 180,
"AllExp": 0,
"Type": 1
},
{
"Level": 10,
"Exp": 200,
"AllExp": 0,
"Type": 1
},
{
"Level": 11,
"Exp": 220,
"AllExp": 0,
"Type": 1
},
{
"Level": 12,
"Exp": 240,
"AllExp": 0,
"Type": 1
},
{
"Level": 13,
"Exp": 260,
"AllExp": 0,
"Type": 1
},
{
"Level": 14,
"Exp": 280,
"AllExp": 0,
"Type": 1
},
{
"Level": 15,
"Exp": 300,
"AllExp": 0,
"Type": 1
},
{
"Level": 16,
"Exp": 320,
"AllExp": 0,
"Type": 1
},
{
"Level": 17,
"Exp": 340,
"AllExp": 0,
"Type": 1
},
{
"Level": 18,
"Exp": 360,
"AllExp": 0,
"Type": 1
},
{
"Level": 19,
"Exp": 380,
"AllExp": 0,
"Type": 1
},
{
"Level": 20,
"Exp": 400,
"AllExp": 0,
"Type": 1
},
{
"Level": 21,
"Exp": 440,
"AllExp": 0,
"Type": 1
},
{
"Level": 22,
"Exp": 480,
"AllExp": 0,
"Type": 1
},
{
"Level": 23,
"Exp": 520,
"AllExp": 0,
"Type": 1
},
{
"Level": 24,
"Exp": 560,
"AllExp": 0,
"Type": 1
},
{
"Level": 25,
"Exp": 600,
"AllExp": 0,
"Type": 1
},
{
"Level": 26,
"Exp": 640,
"AllExp": 0,
"Type": 1
},
{
"Level": 27,
"Exp": 680,
"AllExp": 0,
"Type": 1
},
{
"Level": 28,
"Exp": 720,
"AllExp": 0,
"Type": 1
},
{
"Level": 29,
"Exp": 760,
"AllExp": 0,
"Type": 1
},
{
"Level": 30,
"Exp": 800,
"AllExp": 0,
"Type": 1
},
{
"Level": 31,
"Exp": 960,
"AllExp": 0,
"Type": 1
},
{
"Level": 32,
"Exp": 1120,
"AllExp": 0,
"Type": 1
},
{
"Level": 33,
"Exp": 1280,
"AllExp": 0,
"Type": 1
},
{
"Level": 34,
"Exp": 1440,
"AllExp": 0,
"Type": 1
},
{
"Level": 35,
"Exp": 1600,
"AllExp": 0,
"Type": 1
},
{
"Level": 36,
"Exp": 1760,
"AllExp": 0,
"Type": 1
},
{
"Level": 37,
"Exp": 1920,
"AllExp": 0,
"Type": 1
},
{
"Level": 38,
"Exp": 2080,
"AllExp": 0,
"Type": 1
},
{
"Level": 39,
"Exp": 2240,
"AllExp": 0,
"Type": 1
},
{
"Level": 40,
"Exp": 2400,
"AllExp": 0,
"Type": 1
},
{
"Level": 41,
"Exp": 2640,
"AllExp": 0,
"Type": 1
},
{
"Level": 42,
"Exp": 2880,
"AllExp": 0,
"Type": 1
},
{
"Level": 43,
"Exp": 3120,
"AllExp": 0,
"Type": 1
},
{
"Level": 44,
"Exp": 3360,
"AllExp": 0,
"Type": 1
},
{
"Level": 45,
"Exp": 3600,
"AllExp": 0,
"Type": 1
},
{
"Level": 46,
"Exp": 3840,
"AllExp": 0,
"Type": 1
},
{
"Level": 47,
"Exp": 4080,
"AllExp": 0,
"Type": 1
},
{
"Level": 48,
"Exp": 4320,
"AllExp": 0,
"Type": 1
},
{
"Level": 49,
"Exp": 4560,
"AllExp": 0,
"Type": 1
},
{
"Level": 50,
"Exp": 4800,
"AllExp": 0,
"Type": 1
},
{
"Level": 51,
"Exp": 5280,
"AllExp": 0,
"Type": 1
},
{
"Level": 52,
"Exp": 5760,
"AllExp": 0,
"Type": 1
},
{
"Level": 53,
"Exp": 6240,
"AllExp": 0,
"Type": 1
},
{
"Level": 54,
"Exp": 6720,
"AllExp": 0,
"Type": 1
},
{
"Level": 55,
"Exp": 7200,
"AllExp": 0,
"Type": 1
},
{
"Level": 56,
"Exp": 7680,
"AllExp": 0,
"Type": 1
},
{
"Level": 57,
"Exp": 8160,
"AllExp": 0,
"Type": 1
},
{
"Level": 58,
"Exp": 8640,
"AllExp": 0,
"Type": 1
},
{
"Level": 59,
"Exp": 9120,
"AllExp": 0,
"Type": 1
},
{
"Level": 60,
"Exp": 9600,
"AllExp": 0,
"Type": 1
},
{
"Level": 61,
"Exp": 10440,
"AllExp": 0,
"Type": 1
},
{
"Level": 62,
"Exp": 11280,
"AllExp": 0,
"Type": 1
},
{
"Level": 63,
"Exp": 12120,
"AllExp": 0,
"Type": 1
},
{
"Level": 64,
"Exp": 12960,
"AllExp": 0,
"Type": 1
},
{
"Level": 65,
"Exp": 13800,
"AllExp": 0,
"Type": 1
},
{
"Level": 66,
"Exp": 14640,
"AllExp": 0,
"Type": 1
},
{
"Level": 67,
"Exp": 15480,
"AllExp": 0,
"Type": 1
},
{
"Level": 68,
"Exp": 16320,
"AllExp": 0,
"Type": 1
},
{
"Level": 69,
"Exp": 17160,
"AllExp": 0,
"Type": 1
},
{
"Level": 70,
"Exp": 18000,
"AllExp": 0,
"Type": 1
},
{
"Level": 71,
"Exp": 19200,
"AllExp": 0,
"Type": 1
},
{
"Level": 72,
"Exp": 20400,
"AllExp": 0,
"Type": 1
},
{
"Level": 73,
"Exp": 21600,
"AllExp": 0,
"Type": 1
},
{
"Level": 74,
"Exp": 22800,
"AllExp": 0,
"Type": 1
},
{
"Level": 75,
"Exp": 24000,
"AllExp": 0,
"Type": 1
},
{
"Level": 76,
"Exp": 25200,
"AllExp": 0,
"Type": 1
},
{
"Level": 77,
"Exp": 26400,
"AllExp": 0,
"Type": 1
},
{
"Level": 78,
"Exp": 27600,
"AllExp": 0,
"Type": 1
},
{
"Level": 79,
"Exp": 28800,
"AllExp": 0,
"Type": 1
},
{
"Level": 80,
"Exp": 30000,
"AllExp": 0,
"Type": 1
},
{
"Level": 1,
"Exp": 20,
"AllExp": 0,
"Type": 2
},
{
"Level": 2,
"Exp": 60,
"AllExp": 0,
"Type": 2
},
{
"Level": 3,
"Exp": 100,
"AllExp": 0,
"Type": 2
},
{
"Level": 4,
"Exp": 140,
"AllExp": 0,
"Type": 2
},
{
"Level": 5,
"Exp": 180,
"AllExp": 0,
"Type": 2
},
{
"Level": 6,
"Exp": 240,
"AllExp": 0,
"Type": 2
},
{
"Level": 7,
"Exp": 300,
"AllExp": 0,
"Type": 2
},
{
"Level": 8,
"Exp": 360,
"AllExp": 0,
"Type": 2
},
{
"Level": 9,
"Exp": 420,
"AllExp": 0,
"Type": 2
},
{
"Level": 10,
"Exp": 480,
"AllExp": 0,
"Type": 2
},
{
"Level": 11,
"Exp": 560,
"AllExp": 0,
"Type": 2
},
{
"Level": 12,
"Exp": 640,
"AllExp": 0,
"Type": 2
},
{
"Level": 13,
"Exp": 720,
"AllExp": 0,
"Type": 2
},
{
"Level": 14,
"Exp": 800,
"AllExp": 0,
"Type": 2
},
{
"Level": 15,
"Exp": 880,
"AllExp": 0,
"Type": 2
},
{
"Level": 16,
"Exp": 980,
"AllExp": 0,
"Type": 2
},
{
"Level": 17,
"Exp": 1080,
"AllExp": 0,
"Type": 2
},
{
"Level": 18,
"Exp": 1180,
"AllExp": 0,
"Type": 2
},
{
"Level": 19,
"Exp": 1280,
"AllExp": 0,
"Type": 2
},
{
"Level": 20,
"Exp": 1380,
"AllExp": 0,
"Type": 2
},
{
"Level": 21,
"Exp": 1500,
"AllExp": 0,
"Type": 2
},
{
"Level": 22,
"Exp": 1620,
"AllExp": 0,
"Type": 2
},
{
"Level": 23,
"Exp": 1740,
"AllExp": 0,
"Type": 2
},
{
"Level": 24,
"Exp": 1860,
"AllExp": 0,
"Type": 2
},
{
"Level": 25,
"Exp": 1980,
"AllExp": 0,
"Type": 2
},
{
"Level": 26,
"Exp": 2220,
"AllExp": 0,
"Type": 2
},
{
"Level": 27,
"Exp": 2460,
"AllExp": 0,
"Type": 2
},
{
"Level": 28,
"Exp": 2700,
"AllExp": 0,
"Type": 2
},
{
"Level": 29,
"Exp": 2940,
"AllExp": 0,
"Type": 2
},
{
"Level": 30,
"Exp": 3180,
"AllExp": 0,
"Type": 2
},
{
"Level": 31,
"Exp": 3500,
"AllExp": 0,
"Type": 2
},
{
"Level": 32,
"Exp": 3820,
"AllExp": 0,
"Type": 2
},
{
"Level": 33,
"Exp": 4140,
"AllExp": 0,
"Type": 2
},
{
"Level": 34,
"Exp": 4460,
"AllExp": 0,
"Type": 2
},
{
"Level": 35,
"Exp": 4820,
"AllExp": 0,
"Type": 2
},
{
"Level": 36,
"Exp": 5180,
"AllExp": 0,
"Type": 2
},
{
"Level": 37,
"Exp": 5540,
"AllExp": 0,
"Type": 2
},
{
"Level": 38,
"Exp": 5900,
"AllExp": 0,
"Type": 2
},
{
"Level": 39,
"Exp": 6440,
"AllExp": 0,
"Type": 2
},
{
"Level": 40,
"Exp": 6980,
"AllExp": 0,
"Type": 2
},
{
"Level": 41,
"Exp": 7520,
"AllExp": 0,
"Type": 2
},
{
"Level": 42,
"Exp": 8060,
"AllExp": 0,
"Type": 2
},
{
"Level": 43,
"Exp": 8660,
"AllExp": 0,
"Type": 2
},
{
"Level": 44,
"Exp": 9260,
"AllExp": 0,
"Type": 2
},
{
"Level": 45,
"Exp": 9860,
"AllExp": 0,
"Type": 2
},
{
"Level": 46,
"Exp": 10560,
"AllExp": 0,
"Type": 2
},
{
"Level": 47,
"Exp": 11260,
"AllExp": 0,
"Type": 2
},
{
"Level": 48,
"Exp": 11960,
"AllExp": 0,
"Type": 2
},
{
"Level": 49,
"Exp": 12660,
"AllExp": 0,
"Type": 2
},
{
"Level": 50,
"Exp": 13360,
"AllExp": 0,
"Type": 2
},
{
"Level": 51,
"Exp": 14360,
"AllExp": 0,
"Type": 2
},
{
"Level": 52,
"Exp": 15360,
"AllExp": 0,
"Type": 2
},
{
"Level": 53,
"Exp": 16360,
"AllExp": 0,
"Type": 2
},
{
"Level": 54,
"Exp": 17360,
"AllExp": 0,
"Type": 2
},
{
"Level": 55,
"Exp": 18360,
"AllExp": 0,
"Type": 2
},
{
"Level": 56,
"Exp": 19560,
"AllExp": 0,
"Type": 2
},
{
"Level": 57,
"Exp": 20760,
"AllExp": 0,
"Type": 2
},
{
"Level": 58,
"Exp": 21960,
"AllExp": 0,
"Type": 2
},
{
"Level": 59,
"Exp": 23160,
"AllExp": 0,
"Type": 2
},
{
"Level": 60,
"Exp": 24360,
"AllExp": 0,
"Type": 2
},
{
"Level": 61,
"Exp": 25720,
"AllExp": 0,
"Type": 2
},
{
"Level": 62,
"Exp": 27080,
"AllExp": 0,
"Type": 2
},
{
"Level": 63,
"Exp": 28440,
"AllExp": 0,
"Type": 2
},
{
"Level": 64,
"Exp": 29800,
"AllExp": 0,
"Type": 2
},
{
"Level": 65,
"Exp": 31160,
"AllExp": 0,
"Type": 2
},
{
"Level": 66,
"Exp": 33160,
"AllExp": 0,
"Type": 2
},
{
"Level": 67,
"Exp": 35160,
"AllExp": 0,
"Type": 2
},
{
"Level": 68,
"Exp": 37160,
"AllExp": 0,
"Type": 2
},
{
"Level": 69,
"Exp": 39160,
"AllExp": 0,
"Type": 2
},
{
"Level": 70,
"Exp": 41160,
"AllExp": 0,
"Type": 2
},
{
"Level": 71,
"Exp": 43400,
"AllExp": 0,
"Type": 2
},
{
"Level": 72,
"Exp": 45640,
"AllExp": 0,
"Type": 2
},
{
"Level": 73,
"Exp": 47880,
"AllExp": 0,
"Type": 2
},
{
"Level": 74,
"Exp": 50120,
"AllExp": 0,
"Type": 2
},
{
"Level": 75,
"Exp": 52360,
"AllExp": 0,
"Type": 2
},
{
"Level": 76,
"Exp": 54860,
"AllExp": 0,
"Type": 2
},
{
"Level": 77,
"Exp": 57360,
"AllExp": 0,
"Type": 2
},
{
"Level": 78,
"Exp": 59860,
"AllExp": 0,
"Type": 2
},
{
"Level": 79,
"Exp": 62360,
"AllExp": 0,
"Type": 2
},
{
"Level": 80,
"Exp": 0,
"AllExp": 0,
"Type": 2
}
]