Skip to content

Commit

Permalink
Updating loottables so it's more customisable (#413)
Browse files Browse the repository at this point in the history
* small fix to add multiple drop counts
* switched back to uint weights
  • Loading branch information
Shiniri authored Apr 21, 2024
1 parent 9e16555 commit 17d49f0
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 41 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## 4.0.27
- Improved functionality of loot tables plugin: weights & drop counts are now more customisable, reverted to weight based system instead of percentages.

## 4.0.26
- Add checks for NPC defined in npcInfo. If you define a shipArch, reputation or pilot that's invalid, the FLHook console will log an error.
- Add a check to ensure that invalid NPCs cannot be spawned via startupNpcs, which would cause the server to crash.

## 4.0.25
- Fixed some major issues with daily_tasks.

## 4.0.24
- Add checks for NPC defined in npcInfo. If you define a shipArch, reputation or pilot that's invalid, the FLHook console will log an error.
- Add a check to ensure that invalid NPCs cannot be spawned via startupNpcs, which would cause the server to crash.
Expand Down
2 changes: 1 addition & 1 deletion FLHookSDK
62 changes: 24 additions & 38 deletions plugins/loot_tables/LootTables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ namespace Plugins::LootTables
*/
void ShipDestroyed([[maybe_unused]] DamageList** dmgList, const DWORD** ecx, [[maybe_unused]] const uint& kill)
{
// Calculate what Item to drop
static std::random_device randomDevice; // Used to obtain a seed
static std::mt19937 mersenneTwisterEngine(randomDevice()); // Mersenne Twister algorithm seeded with the variable above

// Get cShip from NPC?
CShip* ship = Hk::Player::CShipFromShipDestroyed(ecx);
for (auto const& lootTable : global->config->lootTables)
Expand All @@ -75,26 +79,25 @@ namespace Plugins::LootTables
return;
}

// Calculate what Item to drop
std::random_device randomDevice; // Used to obtain a seed
std::mt19937 mersenneTwisterEngine(randomDevice()); // Mersenne Twister algorithm seeded with the variable above
std::uniform_real_distribution dist(0.0f, 1.0f);
const float randomFloat = dist(mersenneTwisterEngine);
float sum = 0.0;
for (const auto& [weight, itemHashed, item] : lootTable.dropWeights)
// roll n times, depending on loottable
for (int i = 0; i < lootTable.rollCount; i++)
{
sum += weight;
if (randomFloat <= sum && itemHashed)
{
Server.MineAsteroid(
ship->iSystem,
ship->get_position(),
global->config->lootDropContainerHashed,
itemHashed,
lootTable.dropCount,
ship->GetOwnerPlayer());
return;
}
// Accumulate weights
std::vector<uint> weights;
weights.reserve(lootTable.dropWeights.size());
std::ranges::transform(lootTable.dropWeights, std::back_inserter(weights), [](const DropWeight& dw) { return dw.weighting; });

// Choose a random index
std::discrete_distribution<> discreteDistribution(weights.begin(), weights.end());
auto chosenIndex = discreteDistribution(mersenneTwisterEngine);

// Drop item corresponding to said index
Server.MineAsteroid(ship->iSystem,
ship->get_position(),
global->config->lootDropContainerHashed,
lootTable.dropWeights[chosenIndex].itemHashed,
lootTable.dropWeights[chosenIndex].dropCount,
ship->GetOwnerPlayer());
}
}
}
Expand All @@ -113,23 +116,6 @@ namespace Plugins::LootTables
for (auto& lootTable : config.lootTables)
{
lootTable.triggerItemHashed = CreateID(lootTable.triggerItem.c_str());

// Check that weighting in this loot table entry add up to 1
float weightingCheck = 0;
for (auto& weighting : lootTable.dropWeights)
{
weightingCheck += weighting.weighting;
if (ToLower(weighting.item) != "none")
{
weighting.itemHashed = CreateID(weighting.item.c_str());
}

}

if (abs(weightingCheck - 1.0f) > 1e-9) // Can't just use != due to floating point precision
{
Console::ConErr(std::format("Loot Table for trigger item: {} does not have weightings that add up to exactly 1.", lootTable.triggerItem));
}
}

global->config = std::make_unique<Config>(std::move(config));
Expand All @@ -138,8 +124,8 @@ namespace Plugins::LootTables

using namespace Plugins::LootTables;

REFL_AUTO(type(DropWeight), field(weighting), field(item));
REFL_AUTO(type(LootTable), field(dropCount), field(applyToPlayers), field(applyToNpcs), field(triggerItem), field(dropWeights));
REFL_AUTO(type(DropWeight), field(weighting), field(item), field(dropCount));
REFL_AUTO(type(LootTable), field(rollCount), field(applyToPlayers), field(applyToNpcs), field(triggerItem), field(dropWeights));
REFL_AUTO(type(Config), field(lootDropContainer), field(lootTables));

DefaultDllMainSettings(LoadSettings);
Expand Down
5 changes: 3 additions & 2 deletions plugins/loot_tables/LootTables.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ namespace Plugins::LootTables
{
struct DropWeight final : Reflectable
{
float weighting = 0; // These should add up to 1 for each DropWeight entry in LootTable
uint weighting = 2; // Weights are relative, meaning to compute drop likelihood, do w_i / sum(w_1, w_2, ...)
uint itemHashed = 0;
std::string item = "missile01_mark02_ammo";
uint dropCount = 3;
};

struct LootTable final : Reflectable
{
uint dropCount = 0;
uint rollCount = 5;
bool applyToPlayers = false;
bool applyToNpcs = false;
std::string triggerItem = "missile01_mark02";
Expand Down

0 comments on commit 17d49f0

Please sign in to comment.