Compare commits

..

5 Commits

Author SHA1 Message Date
neru 2bf8407640 fix: use config values from default member initialization
Build / build (push) Successful in 3m17s
2026-04-11 16:00:46 -03:00
neru a8b5e0148f style: add additional comments
Build / build (push) Successful in 3m17s
2026-04-11 15:51:11 -03:00
neru 50413eb420 feat: fix bloodweb for spoofed inventories 2026-04-11 15:50:51 -03:00
neru ea49c39e53 feat: define PLACEHOLDER_ITEMID 2026-04-11 15:43:29 -03:00
neru f599a9a648 fix: remove early return 2026-04-11 15:43:18 -03:00
2 changed files with 46 additions and 17 deletions
+44 -15
View File
@@ -14,6 +14,8 @@
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#define PLACEHOLDER_ITEMID "Anniversary2025Offering"
using json = nlohmann::json; using json = nlohmann::json;
static std::random_device rd; static std::random_device rd;
@@ -101,11 +103,10 @@ void Spoofer::loadConfig()
try try
{ {
json configJson = json::parse(configFile); json configJson = json::parse(configFile);
_config.spoofCharacterOwnership = configJson.value("spoofCharacterOwnership", false); _config.spoofCharacterOwnership =
_config.spoofInventory = configJson.value("spoofInventory", true); configJson.value("spoofCharacterOwnership", _config.spoofCharacterOwnership);
_config.spoofCustomization = configJson.value("spoofCustomization", true); _config.spoofInventory = configJson.value("spoofInventory", _config.spoofInventory);
Log::info("Loaded config: Ownership={}, Inventory={}, Customization={}", _config.spoofCharacterOwnership, _config.spoofCustomization = configJson.value("spoofCustomization", _config.spoofCustomization);
_config.spoofInventory, _config.spoofCustomization);
} }
catch (...) catch (...)
{ {
@@ -115,11 +116,15 @@ void Spoofer::loadConfig()
else else
{ {
Log::info("config.json not found, using default settings"); Log::info("config.json not found, using default settings");
json defaultConfig = { json defaultConfig = {{"spoofCharacterOwnership", _config.spoofCharacterOwnership},
{"spoofCharacterOwnership", true}, {"spoofInventory", true}, {"spoofCustomization", true}}; {"spoofInventory", _config.spoofInventory},
{"spoofCustomization", _config.spoofCustomization}};
std::ofstream out(configPath); std::ofstream out(configPath);
out << defaultConfig.dump(4); out << defaultConfig.dump(4);
} }
Log::info("Loaded config: Ownership={}, Inventory={}, Customization={}", _config.spoofCharacterOwnership,
_config.spoofInventory, _config.spoofCustomization);
} }
/* /*
@@ -202,7 +207,7 @@ std::string Spoofer::getRandomItem()
for (auto* s : allSets) for (auto* s : allSets)
if (!s->empty()) validSets.push_back(s); if (!s->empty()) validSets.push_back(s);
if (validSets.empty()) return "Spring2024Offering"; if (validSets.empty()) return PLACEHOLDER_ITEMID;
std::uniform_int_distribution<> setDist(0, static_cast<int>(validSets.size()) - 1); std::uniform_int_distribution<> setDist(0, static_cast<int>(validSets.size()) - 1);
const auto& selectedSet = *validSets[setDist(gen)]; const auto& selectedSet = *validSets[setDist(gen)];
@@ -304,10 +309,6 @@ void Spoofer::modifyCharacterData(json& js)
if (js.contains("bloodWebData")) generateBloodweb(js["bloodWebData"]); if (js.contains("bloodWebData")) generateBloodweb(js["bloodWebData"]);
} }
} }
else
{
if (js.value("isEntitled", false) == false) return;
}
/* /*
item spoofing item spoofing
@@ -329,9 +330,9 @@ void Spoofer::modifyCharacterData(json& js)
for (auto& item : js["characterItems"]) for (auto& item : js["characterItems"])
{ {
/* /*
set existing items to rnd number set existing items to rnd number
*/ */
if (item.contains("itemId") && item["itemId"].is_string()) if (item.contains("itemId") && item["itemId"].is_string())
{ {
std::string itemId = item["itemId"]; std::string itemId = item["itemId"];
@@ -541,6 +542,9 @@ void Spoofer::onBloodweb(std::string& body, std::string& respHeaders)
json doc = json::parse(body, nullptr, false); json doc = json::parse(body, nullptr, false);
if (doc.is_discarded()) return Log::error("JSON parse error for bloodweb response"); if (doc.is_discarded()) return Log::error("JSON parse error for bloodweb response");
/*
return fake bloodweb data
*/
if (_config.spoofCharacterOwnership) if (_config.spoofCharacterOwnership)
{ {
if (body.find("NotAllowedException") != std::string::npos && body.find("not owned") != std::string::npos) if (body.find("NotAllowedException") != std::string::npos && body.find("not owned") != std::string::npos)
@@ -576,6 +580,31 @@ void Spoofer::onBloodweb(std::string& body, std::string& respHeaders)
} }
} }
/*
bloodweb fixup for perks
(if all perks are unlocked, the game will interpret bloodwebs with perks as invalid so perks will be replaced with PLACEHOLDER_ITEMID)
*/
if (_config.spoofInventory)
{
if (doc.contains("bloodWebData") && doc["bloodWebData"].contains("ringData"))
{
for (auto& ring : doc["bloodWebData"]["ringData"])
{
if (!ring.contains("nodeData")) continue;
for (auto& node : ring["nodeData"])
{
if (!node.contains("contentId")) continue;
std::string contentId = node["contentId"];
if (_camperPerkIds.contains(contentId) || _slasherPerkIds.contains(contentId))
node["contentId"] = PLACEHOLDER_ITEMID;
}
}
}
}
/*
prevent bloodweb reqs from overriding inventory values
*/
modifyCharacterData(doc); modifyCharacterData(doc);
body = doc.dump(); body = doc.dump();
#ifdef _DEBUG #ifdef _DEBUG
+2 -2
View File
@@ -12,8 +12,8 @@
struct SpooferConfig struct SpooferConfig
{ {
bool spoofCharacterOwnership = false; bool spoofCharacterOwnership = false;
bool spoofInventory = false; bool spoofInventory = true;
bool spoofCustomization = false; bool spoofCustomization = true;
}; };
class Spoofer class Spoofer