feat: better orb rewards

This commit is contained in:
Somebody
2025-12-06 22:44:41 +08:00
parent 26f14bb778
commit 6353846741
14 changed files with 637 additions and 53 deletions

View File

@@ -0,0 +1,14 @@
using EggLink.DanhengServer.Data.Excel;
namespace EggLink.DanhengServer.Data.Custom;
public class GridFightBasicOrbRewardsConfig
{
public Dictionary<uint, GridFightBasicOrbRewardsInfo> OrbRewards { get; set; } = [];
}
public class GridFightBasicOrbRewardsInfo
{
public uint OrbId { get; set; }
public Dictionary<uint, List<GridFightBasicBonusPoolV2Excel>> Rewards { get; set; } = [];
}

View File

@@ -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<uint> 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);
}
}

View File

@@ -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<uint> EquipFuncParamList { get; set; } = [];
public List<uint> DressRuleParamList { get; set; } = [];
public override int GetId()
{
return (int)ID;

View File

@@ -119,6 +119,8 @@ public static class GameData
#region GridFight
public static GridFightBasicOrbRewardsConfig GridFightBasicOrbRewardsConfig { get; set; } = new();
public static Dictionary<uint, GridFightBasicBonusPoolV2Excel> GridFightBasicBonusPoolV2Data { get; private set; } = [];
public static Dictionary<uint, GridFightRoleBasicInfoExcel> GridFightRoleBasicInfoData { get; private set; } = [];
public static Dictionary<uint, GridFightRoleStarExcel> GridFightRoleStarData { get; private set; } = [];
public static Dictionary<uint, GridFightRoleRecommendEquipExcel> GridFightRoleRecommendEquipData { get; private set; } =

View File

@@ -52,11 +52,13 @@ public class ResourceManager
GameData.RogueMiracleEffectData =
LoadCustomFile<RogueMiracleEffectConfig>("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<Dictionary<uint, Dictionary<uint, List<GridFightBasicBonusPoolV2Excel>>>>(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))

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}
]
}
}

View File

@@ -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<List<BaseGridFightSyncData>> TakeDrop(List<GridFightDropItemInfo> drops, bool sendPacket = false, GridFightSrc src = GridFightSrc.KGridFightSrcNone, uint groupId = 0, params uint[] param)
public async ValueTask<List<BaseGridFightSyncData>> TakeDrop(List<GridFightDropItemInfo> drops,
bool sendPacket = false, GridFightSrc src = GridFightSrc.KGridFightSrcNone, uint groupId = 0,
params uint[] param)
{
var syncs = new List<BaseGridFightSyncData>();
var basicComp = Inst.GetComponent<GridFightBasicComponent>();
@@ -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<BaseGridFightSyncData>, List<GridFightDropItemInfo>)> TakeBasicBonusItems(
List<GridFightBasicBonusPoolV2Excel> bonuses, GridFightSrc src = GridFightSrc.KGridFightSrcNone, uint groupId = 0, bool sendPacket = true)
{
var basicComp = Inst.GetComponent<GridFightBasicComponent>();
var shopComp = Inst.GetComponent<GridFightShopComponent>();
var roleComp = Inst.GetComponent<GridFightRoleComponent>();
var orbComp = Inst.GetComponent<GridFightOrbComponent>();
List<BaseGridFightSyncData> syncs = [];
List<GridFightDropItemInfo> 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

View File

@@ -597,6 +597,7 @@ public class GridFightGameEncounterInfo
public class GridFightGameMonsterWaveInfo
{
public static readonly List<List<uint>> OrbList = [[102, 199], [203, 204, 205, 206, 207, 208], [120031]];
public GridFightGameMonsterWaveInfo(uint wave, List<GridFightMonsterExcel> 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 [];

View File

@@ -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<BaseGridFightSyncData>, List<GridFightDropItemInfo>)> TakeOrbEffect(GridFightOrbTypeEnum type, uint groupId)
private async ValueTask<(List<BaseGridFightSyncData>, List<GridFightDropItemInfo>)> TakeOrbEffect(
GridFightOrbExcel excel, uint groupId)
{
List<GridFightBasicBonusPoolV2Excel> 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<GridFightItemsComponent>();
return await itemsComp.TakeBasicBonusItems(bonusPools, GridFightSrc.KGridFightSrcUseOrb, groupId, false);
}
// default
return await TakeOrbDefaultEffect(excel.Type, groupId);
}
private async ValueTask<(List<BaseGridFightSyncData>, List<GridFightDropItemInfo>)> TakeOrbDefaultEffect(GridFightOrbTypeEnum type, uint groupId)
{
List<BaseGridFightSyncData> syncDatas = [];
List<GridFightDropItemInfo> dropItems = [];

View File

@@ -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;

View File

@@ -37,7 +37,7 @@ public class GridFightShopComponent(GridFightInstance inst) : BaseGridFightCompo
var avatarComp = Inst.GetComponent<GridFightRoleComponent>();
// check pos
if (!avatarComp.HasAnyEmptyPos()) return Retcode.RetGridFightNoEmptyPos;
//if (!avatarComp.HasAnyEmptyPos()) return Retcode.RetGridFightNoEmptyPos;
var curLevel = Inst.GetComponent<GridFightBasicComponent>().Data.CurLevel;

View File

@@ -14,6 +14,7 @@ public class GridFightTraitComponent(GridFightInstance inst) : BaseGridFightComp
public async ValueTask CheckTrait()
{
var itemsComp = Inst.GetComponent<GridFightItemsComponent>();
var roleComp = Inst.GetComponent<GridFightRoleComponent>();
Dictionary<uint, uint> 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<GridFightItemsComponent>().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