diff --git a/Common/Data/Custom/GridFightBasicOrbRewardsConfig.cs b/Common/Data/Custom/GridFightBasicOrbRewardsConfig.cs new file mode 100644 index 00000000..8ebe007a --- /dev/null +++ b/Common/Data/Custom/GridFightBasicOrbRewardsConfig.cs @@ -0,0 +1,14 @@ +using EggLink.DanhengServer.Data.Excel; + +namespace EggLink.DanhengServer.Data.Custom; + +public class GridFightBasicOrbRewardsConfig +{ + public Dictionary OrbRewards { get; set; } = []; +} + +public class GridFightBasicOrbRewardsInfo +{ + public uint OrbId { get; set; } + public Dictionary> Rewards { get; set; } = []; +} \ No newline at end of file diff --git a/Common/Data/Excel/GridFightBasicBonusPoolV2Excel.cs b/Common/Data/Excel/GridFightBasicBonusPoolV2Excel.cs new file mode 100644 index 00000000..4ddcd1a4 --- /dev/null +++ b/Common/Data/Excel/GridFightBasicBonusPoolV2Excel.cs @@ -0,0 +1,27 @@ +using EggLink.DanhengServer.Enums.GridFight; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; + +namespace EggLink.DanhengServer.Data.Excel; + +[ResourceEntity("GridFightBasicBonusPoolV2.json")] +public class GridFightBasicBonusPoolV2Excel : ExcelResource +{ + public uint BonusID { get; set; } + public uint Value { get; set; } + public uint BonusTypeParam { get; set; } + public List BonusTypeParamList { get; set; } = []; + + [JsonConverter(typeof(StringEnumConverter))] + public GridFightBonusTypeEnum BonusType { get; set; } + + public override int GetId() + { + return (int)BonusID; + } + + public override void Loaded() + { + GameData.GridFightBasicBonusPoolV2Data.TryAdd(BonusID, this); + } +} \ No newline at end of file diff --git a/Common/Data/Excel/GridFightEquipmentExcel.cs b/Common/Data/Excel/GridFightEquipmentExcel.cs index 5add3840..792e309b 100644 --- a/Common/Data/Excel/GridFightEquipmentExcel.cs +++ b/Common/Data/Excel/GridFightEquipmentExcel.cs @@ -16,6 +16,12 @@ public class GridFightEquipmentExcel : ExcelResource [JsonConverter(typeof(StringEnumConverter))] public GridFightEquipDressTypeEnum DressRule { get; set; } + [JsonConverter(typeof(StringEnumConverter))] + public GridFightEquipFuncTypeEnum EquipFunc { get; set; } + + public List EquipFuncParamList { get; set; } = []; + public List DressRuleParamList { get; set; } = []; + public override int GetId() { return (int)ID; diff --git a/Common/Data/GameData.cs b/Common/Data/GameData.cs index dc648272..23d8676b 100644 --- a/Common/Data/GameData.cs +++ b/Common/Data/GameData.cs @@ -119,6 +119,8 @@ public static class GameData #region GridFight + public static GridFightBasicOrbRewardsConfig GridFightBasicOrbRewardsConfig { get; set; } = new(); + public static Dictionary GridFightBasicBonusPoolV2Data { get; private set; } = []; public static Dictionary GridFightRoleBasicInfoData { get; private set; } = []; public static Dictionary GridFightRoleStarData { get; private set; } = []; public static Dictionary GridFightRoleRecommendEquipData { get; private set; } = diff --git a/Common/Data/ResourceManager.cs b/Common/Data/ResourceManager.cs index 60e75f8b..92170a5e 100644 --- a/Common/Data/ResourceManager.cs +++ b/Common/Data/ResourceManager.cs @@ -52,11 +52,13 @@ public class ResourceManager GameData.RogueMiracleEffectData = LoadCustomFile("Rogue Miracle Effect", "RogueMiracleEffectGen") ?? new RogueMiracleEffectConfig(); + LoadChessRogueRoomData(); LoadRogueTournRoomData(); LoadChessRogueDiceSurfaceEffectData(); LoadRogueMagicRoomData(); LoadRogueDialogueEventData(); + LoadGridFightBasicRewardsData(); Task.WaitAll(t1, t2, t3, t4, t5, t6, t7, t8, t9); @@ -1105,6 +1107,49 @@ public class ResourceManager I18NManager.Translate("Word.DialogueInfo"))); } + public static void LoadGridFightBasicRewardsData() + { + Logger.Info(I18NManager.Translate("Server.ServerInfo.LoadingItem", + I18NManager.Translate("Word.GridFightRewardsInfo"))); + var count = 0; + + FileInfo file = new(ConfigManager.Config.Path.ConfigPath + "/GridFight/GridFightBasicOrbRewards.json"); + if (!file.Exists) + { + Logger.Warn(I18NManager.Translate("Server.ServerInfo.ConfigMissing", + I18NManager.Translate("Word.GridFightRewardsInfo"), + $"{ConfigManager.Config.Path.ConfigPath}/GridFight/GridFightBasicOrbRewards.json", + I18NManager.Translate("Word.GridFightRewards"))); + return; + } + + try + { + using var reader = file.OpenRead(); + using StreamReader reader2 = new(reader); + var text = reader2.ReadToEnd(); + var json = JsonConvert.DeserializeObject>>>(text); + if (json == null) throw new Exception("Failed to deserialize GridFightBasicOrbRewards.json"); + foreach (var reward in json) + { + GameData.GridFightBasicOrbRewardsConfig.OrbRewards.Add(reward.Key, new GridFightBasicOrbRewardsInfo + { + OrbId = reward.Key, + Rewards = reward.Value + }); + count++; + } + } + catch (Exception ex) + { + ResourceCache.IsComplete = false; + Logger.Error("Error in reading " + file.Name, ex); + } + + Logger.Info(I18NManager.Translate("Server.ServerInfo.LoadedItems", count.ToString(), + I18NManager.Translate("Word.GridFightRewardsInfo"))); + } + public static void AddRoomToGameData(RogueDLCBlockTypeEnum type, ChessRogueRoomConfig room) { if (GameData.ChessRogueRoomData.TryGetValue(type, out var list)) diff --git a/Common/Enums/GridFight/GridFightBonusTypeEnum.cs b/Common/Enums/GridFight/GridFightBonusTypeEnum.cs new file mode 100644 index 00000000..46a1a362 --- /dev/null +++ b/Common/Enums/GridFight/GridFightBonusTypeEnum.cs @@ -0,0 +1,15 @@ +namespace EggLink.DanhengServer.Enums.GridFight; + +public enum GridFightBonusTypeEnum +{ + Gold = 0, + Refresh = 2, + SpecificAvatar = 5, + RandomAvatar = 6, + Item = 7, + Exp = 8, + Orb = 9, + RandomEquipByCategory = 13, + RandomEquipByFunc = 14, + RandomSameAvatar = 15 +} \ No newline at end of file diff --git a/Common/Enums/GridFight/GridFightEquipFuncTypeEnum.cs b/Common/Enums/GridFight/GridFightEquipFuncTypeEnum.cs new file mode 100644 index 00000000..b3c31c65 --- /dev/null +++ b/Common/Enums/GridFight/GridFightEquipFuncTypeEnum.cs @@ -0,0 +1,13 @@ +namespace EggLink.DanhengServer.Enums.GridFight; + +public enum GridFightEquipFuncTypeEnum +{ + None = 0, + Emblem = 1, + AvatarMaxNumberAdd = 2, + Leader = 3, + CraftableThiefGlove = 5, + RadiantThiefGlove = 6, + OriginEmblem = 10, + ClassEmblem = 11 +} \ No newline at end of file diff --git a/Config/GridFight/GridFightBasicOrbRewards.json b/Config/GridFight/GridFightBasicOrbRewards.json new file mode 100644 index 00000000..166c0c4f --- /dev/null +++ b/Config/GridFight/GridFightBasicOrbRewards.json @@ -0,0 +1,169 @@ +{ + "199": { + "0": [ + { + "BonusType": "Gold", + "Value": 2 + } + ] + }, + "102": { + "0": [ + { + "BonusType": "Item", + "BonusTypeParamList": [ + 350103 + ], + "Value": 1 + } + ], + "1": [ + { + "BonusType": "Item", + "BonusTypeParamList": [ + 350105 + ], + "Value": 1 + } + ] + }, + "203": { + "0": [ + { + "BonusType": "RandomEquipByCategory", + "BonusTypeParamList": [ + 1 + ], + "Value": 1 + } + ] + }, + "204": { + "0": [ + { + "BonusType": "Gold", + "Value": 3 + }, + { + "BonusType": "RandomAvatar", + "BonusTypeParamList": [ + 2, + 1 + ], + "Value": 2 + } + ] + }, + "206": { + "0": [ + { + "BonusType": "RandomAvatar", + "BonusTypeParamList": [ + 3, + 1 + ], + "Value": 3 + } + ], + "1": [ + { + "BonusType": "RandomAvatar", + "BonusTypeParamList": [ + 1, + 1 + ], + "Value": 1 + }, + { + "BonusType": "RandomAvatar", + "BonusTypeParamList": [ + 1, + 1 + ], + "Value": 1 + } + ] + }, + "207": { + "0": [ + { + "BonusType": "RandomAvatar", + "BonusTypeParamList": [ + 4, + 1 + ], + "Value": 4 + } + ], + "1": [ + { + "BonusType": "RandomAvatar", + "BonusTypeParamList": [ + 3, + 1 + ], + "Value": 3 + }, + { + "BonusType": "RandomAvatar", + "BonusTypeParamList": [ + 3, + 1 + ], + "Value": 3 + } + ], + "2": [ + { + "BonusType": "RandomAvatar", + "BonusTypeParamList": [ + 3, + 2 + ], + "Value": 3 + } + ] + }, + "208": { + "0": [ + { + "BonusType": "RandomAvatar", + "BonusTypeParamList": [ + 4, + 1 + ], + "Value": 4 + }, + { + "BonusType": "RandomAvatar", + "BonusTypeParamList": [ + 4, + 1 + ], + "Value": 4 + } + ] + }, + "120031": { + "0": [ + { + "BonusType": "Item", + "BonusTypeParamList": [ + 99998 + ] + } + ] + }, + "123105": { + "0": [ + { + "BonusType": "RandomAvatar", + "BonusTypeParamList": [ + 4, + 2 + ], + "Value": 4 + } + ] + } +} \ No newline at end of file diff --git a/GameServer/Game/GridFight/Component/GridFightItemsComponent.cs b/GameServer/Game/GridFight/Component/GridFightItemsComponent.cs index f1387e36..339f5170 100644 --- a/GameServer/Game/GridFight/Component/GridFightItemsComponent.cs +++ b/GameServer/Game/GridFight/Component/GridFightItemsComponent.cs @@ -1,4 +1,5 @@ using EggLink.DanhengServer.Data; +using EggLink.DanhengServer.Data.Excel; using EggLink.DanhengServer.Enums.GridFight; using EggLink.DanhengServer.GameServer.Game.GridFight.PendingAction; using EggLink.DanhengServer.GameServer.Game.GridFight.Sync; @@ -79,10 +80,10 @@ public class GridFightItemsComponent(GridFightInstance inst) : BaseGridFightComp } BaseGridFightSyncData syncData = isRemove - ? new GridFightRemoveGameItemSyncData(src, [], [existingItem.ToUpdateInfo(count)], 0, param) + ? new GridFightRemoveGameItemSyncData(src, [], [existingItem.ToUpdateInfo(count)], groupId, param) : isUpdate - ? new GridFightUpdateGameItemSyncData(src, [], [existingItem.ToUpdateInfo(count)], 0, param) - : new GridFightAddGameItemSyncData(src, [], [existingItem.ToUpdateInfo(count)], 0, param); + ? new GridFightUpdateGameItemSyncData(src, [], [existingItem.ToUpdateInfo(count)], groupId, param) + : new GridFightAddGameItemSyncData(src, [], [existingItem.ToUpdateInfo(count)], groupId, param); if (sendPacket) await Inst.Player.SendPacket(new PacketGridFightSyncUpdateResultScNotify(syncData)); @@ -156,7 +157,9 @@ public class GridFightItemsComponent(GridFightInstance inst) : BaseGridFightComp #region Rewards - public async ValueTask> TakeDrop(List drops, bool sendPacket = false, GridFightSrc src = GridFightSrc.KGridFightSrcNone, uint groupId = 0, params uint[] param) + public async ValueTask> TakeDrop(List drops, + bool sendPacket = false, GridFightSrc src = GridFightSrc.KGridFightSrcNone, uint groupId = 0, + params uint[] param) { var syncs = new List(); var basicComp = Inst.GetComponent(); @@ -170,52 +173,52 @@ public class GridFightItemsComponent(GridFightInstance inst) : BaseGridFightComp switch (item.DropType) { case GridFightDropType.Coin: - { - await basicComp.UpdateGoldNum((int)item.Num, false); - syncs.Add(new GridFightGoldSyncData(src, basicComp.Data, groupId, param)); - break; - } + { + await basicComp.UpdateGoldNum((int)item.Num, false); + syncs.Add(new GridFightGoldSyncData(src, basicComp.Data, groupId, param)); + break; + } case GridFightDropType.Exp: - { - await basicComp.AddLevelExp(item.Num, false); - syncs.Add(new GridFightPlayerLevelSyncData(src, basicComp.Data, groupId, param)); - break; - } + { + await basicComp.AddLevelExp(item.Num, false); + syncs.Add(new GridFightPlayerLevelSyncData(src, basicComp.Data, groupId, param)); + break; + } case GridFightDropType.Refresh: - { - shopComp.Data.FreeRefreshCount += item.Num; - syncs.Add(new GridFightShopSyncData(src, shopComp.Data, basicComp.Data.CurLevel, groupId, param)); - break; - } + { + shopComp.Data.FreeRefreshCount += item.Num; + syncs.Add(new GridFightShopSyncData(src, shopComp.Data, basicComp.Data.CurLevel, groupId, param)); + break; + } case GridFightDropType.Role: - { - syncs.AddRange(await roleComp.AddAvatar(item.DropItemId, item.DisplayValue.Tier, false, true, - src, groupId, 0, param)); - break; - } + { + syncs.AddRange(await roleComp.AddAvatar(item.DropItemId, item.DisplayValue.Tier, false, true, + src, groupId, 0, param)); + break; + } case GridFightDropType.Item: + { + // consumable or equipment + if (GameData.GridFightConsumablesData.ContainsKey(item.DropItemId)) { - // consumable or equipment - if (GameData.GridFightConsumablesData.ContainsKey(item.DropItemId)) + syncs.AddRange(await UpdateConsumable(item.DropItemId, (int)item.Num, src, false, 0, param)); + } + else if (GameData.GridFightEquipmentData.ContainsKey(item.DropItemId)) + { + for (uint i = 0; i < item.Num; i++) { - syncs.AddRange(await UpdateConsumable(item.DropItemId, (int)item.Num, src, false, 0, param)); - } - else if (GameData.GridFightEquipmentData.ContainsKey(item.DropItemId)) - { - for (uint i = 0; i < item.Num; i++) - { - syncs.AddRange((await AddEquipment(item.DropItemId, src, false, groupId, param)).Item2); - } + syncs.AddRange((await AddEquipment(item.DropItemId, src, false, groupId, param)).Item2); } + } - break; - } + break; + } case GridFightDropType.Orb: - { - // add orbs - syncs.AddRange(await orbComp.AddOrb(item.DropItemId, src, false, groupId, param)); - break; - } + { + // add orbs + syncs.AddRange(await orbComp.AddOrb(item.DropItemId, src, false, groupId, param)); + break; + } } } @@ -227,6 +230,194 @@ public class GridFightItemsComponent(GridFightInstance inst) : BaseGridFightComp return syncs; } + public async ValueTask<(List, List)> TakeBasicBonusItems( + List bonuses, GridFightSrc src = GridFightSrc.KGridFightSrcNone, uint groupId = 0, bool sendPacket = true) + { + var basicComp = Inst.GetComponent(); + var shopComp = Inst.GetComponent(); + var roleComp = Inst.GetComponent(); + var orbComp = Inst.GetComponent(); + + List syncs = []; + List drops = []; + + foreach (var bonus in bonuses) + { + // get drop + switch (bonus.BonusType) + { + case GridFightBonusTypeEnum.Gold: + { + // add gold + await basicComp.UpdateGoldNum((int)bonus.Value, false); + syncs.Add(new GridFightGoldSyncData(src, basicComp.Data, groupId)); + + drops.Add(new GridFightDropItemInfo + { + DropType = GridFightDropType.Coin, + Num = bonus.Value + }); + break; + } + case GridFightBonusTypeEnum.Refresh: + { + // add refresh count + shopComp.Data.FreeRefreshCount += bonus.Value; + syncs.Add(new GridFightShopSyncData(src, shopComp.Data.Clone(), basicComp.Data.CurLevel, groupId)); + + drops.Add(new GridFightDropItemInfo + { + DropType = GridFightDropType.Refresh, + Num = bonus.Value + }); + break; + } + case GridFightBonusTypeEnum.SpecificAvatar: + { + // add role + var roleId = bonus.BonusTypeParamList[0]; + var tier = bonus.BonusTypeParamList[1]; + + syncs.AddRange(await roleComp.AddAvatar(roleId, tier, false, true, src, groupId)); + + drops.Add(new GridFightDropItemInfo + { + DisplayValue = new GridDropItemDisplayInfo + { + Tier = tier + }, + DropItemId = roleId, + DropType = GridFightDropType.Role, + Num = 1 + }); + break; + } + case GridFightBonusTypeEnum.RandomAvatar: + { + // add random role + var rarity = bonus.BonusTypeParamList[0]; + var tier = bonus.BonusTypeParamList[1]; + + var role = GameData.GridFightRoleBasicInfoData.Values.Where(x => x.Rarity == rarity && x.IsInPool) + .ToList() + .RandomElement(); + + syncs.AddRange(await roleComp.AddAvatar(role.ID, tier, false, true, src, groupId)); + + drops.Add(new GridFightDropItemInfo + { + DisplayValue = new GridDropItemDisplayInfo + { + Tier = tier + }, + DropItemId = role.ID, + DropType = GridFightDropType.Role, + Num = 1 + }); + break; + } + case GridFightBonusTypeEnum.Item: + { + // consumable or equipment + var itemId = bonus.BonusTypeParamList[0]; + + drops.Add(new GridFightDropItemInfo + { + DropItemId = itemId, + Num = 1, + DropType = GridFightDropType.Item + }); + + // check if consumable or equipment + if (GameData.GridFightEquipmentData.ContainsKey(itemId)) + { + syncs.AddRange((await AddEquipment(itemId, src, false, groupId)).Item2); + + } + else if (GameData.GridFightConsumablesData.ContainsKey(itemId)) + { + syncs.AddRange(await UpdateConsumable(itemId, 1, src, false, groupId)); + } + + break; + } + case GridFightBonusTypeEnum.Exp: + { + // add exp + await basicComp.AddLevelExp(bonus.Value, false); + syncs.Add(new GridFightPlayerLevelSyncData(src, basicComp.Data, groupId)); + + drops.Add(new GridFightDropItemInfo + { + DropType = GridFightDropType.Exp, + Num = bonus.Value + }); + break; + } + case GridFightBonusTypeEnum.Orb: + { + // add orbs + var orbId = bonus.BonusTypeParamList[0]; + syncs.AddRange(await orbComp.AddOrb(orbId, src, false, groupId)); + + drops.Add(new GridFightDropItemInfo + { + DropItemId = orbId, + DropType = GridFightDropType.Orb, + Num = bonus.Value + }); + break; + } + case GridFightBonusTypeEnum.RandomEquipByCategory: + { + var category = bonus.BonusTypeParamList[0]; + + var equip = GameData.GridFightEquipmentData.Values.Where(x => (int)x.EquipCategory == category) + .ToList().RandomElement(); + + syncs.AddRange((await AddEquipment(equip.ID, src, false, groupId)).Item2); + + drops.Add(new GridFightDropItemInfo + { + DropItemId = equip.ID, + DropType = GridFightDropType.Item, + Num = 1 + }); + break; + } + case GridFightBonusTypeEnum.RandomEquipByFunc: + { + var func = bonus.BonusTypeParamList[0]; + + var equip = GameData.GridFightEquipmentData.Values.Where(x => (int)x.EquipFunc == func) + .ToList().RandomElement(); + + syncs.AddRange((await AddEquipment(equip.ID, src, false, groupId)).Item2); + + drops.Add(new GridFightDropItemInfo + { + DropItemId = equip.ID, + DropType = GridFightDropType.Item, + Num = 1 + }); + break; + } + case GridFightBonusTypeEnum.RandomSameAvatar: + { + // TODO (not used in official server) + break; + } + } + } + + if (syncs.Count > 0 && sendPacket) + { + await Inst.Player.SendPacket(new PacketGridFightSyncUpdateResultScNotify(syncs)); + } + + return (syncs, drops); + } + #endregion #region Consumables diff --git a/GameServer/Game/GridFight/Component/GridFightLevelComponent.cs b/GameServer/Game/GridFight/Component/GridFightLevelComponent.cs index 87782a15..1ef46246 100644 --- a/GameServer/Game/GridFight/Component/GridFightLevelComponent.cs +++ b/GameServer/Game/GridFight/Component/GridFightLevelComponent.cs @@ -597,6 +597,7 @@ public class GridFightGameEncounterInfo public class GridFightGameMonsterWaveInfo { + public static readonly List> OrbList = [[102, 199], [203, 204, 205, 206, 207, 208], [120031]]; public GridFightGameMonsterWaveInfo(uint wave, List monsters, uint campId, uint addOrbNum = 0) { @@ -611,9 +612,12 @@ public class GridFightGameMonsterWaveInfo { DropType = GridFightDropType.Orb, Num = 1, - DropItemId = GameData.GridFightOrbData.Values - .Where(x => x.Type is GridFightOrbTypeEnum.White or GridFightOrbTypeEnum.Blue).ToList() - .RandomElement().OrbID + DropItemId = Random.Shared.Next(10) switch + { + > 5 and < 9 => OrbList[1].RandomElement(), + 9 => OrbList[2].RandomElement(), + _ => OrbList[0].RandomElement() + } }); addOrbNum--; @@ -681,8 +685,6 @@ public static class GridFightEncounterGenerateHelper case GridFightNodeTypeEnum.Boss: return GenerateBossType(section); - default: - break; } return []; diff --git a/GameServer/Game/GridFight/Component/GridFightOrbComponent.cs b/GameServer/Game/GridFight/Component/GridFightOrbComponent.cs index df3ab0bd..d2fa9472 100644 --- a/GameServer/Game/GridFight/Component/GridFightOrbComponent.cs +++ b/GameServer/Game/GridFight/Component/GridFightOrbComponent.cs @@ -1,4 +1,5 @@ using EggLink.DanhengServer.Data; +using EggLink.DanhengServer.Data.Excel; using EggLink.DanhengServer.Enums.GridFight; using EggLink.DanhengServer.GameServer.Game.GridFight.Sync; using EggLink.DanhengServer.GameServer.Server.Packet.Send.GridFight; @@ -50,7 +51,7 @@ public class GridFightOrbComponent(GridFightInstance inst) : BaseGridFightCompon syncDatas.Add(new GridFightRemoveOrbSyncData(GridFightSrc.KGridFightSrcUseOrb, orb, uniqueId, uniqueId, orb.OrbItemId)); // open orb effect - var res = await TakeOrbEffect(excel.Type, uniqueId); + var res = await TakeOrbEffect(excel, uniqueId); syncDatas.AddRange(res.Item1); await Inst.Player.SendPacket(new PacketGridFightUseOrbNotify(uniqueId, res.Item2)); @@ -60,7 +61,57 @@ public class GridFightOrbComponent(GridFightInstance inst) : BaseGridFightCompon await Inst.Player.SendPacket(new PacketGridFightSyncUpdateResultScNotify(syncDatas)); } - private async ValueTask<(List, List)> TakeOrbEffect(GridFightOrbTypeEnum type, uint groupId) + private async ValueTask<(List, List)> TakeOrbEffect( + GridFightOrbExcel excel, uint groupId) + { + List bonusPools = []; + + // check file bonus + if (GameData.GridFightBasicOrbRewardsConfig.OrbRewards.TryGetValue(excel.OrbID, out var fileBonusInfo)) + { + bonusPools.AddRange(fileBonusInfo.Rewards.Values.ToList().RandomElement()); + } + + // check combination bonus + if (bonusPools.Count == 0 && GameData.GridFightCombinationBonusData.TryGetValue(excel.BonusID, out var comboBonusInfo)) + { + for (var i = 0; i < comboBonusInfo.CombinationBonusList.Count; i++) + { + var bonusId = comboBonusInfo.CombinationBonusList[i]; + var bonusNum = comboBonusInfo.BonusNumberList[i]; + + if (bonusId == 1) + bonusPools.Add(new GridFightBasicBonusPoolV2Excel + { + BonusType = GridFightBonusTypeEnum.Gold, + Value = bonusNum / 10000 + }); + else if (GameData.GridFightBasicBonusPoolV2Data.TryGetValue(bonusId, out var bonusPool)) + { + bonusPools.AddRange(Enumerable.Repeat(bonusPool, (int)(bonusNum / 10000))); + } + } + } + + // check basic bonus + if (bonusPools.Count == 0 && GameData.GridFightBasicBonusPoolV2Data.TryGetValue(excel.BonusID, out var basicBonusInfo)) + { + bonusPools.Add(basicBonusInfo); + } + + // execute + if (bonusPools.Count > 0) + { + var itemsComp = Inst.GetComponent(); + + return await itemsComp.TakeBasicBonusItems(bonusPools, GridFightSrc.KGridFightSrcUseOrb, groupId, false); + } + + // default + return await TakeOrbDefaultEffect(excel.Type, groupId); + } + + private async ValueTask<(List, List)> TakeOrbDefaultEffect(GridFightOrbTypeEnum type, uint groupId) { List syncDatas = []; List dropItems = []; diff --git a/GameServer/Game/GridFight/Component/GridFightRoleComponent.cs b/GameServer/Game/GridFight/Component/GridFightRoleComponent.cs index 0b9a0e90..c1ecf51c 100644 --- a/GameServer/Game/GridFight/Component/GridFightRoleComponent.cs +++ b/GameServer/Game/GridFight/Component/GridFightRoleComponent.cs @@ -32,7 +32,7 @@ public class GridFightRoleComponent(GridFightInstance inst) : BaseGridFightCompo // get first empty pos var usedPos = Data.Roles.Select(x => x.Pos).ToHashSet(); - for (var i = initialPos; i <= PrepareAreaPos + 9; i++) + for (var i = initialPos; i <= PrepareAreaPos + 999; i++) // temp store area { if (usedPos.Contains(i)) continue; pos = i; diff --git a/GameServer/Game/GridFight/Component/GridFightShopComponent.cs b/GameServer/Game/GridFight/Component/GridFightShopComponent.cs index 58653460..7f40e949 100644 --- a/GameServer/Game/GridFight/Component/GridFightShopComponent.cs +++ b/GameServer/Game/GridFight/Component/GridFightShopComponent.cs @@ -37,7 +37,7 @@ public class GridFightShopComponent(GridFightInstance inst) : BaseGridFightCompo var avatarComp = Inst.GetComponent(); // check pos - if (!avatarComp.HasAnyEmptyPos()) return Retcode.RetGridFightNoEmptyPos; + //if (!avatarComp.HasAnyEmptyPos()) return Retcode.RetGridFightNoEmptyPos; var curLevel = Inst.GetComponent().Data.CurLevel; diff --git a/GameServer/Game/GridFight/Component/GridFightTraitComponent.cs b/GameServer/Game/GridFight/Component/GridFightTraitComponent.cs index 413e5c28..7894f201 100644 --- a/GameServer/Game/GridFight/Component/GridFightTraitComponent.cs +++ b/GameServer/Game/GridFight/Component/GridFightTraitComponent.cs @@ -14,6 +14,7 @@ public class GridFightTraitComponent(GridFightInstance inst) : BaseGridFightComp public async ValueTask CheckTrait() { + var itemsComp = Inst.GetComponent(); var roleComp = Inst.GetComponent(); Dictionary traitCount = []; @@ -32,6 +33,25 @@ public class GridFightTraitComponent(GridFightInstance inst) : BaseGridFightComp { traitCount[traitId]++; // increase count } + + // get extra traits from equipments + foreach (var equipmentUid in role.EquipmentIds) + { + var equipmentItem = itemsComp.Data.EquipmentItems.FirstOrDefault(x => x.UniqueId == equipmentUid); + if (equipmentItem == null) continue; + + // get conf + var equipmentExcel = GameData.GridFightEquipmentData.GetValueOrDefault(equipmentItem.ItemId); + if (equipmentExcel == null) continue; + + // check category + if (equipmentExcel.EquipCategory != GridFightEquipCategoryEnum.Emblem) continue; + + foreach (var traitId in equipmentExcel.EquipFuncParamList) + { + traitCount[traitId]++; // increase count + } + } } foreach (var (traitId, count) in traitCount) @@ -228,10 +248,39 @@ public static class GridFightTraitInfoPbExtensions public static BattleGridFightTraitInfo ToBattleInfo(this GridFightGameTraitPb info, GridFightRoleComponent roleComp) { - var traitRoles = roleComp.Data.Roles.Where(x => - x.Pos <= GridFightRoleComponent.PrepareAreaPos && GameData.GridFightRoleBasicInfoData - .GetValueOrDefault(x.RoleId)?.TraitList.Contains(info.TraitId) == true).ToList(); + var onGroundRoles = roleComp.Data.Roles.Where(x => x.Pos <= GridFightRoleComponent.PrepareAreaPos).ToList(); + var traitRoles = onGroundRoles.Where(x => GameData.GridFightRoleBasicInfoData + .GetValueOrDefault(x.RoleId)?.TraitList.Contains(info.TraitId) == true).ToList(); + // check equipment traits + foreach (var role in onGroundRoles.Except(traitRoles)) + { + var roleExcel = GameData.GridFightRoleBasicInfoData.GetValueOrDefault(role.RoleId); + if (roleExcel == null) continue; + + foreach (var equipmentUid in role.EquipmentIds) + { + // get item + var equipmentItem = roleComp.Inst.GetComponent().Data.EquipmentItems + .FirstOrDefault(x => x.UniqueId == equipmentUid); + if (equipmentItem == null) continue; + + // get conf + var equipmentExcel = GameData.GridFightEquipmentData.GetValueOrDefault(equipmentItem.ItemId); + if (equipmentExcel == null) continue; + + // category (emblem) + if (equipmentExcel.EquipCategory != GridFightEquipCategoryEnum.Emblem) continue; + + if (equipmentExcel.EquipFuncParamList.Contains(info.TraitId)) + { + // we can add this role directly becuz foreach has Except option + traitRoles.Add(role); + } + } + } + + // check for phainon var phainonRole = roleComp.Data.Roles.FirstOrDefault(x => x.Pos <= GridFightRoleComponent.PrepareAreaPos && x.RoleId == 1408); // hardcode