From 17d49f034566a3e8b780b943a8f0c764bac914c8 Mon Sep 17 00:00:00 2001 From: Marie Bauer <83022833+Shiniri@users.noreply.github.com> Date: Sun, 21 Apr 2024 16:19:55 +0200 Subject: [PATCH] Updating loottables so it's more customisable (#413) * small fix to add multiple drop counts * switched back to uint weights --- CHANGELOG.md | 10 +++++ FLHookSDK | 2 +- plugins/loot_tables/LootTables.cpp | 62 ++++++++++++------------------ plugins/loot_tables/LootTables.hpp | 5 ++- 4 files changed, 38 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ef41fec4..14e8df348 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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. diff --git a/FLHookSDK b/FLHookSDK index 32e6322fb..a99c8e4b9 160000 --- a/FLHookSDK +++ b/FLHookSDK @@ -1 +1 @@ -Subproject commit 32e6322fbf8c9ac3d863680c2d0feeb31be1a87c +Subproject commit a99c8e4b9f6ac8e370f5dec703d91a1ee40dbf82 diff --git a/plugins/loot_tables/LootTables.cpp b/plugins/loot_tables/LootTables.cpp index afc63220a..1135c44ce 100644 --- a/plugins/loot_tables/LootTables.cpp +++ b/plugins/loot_tables/LootTables.cpp @@ -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) @@ -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 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()); } } } @@ -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(std::move(config)); @@ -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); diff --git a/plugins/loot_tables/LootTables.hpp b/plugins/loot_tables/LootTables.hpp index d953e08ea..f5d7874b7 100644 --- a/plugins/loot_tables/LootTables.hpp +++ b/plugins/loot_tables/LootTables.hpp @@ -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";