mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-10-10 17:38:08 +00:00
fix: hardcore mode fixes (#1882)
fixes hardcore modes uscore drops adds config option for excluded item drops
This commit is contained in:
@@ -47,6 +47,7 @@ void dConfig::LoadConfig() {
|
|||||||
void dConfig::ReloadConfig() {
|
void dConfig::ReloadConfig() {
|
||||||
this->m_ConfigValues.clear();
|
this->m_ConfigValues.clear();
|
||||||
LoadConfig();
|
LoadConfig();
|
||||||
|
for (const auto& handler : m_ConfigHandlers) handler();
|
||||||
LogSettings();
|
LogSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,6 +60,10 @@ const std::string& dConfig::GetValue(std::string key) {
|
|||||||
return this->m_ConfigValues[key];
|
return this->m_ConfigValues[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dConfig::AddConfigHandler(std::function<void()> handler) {
|
||||||
|
m_ConfigHandlers.push_back(handler);
|
||||||
|
}
|
||||||
|
|
||||||
void dConfig::LogSettings() const {
|
void dConfig::LogSettings() const {
|
||||||
LOG("Configuration settings:");
|
LOG("Configuration settings:");
|
||||||
for (const auto& [key, value] : m_ConfigValues) {
|
for (const auto& [key, value] : m_ConfigValues) {
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -30,11 +32,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
void ReloadConfig();
|
void ReloadConfig();
|
||||||
|
|
||||||
|
// Adds a function to be called when the config is (re)loaded
|
||||||
|
void AddConfigHandler(std::function<void()> handler);
|
||||||
void LogSettings() const;
|
void LogSettings() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ProcessLine(const std::string& line);
|
void ProcessLine(const std::string& line);
|
||||||
|
|
||||||
std::map<std::string, std::string> m_ConfigValues;
|
std::map<std::string, std::string> m_ConfigValues;
|
||||||
|
std::vector<std::function<void()>> m_ConfigHandlers;
|
||||||
std::string m_ConfigFilePath;
|
std::string m_ConfigFilePath;
|
||||||
};
|
};
|
||||||
|
@@ -52,6 +52,25 @@ std::vector<LOT> EntityManager::m_GhostingExcludedLOTs = {
|
|||||||
4967
|
4967
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void EntityManager::ReloadConfig() {
|
||||||
|
auto hcmode = Game::config->GetValue("hardcore_mode");
|
||||||
|
m_HardcoreMode = hcmode.empty() ? false : (hcmode == "1");
|
||||||
|
auto hcUscorePercent = Game::config->GetValue("hardcore_lose_uscore_on_death_percent");
|
||||||
|
m_HardcoreLoseUscoreOnDeathPercent = hcUscorePercent.empty() ? 10 : std::stoi(hcUscorePercent);
|
||||||
|
auto hcUscoreMult = Game::config->GetValue("hardcore_uscore_enemies_multiplier");
|
||||||
|
m_HardcoreUscoreEnemiesMultiplier = hcUscoreMult.empty() ? 2 : std::stoi(hcUscoreMult);
|
||||||
|
auto hcDropInv = Game::config->GetValue("hardcore_dropinventory_on_death");
|
||||||
|
m_HardcoreDropinventoryOnDeath = hcDropInv.empty() ? false : (hcDropInv == "1");
|
||||||
|
auto hcExcludedItemDrops = Game::config->GetValue("hardcore_excluded_item_drops");
|
||||||
|
m_HardcoreExcludedItemDrops.clear();
|
||||||
|
for (const auto& strLot : GeneralUtils::SplitString(hcExcludedItemDrops, ',')) {
|
||||||
|
const auto lot = GeneralUtils::TryParse<LOT>(strLot);
|
||||||
|
if (lot) {
|
||||||
|
m_HardcoreExcludedItemDrops.insert(lot.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EntityManager::Initialize() {
|
void EntityManager::Initialize() {
|
||||||
// Check if this zone has ghosting enabled
|
// Check if this zone has ghosting enabled
|
||||||
m_GhostingEnabled = std::find(
|
m_GhostingEnabled = std::find(
|
||||||
@@ -61,15 +80,8 @@ void EntityManager::Initialize() {
|
|||||||
) == m_GhostingExcludedZones.end();
|
) == m_GhostingExcludedZones.end();
|
||||||
|
|
||||||
// grab hardcore mode settings and load them with sane defaults
|
// grab hardcore mode settings and load them with sane defaults
|
||||||
auto hcmode = Game::config->GetValue("hardcore_mode");
|
Game::config->AddConfigHandler([]() {Game::entityManager->ReloadConfig();});
|
||||||
m_HardcoreMode = hcmode.empty() ? false : (hcmode == "1");
|
Game::entityManager->ReloadConfig();
|
||||||
auto hcUscorePercent = Game::config->GetValue("hardcore_lose_uscore_on_death_percent");
|
|
||||||
m_HardcoreLoseUscoreOnDeathPercent = hcUscorePercent.empty() ? 10 : std::stoi(hcUscorePercent);
|
|
||||||
auto hcUscoreMult = Game::config->GetValue("hardcore_uscore_enemies_multiplier");
|
|
||||||
m_HardcoreUscoreEnemiesMultiplier = hcUscoreMult.empty() ? 2 : std::stoi(hcUscoreMult);
|
|
||||||
auto hcDropInv = Game::config->GetValue("hardcore_dropinventory_on_death");
|
|
||||||
m_HardcoreDropinventoryOnDeath = hcDropInv.empty() ? false : (hcDropInv == "1");
|
|
||||||
|
|
||||||
// If cloneID is not zero, then hardcore mode is disabled
|
// If cloneID is not zero, then hardcore mode is disabled
|
||||||
// aka minigames and props
|
// aka minigames and props
|
||||||
if (Game::zoneManager->GetZoneID().GetCloneID() != 0) m_HardcoreMode = false;
|
if (Game::zoneManager->GetZoneID().GetCloneID() != 0) m_HardcoreMode = false;
|
||||||
|
@@ -75,11 +75,13 @@ public:
|
|||||||
const uint32_t GetHardcoreLoseUscoreOnDeathPercent() { return m_HardcoreLoseUscoreOnDeathPercent; };
|
const uint32_t GetHardcoreLoseUscoreOnDeathPercent() { return m_HardcoreLoseUscoreOnDeathPercent; };
|
||||||
const bool GetHardcoreDropinventoryOnDeath() { return m_HardcoreDropinventoryOnDeath; };
|
const bool GetHardcoreDropinventoryOnDeath() { return m_HardcoreDropinventoryOnDeath; };
|
||||||
const uint32_t GetHardcoreUscoreEnemiesMultiplier() { return m_HardcoreUscoreEnemiesMultiplier; };
|
const uint32_t GetHardcoreUscoreEnemiesMultiplier() { return m_HardcoreUscoreEnemiesMultiplier; };
|
||||||
|
const std::set<LOT>& GetHardcoreExcludedItemDrops() { return m_HardcoreExcludedItemDrops; };
|
||||||
|
|
||||||
// Messaging
|
// Messaging
|
||||||
bool SendMessage(GameMessages::GameMsg& msg) const;
|
bool SendMessage(GameMessages::GameMsg& msg) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void ReloadConfig();
|
||||||
void SerializeEntities();
|
void SerializeEntities();
|
||||||
void KillEntities();
|
void KillEntities();
|
||||||
void DeleteEntities();
|
void DeleteEntities();
|
||||||
@@ -112,6 +114,7 @@ private:
|
|||||||
uint32_t m_HardcoreLoseUscoreOnDeathPercent;
|
uint32_t m_HardcoreLoseUscoreOnDeathPercent;
|
||||||
bool m_HardcoreDropinventoryOnDeath;
|
bool m_HardcoreDropinventoryOnDeath;
|
||||||
uint32_t m_HardcoreUscoreEnemiesMultiplier;
|
uint32_t m_HardcoreUscoreEnemiesMultiplier;
|
||||||
|
std::set<LOT> m_HardcoreExcludedItemDrops;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ENTITYMANAGER_H
|
#endif // ENTITYMANAGER_H
|
||||||
|
@@ -37,6 +37,7 @@
|
|||||||
#include "eMissionTaskType.h"
|
#include "eMissionTaskType.h"
|
||||||
#include "eStateChangeType.h"
|
#include "eStateChangeType.h"
|
||||||
#include "eGameActivity.h"
|
#include "eGameActivity.h"
|
||||||
|
#include <ranges>
|
||||||
|
|
||||||
#include "CDComponentsRegistryTable.h"
|
#include "CDComponentsRegistryTable.h"
|
||||||
|
|
||||||
@@ -981,7 +982,8 @@ void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source) {
|
|||||||
auto* character = m_Parent->GetComponent<CharacterComponent>();
|
auto* character = m_Parent->GetComponent<CharacterComponent>();
|
||||||
auto uscore = character->GetUScore();
|
auto uscore = character->GetUScore();
|
||||||
|
|
||||||
auto uscoreToLose = uscore * (Game::entityManager->GetHardcoreLoseUscoreOnDeathPercent() / 100);
|
auto uscoreToLose = static_cast<uint64_t>(uscore * (Game::entityManager->GetHardcoreLoseUscoreOnDeathPercent() / 100.0f));
|
||||||
|
LOG("Player %llu has lost %llu uscore!", m_Parent->GetObjectID(), uscoreToLose);
|
||||||
character->SetUScore(uscore - uscoreToLose);
|
character->SetUScore(uscore - uscoreToLose);
|
||||||
|
|
||||||
GameMessages::SendModifyLEGOScore(m_Parent, m_Parent->GetSystemAddress(), -uscoreToLose, eLootSourceType::MISSION);
|
GameMessages::SendModifyLEGOScore(m_Parent, m_Parent->GetSystemAddress(), -uscoreToLose, eLootSourceType::MISSION);
|
||||||
@@ -995,13 +997,11 @@ void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source) {
|
|||||||
if (items) {
|
if (items) {
|
||||||
auto itemMap = items->GetItems();
|
auto itemMap = items->GetItems();
|
||||||
if (!itemMap.empty()) {
|
if (!itemMap.empty()) {
|
||||||
for (const auto& item : itemMap) {
|
for (const auto item : itemMap | std::views::values) {
|
||||||
//drop the item:
|
// Don't drop excluded items or null ones
|
||||||
if (!item.second) continue;
|
if (!item || Game::entityManager->GetHardcoreExcludedItemDrops().contains(item->GetLot())) continue;
|
||||||
// don't drop the thinkng cap
|
GameMessages::SendDropClientLoot(m_Parent, source, item->GetLot(), 0, m_Parent->GetPosition(), item->GetCount());
|
||||||
if (item.second->GetLot() == 6086) continue;
|
item->SetCount(0, false, false);
|
||||||
GameMessages::SendDropClientLoot(m_Parent, source, item.second->GetLot(), 0, m_Parent->GetPosition(), item.second->GetCount());
|
|
||||||
item.second->SetCount(0, false, false);
|
|
||||||
}
|
}
|
||||||
Game::entityManager->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
@@ -1020,11 +1020,6 @@ void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source) {
|
|||||||
//drop all coins:
|
//drop all coins:
|
||||||
GameMessages::SendDropClientLoot(m_Parent, source, LOT_NULL, coins, m_Parent->GetPosition());
|
GameMessages::SendDropClientLoot(m_Parent, source, LOT_NULL, coins, m_Parent->GetPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reload the player since we can't normally reduce uscore from the server and we want the UI to update
|
|
||||||
// do this last so we don't get killed.... again
|
|
||||||
Game::entityManager->DestructEntity(m_Parent);
|
|
||||||
Game::entityManager->ConstructEntity(m_Parent);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1032,12 +1027,12 @@ void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source) {
|
|||||||
auto* player = Game::entityManager->GetEntity(source);
|
auto* player = Game::entityManager->GetEntity(source);
|
||||||
if (player && player->IsPlayer()) {
|
if (player && player->IsPlayer()) {
|
||||||
auto* playerStats = player->GetComponent<CharacterComponent>();
|
auto* playerStats = player->GetComponent<CharacterComponent>();
|
||||||
if (playerStats) {
|
if (playerStats && GetMaxHealth() > 0) {
|
||||||
//get the maximum health from this enemy:
|
//get the maximum health from this enemy:
|
||||||
auto maxHealth = GetMaxHealth();
|
auto maxHealth = GetMaxHealth();
|
||||||
|
|
||||||
int uscore = maxHealth * Game::entityManager->GetHardcoreUscoreEnemiesMultiplier();
|
int uscore = maxHealth * Game::entityManager->GetHardcoreUscoreEnemiesMultiplier();
|
||||||
|
LOG("Rewarding player %llu with %i uscore for killing enemy %i", player->GetObjectID(), uscore, m_Parent->GetLOT());
|
||||||
playerStats->SetUScore(playerStats->GetUScore() + uscore);
|
playerStats->SetUScore(playerStats->GetUScore() + uscore);
|
||||||
GameMessages::SendModifyLEGOScore(player, player->GetSystemAddress(), uscore, eLootSourceType::MISSION);
|
GameMessages::SendModifyLEGOScore(player, player->GetSystemAddress(), uscore, eLootSourceType::MISSION);
|
||||||
|
|
||||||
|
@@ -80,3 +80,6 @@ cdclient_mismatch_message=We detected that your client is out of date. Please up
|
|||||||
|
|
||||||
# Auto reject properties which contain no models | must be 1 in order to auto reject.
|
# Auto reject properties which contain no models | must be 1 in order to auto reject.
|
||||||
auto_reject_empty_properties=0
|
auto_reject_empty_properties=0
|
||||||
|
|
||||||
|
# comma delimited list of items to not drop in hardcore mode
|
||||||
|
hardcore_excluded_item_drops=6086,7044
|
||||||
|
Reference in New Issue
Block a user