Skip to content

Commit

Permalink
fix: Adjust BBM loot
Browse files Browse the repository at this point in the history
- Pruned items from the loot list which shouldn't be present.
- Made loot ranges for normal and sealed chests configurable via the
  BBM JSON.
- Adjusted the loot algorithm so you don't get items from the next tier
  in the current stage after defeating the tier boss.
  • Loading branch information
pacampbell committed Aug 29, 2024
1 parent d4cabf7 commit ea527a8
Show file tree
Hide file tree
Showing 4 changed files with 261 additions and 425 deletions.
59 changes: 10 additions & 49 deletions Arrowgene.Ddon.GameServer/Characters/BitterblackMazeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ public static List<InstancedGatheringItem> RollChestLoot(DdonGameServer server,
break;
}

uint itemId = BitterblackMazeManager.SelectGear(server, character, items, chestType);
uint itemId = BitterblackMazeManager.SelectGear(server, items, chestType, stageId);
if (itemId > 0)
{
results.Add(new InstancedGatheringItem()
Expand All @@ -359,7 +359,7 @@ public static List<InstancedGatheringItem> RollChestLoot(DdonGameServer server,
{
// Sealed chests should have at least one piece of equipment
var items = BitterblackMazeManager.SelectGearType(assets.HighQualityWeapons[jobId], DetermineEquipClass(assets.HighQualityArmors, jobId), assets.HighQualityOther);
uint itemId = BitterblackMazeManager.SelectGear(server, character, items, chestType);
uint itemId = BitterblackMazeManager.SelectGear(server, items, chestType, stageId);
results.Add(new InstancedGatheringItem()
{
ItemId = itemId,
Expand Down Expand Up @@ -444,59 +444,20 @@ private static List<uint> SelectGearType(List<uint> weapons, List<uint> armors,
return weapons;
}

private static (uint, uint) DetermineItemTier(Character character, ChestType chestType)
private static (uint Min, uint Max) DetermineItemTier(DdonGameServer server, ChestType chestType, StageId stageId)
{
var progress = character.BbmProgress;

(uint, uint) result = (3, 3);
switch (progress.ContentMode)
{
case BattleContentMode.Rotunda:
switch (progress.Tier)
{
case 1:
result = (3, 4);
break;
case 2:
result = (4, 5);
break;
case 3:
result = (6, 10);
break;
}
break;
case BattleContentMode.Abyss:
switch (progress.Tier)
{
case 1:
result = (3, 4);
break;
case 2:
result = (5, 6);
break;
case 3:
result = (7, 11);
break;
case 4:
result = (11, 11);
break;
}
break;
}

// If we have a special chest, adjust the lower and upper bound of the item range
var lootRange = server.AssetRepository.BitterblackMazeAsset.LootRanges[stageId.Id];
switch (chestType)
{
case ChestType.Orange:
case ChestType.Purple:
result = (result.Item2, result.Item2 + 1);
break;
return lootRange.SealedRange;
default:
return lootRange.NormalRange;
}

return result;
}

private static uint SelectGear(DdonGameServer server, Character character, List<uint> items, ChestType chestType)
private static uint SelectGear(DdonGameServer server, List<uint> items, ChestType chestType, StageId stageId)
{
if (items.Count == 0)
{
Expand All @@ -505,13 +466,13 @@ private static uint SelectGear(DdonGameServer server, Character character, List<

uint attempts = 0;
uint itemId = 0;
var itemRankRange = DetermineItemTier(character, chestType);
var itemRankRange = DetermineItemTier(server, chestType, stageId);
do
{
itemId = items[Random.Shared.Next(items.Count)];

var itemRank = ClientItemInfo.GetInfoForItemId(server.AssetRepository.ClientItemInfos, itemId).Rank;
if (itemRank >= itemRankRange.Item1 && itemRank <= itemRankRange.Item2)
if (itemRank >= itemRankRange.Min && itemRank <= itemRankRange.Max)
{
break;
}
Expand Down
9 changes: 9 additions & 0 deletions Arrowgene.Ddon.Shared/Asset/BitterblackMazeAsset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public BitterblackMazeAsset()
RareItemAppraisalList = new List<CDataCommonU32>();
ItemTakeawayList = new List<CDataCommonU32>();
StageProgressionList = new List<CDataBattleContentStageProgression>();
LootRanges = new Dictionary<uint, LootRange>();

LowQualityWeapons = new Dictionary<JobId, List<uint>>();
HighQualityWeapons = new Dictionary<JobId, List<uint>>();
Expand All @@ -25,7 +26,15 @@ public BitterblackMazeAsset()
HighQualityOther = new List<uint>();
}

public class LootRange
{
public (uint Min, uint Max) NormalRange;
public (uint Min, uint Max) SealedRange;
}


public Dictionary<StageId, BitterblackMazeConfig> Stages { get; set; }
public Dictionary<uint, LootRange> LootRanges { get; set; }
public Dictionary<JobId, Dictionary<EquipType, List<Item>>> StarterEquipment { get; set; }
public Dictionary<JobId, List<Item>> StarterJobEquipment { get; set; }
public List<CDataCommonU32> RareItemAppraisalList { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using System.Collections.Generic;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using static Arrowgene.Ddon.Shared.Asset.BitterblackMazeAsset;

namespace Arrowgene.Ddon.Shared.AssetReader
{
Expand Down Expand Up @@ -66,6 +67,21 @@ public BitterblackMazeAsset ReadPath(string path)
}
}

var lootRanges = document.RootElement.GetProperty("loot_ranges").EnumerateArray();
foreach (var lootRange in lootRanges)
{
var record = new LootRange()
{
NormalRange = (lootRange.GetProperty("normal").GetProperty("min").GetUInt32(), lootRange.GetProperty("normal").GetProperty("max").GetUInt32()),
SealedRange = (lootRange.GetProperty("sealed").GetProperty("min").GetUInt32(), lootRange.GetProperty("sealed").GetProperty("max").GetUInt32())
};

foreach (var id in lootRange.GetProperty("stage_ids").EnumerateArray())
{
asset.LootRanges[id.GetUInt32()] = record;
}
}

// Fill up Null items for JobId.None
asset.StarterEquipment[JobId.None] = new Dictionary<EquipType, List<Item?>>();
asset.StarterEquipment[JobId.None][EquipType.Performance] = Enumerable.Repeat((Item) null, 15).ToList();
Expand Down
Loading

0 comments on commit ea527a8

Please sign in to comment.