From 29e7495cdf6e31a431e73af085fd9ff6d67df1de Mon Sep 17 00:00:00 2001 From: CCHyper <73803386+CCHyper@users.noreply.github.com> Date: Wed, 22 Sep 2021 17:07:28 +0100 Subject: [PATCH] Implements IsEligibleForAllyBuilding for BuildingTypes. --- .../buildingtype/buildingtypeext.cpp | 9 ++- src/extensions/buildingtype/buildingtypeext.h | 5 ++ src/extensions/display/displayext_hooks.cpp | 71 +++++++++++++++++++ 3 files changed, 83 insertions(+), 2 deletions(-) diff --git a/src/extensions/buildingtype/buildingtypeext.cpp b/src/extensions/buildingtype/buildingtypeext.cpp index 03ee7fb79..1644b4397 100644 --- a/src/extensions/buildingtype/buildingtypeext.cpp +++ b/src/extensions/buildingtype/buildingtypeext.cpp @@ -46,7 +46,6 @@ ExtensionMap BuildingTypeClassExt */ BuildingTypeClassExtension::BuildingTypeClassExtension(BuildingTypeClass *this_ptr) : Extension(this_ptr), - GateUpSound(VOC_NONE), GateDownSound(VOC_NONE), ProduceCashStartup(0), @@ -54,7 +53,8 @@ BuildingTypeClassExtension::BuildingTypeClassExtension(BuildingTypeClass *this_p ProduceCashDelay(0), ProduceCashBudget(0), IsStartupCashOneTime(false), - IsResetBudgetOnCapture(false) + IsResetBudgetOnCapture(false), + IsEligibleForAllyBuilding(false) { ASSERT(ThisPtr != nullptr); //DEV_DEBUG_TRACE("BuildingTypeClassExtension constructor - Name: %s (0x%08X)\n", ThisPtr->Name(), (uintptr_t)(ThisPtr)); @@ -165,6 +165,8 @@ void BuildingTypeClassExtension::Compute_CRC(WWCRCEngine &crc) const { ASSERT(ThisPtr != nullptr); //DEV_DEBUG_TRACE("BuildingTypeClassExtension::Compute_CRC - Name: %s (0x%08X)\n", ThisPtr->Name(), (uintptr_t)(ThisPtr)); + + crc(IsEligibleForAllyBuilding); } @@ -194,6 +196,9 @@ bool BuildingTypeClassExtension::Read_INI(CCINIClass &ini) ProduceCashBudget = ini.Get_Int(ini_name, "ProduceCashBudget", ProduceCashBudget); IsStartupCashOneTime = ini.Get_Int(ini_name, "ProduceCashStartupOneTime", IsStartupCashOneTime); IsResetBudgetOnCapture = ini.Get_Bool(ini_name, "ProduceCashResetOnCapture", IsResetBudgetOnCapture); + + IsEligibleForAllyBuilding = ini.Get_Bool(ini_name, "EligibleForAllyBuilding", + ThisPtr->IsConstructionYard ? true : IsEligibleForAllyBuilding); return true; } diff --git a/src/extensions/buildingtype/buildingtypeext.h b/src/extensions/buildingtype/buildingtypeext.h index d53bd4921..63e2b38cc 100644 --- a/src/extensions/buildingtype/buildingtypeext.h +++ b/src/extensions/buildingtype/buildingtypeext.h @@ -91,6 +91,11 @@ class BuildingTypeClassExtension final : public Extension * Reset the available budget when captured? */ bool IsResetBudgetOnCapture; + + /** + * Is this building eligible for proximity checks by players who are its owner's allies? + */ + bool IsEligibleForAllyBuilding; }; diff --git a/src/extensions/display/displayext_hooks.cpp b/src/extensions/display/displayext_hooks.cpp index 3083e5c20..8a0886c16 100644 --- a/src/extensions/display/displayext_hooks.cpp +++ b/src/extensions/display/displayext_hooks.cpp @@ -31,6 +31,14 @@ #include "tibsun_util.h" #include "display.h" #include "iomap.h" +#include "cell.h" +#include "building.h" +#include "buildingtype.h" +#include "buildingtypeext.h" +#include "house.h" +#include "housetype.h" +#include "session.h" +#include "sessionext.h" #include "wwmouse.h" #include "fatal.h" #include "debughandler.h" @@ -40,6 +48,68 @@ #include "hooker_macros.h" +/** + * #issue-171 + * + * Adds game option to control if allies can build off each others bases. + * + * @author: CCHyper + */ +DECLARE_PATCH(_DisplayClass_Passes_Proximity_Passes_Check_Patch) +{ + //GET_REGISTER_STATIC(DisplayClass *, this_ptr, ?); // No access to "this". + GET_REGISTER_STATIC(BuildingClass *, base, eax); + GET_STACK_STATIC(HousesType, house, esp, 0x38); + //GET_STACK_STATIC8(bool, passes, esp, 0x3C); + static BuildingTypeClassExtension *buildingtypeext; + static HouseClass *hptr; + + /** + * Store the proximity check result. + */ + #define passes() _asm { mov byte ptr [esp+0x3C], 1 } + + hptr = Houses[house]; + + /** + * Stolen bytes/code. + * + * Ensure the building is considered eligible for adjacency checks. + */ + if (base->House->ID == house && base->Class->IsBase) { + passes(); + } + + /** + * If the build-off-ally option is enabled, ensure the building is + * owned by an ally house and is eligible for adjacent building before + * passing the check. + * + * #NOTE: This feature is only available for multiplayer games. + */ + if (Session.Type != GAME_NORMAL) { + if (SessionExtension && SessionExtension->ExtOptions.IsBuildOffAlly) { + + if (base->House != hptr && base->House->Is_Ally(hptr)) { + + buildingtypeext = BuildingTypeClassExtensions.find(base->Class); + if (buildingtypeext && buildingtypeext->IsEligibleForAllyBuilding) { +#ifndef NDEBUG + //DEV_DEBUG_INFO("Ally \"%s's\" building \"%s\" is eligible for building off.\n", base->House->IniName, base->Name()); +#endif + passes(); + } + } + } + } + + #undef passes + +continue_scan: + JMP(0x00476308); +} + + /** * #issue-344 * @@ -179,6 +249,7 @@ void DisplayClassExtension_Hooks() { Patch_Jump(0x0047AFA6, &_DisplayClass_Help_Text_GetCursorPosition_Patch); Patch_Jump(0x00478974, &_DisplayClass_Mouse_Left_Release_PlaceAnywhere_BugFix_Patch); + Patch_Jump(0x004762E4, &_DisplayClass_Passes_Proximity_Passes_Check_Patch); /** * #issue-76