diff --git a/src/extensions/building/buildingext.cpp b/src/extensions/building/buildingext.cpp index 9812ed931..df7c72dd3 100644 --- a/src/extensions/building/buildingext.cpp +++ b/src/extensions/building/buildingext.cpp @@ -29,6 +29,7 @@ #include "building.h" #include "buildingtype.h" #include "buildingtypeext.h" +#include "tibsun_inline.h" #include "house.h" #include "housetype.h" #include "wwcrc.h" @@ -172,6 +173,7 @@ void BuildingClassExtension::Compute_CRC(WWCRCEngine &crc) const crc(ProduceCashTimer()); } + /** * #issue-26 * @@ -286,3 +288,55 @@ void BuildingClassExtension::Produce_Cash_AI() } } + + +/** + * Fetches the coordinate to use for docking. + * + * @author: CCHyper + */ +Coordinate BuildingClassExtension::Docking_Coord() const +{ + ASSERT(ThisPtr != nullptr); + //EXT_DEBUG_TRACE("BuildingClassExtension::Docking_Coord - Name: %s (0x%08X)\n", ThisPtr->Name(), (uintptr_t)(ThisPtr)); + + if (ThisPtr->Class->IsWeeder) { + Cell cell = ThisPtr->Get_Cell(); + cell.X += 2; + cell.Y += 1; + Coordinate coord = Cell_Coord(cell, true); + coord.Z = ThisPtr->Get_Coord().Z; + return coord; + } + + if (ThisPtr->Class->IsRefinery) { + Coordinate coord = ThisPtr->Center_Coord(); + coord.X += CELL_LEPTON_W/2; + return coord; + } + + /** + * #issue-786 + * + * Implements DockingOffset for BuildingTypes (currently limited to Helipads). + * + * @author: CCHyper + */ + BuildingTypeClassExtension *buildingtypeext = BuildingTypeClassExtensions.find(ThisPtr->Class); + + if (buildingtypeext && buildingtypeext->NumberOfDocks > 0) { + + TPoint3D docking_offset_0 = buildingtypeext->DockingOffsets[0]; + + if (ThisPtr->Class->IsHelipad) { + Coordinate coord = ThisPtr->Center_Coord(); + coord.X += docking_offset_0.X; + coord.Y += docking_offset_0.Y; + coord.Z += docking_offset_0.Z; + return coord; + } + + } + + return ThisPtr->Docking_Coord(); +} diff --git a/src/extensions/building/buildingext.h b/src/extensions/building/buildingext.h index 2c90afaac..c7bc08ad8 100644 --- a/src/extensions/building/buildingext.h +++ b/src/extensions/building/buildingext.h @@ -53,6 +53,7 @@ class BuildingClassExtension final : public Extension virtual void Compute_CRC(WWCRCEngine &crc) const override; void Produce_Cash_AI(); + Coordinate Docking_Coord() const; public: /** diff --git a/src/extensions/building/buildingext_hooks.cpp b/src/extensions/building/buildingext_hooks.cpp index de0b879bc..73db960cf 100644 --- a/src/extensions/building/buildingext_hooks.cpp +++ b/src/extensions/building/buildingext_hooks.cpp @@ -55,6 +55,36 @@ #include "hooker_macros.h" +/** + * A fake class for implementing new member functions which allow + * access to the "this" pointer of the intended class. + * + * @note: This must not contain a constructor or destructor! + * @note: All functions must be prefixed with "_" to prevent accidental virtualization. + */ +class BuildingClassExt final : public BuildingClass +{ + public: + Coordinate _Docking_Coord() const; +}; + + +/** + * Reimplementation of BuildingClass::Docking_Coord. + * + * @author: CCHyper + */ +Coordinate BuildingClassExt::_Docking_Coord() const +{ + BuildingClassExtension *buildingext = BuildingClassExtensions.find(this); + if (buildingext) { + return buildingext->Docking_Coord(); + } else { + return BuildingClass::Docking_Coord(); + } +} + + /** * #issue-26 * @@ -493,4 +523,6 @@ void BuildingClassExtension_Hooks() Patch_Jump(0x00429A96, &_BuildingClass_AI_ProduceCash_Patch); Patch_Jump(0x0042F67D, &_BuildingClass_Captured_ProduceCash_Patch); Patch_Jump(0x0042E179, &_BuildingClass_Grand_Opening_ProduceCash_Patch); + + Change_Virtual_Address(0x006CC3A0, Get_Func_Address(&BuildingClassExt::_Docking_Coord)); } diff --git a/src/extensions/buildingtype/buildingtypeext.cpp b/src/extensions/buildingtype/buildingtypeext.cpp index d34c60155..fcfd5edca 100644 --- a/src/extensions/buildingtype/buildingtypeext.cpp +++ b/src/extensions/buildingtype/buildingtypeext.cpp @@ -54,7 +54,9 @@ BuildingTypeClassExtension::BuildingTypeClassExtension(BuildingTypeClass *this_p ProduceCashBudget(0), IsStartupCashOneTime(false), IsResetBudgetOnCapture(false), - IsEligibleForAllyBuilding(false) + IsEligibleForAllyBuilding(false), + NumberOfDocks(0), + DockingOffsets() { ASSERT(ThisPtr != nullptr); //EXT_DEBUG_TRACE("BuildingTypeClassExtension constructor - Name: %s (0x%08X)\n", ThisPtr->Name(), (uintptr_t)(ThisPtr)); @@ -167,6 +169,8 @@ void BuildingTypeClassExtension::Compute_CRC(WWCRCEngine &crc) const //EXT_DEBUG_TRACE("BuildingTypeClassExtension::Compute_CRC - Name: %s (0x%08X)\n", ThisPtr->Name(), (uintptr_t)(ThisPtr)); crc(IsEligibleForAllyBuilding); + crc(NumberOfDocks); + crc(DockingOffsets.Count()); } @@ -181,12 +185,26 @@ bool BuildingTypeClassExtension::Read_INI(CCINIClass &ini) //EXT_DEBUG_TRACE("BuildingTypeClassExtension::Read_INI - Name: %s (0x%08X)\n", ThisPtr->Name(), (uintptr_t)(ThisPtr)); EXT_DEBUG_WARNING("BuildingTypeClassExtension::Read_INI - Name: %s (0x%08X)\n", ThisPtr->Name(), (uintptr_t)(ThisPtr)); + char buffer[1024]; + const char *ini_name = ThisPtr->Name(); + const char *graphic_name = ThisPtr->Graphic_Name(); if (!ini.Is_Present(ini_name)) { return false; } + //if (!ArtINI.Is_Present(graphic_name)) { + // return false; + //} + + /** + * The following structures have at least one docking location. + */ + if (ThisPtr->IsHelipad) { + NumberOfDocks = 1; + } + GateUpSound = ini.Get_VocType(ini_name, "GateUpSound", GateUpSound); GateDownSound = ini.Get_VocType(ini_name, "GateDownSound", GateDownSound); @@ -199,6 +217,14 @@ bool BuildingTypeClassExtension::Read_INI(CCINIClass &ini) IsEligibleForAllyBuilding = ini.Get_Bool(ini_name, "EligibleForAllyBuilding", ThisPtr->IsConstructionYard ? true : IsEligibleForAllyBuilding); + + NumberOfDocks = ini.Get_Int(ini_name, "NumberOfDocks", NumberOfDocks); + + for (int i = 0; i < NumberOfDocks; ++i) { + std::snprintf(buffer, sizeof(buffer), "DockingOffset%d", i); + TPoint3D offset = ArtINI.Get_Point(graphic_name, buffer, TPoint3D(0,0,0)); + DockingOffsets.Add(offset); + } return true; } diff --git a/src/extensions/buildingtype/buildingtypeext.h b/src/extensions/buildingtype/buildingtypeext.h index 63e2b38cc..f8aa9f9dc 100644 --- a/src/extensions/buildingtype/buildingtypeext.h +++ b/src/extensions/buildingtype/buildingtypeext.h @@ -29,6 +29,7 @@ #include "extension.h" #include "container.h" +#include "tpoint.h" class BuildingTypeClass; @@ -96,6 +97,16 @@ class BuildingTypeClassExtension final : public Extension * Is this building eligible for proximity checks by players who are its owner's allies? */ bool IsEligibleForAllyBuilding; + + /** + * The number of available docking positions this building has. + */ + unsigned NumberOfDocks; + + /** + * The offset(s) from the center of the building for each docking position. + */ + DynamicVectorClass> DockingOffsets; };