Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save widberg/daf01e950a7f16836dc6756ddff769a5 to your computer and use it in GitHub Desktop.
Save widberg/daf01e950a7f16836dc6756ddff769a5 to your computer and use it in GitHub Desktop.

The Mighty Quest for Epic Loot Offline Build Instructions

This is a guide for building MQELOffline_cpp and all of its dependencies on Windows.

Please join the Zouna Underground Discord if this interests you.

Prerequisites

You will need a recent version of CMake and Visual Studio 2022. You will also need to download a recent version of ninja and make sure ninja.exe is available in the PATH. Finally, download and install a recent version of Win32 OpenSSL (NOT Light) from Shining Light Productions Win32/Win64 OpenSSL Page and make sure the dlls are installed to the Windows system directory or /bin is added to the PATH. After everything is installed you should close any terminal Windows you may have open or other tools that should refresh the PATH.

Do the rest of the steps in this guide from the x86 Native Tools Command Prompt for VS 2022 that came with Visual Studio 2022. This ensures all of the environment variables are setup correctly.

Checkout

There are four repositories that you will need to clone. I recommend cloning them all to the same directory to keep things organized but this is not required.

git clone https://github.com/Convery/Platformwrapper_cpp.git
git clone https://github.com/AyriaPublic/Bootstrapmodule_cpp.git
git clone https://github.com/Hedgehogscience/Localnetworking_cpp.git
git clone https://github.com/Hedgehogscience/MQELOffline_cpp.git

Patch

You will need to apply a small patch to each repository for it to work with Visual Studio 2022.

Platformwrapper_cpp

diff --git a/Source/Stdinclude.hpp b/Source/Stdinclude.hpp
index 6d9b2f9..2f42c5d 100644
--- a/Source/Stdinclude.hpp
+++ b/Source/Stdinclude.hpp
@@ -29,6 +29,7 @@
 #include <string>
 #include <mutex>
 #include <ctime>
+#include <functional>

 // Platformspecific libraries.
 #if defined(_WIN32)

Bootstrapmodule_cpp

No patch needed

Localnetworking_cpp

diff --git a/Source/Stdinclude.hpp b/Source/Stdinclude.hpp
index 796aa7d..81fe263 100644
--- a/Source/Stdinclude.hpp
+++ b/Source/Stdinclude.hpp
@@ -29,6 +29,8 @@
 #include <string>
 #include <mutex>
 #include <ctime>
+#include <functional>
+#include <iterator>

 // Platformspecific libraries.
 #if defined(_WIN32)

MQELOffline_cpp

This one is a little bit longer because the way that GetCastle works on master tries to load castles from an empty zip archive. So I hunted through the git history to find how it was done before that and they had a few castles hardcoded which seems to work well enough.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index c7e2365..75426b4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -57,7 +57,7 @@ else()
 endif()
 
 # External library dependencies.
-find_package(OPENSSL)
+find_package(OPENSSL REQUIRED)
 if (OPENSSL_FOUND)
     include_directories(${OPENSSL_INCLUDE_DIR})
     target_link_libraries(MQELOffline ${OPENSSL_LIBRARIES})
