mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-22 16:28:28 +00:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d142e1ca81 | |||
| d9f4d49ef4 | |||
| 0a1df5bbb6 | |||
| 41f3d7ff31 | |||
| 0afef19d26 | |||
| e9be2d76c3 | |||
| ffa813b92c | |||
| 909de47acd | |||
| 73a5f11e17 | |||
| 9544e100c3 | |||
| f3232cdc3a |
@@ -1,3 +1,52 @@
|
||||
## [23.9.1] 8/2/2025
|
||||
|
||||
### Hotfix
|
||||
|
||||
* Fix Quest Ownership Edge Case ([#4977](https://github.com/EQEmu/Server/pull/4977)) @Kinglykrab 2025-08-02
|
||||
|
||||
## [23.9.0] 8/2/2025
|
||||
|
||||
### Bots
|
||||
|
||||
* Fix FinishBuffing rule ([#4961](https://github.com/EQEmu/Server/pull/4961)) @nytmyr 2025-07-01
|
||||
* Fix ^cast resurrects ([#4958](https://github.com/EQEmu/Server/pull/4958)) @nytmyr 2025-06-29
|
||||
|
||||
### Build
|
||||
|
||||
* Fix Linking with GCC ([#4969](https://github.com/EQEmu/Server/pull/4969)) @solar984 2025-08-03
|
||||
* More Build Speed Improvements ([#4959](https://github.com/EQEmu/Server/pull/4959)) @Akkadius 2025-06-30
|
||||
|
||||
### Commands
|
||||
|
||||
* Add #show keyring Subcommand ([#4973](https://github.com/EQEmu/Server/pull/4973)) @Kinglykrab 2025-08-03
|
||||
|
||||
### Database
|
||||
|
||||
* Add Indexes to NPC's Spawns Loot ([#4972](https://github.com/EQEmu/Server/pull/4972)) @Akkadius 2025-07-30
|
||||
|
||||
### Feature
|
||||
|
||||
* Zone Scripting ([#4908](https://github.com/EQEmu/Server/pull/4908)) @Kinglykrab 2025-07-10
|
||||
|
||||
### Fixes
|
||||
|
||||
* Add a missing Froglok starting area for Titanium Startzone. ([#4962](https://github.com/EQEmu/Server/pull/4962)) @regneq 2025-07-04
|
||||
* Fix Hero's Forge Ingame and Character Select ([#4966](https://github.com/EQEmu/Server/pull/4966)) @Kinglykrab 2025-07-30
|
||||
* Show player count on the server list status. ([#4971](https://github.com/EQEmu/Server/pull/4971)) @regneq 2025-07-30
|
||||
|
||||
### Loginserver
|
||||
|
||||
* Fix Legacy World When Using Local DB ([#4970](https://github.com/EQEmu/Server/pull/4970)) @solar984 2025-08-03
|
||||
|
||||
### Performance
|
||||
|
||||
* Clear Wearchange Deduplication Cache ([#4960](https://github.com/EQEmu/Server/pull/4960)) @Akkadius 2025-06-30
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add GetMemberRole() to Perl/Lua ([#4963](https://github.com/EQEmu/Server/pull/4963)) @Barathos 2025-07-10
|
||||
* Add GetTimers() and GetPausedTimers() to Perl/Lua ([#4965](https://github.com/EQEmu/Server/pull/4965)) @Kinglykrab 2025-08-03
|
||||
|
||||
## [23.8.1] 6/28/2025
|
||||
|
||||
### Crash Fix
|
||||
|
||||
@@ -9,7 +9,6 @@ SET(common_sources
|
||||
compression.cpp
|
||||
condition.cpp
|
||||
content/world_content_service.cpp
|
||||
content/world_content_service_rulesets.cpp
|
||||
discord/discord.cpp
|
||||
crash.cpp
|
||||
crc16.cpp
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
#include "world_content_service.h"
|
||||
|
||||
#include <utility>
|
||||
#include <glm/vec3.hpp>
|
||||
#include "../database.h"
|
||||
#include "../rulesys.h"
|
||||
#include "../eqemu_logsys.h"
|
||||
#include "../repositories/instance_list_repository.h"
|
||||
#include "../repositories/rule_sets_repository.h"
|
||||
#include "../repositories/rule_values_repository.h"
|
||||
#include "../zone_store.h"
|
||||
|
||||
|
||||
WorldContentService::WorldContentService()
|
||||
{
|
||||
SetCurrentExpansion(Expansion::EXPANSION_ALL);
|
||||
}
|
||||
|
||||
int WorldContentService::GetCurrentExpansion() const
|
||||
{
|
||||
return current_expansion;
|
||||
@@ -22,7 +27,7 @@ WorldContentService *WorldContentService::SetExpansionContext()
|
||||
// pull expansion from rules
|
||||
int expansion = RuleI(Expansion, CurrentExpansion);
|
||||
if (expansion >= Expansion::Classic && expansion <= Expansion::MaxId) {
|
||||
SetCurrentExpansion(expansion);
|
||||
WorldContentService::Instance()->SetCurrentExpansion(expansion);
|
||||
}
|
||||
|
||||
LogInfo(
|
||||
@@ -36,27 +41,36 @@ WorldContentService *WorldContentService::SetExpansionContext()
|
||||
|
||||
std::string WorldContentService::GetCurrentExpansionName()
|
||||
{
|
||||
if (GetCurrentExpansion() == Expansion::EXPANSION_ALL) {
|
||||
if (WorldContentService::Instance()->GetCurrentExpansion() == Expansion::EXPANSION_ALL) {
|
||||
return "All Expansions";
|
||||
}
|
||||
|
||||
if (current_expansion >= Expansion::Classic && current_expansion <= Expansion::MaxId) {
|
||||
return Expansion::ExpansionName[GetCurrentExpansion()];
|
||||
return Expansion::ExpansionName[WorldContentService::Instance()->GetCurrentExpansion()];
|
||||
}
|
||||
|
||||
return "Unknown Expansion";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param current_expansion
|
||||
*/
|
||||
void WorldContentService::SetCurrentExpansion(int current_expansion)
|
||||
{
|
||||
WorldContentService::current_expansion = current_expansion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
const std::vector<ContentFlagsRepository::ContentFlags> &WorldContentService::GetContentFlags() const
|
||||
{
|
||||
return content_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
std::vector<std::string> WorldContentService::GetContentFlagsEnabled()
|
||||
{
|
||||
std::vector<std::string> enabled_flags;
|
||||
@@ -70,6 +84,9 @@ std::vector<std::string> WorldContentService::GetContentFlagsEnabled()
|
||||
return enabled_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
std::vector<std::string> WorldContentService::GetContentFlagsDisabled()
|
||||
{
|
||||
std::vector<std::string> disabled_flags;
|
||||
@@ -83,11 +100,18 @@ std::vector<std::string> WorldContentService::GetContentFlagsDisabled()
|
||||
return disabled_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param content_flags
|
||||
*/
|
||||
void WorldContentService::SetContentFlags(const std::vector<ContentFlagsRepository::ContentFlags> &content_flags)
|
||||
{
|
||||
WorldContentService::content_flags = content_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param content_flag
|
||||
* @return
|
||||
*/
|
||||
bool WorldContentService::IsContentFlagEnabled(const std::string &content_flag)
|
||||
{
|
||||
for (auto &f: GetContentFlags()) {
|
||||
@@ -99,6 +123,10 @@ bool WorldContentService::IsContentFlagEnabled(const std::string &content_flag)
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param content_flag
|
||||
* @return
|
||||
*/
|
||||
bool WorldContentService::IsContentFlagDisabled(const std::string &content_flag)
|
||||
{
|
||||
for (auto &f: GetContentFlags()) {
|
||||
@@ -167,7 +195,7 @@ Database *WorldContentService::GetDatabase() const
|
||||
|
||||
WorldContentService *WorldContentService::SetDatabase(Database *database)
|
||||
{
|
||||
m_database = database;
|
||||
WorldContentService::m_database = database;
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -285,7 +313,7 @@ WorldContentService::FindZoneResult WorldContentService::FindZone(uint32 zone_id
|
||||
i.notes
|
||||
);
|
||||
|
||||
return FindZoneResult{
|
||||
return WorldContentService::FindZoneResult{
|
||||
.zone_id = static_cast<uint32>(z.zoneidnumber),
|
||||
.instance = i,
|
||||
.zone = z
|
||||
@@ -294,7 +322,7 @@ WorldContentService::FindZoneResult WorldContentService::FindZone(uint32 zone_id
|
||||
}
|
||||
}
|
||||
|
||||
return FindZoneResult{.zone_id = 0};
|
||||
return WorldContentService::FindZoneResult{.zone_id = 0};
|
||||
}
|
||||
|
||||
bool WorldContentService::IsInPublicStaticInstance(uint32 instance_id)
|
||||
@@ -319,4 +347,3 @@ bool WorldContentService::DoesZonePassContentFiltering(const ZoneRepository::Zon
|
||||
|
||||
return DoesPassContentFiltering(f);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "../rulesys.h"
|
||||
#include "../repositories/content_flags_repository.h"
|
||||
#include "../repositories/zone_repository.h"
|
||||
#include "../repositories/instance_list_repository.h"
|
||||
@@ -18,10 +17,8 @@ struct ContentFlags {
|
||||
};
|
||||
|
||||
namespace Expansion {
|
||||
static constexpr int8 EXPANSION_ZERO_VALUE = -2;
|
||||
static constexpr int8 EXPANSION_MAX = 98;
|
||||
static const int EXPANSION_ALL = -1;
|
||||
static const int EXPANSION_FILTER_MAX = 99;
|
||||
static const int EXPANSION_ALL = -1;
|
||||
static const int EXPANSION_FILTER_MAX = 99;
|
||||
|
||||
enum ExpansionNumber {
|
||||
Classic = 0,
|
||||
@@ -84,25 +81,14 @@ namespace Expansion {
|
||||
"Empires of Kunark",
|
||||
"Ring of Scale",
|
||||
"The Burning Lands",
|
||||
"Torment of Velious"
|
||||
"Torment of Velious",
|
||||
};
|
||||
}
|
||||
|
||||
class WorldContentService {
|
||||
public:
|
||||
|
||||
// Constructor can initialize from singleton
|
||||
WorldContentService()
|
||||
: m_rule_manager(RuleManager::Instance())
|
||||
{
|
||||
SetCurrentExpansion(Expansion::EXPANSION_ALL);
|
||||
}
|
||||
|
||||
static WorldContentService* Instance()
|
||||
{
|
||||
static WorldContentService instance;
|
||||
return &instance;
|
||||
}
|
||||
WorldContentService();
|
||||
|
||||
std::string GetCurrentExpansionName();
|
||||
int GetCurrentExpansion() const;
|
||||
@@ -195,11 +181,11 @@ public:
|
||||
FindZoneResult FindZone(uint32 zone_id, uint32 instance_id);
|
||||
bool IsInPublicStaticInstance(uint32 instance_id);
|
||||
|
||||
// targeted rulesets
|
||||
void SeedDefaultRulesets() const;
|
||||
void LoadTargetedRulesets();
|
||||
inline void SetZoneId(int zone_id) { m_zone_id = zone_id; }
|
||||
inline void SetInstanceVersion(int instance_version) { m_instance_version = instance_version; }
|
||||
static WorldContentService* Instance()
|
||||
{
|
||||
static WorldContentService instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
private:
|
||||
int current_expansion{};
|
||||
@@ -208,10 +194,6 @@ private:
|
||||
// reference to database
|
||||
Database *m_database;
|
||||
Database *m_content_database;
|
||||
RuleManager* m_rule_manager;
|
||||
|
||||
int m_zone_id = 0;
|
||||
int m_instance_version = 0;
|
||||
|
||||
// holds a record of the zone table from the database
|
||||
WorldContentService *LoadStaticGlobalZoneInstances();
|
||||
|
||||
@@ -1,981 +0,0 @@
|
||||
#include "world_content_service.h"
|
||||
#include "../repositories/rule_sets_repository.h"
|
||||
#include "../repositories/rule_values_repository.h"
|
||||
|
||||
// RuleSet is a struct that contains a ruleset and its associated rules.
|
||||
struct RuleSet {
|
||||
RuleSetsRepository::RuleSets rule_set;
|
||||
std::vector<RuleValuesRepository::RuleValues> rules;
|
||||
};
|
||||
|
||||
inline RuleSet GetClassicRuleset()
|
||||
{
|
||||
return {
|
||||
.rule_set = {
|
||||
.ruleset_id = 100,
|
||||
.name = "Original (Classic)",
|
||||
.zone_ids = "",
|
||||
.instance_versions = "",
|
||||
.content_flags = "",
|
||||
.content_flags_disabled = "",
|
||||
.min_expansion = Expansion::Classic,
|
||||
.max_expansion = Expansion::EXPANSION_MAX,
|
||||
.notes = "Classic client-based ruleset",
|
||||
},
|
||||
.rules = {
|
||||
{
|
||||
.rule_name = "Character:EnableXTargetting",
|
||||
.rule_value = "false",
|
||||
.notes = "Added in Call of the Forsaken"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:LeaveCorpses",
|
||||
.rule_value = "true",
|
||||
.notes = "Leave corpses behind"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:LeaveNakedCorpses",
|
||||
.rule_value = "false",
|
||||
.notes = "Gear left on corpses until SoD"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:MaxExpLevel",
|
||||
.rule_value = "50",
|
||||
.notes = "Level 50 cap until Kunark"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:MaxLevel",
|
||||
.rule_value = "50",
|
||||
.notes = "Level 50 cap until Kunark"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:RestRegenEnabled",
|
||||
.rule_value = "false",
|
||||
.notes = "OoC regen not added until TSS"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:SharedBankPlat",
|
||||
.rule_value = "false",
|
||||
.notes = "No shared bank until LoY"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:StatCap",
|
||||
.rule_value = "255",
|
||||
.notes = "Classic stat cap is 255"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:UseOldBindWound",
|
||||
.rule_value = "true",
|
||||
.notes = ""
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:UseOldClassExpPenalties",
|
||||
.rule_value = "true",
|
||||
.notes = "Exp penalties removed in SoF"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:UseOldConSystem",
|
||||
.rule_value = "true",
|
||||
.notes = "Con system changed in SoF"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:UseOldRaceExpPenalties",
|
||||
.rule_value = "true",
|
||||
.notes = "Exp penalties removed in SoF"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:UseOldRaceRezEffects",
|
||||
.rule_value = "true",
|
||||
.notes = "May need testing to ensure it can't be dispelled"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:UseRaceClassExpBonuses",
|
||||
.rule_value = "true",
|
||||
.notes = ""
|
||||
},
|
||||
{
|
||||
.rule_name = "Chat:EnableVoiceMacros",
|
||||
.rule_value = "false",
|
||||
.notes = "Introduced in GoD"
|
||||
},
|
||||
{
|
||||
.rule_name = "Chat:ServerWideAuction",
|
||||
.rule_value = "false",
|
||||
.notes = "Disable Server-Wide Auction Chat"
|
||||
},
|
||||
{
|
||||
.rule_name = "Chat:ServerWideOOC",
|
||||
.rule_value = "false",
|
||||
.notes = "Disable Server-Wide OOC Chat"
|
||||
},
|
||||
{
|
||||
.rule_name = "Combat:ClassicNPCBackstab",
|
||||
.rule_value = "true",
|
||||
.notes = "Disables front backstab"
|
||||
},
|
||||
{
|
||||
.rule_name = "Mail:EnableMailSystem",
|
||||
.rule_value = "false",
|
||||
.notes = "Mail system added in DoN"
|
||||
},
|
||||
{
|
||||
.rule_name = "Spells:PreNerfBardAEDoT",
|
||||
.rule_value = "true",
|
||||
.notes = "Bard AE nerf not added until OoW"
|
||||
},
|
||||
{
|
||||
.rule_name = "Spells:WizCritLevel",
|
||||
.rule_value = "65",
|
||||
.notes = "Wiz non-AA crits not until Luclin"
|
||||
},
|
||||
{
|
||||
.rule_name = "TaskSystem:EnableTaskSystem",
|
||||
.rule_value = "false",
|
||||
.notes = "Task system added in OoW"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:CharacterSelectExpansionSettings",
|
||||
.rule_value = "0",
|
||||
.notes = "Classic Client-Based Expansion Setting"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:EnableReturnHomeButton",
|
||||
.rule_value = "false",
|
||||
.notes = "Return Home added in DoN"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:EnableTutorialButton",
|
||||
.rule_value = "false",
|
||||
.notes = "Tutorial added in DoN"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:ExpansionSettings",
|
||||
.rule_value = "0",
|
||||
.notes = "Classic Client-Based Expansion Setting"
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline RuleSet GetKunarkRuleset()
|
||||
{
|
||||
return {
|
||||
.rule_set = {
|
||||
.ruleset_id = 101,
|
||||
.name = "Ruins of Kunark",
|
||||
.zone_ids = "",
|
||||
.instance_versions = "",
|
||||
.content_flags = "",
|
||||
.content_flags_disabled = "",
|
||||
.min_expansion = Expansion::TheRuinsOfKunark,
|
||||
.max_expansion = Expansion::EXPANSION_MAX,
|
||||
.notes = "Kunark client-based ruleset. Level 60 cap until PoP.",
|
||||
},
|
||||
.rules = {
|
||||
{
|
||||
.rule_name = "Expansion:CurrentExpansion",
|
||||
.rule_value = "1",
|
||||
.notes = "Current Expansion"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:ExpansionSettings",
|
||||
.rule_value = "1",
|
||||
.notes = "Kunark Client-Based Expansion Setting"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:CharacterSelectExpansionSettings",
|
||||
.rule_value = "1",
|
||||
.notes = "Kunark Client-Based Expansion Setting"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:MaxExpLevel",
|
||||
.rule_value = "60",
|
||||
.notes = "Level 60 cap until PoP"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:MaxLevel",
|
||||
.rule_value = "60",
|
||||
.notes = "Level 60 cap until PoP"
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline RuleSet GetVeliousRuleset()
|
||||
{
|
||||
return {
|
||||
.rule_set = {
|
||||
.ruleset_id = 102,
|
||||
.name = "Scars of Velious",
|
||||
.zone_ids = "",
|
||||
.instance_versions = "",
|
||||
.content_flags = "",
|
||||
.content_flags_disabled = "",
|
||||
.min_expansion = Expansion::TheScarsOfVelious,
|
||||
.max_expansion = Expansion::EXPANSION_MAX,
|
||||
.notes = "Velious client-based ruleset. Level 60 cap until PoP."
|
||||
},
|
||||
.rules = {
|
||||
{
|
||||
.rule_name = "Expansion:CurrentExpansion",
|
||||
.rule_value = "2",
|
||||
.notes = "Current Expansion"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:ExpansionSettings",
|
||||
.rule_value = "3",
|
||||
.notes = "Velious Client-Based Expansion Setting"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:CharacterSelectExpansionSettings",
|
||||
.rule_value = "3",
|
||||
.notes = "Velious Client-Based Expansion Setting"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:MaxExpLevel",
|
||||
.rule_value = "60",
|
||||
.notes = "Level 60 cap until PoP"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:MaxLevel",
|
||||
.rule_value = "60",
|
||||
.notes = "Level 60 cap until PoP"
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline RuleSet GetLuclinRuleset()
|
||||
{
|
||||
return {
|
||||
.rule_set = {
|
||||
.ruleset_id = 103,
|
||||
.name = "Shadows of Luclin",
|
||||
.zone_ids = "",
|
||||
.instance_versions = "",
|
||||
.content_flags = "",
|
||||
.content_flags_disabled = "",
|
||||
.min_expansion = Expansion::TheShadowsOfLuclin,
|
||||
.max_expansion = Expansion::EXPANSION_MAX,
|
||||
.notes = "Luclin client-based ruleset. Level 60 cap. Added Wiz crits."
|
||||
},
|
||||
.rules = {
|
||||
{
|
||||
.rule_name = "Expansion:CurrentExpansion",
|
||||
.rule_value = "3",
|
||||
.notes = "Current Expansion"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:ExpansionSettings",
|
||||
.rule_value = "7",
|
||||
.notes = "Luclin Client-Based Expansion Setting"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:CharacterSelectExpansionSettings",
|
||||
.rule_value = "7",
|
||||
.notes = "Luclin Client-Based Expansion Setting"
|
||||
},
|
||||
{
|
||||
.rule_name = "Spells:WizCritLevel",
|
||||
.rule_value = "12",
|
||||
.notes = "Wizard non-AA Criticals Not added until Luclin"
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline RuleSet GetPlanesRuleset()
|
||||
{
|
||||
return {
|
||||
.rule_set = {
|
||||
.ruleset_id = 104,
|
||||
.name = "Planes of Power",
|
||||
.zone_ids = "",
|
||||
.instance_versions = "",
|
||||
.content_flags = "",
|
||||
.content_flags_disabled = "",
|
||||
.min_expansion = Expansion::ThePlanesOfPower,
|
||||
.max_expansion = Expansion::EXPANSION_MAX,
|
||||
.notes = "PoP client-based ruleset. Level 65 cap. Stat cap increased. Bind Wound changed."
|
||||
},
|
||||
.rules = {
|
||||
{
|
||||
.rule_name = "Expansion:CurrentExpansion",
|
||||
.rule_value = "4",
|
||||
.notes = "Current Expansion"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:CharacterSelectExpansionSettings",
|
||||
.rule_value = "15",
|
||||
.notes = "Planes of Power Client-Based Expansion Setting"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:ExpansionSettings",
|
||||
.rule_value = "15",
|
||||
.notes = "Planes of Power Client-Based Expansion Setting"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:MaxExpLevel",
|
||||
.rule_value = "65",
|
||||
.notes = "Level 65 cap until Omens of War"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:MaxLevel",
|
||||
.rule_value = "65",
|
||||
.notes = "Level 65 cap until Omens of War"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:StatCap",
|
||||
.rule_value = "305",
|
||||
.notes = "Stat cap raised from 255 to 305 with PoP"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:UseOldBindWound",
|
||||
.rule_value = "false",
|
||||
.notes = "PoP introduced a more effective bind wound system"
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Returns a RuleSet for the Legacy of Ykesha ruleset.
|
||||
inline RuleSet GetLegacyOfYkeshaRuleset()
|
||||
{
|
||||
return {
|
||||
.rule_set = {
|
||||
.ruleset_id = 105,
|
||||
.name = "Legacy of Ykesha",
|
||||
.zone_ids = "",
|
||||
.instance_versions = "",
|
||||
.content_flags = "",
|
||||
.content_flags_disabled = "",
|
||||
.min_expansion = Expansion::TheLegacyOfYkesha,
|
||||
.max_expansion = Expansion::EXPANSION_MAX,
|
||||
.notes = "LoY client-based ruleset. Shared bank introduced. Stat cap raised to 350."
|
||||
},
|
||||
.rules = {
|
||||
{
|
||||
.rule_name = "Expansion:CurrentExpansion",
|
||||
.rule_value = "5",
|
||||
.notes = "Current Expansion"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:CharacterSelectExpansionSettings",
|
||||
.rule_value = "31",
|
||||
.notes = "Legacy of Ykesha Client-Based Expansion Setting"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:ExpansionSettings",
|
||||
.rule_value = "31",
|
||||
.notes = "Legacy of Ykesha Client-Based Expansion Setting"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:MaxExpLevel",
|
||||
.rule_value = "65",
|
||||
.notes = "Level 65 cap until Omens of War"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:MaxLevel",
|
||||
.rule_value = "65",
|
||||
.notes = "Level 65 cap until Omens of War"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:SharedBankPlat",
|
||||
.rule_value = "true",
|
||||
.notes = "Shared bank enabled in Legacy of Ykesha"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:StatCap",
|
||||
.rule_value = "350",
|
||||
.notes = "Stat cap increased to 350 with LoY (was 305 in PoP)"
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline RuleSet GetLDoNRuleset()
|
||||
{
|
||||
return {
|
||||
.rule_set = {
|
||||
.ruleset_id = 106,
|
||||
.name = "Lost Dungeons of Norrath",
|
||||
.zone_ids = "",
|
||||
.instance_versions = "",
|
||||
.content_flags = "",
|
||||
.content_flags_disabled = "",
|
||||
.min_expansion = Expansion::LostDungeonsOfNorrath,
|
||||
.max_expansion = Expansion::EXPANSION_MAX,
|
||||
.notes = "LDoN client-based ruleset. Stat cap raised to 400."
|
||||
},
|
||||
.rules = {
|
||||
{
|
||||
.rule_name = "Expansion:CurrentExpansion",
|
||||
.rule_value = "6",
|
||||
.notes = "Current Expansion"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:CharacterSelectExpansionSettings",
|
||||
.rule_value = "63",
|
||||
.notes = "Lost Dungeons of Norrath Client-Based Expansion Setting"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:ExpansionSettings",
|
||||
.rule_value = "63",
|
||||
.notes = "Lost Dungeons of Norrath Client-Based Expansion Setting"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:StatCap",
|
||||
.rule_value = "400",
|
||||
.notes = "Stat cap increased to 400 with LDoN (was 350 in LoY)"
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline RuleSet GetGatesOfDiscordRuleset()
|
||||
{
|
||||
return {
|
||||
.rule_set = {
|
||||
.ruleset_id = 107,
|
||||
.name = "Gates of Discord",
|
||||
.zone_ids = "",
|
||||
.instance_versions = "",
|
||||
.content_flags = "",
|
||||
.content_flags_disabled = "",
|
||||
.min_expansion = Expansion::GatesOfDiscord,
|
||||
.max_expansion = Expansion::EXPANSION_MAX,
|
||||
.notes = "GoD client-based ruleset. Voice macros introduced."
|
||||
},
|
||||
.rules = {
|
||||
{
|
||||
.rule_name = "Expansion:CurrentExpansion",
|
||||
.rule_value = "7",
|
||||
.notes = "Current Expansion"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:CharacterSelectExpansionSettings",
|
||||
.rule_value = "127",
|
||||
.notes = "Gates of Discord Client-Based Expansion Setting"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:ExpansionSettings",
|
||||
.rule_value = "127",
|
||||
.notes = "Gates of Discord Client-Based Expansion Setting"
|
||||
},
|
||||
{
|
||||
.rule_name = "Chat:EnableVoiceMacros",
|
||||
.rule_value = "true",
|
||||
.notes = "Enable Voice Macros - Introduced in Gates of Discord"
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline RuleSet GetOmensOfWarRuleset()
|
||||
{
|
||||
return {
|
||||
.rule_set = {
|
||||
.ruleset_id = 108,
|
||||
.name = "Omens of War",
|
||||
.zone_ids = "",
|
||||
.instance_versions = "",
|
||||
.content_flags = "",
|
||||
.content_flags_disabled = "",
|
||||
.min_expansion = Expansion::OmensOfWar,
|
||||
.max_expansion = Expansion::EXPANSION_MAX,
|
||||
.notes = "OoW client-based ruleset. Level cap raised to 70. Bard AE nerfed. Task system enabled."
|
||||
},
|
||||
.rules = {
|
||||
{
|
||||
.rule_name = "Expansion:CurrentExpansion",
|
||||
.rule_value = "8",
|
||||
.notes = "Current Expansion"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:CharacterSelectExpansionSettings",
|
||||
.rule_value = "255",
|
||||
.notes = "Omens of War Client-Based Expansion Setting"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:ExpansionSettings",
|
||||
.rule_value = "255",
|
||||
.notes = "Omens of War Client-Based Expansion Setting"
|
||||
},
|
||||
{
|
||||
.rule_name = "Spells:PreNerfBardAEDoT",
|
||||
.rule_value = "false",
|
||||
.notes = "Bard AE Nerf"
|
||||
},
|
||||
{
|
||||
.rule_name = "TaskSystem:EnableTaskSystem",
|
||||
.rule_value = "true",
|
||||
.notes = "Task system was introduced in Omens of War"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:MaxExpLevel",
|
||||
.rule_value = "70",
|
||||
.notes = "Level 70 cap until The Serpent's Spine"
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:MaxLevel",
|
||||
.rule_value = "70",
|
||||
.notes = "Level 70 cap until The Serpent's Spine"
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline RuleSet GetDragonsOfNorrathRuleset()
|
||||
{
|
||||
return {
|
||||
.rule_set = {
|
||||
.ruleset_id = 109,
|
||||
.name = "Dragons of Norrath",
|
||||
.zone_ids = "",
|
||||
.instance_versions = "",
|
||||
.content_flags = "",
|
||||
.content_flags_disabled = "",
|
||||
.min_expansion = Expansion::DragonsOfNorrath,
|
||||
.max_expansion = Expansion::EXPANSION_MAX,
|
||||
.notes = "DoN client-based ruleset. Mail system introduced. Accursed Nest unlockable."
|
||||
},
|
||||
.rules = {
|
||||
{
|
||||
.rule_name = "Expansion:CurrentExpansion",
|
||||
.rule_value = "9",
|
||||
.notes = "Current Expansion"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:CharacterSelectExpansionSettings",
|
||||
.rule_value = "511",
|
||||
.notes = "Dragons of Norrath Client-Based Expansion Setting"
|
||||
},
|
||||
{
|
||||
.rule_name = "World:ExpansionSettings",
|
||||
.rule_value = "511",
|
||||
.notes = "Dragons of Norrath Client-Based Expansion Setting"
|
||||
},
|
||||
{
|
||||
.rule_name = "Mail:EnableMailSystem",
|
||||
.rule_value = "true",
|
||||
.notes = "Mail System not added until Dragons of Norrath"
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline RuleSet GetEraOverridesRuleset()
|
||||
{
|
||||
return {
|
||||
.rule_set = {
|
||||
.ruleset_id = 200,
|
||||
.name = "Era Overrides",
|
||||
.zone_ids = "",
|
||||
.instance_versions = "",
|
||||
.content_flags = "",
|
||||
.content_flags_disabled = "",
|
||||
.min_expansion = Expansion::EXPANSION_ALL,
|
||||
.max_expansion = Expansion::EXPANSION_MAX,
|
||||
.notes = "If you want to override any rules for era specific rulesets, use this ruleset. It will not be used by default.",
|
||||
},
|
||||
.rules = {
|
||||
// users will add their own dynamically
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline RuleSet GetDepthsOfDarkhollowRuleset()
|
||||
{
|
||||
return {
|
||||
.rule_set = {
|
||||
.ruleset_id = 110,
|
||||
.name = "Depths of Darkhollow",
|
||||
.zone_ids = "",
|
||||
.instance_versions = "",
|
||||
.content_flags = "",
|
||||
.content_flags_disabled = "",
|
||||
.min_expansion = Expansion::DepthsOfDarkhollow,
|
||||
.max_expansion = Expansion::EXPANSION_MAX,
|
||||
.notes = "DoD client-based ruleset. Introduced Shroud system.",
|
||||
},
|
||||
.rules = {
|
||||
{
|
||||
.rule_name = "Expansion:CurrentExpansion",
|
||||
.rule_value = "10",
|
||||
.notes = "Current Expansion",
|
||||
},
|
||||
{
|
||||
.rule_name = "World:CharacterSelectExpansionSettings",
|
||||
.rule_value = "1023",
|
||||
.notes = "Depths of Darkhollow Client-Based Expansion Setting",
|
||||
},
|
||||
{
|
||||
.rule_name = "World:ExpansionSettings",
|
||||
.rule_value = "1023",
|
||||
.notes = "Depths of Darkhollow Client-Based Expansion Setting",
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:EnableShroudSystem",
|
||||
.rule_value = "true",
|
||||
.notes = "Shroud system was introduced in Depths of Darkhollow",
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline RuleSet GetProphecyOfRoRuleset()
|
||||
{
|
||||
return {
|
||||
.rule_set = {
|
||||
.ruleset_id = 111,
|
||||
.name = "Prophecy of Ro",
|
||||
.zone_ids = "",
|
||||
.instance_versions = "",
|
||||
.content_flags = "",
|
||||
.content_flags_disabled = "",
|
||||
.min_expansion = Expansion::ProphecyOfRo,
|
||||
.max_expansion = Expansion::EXPANSION_MAX,
|
||||
.notes = "PoR client-based ruleset. Introduced aura system.",
|
||||
},
|
||||
.rules = {
|
||||
{
|
||||
.rule_name = "Expansion:CurrentExpansion",
|
||||
.rule_value = "11",
|
||||
.notes = "Current Expansion",
|
||||
},
|
||||
{
|
||||
.rule_name = "World:CharacterSelectExpansionSettings",
|
||||
.rule_value = "2047",
|
||||
.notes = "Prophecy of Ro Client-Based Expansion Setting",
|
||||
},
|
||||
{
|
||||
.rule_name = "World:ExpansionSettings",
|
||||
.rule_value = "2047",
|
||||
.notes = "Prophecy of Ro Client-Based Expansion Setting",
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:EnableAuraSystem",
|
||||
.rule_value = "true",
|
||||
.notes = "Aura system introduced in Prophecy of Ro",
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline RuleSet GetTheSerpentsSpineRuleset()
|
||||
{
|
||||
return {
|
||||
.rule_set = {
|
||||
.ruleset_id = 112,
|
||||
.name = "The Serpent's Spine",
|
||||
.zone_ids = "",
|
||||
.instance_versions = "",
|
||||
.content_flags = "",
|
||||
.content_flags_disabled = "",
|
||||
.min_expansion = Expansion::TheSerpentsSpine,
|
||||
.max_expansion = Expansion::EXPANSION_MAX,
|
||||
.notes = "TSS client-based ruleset. Level cap raised to 75. Out-of-combat regen enabled.",
|
||||
},
|
||||
.rules = {
|
||||
{
|
||||
.rule_name = "Expansion:CurrentExpansion",
|
||||
.rule_value = "12",
|
||||
.notes = "Current Expansion",
|
||||
},
|
||||
{
|
||||
.rule_name = "World:CharacterSelectExpansionSettings",
|
||||
.rule_value = "4095",
|
||||
.notes = "The Serpent's Spine Client-Based Expansion Setting",
|
||||
},
|
||||
{
|
||||
.rule_name = "World:ExpansionSettings",
|
||||
.rule_value = "4095",
|
||||
.notes = "The Serpent's Spine Client-Based Expansion Setting",
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:MaxExpLevel",
|
||||
.rule_value = "75",
|
||||
.notes = "Level 75 cap until The Buried Sea",
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:MaxLevel",
|
||||
.rule_value = "75",
|
||||
.notes = "Level 75 cap until The Buried Sea",
|
||||
},
|
||||
{
|
||||
.rule_name = "Character:RestRegenEnabled",
|
||||
.rule_value = "true",
|
||||
.notes = "Out of combat regeneration enabled in The Serpent's Spine",
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline RuleSet GetTheBuriedSeaRuleset()
|
||||
{
|
||||
return {
|
||||
.rule_set = {
|
||||
.ruleset_id = 113,
|
||||
.name = "The Buried Sea",
|
||||
.zone_ids = "",
|
||||
.instance_versions = "",
|
||||
.content_flags = "",
|
||||
.content_flags_disabled = "",
|
||||
.min_expansion = Expansion::TheBuriedSea,
|
||||
.max_expansion = Expansion::EXPANSION_MAX,
|
||||
.notes = "TBS client-based ruleset. Fellowship and item aug system added.",
|
||||
},
|
||||
.rules = {
|
||||
{
|
||||
.rule_name = "Expansion:CurrentExpansion",
|
||||
.rule_value = "13",
|
||||
.notes = "Current Expansion",
|
||||
},
|
||||
{
|
||||
.rule_name = "World:CharacterSelectExpansionSettings",
|
||||
.rule_value = "8191",
|
||||
.notes = "The Buried Sea Client-Based Expansion Setting",
|
||||
},
|
||||
{
|
||||
.rule_name = "World:ExpansionSettings",
|
||||
.rule_value = "8191",
|
||||
.notes = "The Buried Sea Client-Based Expansion Setting",
|
||||
},
|
||||
{
|
||||
.rule_name = "Fellowship:Enabled",
|
||||
.rule_value = "true",
|
||||
.notes = "Fellowships were introduced in The Buried Sea",
|
||||
},
|
||||
{
|
||||
.rule_name = "Items:AllowItemAugmenting",
|
||||
.rule_value = "true",
|
||||
.notes = "Item augmenting system introduced in The Buried Sea",
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline std::vector<RuleSet> GetCustomRulesets()
|
||||
{
|
||||
return {
|
||||
{
|
||||
.rule_set = {
|
||||
.ruleset_id = 300,
|
||||
.name = "Double Experience",
|
||||
.zone_ids = "",
|
||||
.instance_versions = "",
|
||||
.content_flags = "",
|
||||
.content_flags_disabled = "",
|
||||
.min_expansion = Expansion::EXPANSION_ZERO_VALUE,
|
||||
.max_expansion = Expansion::EXPANSION_ZERO_VALUE,
|
||||
.notes = "Doubles EXP globally",
|
||||
},
|
||||
.rules = {
|
||||
{
|
||||
.rule_name = "Character:FinalExpMultiplier",
|
||||
.rule_value = "2"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
.rule_set = {
|
||||
.ruleset_id = 1000,
|
||||
.name = "Custom Boundary (Put your custom rulesets after here)",
|
||||
.zone_ids = "",
|
||||
.instance_versions = "",
|
||||
.content_flags = "",
|
||||
.content_flags_disabled = "",
|
||||
.min_expansion = Expansion::EXPANSION_ZERO_VALUE,
|
||||
.max_expansion = Expansion::EXPANSION_ZERO_VALUE,
|
||||
.notes = "You may add your own rulesets above 1000+"
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
inline std::vector<RuleSet> GetDefaultRulesets()
|
||||
{
|
||||
std::vector<RuleSet> sets = {
|
||||
GetClassicRuleset(),
|
||||
GetKunarkRuleset(),
|
||||
GetVeliousRuleset(),
|
||||
GetLuclinRuleset(),
|
||||
GetPlanesRuleset(),
|
||||
GetLegacyOfYkeshaRuleset(),
|
||||
GetLDoNRuleset(),
|
||||
GetGatesOfDiscordRuleset(),
|
||||
GetOmensOfWarRuleset(),
|
||||
GetDragonsOfNorrathRuleset(),
|
||||
GetDepthsOfDarkhollowRuleset(),
|
||||
GetProphecyOfRoRuleset(),
|
||||
GetTheSerpentsSpineRuleset(),
|
||||
GetTheBuriedSeaRuleset(),
|
||||
GetEraOverridesRuleset()
|
||||
};
|
||||
|
||||
// Append custom rulesets
|
||||
const auto custom = GetCustomRulesets();
|
||||
sets.insert(sets.end(), custom.begin(), custom.end());
|
||||
|
||||
return sets;
|
||||
}
|
||||
|
||||
void WorldContentService::SeedDefaultRulesets() const
|
||||
{
|
||||
LogInfo("Seeding default rulesets");
|
||||
|
||||
// Load existing rule_sets into a map
|
||||
std::unordered_map<uint32_t, RuleSetsRepository::RuleSets> existing_rulesets;
|
||||
for (const auto& r : RuleSetsRepository::All(*m_database)) {
|
||||
existing_rulesets[r.ruleset_id] = r;
|
||||
}
|
||||
|
||||
// Load existing rule_values into a map<ruleset_id, map<rule_name, RuleValues>>
|
||||
std::unordered_map<uint32_t, std::unordered_map<std::string, RuleValuesRepository::RuleValues>> existing_rule_values;
|
||||
for (const auto& r : RuleValuesRepository::All(*m_database)) {
|
||||
existing_rule_values[r.ruleset_id][r.rule_name] = r;
|
||||
}
|
||||
|
||||
std::vector<RuleSetsRepository::RuleSets> rule_sets_to_insert;
|
||||
std::vector<RuleSetsRepository::RuleSets> rule_sets_to_update;
|
||||
std::vector<RuleValuesRepository::RuleValues> rule_values_to_insert;
|
||||
std::unordered_map<uint32_t, std::vector<std::string>> rule_values_to_delete;
|
||||
|
||||
for (const auto& entry : GetDefaultRulesets()) {
|
||||
const auto& rs = entry.rule_set;
|
||||
const auto existing_it = existing_rulesets.find(rs.ruleset_id);
|
||||
|
||||
if (existing_it == existing_rulesets.end()) {
|
||||
rule_sets_to_insert.push_back(rs);
|
||||
}
|
||||
else {
|
||||
const auto& existing = existing_it->second;
|
||||
if (rs.name != existing.name ||
|
||||
rs.zone_ids != existing.zone_ids ||
|
||||
rs.instance_versions != existing.instance_versions ||
|
||||
rs.content_flags != existing.content_flags ||
|
||||
rs.content_flags_disabled != existing.content_flags_disabled ||
|
||||
rs.min_expansion != existing.min_expansion ||
|
||||
rs.max_expansion != existing.max_expansion ||
|
||||
rs.notes != existing.notes) {
|
||||
rule_sets_to_update.push_back(rs);
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_set<std::string> defined_rule_names;
|
||||
|
||||
for (auto rule : entry.rules) {
|
||||
rule.ruleset_id = rs.ruleset_id;
|
||||
|
||||
if (rule.notes.empty()) {
|
||||
rule.notes = m_rule_manager->GetRuleNotesByName(rule.rule_name);
|
||||
}
|
||||
|
||||
defined_rule_names.insert(rule.rule_name);
|
||||
|
||||
auto& existing_rules = existing_rule_values[rs.ruleset_id];
|
||||
if (existing_rules.find(rule.rule_name) == existing_rules.end()) {
|
||||
rule_values_to_insert.push_back(rule);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& [rule_name, _] : existing_rule_values[rs.ruleset_id]) {
|
||||
if (!defined_rule_names.count(rule_name)) {
|
||||
rule_values_to_delete[rs.ruleset_id].push_back(rule_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Insert new rule sets
|
||||
for (const auto& rs : rule_sets_to_insert) {
|
||||
RuleSetsRepository::InsertOne(*m_database, rs);
|
||||
LogInfo("Inserted ruleset [{}] {}", rs.ruleset_id, rs.name);
|
||||
}
|
||||
|
||||
// Update modified rule sets
|
||||
for (const auto& rs : rule_sets_to_update) {
|
||||
RuleSetsRepository::UpdateOne(*m_database, rs);
|
||||
LogInfo("Updated ruleset metadata [{}] {}", rs.ruleset_id, rs.name);
|
||||
}
|
||||
|
||||
// Insert new rule values
|
||||
if (!rule_values_to_insert.empty()) {
|
||||
RuleValuesRepository::InsertMany(*m_database, rule_values_to_insert);
|
||||
LogInfo("Inserted [{}] new rule(s)]", rule_values_to_insert.size());
|
||||
}
|
||||
|
||||
// Delete obsolete rule values in batches
|
||||
for (const auto& [ruleset_id, rule_names] : rule_values_to_delete) {
|
||||
if (rule_names.empty()) continue;
|
||||
|
||||
std::string in_clause = "'" + Strings::Join(rule_names, "','") + "'";
|
||||
std::string where = fmt::format("ruleset_id = {} AND rule_name IN ({})", ruleset_id, in_clause);
|
||||
|
||||
int removed = RuleValuesRepository::DeleteWhere(*m_database, where);
|
||||
LogInfo("Deleted [{}] obsolete rule(s) from ruleset [{}]: [{}]", removed, ruleset_id, Strings::Join(rule_names, ", "));
|
||||
}
|
||||
}
|
||||
|
||||
void WorldContentService::LoadTargetedRulesets()
|
||||
{
|
||||
if (!m_zone_id) {
|
||||
LogError("Zone ID is not set. Cannot load targeted rulesets.");
|
||||
return;
|
||||
}
|
||||
|
||||
SeedDefaultRulesets();
|
||||
|
||||
LogInfo("Zone ID [{}] Instance Version [{}] - Loading targeted rulesets", m_zone_id, m_instance_version);
|
||||
|
||||
auto rules = RuleValuesRepository::GetWhere(*m_database, "TRUE ORDER BY ruleset_id, rule_name");
|
||||
auto sets = RuleSetsRepository::GetWhere(*m_database, "TRUE ORDER BY ruleset_id");
|
||||
for (auto& e : sets) {
|
||||
bool has_filters =
|
||||
!e.zone_ids.empty() ||
|
||||
!e.instance_versions.empty() ||
|
||||
!e.content_flags.empty() ||
|
||||
!e.content_flags_disabled.empty() ||
|
||||
e.min_expansion != Expansion::EXPANSION_ZERO_VALUE ||
|
||||
e.max_expansion != Expansion::EXPANSION_ZERO_VALUE;
|
||||
if (!has_filters) {
|
||||
continue; // not a targeted ruleset
|
||||
}
|
||||
|
||||
auto zone_id = std::to_string(m_zone_id);
|
||||
if (!e.zone_ids.empty() && !Strings::Contains(e.zone_ids, zone_id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto instance_id = std::to_string(m_instance_version);
|
||||
if (!e.instance_versions.empty() && !Strings::Contains(e.instance_versions, instance_id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!DoesPassContentFiltering(
|
||||
ContentFlags{
|
||||
.min_expansion = e.min_expansion,
|
||||
.max_expansion = e.max_expansion,
|
||||
.content_flags = e.content_flags,
|
||||
.content_flags_disabled = e.content_flags_disabled
|
||||
}
|
||||
)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto& r : rules) {
|
||||
if (r.ruleset_id != e.ruleset_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
m_rule_manager->SetRule(r.rule_name, r.rule_value);
|
||||
|
||||
LogInfo(
|
||||
"Loaded [{}] ruleset [{}] name [{}] value [{}]",
|
||||
e.ruleset_id,
|
||||
e.name,
|
||||
r.rule_name,
|
||||
r.rule_value
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,7 @@ void DatabaseUpdate::CheckDbUpdates()
|
||||
}
|
||||
|
||||
if (UpdateManifest(manifest_entries, v.server_database_version, b.server_database_version)) {
|
||||
LogInfoNoFn(
|
||||
LogInfo(
|
||||
"Updates ran successfully, setting database version to [{}] from [{}]",
|
||||
b.server_database_version,
|
||||
v.server_database_version
|
||||
@@ -64,7 +64,7 @@ void DatabaseUpdate::CheckDbUpdates()
|
||||
}
|
||||
|
||||
if (UpdateManifest(manifest_entries_custom, v.custom_database_version, b.custom_database_version)) {
|
||||
LogInfoNoFn(
|
||||
LogInfo(
|
||||
"Updates ran successfully, setting database version to [{}] from [{}]",
|
||||
b.custom_database_version,
|
||||
v.custom_database_version
|
||||
@@ -337,9 +337,9 @@ DatabaseUpdate *DatabaseUpdate::SetSkipBackup(bool skip)
|
||||
|
||||
bool DatabaseUpdate::CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b)
|
||||
{
|
||||
LogInfoNoFn("{}", Strings::Repeat("-", BREAK_LENGTH));
|
||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
||||
|
||||
LogInfoNoFn(
|
||||
LogInfo(
|
||||
"{:>8} | database [{}] binary [{}] {}",
|
||||
"Server",
|
||||
v.server_database_version,
|
||||
@@ -348,7 +348,7 @@ bool DatabaseUpdate::CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b)
|
||||
);
|
||||
|
||||
if (RuleB(Bots, Enabled) && b.bots_database_version > 0) {
|
||||
LogInfoNoFn(
|
||||
LogInfo(
|
||||
"{:>8} | database [{}] binary [{}] {}",
|
||||
"Bots",
|
||||
v.bots_database_version,
|
||||
@@ -358,7 +358,7 @@ bool DatabaseUpdate::CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b)
|
||||
}
|
||||
|
||||
if (b.custom_database_version > 0) {
|
||||
LogInfoNoFn(
|
||||
LogInfo(
|
||||
"{:>8} | database [{}] binary [{}] {}",
|
||||
"Custom",
|
||||
v.custom_database_version,
|
||||
@@ -367,9 +367,9 @@ bool DatabaseUpdate::CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b)
|
||||
);
|
||||
}
|
||||
|
||||
LogInfoNoFn("{:>8} | [server.auto_database_updates] [<green>true]", "Config");
|
||||
LogInfo("{:>8} | [server.auto_database_updates] [<green>true]", "Config");
|
||||
|
||||
LogInfoNoFn("{}", Strings::Repeat("-", BREAK_LENGTH));
|
||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
||||
|
||||
// server database version is required
|
||||
bool server_up_to_date = v.server_database_version >= b.server_database_version;
|
||||
|
||||
@@ -7138,26 +7138,29 @@ ADD COLUMN `entity_variables` TEXT DEFAULT NULL AFTER `rezzable`;
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9326,
|
||||
.description = "2025_06_16_rule_set_expansion.sql",
|
||||
.check = "SHOW COLUMNS FROM `rule_sets` LIKE 'zone_ids'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.description = "2025_07_27_add_indexes_npc_spawns_loot.sql",
|
||||
.check = "SHOW INDEX FROM npc_types",
|
||||
.condition = "missing",
|
||||
.match = "idx_npc_types_loottable_id",
|
||||
.sql = R"(
|
||||
ALTER TABLE `rule_sets`
|
||||
ADD COLUMN `zone_ids` TEXT NOT NULL DEFAULT '',
|
||||
ADD COLUMN `instance_versions` TEXT NOT NULL DEFAULT '',
|
||||
ADD COLUMN `content_flags` TEXT NOT NULL DEFAULT '',
|
||||
ADD COLUMN `content_flags_disabled` TEXT NOT NULL DEFAULT '',
|
||||
ADD COLUMN `min_expansion` TINYINT NOT NULL DEFAULT -2,
|
||||
ADD COLUMN `max_expansion` TINYINT NOT NULL DEFAULT -2,
|
||||
ADD COLUMN `notes` VARCHAR(255) NOT NULL DEFAULT '';
|
||||
ALTER TABLE `rule_sets`
|
||||
CHANGE `ruleset_id` `ruleset_id` int NOT NULL auto_increment;
|
||||
ALTER TABLE `rule_values`
|
||||
CHANGE `ruleset_id` `ruleset_id` int NOT NULL DEFAULT 0;
|
||||
ALTER TABLE npc_types
|
||||
ADD INDEX idx_npc_types_loottable_id (loottable_id);
|
||||
|
||||
ALTER TABLE spawnentry
|
||||
ADD INDEX idx_spawnentry_spawngroup_id (spawngroupID),
|
||||
ADD INDEX idx_spawnentry_npc_id (npcID);
|
||||
|
||||
ALTER TABLE lootdrop_entries
|
||||
ADD INDEX idx_lootdrop_entries_lootdrop_id (lootdrop_id),
|
||||
ADD INDEX idx_lootdrop_entries_item_id (item_id);
|
||||
|
||||
ALTER TABLE loottable_entries
|
||||
ADD INDEX idx_loottable_entries_lootdrop_id (lootdrop_id),
|
||||
ADD INDEX idx_loottable_entries_loottable_id (loottable_id);
|
||||
)",
|
||||
.content_schema_update = false
|
||||
.content_schema_update = true
|
||||
},
|
||||
|
||||
// -- template; copy/paste this when you need to create a new entry
|
||||
// ManifestEntry{
|
||||
// .version = 9228,
|
||||
|
||||
+138
-65
@@ -224,22 +224,48 @@ void EQEmuLogSys::ProcessConsoleMessage(
|
||||
const char *file,
|
||||
const char *func,
|
||||
int line
|
||||
) {
|
||||
)
|
||||
{
|
||||
bool is_error = (
|
||||
log_category == Logs::LogCategory::Error ||
|
||||
log_category == Logs::LogCategory::MySQLError ||
|
||||
log_category == Logs::LogCategory::Crash ||
|
||||
log_category == Logs::LogCategory::QuestErrors
|
||||
);
|
||||
bool is_warning = (log_category == Logs::LogCategory::Warning);
|
||||
bool is_warning = (
|
||||
log_category == Logs::LogCategory::Warning
|
||||
);
|
||||
|
||||
std::ostream &out = (!is_error ? std::cout : std::cerr);
|
||||
(!is_error ? std::cout : std::cerr)
|
||||
<< ""
|
||||
<< rang::fgB::black
|
||||
<< rang::style::bold
|
||||
<< fmt::format("{:>6}", GetPlatformName().substr(0, 6))
|
||||
<< rang::style::reset
|
||||
<< rang::fgB::gray
|
||||
<< " | "
|
||||
<< ((is_error || is_warning) ? rang::fgB::red : rang::fgB::gray)
|
||||
<< rang::style::bold
|
||||
<< fmt::format("{:^10}", fmt::format("{}", Logs::LogCategoryName[log_category]).substr(0, 10))
|
||||
<< rang::style::reset
|
||||
<< rang::fgB::gray
|
||||
<< " | "
|
||||
<< rang::fgB::gray
|
||||
<< rang::style::bold
|
||||
<< fmt::format("{}", func)
|
||||
<< rang::style::reset
|
||||
<< rang::fgB::gray
|
||||
<< " ";
|
||||
|
||||
out
|
||||
<< rang::style::bold << rang::fgB::gray << GetPlatformName() << " › "
|
||||
<< rang::fgB::gray << Logs::LogCategoryName[log_category] << " › "
|
||||
// << rang::fgB::gray << func << " › "
|
||||
<< rang::style::reset;
|
||||
if (RuleB(Logging, PrintFileFunctionAndLine)) {
|
||||
(!is_error ? std::cout : std::cerr)
|
||||
<< ""
|
||||
<< rang::fgB::green
|
||||
<< rang::style::bold
|
||||
<< fmt::format("{:}", fmt::format("{}:{}:{}", std::filesystem::path(file).filename().string(), func, line))
|
||||
<< rang::style::reset
|
||||
<< " | ";
|
||||
}
|
||||
|
||||
if (log_category == Logs::LogCategory::MySQLQuery) {
|
||||
auto s = Strings::Split(message, "--");
|
||||
@@ -247,84 +273,132 @@ void EQEmuLogSys::ProcessConsoleMessage(
|
||||
std::string query = Strings::Trim(s[0]);
|
||||
std::string meta = Strings::Trim(s[1]);
|
||||
|
||||
out << rang::fgB::green << query << rang::style::reset;
|
||||
out << rang::fgB::black << " -- " << meta << rang::style::reset;
|
||||
std::cout <<
|
||||
rang::fgB::green
|
||||
<<
|
||||
query
|
||||
<<
|
||||
rang::style::reset;
|
||||
|
||||
std::cout <<
|
||||
rang::fgB::black
|
||||
<<
|
||||
" -- "
|
||||
<<
|
||||
meta
|
||||
<<
|
||||
rang::style::reset;
|
||||
}
|
||||
} else {
|
||||
std::vector<std::string> tokens = Strings::Split(message, " ");
|
||||
}
|
||||
else if (Strings::Contains(message, "[")) {
|
||||
for (auto &e: Strings::Split(message, " ")) {
|
||||
if (Strings::Contains(e, "[") && Strings::Contains(e, "]")) {
|
||||
e = Strings::Replace(e, "[", "");
|
||||
e = Strings::Replace(e, "]", "");
|
||||
|
||||
for (auto &token : tokens) {
|
||||
bool has_brackets = Strings::Contains(token, "[") && Strings::Contains(token, "]");
|
||||
std::string clean_token = Strings::Replace(Strings::Replace(token, "[", ""), "]", "");
|
||||
bool is_upper = false;
|
||||
|
||||
// Bracket formatting
|
||||
if (has_brackets) {
|
||||
static std::map<std::string, rang::fgB> color_tags = {
|
||||
{"<black>", rang::fgB::black},
|
||||
{"<green>", rang::fgB::green},
|
||||
{"<yellow>", rang::fgB::yellow},
|
||||
{"<blue>", rang::fgB::blue},
|
||||
for (int i = 0; i < strlen(e.c_str()); i++) {
|
||||
if (isupper(e[i])) {
|
||||
is_upper = true;
|
||||
}
|
||||
}
|
||||
|
||||
// color matching in []
|
||||
// ex: [<red>variable] would produce [variable] with red inside brackets
|
||||
std::map<std::string, rang::fgB> colors = {
|
||||
{"<black>", rang::fgB::black},
|
||||
{"<green>", rang::fgB::green},
|
||||
{"<yellow>", rang::fgB::yellow},
|
||||
{"<blue>", rang::fgB::blue},
|
||||
{"<magenta>", rang::fgB::magenta},
|
||||
{"<cyan>", rang::fgB::cyan},
|
||||
{"<gray>", rang::fgB::gray},
|
||||
{"<red>", rang::fgB::red},
|
||||
{"<cyan>", rang::fgB::cyan},
|
||||
{"<gray>", rang::fgB::gray},
|
||||
{"<red>", rang::fgB::red},
|
||||
};
|
||||
|
||||
static std::map<std::string, rang::fgB> keyword_matches = {
|
||||
bool match_color = false;
|
||||
for (auto &c: colors) {
|
||||
if (Strings::Contains(e, c.first)) {
|
||||
e = Strings::Replace(e, c.first, "");
|
||||
(!is_error ? std::cout : std::cerr)
|
||||
<< rang::fgB::gray
|
||||
<< "["
|
||||
<< rang::style::bold
|
||||
<< c.second
|
||||
<< e
|
||||
<< rang::style::reset
|
||||
<< rang::fgB::gray
|
||||
<< "] ";
|
||||
match_color = true;
|
||||
}
|
||||
}
|
||||
|
||||
// string match to colors
|
||||
std::map<std::string, rang::fgB> matches = {
|
||||
{"missing", rang::fgB::red},
|
||||
{"error", rang::fgB::red},
|
||||
{"ok", rang::fgB::green},
|
||||
};
|
||||
|
||||
bool matched = false;
|
||||
|
||||
for (auto &[tag, color] : color_tags) {
|
||||
if (Strings::Contains(clean_token, tag)) {
|
||||
clean_token = Strings::Replace(clean_token, tag, "");
|
||||
out << rang::fgB::gray << "["
|
||||
<< rang::style::bold << color << clean_token
|
||||
<< rang::style::reset << rang::fgB::gray << "] ";
|
||||
matched = true;
|
||||
break;
|
||||
for (auto &c: matches) {
|
||||
if (Strings::Contains(e, c.first)) {
|
||||
(!is_error ? std::cout : std::cerr)
|
||||
<< rang::fgB::gray
|
||||
<< "["
|
||||
<< rang::style::bold
|
||||
<< c.second
|
||||
<< e
|
||||
<< rang::style::reset
|
||||
<< rang::fgB::gray
|
||||
<< "] ";
|
||||
match_color = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!matched) {
|
||||
for (auto &[keyword, color] : keyword_matches) {
|
||||
if (Strings::Contains(clean_token, keyword)) {
|
||||
out << rang::fgB::gray << "["
|
||||
<< rang::style::bold << color << clean_token
|
||||
<< rang::style::reset << rang::fgB::gray << "] ";
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!matched) {
|
||||
bool is_upper = std::any_of(clean_token.begin(), clean_token.end(), ::isupper);
|
||||
// if we don't match a color in either the string matching or
|
||||
// the color tag matching, we default to yellow inside brackets
|
||||
// if uppercase, does not get colored
|
||||
if (!match_color) {
|
||||
if (!is_upper) {
|
||||
out << rang::fgB::gray << "["
|
||||
<< rang::style::bold << "\033[92m" << clean_token
|
||||
<< rang::style::reset << rang::fgB::gray << "] ";
|
||||
} else {
|
||||
out << rang::fgB::gray << "[" << clean_token << "] ";
|
||||
(!is_error ? std::cout : std::cerr)
|
||||
<< rang::fgB::gray
|
||||
<< "["
|
||||
<< rang::style::bold
|
||||
<< rang::fgB::yellow
|
||||
<< e
|
||||
<< rang::style::reset
|
||||
<< rang::fgB::gray
|
||||
<< "] ";
|
||||
}
|
||||
else {
|
||||
(!is_error ? std::cout : std::cerr) << rang::fgB::gray << "[" << e << "] ";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out << (is_error ? rang::fgB::red : rang::fgB::gray) << token << " ";
|
||||
}
|
||||
else {
|
||||
(!is_error ? std::cout : std::cerr)
|
||||
<< (is_error ? rang::fgB::red : rang::fgB::gray)
|
||||
<< e
|
||||
<< " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if func is not empty
|
||||
if (func && *func) {
|
||||
out << rang::fgB::black << "#" << func << " ";
|
||||
else {
|
||||
(!is_error ? std::cout : std::cerr)
|
||||
<< (is_error ? rang::fgB::red : rang::fgB::gray)
|
||||
<< message
|
||||
<< " ";
|
||||
}
|
||||
|
||||
if (!origination_info.zone_short_name.empty()) {
|
||||
out << rang::fgB::black << "-- "
|
||||
<< fmt::format(
|
||||
(!is_error ? std::cout : std::cerr)
|
||||
<<
|
||||
rang::fgB::black
|
||||
<<
|
||||
"-- "
|
||||
<<
|
||||
fmt::format(
|
||||
"[{}] ({}) inst_id [{}]",
|
||||
origination_info.zone_short_name,
|
||||
origination_info.zone_long_name,
|
||||
@@ -332,12 +406,11 @@ void EQEmuLogSys::ProcessConsoleMessage(
|
||||
);
|
||||
}
|
||||
|
||||
out << rang::style::reset << std::endl;
|
||||
(!is_error ? std::cout : std::cerr) << rang::style::reset << std::endl;
|
||||
|
||||
m_on_log_console_hook(log_category, message);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param str
|
||||
* @return
|
||||
|
||||
@@ -449,11 +449,6 @@ inline auto logsys = EQEmuLogSys::Instance();
|
||||
OutF(logsys, Logs::General, Logs::Info, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogInfoNoFn(message, ...) do {\
|
||||
if (logsys->IsLogEnabled(Logs::General, Logs::Info))\
|
||||
OutF(logsys, Logs::General, Logs::Info, "", "", 0, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogInfoDetail(message, ...) do {\
|
||||
if (logsys->IsLogEnabled(Logs::Detail, Logs::Info))\
|
||||
OutF(logsys, Logs::Detail, Logs::Info, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
@@ -464,11 +459,6 @@ inline auto logsys = EQEmuLogSys::Instance();
|
||||
OutF(logsys, Logs::General, Logs::Warning, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogWarningNoFn(message, ...) do {\
|
||||
if (logsys->IsLogEnabled(Logs::General, Logs::Info))\
|
||||
OutF(logsys, Logs::General, Logs::Warning, "", "", 0, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogWarningDetail(message, ...) do {\
|
||||
if (logsys->IsLogEnabled(Logs::Detail, Logs::Warning))\
|
||||
OutF(logsys, Logs::Detail, Logs::Warning, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
|
||||
@@ -87,16 +87,16 @@ void PathManager::Init()
|
||||
constexpr int break_length = 70;
|
||||
|
||||
LogInfo("Loading server paths");
|
||||
LogInfoNoFn("{}", Strings::Repeat("-", break_length));
|
||||
LogInfo("{}", Strings::Repeat("-", break_length));
|
||||
for (const auto& [name, in_path] : paths) {
|
||||
if (!in_path.empty()) {
|
||||
LogInfoNoFn("{:>{}} > {:<{}}", name, name_width, in_path, path_width);
|
||||
LogInfo("{:>{}} > [{:<{}}]", name, name_width, in_path, path_width);
|
||||
}
|
||||
}
|
||||
|
||||
auto log_paths = [&](const std::string& label, const std::vector<std::string>& paths) {
|
||||
if (!paths.empty()) {
|
||||
LogInfoNoFn("{:>{}} > {:<{}}", label, name_width, Strings::Join(paths, ";"), path_width);
|
||||
LogInfo("{:>{}} > [{:<{}}]", label, name_width - 1, Strings::Join(paths, ";"), path_width);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -104,7 +104,7 @@ void PathManager::Init()
|
||||
log_paths("plugins", m_plugin_paths);
|
||||
log_paths("lua_modules", m_lua_module_paths);
|
||||
|
||||
LogInfoNoFn("{}", Strings::Repeat("-", break_length));
|
||||
LogInfo("{}", Strings::Repeat("-", break_length));
|
||||
}
|
||||
|
||||
const std::string &PathManager::GetServerPath() const
|
||||
|
||||
@@ -19,15 +19,8 @@
|
||||
class BaseRuleSetsRepository {
|
||||
public:
|
||||
struct RuleSets {
|
||||
int32_t ruleset_id;
|
||||
uint8_t ruleset_id;
|
||||
std::string name;
|
||||
std::string zone_ids;
|
||||
std::string instance_versions;
|
||||
std::string content_flags;
|
||||
std::string content_flags_disabled;
|
||||
int8_t min_expansion;
|
||||
int8_t max_expansion;
|
||||
std::string notes;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@@ -40,13 +33,6 @@ public:
|
||||
return {
|
||||
"ruleset_id",
|
||||
"name",
|
||||
"zone_ids",
|
||||
"instance_versions",
|
||||
"content_flags",
|
||||
"content_flags_disabled",
|
||||
"min_expansion",
|
||||
"max_expansion",
|
||||
"notes",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -55,13 +41,6 @@ public:
|
||||
return {
|
||||
"ruleset_id",
|
||||
"name",
|
||||
"zone_ids",
|
||||
"instance_versions",
|
||||
"content_flags",
|
||||
"content_flags_disabled",
|
||||
"min_expansion",
|
||||
"max_expansion",
|
||||
"notes",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -102,15 +81,8 @@ public:
|
||||
{
|
||||
RuleSets e{};
|
||||
|
||||
e.ruleset_id = 0;
|
||||
e.name = "";
|
||||
e.zone_ids = "";
|
||||
e.instance_versions = "";
|
||||
e.content_flags = "";
|
||||
e.content_flags_disabled = "";
|
||||
e.min_expansion = -2;
|
||||
e.max_expansion = -2;
|
||||
e.notes = "";
|
||||
e.ruleset_id = 0;
|
||||
e.name = "";
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -147,15 +119,8 @@ public:
|
||||
if (results.RowCount() == 1) {
|
||||
RuleSets e{};
|
||||
|
||||
e.ruleset_id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
||||
e.name = row[1] ? row[1] : "";
|
||||
e.zone_ids = row[2] ? row[2] : "";
|
||||
e.instance_versions = row[3] ? row[3] : "";
|
||||
e.content_flags = row[4] ? row[4] : "";
|
||||
e.content_flags_disabled = row[5] ? row[5] : "";
|
||||
e.min_expansion = row[6] ? static_cast<int8_t>(atoi(row[6])) : -2;
|
||||
e.max_expansion = row[7] ? static_cast<int8_t>(atoi(row[7])) : -2;
|
||||
e.notes = row[8] ? row[8] : "";
|
||||
e.ruleset_id = row[0] ? static_cast<uint8_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.name = row[1] ? row[1] : "";
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -190,13 +155,6 @@ public:
|
||||
auto columns = Columns();
|
||||
|
||||
v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'");
|
||||
v.push_back(columns[2] + " = '" + Strings::Escape(e.zone_ids) + "'");
|
||||
v.push_back(columns[3] + " = '" + Strings::Escape(e.instance_versions) + "'");
|
||||
v.push_back(columns[4] + " = '" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back(columns[5] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
v.push_back(columns[6] + " = " + std::to_string(e.min_expansion));
|
||||
v.push_back(columns[7] + " = " + std::to_string(e.max_expansion));
|
||||
v.push_back(columns[8] + " = '" + Strings::Escape(e.notes) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -220,13 +178,6 @@ public:
|
||||
|
||||
v.push_back(std::to_string(e.ruleset_id));
|
||||
v.push_back("'" + Strings::Escape(e.name) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.zone_ids) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.instance_versions) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.notes) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -258,13 +209,6 @@ public:
|
||||
|
||||
v.push_back(std::to_string(e.ruleset_id));
|
||||
v.push_back("'" + Strings::Escape(e.name) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.zone_ids) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.instance_versions) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.notes) + "'");
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@@ -298,15 +242,8 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
RuleSets e{};
|
||||
|
||||
e.ruleset_id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
||||
e.name = row[1] ? row[1] : "";
|
||||
e.zone_ids = row[2] ? row[2] : "";
|
||||
e.instance_versions = row[3] ? row[3] : "";
|
||||
e.content_flags = row[4] ? row[4] : "";
|
||||
e.content_flags_disabled = row[5] ? row[5] : "";
|
||||
e.min_expansion = row[6] ? static_cast<int8_t>(atoi(row[6])) : -2;
|
||||
e.max_expansion = row[7] ? static_cast<int8_t>(atoi(row[7])) : -2;
|
||||
e.notes = row[8] ? row[8] : "";
|
||||
e.ruleset_id = row[0] ? static_cast<uint8_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.name = row[1] ? row[1] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -331,15 +268,8 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
RuleSets e{};
|
||||
|
||||
e.ruleset_id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
||||
e.name = row[1] ? row[1] : "";
|
||||
e.zone_ids = row[2] ? row[2] : "";
|
||||
e.instance_versions = row[3] ? row[3] : "";
|
||||
e.content_flags = row[4] ? row[4] : "";
|
||||
e.content_flags_disabled = row[5] ? row[5] : "";
|
||||
e.min_expansion = row[6] ? static_cast<int8_t>(atoi(row[6])) : -2;
|
||||
e.max_expansion = row[7] ? static_cast<int8_t>(atoi(row[7])) : -2;
|
||||
e.notes = row[8] ? row[8] : "";
|
||||
e.ruleset_id = row[0] ? static_cast<uint8_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.name = row[1] ? row[1] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -416,13 +346,6 @@ public:
|
||||
|
||||
v.push_back(std::to_string(e.ruleset_id));
|
||||
v.push_back("'" + Strings::Escape(e.name) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.zone_ids) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.instance_versions) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.notes) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -447,13 +370,6 @@ public:
|
||||
|
||||
v.push_back(std::to_string(e.ruleset_id));
|
||||
v.push_back("'" + Strings::Escape(e.name) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.zone_ids) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.instance_versions) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.notes) + "'");
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
class BaseRuleValuesRepository {
|
||||
public:
|
||||
struct RuleValues {
|
||||
int32_t ruleset_id;
|
||||
uint8_t ruleset_id;
|
||||
std::string rule_name;
|
||||
std::string rule_value;
|
||||
std::string notes;
|
||||
@@ -127,7 +127,7 @@ public:
|
||||
if (results.RowCount() == 1) {
|
||||
RuleValues e{};
|
||||
|
||||
e.ruleset_id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
||||
e.ruleset_id = row[0] ? static_cast<uint8_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.rule_name = row[1] ? row[1] : "";
|
||||
e.rule_value = row[2] ? row[2] : "";
|
||||
e.notes = row[3] ? row[3] : "";
|
||||
@@ -259,7 +259,7 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
RuleValues e{};
|
||||
|
||||
e.ruleset_id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
||||
e.ruleset_id = row[0] ? static_cast<uint8_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.rule_name = row[1] ? row[1] : "";
|
||||
e.rule_value = row[2] ? row[2] : "";
|
||||
e.notes = row[3] ? row[3] : "";
|
||||
@@ -287,7 +287,7 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
RuleValues e{};
|
||||
|
||||
e.ruleset_id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
||||
e.ruleset_id = row[0] ? static_cast<uint8_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.rule_name = row[1] ? row[1] : "";
|
||||
e.rule_value = row[2] ? row[2] : "";
|
||||
e.notes = row[3] ? row[3] : "";
|
||||
|
||||
@@ -142,6 +142,7 @@ public:
|
||||
{.parent_command = "show", .sub_command = "hatelist", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "hatelist"},
|
||||
{.parent_command = "show", .sub_command = "inventory", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "peekinv"},
|
||||
{.parent_command = "show", .sub_command = "ip_lookup", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "iplookup"},
|
||||
{.parent_command = "show", .sub_command = "keyring", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showkeyring"},
|
||||
{.parent_command = "show", .sub_command = "line_of_sight", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "checklos"},
|
||||
{.parent_command = "show", .sub_command = "network", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "network"},
|
||||
{.parent_command = "show", .sub_command = "network_stats", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "netstats"},
|
||||
|
||||
+1
-17
@@ -26,7 +26,6 @@
|
||||
|
||||
#include "../common/repositories/rule_sets_repository.h"
|
||||
#include "../common/repositories/rule_values_repository.h"
|
||||
#include "../common/content/world_content_service.h"
|
||||
|
||||
const char *RuleManager::s_categoryNames[_CatCount + 1] = {
|
||||
#define RULE_CATEGORY(category_name) \
|
||||
@@ -269,6 +268,7 @@ bool RuleManager::LoadRules(Database *db, const std::string &rule_set_name, bool
|
||||
|
||||
const std::string default_ruleset_name = "default";
|
||||
bool is_default = rule_set_name == default_ruleset_name;
|
||||
|
||||
if (!is_default) {
|
||||
const auto default_rule_set_id = RuleSetsRepository::GetRuleSetID(*db, default_ruleset_name);
|
||||
|
||||
@@ -327,10 +327,6 @@ bool RuleManager::LoadRules(Database *db, const std::string &rule_set_name, bool
|
||||
rule_set_id
|
||||
);
|
||||
|
||||
if (m_post_load_callback) {
|
||||
m_post_load_callback();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -666,15 +662,3 @@ std::string RuleManager::GetStringRule(RuleManager::StringType t) const
|
||||
{
|
||||
return m_RuleStringValues[t];
|
||||
}
|
||||
|
||||
std::string RuleManager::GetRuleNotesByName(std::string rule_name) const
|
||||
{
|
||||
for (const auto &r : s_RuleInfo) {
|
||||
if (Strings::EqualFold(r.name, rule_name)) {
|
||||
return r.notes;
|
||||
}
|
||||
}
|
||||
|
||||
LogRulesDetail("Unable to find rule notes for '{}'.", rule_name);
|
||||
return "";
|
||||
}
|
||||
+3
-11
@@ -40,7 +40,6 @@
|
||||
RuleManager::Instance()->GetStringRule( RuleManager::String__##rule_name )
|
||||
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
@@ -120,9 +119,9 @@ public:
|
||||
static const uint32 RulesCount = IntRuleCount + RealRuleCount + BoolRuleCount + StringRuleCount;
|
||||
|
||||
//fetch routines, you should generally use the Rule* macros instead of this
|
||||
int GetIntRule(IntType t) const;
|
||||
float GetRealRule(RealType t) const;
|
||||
bool GetBoolRule(BoolType t) const;
|
||||
int GetIntRule(IntType t) const;
|
||||
float GetRealRule(RealType t) const;
|
||||
bool GetBoolRule(BoolType t) const;
|
||||
std::string GetStringRule(StringType t) const;
|
||||
|
||||
//management routines
|
||||
@@ -134,8 +133,6 @@ public:
|
||||
static const std::string& GetRuleNotes(RealType t) { return s_RuleInfo[static_cast<int>(t) + IntRuleCount].notes; }
|
||||
static const std::string& GetRuleNotes(BoolType t) { return s_RuleInfo[static_cast<int>(t) + IntRuleCount + RealRuleCount].notes; }
|
||||
static const std::string& GetRuleNotes(StringType t) { return s_RuleInfo[static_cast<int>(t) + IntRuleCount + RealRuleCount + StringRuleCount].notes; }
|
||||
std::string GetRuleNotesByName(std::string rule_name) const;
|
||||
|
||||
static uint32 CountRules() { return RulesCount; }
|
||||
static CategoryType FindCategory(const std::string& category_name);
|
||||
bool ListRules(const std::string& category_name, std::vector<std::string>& l);
|
||||
@@ -159,9 +156,6 @@ public:
|
||||
bool UpdateInjectedRules(Database* db, const std::string& rule_set_name, bool quiet_update = false);
|
||||
bool UpdateOrphanedRules(Database* db, bool quiet_update = false);
|
||||
bool RestoreRuleNotes(Database* db);
|
||||
void SetPostLoadCallback(std::function<void()> cb) {
|
||||
m_post_load_callback = std::move(cb);
|
||||
}
|
||||
|
||||
private:
|
||||
RuleManager();
|
||||
@@ -176,8 +170,6 @@ private:
|
||||
uint32 m_RuleBoolValues[BoolRuleCount];
|
||||
std::string m_RuleStringValues[StringRuleCount];
|
||||
|
||||
std::function<void()> m_post_load_callback;
|
||||
|
||||
typedef enum {
|
||||
IntRule,
|
||||
RealRule,
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
|
||||
// Build variables
|
||||
// these get injected during the build pipeline
|
||||
#define CURRENT_VERSION "23.8.1-dev" // always append -dev to the current version for custom-builds
|
||||
#define CURRENT_VERSION "23.9.1-dev" // always append -dev to the current version for custom-builds
|
||||
#define LOGIN_VERSION "0.8.0"
|
||||
#define COMPILE_DATE __DATE__
|
||||
#define COMPILE_TIME __TIME__
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
inline void DefaultLoginServerName(const std::string &v) { m_default_loginserver_name = v; }
|
||||
inline std::string GetDefaultLoginServerName() const { return m_default_loginserver_name; }
|
||||
inline bool IsShowPlayerCountEnabled() const { return m_show_player_count; }
|
||||
inline void SetShowPlayerCount(bool show_player_count) { show_player_count = show_player_count; }
|
||||
inline void SetShowPlayerCount(bool show_player_count) { m_show_player_count = show_player_count; }
|
||||
inline bool IsWorldDevTestServersListBottom() const { return m_world_dev_list_bottom; }
|
||||
inline void SetWorldDevTestServersListBottom(bool list_bottom) { m_world_dev_list_bottom = list_bottom; }
|
||||
inline bool IsWorldSpecialCharacterStartListBottom() const { return m_special_char_list_bottom; }
|
||||
|
||||
@@ -155,7 +155,11 @@ void WorldServer::ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Ne
|
||||
auto *res = (UsertoWorldResponseLegacy *) packet.Data();
|
||||
|
||||
LogDebug("Trying to find client with user id of [{}]", res->lsaccountid);
|
||||
Client *c = server.client_manager->GetClient(res->lsaccountid, "eqemu");
|
||||
std::string db_loginserver = "local";
|
||||
if (std::getenv("LSPX")) {
|
||||
db_loginserver = "eqemu";
|
||||
}
|
||||
Client *c = server.client_manager->GetClient(res->lsaccountid, db_loginserver);
|
||||
if (c) {
|
||||
LogDebug(
|
||||
"Found client with user id of [{}] and account name of [{}]",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "eqemu-server",
|
||||
"version": "23.8.1",
|
||||
"version": "23.9.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/EQEmu/Server.git"
|
||||
|
||||
@@ -6,13 +6,10 @@ toolchain go1.23.5
|
||||
|
||||
require (
|
||||
github.com/google/go-github/v41 v41.0.0
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be
|
||||
golang.org/x/oauth2 v0.27.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/golang/protobuf v1.3.2 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
golang.org/x/crypto v0.36.0 // indirect
|
||||
golang.org/x/net v0.38.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-github/v41 v41.0.0 h1:HseJrM2JFf2vfiZJ8anY2hqBjdfY1Vlj/K27ueww4gg=
|
||||
github.com/google/go-github/v41 v41.0.0/go.mod h1:XgmCA5H323A9rtgExdTcnDkcqp6S30AVACCBDOonIxg=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
@@ -14,10 +14,9 @@ golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
|
||||
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -27,5 +26,4 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
|
||||
+88
-55
@@ -419,7 +419,7 @@ void WorldBoot::CheckForPossibleConfigurationIssues()
|
||||
const auto c = EQEmuConfig::get();
|
||||
|
||||
if (c->DisableConfigChecks) {
|
||||
LogInfoNoFn("Configuration checking [disabled]");
|
||||
LogInfo("Configuration checking [disabled]");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -429,17 +429,17 @@ void WorldBoot::CheckForPossibleConfigurationIssues()
|
||||
const std::ifstream is_in_docker("/.dockerenv");
|
||||
|
||||
if (local_address.empty() && public_address.empty()) {
|
||||
LogInfoNoFn("Configuration check, probes failed for local and public address, returning");
|
||||
LogInfo("Configuration check, probes failed for local and public address, returning");
|
||||
return;
|
||||
}
|
||||
|
||||
LogInfoNoFn("Checking for possible configuration issues");
|
||||
LogInfoNoFn("To disable configuration checks, set [server.disable_config_checks] to [true] in [{}]", config_file);
|
||||
LogInfo("Checking for possible configuration issues");
|
||||
LogInfo("To disable configuration checks, set [server.disable_config_checks] to [true] in [{}]", config_file);
|
||||
|
||||
std::string config_address = c->WorldAddress;
|
||||
if (!IpUtil::IsIPAddress(config_address)) {
|
||||
config_address = IpUtil::DNSLookupSync(c->WorldAddress, 9000);
|
||||
LogInfoNoFn(
|
||||
LogInfo(
|
||||
"World config address using DNS [{}] resolves to [{}]",
|
||||
c->WorldAddress,
|
||||
config_address
|
||||
@@ -454,12 +454,16 @@ void WorldBoot::CheckForPossibleConfigurationIssues()
|
||||
&& local_address != c->LocalAddress
|
||||
&& !is_in_docker
|
||||
) {
|
||||
LogWarningNoFn("# LAN detection (Configuration)");
|
||||
LogWarningNoFn("You appear to be on a LAN and your localaddress may not be properly set!");
|
||||
LogWarningNoFn("This can prevent local clients from properly connecting to your server");
|
||||
LogWarningNoFn("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
||||
LogWarningNoFn("Config file [{}] path [server.world] variable [localaddress]", config_file);
|
||||
LogWarningNoFn("Local address (eqemu_config) value [{}] detected value [{}]", c->LocalAddress, local_address);
|
||||
LogWarning("# LAN detection (Configuration)");
|
||||
LogWarning("");
|
||||
LogWarning("You appear to be on a LAN and your localaddress may not be properly set!");
|
||||
LogWarning("This can prevent local clients from properly connecting to your server");
|
||||
LogWarning("");
|
||||
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
||||
LogWarning("");
|
||||
LogWarning("Config file [{}] path [server.world] variable [localaddress]", config_file);
|
||||
LogWarning("");
|
||||
LogWarning("Local address (eqemu_config) value [{}] detected value [{}]", c->LocalAddress, local_address);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
@@ -471,21 +475,28 @@ void WorldBoot::CheckForPossibleConfigurationIssues()
|
||||
)
|
||||
&& is_in_docker
|
||||
) {
|
||||
LogWarningNoFn("# Docker Configuration (Configuration)");
|
||||
LogWarningNoFn("You appear to running EQEmu in a docker container");
|
||||
LogWarningNoFn("In order for networking to work properly you will need to properly configure your server");
|
||||
LogWarningNoFn(
|
||||
LogWarning("# Docker Configuration (Configuration)");
|
||||
LogWarning("");
|
||||
LogWarning("You appear to running EQEmu in a docker container");
|
||||
LogWarning("In order for networking to work properly you will need to properly configure your server");
|
||||
LogWarning("");
|
||||
LogWarning(
|
||||
"If your Docker host is on a [LAN] or behind a NAT / Firewall, your [localaddress] variable under [server.world] will need to");
|
||||
LogWarningNoFn(
|
||||
LogWarning(
|
||||
"be set to your LAN address on the host, not the container address. [address] will need to be your public address");
|
||||
LogWarningNoFn(
|
||||
LogWarning("");
|
||||
LogWarning(
|
||||
"If your Docker host is directly on the [public internet], your [localaddress] variable under [server.world] can be set to [127.0.0.1]."
|
||||
);
|
||||
LogWarningNoFn("[address] will need to be your public address");
|
||||
LogWarningNoFn("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
||||
LogWarningNoFn("Config file [{}] path [server.world] variable(s) [localaddress] [address]", config_file);
|
||||
LogWarningNoFn("Local address (eqemu_config) value [{}] detected value [{}]", c->LocalAddress, local_address);
|
||||
LogWarningNoFn(
|
||||
LogWarning("");
|
||||
LogWarning("[address] will need to be your public address");
|
||||
LogWarning("");
|
||||
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
||||
LogWarning("");
|
||||
LogWarning("Config file [{}] path [server.world] variable(s) [localaddress] [address]", config_file);
|
||||
LogWarning("");
|
||||
LogWarning("Local address (eqemu_config) value [{}] detected value [{}]", c->LocalAddress, local_address);
|
||||
LogWarning(
|
||||
"Public address (eqemu_config) value [{}] detected value [{}]",
|
||||
config_address,
|
||||
public_address
|
||||
@@ -495,23 +506,30 @@ void WorldBoot::CheckForPossibleConfigurationIssues()
|
||||
|
||||
// docker LAN not set
|
||||
if (c->LocalAddress.empty() && is_in_docker) {
|
||||
LogWarningNoFn("# Docker LAN (Configuration)");
|
||||
LogWarningNoFn("You appear to running EQEmu in a docker container");
|
||||
LogWarningNoFn(
|
||||
LogWarning("# Docker LAN (Configuration)");
|
||||
LogWarning("");
|
||||
LogWarning("You appear to running EQEmu in a docker container");
|
||||
LogWarning(
|
||||
"Your local address does not appear to be set, this may not be an issue if your deployment is not on a LAN"
|
||||
);
|
||||
LogWarningNoFn(
|
||||
LogWarning("");
|
||||
LogWarning(
|
||||
"If your Docker host is on a [LAN] or behind a NAT / Firewall, your [localaddress] variable under [server.world] will need to");
|
||||
LogWarningNoFn(
|
||||
LogWarning(
|
||||
"be set to your LAN address on the host, not the container address. [address] will need to be your public address");
|
||||
LogWarningNoFn(
|
||||
LogWarning("");
|
||||
LogWarning(
|
||||
"If your Docker host is directly on the [public internet], your [localaddress] variable under [server.world] can be set to [127.0.0.1]."
|
||||
);
|
||||
LogWarningNoFn("[address] will need to be your public address");
|
||||
LogWarningNoFn("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
||||
LogWarningNoFn("Config file [{}] path [server.world] variable(s) [localaddress] [address]", config_file);
|
||||
LogWarningNoFn("Local address (eqemu_config) value [{}] detected value [{}]", c->LocalAddress, local_address);
|
||||
LogWarningNoFn(
|
||||
LogWarning("");
|
||||
LogWarning("[address] will need to be your public address");
|
||||
LogWarning("");
|
||||
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
||||
LogWarning("");
|
||||
LogWarning("Config file [{}] path [server.world] variable(s) [localaddress] [address]", config_file);
|
||||
LogWarning("");
|
||||
LogWarning("Local address (eqemu_config) value [{}] detected value [{}]", c->LocalAddress, local_address);
|
||||
LogWarning(
|
||||
"Public address (eqemu_config) value [{}] detected value [{}]",
|
||||
config_address,
|
||||
public_address
|
||||
@@ -521,11 +539,15 @@ void WorldBoot::CheckForPossibleConfigurationIssues()
|
||||
|
||||
// public address different from configuration
|
||||
if (!config_address.empty() && public_address != config_address) {
|
||||
LogWarningNoFn("# Public address (Configuration)");
|
||||
LogWarningNoFn("Your configured public address appears to be different from what's detected!");
|
||||
LogWarningNoFn("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
||||
LogWarningNoFn("Config file [{}] path [server.world] variable [address]", config_file);
|
||||
LogWarningNoFn(
|
||||
LogWarning("# Public address (Configuration)");
|
||||
LogWarning("");
|
||||
LogWarning("Your configured public address appears to be different from what's detected!");
|
||||
LogWarning("");
|
||||
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
||||
LogWarning("");
|
||||
LogWarning("Config file [{}] path [server.world] variable [address]", config_file);
|
||||
LogWarning("");
|
||||
LogWarning(
|
||||
"Public address (eqemu_config) value [{}] detected value [{}]",
|
||||
config_address,
|
||||
public_address
|
||||
@@ -535,13 +557,17 @@ void WorldBoot::CheckForPossibleConfigurationIssues()
|
||||
|
||||
// public address set to meta-address
|
||||
if (config_address == "0.0.0.0") {
|
||||
LogWarningNoFn("# Public meta-address (Configuration)");
|
||||
LogWarningNoFn("Your configured public address is set to a meta-address (0.0.0.0) (all-interfaces)");
|
||||
LogWarningNoFn(
|
||||
LogWarning("# Public meta-address (Configuration)");
|
||||
LogWarning("");
|
||||
LogWarning("Your configured public address is set to a meta-address (0.0.0.0) (all-interfaces)");
|
||||
LogWarning(
|
||||
"The meta-address may not work properly and it is recommended you configure your public address explicitly");
|
||||
LogWarningNoFn("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
||||
LogWarningNoFn("Config file [{}] path [server.world] variable [address]", config_file);
|
||||
LogWarningNoFn(
|
||||
LogWarning("");
|
||||
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
||||
LogWarning("");
|
||||
LogWarning("Config file [{}] path [server.world] variable [address]", config_file);
|
||||
LogWarning("");
|
||||
LogWarning(
|
||||
"Public address (eqemu_config) value [{}] detected value [{}]",
|
||||
config_address,
|
||||
public_address
|
||||
@@ -551,14 +577,18 @@ void WorldBoot::CheckForPossibleConfigurationIssues()
|
||||
|
||||
// local address set to meta-address
|
||||
if (c->LocalAddress == "0.0.0.0") {
|
||||
LogWarningNoFn("# Local meta-address (Configuration)");
|
||||
LogWarningNoFn("Your configured local address is set to a meta-address (0.0.0.0) (all-interfaces)");
|
||||
LogWarningNoFn(
|
||||
LogWarning("# Local meta-address (Configuration)");
|
||||
LogWarning("");
|
||||
LogWarning("Your configured local address is set to a meta-address (0.0.0.0) (all-interfaces)");
|
||||
LogWarning(
|
||||
"The meta-address may not work properly and it is recommended you configure your local address explicitly"
|
||||
);
|
||||
LogWarningNoFn("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
||||
LogWarningNoFn("Config file [{}] path [server.world] variable [localaddress]", config_file);
|
||||
LogWarningNoFn("Local address (eqemu_config) value [{}] detected value [{}]", c->LocalAddress, local_address);
|
||||
LogWarning("");
|
||||
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
||||
LogWarning("");
|
||||
LogWarning("Config file [{}] path [server.world] variable [localaddress]", config_file);
|
||||
LogWarning("");
|
||||
LogWarning("Local address (eqemu_config) value [{}] detected value [{}]", c->LocalAddress, local_address);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
@@ -566,13 +596,16 @@ void WorldBoot::CheckForPossibleConfigurationIssues()
|
||||
if (
|
||||
(!config_address.empty() && c->GetUCSHost() != config_address)
|
||||
) {
|
||||
LogWarningNoFn("# UCS Address Mailhost (Configuration)");
|
||||
LogWarningNoFn(
|
||||
LogWarning("# UCS Address Mailhost (Configuration)");
|
||||
LogWarning("");
|
||||
LogWarning(
|
||||
"UCS (Universal Chat Service) mail or chat appears to use a different address from your main world address"
|
||||
);
|
||||
LogWarningNoFn("This can result in a chat service that doesn't network properly");
|
||||
LogWarningNoFn("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#mailserver]");
|
||||
LogWarningNoFn(
|
||||
LogWarning("This can result in a chat service that doesn't network properly");
|
||||
LogWarning("");
|
||||
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#mailserver]");
|
||||
LogWarning("");
|
||||
LogWarning(
|
||||
"[server.world.address] value [{}] [server.ucs.host] [{}]",
|
||||
config_address,
|
||||
c->GetUCSHost()
|
||||
|
||||
+7
-3
@@ -901,9 +901,13 @@ bool WorldDatabase::GetCharSelInventory(
|
||||
inst->SetCustomDataString(e.custom_data);
|
||||
}
|
||||
|
||||
inst->SetOrnamentIcon(e.ornament_icon);
|
||||
inst->SetOrnamentationIDFile(e.ornament_idfile);
|
||||
inst->SetOrnamentHeroModel(e.ornament_hero_model);
|
||||
if (e.ornament_icon != 0 || e.ornament_idfile != 0 || e.ornament_hero_model != 0) {
|
||||
inst->SetOrnamentIcon(e.ornament_icon);
|
||||
inst->SetOrnamentationIDFile(e.ornament_idfile);
|
||||
inst->SetOrnamentHeroModel(e.ornament_hero_model);
|
||||
} else if (item->HerosForgeModel > 0) {
|
||||
inst->SetOrnamentHeroModel(item->HerosForgeModel);
|
||||
}
|
||||
|
||||
inv->PutItem(e.slot_id, *inst);
|
||||
|
||||
|
||||
+1
-1
@@ -502,7 +502,7 @@ if (EQEMU_BUILD_STATIC AND PERL_LIBRARY)
|
||||
endif()
|
||||
|
||||
# link zone against common libraries
|
||||
target_link_libraries(zone PRIVATE ${ZONE_LIBS} lua_zone perl_zone gm_commands_zone)
|
||||
target_link_libraries(zone PRIVATE lua_zone perl_zone gm_commands_zone ${ZONE_LIBS})
|
||||
|
||||
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
|
||||
|
||||
|
||||
+15
-3
@@ -4780,9 +4780,21 @@ bool Client::KeyRingClear()
|
||||
);
|
||||
}
|
||||
|
||||
void Client::KeyRingList()
|
||||
void Client::KeyRingList(Client* c)
|
||||
{
|
||||
Message(Chat::LightBlue, "Keys on Keyring:");
|
||||
if (!c) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string message = "Keys on Keyring:";
|
||||
if (c != this) {
|
||||
message = fmt::format(
|
||||
"Keys on Keyring for {}:",
|
||||
GetCleanName()
|
||||
);
|
||||
}
|
||||
|
||||
c->Message(Chat::LightBlue, message.c_str());
|
||||
|
||||
const EQ::ItemData *item = nullptr;
|
||||
|
||||
@@ -4795,7 +4807,7 @@ void Client::KeyRingList()
|
||||
item->Name
|
||||
);
|
||||
|
||||
Message(Chat::LightBlue, item_string.c_str());
|
||||
c->Message(Chat::LightBlue, item_string.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -331,7 +331,7 @@ public:
|
||||
bool KeyRingCheck(uint32 item_id);
|
||||
bool KeyRingClear();
|
||||
bool KeyRingRemove(uint32 item_id);
|
||||
void KeyRingList();
|
||||
void KeyRingList(Client* c = nullptr);
|
||||
bool IsNameChangeAllowed();
|
||||
void InvokeChangeNameWindow(bool immediate = true);
|
||||
bool ClearNameChange();
|
||||
|
||||
+9
-16
@@ -4983,9 +4983,6 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
||||
m_Proximity = glm::vec3(cx, cy, cz);
|
||||
}
|
||||
|
||||
/* Update internal state */
|
||||
m_Delta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, EQ10toFloat(ppu->delta_heading));
|
||||
|
||||
if (RuleB(Skills, TrackingAutoRefreshSkillUps) && IsTracking() && ((m_Position.x != cx) || (m_Position.y != cy))) {
|
||||
if (zone->random.Real(0, 100) < 70)//should be good
|
||||
CheckIncreaseSkill(EQ::skills::SkillTracking, nullptr, -20);
|
||||
@@ -5019,6 +5016,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
||||
rewind_timer.Start(30000, true);
|
||||
}
|
||||
|
||||
glm::vec4 prevDelta = m_Delta; // SetMoving clears m_Delta
|
||||
SetMoving(!(cy == m_Position.y && cx == m_Position.x));
|
||||
|
||||
if (RuleB(Character, EnableAutoAFK)) {
|
||||
@@ -5033,12 +5031,13 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
||||
|
||||
CheckSendBulkNpcPositions();
|
||||
|
||||
int32 new_animation = ppu->animation;
|
||||
|
||||
/* Update internal server position from what the client has sent */
|
||||
m_Position.x = cx;
|
||||
m_Position.y = cy;
|
||||
m_Position.z = cz;
|
||||
glm::vec4 prevPosition = m_Position;
|
||||
m_Position = glm::vec4(cx, cy, cz, new_heading);
|
||||
m_Delta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, EQ10toFloat(ppu->delta_heading));
|
||||
int32 prevAnimation = ppu->animation;
|
||||
animation = ppu->animation;
|
||||
bool positionUpdated = m_Position != prevPosition || m_Delta != prevDelta || m_Delta != glm::vec4(0.0f) || prevAnimation != animation;
|
||||
|
||||
/* Visual Debugging */
|
||||
if (RuleB(Character, OPClientUpdateVisualDebug)) {
|
||||
@@ -5048,11 +5047,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
||||
}
|
||||
|
||||
/* Only feed real time updates when client is moving */
|
||||
if (IsMoving() || new_heading != m_Position.w || new_animation != animation) {
|
||||
|
||||
animation = ppu->animation;
|
||||
m_Position.w = new_heading;
|
||||
|
||||
if (positionUpdated) {
|
||||
/* Broadcast update to other clients */
|
||||
static EQApplicationPacket outapp(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
|
||||
PlayerPositionUpdateServer_Struct *position_update = (PlayerPositionUpdateServer_Struct *) outapp.pBuffer;
|
||||
@@ -5065,7 +5060,6 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
||||
entity_list.QueueCloseClients(this, &outapp, true, RuleI(Range, ClientPositionUpdates), nullptr, true);
|
||||
}
|
||||
|
||||
|
||||
/* Always send position updates to group - send when beyond normal ClientPositionUpdate range */
|
||||
Group *group = GetGroup();
|
||||
Raid *raid = GetRaid();
|
||||
@@ -5091,7 +5085,6 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
||||
}
|
||||
|
||||
CheckVirtualZoneLines();
|
||||
|
||||
}
|
||||
|
||||
void Client::Handle_OP_CombatAbility(const EQApplicationPacket *app)
|
||||
@@ -9789,7 +9782,7 @@ void Client::Handle_OP_Jump(const EQApplicationPacket *app)
|
||||
|
||||
void Client::Handle_OP_KeyRing(const EQApplicationPacket *app)
|
||||
{
|
||||
KeyRingList();
|
||||
KeyRingList(this);
|
||||
}
|
||||
|
||||
void Client::Handle_OP_KickPlayers(const EQApplicationPacket *app)
|
||||
|
||||
+5
-3
@@ -998,11 +998,13 @@ int PerlembParser::SendCommands(
|
||||
|
||||
int ret_value = 0;
|
||||
RunningQuest q;
|
||||
|
||||
q.owner = other;
|
||||
q.questitem = inst;
|
||||
q.questspell = spell;
|
||||
|
||||
if (mob && mob->IsClient()) {
|
||||
q.owner = other;
|
||||
q.initiator = mob->CastToClient();
|
||||
q.questitem = inst;
|
||||
q.questspell = spell;
|
||||
}
|
||||
|
||||
if (zone) {
|
||||
|
||||
@@ -6005,6 +6005,40 @@ bool Perl__handin(perl::reference handin_ref)
|
||||
return quest_manager.handin(handin_map);
|
||||
}
|
||||
|
||||
perl::array Perl__get_paused_timers(Mob* m)
|
||||
{
|
||||
perl::array a;
|
||||
|
||||
const auto& l = quest_manager.GetPausedTimers(m);
|
||||
|
||||
if (!l.empty()) {
|
||||
a.reserve(l.size());
|
||||
|
||||
for (const auto& v : l) {
|
||||
a.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
perl::array Perl__get_timers(Mob* m)
|
||||
{
|
||||
perl::array a;
|
||||
|
||||
const auto& l = quest_manager.GetTimers(m);
|
||||
|
||||
if (!l.empty()) {
|
||||
a.reserve(l.size());
|
||||
|
||||
for (const auto& v: l) {
|
||||
a.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
void perl_register_quest()
|
||||
{
|
||||
perl::interpreter perl(PERL_GET_THX);
|
||||
@@ -6694,6 +6728,7 @@ void perl_register_quest()
|
||||
package.add("getguildidbycharid", &Perl__getguildidbycharid);
|
||||
package.add("getgroupidbycharid", &Perl__getgroupidbycharid);
|
||||
package.add("getinventoryslotname", &Perl__getinventoryslotname);
|
||||
package.add("get_paused_timers", &Perl__get_paused_timers);
|
||||
package.add("getraididbycharid", &Perl__getraididbycharid);
|
||||
package.add("get_race_bitmask", &Perl__get_race_bitmask);
|
||||
package.add("get_recipe_component_item_ids", &Perl__GetRecipeComponentItemIDs);
|
||||
@@ -6713,6 +6748,7 @@ void perl_register_quest()
|
||||
package.add("getspellstat", (int(*)(uint32, std::string))&Perl__getspellstat);
|
||||
package.add("getspellstat", (int(*)(uint32, std::string, uint8))&Perl__getspellstat);
|
||||
package.add("getskillname", &Perl__getskillname);
|
||||
package.add("get_timers", &Perl__get_timers);
|
||||
package.add("getlevel", &Perl__getlevel);
|
||||
package.add("getplayerburiedcorpsecount", &Perl__getplayerburiedcorpsecount);
|
||||
package.add("getplayercorpsecount", &Perl__getplayercorpsecount);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "show/group_info.cpp"
|
||||
#include "show/hatelist.cpp"
|
||||
#include "show/inventory.cpp"
|
||||
#include "show/keyring.cpp"
|
||||
#include "show/ip_lookup.cpp"
|
||||
#include "show/line_of_sight.cpp"
|
||||
#include "show/network.cpp"
|
||||
@@ -78,6 +79,7 @@ void command_show(Client *c, const Seperator *sep)
|
||||
Cmd{.cmd = "hatelist", .u = "hatelist", .fn = ShowHateList, .a = {"#hatelist"}},
|
||||
Cmd{.cmd = "inventory", .u = "inventory", .fn = ShowInventory, .a = {"#peekinv"}},
|
||||
Cmd{.cmd = "ip_lookup", .u = "ip_lookup", .fn = ShowIPLookup, .a = {"#iplookup"}},
|
||||
Cmd{.cmd = "keyring", .u = "keyring", .fn = ShowKeyring, .a = {"#showkeyring"}},
|
||||
Cmd{.cmd = "line_of_sight", .u = "line_of_sight", .fn = ShowLineOfSight, .a = {"#checklos"}},
|
||||
Cmd{.cmd = "network", .u = "network", .fn = ShowNetwork, .a = {"#network"}},
|
||||
Cmd{.cmd = "network_stats", .u = "network_stats", .fn = ShowNetworkStats, .a = {"#netstats"}},
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "../../client.h"
|
||||
#include "../../dialogue_window.h"
|
||||
|
||||
void ShowKeyring(Client *c, const Seperator *sep)
|
||||
{
|
||||
Client* t = c;
|
||||
if (c->GetTarget() && c->GetTarget()->IsClient()) {
|
||||
t = c->GetTarget()->CastToClient();
|
||||
}
|
||||
|
||||
t->KeyRingList(c);
|
||||
}
|
||||
+8
-1
@@ -3575,7 +3575,13 @@ bool Lua_Client::KeyRingClear()
|
||||
void Lua_Client::KeyRingList()
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
self->KeyRingList();
|
||||
self->KeyRingList(self);
|
||||
}
|
||||
|
||||
void Lua_Client::KeyRingList(Lua_Client c)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
self->KeyRingList(self);
|
||||
}
|
||||
|
||||
bool Lua_Client::KeyRingRemove(uint32 item_id)
|
||||
@@ -3932,6 +3938,7 @@ luabind::scope lua_register_client() {
|
||||
.def("KeyRingCheck", (bool(Lua_Client::*)(uint32))&Lua_Client::KeyRingCheck)
|
||||
.def("KeyRingClear", (bool(Lua_Client::*)(void))&Lua_Client::KeyRingClear)
|
||||
.def("KeyRingList", (void(Lua_Client::*)(void))&Lua_Client::KeyRingList)
|
||||
.def("KeyRingList", (void(Lua_Client::*)(Lua_Client))&Lua_Client::KeyRingList)
|
||||
.def("KeyRingRemove", (bool(Lua_Client::*)(uint32))&Lua_Client::KeyRingRemove)
|
||||
.def("Kick", (void(Lua_Client::*)(void))&Lua_Client::Kick)
|
||||
.def("LearnDisciplines", (uint16(Lua_Client::*)(uint8,uint8))&Lua_Client::LearnDisciplines)
|
||||
|
||||
@@ -521,6 +521,7 @@ public:
|
||||
bool KeyRingCheck(uint32 item_id);
|
||||
bool KeyRingClear();
|
||||
void KeyRingList();
|
||||
void KeyRingList(Lua_Client c);
|
||||
bool KeyRingRemove(uint32 item_id);
|
||||
bool CompleteTask(int task_id);
|
||||
bool UncompleteTask(int task_id);
|
||||
|
||||
@@ -5675,6 +5675,32 @@ bool lua_handin(luabind::adl::object handin_table)
|
||||
return quest_manager.handin(handin_map);
|
||||
}
|
||||
|
||||
luabind::object lua_get_paused_timers(lua_State* L, Mob* m) {
|
||||
auto t = luabind::newtable(L);
|
||||
auto v = quest_manager.GetPausedTimers(m);
|
||||
int i = 1;
|
||||
|
||||
for (const auto& e : v) {
|
||||
t[i] = e;
|
||||
i++;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
luabind::object lua_get_timers(lua_State* L, Mob* m) {
|
||||
auto t = luabind::newtable(L);
|
||||
auto v = quest_manager.GetTimers(m);
|
||||
int i = 1;
|
||||
|
||||
for (const auto& e : v) {
|
||||
t[i] = e;
|
||||
i++;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
#define LuaCreateNPCParse(name, c_type, default_value) do { \
|
||||
cur = table[#name]; \
|
||||
if(luabind::type(cur) != LUA_TNIL) { \
|
||||
@@ -6486,6 +6512,8 @@ luabind::scope lua_register_general() {
|
||||
luabind::def("spawn_grid", &lua_spawn_grid),
|
||||
luabind::def("get_zone", &lua_get_zone),
|
||||
luabind::def("handin", &lua_handin),
|
||||
luabind::def("get_paused_timers", &lua_get_paused_timers),
|
||||
luabind::def("get_timers", &lua_get_timers),
|
||||
/*
|
||||
Cross Zone
|
||||
*/
|
||||
|
||||
+33
-1
@@ -3482,6 +3482,36 @@ void Lua_Mob::BuffFadeSongs()
|
||||
self->BuffFadeSongs();
|
||||
}
|
||||
|
||||
luabind::object Lua_Mob::GetPausedTimers(lua_State* L) {
|
||||
auto t = luabind::newtable(L);
|
||||
if (d_) {
|
||||
auto self = reinterpret_cast<NativeType*>(d_);
|
||||
auto l = quest_manager.GetPausedTimers(self);
|
||||
int i = 1;
|
||||
for (const auto& v : l) {
|
||||
t[i] = v;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
luabind::object Lua_Mob::GetTimers(lua_State* L) {
|
||||
auto t = luabind::newtable(L);
|
||||
if (d_) {
|
||||
auto self = reinterpret_cast<NativeType*>(d_);
|
||||
auto l = quest_manager.GetTimers(self);
|
||||
int i = 1;
|
||||
for (const auto& v : l) {
|
||||
t[i] = v;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
luabind::scope lua_register_mob() {
|
||||
return luabind::class_<Lua_Mob, Lua_Entity>("Mob")
|
||||
.def(luabind::constructor<>())
|
||||
@@ -3822,6 +3852,7 @@ luabind::scope lua_register_mob() {
|
||||
.def("GetOwner", &Lua_Mob::GetOwner)
|
||||
.def("GetOwnerID", &Lua_Mob::GetOwnerID)
|
||||
.def("GetPR", &Lua_Mob::GetPR)
|
||||
.def("GetPausedTimers", &Lua_Mob::GetPausedTimers)
|
||||
.def("GetPet", &Lua_Mob::GetPet)
|
||||
.def("GetPetOrder", (int(Lua_Mob::*)(void))&Lua_Mob::GetPetOrder)
|
||||
.def("GetPhR", &Lua_Mob::GetPhR)
|
||||
@@ -3847,6 +3878,7 @@ luabind::scope lua_register_mob() {
|
||||
.def("GetTarget", &Lua_Mob::GetTarget)
|
||||
.def("GetTexture", &Lua_Mob::GetTexture)
|
||||
.def("GetTimerDurationMS", &Lua_Mob::GetTimerDurationMS)
|
||||
.def("GetTimers", &Lua_Mob::GetTimers)
|
||||
.def("GetUltimateOwner", &Lua_Mob::GetUltimateOwner)
|
||||
.def("GetWIS", &Lua_Mob::GetWIS)
|
||||
.def("GetWalkspeed", &Lua_Mob::GetWalkspeed)
|
||||
@@ -3908,7 +3940,7 @@ luabind::scope lua_register_mob() {
|
||||
.def("IsPausedTimer", &Lua_Mob::IsPausedTimer)
|
||||
.def("IsPet", (bool(Lua_Mob::*)(void))&Lua_Mob::IsPet)
|
||||
.def("IsPetOwnerBot", &Lua_Mob::IsPetOwnerBot)
|
||||
.def("IsPetOwnerClient", &Lua_Mob::IsPetOwnerClient)
|
||||
.def("IsPetOwnerClient", &Lua_Mob::IsPetOwnerClient)
|
||||
.def("IsPetOwnerNPC", &Lua_Mob::IsPetOwnerNPC)
|
||||
.def("IsPetOwnerOfClientBot", &Lua_Mob::IsPetOwnerOfClientBot)
|
||||
.def("IsPureMeleeClass", &Lua_Mob::IsPureMeleeClass)
|
||||
|
||||
+3
-1
@@ -574,7 +574,7 @@ public:
|
||||
bool IsFamiliar();
|
||||
bool IsTargetLockPet();
|
||||
bool IsPetOwnerBot();
|
||||
bool IsPetOwnerClient();
|
||||
bool IsPetOwnerClient();
|
||||
bool IsPetOwnerNPC();
|
||||
bool IsPetOwnerOfClientBot();
|
||||
bool IsDestructibleObject();
|
||||
@@ -612,6 +612,8 @@ public:
|
||||
void BuffFadeDetrimentalByCaster(Lua_Mob caster);
|
||||
void BuffFadeNonPersistDeath();
|
||||
void BuffFadeSongs();
|
||||
luabind::object GetPausedTimers(lua_State* L);
|
||||
luabind::object GetTimers(lua_State* L);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -838,6 +838,36 @@ void Lua_Zone::Signal(int signal_id)
|
||||
self->Signal(signal_id);
|
||||
}
|
||||
|
||||
luabind::object Lua_Zone::GetPausedTimers(lua_State* L) {
|
||||
auto t = luabind::newtable(L);
|
||||
if (d_) {
|
||||
auto self = reinterpret_cast<NativeType*>(d_);
|
||||
auto l = self->GetPausedTimers();
|
||||
int i = 1;
|
||||
for (const auto& v : l) {
|
||||
t[i] = v;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
luabind::object Lua_Zone::GetTimers(lua_State* L) {
|
||||
auto t = luabind::newtable(L);
|
||||
if (d_) {
|
||||
auto self = reinterpret_cast<NativeType*>(d_);
|
||||
auto l = self->GetTimers();
|
||||
int i = 1;
|
||||
for (const auto& v : l) {
|
||||
t[i] = v;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
luabind::scope lua_register_zone() {
|
||||
return luabind::class_<Lua_Zone>("Zones")
|
||||
.def(luabind::constructor<>())
|
||||
@@ -906,6 +936,7 @@ luabind::scope lua_register_zone() {
|
||||
.def("GetMinimumStatus", &Lua_Zone::GetMinimumStatus)
|
||||
.def("GetNote", &Lua_Zone::GetNote)
|
||||
.def("GetNPCMaximumAggroDistance", &Lua_Zone::GetNPCMaximumAggroDistance)
|
||||
.def("GetPausedTimers", &Lua_Zone::GetPausedTimers)
|
||||
.def("GetPEQZone", &Lua_Zone::GetPEQZone)
|
||||
.def("GetRainChance", (int(Lua_Zone::*)(void))&Lua_Zone::GetRainChance)
|
||||
.def("GetRainChance", (int(Lua_Zone::*)(uint8))&Lua_Zone::GetRainChance)
|
||||
@@ -929,6 +960,7 @@ luabind::scope lua_register_zone() {
|
||||
.def("GetTimeZone", &Lua_Zone::GetTimeZone)
|
||||
.def("GetTimerDuration", &Lua_Zone::GetTimerDuration)
|
||||
.def("GetTimerRemainingTime", &Lua_Zone::GetTimerRemainingTime)
|
||||
.def("GetTimers", &Lua_Zone::GetTimers)
|
||||
.def("GetZoneDescription", &Lua_Zone::GetZoneDescription)
|
||||
.def("GetZoneID", &Lua_Zone::GetZoneID)
|
||||
.def("GetZoneType", &Lua_Zone::GetZoneType)
|
||||
|
||||
@@ -158,6 +158,8 @@ public:
|
||||
void StopAllTimers();
|
||||
void Signal(int signal_id);
|
||||
void SendPayload(int payload_id, std::string payload_value);
|
||||
luabind::object GetPausedTimers(lua_State* L);
|
||||
luabind::object GetTimers(lua_State* L);
|
||||
|
||||
// data buckets
|
||||
void SetBucket(const std::string& bucket_name, const std::string& bucket_value);
|
||||
|
||||
@@ -413,11 +413,6 @@ int main(int argc, char **argv)
|
||||
->ReloadContentFlags();
|
||||
|
||||
ZoneEventScheduler::Instance()->SetDatabase(&database)->LoadScheduledEvents();
|
||||
RuleManager::Instance()->SetPostLoadCallback(
|
||||
[&]() {
|
||||
WorldContentService::Instance()->LoadTargetedRulesets();
|
||||
}
|
||||
);
|
||||
|
||||
EQ::SayLinkEngine::LoadCachedSaylinks();
|
||||
|
||||
|
||||
@@ -286,8 +286,8 @@ uint32 Mob::GetHerosForgeModel(uint8 material_slot) const
|
||||
if (augment) {
|
||||
item = augment->GetItem();
|
||||
heros_forge_model = item->HerosForgeModel;
|
||||
} else if (inst->GetOrnamentHeroModel()) {
|
||||
heros_forge_model = inst->GetOrnamentHeroModel();
|
||||
} else if (inst->GetOrnamentHeroModel(material_slot)) {
|
||||
heros_forge_model = inst->GetOrnamentHeroModel(material_slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -421,7 +421,7 @@ void Mob::SendWearChange(uint8 material_slot, Client *one_client)
|
||||
return key;
|
||||
};
|
||||
|
||||
|
||||
|
||||
auto dedupe_key = build_key(*w);
|
||||
auto send_if_changed = [&](Client* client) {
|
||||
auto& last_key = m_last_seen_wearchange[client->GetID()][material_slot];
|
||||
|
||||
@@ -3328,7 +3328,12 @@ bool Perl_Client_KeyRingClear(Client* self)
|
||||
|
||||
void Perl_Client_KeyRingList(Client* self)
|
||||
{
|
||||
self->KeyRingList();
|
||||
self->KeyRingList(self);
|
||||
}
|
||||
|
||||
void Perl_Client_KeyRingList(Client* self, Client* c)
|
||||
{
|
||||
self->KeyRingList(c);
|
||||
}
|
||||
|
||||
bool Perl_Client_KeyRingRemove(Client* self, uint32 item_id)
|
||||
@@ -3675,7 +3680,8 @@ void perl_register_client()
|
||||
package.add("KeyRingAdd", &Perl_Client_KeyRingAdd);
|
||||
package.add("KeyRingCheck", &Perl_Client_KeyRingCheck);
|
||||
package.add("KeyRingClear", &Perl_Client_KeyRingClear);
|
||||
package.add("KeyRingList", &Perl_Client_KeyRingList);
|
||||
package.add("KeyRingList", (void(*)(Client*))&Perl_Client_KeyRingList);
|
||||
package.add("KeyRingList", (void(*)(Client*, Client*))&Perl_Client_KeyRingList);
|
||||
package.add("KeyRingRemove", &Perl_Client_KeyRingRemove);
|
||||
package.add("Kick", &Perl_Client_Kick);
|
||||
package.add("LearnDisciplines", &Perl_Client_LearnDisciplines);
|
||||
|
||||
@@ -3573,6 +3573,30 @@ void Perl_Mob_BuffFadeSongs(Mob* self)
|
||||
self->BuffFadeSongs();
|
||||
}
|
||||
|
||||
perl::array Perl_Mob_GetPausedTimers(Mob* self)
|
||||
{
|
||||
perl::array a;
|
||||
|
||||
const auto& l = quest_manager.GetPausedTimers(self);
|
||||
for (const auto& v : l) {
|
||||
a.push_back(v);
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
perl::array Perl_Mob_GetTimers(Mob* self)
|
||||
{
|
||||
perl::array a;
|
||||
|
||||
const auto& l = quest_manager.GetTimers(self);
|
||||
for (const auto& v : l) {
|
||||
a.push_back(v);
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
void perl_register_mob()
|
||||
{
|
||||
perl::interpreter perl(PERL_GET_THX);
|
||||
@@ -3897,6 +3921,7 @@ void perl_register_mob()
|
||||
package.add("GetOwner", &Perl_Mob_GetOwner);
|
||||
package.add("GetOwnerID", &Perl_Mob_GetOwnerID);
|
||||
package.add("GetPR", &Perl_Mob_GetPR);
|
||||
package.add("GetPausedTimers", &Perl_Mob_GetPausedTimers);
|
||||
package.add("GetPet", &Perl_Mob_GetPet);
|
||||
package.add("GetPetID", &Perl_Mob_GetPetID);
|
||||
package.add("GetPetOrder", &Perl_Mob_GetPetOrder);
|
||||
@@ -3927,6 +3952,7 @@ void perl_register_mob()
|
||||
package.add("GetTarget", &Perl_Mob_GetTarget);
|
||||
package.add("GetTexture", &Perl_Mob_GetTexture);
|
||||
package.add("GetTimerDurationMS", &Perl_Mob_GetTimerDurationMS);
|
||||
package.add("GetTimers", &Perl_Mob_GetTimers);
|
||||
package.add("GetUltimateOwner", &Perl_Mob_GetUltimateOwner);
|
||||
package.add("GetWIS", &Perl_Mob_GetWIS);
|
||||
package.add("GetWalkspeed", &Perl_Mob_GetWalkspeed);
|
||||
|
||||
@@ -653,6 +653,40 @@ void Perl_Zone_Signal(Zone* self, int signal_id)
|
||||
self->Signal(signal_id);
|
||||
}
|
||||
|
||||
perl::array Perl_Zone_GetPausedTimers(Zone* self)
|
||||
{
|
||||
perl::array a;
|
||||
|
||||
const auto& l = self->GetPausedTimers();
|
||||
|
||||
if (!l.empty()) {
|
||||
a.reserve(l.size());
|
||||
|
||||
for (const auto& v : l) {
|
||||
a.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
perl::array Perl_Zone_GetTimers(Zone* self)
|
||||
{
|
||||
perl::array a;
|
||||
|
||||
const auto& l = self->GetTimers();
|
||||
|
||||
if (!l.empty()) {
|
||||
a.reserve(l.size());
|
||||
|
||||
for (const auto& v : l) {
|
||||
a.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
void perl_register_zone()
|
||||
{
|
||||
perl::interpreter perl(PERL_GET_THX);
|
||||
@@ -723,6 +757,7 @@ void perl_register_zone()
|
||||
package.add("GetMinimumStatus", &Perl_Zone_GetMinimumStatus);
|
||||
package.add("GetNote", &Perl_Zone_GetNote);
|
||||
package.add("GetNPCMaximumAggroDistance", &Perl_Zone_GetNPCMaximumAggroDistance);
|
||||
package.add("GetPausedTimers", &Perl_Zone_GetPausedTimers);
|
||||
package.add("GetPEQZone", &Perl_Zone_GetPEQZone);
|
||||
package.add("GetRainChance", (int(*)(Zone*))&Perl_Zone_GetRainChance);
|
||||
package.add("GetRainChance", (int(*)(Zone*, uint8))&Perl_Zone_GetRainChance);
|
||||
@@ -746,6 +781,7 @@ void perl_register_zone()
|
||||
package.add("GetTimeZone", &Perl_Zone_GetTimeZone);
|
||||
package.add("GetTimerDuration", &Perl_Zone_GetTimerDuration);
|
||||
package.add("GetTimerRemainingTime", &Perl_Zone_GetTimerRemainingTime);
|
||||
package.add("GetTimers", &Perl_Zone_GetTimers);
|
||||
package.add("GetZoneDescription", &Perl_Zone_GetZoneDescription);
|
||||
package.add("GetZoneID", &Perl_Zone_GetZoneID);
|
||||
package.add("GetZoneType", &Perl_Zone_GetZoneType);
|
||||
|
||||
@@ -4667,3 +4667,33 @@ bool QuestManager::handin(std::map<std::string, uint32> required) {
|
||||
|
||||
return owner->CastToNPC()->CheckHandin(initiator, {}, required, {});
|
||||
}
|
||||
|
||||
std::vector<std::string> QuestManager::GetPausedTimers(Mob* m)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
if (m && !PTimerList.empty()) {
|
||||
for (auto e = PTimerList.begin(); e != PTimerList.end(); e++) {
|
||||
if (e->owner == m) {
|
||||
v.emplace_back(e->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
std::vector<std::string> QuestManager::GetTimers(Mob* m)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
if (m && !QTimerList.empty()) {
|
||||
for (auto e = QTimerList.begin(); e != QTimerList.end(); e++) {
|
||||
if (e->mob == m) {
|
||||
v.emplace_back(e->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -364,6 +364,8 @@ public:
|
||||
bool SetAutoLoginCharacterNameByAccountID(uint32 account_id, const std::string& character_name);
|
||||
void SpawnCircle(uint32 npc_id, glm::vec4 position, float radius, uint32 points);
|
||||
void SpawnGrid(uint32 npc_id, glm::vec4 position, float spacing, uint32 spawn_count);
|
||||
std::vector<std::string> GetPausedTimers(Mob* m);
|
||||
std::vector<std::string> GetTimers(Mob* m);
|
||||
|
||||
Bot *GetBot() const;
|
||||
Client *GetInitiator() const;
|
||||
|
||||
+27
-12
@@ -1151,7 +1151,12 @@ bool Zone::Init(bool is_static) {
|
||||
);
|
||||
} // if that fails, try the file name, then load defaults
|
||||
|
||||
LoadRules();
|
||||
if (RuleManager::Instance()->GetActiveRulesetID() != default_ruleset) {
|
||||
std::string r_name = RuleSetsRepository::GetRuleSetName(database, default_ruleset);
|
||||
if (r_name.size() > 0) {
|
||||
RuleManager::Instance()->LoadRules(&database, r_name, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!map_name) {
|
||||
LogError("No map name found for zone [{}]", GetShortName());
|
||||
@@ -3554,20 +3559,30 @@ void Zone::SendPayload(int payload_id, std::string payload_value)
|
||||
}
|
||||
}
|
||||
|
||||
void Zone::LoadRules()
|
||||
std::vector<std::string> Zone::GetPausedTimers()
|
||||
{
|
||||
if (GetZoneID() > 0) {
|
||||
WorldContentService::Instance()->SetZoneId(GetZoneID());
|
||||
WorldContentService::Instance()->SetInstanceVersion(GetInstanceVersion());
|
||||
}
|
||||
const auto rm = RuleManager::Instance();
|
||||
rm->LoadRules(&database, rm->GetActiveRuleset(), true);
|
||||
if (rm->GetActiveRulesetID() != default_ruleset) {
|
||||
std::string r_name = RuleSetsRepository::GetRuleSetName(database, default_ruleset);
|
||||
if (r_name.size() > 0) {
|
||||
rm->LoadRules(&database, r_name, false);
|
||||
std::vector<std::string> v;
|
||||
|
||||
if (!paused_zone_timers.empty()) {
|
||||
for (auto e = paused_zone_timers.begin(); e != paused_zone_timers.end(); e++) {
|
||||
v.emplace_back(e->name);
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
std::vector<std::string> Zone::GetTimers()
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
if (!zone_timers.empty()) {
|
||||
for (auto e = zone_timers.begin(); e != zone_timers.end(); e++) {
|
||||
v.emplace_back(e->name);
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
#include "zone_loot.cpp"
|
||||
|
||||
+2
-1
@@ -485,7 +485,6 @@ public:
|
||||
void SaveZoneState();
|
||||
static void ClearZoneState(uint32 zone_id, uint32 instance_id);
|
||||
void ReloadMaps();
|
||||
void LoadRules();
|
||||
|
||||
void Signal(int signal_id);
|
||||
void SendPayload(int payload_id, std::string payload_value);
|
||||
@@ -504,6 +503,8 @@ public:
|
||||
void SetTimer(std::string name, uint32 duration);
|
||||
void StopTimer(std::string name);
|
||||
void StopAllTimers();
|
||||
std::vector<std::string> GetPausedTimers();
|
||||
std::vector<std::string> GetTimers();
|
||||
|
||||
private:
|
||||
bool allow_mercs;
|
||||
|
||||
Reference in New Issue
Block a user