mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-08-05 10:14:06 +00:00
format codebase
This commit is contained in:
@@ -4,25 +4,24 @@
|
||||
#include "BrickDatabase.h"
|
||||
#include "Game.h"
|
||||
|
||||
std::vector<Brick> BrickDatabase::emptyCache {};
|
||||
std::vector<Brick> BrickDatabase::emptyCache{};
|
||||
BrickDatabase* BrickDatabase::m_Address = nullptr;
|
||||
|
||||
BrickDatabase::BrickDatabase() = default;
|
||||
BrickDatabase::~BrickDatabase() = default;
|
||||
|
||||
std::vector<Brick>& BrickDatabase::GetBricks(const std::string& lxfmlPath)
|
||||
{
|
||||
const auto cached = m_Cache.find(lxfmlPath);
|
||||
std::vector<Brick>& BrickDatabase::GetBricks(const std::string& lxfmlPath) {
|
||||
const auto cached = m_Cache.find(lxfmlPath);
|
||||
|
||||
if (cached != m_Cache.end()) {
|
||||
return cached->second;
|
||||
}
|
||||
if (cached != m_Cache.end()) {
|
||||
return cached->second;
|
||||
}
|
||||
|
||||
std::ifstream file(lxfmlPath);
|
||||
std::ifstream file(lxfmlPath);
|
||||
if (!file.good()) {
|
||||
return emptyCache;
|
||||
}
|
||||
|
||||
|
||||
std::stringstream data;
|
||||
data << file.rdbuf();
|
||||
if (data.str().empty()) {
|
||||
@@ -40,53 +39,53 @@ std::vector<Brick>& BrickDatabase::GetBricks(const std::string& lxfmlPath)
|
||||
auto* lxfml = doc->FirstChildElement("LXFML");
|
||||
auto* bricks = lxfml->FirstChildElement("Bricks");
|
||||
std::string searchTerm = "Brick";
|
||||
|
||||
|
||||
if (!bricks) {
|
||||
searchTerm = "Part";
|
||||
bricks = lxfml->FirstChildElement("Scene")->FirstChildElement("Model")->FirstChildElement("Group");
|
||||
|
||||
|
||||
if (!bricks) {
|
||||
return emptyCache;
|
||||
return emptyCache;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
auto* currentBrick = bricks->FirstChildElement(searchTerm.c_str());
|
||||
while (currentBrick != nullptr) {
|
||||
|
||||
auto* part = currentBrick->FirstChildElement("Part");
|
||||
auto* part = currentBrick->FirstChildElement("Part");
|
||||
if (part == nullptr) part = currentBrick;
|
||||
|
||||
if (part->Attribute("designID") != nullptr) {
|
||||
Brick brick { static_cast<uint32_t>(part->IntAttribute("designID")) };
|
||||
Brick brick{ static_cast<uint32_t>(part->IntAttribute("designID")) };
|
||||
|
||||
// Depends on the file, some don't specify a list but just a single material
|
||||
const auto* materialList = part->Attribute("materials");
|
||||
const auto* materialID = part->Attribute("materialID");
|
||||
// Depends on the file, some don't specify a list but just a single material
|
||||
const auto* materialList = part->Attribute("materials");
|
||||
const auto* materialID = part->Attribute("materialID");
|
||||
|
||||
if (materialList != nullptr) {
|
||||
std::string materialString(materialList);
|
||||
const auto materials = GeneralUtils::SplitString(materialString, ',');
|
||||
if (materialList != nullptr) {
|
||||
std::string materialString(materialList);
|
||||
const auto materials = GeneralUtils::SplitString(materialString, ',');
|
||||
|
||||
if (!materials.empty()) {
|
||||
brick.materialID = std::stoi(materials[0]);
|
||||
} else {
|
||||
brick.materialID = 0;
|
||||
}
|
||||
} else if (materialID != nullptr) {
|
||||
brick.materialID = std::stoi(materialID);
|
||||
} else {
|
||||
brick.materialID = 0; // This is bad, makes it so the minigame can't be played
|
||||
}
|
||||
if (!materials.empty()) {
|
||||
brick.materialID = std::stoi(materials[0]);
|
||||
} else {
|
||||
brick.materialID = 0;
|
||||
}
|
||||
} else if (materialID != nullptr) {
|
||||
brick.materialID = std::stoi(materialID);
|
||||
} else {
|
||||
brick.materialID = 0; // This is bad, makes it so the minigame can't be played
|
||||
}
|
||||
|
||||
parts.push_back(brick);
|
||||
}
|
||||
|
||||
|
||||
currentBrick = currentBrick->NextSiblingElement(searchTerm.c_str());
|
||||
}
|
||||
|
||||
m_Cache[lxfmlPath] = parts;
|
||||
m_Cache[lxfmlPath] = parts;
|
||||
|
||||
delete doc;
|
||||
|
||||
return m_Cache[lxfmlPath];
|
||||
return m_Cache[lxfmlPath];
|
||||
}
|
||||
|
@@ -4,28 +4,26 @@
|
||||
class BrickDatabase
|
||||
{
|
||||
public:
|
||||
static BrickDatabase* Instance()
|
||||
{
|
||||
if (m_Address == nullptr)
|
||||
{
|
||||
m_Address = new BrickDatabase();
|
||||
}
|
||||
static BrickDatabase* Instance() {
|
||||
if (m_Address == nullptr) {
|
||||
m_Address = new BrickDatabase();
|
||||
}
|
||||
|
||||
return m_Address;
|
||||
}
|
||||
return m_Address;
|
||||
}
|
||||
|
||||
std::vector<Brick>& GetBricks(const std::string& lxfmlPath);
|
||||
std::vector<Brick>& GetBricks(const std::string& lxfmlPath);
|
||||
|
||||
explicit BrickDatabase();
|
||||
explicit BrickDatabase();
|
||||
|
||||
~BrickDatabase();
|
||||
|
||||
~BrickDatabase();
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, std::vector<Brick>> m_Cache;
|
||||
std::unordered_map<std::string, std::vector<Brick>> m_Cache;
|
||||
|
||||
static std::vector<Brick> emptyCache;
|
||||
static std::vector<Brick> emptyCache;
|
||||
|
||||
static BrickDatabase* m_Address; //For singleton method
|
||||
static BrickDatabase* m_Address; //For singleton method
|
||||
|
||||
/* data */
|
||||
/* data */
|
||||
};
|
||||
|
@@ -1,27 +1,27 @@
|
||||
#include "GUID.h"
|
||||
|
||||
GUID::GUID(const std::string &guid) {
|
||||
sscanf(guid.c_str(),
|
||||
"{%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx}",
|
||||
&this->data1, &this->data2, &this->data3,
|
||||
&this->data4[0], &this->data4[1], &this->data4[2], &this->data4[3],
|
||||
&this->data4[4], &this->data4[5], &this->data4[6], &this->data4[7]);
|
||||
GUID::GUID(const std::string& guid) {
|
||||
sscanf(guid.c_str(),
|
||||
"{%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx}",
|
||||
&this->data1, &this->data2, &this->data3,
|
||||
&this->data4[0], &this->data4[1], &this->data4[2], &this->data4[3],
|
||||
&this->data4[4], &this->data4[5], &this->data4[6], &this->data4[7]);
|
||||
}
|
||||
|
||||
uint32_t GUID::GetData1() const {
|
||||
return data1;
|
||||
return data1;
|
||||
}
|
||||
|
||||
uint16_t GUID::GetData2() const {
|
||||
return data2;
|
||||
return data2;
|
||||
}
|
||||
|
||||
uint16_t GUID::GetData3() const {
|
||||
return data3;
|
||||
return data3;
|
||||
}
|
||||
|
||||
std::array<uint8_t, 8> GUID::GetData4() const {
|
||||
return data4;
|
||||
return data4;
|
||||
}
|
||||
|
||||
GUID::GUID() = default;
|
||||
|
@@ -5,15 +5,15 @@
|
||||
|
||||
class GUID {
|
||||
public:
|
||||
explicit GUID();
|
||||
explicit GUID(const std::string& guid);
|
||||
uint32_t GetData1() const;
|
||||
uint16_t GetData2() const;
|
||||
uint16_t GetData3() const;
|
||||
std::array<uint8_t, 8> GetData4() const;
|
||||
explicit GUID();
|
||||
explicit GUID(const std::string& guid);
|
||||
uint32_t GetData1() const;
|
||||
uint16_t GetData2() const;
|
||||
uint16_t GetData3() const;
|
||||
std::array<uint8_t, 8> GetData4() const;
|
||||
private:
|
||||
uint32_t data1 = 0;
|
||||
uint16_t data2 = 0;
|
||||
uint16_t data3 = 0;
|
||||
std::array<uint8_t, 8> data4 = { 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
uint32_t data1 = 0;
|
||||
uint16_t data2 = 0;
|
||||
uint16_t data3 = 0;
|
||||
std::array<uint8_t, 8> data4 = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
};
|
||||
|
@@ -1,8 +1,8 @@
|
||||
#include "GameConfig.h"
|
||||
#include <sstream>
|
||||
|
||||
std::map<std::string, std::string> GameConfig::m_Config {};
|
||||
std::string GameConfig::m_EmptyString {};
|
||||
std::map<std::string, std::string> GameConfig::m_Config{};
|
||||
std::string GameConfig::m_EmptyString{};
|
||||
|
||||
void GameConfig::Load(const std::string& filepath) {
|
||||
m_EmptyString = "";
|
||||
@@ -15,7 +15,7 @@ void GameConfig::Load(const std::string& filepath) {
|
||||
if (line[0] != '#') ProcessLine(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& GameConfig::GetValue(const std::string& key) {
|
||||
const auto& it = m_Config.find(key);
|
||||
@@ -37,14 +37,14 @@ void GameConfig::ProcessLine(const std::string& line) {
|
||||
std::vector<std::string> seglist;
|
||||
|
||||
while (std::getline(ss, segment, '=')) {
|
||||
seglist.push_back(segment);
|
||||
seglist.push_back(segment);
|
||||
}
|
||||
|
||||
if (seglist.size() != 2) return;
|
||||
|
||||
//Make sure that on Linux, we remove special characters:
|
||||
if (!seglist[1].empty() && seglist[1][seglist[1].size() - 1] == '\r')
|
||||
seglist[1].erase(seglist[1].size() - 1);
|
||||
seglist[1].erase(seglist[1].size() - 1);
|
||||
|
||||
m_Config.insert_or_assign(seglist[0], seglist[1]);
|
||||
}
|
||||
}
|
||||
|
@@ -35,4 +35,4 @@ private:
|
||||
|
||||
static std::map<std::string, std::string> m_Config;
|
||||
static std::string m_EmptyString;
|
||||
};
|
||||
};
|
||||
|
@@ -15,375 +15,375 @@
|
||||
#include "MissionComponent.h"
|
||||
|
||||
LootGenerator::LootGenerator() {
|
||||
CDLootTableTable* lootTableTable = CDClientManager::Instance()->GetTable<CDLootTableTable>("LootTable");
|
||||
CDComponentsRegistryTable* componentsRegistryTable = CDClientManager::Instance()->GetTable<CDComponentsRegistryTable>("ComponentsRegistry");
|
||||
CDItemComponentTable* itemComponentTable = CDClientManager::Instance()->GetTable<CDItemComponentTable>("ItemComponent");
|
||||
CDLootMatrixTable* lootMatrixTable = CDClientManager::Instance()->GetTable<CDLootMatrixTable>("LootMatrix");
|
||||
CDRarityTableTable* rarityTableTable = CDClientManager::Instance()->GetTable<CDRarityTableTable>("RarityTable");
|
||||
CDLootTableTable* lootTableTable = CDClientManager::Instance()->GetTable<CDLootTableTable>("LootTable");
|
||||
CDComponentsRegistryTable* componentsRegistryTable = CDClientManager::Instance()->GetTable<CDComponentsRegistryTable>("ComponentsRegistry");
|
||||
CDItemComponentTable* itemComponentTable = CDClientManager::Instance()->GetTable<CDItemComponentTable>("ItemComponent");
|
||||
CDLootMatrixTable* lootMatrixTable = CDClientManager::Instance()->GetTable<CDLootMatrixTable>("LootMatrix");
|
||||
CDRarityTableTable* rarityTableTable = CDClientManager::Instance()->GetTable<CDRarityTableTable>("RarityTable");
|
||||
|
||||
// ==============================
|
||||
// Cache Item Rarities
|
||||
// ==============================
|
||||
// ==============================
|
||||
// Cache Item Rarities
|
||||
// ==============================
|
||||
|
||||
std::vector<uint32_t> uniqueItems;
|
||||
std::vector<uint32_t> uniqueItems;
|
||||
|
||||
for (const CDLootTable& loot : lootTableTable->GetEntries()) {
|
||||
uniqueItems.push_back(loot.itemid);
|
||||
}
|
||||
for (const CDLootTable& loot : lootTableTable->GetEntries()) {
|
||||
uniqueItems.push_back(loot.itemid);
|
||||
}
|
||||
|
||||
// filter out duplicates
|
||||
std::sort(uniqueItems.begin(), uniqueItems.end());
|
||||
uniqueItems.erase(std::unique(uniqueItems.begin(), uniqueItems.end()), uniqueItems.end());
|
||||
// filter out duplicates
|
||||
std::sort(uniqueItems.begin(), uniqueItems.end());
|
||||
uniqueItems.erase(std::unique(uniqueItems.begin(), uniqueItems.end()), uniqueItems.end());
|
||||
|
||||
for (const uint32_t itemID : uniqueItems) {
|
||||
uint32_t itemComponentID = componentsRegistryTable->GetByIDAndType(itemID, COMPONENT_TYPE_ITEM);
|
||||
const CDItemComponent& item = itemComponentTable->GetItemComponentByID(itemComponentID);
|
||||
for (const uint32_t itemID : uniqueItems) {
|
||||
uint32_t itemComponentID = componentsRegistryTable->GetByIDAndType(itemID, COMPONENT_TYPE_ITEM);
|
||||
const CDItemComponent& item = itemComponentTable->GetItemComponentByID(itemComponentID);
|
||||
|
||||
m_ItemRarities.insert({itemID, item.rarity});
|
||||
}
|
||||
m_ItemRarities.insert({ itemID, item.rarity });
|
||||
}
|
||||
|
||||
// ==============================
|
||||
// Cache Rarity Tables
|
||||
// ==============================
|
||||
// ==============================
|
||||
// Cache Rarity Tables
|
||||
// ==============================
|
||||
|
||||
std::vector<uint32_t> uniqueRarityIndices;
|
||||
std::vector<uint32_t> uniqueRarityIndices;
|
||||
|
||||
for (const CDRarityTable& rarity : rarityTableTable->GetEntries()) {
|
||||
uniqueRarityIndices.push_back(rarity.RarityTableIndex);
|
||||
}
|
||||
for (const CDRarityTable& rarity : rarityTableTable->GetEntries()) {
|
||||
uniqueRarityIndices.push_back(rarity.RarityTableIndex);
|
||||
}
|
||||
|
||||
// filter out duplicates
|
||||
std::sort(uniqueRarityIndices.begin(), uniqueRarityIndices.end());
|
||||
uniqueRarityIndices.erase(std::unique(uniqueRarityIndices.begin(), uniqueRarityIndices.end()), uniqueRarityIndices.end());
|
||||
// filter out duplicates
|
||||
std::sort(uniqueRarityIndices.begin(), uniqueRarityIndices.end());
|
||||
uniqueRarityIndices.erase(std::unique(uniqueRarityIndices.begin(), uniqueRarityIndices.end()), uniqueRarityIndices.end());
|
||||
|
||||
for (const uint32_t index : uniqueRarityIndices) {
|
||||
std::vector<CDRarityTable> table = rarityTableTable->Query([index](const CDRarityTable& entry) { return entry.RarityTableIndex == index; });
|
||||
for (const uint32_t index : uniqueRarityIndices) {
|
||||
std::vector<CDRarityTable> table = rarityTableTable->Query([index](const CDRarityTable& entry) { return entry.RarityTableIndex == index; });
|
||||
|
||||
RarityTable rarityTable;
|
||||
RarityTable rarityTable;
|
||||
|
||||
for (const CDRarityTable& entry : table) {
|
||||
RarityTableEntry rarity{entry.rarity, entry.randmax};
|
||||
rarityTable.push_back(rarity);
|
||||
}
|
||||
for (const CDRarityTable& entry : table) {
|
||||
RarityTableEntry rarity{ entry.rarity, entry.randmax };
|
||||
rarityTable.push_back(rarity);
|
||||
}
|
||||
|
||||
// sort in descending order based on randMax
|
||||
std::sort(rarityTable.begin(), rarityTable.end(), [](const RarityTableEntry& x, const RarityTableEntry& y) { return x.randMax > y.randMax; });
|
||||
// sort in descending order based on randMax
|
||||
std::sort(rarityTable.begin(), rarityTable.end(), [](const RarityTableEntry& x, const RarityTableEntry& y) { return x.randMax > y.randMax; });
|
||||
|
||||
m_RarityTables.insert({index, rarityTable});
|
||||
}
|
||||
m_RarityTables.insert({ index, rarityTable });
|
||||
}
|
||||
|
||||
// ==============================
|
||||
// Cache Loot Matrices
|
||||
// ==============================
|
||||
// ==============================
|
||||
// Cache Loot Matrices
|
||||
// ==============================
|
||||
|
||||
std::vector<uint32_t> uniqueMatrixIndices;
|
||||
std::vector<uint32_t> uniqueMatrixIndices;
|
||||
|
||||
for (const CDLootMatrix& matrix : lootMatrixTable->GetEntries()) {
|
||||
uniqueMatrixIndices.push_back(matrix.LootMatrixIndex);
|
||||
}
|
||||
for (const CDLootMatrix& matrix : lootMatrixTable->GetEntries()) {
|
||||
uniqueMatrixIndices.push_back(matrix.LootMatrixIndex);
|
||||
}
|
||||
|
||||
// filter out duplicates
|
||||
std::sort(uniqueMatrixIndices.begin(), uniqueMatrixIndices.end());
|
||||
uniqueMatrixIndices.erase(std::unique(uniqueMatrixIndices.begin(), uniqueMatrixIndices.end()), uniqueMatrixIndices.end());
|
||||
// filter out duplicates
|
||||
std::sort(uniqueMatrixIndices.begin(), uniqueMatrixIndices.end());
|
||||
uniqueMatrixIndices.erase(std::unique(uniqueMatrixIndices.begin(), uniqueMatrixIndices.end()), uniqueMatrixIndices.end());
|
||||
|
||||
for (const uint32_t index : uniqueMatrixIndices) {
|
||||
std::vector<CDLootMatrix> matrix = lootMatrixTable->Query([index](const CDLootMatrix& entry) { return entry.LootMatrixIndex == index; });
|
||||
for (const uint32_t index : uniqueMatrixIndices) {
|
||||
std::vector<CDLootMatrix> matrix = lootMatrixTable->Query([index](const CDLootMatrix& entry) { return entry.LootMatrixIndex == index; });
|
||||
|
||||
LootMatrix lootMatrix;
|
||||
LootMatrix lootMatrix;
|
||||
|
||||
for (const CDLootMatrix& entry : matrix) {
|
||||
LootMatrixEntry matrixEntry{entry.LootTableIndex, entry.RarityTableIndex, entry.percent, entry.minToDrop, entry.maxToDrop};
|
||||
lootMatrix.push_back(matrixEntry);
|
||||
}
|
||||
for (const CDLootMatrix& entry : matrix) {
|
||||
LootMatrixEntry matrixEntry{ entry.LootTableIndex, entry.RarityTableIndex, entry.percent, entry.minToDrop, entry.maxToDrop };
|
||||
lootMatrix.push_back(matrixEntry);
|
||||
}
|
||||
|
||||
m_LootMatrices.insert({index, lootMatrix});
|
||||
}
|
||||
m_LootMatrices.insert({ index, lootMatrix });
|
||||
}
|
||||
|
||||
// ==============================
|
||||
// Cache Loot Tables
|
||||
// ==============================
|
||||
// ==============================
|
||||
// Cache Loot Tables
|
||||
// ==============================
|
||||
|
||||
std::vector<uint32_t> uniqueTableIndices;
|
||||
std::vector<uint32_t> uniqueTableIndices;
|
||||
|
||||
for (const CDLootTable& entry : lootTableTable->GetEntries()) {
|
||||
uniqueTableIndices.push_back(entry.LootTableIndex);
|
||||
}
|
||||
for (const CDLootTable& entry : lootTableTable->GetEntries()) {
|
||||
uniqueTableIndices.push_back(entry.LootTableIndex);
|
||||
}
|
||||
|
||||
// filter out duplicates
|
||||
std::sort(uniqueTableIndices.begin(), uniqueTableIndices.end());
|
||||
uniqueTableIndices.erase(std::unique(uniqueTableIndices.begin(), uniqueTableIndices.end()), uniqueTableIndices.end());
|
||||
// filter out duplicates
|
||||
std::sort(uniqueTableIndices.begin(), uniqueTableIndices.end());
|
||||
uniqueTableIndices.erase(std::unique(uniqueTableIndices.begin(), uniqueTableIndices.end()), uniqueTableIndices.end());
|
||||
|
||||
for (const uint32_t index : uniqueTableIndices) {
|
||||
std::vector<CDLootTable> entries = lootTableTable->Query([index](const CDLootTable& entry) { return entry.LootTableIndex == index; });
|
||||
for (const uint32_t index : uniqueTableIndices) {
|
||||
std::vector<CDLootTable> entries = lootTableTable->Query([index](const CDLootTable& entry) { return entry.LootTableIndex == index; });
|
||||
|
||||
LootTable lootTable;
|
||||
LootTable lootTable;
|
||||
|
||||
for (const CDLootTable& entry : entries) {
|
||||
LootTableEntry tableEntry{(LOT)entry.itemid, entry.MissionDrop};
|
||||
lootTable.push_back(tableEntry);
|
||||
}
|
||||
for (const CDLootTable& entry : entries) {
|
||||
LootTableEntry tableEntry{ (LOT)entry.itemid, entry.MissionDrop };
|
||||
lootTable.push_back(tableEntry);
|
||||
}
|
||||
|
||||
// sort by item rarity descending
|
||||
std::sort(lootTable.begin(), lootTable.end(), [&](const LootTableEntry& x, const LootTableEntry& y) {
|
||||
return m_ItemRarities[x.itemID] > m_ItemRarities[y.itemID];
|
||||
});
|
||||
// sort by item rarity descending
|
||||
std::sort(lootTable.begin(), lootTable.end(), [&](const LootTableEntry& x, const LootTableEntry& y) {
|
||||
return m_ItemRarities[x.itemID] > m_ItemRarities[y.itemID];
|
||||
});
|
||||
|
||||
m_LootTables.insert({index, lootTable});
|
||||
}
|
||||
m_LootTables.insert({ index, lootTable });
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_map<LOT, int32_t> LootGenerator::RollLootMatrix(Entity* player, uint32_t matrixIndex) {
|
||||
auto* missionComponent = player->GetComponent<MissionComponent>();
|
||||
auto* missionComponent = player->GetComponent<MissionComponent>();
|
||||
|
||||
std::unordered_map<LOT, int32_t> drops;
|
||||
std::unordered_map<LOT, int32_t> drops;
|
||||
|
||||
if (missionComponent == nullptr) {
|
||||
return drops;
|
||||
}
|
||||
if (missionComponent == nullptr) {
|
||||
return drops;
|
||||
}
|
||||
|
||||
const LootMatrix& matrix = m_LootMatrices[matrixIndex];
|
||||
const LootMatrix& matrix = m_LootMatrices[matrixIndex];
|
||||
|
||||
for (const LootMatrixEntry& entry : matrix) {
|
||||
if (GeneralUtils::GenerateRandomNumber<float>(0, 1) < entry.percent) {
|
||||
const LootTable& lootTable = m_LootTables[entry.lootTableIndex];
|
||||
const RarityTable& rarityTable = m_RarityTables[entry.rarityTableIndex];
|
||||
for (const LootMatrixEntry& entry : matrix) {
|
||||
if (GeneralUtils::GenerateRandomNumber<float>(0, 1) < entry.percent) {
|
||||
const LootTable& lootTable = m_LootTables[entry.lootTableIndex];
|
||||
const RarityTable& rarityTable = m_RarityTables[entry.rarityTableIndex];
|
||||
|
||||
uint32_t dropCount = GeneralUtils::GenerateRandomNumber<uint32_t>(entry.minDrop, entry.maxDrop);
|
||||
for (uint32_t i = 0; i < dropCount; ++i) {
|
||||
uint32_t maxRarity = 1;
|
||||
uint32_t dropCount = GeneralUtils::GenerateRandomNumber<uint32_t>(entry.minDrop, entry.maxDrop);
|
||||
for (uint32_t i = 0; i < dropCount; ++i) {
|
||||
uint32_t maxRarity = 1;
|
||||
|
||||
float rarityRoll = GeneralUtils::GenerateRandomNumber<float>(0, 1);
|
||||
float rarityRoll = GeneralUtils::GenerateRandomNumber<float>(0, 1);
|
||||
|
||||
for (const RarityTableEntry& rarity : rarityTable) {
|
||||
if (rarity.randMax >= rarityRoll) {
|
||||
maxRarity = rarity.rarity;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (const RarityTableEntry& rarity : rarityTable) {
|
||||
if (rarity.randMax >= rarityRoll) {
|
||||
maxRarity = rarity.rarity;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool rarityFound = false;
|
||||
std::vector<LootTableEntry> possibleDrops;
|
||||
bool rarityFound = false;
|
||||
std::vector<LootTableEntry> possibleDrops;
|
||||
|
||||
for (const LootTableEntry& loot : lootTable) {
|
||||
uint32_t rarity = m_ItemRarities[loot.itemID];
|
||||
for (const LootTableEntry& loot : lootTable) {
|
||||
uint32_t rarity = m_ItemRarities[loot.itemID];
|
||||
|
||||
if (rarity == maxRarity) {
|
||||
possibleDrops.push_back(loot);
|
||||
rarityFound = true;
|
||||
} else if (rarity < maxRarity && !rarityFound) {
|
||||
possibleDrops.push_back(loot);
|
||||
maxRarity = rarity;
|
||||
}
|
||||
}
|
||||
if (rarity == maxRarity) {
|
||||
possibleDrops.push_back(loot);
|
||||
rarityFound = true;
|
||||
} else if (rarity < maxRarity && !rarityFound) {
|
||||
possibleDrops.push_back(loot);
|
||||
maxRarity = rarity;
|
||||
}
|
||||
}
|
||||
|
||||
if (possibleDrops.size() > 0) {
|
||||
LootTableEntry drop = possibleDrops[GeneralUtils::GenerateRandomNumber<uint32_t>(0, possibleDrops.size() - 1)];
|
||||
if (possibleDrops.size() > 0) {
|
||||
LootTableEntry drop = possibleDrops[GeneralUtils::GenerateRandomNumber<uint32_t>(0, possibleDrops.size() - 1)];
|
||||
|
||||
// filter out uneeded mission items
|
||||
if (drop.isMissionDrop && !missionComponent->RequiresItem(drop.itemID))
|
||||
continue;
|
||||
// filter out uneeded mission items
|
||||
if (drop.isMissionDrop && !missionComponent->RequiresItem(drop.itemID))
|
||||
continue;
|
||||
|
||||
// convert faction token proxy
|
||||
if (drop.itemID == 13763) {
|
||||
if (missionComponent->GetMissionState(545) == MissionState::MISSION_STATE_COMPLETE)
|
||||
drop.itemID = 8318; // "Assembly Token"
|
||||
else if (missionComponent->GetMissionState(556) == MissionState::MISSION_STATE_COMPLETE)
|
||||
drop.itemID = 8321; // "Venture League Token"
|
||||
else if (missionComponent->GetMissionState(567) == MissionState::MISSION_STATE_COMPLETE)
|
||||
drop.itemID = 8319; // "Sentinels Token"
|
||||
else if (missionComponent->GetMissionState(578) == MissionState::MISSION_STATE_COMPLETE)
|
||||
drop.itemID = 8320; // "Paradox Token"
|
||||
}
|
||||
// convert faction token proxy
|
||||
if (drop.itemID == 13763) {
|
||||
if (missionComponent->GetMissionState(545) == MissionState::MISSION_STATE_COMPLETE)
|
||||
drop.itemID = 8318; // "Assembly Token"
|
||||
else if (missionComponent->GetMissionState(556) == MissionState::MISSION_STATE_COMPLETE)
|
||||
drop.itemID = 8321; // "Venture League Token"
|
||||
else if (missionComponent->GetMissionState(567) == MissionState::MISSION_STATE_COMPLETE)
|
||||
drop.itemID = 8319; // "Sentinels Token"
|
||||
else if (missionComponent->GetMissionState(578) == MissionState::MISSION_STATE_COMPLETE)
|
||||
drop.itemID = 8320; // "Paradox Token"
|
||||
}
|
||||
|
||||
if (drop.itemID == 13763) {
|
||||
continue;
|
||||
} // check if we aren't in faction
|
||||
if (drop.itemID == 13763) {
|
||||
continue;
|
||||
} // check if we aren't in faction
|
||||
|
||||
if (drops.find(drop.itemID) == drops.end()) {
|
||||
drops.insert({drop.itemID, 1});
|
||||
} else {
|
||||
++drops[drop.itemID];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (drops.find(drop.itemID) == drops.end()) {
|
||||
drops.insert({ drop.itemID, 1 });
|
||||
} else {
|
||||
++drops[drop.itemID];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return drops;
|
||||
return drops;
|
||||
}
|
||||
|
||||
std::unordered_map<LOT, int32_t> LootGenerator::RollLootMatrix(uint32_t matrixIndex) {
|
||||
std::unordered_map<LOT, int32_t> drops;
|
||||
std::unordered_map<LOT, int32_t> drops;
|
||||
|
||||
const LootMatrix& matrix = m_LootMatrices[matrixIndex];
|
||||
const LootMatrix& matrix = m_LootMatrices[matrixIndex];
|
||||
|
||||
for (const LootMatrixEntry& entry : matrix) {
|
||||
if (GeneralUtils::GenerateRandomNumber<float>(0, 1) < entry.percent) {
|
||||
const LootTable& lootTable = m_LootTables[entry.lootTableIndex];
|
||||
const RarityTable& rarityTable = m_RarityTables[entry.rarityTableIndex];
|
||||
for (const LootMatrixEntry& entry : matrix) {
|
||||
if (GeneralUtils::GenerateRandomNumber<float>(0, 1) < entry.percent) {
|
||||
const LootTable& lootTable = m_LootTables[entry.lootTableIndex];
|
||||
const RarityTable& rarityTable = m_RarityTables[entry.rarityTableIndex];
|
||||
|
||||
uint32_t dropCount = GeneralUtils::GenerateRandomNumber<uint32_t>(entry.minDrop, entry.maxDrop);
|
||||
for (uint32_t i = 0; i < dropCount; ++i) {
|
||||
uint32_t maxRarity = 1;
|
||||
uint32_t dropCount = GeneralUtils::GenerateRandomNumber<uint32_t>(entry.minDrop, entry.maxDrop);
|
||||
for (uint32_t i = 0; i < dropCount; ++i) {
|
||||
uint32_t maxRarity = 1;
|
||||
|
||||
float rarityRoll = GeneralUtils::GenerateRandomNumber<float>(0, 1);
|
||||
float rarityRoll = GeneralUtils::GenerateRandomNumber<float>(0, 1);
|
||||
|
||||
for (const RarityTableEntry& rarity : rarityTable) {
|
||||
if (rarity.randMax >= rarityRoll) {
|
||||
maxRarity = rarity.rarity;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (const RarityTableEntry& rarity : rarityTable) {
|
||||
if (rarity.randMax >= rarityRoll) {
|
||||
maxRarity = rarity.rarity;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool rarityFound = false;
|
||||
std::vector<LootTableEntry> possibleDrops;
|
||||
bool rarityFound = false;
|
||||
std::vector<LootTableEntry> possibleDrops;
|
||||
|
||||
for (const LootTableEntry& loot : lootTable) {
|
||||
uint32_t rarity = m_ItemRarities[loot.itemID];
|
||||
for (const LootTableEntry& loot : lootTable) {
|
||||
uint32_t rarity = m_ItemRarities[loot.itemID];
|
||||
|
||||
if (rarity == maxRarity) {
|
||||
possibleDrops.push_back(loot);
|
||||
rarityFound = true;
|
||||
} else if (rarity < maxRarity && !rarityFound) {
|
||||
possibleDrops.push_back(loot);
|
||||
maxRarity = rarity;
|
||||
}
|
||||
}
|
||||
if (rarity == maxRarity) {
|
||||
possibleDrops.push_back(loot);
|
||||
rarityFound = true;
|
||||
} else if (rarity < maxRarity && !rarityFound) {
|
||||
possibleDrops.push_back(loot);
|
||||
maxRarity = rarity;
|
||||
}
|
||||
}
|
||||
|
||||
if (possibleDrops.size() > 0) {
|
||||
const LootTableEntry& drop = possibleDrops[GeneralUtils::GenerateRandomNumber<uint32_t>(0, possibleDrops.size() - 1)];
|
||||
if (possibleDrops.size() > 0) {
|
||||
const LootTableEntry& drop = possibleDrops[GeneralUtils::GenerateRandomNumber<uint32_t>(0, possibleDrops.size() - 1)];
|
||||
|
||||
if (drops.find(drop.itemID) == drops.end()) {
|
||||
drops.insert({drop.itemID, 1});
|
||||
} else {
|
||||
++drops[drop.itemID];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (drops.find(drop.itemID) == drops.end()) {
|
||||
drops.insert({ drop.itemID, 1 });
|
||||
} else {
|
||||
++drops[drop.itemID];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return drops;
|
||||
return drops;
|
||||
}
|
||||
|
||||
void LootGenerator::GiveLoot(Entity* player, uint32_t matrixIndex, eLootSourceType lootSourceType) {
|
||||
player = player->GetOwner(); // If the owner is overwritten, we collect that here
|
||||
player = player->GetOwner(); // If the owner is overwritten, we collect that here
|
||||
|
||||
std::unordered_map<LOT, int32_t> result = RollLootMatrix(player, matrixIndex);
|
||||
std::unordered_map<LOT, int32_t> result = RollLootMatrix(player, matrixIndex);
|
||||
|
||||
GiveLoot(player, result, lootSourceType);
|
||||
GiveLoot(player, result, lootSourceType);
|
||||
}
|
||||
|
||||
void LootGenerator::GiveLoot(Entity* player, std::unordered_map<LOT, int32_t>& result, eLootSourceType lootSourceType) {
|
||||
player = player->GetOwner(); // if the owner is overwritten, we collect that here
|
||||
player = player->GetOwner(); // if the owner is overwritten, we collect that here
|
||||
|
||||
auto* inventoryComponent = player->GetComponent<InventoryComponent>();
|
||||
auto* inventoryComponent = player->GetComponent<InventoryComponent>();
|
||||
|
||||
if (!inventoryComponent)
|
||||
return;
|
||||
if (!inventoryComponent)
|
||||
return;
|
||||
|
||||
for (const auto& pair : result) {
|
||||
inventoryComponent->AddItem(pair.first, pair.second, lootSourceType);
|
||||
}
|
||||
for (const auto& pair : result) {
|
||||
inventoryComponent->AddItem(pair.first, pair.second, lootSourceType);
|
||||
}
|
||||
}
|
||||
|
||||
void LootGenerator::GiveActivityLoot(Entity* player, Entity* source, uint32_t activityID, int32_t rating) {
|
||||
CDActivityRewardsTable* activityRewardsTable = CDClientManager::Instance()->GetTable<CDActivityRewardsTable>("ActivityRewards");
|
||||
std::vector<CDActivityRewards> activityRewards = activityRewardsTable->Query([activityID](CDActivityRewards entry) { return (entry.objectTemplate == activityID); });
|
||||
CDActivityRewardsTable* activityRewardsTable = CDClientManager::Instance()->GetTable<CDActivityRewardsTable>("ActivityRewards");
|
||||
std::vector<CDActivityRewards> activityRewards = activityRewardsTable->Query([activityID](CDActivityRewards entry) { return (entry.objectTemplate == activityID); });
|
||||
|
||||
const CDActivityRewards* selectedReward = nullptr;
|
||||
for (const auto& activityReward : activityRewards) {
|
||||
if (activityReward.activityRating <= rating && (selectedReward == nullptr || activityReward.activityRating > selectedReward->activityRating)) {
|
||||
selectedReward = &activityReward;
|
||||
}
|
||||
}
|
||||
const CDActivityRewards* selectedReward = nullptr;
|
||||
for (const auto& activityReward : activityRewards) {
|
||||
if (activityReward.activityRating <= rating && (selectedReward == nullptr || activityReward.activityRating > selectedReward->activityRating)) {
|
||||
selectedReward = &activityReward;
|
||||
}
|
||||
}
|
||||
|
||||
if (!selectedReward)
|
||||
return;
|
||||
if (!selectedReward)
|
||||
return;
|
||||
|
||||
uint32_t minCoins = 0;
|
||||
uint32_t maxCoins = 0;
|
||||
uint32_t minCoins = 0;
|
||||
uint32_t maxCoins = 0;
|
||||
|
||||
CDCurrencyTableTable* currencyTableTable = CDClientManager::Instance()->GetTable<CDCurrencyTableTable>("CurrencyTable");
|
||||
std::vector<CDCurrencyTable> currencyTable = currencyTableTable->Query([selectedReward](CDCurrencyTable entry) { return (entry.currencyIndex == selectedReward->CurrencyIndex && entry.npcminlevel == 1); });
|
||||
CDCurrencyTableTable* currencyTableTable = CDClientManager::Instance()->GetTable<CDCurrencyTableTable>("CurrencyTable");
|
||||
std::vector<CDCurrencyTable> currencyTable = currencyTableTable->Query([selectedReward](CDCurrencyTable entry) { return (entry.currencyIndex == selectedReward->CurrencyIndex && entry.npcminlevel == 1); });
|
||||
|
||||
if (currencyTable.size() > 0) {
|
||||
minCoins = currencyTable[0].minvalue;
|
||||
maxCoins = currencyTable[0].maxvalue;
|
||||
}
|
||||
if (currencyTable.size() > 0) {
|
||||
minCoins = currencyTable[0].minvalue;
|
||||
maxCoins = currencyTable[0].maxvalue;
|
||||
}
|
||||
|
||||
GiveLoot(player, selectedReward->LootMatrixIndex, eLootSourceType::LOOT_SOURCE_ACTIVITY);
|
||||
GiveLoot(player, selectedReward->LootMatrixIndex, eLootSourceType::LOOT_SOURCE_ACTIVITY);
|
||||
|
||||
uint32_t coins = (int)(minCoins + GeneralUtils::GenerateRandomNumber<float>(0, 1) * (maxCoins - minCoins));
|
||||
uint32_t coins = (int)(minCoins + GeneralUtils::GenerateRandomNumber<float>(0, 1) * (maxCoins - minCoins));
|
||||
|
||||
auto* character = player->GetCharacter();
|
||||
auto* character = player->GetCharacter();
|
||||
|
||||
character->SetCoins(character->GetCoins() + coins, eLootSourceType::LOOT_SOURCE_ACTIVITY);
|
||||
character->SetCoins(character->GetCoins() + coins, eLootSourceType::LOOT_SOURCE_ACTIVITY);
|
||||
}
|
||||
|
||||
void LootGenerator::DropLoot(Entity* player, Entity* killedObject, uint32_t matrixIndex, uint32_t minCoins, uint32_t maxCoins) {
|
||||
player = player->GetOwner(); // if the owner is overwritten, we collect that here
|
||||
player = player->GetOwner(); // if the owner is overwritten, we collect that here
|
||||
|
||||
auto* inventoryComponent = player->GetComponent<InventoryComponent>();
|
||||
auto* inventoryComponent = player->GetComponent<InventoryComponent>();
|
||||
|
||||
if (!inventoryComponent)
|
||||
return;
|
||||
if (!inventoryComponent)
|
||||
return;
|
||||
|
||||
std::unordered_map<LOT, int32_t> result = RollLootMatrix(player, matrixIndex);
|
||||
std::unordered_map<LOT, int32_t> result = RollLootMatrix(player, matrixIndex);
|
||||
|
||||
DropLoot(player, killedObject, result, minCoins, maxCoins);
|
||||
DropLoot(player, killedObject, result, minCoins, maxCoins);
|
||||
}
|
||||
|
||||
void LootGenerator::DropLoot(Entity* player, Entity* killedObject, std::unordered_map<LOT, int32_t>& result, uint32_t minCoins, uint32_t maxCoins) {
|
||||
player = player->GetOwner(); // if the owner is overwritten, we collect that here
|
||||
player = player->GetOwner(); // if the owner is overwritten, we collect that here
|
||||
|
||||
auto* inventoryComponent = player->GetComponent<InventoryComponent>();
|
||||
auto* inventoryComponent = player->GetComponent<InventoryComponent>();
|
||||
|
||||
if (!inventoryComponent)
|
||||
return;
|
||||
if (!inventoryComponent)
|
||||
return;
|
||||
|
||||
const auto spawnPosition = killedObject->GetPosition();
|
||||
const auto spawnPosition = killedObject->GetPosition();
|
||||
|
||||
const auto source = killedObject->GetObjectID();
|
||||
const auto source = killedObject->GetObjectID();
|
||||
|
||||
for (const auto& pair : result) {
|
||||
for (int i = 0; i < pair.second; ++i) {
|
||||
GameMessages::SendDropClientLoot(player, source, pair.first, 0, spawnPosition, 1);
|
||||
}
|
||||
}
|
||||
for (const auto& pair : result) {
|
||||
for (int i = 0; i < pair.second; ++i) {
|
||||
GameMessages::SendDropClientLoot(player, source, pair.first, 0, spawnPosition, 1);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t coins = (int)(minCoins + GeneralUtils::GenerateRandomNumber<float>(0, 1) * (maxCoins - minCoins));
|
||||
uint32_t coins = (int)(minCoins + GeneralUtils::GenerateRandomNumber<float>(0, 1) * (maxCoins - minCoins));
|
||||
|
||||
GameMessages::SendDropClientLoot(player, source, LOT_NULL, coins, spawnPosition);
|
||||
GameMessages::SendDropClientLoot(player, source, LOT_NULL, coins, spawnPosition);
|
||||
}
|
||||
|
||||
void LootGenerator::DropActivityLoot(Entity* player, Entity* source, uint32_t activityID, int32_t rating) {
|
||||
CDActivityRewardsTable* activityRewardsTable = CDClientManager::Instance()->GetTable<CDActivityRewardsTable>("ActivityRewards");
|
||||
std::vector<CDActivityRewards> activityRewards = activityRewardsTable->Query([activityID](CDActivityRewards entry) { return (entry.objectTemplate == activityID); });
|
||||
CDActivityRewardsTable* activityRewardsTable = CDClientManager::Instance()->GetTable<CDActivityRewardsTable>("ActivityRewards");
|
||||
std::vector<CDActivityRewards> activityRewards = activityRewardsTable->Query([activityID](CDActivityRewards entry) { return (entry.objectTemplate == activityID); });
|
||||
|
||||
const CDActivityRewards* selectedReward = nullptr;
|
||||
for (const auto& activityReward : activityRewards) {
|
||||
if (activityReward.activityRating <= rating && (selectedReward == nullptr || activityReward.activityRating > selectedReward->activityRating)) {
|
||||
selectedReward = &activityReward;
|
||||
}
|
||||
}
|
||||
const CDActivityRewards* selectedReward = nullptr;
|
||||
for (const auto& activityReward : activityRewards) {
|
||||
if (activityReward.activityRating <= rating && (selectedReward == nullptr || activityReward.activityRating > selectedReward->activityRating)) {
|
||||
selectedReward = &activityReward;
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedReward == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (selectedReward == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t minCoins = 0;
|
||||
uint32_t maxCoins = 0;
|
||||
uint32_t minCoins = 0;
|
||||
uint32_t maxCoins = 0;
|
||||
|
||||
CDCurrencyTableTable* currencyTableTable = CDClientManager::Instance()->GetTable<CDCurrencyTableTable>("CurrencyTable");
|
||||
std::vector<CDCurrencyTable> currencyTable = currencyTableTable->Query([selectedReward](CDCurrencyTable entry) { return (entry.currencyIndex == selectedReward->CurrencyIndex && entry.npcminlevel == 1); });
|
||||
CDCurrencyTableTable* currencyTableTable = CDClientManager::Instance()->GetTable<CDCurrencyTableTable>("CurrencyTable");
|
||||
std::vector<CDCurrencyTable> currencyTable = currencyTableTable->Query([selectedReward](CDCurrencyTable entry) { return (entry.currencyIndex == selectedReward->CurrencyIndex && entry.npcminlevel == 1); });
|
||||
|
||||
if (currencyTable.size() > 0) {
|
||||
minCoins = currencyTable[0].minvalue;
|
||||
maxCoins = currencyTable[0].maxvalue;
|
||||
}
|
||||
if (currencyTable.size() > 0) {
|
||||
minCoins = currencyTable[0].minvalue;
|
||||
maxCoins = currencyTable[0].maxvalue;
|
||||
}
|
||||
|
||||
DropLoot(player, source, selectedReward->LootMatrixIndex, minCoins, maxCoins);
|
||||
DropLoot(player, source, selectedReward->LootMatrixIndex, minCoins, maxCoins);
|
||||
}
|
||||
|
@@ -8,55 +8,55 @@
|
||||
class Entity;
|
||||
|
||||
struct RarityTableEntry {
|
||||
uint32_t rarity;
|
||||
float randMax;
|
||||
uint32_t rarity;
|
||||
float randMax;
|
||||
};
|
||||
|
||||
typedef std::vector<RarityTableEntry> RarityTable;
|
||||
|
||||
struct LootMatrixEntry {
|
||||
uint32_t lootTableIndex;
|
||||
uint32_t rarityTableIndex;
|
||||
float percent;
|
||||
uint32_t minDrop;
|
||||
uint32_t maxDrop;
|
||||
uint32_t lootTableIndex;
|
||||
uint32_t rarityTableIndex;
|
||||
float percent;
|
||||
uint32_t minDrop;
|
||||
uint32_t maxDrop;
|
||||
};
|
||||
|
||||
typedef std::vector<LootMatrixEntry> LootMatrix;
|
||||
|
||||
struct LootTableEntry {
|
||||
LOT itemID;
|
||||
bool isMissionDrop;
|
||||
LOT itemID;
|
||||
bool isMissionDrop;
|
||||
};
|
||||
|
||||
typedef std::vector<LootTableEntry> LootTable;
|
||||
|
||||
// used for glue code with Entity and Player classes
|
||||
namespace Loot {
|
||||
struct Info {
|
||||
LWOOBJID id;
|
||||
LOT lot;
|
||||
uint32_t count;
|
||||
};
|
||||
struct Info {
|
||||
LWOOBJID id;
|
||||
LOT lot;
|
||||
uint32_t count;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
class LootGenerator : public Singleton<LootGenerator> {
|
||||
public:
|
||||
LootGenerator();
|
||||
public:
|
||||
LootGenerator();
|
||||
|
||||
std::unordered_map<LOT, int32_t> RollLootMatrix(Entity* player, uint32_t matrixIndex);
|
||||
std::unordered_map<LOT, int32_t> RollLootMatrix(uint32_t matrixIndex);
|
||||
void GiveLoot(Entity* player, uint32_t matrixIndex, eLootSourceType lootSourceType = eLootSourceType::LOOT_SOURCE_NONE);
|
||||
void GiveLoot(Entity* player, std::unordered_map<LOT, int32_t>& result, eLootSourceType lootSourceType = eLootSourceType::LOOT_SOURCE_NONE);
|
||||
void GiveActivityLoot(Entity* player, Entity* source, uint32_t activityID, int32_t rating = 0);
|
||||
void DropLoot(Entity* player, Entity* killedObject, uint32_t matrixIndex, uint32_t minCoins, uint32_t maxCoins);
|
||||
void DropLoot(Entity* player, Entity* killedObject, std::unordered_map<LOT, int32_t>& result, uint32_t minCoins, uint32_t maxCoins);
|
||||
void DropActivityLoot(Entity* player, Entity* source, uint32_t activityID, int32_t rating = 0);
|
||||
std::unordered_map<LOT, int32_t> RollLootMatrix(Entity* player, uint32_t matrixIndex);
|
||||
std::unordered_map<LOT, int32_t> RollLootMatrix(uint32_t matrixIndex);
|
||||
void GiveLoot(Entity* player, uint32_t matrixIndex, eLootSourceType lootSourceType = eLootSourceType::LOOT_SOURCE_NONE);
|
||||
void GiveLoot(Entity* player, std::unordered_map<LOT, int32_t>& result, eLootSourceType lootSourceType = eLootSourceType::LOOT_SOURCE_NONE);
|
||||
void GiveActivityLoot(Entity* player, Entity* source, uint32_t activityID, int32_t rating = 0);
|
||||
void DropLoot(Entity* player, Entity* killedObject, uint32_t matrixIndex, uint32_t minCoins, uint32_t maxCoins);
|
||||
void DropLoot(Entity* player, Entity* killedObject, std::unordered_map<LOT, int32_t>& result, uint32_t minCoins, uint32_t maxCoins);
|
||||
void DropActivityLoot(Entity* player, Entity* source, uint32_t activityID, int32_t rating = 0);
|
||||
|
||||
private:
|
||||
std::unordered_map<uint32_t, uint8_t> m_ItemRarities;
|
||||
std::unordered_map<uint32_t, RarityTable> m_RarityTables;
|
||||
std::unordered_map<uint32_t, LootMatrix> m_LootMatrices;
|
||||
std::unordered_map<uint32_t, LootTable> m_LootTables;
|
||||
private:
|
||||
std::unordered_map<uint32_t, uint8_t> m_ItemRarities;
|
||||
std::unordered_map<uint32_t, RarityTable> m_RarityTables;
|
||||
std::unordered_map<uint32_t, LootMatrix> m_LootMatrices;
|
||||
std::unordered_map<uint32_t, LootTable> m_LootTables;
|
||||
};
|
||||
|
@@ -24,8 +24,7 @@
|
||||
#include "Character.h"
|
||||
|
||||
void Mail::SendMail(const Entity* recipient, const std::string& subject, const std::string& body, const LOT attachment,
|
||||
const uint16_t attachmentCount)
|
||||
{
|
||||
const uint16_t attachmentCount) {
|
||||
SendMail(
|
||||
LWOOBJID_EMPTY,
|
||||
ServerName,
|
||||
@@ -40,8 +39,7 @@ void Mail::SendMail(const Entity* recipient, const std::string& subject, const s
|
||||
}
|
||||
|
||||
void Mail::SendMail(const LWOOBJID recipient, const std::string& recipientName, const std::string& subject,
|
||||
const std::string& body, const LOT attachment, const uint16_t attachmentCount, const SystemAddress& sysAddr)
|
||||
{
|
||||
const std::string& body, const LOT attachment, const uint16_t attachmentCount, const SystemAddress& sysAddr) {
|
||||
SendMail(
|
||||
LWOOBJID_EMPTY,
|
||||
ServerName,
|
||||
@@ -56,8 +54,7 @@ void Mail::SendMail(const LWOOBJID recipient, const std::string& recipientName,
|
||||
}
|
||||
|
||||
void Mail::SendMail(const LWOOBJID sender, const std::string& senderName, const Entity* recipient, const std::string& subject,
|
||||
const std::string& body, const LOT attachment, const uint16_t attachmentCount)
|
||||
{
|
||||
const std::string& body, const LOT attachment, const uint16_t attachmentCount) {
|
||||
SendMail(
|
||||
sender,
|
||||
senderName,
|
||||
@@ -72,9 +69,8 @@ void Mail::SendMail(const LWOOBJID sender, const std::string& senderName, const
|
||||
}
|
||||
|
||||
void Mail::SendMail(const LWOOBJID sender, const std::string& senderName, LWOOBJID recipient,
|
||||
const std::string& recipientName, const std::string& subject, const std::string& body, const LOT attachment,
|
||||
const uint16_t attachmentCount, const SystemAddress& sysAddr)
|
||||
{
|
||||
const std::string& recipientName, const std::string& subject, const std::string& body, const LOT attachment,
|
||||
const uint16_t attachmentCount, const SystemAddress& sysAddr) {
|
||||
auto* ins = Database::CreatePreppedStmt("INSERT INTO `mail`(`sender_id`, `sender_name`, `receiver_id`, `receiver_name`, `time_sent`, `subject`, `body`, `attachment_id`, `attachment_lot`, `attachment_subkey`, `attachment_count`, `was_read`) VALUES (?,?,?,?,?,?,?,?,?,?,?,0)");
|
||||
|
||||
ins->setUInt(1, sender);
|
||||
@@ -154,7 +150,7 @@ void Mail::HandleMailStuff(RakNet::BitStream* packet, const SystemAddress& sysAd
|
||||
default:
|
||||
Game::logger->Log("Mail", "Unhandled and possibly undefined MailStuffID: %i", int(stuffID));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void Mail::HandleSendMail(RakNet::BitStream* packet, const SystemAddress& sysAddr, Entity* entity) {
|
||||
@@ -167,8 +163,7 @@ void Mail::HandleSendMail(RakNet::BitStream* packet, const SystemAddress& sysAdd
|
||||
|
||||
if (!character) return;
|
||||
|
||||
if (character->HasPermission(PermissionMap::RestrictedMailAccess))
|
||||
{
|
||||
if (character->HasPermission(PermissionMap::RestrictedMailAccess)) {
|
||||
// Send a message to the player
|
||||
ChatPackets::SendSystemMessage(
|
||||
sysAddr,
|
||||
@@ -227,8 +222,7 @@ void Mail::HandleSendMail(RakNet::BitStream* packet, const SystemAddress& sysAdd
|
||||
|
||||
if (res->rowsCount() > 0) {
|
||||
while (res->next()) receiverID = res->getUInt(1);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Mail::SendSendResponse(sysAddr, Mail::MailSendResponse::RecipientNotFound);
|
||||
delete stmt;
|
||||
delete res;
|
||||
@@ -242,8 +236,7 @@ void Mail::HandleSendMail(RakNet::BitStream* packet, const SystemAddress& sysAdd
|
||||
if (GeneralUtils::CaseInsensitiveStringCompare(recipient, character->GetName()) || receiverID == character->GetObjectID()) {
|
||||
Mail::SendSendResponse(sysAddr, Mail::MailSendResponse::CannotMailSelf);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
uint64_t currentTime = time(NULL);
|
||||
sql::PreparedStatement* ins = Database::CreatePreppedStmt("INSERT INTO `mail`(`sender_id`, `sender_name`, `receiver_id`, `receiver_name`, `time_sent`, `subject`, `body`, `attachment_id`, `attachment_lot`, `attachment_subkey`, `attachment_count`, `was_read`) VALUES (?,?,?,?,?,?,?,?,?,?,?,0)");
|
||||
ins->setUInt(1, character->GetObjectID());
|
||||
@@ -272,8 +265,7 @@ void Mail::HandleSendMail(RakNet::BitStream* packet, const SystemAddress& sysAdd
|
||||
|
||||
auto* missionCompoent = entity->GetComponent<MissionComponent>();
|
||||
|
||||
if (missionCompoent != nullptr)
|
||||
{
|
||||
if (missionCompoent != nullptr) {
|
||||
missionCompoent->Progress(MissionTaskType::MISSION_TASK_TYPE_ITEM_COLLECTION, itemLOT, LWOOBJID_EMPTY, "", -attachmentCount);
|
||||
}
|
||||
}
|
||||
@@ -405,7 +397,7 @@ void Mail::HandleNotificationRequest(const SystemAddress& sysAddr, uint32_t obje
|
||||
if (res->rowsCount() > 0) Mail::SendNotification(sysAddr, res->rowsCount());
|
||||
delete res;
|
||||
delete stmt;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void Mail::SendSendResponse(const SystemAddress& sysAddr, MailSendResponse response) {
|
||||
|
@@ -56,7 +56,7 @@ namespace Mail {
|
||||
uint16_t attachmentCount,
|
||||
const SystemAddress& sysAddr
|
||||
);
|
||||
|
||||
|
||||
void SendMail(
|
||||
LWOOBJID sender,
|
||||
const std::string& senderName,
|
||||
@@ -92,4 +92,4 @@ namespace Mail {
|
||||
void SendAttachmentRemoveConfirm(const SystemAddress& sysAddr, uint64_t mailID);
|
||||
void SendDeleteConfirm(const SystemAddress& sysAddr, uint64_t mailID, LWOOBJID playerID);
|
||||
void SendReadConfirm(const SystemAddress& sysAddr, uint64_t mailID);
|
||||
};
|
||||
};
|
||||
|
@@ -19,12 +19,11 @@ std::map<uint32_t, Precondition*> Preconditions::cache = {};
|
||||
Precondition::Precondition(const uint32_t condition) {
|
||||
auto query = CDClientDatabase::CreatePreppedStmt(
|
||||
"SELECT type, targetLOT, targetCount FROM Preconditions WHERE id = ?;");
|
||||
query.bind(1, (int) condition);
|
||||
query.bind(1, (int)condition);
|
||||
|
||||
auto result = query.execQuery();
|
||||
|
||||
if (result.eof())
|
||||
{
|
||||
if (result.eof()) {
|
||||
this->type = PreconditionType::ItemEquipped;
|
||||
this->count = 1;
|
||||
this->values = { 0 };
|
||||
@@ -36,16 +35,13 @@ Precondition::Precondition(const uint32_t condition) {
|
||||
|
||||
this->type = static_cast<PreconditionType>(result.fieldIsNull(0) ? 0 : result.getIntField(0));
|
||||
|
||||
if (!result.fieldIsNull(1))
|
||||
{
|
||||
if (!result.fieldIsNull(1)) {
|
||||
std::istringstream stream(result.getStringField(1));
|
||||
std::string token;
|
||||
|
||||
while (std::getline(stream, token, ','))
|
||||
{
|
||||
while (std::getline(stream, token, ',')) {
|
||||
uint32_t value;
|
||||
if (GeneralUtils::TryParse(token, value))
|
||||
{
|
||||
if (GeneralUtils::TryParse(token, value)) {
|
||||
this->values.push_back(value);
|
||||
}
|
||||
}
|
||||
@@ -57,10 +53,8 @@ Precondition::Precondition(const uint32_t condition) {
|
||||
}
|
||||
|
||||
|
||||
bool Precondition::Check(Entity* player, bool evaluateCosts) const
|
||||
{
|
||||
if (values.empty())
|
||||
{
|
||||
bool Precondition::Check(Entity* player, bool evaluateCosts) const {
|
||||
if (values.empty()) {
|
||||
return true; // There are very few of these
|
||||
}
|
||||
|
||||
@@ -100,22 +94,18 @@ bool Precondition::Check(Entity* player, bool evaluateCosts) const
|
||||
|
||||
auto passedAny = false;
|
||||
|
||||
for (const auto value : values)
|
||||
{
|
||||
for (const auto value : values) {
|
||||
const auto passed = CheckValue(player, value, evaluateCosts);
|
||||
|
||||
if (passed && any)
|
||||
{
|
||||
if (passed && any) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!passed && !any)
|
||||
{
|
||||
if (!passed && !any) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (passed)
|
||||
{
|
||||
if (passed) {
|
||||
passedAny = true;
|
||||
}
|
||||
}
|
||||
@@ -124,8 +114,7 @@ bool Precondition::Check(Entity* player, bool evaluateCosts) const
|
||||
}
|
||||
|
||||
|
||||
bool Precondition::CheckValue(Entity* player, const uint32_t value, bool evaluateCosts) const
|
||||
{
|
||||
bool Precondition::CheckValue(Entity* player, const uint32_t value, bool evaluateCosts) const {
|
||||
auto* missionComponent = player->GetComponent<MissionComponent>();
|
||||
auto* inventoryComponent = player->GetComponent<InventoryComponent>();
|
||||
auto* destroyableComponent = player->GetComponent<DestroyableComponent>();
|
||||
@@ -134,8 +123,7 @@ bool Precondition::CheckValue(Entity* player, const uint32_t value, bool evaluat
|
||||
|
||||
Mission* mission;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
switch (type) {
|
||||
case PreconditionType::ItemEquipped:
|
||||
return inventoryComponent->IsEquipped(value);
|
||||
case PreconditionType::ItemNotEquipped:
|
||||
@@ -180,20 +168,16 @@ bool Precondition::CheckValue(Entity* player, const uint32_t value, bool evaluat
|
||||
case PreconditionType::IsPetTaming:
|
||||
return false; // TODO
|
||||
case PreconditionType::HasFaction:
|
||||
for (const auto faction : destroyableComponent->GetFactionIDs())
|
||||
{
|
||||
if (faction == static_cast<int>(value))
|
||||
{
|
||||
for (const auto faction : destroyableComponent->GetFactionIDs()) {
|
||||
if (faction == static_cast<int>(value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
case PreconditionType::DoesNotHaveFaction:
|
||||
for (const auto faction : destroyableComponent->GetFactionIDs())
|
||||
{
|
||||
if (faction == static_cast<int>(value))
|
||||
{
|
||||
for (const auto faction : destroyableComponent->GetFactionIDs()) {
|
||||
if (faction == static_cast<int>(value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -214,10 +198,8 @@ bool Precondition::CheckValue(Entity* player, const uint32_t value, bool evaluat
|
||||
}
|
||||
}
|
||||
|
||||
PreconditionExpression::PreconditionExpression(const std::string& conditions)
|
||||
{
|
||||
if (conditions.empty())
|
||||
{
|
||||
PreconditionExpression::PreconditionExpression(const std::string& conditions) {
|
||||
if (conditions.empty()) {
|
||||
empty = true;
|
||||
|
||||
return;
|
||||
@@ -230,17 +212,14 @@ PreconditionExpression::PreconditionExpression(const std::string& conditions)
|
||||
|
||||
auto done = false;
|
||||
|
||||
for (auto i = 0u; i < conditions.size(); ++i)
|
||||
{
|
||||
if (done)
|
||||
{
|
||||
for (auto i = 0u; i < conditions.size(); ++i) {
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
|
||||
const auto character = conditions[i];
|
||||
|
||||
switch (character)
|
||||
{
|
||||
switch (character) {
|
||||
case '|':
|
||||
bor = true;
|
||||
b << conditions.substr(i + 1);
|
||||
@@ -277,32 +256,24 @@ PreconditionExpression::PreconditionExpression(const std::string& conditions)
|
||||
|
||||
const auto aString = a.str();
|
||||
|
||||
if (!aString.empty())
|
||||
{
|
||||
if (!aString.empty()) {
|
||||
this->condition = std::stoul(a.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
this->condition = 0;
|
||||
}
|
||||
|
||||
const auto bString = b.str();
|
||||
|
||||
if (!bString.empty())
|
||||
{
|
||||
if (!bString.empty()) {
|
||||
this->next = new PreconditionExpression(bString);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
this->next = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool PreconditionExpression::Check(Entity* player, bool evaluateCosts) const
|
||||
{
|
||||
if (empty)
|
||||
{
|
||||
bool PreconditionExpression::Check(Entity* player, bool evaluateCosts) const {
|
||||
if (empty) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -313,8 +284,7 @@ bool PreconditionExpression::Check(Entity* player, bool evaluateCosts) const
|
||||
|
||||
const auto a = Preconditions::Check(player, condition, evaluateCosts);
|
||||
|
||||
if (!a)
|
||||
{
|
||||
if (!a) {
|
||||
GameMessages::SendNotifyClientFailedPrecondition(player->GetObjectID(), player->GetSystemAddress(), u"", condition);
|
||||
}
|
||||
|
||||
@@ -323,24 +293,19 @@ bool PreconditionExpression::Check(Entity* player, bool evaluateCosts) const
|
||||
return m_or ? a || b : a && b;
|
||||
}
|
||||
|
||||
PreconditionExpression::~PreconditionExpression()
|
||||
{
|
||||
PreconditionExpression::~PreconditionExpression() {
|
||||
delete next;
|
||||
}
|
||||
|
||||
|
||||
bool Preconditions::Check(Entity* player, const uint32_t condition, bool evaluateCosts)
|
||||
{
|
||||
bool Preconditions::Check(Entity* player, const uint32_t condition, bool evaluateCosts) {
|
||||
Precondition* precondition;
|
||||
|
||||
const auto& index = cache.find(condition);
|
||||
|
||||
if (index != cache.end())
|
||||
{
|
||||
if (index != cache.end()) {
|
||||
precondition = index->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
precondition = new Precondition(condition);
|
||||
|
||||
cache.insert_or_assign(condition, precondition);
|
||||
@@ -350,16 +315,13 @@ bool Preconditions::Check(Entity* player, const uint32_t condition, bool evaluat
|
||||
}
|
||||
|
||||
|
||||
PreconditionExpression Preconditions::CreateExpression(const std::string& conditions)
|
||||
{
|
||||
PreconditionExpression Preconditions::CreateExpression(const std::string& conditions) {
|
||||
return PreconditionExpression(conditions);
|
||||
}
|
||||
|
||||
|
||||
Preconditions::~Preconditions()
|
||||
{
|
||||
for (const auto& condition : cache)
|
||||
{
|
||||
Preconditions::~Preconditions() {
|
||||
for (const auto& condition : cache) {
|
||||
delete condition.second;
|
||||
}
|
||||
|
||||
|
@@ -6,26 +6,26 @@
|
||||
|
||||
enum class PreconditionType
|
||||
{
|
||||
ItemEquipped,
|
||||
ItemNotEquipped,
|
||||
HasItem,
|
||||
DoesNotHaveItem,
|
||||
HasAchievement,
|
||||
MissionAvailable,
|
||||
OnMission,
|
||||
MissionComplete,
|
||||
PetDeployed,
|
||||
HasFlag,
|
||||
WithinShape,
|
||||
InBuild,
|
||||
TeamCheck,
|
||||
IsPetTaming,
|
||||
HasFaction,
|
||||
DoesNotHaveFaction,
|
||||
HasRacingLicence,
|
||||
DoesNotHaveRacingLicence,
|
||||
LegoClubMember,
|
||||
NoInteraction,
|
||||
ItemEquipped,
|
||||
ItemNotEquipped,
|
||||
HasItem,
|
||||
DoesNotHaveItem,
|
||||
HasAchievement,
|
||||
MissionAvailable,
|
||||
OnMission,
|
||||
MissionComplete,
|
||||
PetDeployed,
|
||||
HasFlag,
|
||||
WithinShape,
|
||||
InBuild,
|
||||
TeamCheck,
|
||||
IsPetTaming,
|
||||
HasFaction,
|
||||
DoesNotHaveFaction,
|
||||
HasRacingLicence,
|
||||
DoesNotHaveRacingLicence,
|
||||
LegoClubMember,
|
||||
NoInteraction,
|
||||
HasLevel = 22
|
||||
};
|
||||
|
||||
@@ -33,49 +33,49 @@ enum class PreconditionType
|
||||
class Precondition final
|
||||
{
|
||||
public:
|
||||
explicit Precondition(uint32_t condition);
|
||||
|
||||
bool Check(Entity* player, bool evaluateCosts = false) const;
|
||||
|
||||
explicit Precondition(uint32_t condition);
|
||||
|
||||
bool Check(Entity* player, bool evaluateCosts = false) const;
|
||||
|
||||
private:
|
||||
bool CheckValue(Entity* player, uint32_t value, bool evaluateCosts = false) const;
|
||||
|
||||
PreconditionType type;
|
||||
bool CheckValue(Entity* player, uint32_t value, bool evaluateCosts = false) const;
|
||||
|
||||
std::vector<uint32_t> values;
|
||||
PreconditionType type;
|
||||
|
||||
uint32_t count;
|
||||
std::vector<uint32_t> values;
|
||||
|
||||
uint32_t count;
|
||||
};
|
||||
|
||||
|
||||
class PreconditionExpression final
|
||||
{
|
||||
public:
|
||||
explicit PreconditionExpression(const std::string& conditions);
|
||||
explicit PreconditionExpression(const std::string& conditions);
|
||||
|
||||
bool Check(Entity* player, bool evaluateCosts = false) const;
|
||||
|
||||
~PreconditionExpression();
|
||||
|
||||
bool Check(Entity* player, bool evaluateCosts = false) const;
|
||||
|
||||
~PreconditionExpression();
|
||||
|
||||
private:
|
||||
uint32_t condition = 0;
|
||||
uint32_t condition = 0;
|
||||
|
||||
bool m_or = false;
|
||||
bool m_or = false;
|
||||
|
||||
bool empty = false;
|
||||
bool empty = false;
|
||||
|
||||
PreconditionExpression* next = nullptr;
|
||||
PreconditionExpression* next = nullptr;
|
||||
};
|
||||
|
||||
class Preconditions final
|
||||
{
|
||||
public:
|
||||
static bool Check(Entity* player, uint32_t condition, bool evaluateCosts = false);
|
||||
static bool Check(Entity* player, uint32_t condition, bool evaluateCosts = false);
|
||||
|
||||
static PreconditionExpression CreateExpression(const std::string& conditions);
|
||||
static PreconditionExpression CreateExpression(const std::string& conditions);
|
||||
|
||||
~Preconditions();
|
||||
|
||||
|
||||
private:
|
||||
static std::map<uint32_t, Precondition*> cache;
|
||||
static std::map<uint32_t, Precondition*> cache;
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -12,10 +12,10 @@
|
||||
class Entity;
|
||||
|
||||
namespace SlashCommandHandler {
|
||||
void HandleChatCommand(const std::u16string& command, Entity* entity, const SystemAddress& sysAddr);
|
||||
bool CheckIfAccessibleZone(const unsigned int zoneID);
|
||||
void HandleChatCommand(const std::u16string& command, Entity* entity, const SystemAddress& sysAddr);
|
||||
bool CheckIfAccessibleZone(const unsigned int zoneID);
|
||||
|
||||
void SendAnnouncement(const std::string& title, const std::string& message);
|
||||
void SendAnnouncement(const std::string& title, const std::string& message);
|
||||
};
|
||||
|
||||
#endif // SLASHCOMMANDHANDLER_H
|
||||
|
@@ -20,520 +20,513 @@ std::vector<VanityNPC> VanityUtilities::m_NPCs = {};
|
||||
std::vector<VanityParty> VanityUtilities::m_Parties = {};
|
||||
std::vector<std::string> VanityUtilities::m_PartyPhrases = {};
|
||||
|
||||
void VanityUtilities::SpawnVanity()
|
||||
{
|
||||
if (Game::config->GetValue("disable_vanity") == "1") {
|
||||
return;
|
||||
}
|
||||
void VanityUtilities::SpawnVanity() {
|
||||
if (Game::config->GetValue("disable_vanity") == "1") {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t zoneID = Game::server->GetZoneID();
|
||||
const uint32_t zoneID = Game::server->GetZoneID();
|
||||
|
||||
ParseXML("./vanity/NPC.xml");
|
||||
ParseXML("./vanity/NPC.xml");
|
||||
|
||||
// Loop through all parties
|
||||
for (const auto& party : m_Parties) {
|
||||
const auto chance = party.m_Chance;
|
||||
const auto zone = party.m_Zone;
|
||||
// Loop through all parties
|
||||
for (const auto& party : m_Parties) {
|
||||
const auto chance = party.m_Chance;
|
||||
const auto zone = party.m_Zone;
|
||||
|
||||
if (zone != Game::server->GetZoneID()) {
|
||||
continue;
|
||||
}
|
||||
if (zone != Game::server->GetZoneID()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float rate = GeneralUtils::GenerateRandomNumber<float>(0, 1);
|
||||
if (chance < rate) {
|
||||
continue;
|
||||
}
|
||||
float rate = GeneralUtils::GenerateRandomNumber<float>(0, 1);
|
||||
if (chance < rate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Copy m_NPCs into a new vector
|
||||
std::vector<VanityNPC> npcList = m_NPCs;
|
||||
std::vector<uint32_t> taken = {};
|
||||
// Copy m_NPCs into a new vector
|
||||
std::vector<VanityNPC> npcList = m_NPCs;
|
||||
std::vector<uint32_t> taken = {};
|
||||
|
||||
Game::logger->Log("VanityUtilities", "Spawning party with %i locations", party.m_Locations.size());
|
||||
Game::logger->Log("VanityUtilities", "Spawning party with %i locations", party.m_Locations.size());
|
||||
|
||||
// Loop through all locations
|
||||
for (const auto& location : party.m_Locations) {
|
||||
rate = GeneralUtils::GenerateRandomNumber<float>(0, 1);
|
||||
if (0.75f < rate) {
|
||||
continue;
|
||||
}
|
||||
// Loop through all locations
|
||||
for (const auto& location : party.m_Locations) {
|
||||
rate = GeneralUtils::GenerateRandomNumber<float>(0, 1);
|
||||
if (0.75f < rate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get a random NPC
|
||||
auto npcIndex = GeneralUtils::GenerateRandomNumber<uint32_t>(0, npcList.size() - 1);
|
||||
// Get a random NPC
|
||||
auto npcIndex = GeneralUtils::GenerateRandomNumber<uint32_t>(0, npcList.size() - 1);
|
||||
|
||||
while (std::find(taken.begin(), taken.end(), npcIndex) != taken.end()) {
|
||||
npcIndex = GeneralUtils::GenerateRandomNumber<uint32_t>(0, npcList.size() - 1);
|
||||
}
|
||||
while (std::find(taken.begin(), taken.end(), npcIndex) != taken.end()) {
|
||||
npcIndex = GeneralUtils::GenerateRandomNumber<uint32_t>(0, npcList.size() - 1);
|
||||
}
|
||||
|
||||
const auto& npc = npcList[npcIndex];
|
||||
const auto& npc = npcList[npcIndex];
|
||||
|
||||
taken.push_back(npcIndex);
|
||||
taken.push_back(npcIndex);
|
||||
|
||||
// Spawn the NPC
|
||||
std::vector<LDFBaseData*> data = { new LDFData<std::vector<std::u16string>>(
|
||||
u"syncLDF", { u"custom_script_client" }),
|
||||
new LDFData<std::u16string>(u"custom_script_client", u"scripts\\ai\\SPEC\\MISSION_MINIGAME_CLIENT.lua") };
|
||||
// Spawn the NPC
|
||||
std::vector<LDFBaseData*> data = { new LDFData<std::vector<std::u16string>>(
|
||||
u"syncLDF", { u"custom_script_client" }),
|
||||
new LDFData<std::u16string>(u"custom_script_client", u"scripts\\ai\\SPEC\\MISSION_MINIGAME_CLIENT.lua") };
|
||||
|
||||
// Spawn the NPC
|
||||
auto* npcEntity = SpawnNPC(npc.m_LOT, npc.m_Name, location.m_Position, location.m_Rotation, npc.m_Equipment, data);
|
||||
// Spawn the NPC
|
||||
auto* npcEntity = SpawnNPC(npc.m_LOT, npc.m_Name, location.m_Position, location.m_Rotation, npc.m_Equipment, data);
|
||||
|
||||
npcEntity->SetVar<std::vector<std::string>>(u"chats", m_PartyPhrases);
|
||||
npcEntity->SetVar<std::vector<std::string>>(u"chats", m_PartyPhrases);
|
||||
|
||||
SetupNPCTalk(npcEntity);
|
||||
}
|
||||
SetupNPCTalk(npcEntity);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Loop through all NPCs
|
||||
for (const auto& pair : m_NPCs) {
|
||||
if (pair.m_Locations.find(Game::server->GetZoneID()) == pair.m_Locations.end())
|
||||
continue;
|
||||
// Loop through all NPCs
|
||||
for (const auto& pair : m_NPCs) {
|
||||
if (pair.m_Locations.find(Game::server->GetZoneID()) == pair.m_Locations.end())
|
||||
continue;
|
||||
|
||||
const std::vector<VanityNPCLocation>& locations = pair.m_Locations.at(Game::server->GetZoneID());
|
||||
const std::vector<VanityNPCLocation>& locations = pair.m_Locations.at(Game::server->GetZoneID());
|
||||
|
||||
// Pick a random location
|
||||
const auto& location = locations[GeneralUtils::GenerateRandomNumber<int>(
|
||||
static_cast<size_t>(0), static_cast<size_t>(locations.size() - 1))];
|
||||
// Pick a random location
|
||||
const auto& location = locations[GeneralUtils::GenerateRandomNumber<int>(
|
||||
static_cast<size_t>(0), static_cast<size_t>(locations.size() - 1))];
|
||||
|
||||
float rate = GeneralUtils::GenerateRandomNumber<float>(0, 1);
|
||||
if (location.m_Chance < rate) {
|
||||
continue;
|
||||
}
|
||||
float rate = GeneralUtils::GenerateRandomNumber<float>(0, 1);
|
||||
if (location.m_Chance < rate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<LDFBaseData*> data = { new LDFData<std::vector<std::u16string>>(
|
||||
u"syncLDF", { u"custom_script_client" }),
|
||||
new LDFData<std::u16string>(u"custom_script_client", u"scripts\\ai\\SPEC\\MISSION_MINIGAME_CLIENT.lua") };
|
||||
std::vector<LDFBaseData*> data = { new LDFData<std::vector<std::u16string>>(
|
||||
u"syncLDF", { u"custom_script_client" }),
|
||||
new LDFData<std::u16string>(u"custom_script_client", u"scripts\\ai\\SPEC\\MISSION_MINIGAME_CLIENT.lua") };
|
||||
|
||||
// Spawn the NPC
|
||||
auto* npc = SpawnNPC(pair.m_LOT, pair.m_Name, location.m_Position, location.m_Rotation, pair.m_Equipment, data);
|
||||
// Spawn the NPC
|
||||
auto* npc = SpawnNPC(pair.m_LOT, pair.m_Name, location.m_Position, location.m_Rotation, pair.m_Equipment, data);
|
||||
|
||||
npc->SetVar<std::vector<std::string>>(u"chats", pair.m_Phrases);
|
||||
npc->SetVar<std::vector<std::string>>(u"chats", pair.m_Phrases);
|
||||
|
||||
auto* scriptComponent = npc->GetComponent<ScriptComponent>();
|
||||
auto* scriptComponent = npc->GetComponent<ScriptComponent>();
|
||||
|
||||
if (scriptComponent != nullptr) {
|
||||
scriptComponent->SetScript(pair.m_Script);
|
||||
scriptComponent->SetSerialized(false);
|
||||
if (scriptComponent != nullptr) {
|
||||
scriptComponent->SetScript(pair.m_Script);
|
||||
scriptComponent->SetSerialized(false);
|
||||
|
||||
for (const auto& pair : pair.m_Flags) {
|
||||
npc->SetVar<bool>(GeneralUtils::ASCIIToUTF16(pair.first), pair.second);
|
||||
}
|
||||
}
|
||||
for (const auto& pair : pair.m_Flags) {
|
||||
npc->SetVar<bool>(GeneralUtils::ASCIIToUTF16(pair.first), pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
SetupNPCTalk(npc);
|
||||
}
|
||||
SetupNPCTalk(npc);
|
||||
}
|
||||
|
||||
if (zoneID == 1200) {
|
||||
{
|
||||
EntityInfo info;
|
||||
info.lot = 8139;
|
||||
info.pos = { 259.5f, 246.4f, -705.2f };
|
||||
info.rot = { 0.0f, 0.0f, 1.0f, 0.0f };
|
||||
info.spawnerID = EntityManager::Instance()->GetZoneControlEntity()->GetObjectID();
|
||||
if (zoneID == 1200) {
|
||||
{
|
||||
EntityInfo info;
|
||||
info.lot = 8139;
|
||||
info.pos = { 259.5f, 246.4f, -705.2f };
|
||||
info.rot = { 0.0f, 0.0f, 1.0f, 0.0f };
|
||||
info.spawnerID = EntityManager::Instance()->GetZoneControlEntity()->GetObjectID();
|
||||
|
||||
info.settings = { new LDFData<bool>(u"hasCustomText", true),
|
||||
new LDFData<std::string>(u"customText", ParseMarkdown("./vanity/TESTAMENT.md")) };
|
||||
info.settings = { new LDFData<bool>(u"hasCustomText", true),
|
||||
new LDFData<std::string>(u"customText", ParseMarkdown("./vanity/TESTAMENT.md")) };
|
||||
|
||||
auto* entity = EntityManager::Instance()->CreateEntity(info);
|
||||
auto* entity = EntityManager::Instance()->CreateEntity(info);
|
||||
|
||||
EntityManager::Instance()->ConstructEntity(entity);
|
||||
}
|
||||
}
|
||||
EntityManager::Instance()->ConstructEntity(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Entity* VanityUtilities::SpawnNPC(LOT lot, const std::string& name, const NiPoint3& position,
|
||||
const NiQuaternion& rotation, const std::vector<LOT>& inventory, const std::vector<LDFBaseData*>& ldf)
|
||||
{
|
||||
EntityInfo info;
|
||||
info.lot = lot;
|
||||
info.pos = position;
|
||||
info.rot = rotation;
|
||||
info.spawnerID = EntityManager::Instance()->GetZoneControlEntity()->GetObjectID();
|
||||
info.settings = ldf;
|
||||
const NiQuaternion& rotation, const std::vector<LOT>& inventory, const std::vector<LDFBaseData*>& ldf) {
|
||||
EntityInfo info;
|
||||
info.lot = lot;
|
||||
info.pos = position;
|
||||
info.rot = rotation;
|
||||
info.spawnerID = EntityManager::Instance()->GetZoneControlEntity()->GetObjectID();
|
||||
info.settings = ldf;
|
||||
|
||||
auto* entity = EntityManager::Instance()->CreateEntity(info);
|
||||
entity->SetVar(u"npcName", name);
|
||||
auto* entity = EntityManager::Instance()->CreateEntity(info);
|
||||
entity->SetVar(u"npcName", name);
|
||||
|
||||
auto* inventoryComponent = entity->GetComponent<InventoryComponent>();
|
||||
auto* inventoryComponent = entity->GetComponent<InventoryComponent>();
|
||||
|
||||
if (inventoryComponent != nullptr) {
|
||||
inventoryComponent->SetNPCItems(inventory);
|
||||
}
|
||||
if (inventoryComponent != nullptr) {
|
||||
inventoryComponent->SetNPCItems(inventory);
|
||||
}
|
||||
|
||||
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
|
||||
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
|
||||
|
||||
if (destroyableComponent != nullptr) {
|
||||
destroyableComponent->SetIsGMImmune(true);
|
||||
destroyableComponent->SetMaxHealth(0);
|
||||
destroyableComponent->SetHealth(0);
|
||||
}
|
||||
if (destroyableComponent != nullptr) {
|
||||
destroyableComponent->SetIsGMImmune(true);
|
||||
destroyableComponent->SetMaxHealth(0);
|
||||
destroyableComponent->SetHealth(0);
|
||||
}
|
||||
|
||||
EntityManager::Instance()->ConstructEntity(entity);
|
||||
EntityManager::Instance()->ConstructEntity(entity);
|
||||
|
||||
return entity;
|
||||
return entity;
|
||||
}
|
||||
|
||||
void VanityUtilities::ParseXML(const std::string& file)
|
||||
{
|
||||
// Read the entire file
|
||||
std::ifstream xmlFile(file);
|
||||
std::string xml((std::istreambuf_iterator<char>(xmlFile)), std::istreambuf_iterator<char>());
|
||||
void VanityUtilities::ParseXML(const std::string& file) {
|
||||
// Read the entire file
|
||||
std::ifstream xmlFile(file);
|
||||
std::string xml((std::istreambuf_iterator<char>(xmlFile)), std::istreambuf_iterator<char>());
|
||||
|
||||
// Parse the XML
|
||||
tinyxml2::XMLDocument doc;
|
||||
doc.Parse(xml.c_str(), xml.size());
|
||||
// Parse the XML
|
||||
tinyxml2::XMLDocument doc;
|
||||
doc.Parse(xml.c_str(), xml.size());
|
||||
|
||||
// Read the NPCs
|
||||
auto* npcs = doc.FirstChildElement("npcs");
|
||||
// Read the NPCs
|
||||
auto* npcs = doc.FirstChildElement("npcs");
|
||||
|
||||
if (npcs == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPCs");
|
||||
return;
|
||||
}
|
||||
if (npcs == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPCs");
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto* party = npcs->FirstChildElement("party"); party != nullptr; party = party->NextSiblingElement("party")) {
|
||||
// Get 'zone' as uint32_t and 'chance' as float
|
||||
uint32_t zone = 0;
|
||||
float chance = 0.0f;
|
||||
for (auto* party = npcs->FirstChildElement("party"); party != nullptr; party = party->NextSiblingElement("party")) {
|
||||
// Get 'zone' as uint32_t and 'chance' as float
|
||||
uint32_t zone = 0;
|
||||
float chance = 0.0f;
|
||||
|
||||
if (party->Attribute("zone") != nullptr) {
|
||||
zone = std::stoul(party->Attribute("zone"));
|
||||
}
|
||||
if (party->Attribute("zone") != nullptr) {
|
||||
zone = std::stoul(party->Attribute("zone"));
|
||||
}
|
||||
|
||||
if (party->Attribute("chance") != nullptr) {
|
||||
chance = std::stof(party->Attribute("chance"));
|
||||
}
|
||||
if (party->Attribute("chance") != nullptr) {
|
||||
chance = std::stof(party->Attribute("chance"));
|
||||
}
|
||||
|
||||
VanityParty partyInfo;
|
||||
partyInfo.m_Zone = zone;
|
||||
partyInfo.m_Chance = chance;
|
||||
VanityParty partyInfo;
|
||||
partyInfo.m_Zone = zone;
|
||||
partyInfo.m_Chance = chance;
|
||||
|
||||
auto* locations = party->FirstChildElement("locations");
|
||||
auto* locations = party->FirstChildElement("locations");
|
||||
|
||||
if (locations == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse party locations");
|
||||
continue;
|
||||
}
|
||||
if (locations == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse party locations");
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto* location = locations->FirstChildElement("location"); location != nullptr;
|
||||
location = location->NextSiblingElement("location")) {
|
||||
// Get the location data
|
||||
auto* x = location->Attribute("x");
|
||||
auto* y = location->Attribute("y");
|
||||
auto* z = location->Attribute("z");
|
||||
auto* rw = location->Attribute("rw");
|
||||
auto* rx = location->Attribute("rx");
|
||||
auto* ry = location->Attribute("ry");
|
||||
auto* rz = location->Attribute("rz");
|
||||
for (auto* location = locations->FirstChildElement("location"); location != nullptr;
|
||||
location = location->NextSiblingElement("location")) {
|
||||
// Get the location data
|
||||
auto* x = location->Attribute("x");
|
||||
auto* y = location->Attribute("y");
|
||||
auto* z = location->Attribute("z");
|
||||
auto* rw = location->Attribute("rw");
|
||||
auto* rx = location->Attribute("rx");
|
||||
auto* ry = location->Attribute("ry");
|
||||
auto* rz = location->Attribute("rz");
|
||||
|
||||
if (x == nullptr || y == nullptr || z == nullptr || rw == nullptr || rx == nullptr || ry == nullptr
|
||||
|| rz == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse party location data");
|
||||
continue;
|
||||
}
|
||||
if (x == nullptr || y == nullptr || z == nullptr || rw == nullptr || rx == nullptr || ry == nullptr
|
||||
|| rz == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse party location data");
|
||||
continue;
|
||||
}
|
||||
|
||||
VanityNPCLocation locationData;
|
||||
locationData.m_Position = { std::stof(x), std::stof(y), std::stof(z) };
|
||||
locationData.m_Rotation = { std::stof(rw), std::stof(rx), std::stof(ry), std::stof(rz) };
|
||||
locationData.m_Chance = 1.0f;
|
||||
VanityNPCLocation locationData;
|
||||
locationData.m_Position = { std::stof(x), std::stof(y), std::stof(z) };
|
||||
locationData.m_Rotation = { std::stof(rw), std::stof(rx), std::stof(ry), std::stof(rz) };
|
||||
locationData.m_Chance = 1.0f;
|
||||
|
||||
partyInfo.m_Locations.push_back(locationData);
|
||||
}
|
||||
partyInfo.m_Locations.push_back(locationData);
|
||||
}
|
||||
|
||||
m_Parties.push_back(partyInfo);
|
||||
}
|
||||
m_Parties.push_back(partyInfo);
|
||||
}
|
||||
|
||||
auto* partyPhrases = npcs->FirstChildElement("partyphrases");
|
||||
auto* partyPhrases = npcs->FirstChildElement("partyphrases");
|
||||
|
||||
if (partyPhrases == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse party phrases");
|
||||
return;
|
||||
}
|
||||
if (partyPhrases == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse party phrases");
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto* phrase = partyPhrases->FirstChildElement("phrase"); phrase != nullptr;
|
||||
phrase = phrase->NextSiblingElement("phrase")) {
|
||||
// Get the phrase
|
||||
auto* text = phrase->GetText();
|
||||
for (auto* phrase = partyPhrases->FirstChildElement("phrase"); phrase != nullptr;
|
||||
phrase = phrase->NextSiblingElement("phrase")) {
|
||||
// Get the phrase
|
||||
auto* text = phrase->GetText();
|
||||
|
||||
if (text == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse party phrase");
|
||||
continue;
|
||||
}
|
||||
if (text == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse party phrase");
|
||||
continue;
|
||||
}
|
||||
|
||||
m_PartyPhrases.push_back(text);
|
||||
}
|
||||
m_PartyPhrases.push_back(text);
|
||||
}
|
||||
|
||||
for (auto* npc = npcs->FirstChildElement("npc"); npc != nullptr; npc = npc->NextSiblingElement("npc")) {
|
||||
// Get the NPC name
|
||||
auto* name = npc->Attribute("name");
|
||||
for (auto* npc = npcs->FirstChildElement("npc"); npc != nullptr; npc = npc->NextSiblingElement("npc")) {
|
||||
// Get the NPC name
|
||||
auto* name = npc->Attribute("name");
|
||||
|
||||
if (name == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC name");
|
||||
continue;
|
||||
}
|
||||
if (name == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC name");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the NPC lot
|
||||
auto* lot = npc->Attribute("lot");
|
||||
// Get the NPC lot
|
||||
auto* lot = npc->Attribute("lot");
|
||||
|
||||
if (lot == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC lot");
|
||||
continue;
|
||||
}
|
||||
if (lot == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC lot");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the equipment
|
||||
auto* equipment = npc->FirstChildElement("equipment");
|
||||
// Get the equipment
|
||||
auto* equipment = npc->FirstChildElement("equipment");
|
||||
|
||||
if (equipment == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC equipment");
|
||||
continue;
|
||||
}
|
||||
if (equipment == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC equipment");
|
||||
continue;
|
||||
}
|
||||
|
||||
auto* text = equipment->GetText();
|
||||
auto* text = equipment->GetText();
|
||||
|
||||
std::vector<LOT> inventory;
|
||||
std::vector<LOT> inventory;
|
||||
|
||||
if (text != nullptr) {
|
||||
std::string equipmentString(text);
|
||||
if (text != nullptr) {
|
||||
std::string equipmentString(text);
|
||||
|
||||
std::vector<std::string> splitEquipment = GeneralUtils::SplitString(equipmentString, ',');
|
||||
std::vector<std::string> splitEquipment = GeneralUtils::SplitString(equipmentString, ',');
|
||||
|
||||
for (auto& item : splitEquipment) {
|
||||
inventory.push_back(std::stoi(item));
|
||||
}
|
||||
}
|
||||
for (auto& item : splitEquipment) {
|
||||
inventory.push_back(std::stoi(item));
|
||||
}
|
||||
}
|
||||
|
||||
// Get the phrases
|
||||
auto* phrases = npc->FirstChildElement("phrases");
|
||||
// Get the phrases
|
||||
auto* phrases = npc->FirstChildElement("phrases");
|
||||
|
||||
if (phrases == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC phrases");
|
||||
continue;
|
||||
}
|
||||
if (phrases == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC phrases");
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<std::string> phraseList;
|
||||
std::vector<std::string> phraseList;
|
||||
|
||||
for (auto* phrase = phrases->FirstChildElement("phrase"); phrase != nullptr;
|
||||
phrase = phrase->NextSiblingElement("phrase")) {
|
||||
// Get the phrase
|
||||
auto* text = phrase->GetText();
|
||||
for (auto* phrase = phrases->FirstChildElement("phrase"); phrase != nullptr;
|
||||
phrase = phrase->NextSiblingElement("phrase")) {
|
||||
// Get the phrase
|
||||
auto* text = phrase->GetText();
|
||||
|
||||
if (text == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC phrase");
|
||||
continue;
|
||||
}
|
||||
if (text == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC phrase");
|
||||
continue;
|
||||
}
|
||||
|
||||
phraseList.push_back(text);
|
||||
}
|
||||
phraseList.push_back(text);
|
||||
}
|
||||
|
||||
// Get the script
|
||||
auto* scriptElement = npc->FirstChildElement("script");
|
||||
// Get the script
|
||||
auto* scriptElement = npc->FirstChildElement("script");
|
||||
|
||||
std::string scriptName;
|
||||
std::string scriptName;
|
||||
|
||||
if (scriptElement != nullptr) {
|
||||
auto* scriptNameAttribute = scriptElement->Attribute("name");
|
||||
if (scriptElement != nullptr) {
|
||||
auto* scriptNameAttribute = scriptElement->Attribute("name");
|
||||
|
||||
if (scriptNameAttribute == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC script name");
|
||||
continue;
|
||||
}
|
||||
if (scriptNameAttribute == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC script name");
|
||||
continue;
|
||||
}
|
||||
|
||||
scriptName = scriptNameAttribute;
|
||||
}
|
||||
scriptName = scriptNameAttribute;
|
||||
}
|
||||
|
||||
VanityNPC npcData;
|
||||
npcData.m_Name = name;
|
||||
npcData.m_LOT = std::stoi(lot);
|
||||
npcData.m_Equipment = inventory;
|
||||
npcData.m_Phrases = phraseList;
|
||||
npcData.m_Script = scriptName;
|
||||
VanityNPC npcData;
|
||||
npcData.m_Name = name;
|
||||
npcData.m_LOT = std::stoi(lot);
|
||||
npcData.m_Equipment = inventory;
|
||||
npcData.m_Phrases = phraseList;
|
||||
npcData.m_Script = scriptName;
|
||||
|
||||
// Get flags
|
||||
auto* flags = npc->FirstChildElement("flags");
|
||||
// Get flags
|
||||
auto* flags = npc->FirstChildElement("flags");
|
||||
|
||||
if (flags != nullptr) {
|
||||
for (auto* flag = flags->FirstChildElement("flag"); flag != nullptr;
|
||||
flag = flag->NextSiblingElement("flag")) {
|
||||
// Get the flag name
|
||||
auto* name = flag->Attribute("name");
|
||||
if (flags != nullptr) {
|
||||
for (auto* flag = flags->FirstChildElement("flag"); flag != nullptr;
|
||||
flag = flag->NextSiblingElement("flag")) {
|
||||
// Get the flag name
|
||||
auto* name = flag->Attribute("name");
|
||||
|
||||
if (name == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC flag name");
|
||||
continue;
|
||||
}
|
||||
if (name == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC flag name");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the flag value
|
||||
auto* value = flag->Attribute("value");
|
||||
// Get the flag value
|
||||
auto* value = flag->Attribute("value");
|
||||
|
||||
if (value == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC flag value");
|
||||
continue;
|
||||
}
|
||||
if (value == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC flag value");
|
||||
continue;
|
||||
}
|
||||
|
||||
npcData.m_Flags[name] = std::stoi(value);
|
||||
}
|
||||
}
|
||||
npcData.m_Flags[name] = std::stoi(value);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the zones
|
||||
for (auto* zone = npc->FirstChildElement("zone"); zone != nullptr; zone = zone->NextSiblingElement("zone")) {
|
||||
// Get the zone ID
|
||||
auto* zoneID = zone->Attribute("id");
|
||||
// Get the zones
|
||||
for (auto* zone = npc->FirstChildElement("zone"); zone != nullptr; zone = zone->NextSiblingElement("zone")) {
|
||||
// Get the zone ID
|
||||
auto* zoneID = zone->Attribute("id");
|
||||
|
||||
if (zoneID == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC zone ID");
|
||||
continue;
|
||||
}
|
||||
if (zoneID == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC zone ID");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the locations
|
||||
auto* locations = zone->FirstChildElement("locations");
|
||||
// Get the locations
|
||||
auto* locations = zone->FirstChildElement("locations");
|
||||
|
||||
if (locations == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC locations");
|
||||
continue;
|
||||
}
|
||||
if (locations == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC locations");
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto* location = locations->FirstChildElement("location"); location != nullptr;
|
||||
location = location->NextSiblingElement("location")) {
|
||||
// Get the location data
|
||||
auto* x = location->Attribute("x");
|
||||
auto* y = location->Attribute("y");
|
||||
auto* z = location->Attribute("z");
|
||||
auto* rw = location->Attribute("rw");
|
||||
auto* rx = location->Attribute("rx");
|
||||
auto* ry = location->Attribute("ry");
|
||||
auto* rz = location->Attribute("rz");
|
||||
for (auto* location = locations->FirstChildElement("location"); location != nullptr;
|
||||
location = location->NextSiblingElement("location")) {
|
||||
// Get the location data
|
||||
auto* x = location->Attribute("x");
|
||||
auto* y = location->Attribute("y");
|
||||
auto* z = location->Attribute("z");
|
||||
auto* rw = location->Attribute("rw");
|
||||
auto* rx = location->Attribute("rx");
|
||||
auto* ry = location->Attribute("ry");
|
||||
auto* rz = location->Attribute("rz");
|
||||
|
||||
if (x == nullptr || y == nullptr || z == nullptr || rw == nullptr || rx == nullptr || ry == nullptr
|
||||
|| rz == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC location data");
|
||||
continue;
|
||||
}
|
||||
if (x == nullptr || y == nullptr || z == nullptr || rw == nullptr || rx == nullptr || ry == nullptr
|
||||
|| rz == nullptr) {
|
||||
Game::logger->Log("VanityUtilities", "Failed to parse NPC location data");
|
||||
continue;
|
||||
}
|
||||
|
||||
VanityNPCLocation locationData;
|
||||
locationData.m_Position = { std::stof(x), std::stof(y), std::stof(z) };
|
||||
locationData.m_Rotation = { std::stof(rw), std::stof(rx), std::stof(ry), std::stof(rz) };
|
||||
locationData.m_Chance = 1.0f;
|
||||
VanityNPCLocation locationData;
|
||||
locationData.m_Position = { std::stof(x), std::stof(y), std::stof(z) };
|
||||
locationData.m_Rotation = { std::stof(rw), std::stof(rx), std::stof(ry), std::stof(rz) };
|
||||
locationData.m_Chance = 1.0f;
|
||||
|
||||
if (location->Attribute("chance") != nullptr) {
|
||||
locationData.m_Chance = std::stof(location->Attribute("chance"));
|
||||
}
|
||||
if (location->Attribute("chance") != nullptr) {
|
||||
locationData.m_Chance = std::stof(location->Attribute("chance"));
|
||||
}
|
||||
|
||||
const auto& it = npcData.m_Locations.find(std::stoi(zoneID));
|
||||
const auto& it = npcData.m_Locations.find(std::stoi(zoneID));
|
||||
|
||||
if (it != npcData.m_Locations.end()) {
|
||||
it->second.push_back(locationData);
|
||||
} else {
|
||||
std::vector<VanityNPCLocation> locations;
|
||||
locations.push_back(locationData);
|
||||
npcData.m_Locations.insert(std::make_pair(std::stoi(zoneID), locations));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (it != npcData.m_Locations.end()) {
|
||||
it->second.push_back(locationData);
|
||||
} else {
|
||||
std::vector<VanityNPCLocation> locations;
|
||||
locations.push_back(locationData);
|
||||
npcData.m_Locations.insert(std::make_pair(std::stoi(zoneID), locations));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_NPCs.push_back(npcData);
|
||||
}
|
||||
m_NPCs.push_back(npcData);
|
||||
}
|
||||
}
|
||||
|
||||
VanityNPC* VanityUtilities::GetNPC(const std::string& name)
|
||||
{
|
||||
for (size_t i = 0; i < m_NPCs.size(); i++) {
|
||||
if (m_NPCs[i].m_Name == name) {
|
||||
return &m_NPCs[i];
|
||||
}
|
||||
}
|
||||
VanityNPC* VanityUtilities::GetNPC(const std::string& name) {
|
||||
for (size_t i = 0; i < m_NPCs.size(); i++) {
|
||||
if (m_NPCs[i].m_Name == name) {
|
||||
return &m_NPCs[i];
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string VanityUtilities::ParseMarkdown(const std::string& file)
|
||||
{
|
||||
// This function will read the file and return the content formatted as ASCII text.
|
||||
std::string VanityUtilities::ParseMarkdown(const std::string& file) {
|
||||
// This function will read the file and return the content formatted as ASCII text.
|
||||
|
||||
// Read the file into a string
|
||||
std::ifstream t(file);
|
||||
// Read the file into a string
|
||||
std::ifstream t(file);
|
||||
|
||||
// If the file does not exist, return an empty string.
|
||||
if (!t.good()) {
|
||||
return "";
|
||||
}
|
||||
// If the file does not exist, return an empty string.
|
||||
if (!t.good()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::stringstream buffer;
|
||||
buffer << t.rdbuf();
|
||||
std::string fileContents = buffer.str();
|
||||
std::stringstream buffer;
|
||||
buffer << t.rdbuf();
|
||||
std::string fileContents = buffer.str();
|
||||
|
||||
// Loop through all lines in the file.
|
||||
// Replace all instances of the markdown syntax with the corresponding HTML.
|
||||
// Only care about headers
|
||||
std::stringstream output;
|
||||
std::string line;
|
||||
std::stringstream ss;
|
||||
ss << fileContents;
|
||||
while (std::getline(ss, line)) {
|
||||
// Loop through all lines in the file.
|
||||
// Replace all instances of the markdown syntax with the corresponding HTML.
|
||||
// Only care about headers
|
||||
std::stringstream output;
|
||||
std::string line;
|
||||
std::stringstream ss;
|
||||
ss << fileContents;
|
||||
while (std::getline(ss, line)) {
|
||||
|
||||
#define TOSTRING(x) #x
|
||||
#define STRINGIFY(x) TOSTRING(x)
|
||||
|
||||
// Replace "__TIMESTAMP__" with the __TIMESTAMP__
|
||||
GeneralUtils::ReplaceInString(line, "__TIMESTAMP__", __TIMESTAMP__);
|
||||
// Replace "__VERSION__" wit'h the PROJECT_VERSION
|
||||
GeneralUtils::ReplaceInString(line, "__VERSION__", STRINGIFY(PROJECT_VERSION));
|
||||
// Replace "__SOURCE__" with SOURCE
|
||||
GeneralUtils::ReplaceInString(line, "__SOURCE__", Game::config->GetValue("source"));
|
||||
// Replace "__LICENSE__" with LICENSE
|
||||
GeneralUtils::ReplaceInString(line, "__LICENSE__", STRINGIFY(LICENSE));
|
||||
// Replace "__TIMESTAMP__" with the __TIMESTAMP__
|
||||
GeneralUtils::ReplaceInString(line, "__TIMESTAMP__", __TIMESTAMP__);
|
||||
// Replace "__VERSION__" wit'h the PROJECT_VERSION
|
||||
GeneralUtils::ReplaceInString(line, "__VERSION__", STRINGIFY(PROJECT_VERSION));
|
||||
// Replace "__SOURCE__" with SOURCE
|
||||
GeneralUtils::ReplaceInString(line, "__SOURCE__", Game::config->GetValue("source"));
|
||||
// Replace "__LICENSE__" with LICENSE
|
||||
GeneralUtils::ReplaceInString(line, "__LICENSE__", STRINGIFY(LICENSE));
|
||||
|
||||
if (line.find("##") != std::string::npos) {
|
||||
// Add "<font size='18' color='#000000'>" before the header
|
||||
output << "<font size=\"14\" color=\"#000000\">";
|
||||
// Add the header without the markdown syntax
|
||||
output << line.substr(3);
|
||||
if (line.find("##") != std::string::npos) {
|
||||
// Add "<font size='18' color='#000000'>" before the header
|
||||
output << "<font size=\"14\" color=\"#000000\">";
|
||||
// Add the header without the markdown syntax
|
||||
output << line.substr(3);
|
||||
|
||||
output << "</font>";
|
||||
} else if (line.find("#") != std::string::npos) {
|
||||
// Add "<font size='18' color='#000000'>" before the header
|
||||
output << "<font size=\"18\" color=\"#000000\">";
|
||||
// Add the header without the markdown syntax
|
||||
output << line.substr(2);
|
||||
output << "</font>";
|
||||
} else if (line.find("#") != std::string::npos) {
|
||||
// Add "<font size='18' color='#000000'>" before the header
|
||||
output << "<font size=\"18\" color=\"#000000\">";
|
||||
// Add the header without the markdown syntax
|
||||
output << line.substr(2);
|
||||
|
||||
output << "</font>";
|
||||
} else {
|
||||
output << line;
|
||||
}
|
||||
output << "</font>";
|
||||
} else {
|
||||
output << line;
|
||||
}
|
||||
|
||||
output << "\n";
|
||||
}
|
||||
output << "\n";
|
||||
}
|
||||
|
||||
return output.str();
|
||||
return output.str();
|
||||
}
|
||||
|
||||
void VanityUtilities::SetupNPCTalk(Entity* npc)
|
||||
{
|
||||
npc->AddCallbackTimer(15.0f, [npc]() { NPCTalk(npc); });
|
||||
void VanityUtilities::SetupNPCTalk(Entity* npc) {
|
||||
npc->AddCallbackTimer(15.0f, [npc]() { NPCTalk(npc); });
|
||||
|
||||
npc->SetProximityRadius(20.0f, "talk");
|
||||
npc->SetProximityRadius(20.0f, "talk");
|
||||
}
|
||||
|
||||
void VanityUtilities::NPCTalk(Entity* npc)
|
||||
{
|
||||
auto* proximityMonitorComponent = npc->GetComponent<ProximityMonitorComponent>();
|
||||
void VanityUtilities::NPCTalk(Entity* npc) {
|
||||
auto* proximityMonitorComponent = npc->GetComponent<ProximityMonitorComponent>();
|
||||
|
||||
if (!proximityMonitorComponent->GetProximityObjects("talk").empty()) {
|
||||
const auto& chats = npc->GetVar<std::vector<std::string>>(u"chats");
|
||||
if (!proximityMonitorComponent->GetProximityObjects("talk").empty()) {
|
||||
const auto& chats = npc->GetVar<std::vector<std::string>>(u"chats");
|
||||
|
||||
if (chats.empty()) {
|
||||
return;
|
||||
}
|
||||
if (chats.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& selected
|
||||
= chats[GeneralUtils::GenerateRandomNumber<int32_t>(0, static_cast<int32_t>(chats.size() - 1))];
|
||||
const auto& selected
|
||||
= chats[GeneralUtils::GenerateRandomNumber<int32_t>(0, static_cast<int32_t>(chats.size() - 1))];
|
||||
|
||||
GameMessages::SendNotifyClientZoneObject(
|
||||
npc->GetObjectID(), u"sendToclient_bubble", 0, 0, npc->GetObjectID(), selected, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
GameMessages::SendNotifyClientZoneObject(
|
||||
npc->GetObjectID(), u"sendToclient_bubble", 0, 0, npc->GetObjectID(), selected, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(npc);
|
||||
EntityManager::Instance()->SerializeEntity(npc);
|
||||
|
||||
const float nextTime = GeneralUtils::GenerateRandomNumber<float>(15, 60);
|
||||
const float nextTime = GeneralUtils::GenerateRandomNumber<float>(15, 60);
|
||||
|
||||
npc->AddCallbackTimer(nextTime, [npc]() { NPCTalk(npc); });
|
||||
npc->AddCallbackTimer(nextTime, [npc]() { NPCTalk(npc); });
|
||||
}
|
||||
|
@@ -6,61 +6,61 @@
|
||||
|
||||
struct VanityNPCLocation
|
||||
{
|
||||
float m_Chance = 1.0f;
|
||||
NiPoint3 m_Position;
|
||||
NiQuaternion m_Rotation;
|
||||
float m_Chance = 1.0f;
|
||||
NiPoint3 m_Position;
|
||||
NiQuaternion m_Rotation;
|
||||
};
|
||||
|
||||
struct VanityNPC
|
||||
{
|
||||
std::string m_Name;
|
||||
LOT m_LOT;
|
||||
std::vector<LOT> m_Equipment;
|
||||
std::vector<std::string> m_Phrases;
|
||||
std::string m_Script;
|
||||
std::map<std::string, bool> m_Flags;
|
||||
std::map<uint32_t, std::vector<VanityNPCLocation>> m_Locations;
|
||||
std::string m_Name;
|
||||
LOT m_LOT;
|
||||
std::vector<LOT> m_Equipment;
|
||||
std::vector<std::string> m_Phrases;
|
||||
std::string m_Script;
|
||||
std::map<std::string, bool> m_Flags;
|
||||
std::map<uint32_t, std::vector<VanityNPCLocation>> m_Locations;
|
||||
};
|
||||
|
||||
struct VanityParty
|
||||
{
|
||||
uint32_t m_Zone;
|
||||
float m_Chance = 1.0f;
|
||||
std::vector<VanityNPCLocation> m_Locations;
|
||||
uint32_t m_Zone;
|
||||
float m_Chance = 1.0f;
|
||||
std::vector<VanityNPCLocation> m_Locations;
|
||||
};
|
||||
|
||||
class VanityUtilities
|
||||
{
|
||||
public:
|
||||
static void SpawnVanity();
|
||||
static void SpawnVanity();
|
||||
|
||||
static Entity* SpawnNPC(
|
||||
LOT lot,
|
||||
const std::string& name,
|
||||
const NiPoint3& position,
|
||||
const NiQuaternion& rotation,
|
||||
const std::vector<LOT>& inventory,
|
||||
const std::vector<LDFBaseData*>& ldf
|
||||
);
|
||||
static Entity* SpawnNPC(
|
||||
LOT lot,
|
||||
const std::string& name,
|
||||
const NiPoint3& position,
|
||||
const NiQuaternion& rotation,
|
||||
const std::vector<LOT>& inventory,
|
||||
const std::vector<LDFBaseData*>& ldf
|
||||
);
|
||||
|
||||
static std::string ParseMarkdown(
|
||||
const std::string& file
|
||||
);
|
||||
static std::string ParseMarkdown(
|
||||
const std::string& file
|
||||
);
|
||||
|
||||
static void ParseXML(
|
||||
const std::string& file
|
||||
);
|
||||
static void ParseXML(
|
||||
const std::string& file
|
||||
);
|
||||
|
||||
static VanityNPC* GetNPC(const std::string& name);
|
||||
static VanityNPC* GetNPC(const std::string& name);
|
||||
|
||||
private:
|
||||
static void SetupNPCTalk(Entity* npc);
|
||||
static void SetupNPCTalk(Entity* npc);
|
||||
|
||||
static void NPCTalk(Entity* npc);
|
||||
static void NPCTalk(Entity* npc);
|
||||
|
||||
static std::vector<VanityNPC> m_NPCs;
|
||||
static std::vector<VanityNPC> m_NPCs;
|
||||
|
||||
static std::vector<VanityParty> m_Parties;
|
||||
static std::vector<VanityParty> m_Parties;
|
||||
|
||||
static std::vector<std::string> m_PartyPhrases;
|
||||
static std::vector<std::string> m_PartyPhrases;
|
||||
};
|
||||
|
@@ -11,71 +11,71 @@
|
||||
#include "dConfig.h"
|
||||
|
||||
dLocale::dLocale() {
|
||||
if (Game::config->GetValue("locale_enabled") != "1") {
|
||||
return;
|
||||
}
|
||||
if (Game::config->GetValue("locale_enabled") != "1") {
|
||||
return;
|
||||
}
|
||||
|
||||
std::ifstream file(m_LocalePath);
|
||||
std::ifstream file(m_LocalePath);
|
||||
|
||||
if (!file.good()) {
|
||||
return;
|
||||
}
|
||||
if (!file.good()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::stringstream data;
|
||||
data << file.rdbuf();
|
||||
std::stringstream data;
|
||||
data << file.rdbuf();
|
||||
|
||||
if (data.str().empty()) {
|
||||
return;
|
||||
}
|
||||
if (data.str().empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* doc = new tinyxml2::XMLDocument();
|
||||
auto* doc = new tinyxml2::XMLDocument();
|
||||
|
||||
if (doc == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (doc == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (doc->Parse(data.str().c_str(), data.str().size()) != 0) {
|
||||
return;
|
||||
}
|
||||
if (doc->Parse(data.str().c_str(), data.str().size()) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::hash<std::string> hash;
|
||||
std::hash<std::string> hash;
|
||||
|
||||
auto* localization = doc->FirstChildElement("localization");
|
||||
auto* phrases = localization->FirstChildElement("phrases");
|
||||
auto* localization = doc->FirstChildElement("localization");
|
||||
auto* phrases = localization->FirstChildElement("phrases");
|
||||
|
||||
auto* phrase = phrases->FirstChildElement("phrase");
|
||||
auto* phrase = phrases->FirstChildElement("phrase");
|
||||
|
||||
while (phrase != nullptr) {
|
||||
// Add the phrase hash to the vector
|
||||
m_Phrases.push_back(hash(phrase->Attribute("id")));
|
||||
phrase = phrase->NextSiblingElement("phrase");
|
||||
}
|
||||
while (phrase != nullptr) {
|
||||
// Add the phrase hash to the vector
|
||||
m_Phrases.push_back(hash(phrase->Attribute("id")));
|
||||
phrase = phrase->NextSiblingElement("phrase");
|
||||
}
|
||||
|
||||
file.close();
|
||||
file.close();
|
||||
|
||||
delete doc;
|
||||
delete doc;
|
||||
}
|
||||
|
||||
dLocale::~dLocale() = default;
|
||||
|
||||
std::string dLocale::GetTemplate(const std::string& phraseID) {
|
||||
return "%[" + phraseID + "]";
|
||||
return "%[" + phraseID + "]";
|
||||
}
|
||||
|
||||
bool dLocale::HasPhrase(const std::string& phraseID) {
|
||||
if (Game::config->GetValue("locale_enabled") != "1") {
|
||||
return true;
|
||||
}
|
||||
if (Game::config->GetValue("locale_enabled") != "1") {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Compute the hash and see if it's in the vector
|
||||
std::hash<std::string> hash;
|
||||
std::size_t hashValue = hash(phraseID);
|
||||
return std::find(m_Phrases.begin(), m_Phrases.end(), hashValue) != m_Phrases.end();
|
||||
// Compute the hash and see if it's in the vector
|
||||
std::hash<std::string> hash;
|
||||
std::size_t hashValue = hash(phraseID);
|
||||
return std::find(m_Phrases.begin(), m_Phrases.end(), hashValue) != m_Phrases.end();
|
||||
}
|
||||
|
||||
/*std::string dLocale::GetPhrase(const std::string& phraseID) {
|
||||
if (m_Phrases.find(phraseID) == m_Phrases.end()) {
|
||||
return "";
|
||||
}
|
||||
return m_Phrases[phraseID];
|
||||
}*/
|
||||
if (m_Phrases.find(phraseID) == m_Phrases.end()) {
|
||||
return "";
|
||||
}
|
||||
return m_Phrases[phraseID];
|
||||
}*/
|
||||
|
@@ -6,14 +6,14 @@
|
||||
|
||||
class dLocale {
|
||||
public:
|
||||
dLocale();
|
||||
~dLocale();
|
||||
static std::string GetTemplate(const std::string& phraseID);
|
||||
bool HasPhrase(const std::string& phraseID);
|
||||
//std::string GetPhrase(const std::string& phraseID);
|
||||
dLocale();
|
||||
~dLocale();
|
||||
static std::string GetTemplate(const std::string& phraseID);
|
||||
bool HasPhrase(const std::string& phraseID);
|
||||
//std::string GetPhrase(const std::string& phraseID);
|
||||
|
||||
private:
|
||||
std::string m_LocalePath = "./locale/locale.xml";
|
||||
std::string m_Locale = "en_US"; // TODO: add to config
|
||||
std::vector<std::size_t> m_Phrases;
|
||||
};
|
||||
std::string m_LocalePath = "./locale/locale.xml";
|
||||
std::string m_Locale = "en_US"; // TODO: add to config
|
||||
std::vector<std::size_t> m_Phrases;
|
||||
};
|
||||
|
Reference in New Issue
Block a user