diff --git a/Source/Common/Structs.hpp b/Source/Common/Structs.hpp
index 0fcfeda..9f288eb 100644
--- a/Source/Common/Structs.hpp
+++ b/Source/Common/Structs.hpp
@@ -100,7 +100,7 @@ struct Equipment_t
     }
     void Deserialize(MQEL_json &Object)
     {
-        if (!Object["Type"].is_null()) { Itemtype = Object["Type"]; }
+        if (!Object["Type"].is_null()) { Itemtype = Object["Type"].get<MQEL_json::string_t>(); }
         if (!Object["ItemLevel"].is_null()) { Level = Object["ItemLevel"]; }
         if (!Object["ArchetypeId"].is_null()) { Archetype = Object["ArchetypeId"]; }
         if (!Object["PrimaryStatsModifiers"].is_null()) { for (auto &Item : Object["PrimaryStatsModifiers"]) Modifiers.push_back(Item); }
diff --git a/Source/Frontend/Services/AttackService.cpp b/Source/Frontend/Services/AttackService.cpp
index 32082eb..e75854f 100644
--- a/Source/Frontend/Services/AttackService.cpp
+++ b/Source/Frontend/Services/AttackService.cpp
@@ -18,29 +18,22 @@ uint32_t GetCastlelevel()
 {
     return 3;
 }
-MQEL_json GetCastle(uint64_t AccountID, eCastletype Type)
+MQEL_json GetCastle(uint32_t AccountID)
 {
-    MQEL_json Result;
-
-    // Get the castle-type.
-    if (Type == eCastletype::Ubisoft) Result["$type"] = "HyperQuest.GameServer.Contracts.UbisoftCastle, HyperQuest.GameServer.Contracts";
-    if (Type == eCastletype::User) Result["$type"] = "HyperQuest.GameServer.Contracts.UserCastle, HyperQuest.GameServer.Contracts";
-
-    // Check tutorial status.
-    if (AccountID <= 3) Result["IsTutorialCastle"] = true;
-
-    // The FIFO-maps does not support patching, so we need to create a new object.
+    return MQEL_json::parse(R"({"Result":{"AttackId":"58043d5d5c98320eb4f506fa","Castle":{"$type":"HyperQuest.GameServer.Contracts.UbisoftCastle, HyperQuest.GameServer.Contracts","Level":3,"CastleValidationDuration":44.23333,"AccountId":3000947,"AccountDisplayName":"Hedgehog","LayoutId":1,"CreationDate":"2015-12-27T10:15:45Z","ModificationDate":"2016-01-08T20:11:15Z","Rooms":[{"X":5,"Y":3,"Id":1,"SpecContainerId":21},{"Creatures":[{"RoomZoneId":1,"X":13,"Y":26,"Orientation":3,"Id":40,"SpecContainerId":1081},{"RoomZoneId":1,"X":20,"Y":27,"Orientation":3,"Id":41,"SpecContainerId":1081},{"RoomZoneId":1,"X":19,"Y":27,"Orientation":3,"Id":42,"SpecContainerId":1081},{"RoomZoneId":1,"X":20,"Y":26,"Orientation":3,"Id":43,"SpecContainerId":1081},{"RoomZoneId":1,"X":19,"Y":26,"Orientation":3,"Id":44,"SpecContainerId":1081},{"RoomZoneId":1,"X":12,"Y":26,"Orientation":3,"Id":45,"SpecContainerId":1081},{"RoomZoneId":1,"X":12,"Y":25,"Orientation":3,"Id":46,"SpecContainerId":1081},{"RoomZoneId":1,"X":13,"Y":25,"Orientation":3,"Id":47,"SpecContainerId":1081},{"RoomZoneId":1,"X":15,"Y":14,"Orientation":3,"Id":48,"SpecContainerId":1003}],"Buildings":[{"Rank":3,"RoomZoneId":12,"X":3,"Y":3,"Orientation":2,"Id":1,"SpecContainerId":1},{"Rank":1,"RoomZoneId":11,"Id":2,"SpecContainerId":3},{"Rank":1,"RoomZoneId":13,"Id":3,"SpecContainerId":4},{"Rank":1,"RoomZoneId":7,"X":3,"Orientation":3,"Id":4,"SpecContainerId":13},{"RoomZoneId":4,"X":3,"Orientation":3,"Id":6,"SpecContainerId":10},{"Rank":1,"RoomZoneId":6,"X":3,"Y":3,"Orientation":2,"Id":7,"SpecContainerId":8},{"RoomZoneId":3,"Y":3,"Orientation":1,"Id":8,"SpecContainerId":9},{"Rank":1,"RoomZoneId":1,"X":26,"Y":1,"Orientation":3,"Id":9,"SpecContainerId":5}],"X":3,"Y":3,"Id":3,"SpecContainerId":25},{"Traps":[{"PowerSupplyCastleBuildableId":6,"RoomZoneId":1,"X":33,"Y":17,"Id":5,"SpecContainerId":1004},{"RoomZoneId":1,"X":27,"Y":16,"Id":6,"SpecContainerId":67}],"X":4,"Y":3,"Id":4,"SpecContainerId":5018}],"CreatureTiers":[{"SpecContainerId":1081},{"SpecContainerId":1003}],"TrapTiers":[{"SpecContainerId":1004},{"SpecContainerId":67}],"ThemeId":21},"Level":3,"Hero":{},"AttackerDisplayName":"Hedgehog","CreatureLoot":[{"Id":40,"Gold":3,"Xp":4,"HealthOrbFragments":1,"InventoryItems":[{"$type":"HyperQuest.GameServer.Contracts.HeroEquipmentItem, HyperQuest.GameServer.Contracts","ItemLevel":2,"ArchetypeId":4,"PrimaryStatsModifiers":[0.566,0.342,0.122],"IsSellable":true,"TemplateId":17}]},{"Id":41,"Gold":2,"Xp":5,"LifeForce":10,"HealthOrbFragments":1,"InventoryItems":[{"$type":"HyperQuest.GameServer.Contracts.HeroConsumableItem, HyperQuest.GameServer.Contracts","StackCount":1,"TemplateId":1000}]},{"Id":42,"Gold":1,"Xp":5,"HealthOrbFragments":1},{"Id":43,"Gold":1,"Xp":5,"LifeForce":2,"HealthOrbFragments":1},{"Id":44,"Gold":2,"Xp":4,"LifeForce":4,"HealthOrbFragments":1},{"Id":45,"Gold":2,"Xp":5,"LifeForce":1,"HealthOrbFragments":1},{"Id":46,"Gold":13,"Xp":5,"LifeForce":1,"HealthOrbFragments":1},{"Id":47,"Gold":2,"Xp":5,"HealthOrbFragments":1},{"Id":48,"Gold":2,"Xp":28,"LifeForce":10,"HealthOrbFragments":24,"InventoryItems":[{"$type":"HyperQuest.GameServer.Contracts.HeroEquipmentItem, HyperQuest.GameServer.Contracts","ItemLevel":4,"ArchetypeId":3,"PrimaryStatsModifiers":[0.938,0.568,0.491],"IsSellable":true,"TemplateId":205},{"$type":"HyperQuest.GameServer.Contracts.HeroEquipmentItem, HyperQuest.GameServer.Contracts","ItemLevel":3,"ArchetypeId":8,"PrimaryStatsModifiers":[0.98,0.24,0.777],"IsSellable":true,"TemplateId":44}]}],"TrapLoot":[{"Id":5,"Gold":1,"Xp":14,"LifeForce":1}],"FirstResurrectionCost":500,"AttackRandomSeed":2109661510,"UnlockedSpells":[{"SpellSpecContainerId":611,"Level":1},{"SpellSpecContainerId":608,"Level":1},{"SpellSpecContainerId":613,"Level":1}],"UnlockedEmotes":[1,2,3],"AttackUserSettings":{},"VictoryConditionRewardRatios":[1,0.75,0.5],"FreeInventorySlotsCount":22,"InventoryConsumablesInfo":[{"TemplateId":1002,"StackCount":2},{"TemplateId":1004,"StackCount":2},{"TemplateId":1011,"StackCount":1},{"TemplateId":1000,"StackCount":1}],"DefenderActiveConsumables":[{"TemplateId":402,"ConsumableType":10}],"TreasureRoomStealableIGC":{"CurrencyType":2,"Amount":7},"TreasureRoomStealableLifeForce":{"CurrencyType":4},"StealableMines":[{"CastleBuildingId":9,"StealableAmount":67,"MaxStealableAmount":67}],"TreasureRoomGoldRatio":0.3,"TreasureRoomLifeForceRatio":0.3,"AttackType":5,"CastleValidationDuration":44.23333,"IsResurrectionAllowed":true}})");
+}
+MQEL_json GetTutorialcastle(eAttacktype Type)
+{
+    // Wilderness tutorial.
+    if (Type == eAttacktype::None)
     {
-        // Raw data.
-        std::string Castle = Backend::PvPCastle::Getcastle(AccountID).dump(4);
-        std::string Insert = Result.dump(4);
-
-        // Trim "{}".
-        Castle = Castle.substr(1, Castle.size() - 2);
-        Insert = Insert.substr(1, Insert.size() - 2);
+        return MQEL_json::parse(R"({"$type":"HyperQuest.GameServer.Contracts.UbisoftCastle, HyperQuest.GameServer.Contracts","IsTutorialCastle":true,"ForceCastleLevelOnBuildables":true,"AccountId":2,"OasisNameId":2325,"LayoutId":1,"Rooms":[{"Triggers":[{"SizeX":18,"SizeY":6,"RoomZoneId":1,"Y":18,"Orientation":1,"Id":1,"SpecContainerId":52}],"X":4,"Y":8,"Orientation":3,"Id":11,"SpecContainerId":7105},{"Creatures":[{"AggroPropagationOffsetX":2.539598,"AggroPropagationOffsetZ":-0.9580116,"RoomZoneId":1,"X":9,"Y":11,"Orientation":3,"Id":45,"SpecContainerId":1081},{"AggroPropagationOffsetX":-0.1254749,"AggroPropagationOffsetZ":-0.4284554,"RoomZoneId":1,"X":14,"Y":21,"Orientation":2,"Id":46,"SpecContainerId":1081},{"AggroPropagationOffsetX":-0.588815,"AggroPropagationOffsetZ":0.1549107,"RoomZoneId":1,"X":9,"Y":28,"Orientation":1,"Id":47,"SpecContainerId":1081},{"AggroPropagationOffsetX":1.657236,"AggroPropagationOffsetZ":-1.133854,"RoomZoneId":1,"X":22,"Y":7,"Orientation":2,"Id":48,"SpecContainerId":1081},{"AggroPropagationOffsetX":-1.982243,"AggroPropagationOffsetZ":0.1102066,"RoomZoneId":1,"X":23,"Y":29,"Orientation":2,"Id":49,"SpecContainerId":1081},{"RoomZoneId":1,"X":26,"Y":18,"Orientation":2,"Id":50,"SpecContainerId":1081}],"Triggers":[{"SizeX":18,"SizeY":6,"RoomZoneId":1,"X":18,"Y":2,"Id":8,"SpecContainerId":52}],"Decorations":[{"RoomZoneId":1,"X":13,"Y":8,"Orientation":3,"Id":115,"SpecContainerId":224},{"RoomZoneId":1,"X":20,"Y":20,"Orientation":2,"Id":116,"SpecContainerId":224},{"RoomZoneId":1,"X":18,"Y":18,"Orientation":2,"Id":118,"SpecContainerId":224},{"RoomZoneId":1,"X":18,"Y":22,"Orientation":2,"Id":119,"SpecContainerId":224},{"RoomZoneId":1,"X":16,"Y":29,"Orientation":3,"Id":120,"SpecContainerId":224},{"RoomZoneId":1,"X":7,"Y":19,"Orientation":3,"Id":131,"SpecContainerId":223},{"RoomZoneId":1,"X":23,"Y":11,"Orientation":2,"Id":126,"SpecContainerId":224},{"RoomZoneId":1,"X":25,"Y":25,"Orientation":3,"Id":139,"SpecContainerId":223},{"RoomZoneId":1,"X":15,"Y":27,"Orientation":3,"Id":166,"SpecContainerId":236},{"RoomZoneId":1,"X":30,"Y":11,"Orientation":2,"Id":167,"SpecContainerId":236},{"RoomZoneId":1,"X":33,"Y":22,"Orientation":2,"Id":169,"SpecContainerId":236},{"RoomZoneId":1,"X":6,"Y":17,"Orientation":3,"Id":170,"SpecContainerId":235},{"RoomZoneId":1,"X":29,"Y":5,"Id":171,"SpecContainerId":235},{"RoomZoneId":1,"X":22,"Y":33,"Orientation":3,"Id":172,"SpecContainerId":236}],"X":4,"Y":7,"Id":26,"SpecContainerId":5025},{"Traps":[{"RoomZoneId":4,"X":17,"Y":33,"Id":1,"SpecContainerId":79},{"RoomZoneId":4,"X":18,"Y":33,"Id":2,"SpecContainerId":79}],"Triggers":[{"SizeX":14,"SizeY":7,"RoomZoneId":1,"X":30,"Y":18,"Orientation":1,"Id":2,"SpecContainerId":52},{"SizeX":2,"SizeY":2,"RoomZoneId":1,"X":24,"Y":18,"Orientation":1,"Id":3,"SpecContainerId":52},{"SizeX":2,"SizeY":2,"RoomZoneId":1,"X":6,"Y":25,"Orientation":1,"Id":4,"SpecContainerId":52},{"SizeX":12,"SizeY":2,"RoomZoneId":1,"X":14,"Y":18,"Orientation":1,"Id":5,"SpecContainerId":52}],"Decorations":[{"RoomZoneId":4,"X":13,"Y":34,"Id":174,"SpecContainerId":236},{"RoomZoneId":4,"X":21,"Y":34,"Id":175,"SpecContainerId":235}],"Buildings":[{"Rank":1,"RoomZoneId":1,"Id":3,"SpecContainerId":1}],"X":4,"Y":3,"Orientation":3,"Id":23,"SpecContainerId":7104},{"Creatures":[{"RoomZoneId":1,"X":21,"Y":18,"Orientation":2,"Id":68,"SpecContainerId":1081},{"RoomZoneId":1,"X":18,"Y":34,"Orientation":3,"Id":58,"SpecContainerId":1029},{"RoomZoneId":1,"X":16,"Y":17,"Id":65,"SpecContainerId":1081}],"Decorations":[{"RoomZoneId":1,"X":20,"Y":13,"Id":110,"SpecContainerId":223},{"RoomZoneId":1,"X":19,"Y":3,"Orientation":3,"Id":111,"SpecContainerId":223},{"RoomZoneId":1,"X":16,"Y":4,"Id":112,"SpecContainerId":223},{"RoomZoneId":1,"X":14,"Y":34,"Orientation":2,"Id":114,"SpecContainerId":224},{"RoomZoneId":1,"X":21,"Y":29,"Id":140,"SpecContainerId":224},{"RoomZoneId":1,"X":13,"Y":22,"Id":141,"SpecContainerId":224},{"RoomZoneId":1,"X":22,"Y":1,"Orientation":3,"Id":143,"SpecContainerId":224},{"RoomZoneId":1,"X":13,"Y":7,"Orientation":1,"Id":142,"SpecContainerId":224},{"RoomZoneId":1,"X":16,"Y":1,"Id":113,"SpecContainerId":223}],"X":4,"Y":6,"Orientation":3,"Id":29,"SpecContainerId":2006},{"Creatures":[{"RoomZoneId":1,"X":24,"Y":19,"Orientation":2,"Id":56,"SpecContainerId":1003},{"AggroPropagationOffsetX":-0.6984169,"AggroPropagationOffsetZ":-0.2310722,"RoomZoneId":1,"X":21,"Y":25,"Orientation":1,"Id":44,"SpecContainerId":1081},{"RoomZoneId":1,"X":20,"Y":13,"Orientation":1,"Id":69,"SpecContainerId":1081},{"RoomZoneId":1,"X":21,"Y":1,"Orientation":1,"Id":81,"SpecContainerId":1001}],"Decorations":[{"RoomZoneId":1,"X":13,"Y":14,"Id":153,"SpecContainerId":155},{"RoomZoneId":1,"X":14,"Y":25,"Orientation":2,"Id":154,"SpecContainerId":155},{"RoomZoneId":1,"X":22,"Y":25,"Orientation":2,"Id":155,"SpecContainerId":155},{"RoomZoneId":1,"X":22,"Y":14,"Orientation":2,"Id":156,"SpecContainerId":155},{"RoomZoneId":1,"X":18,"Y":24,"Orientation":2,"Id":157,"SpecContainerId":154},{"RoomZoneId":1,"X":10,"Y":20,"Orientation":2,"Id":158,"SpecContainerId":154},{"RoomZoneId":1,"X":17,"Y":11,"Orientation":2,"Id":159,"SpecContainerId":154},{"RoomZoneId":1,"X":28,"Y":21,"Orientation":2,"Id":160,"SpecContainerId":154},{"RoomZoneId":1,"X":1,"Y":18,"Orientation":1,"Id":144,"SpecContainerId":224},{"RoomZoneId":1,"X":21,"Orientation":3,"Id":165,"SpecContainerId":238}],"X":4,"Y":4,"Id":36,"SpecContainerId":5020},{"Creatures":[{"RoomZoneId":1,"X":16,"Y":10,"Id":70,"SpecContainerId":1081},{"RoomZoneId":1,"X":26,"Y":16,"Orientation":2,"Id":59,"SpecContainerId":1029},{"RoomZoneId":1,"X":25,"Y":21,"Orientation":1,"Id":57,"SpecContainerId":1029},{"RoomZoneId":1,"X":18,"Y":28,"Orientation":2,"Id":66,"SpecContainerId":1081}],"Triggers":[{"SizeX":14,"SizeY":7,"RoomZoneId":1,"X":17,"Y":32,"Id":6,"SpecContainerId":52},{"SizeX":14,"SizeY":7,"RoomZoneId":1,"X":17,"Y":2,"Id":7,"SpecContainerId":52}],"Decorations":[{"RoomZoneId":1,"X":18,"Y":16,"Orientation":1,"Id":146,"SpecContainerId":224},{"RoomZoneId":1,"X":17,"Y":24,"Orientation":1,"Id":145,"SpecContainerId":224},{"RoomZoneId":1,"X":13,"Y":17,"Orientation":3,"Id":147,"SpecContainerId":223},{"RoomZoneId":1,"X":22,"Y":6,"Orientation":3,"Id":173,"SpecContainerId":236}],"X":4,"Y":5,"Id":39,"SpecContainerId":5020}],"CreatureTiers":[{"SpecContainerId":1081},{"SpecContainerId":1029},{"SpecContainerId":1003},{"SpecContainerId":1001}],"TrapTiers":[{"SpecContainerId":79}],"ThemeId":25})");
+    }
 
-        std::string Hackery = "{" + Insert + ", " + Castle + "}";
-        return MQEL_json::parse(Hackery.c_str());
+    // Castle tutorial.
+    else
+    {
+        return MQEL_json::parse(R"({"$type":"HyperQuest.GameServer.Contracts.UbisoftCastle, HyperQuest.GameServer.Contracts","IsTutorialCastle":true,"ForceCastleLevelOnBuildables":true,"AccountId":3,"AccountDisplayName":"HedgehogCastle","OasisNameId":16675,"LayoutId":1,"Rooms":[{"X":5,"Y":5,"Id":11,"SpecContainerId":22},{"Triggers":[{"SizeX":4,"SizeY":1,"RoomZoneId":1,"X":19,"Y":18,"Orientation":1,"Id":5,"SpecContainerId":52},{"SizeX":20,"SizeY":6,"RoomZoneId":1,"X":5,"Y":18,"Orientation":1,"Id":8,"SpecContainerId":52}],"Buildings":[{"Rank":1,"RoomZoneId":1,"Id":4,"SpecContainerId":1},{"Rank":1,"RoomZoneId":2,"Id":5,"SpecContainerId":3},{"Rank":1,"RoomZoneId":3,"Id":6,"SpecContainerId":4}],"X":5,"Y":1,"Orientation":3,"Id":25,"SpecContainerId":27},{"Creatures":[{"RoomZoneId":1,"X":20,"Y":26,"Orientation":3,"Id":6,"SpecContainerId":1000},{"RoomZoneId":1,"X":17,"Y":19,"Orientation":3,"Id":10,"SpecContainerId":1000},{"RoomZoneId":1,"X":20,"Y":18,"Orientation":3,"Id":7,"SpecContainerId":1000},{"RoomZoneId":1,"X":16,"Y":31,"Orientation":3,"Id":9,"SpecContainerId":1000}],"Triggers":[{"SizeX":14,"SizeY":12,"RoomZoneId":1,"X":35,"Y":17,"Id":1,"SpecContainerId":52}],"Decorations":[{"RoomZoneId":1,"X":16,"Y":15,"Orientation":3,"Id":8,"SpecContainerId":141},{"RoomZoneId":1,"X":25,"Y":22,"Orientation":3,"Id":19,"SpecContainerId":149},{"RoomZoneId":1,"X":32,"Y":13,"Orientation":3,"Id":20,"SpecContainerId":127}],"X":4,"Y":5,"Id":40,"SpecContainerId":7045},{"Creatures":[{"RoomZoneId":1,"X":16,"Y":5,"Orientation":3,"Id":18,"SpecContainerId":1006},{"RoomZoneId":1,"X":20,"Y":5,"Orientation":3,"Id":20,"SpecContainerId":1006},{"RoomZoneId":1,"X":17,"Y":28,"Orientation":3,"Id":37,"SpecContainerId":1000},{"RoomZoneId":1,"X":14,"Y":28,"Id":42,"SpecContainerId":1000},{"RoomZoneId":1,"X":19,"Y":27,"Orientation":1,"Id":43,"SpecContainerId":1000},{"RoomZoneId":1,"X":22,"Y":28,"Id":44,"SpecContainerId":1000},{"RoomZoneId":1,"X":20,"Y":25,"Orientation":3,"Id":45,"SpecContainerId":1000},{"AggroPropagationOffsetX":-3.080803,"AggroPropagationOffsetZ":-0.786087,"RoomZoneId":1,"X":17,"Y":31,"Orientation":2,"Id":46,"SpecContainerId":1000},{"RoomZoneId":1,"X":15,"Y":25,"Orientation":3,"Id":47,"SpecContainerId":1000},{"RoomZoneId":1,"X":17,"Y":11,"Orientation":3,"Id":48,"SpecContainerId":1000},{"RoomZoneId":1,"X":21,"Y":13,"Orientation":2,"Id":49,"SpecContainerId":1000},{"RoomZoneId":1,"X":14,"Y":13,"Orientation":2,"Id":50,"SpecContainerId":1000},{"RoomZoneId":1,"X":18,"Y":14,"Orientation":1,"Id":51,"SpecContainerId":1000}],"Decorations":[{"RoomZoneId":1,"X":13,"Y":24,"Orientation":2,"Id":9,"SpecContainerId":141},{"RoomZoneId":1,"X":22,"Y":35,"Orientation":3,"Id":10,"SpecContainerId":141},{"RoomZoneId":1,"X":22,"Y":26,"Orientation":2,"Id":39,"SpecContainerId":141},{"RoomZoneId":1,"X":19,"Y":25,"Orientation":3,"Id":40,"SpecContainerId":141},{"RoomZoneId":1,"X":16,"Y":32,"Orientation":2,"Id":41,"SpecContainerId":141},{"RoomZoneId":1,"X":20,"Y":17,"Id":43,"SpecContainerId":140},{"RoomZoneId":1,"X":15,"Y":18,"Id":44,"SpecContainerId":140},{"RoomZoneId":1,"X":22,"Y":20,"Orientation":2,"Id":45,"SpecContainerId":141},{"RoomZoneId":1,"X":15,"Y":32,"Id":91,"SpecContainerId":261},{"RoomZoneId":1,"X":21,"Y":4,"Id":92,"SpecContainerId":261},{"RoomZoneId":1,"X":14,"Y":4,"Id":93,"SpecContainerId":261}],"X":5,"Y":2,"Orientation":3,"Id":41,"SpecContainerId":2006},{"Creatures":[{"RoomZoneId":1,"X":12,"Y":11,"Orientation":3,"Id":11,"SpecContainerId":1023},{"RoomZoneId":1,"X":8,"Y":12,"Orientation":3,"Id":15,"SpecContainerId":1023},{"RoomZoneId":1,"X":27,"Y":23,"Orientation":3,"Id":16,"SpecContainerId":1023},{"RoomZoneId":1,"X":17,"Y":35,"Orientation":3,"Id":8,"SpecContainerId":1000},{"RoomZoneId":1,"X":23,"Y":24,"Id":38,"SpecContainerId":1000},{"RoomZoneId":1,"X":28,"Y":26,"Orientation":2,"Id":39,"SpecContainerId":1000},{"RoomZoneId":1,"X":12,"Y":15,"Orientation":3,"Id":40,"SpecContainerId":1000},{"RoomZoneId":1,"X":6,"Y":16,"Id":41,"SpecContainerId":1000}],"Traps":[{"RoomZoneId":1,"X":24,"Y":13,"Id":30,"SpecContainerId":1000},{"RoomZoneId":1,"X":21,"Y":7,"Id":33,"SpecContainerId":1000},{"RoomZoneId":1,"X":29,"Y":12,"Id":29,"SpecContainerId":1000},{"RoomZoneId":1,"X":26,"Y":6,"Id":34,"SpecContainerId":1000}],"Decorations":[{"RoomZoneId":1,"X":22,"Y":32,"Orientation":3,"Id":28,"SpecContainerId":141},{"RoomZoneId":1,"X":15,"Y":35,"Id":11,"SpecContainerId":140},{"RoomZoneId":1,"X":8,"Y":23,"Orientation":2,"Id":30,"SpecContainerId":141},{"RoomZoneId":1,"X":9,"Y":23,"Orientation":2,"Id":31,"SpecContainerId":141},{"RoomZoneId":1,"X":8,"Y":24,"Orientation":1,"Id":32,"SpecContainerId":141},{"RoomZoneId":1,"X":25,"Y":9,"Id":35,"SpecContainerId":140},{"RoomZoneId":1,"X":5,"Y":16,"Id":36,"SpecContainerId":127},{"RoomZoneId":1,"X":20,"Y":25,"Id":67,"SpecContainerId":127},{"RoomZoneId":1,"X":15,"Y":10,"Orientation":2,"Id":68,"SpecContainerId":127},{"RoomZoneId":1,"X":5,"Y":9,"Id":88,"SpecContainerId":261},{"RoomZoneId":1,"X":8,"Y":21,"Id":89,"SpecContainerId":261},{"RoomZoneId":1,"X":15,"Y":34,"Id":90,"SpecContainerId":261}],"X":5,"Y":3,"Orientation":3,"Id":45,"SpecContainerId":7062},{"Creatures":[{"RoomZoneId":1,"X":17,"Y":27,"Orientation":1,"Id":12,"SpecContainerId":1023}],"Traps":[{"RoomZoneId":1,"X":35,"Y":20,"Orientation":2,"Id":25,"SpecContainerId":1000}],"Decorations":[{"RoomZoneId":1,"X":35,"Y":17,"Orientation":2,"Id":7,"SpecContainerId":141},{"RoomZoneId":1,"X":28,"Y":18,"Orientation":2,"Id":27,"SpecContainerId":141},{"RoomZoneId":1,"X":17,"Y":17,"Orientation":2,"Id":85,"SpecContainerId":261},{"RoomZoneId":1,"X":33,"Y":15,"Orientation":2,"Id":86,"SpecContainerId":261},{"RoomZoneId":1,"X":33,"Y":20,"Orientation":2,"Id":87,"SpecContainerId":261}],"X":5,"Y":4,"Orientation":1,"Id":47,"SpecContainerId":7057},{"Creatures":[{"RoomZoneId":1,"X":18,"Y":34,"Orientation":3,"Id":19,"SpecContainerId":1006}],"Traps":[{"RoomZoneId":1,"X":25,"Y":20,"Id":22,"SpecContainerId":1000},{"RoomZoneId":1,"X":27,"Y":10,"Id":24,"SpecContainerId":1000},{"RoomZoneId":1,"X":33,"Y":21,"Id":21,"SpecContainerId":1000},{"RoomZoneId":1,"X":32,"Y":16,"Id":23,"SpecContainerId":1000},{"RoomZoneId":1,"X":24,"Y":14,"Id":26,"SpecContainerId":1000},{"RoomZoneId":1,"X":20,"Y":11,"Id":27,"SpecContainerId":1000},{"RoomZoneId":1,"X":19,"Y":19,"Id":28,"SpecContainerId":1000},{"RoomZoneId":1,"X":7,"Y":16,"Id":32,"SpecContainerId":1000}],"Triggers":[{"SizeX":1,"SizeY":4,"RoomZoneId":1,"X":14,"Y":21,"Orientation":1,"Id":4,"SpecContainerId":52}],"Decorations":[{"RoomZoneId":1,"X":21,"Y":14,"Id":2,"SpecContainerId":141},{"RoomZoneId":1,"X":30,"Y":19,"Id":4,"SpecContainerId":141},{"RoomZoneId":1,"X":29,"Y":13,"Id":5,"SpecContainerId":141},{"RoomZoneId":1,"X":23,"Y":9,"Id":6,"SpecContainerId":141},{"RoomZoneId":1,"X":5,"Y":23,"Id":21,"SpecContainerId":127},{"RoomZoneId":1,"X":22,"Y":22,"Id":23,"SpecContainerId":140},{"RoomZoneId":1,"X":31,"Y":13,"Orientation":3,"Id":25,"SpecContainerId":141},{"RoomZoneId":1,"X":31,"Y":18,"Orientation":3,"Id":26,"SpecContainerId":141},{"RoomZoneId":1,"X":26,"Y":16,"Id":42,"SpecContainerId":141},{"RoomZoneId":1,"X":16,"Y":34,"Id":81,"SpecContainerId":261},{"RoomZoneId":1,"X":5,"Y":17,"Id":83,"SpecContainerId":261},{"RoomZoneId":1,"X":15,"Y":34,"Id":94,"SpecContainerId":140}],"X":4,"Y":4,"Orientation":3,"Id":52,"SpecContainerId":7068}],"CreatureTiers":[{"SpecContainerId":1000},{"SpecContainerId":1006},{"SpecContainerId":1023}],"TrapTiers":[{"SpecContainerId":1000}],"ThemeId":26})");
     }
 }
 MQEL_json GetCreatureloot()
@@ -134,7 +127,8 @@ void StartAttack(Gameserver *Server, std::string Request, std::string Body)
     // Create the challenge.
     auto Response = MQEL_json::object();
                     Response["Result"]["AttackId"] = va("%x", CurrentattackID);
-                    Response["Result"]["Castle"] = GetCastle(Parsed["castleAccountId"], Castletype);
+    if(Tutorial)    Response["Result"]["Castle"] = GetTutorialcastle(Attacktype);
+    if(!Tutorial)   Response["Result"]["Castle"] = GetCastle(Parsed["castleAccountId"]);
     if(Tutorial)    Response["Result"]["CastleType"] = Parsed["castleType"].get<uint32_t>();
                     Response["Result"]["Level"] = Tutorial ? 1 : GetCastlelevel();
                     Response["Result"]["Hero"] = Backend::Hero::Serialize();
diff --git a/Source/Stdinclude.hpp b/Source/Stdinclude.hpp
index 51f1564..a773fdc 100644
--- a/Source/Stdinclude.hpp
+++ b/Source/Stdinclude.hpp
@@ -27,6 +27,7 @@
 #include <string>
 #include <mutex>
 #include <ctime>
+#include <functional>
 
 // Platformspecific libraries.
 #if defined(_WIN32)

Configure and Build

From within each of the cloned repositories run the following two commands to configure and build the project respectively. You can choose not to build it debug but I don't recommend that.

cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
cmake --build build

It is possible that you will get a CMake error when configuring the MQELOffline_cpp project if OpenSSL is not found. In this case I would manually set the include_directories and target_link_libraries with absolute paths. Trying to build without OpenSSL will not work.

Install

To set the game directory up so that the build artifacts are in the right places. First rename the old steam_api.dll to steam_api.dll.bak or otherwise remove it from the directory, then create a Plugins directory next to the MightyQuest.exe file. The original repository recommends symlinking the build artifacts to the game directories. Note that if you build debug you will need to include the ds and if not then exclude them. I highly recommend using the dir /a command to tripple check that the symlinks are pointing to where you think they are. If you try to make a symlink to a file that does not exist, it will appear to succeed but will actually create a symlink to itself that has strange behavior. If something isn't working, check this first. Longer paths are shown for clarity, you do not need to use these exact paths.

mklink "steamapps/common/The Mighty Quest For Epic Loot/GameData/Bin/steam_api.dll" Platformwrapper_cpp/Bin/steam_api[d].dll
mklink "steamapps/common/The Mighty Quest For Epic Loot/GameData/Bin/Localbootstrap.dll" Bootstrapmodule_cpp/Bin/Nativebootstrap32[d].dll
mklink "steamapps/common/The Mighty Quest For Epic Loot/GameData/Bin/Plugins/Developerplugin.dll" Localnetworking_cpp/Bin/Localnetworking[d].ayria32
mklink "steamapps/common/The Mighty Quest For Epic Loot/GameData/Bin/Plugins/Developermodule.dll" MQELOffline_cpp/Bin/MQELOffline[d].LN32

Alternatively, you can just copy the files after each build. Make sure the copied files have the same file names they would have had if you followed the symlink instructions.

Run

Once all that is set up you can run the game executable from the same directory it is in. Type the command as-is nothing needs to be changed or replaced. You may need to run the game 2-3 times before you get past the network error. If it takes more than 3 tries something is wrong.

cd "steamapps/common/The Mighty Quest For Epic Loot/GameData/Bin"
MightyQuest.exe -server_url https://Gameserver -environmentName mqel-live -branchName mqel -steamid 76561201696194782 -steamticket "" -token ""

When it is time to pick a character, pick the Mage. Don't pick the Runaway because it is not fully implemented and don't pick the Knight or Archer because there will not be any loot for them in the first castle. Note that the game will soft lock after two castles due to how level ups are processed.

I recorded myself playing through as much as I could after having followed this guide: https://youtu.be/smHCHmNJ_Uo

Debug

Here's a sample launch.json for VSCode that can be used to run the game and patch code under a debugger or not. It won't build the projects when you run it so make sure you build everything before launching the task.

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [


        {
            "type": "cppvsdbg",
            "request": "launch",
            "name": "Debug",
            "program": "D:\\SteamLibrary\\steamapps\\common\\The Mighty Quest For Epic Loot\\GameData\\Bin\\MightyQuest.exe",
            "args": ["-server_url", "https://Gameserver", "-environmentName", "mqel-live", "-branchName", "mqel", "-steamid", "76561201696194782", "-steamticket", "\"\"", "-token", "\"\""],
            "cwd": "D:\\SteamLibrary\\steamapps\\common\\The Mighty Quest For Epic Loot\\GameData\\Bin\\"
        }
    ]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment