Skip to content

Commit

Permalink
Add allowed / disallowed type lists for FactoryPlant (#1337)
Browse files Browse the repository at this point in the history
### Allowed / disallowed types for FactoryPlant

- It is now possible to customize which TechnoTypes benefit from bonuses
of a `FactoryPlant=true` building by listing them on
`FactoryPlant.AllowTypes` and/or `FactoryPlant.DisallowTypes`.
- `FactoryPlant.Multiplier` (Ares feature) is still applied on the
bonuses if they are in effect.

In `rulesmd.ini`:
```ini
[SOMEBUILDING]               ; BuildingType
FactoryPlant.AllowTypes=     ; List of TechnoTypes
FactoryPlant.DisallowTypes=  ; List of TechnoTypes
```
  • Loading branch information
Starkku authored Aug 28, 2024
1 parent 2c6ba54 commit 8baebb6
Show file tree
Hide file tree
Showing 11 changed files with 193 additions and 9 deletions.
1 change: 1 addition & 0 deletions CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ This page lists all the individual contributions to the project by their author.
- AI superweapon delay timer customization
- Disabling `MultipleFactory` bonus from specific BuildingType
- Customizable ChronoSphere teleport delays for units
- Allowed and disallowed types for `FactoryPlant`
- **Morton (MortonPL)**:
- `XDrawOffset` for animations
- Shield passthrough & absorption
Expand Down
12 changes: 12 additions & 0 deletions docs/Fixed-or-Improved-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,18 @@ In `rulesmd.ini`:
AllowAirstrike= ; boolean
```

### Allowed / disallowed types for FactoryPlant

- It is now possible to customize which TechnoTypes benefit from bonuses of a `FactoryPlant=true` building by listing them on `FactoryPlant.AllowTypes` and/or `FactoryPlant.DisallowTypes`.
- `FactoryPlant.Multiplier` (Ares feature) is still applied on the bonuses if they are in effect.

In `rulesmd.ini`:
```ini
[SOMEBUILDING] ; BuildingType
FactoryPlant.AllowTypes= ; List of TechnoTypes
FactoryPlant.DisallowTypes= ; List of TechnoTypes
```

### Apply ZShapePointMove during buildups

- By default buildings do not apply `ZShapePointMove` (which offsets the 'z shape' applied on buildings which is used to adjust them in depth buffer and is used to fix issues related to that such as corners of buildings getting cut off when drawn) when buildup is being displayed. This behaviour can now be toggled by setting `ZShapePointMove.OnBuildup`.
Expand Down
1 change: 1 addition & 0 deletions docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,7 @@ New:
- AI superweapon delay timer customization (by Starkku)
- Disabling `MultipleFactory` bonus from specific BuildingType (by Starkku)
- Customizable ChronoSphere teleport delays for units (by Starkku)
- Allowed and disallowed types for `FactoryPlant` (by Starkku)
Vanilla fixes:
- Allow AI to repair structures built from base nodes/trigger action 125/SW delivery in single player missions (by Trsdy)
Expand Down
67 changes: 67 additions & 0 deletions src/Ext/Building/Hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -396,3 +396,70 @@ DEFINE_HOOK(0x4511D6, BuildingClass_AnimationAI_SellBuildup, 0x7)

return pTypeExt->SellBuildupLength == pThis->Animation.Value ? Continue : Skip;
}

#pragma region FactoryPlant

DEFINE_HOOK(0x441501, BuildingClass_Unlimbo_FactoryPlant, 0x6)
{
enum { Skip = 0x441553 };

GET(BuildingClass*, pThis, ESI);

auto const pTypeExt = BuildingTypeExt::ExtMap.Find(pThis->Type);

if (pTypeExt->FactoryPlant_AllowTypes.size() > 0 || pTypeExt->FactoryPlant_DisallowTypes.size() > 0)
{
auto const pHouseExt = HouseExt::ExtMap.Find(pThis->Owner);
pHouseExt->RestrictedFactoryPlants.push_back(pThis);

return Skip;
}

return 0;
}

DEFINE_HOOK(0x448A31, BuildingClass_Captured_FactoryPlant1, 0x6)
{
enum { Skip = 0x448A78 };

GET(BuildingClass*, pThis, ESI);

auto const pTypeExt = BuildingTypeExt::ExtMap.Find(pThis->Type);

if (pTypeExt->FactoryPlant_AllowTypes.size() > 0 || pTypeExt->FactoryPlant_DisallowTypes.size() > 0)
{
auto const pHouseExt = HouseExt::ExtMap.Find(pThis->Owner);

if (!pHouseExt->RestrictedFactoryPlants.empty())
{
auto& vec = pHouseExt->RestrictedFactoryPlants;
vec.erase(std::remove(vec.begin(), vec.end(), pThis), vec.end());
}

return Skip;
}

return 0;
}

DEFINE_HOOK(0x449149, BuildingClass_Captured_FactoryPlant2, 0x6)
{
enum { Skip = 0x449197 };

GET(BuildingClass*, pThis, ESI);
GET(HouseClass*, pNewOwner, EBP);

auto const pTypeExt = BuildingTypeExt::ExtMap.Find(pThis->Type);

if (pTypeExt->FactoryPlant_AllowTypes.size() > 0 || pTypeExt->FactoryPlant_DisallowTypes.size() > 0)
{
auto const pHouseExt = HouseExt::ExtMap.Find(pNewOwner);
pHouseExt->RestrictedFactoryPlants.push_back(pThis);

return Skip;
}

return 0;
}

#pragma endregion
5 changes: 5 additions & 0 deletions src/Ext/BuildingType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ void BuildingTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
this->ConsideredVehicle.Read(exINI, pSection, "ConsideredVehicle");
this->SellBuildupLength.Read(exINI, pSection, "SellBuildupLength");

this->FactoryPlant_AllowTypes.Read(exINI, pSection, "FactoryPlant.AllowTypes");
this->FactoryPlant_DisallowTypes.Read(exINI, pSection, "FactoryPlant.DisallowTypes");

if (pThis->NumberOfDocks > 0)
{
this->AircraftDockingDirs.clear();
Expand Down Expand Up @@ -261,6 +264,8 @@ void BuildingTypeExt::ExtData::Serialize(T& Stm)
.Process(this->ZShapePointMove_OnBuildup)
.Process(this->SellBuildupLength)
.Process(this->AircraftDockingDirs)
.Process(this->FactoryPlant_AllowTypes)
.Process(this->FactoryPlant_DisallowTypes)
;
}

Expand Down
5 changes: 5 additions & 0 deletions src/Ext/BuildingType/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ class BuildingTypeExt

std::vector<OptionalStruct<DirType, true>> AircraftDockingDirs;

ValueableVector<TechnoTypeClass*> FactoryPlant_AllowTypes;
ValueableVector<TechnoTypeClass*> FactoryPlant_DisallowTypes;

ExtData(BuildingTypeClass* OwnerObject) : Extension<BuildingTypeClass>(OwnerObject)
, PowersUp_Owner { AffectedHouse::Owner }
, PowersUp_Buildings {}
Expand Down Expand Up @@ -103,6 +106,8 @@ class BuildingTypeExt
, ZShapePointMove_OnBuildup { false }
, SellBuildupLength { 23 }
, AircraftDockingDirs {}
, FactoryPlant_AllowTypes {}
, FactoryPlant_DisallowTypes {}
{ }

// Ares 0.A functions
Expand Down
73 changes: 64 additions & 9 deletions src/Ext/House/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,50 @@ int HouseExt::ExtData::GetFactoryCountWithoutNonMFB(AbstractType rtti, bool isNa
return Math::max(count, 0);
}

float HouseExt::ExtData::GetRestrictedFactoryPlantMult(TechnoTypeClass* pTechnoType) const
{
float mult = 1.0;
auto const pTechnoTypeExt = TechnoTypeExt::ExtMap.Find(pTechnoType);

for (auto const pBuilding : this->RestrictedFactoryPlants)
{
auto const pTypeExt = BuildingTypeExt::ExtMap.Find(pBuilding->Type);

if (pTypeExt->FactoryPlant_AllowTypes.size() > 0 && !pTypeExt->FactoryPlant_AllowTypes.Contains(pTechnoType))
continue;

if (pTypeExt->FactoryPlant_DisallowTypes.size() > 0 && pTypeExt->FactoryPlant_DisallowTypes.Contains(pTechnoType))
continue;

float currentMult = 1.0f;

switch (pTechnoType->WhatAmI())
{
case AbstractType::BuildingType:
if (((BuildingTypeClass*)pTechnoType)->BuildCat == BuildCat::Combat)
currentMult -= pBuilding->Type->DefensesCostBonus;
else
currentMult -= pBuilding->Type->BuildingsCostBonus;
break;
case AbstractType::AircraftType:
currentMult -= pBuilding->Type->AircraftCostBonus;
break;
case AbstractType::InfantryType:
currentMult -= pBuilding->Type->InfantryCostBonus;
break;
case AbstractType::UnitType:
currentMult -= pBuilding->Type->UnitsCostBonus;
break;
default:
break;
}

mult *= (1.0f - currentMult * pTechnoTypeExt->FactoryPlant_Multiplier);
}

return mult;
}

void HouseExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
{
const char* pSection = this->OwnerObject()->PlainName;
Expand Down Expand Up @@ -594,6 +638,7 @@ void HouseExt::ExtData::Serialize(T& Stm)
.Process(this->Factory_AircraftType)
.Process(this->AISuperWeaponDelayTimer)
.Process(this->RepairBaseNodes)
.Process(this->RestrictedFactoryPlants)
.Process(this->LastBuiltNavalVehicleType)
.Process(this->ProducingNavalUnitTypeIndex)
.Process(this->NumAirpads_NonMFB)
Expand Down Expand Up @@ -636,11 +681,21 @@ void HouseExt::ExtData::InvalidatePointer(void* ptr, bool bRemoved)
AnnounceInvalidPointer(Factory_NavyType, ptr);
AnnounceInvalidPointer(Factory_AircraftType, ptr);

if (!OwnedLimboDeliveredBuildings.empty() && ptr != nullptr)
if (ptr != nullptr)
{
auto& vec = this->OwnedLimboDeliveredBuildings;
vec.erase(std::remove(vec.begin(), vec.end(), reinterpret_cast<BuildingClass*>(ptr)), vec.end());
if (!OwnedLimboDeliveredBuildings.empty())
{
auto& vec = this->OwnedLimboDeliveredBuildings;
vec.erase(std::remove(vec.begin(), vec.end(), reinterpret_cast<BuildingClass*>(ptr)), vec.end());
}

if (!RestrictedFactoryPlants.empty())
{
auto& vec = this->RestrictedFactoryPlants;
vec.erase(std::remove(vec.begin(), vec.end(), reinterpret_cast<BuildingClass*>(ptr)), vec.end());
}
}

}

// =============================
Expand Down Expand Up @@ -723,7 +778,7 @@ CanBuildResult HouseExt::BuildLimitGroupCheck(const HouseClass* pThis, const Tec

if (!pItemExt->BuildLimitGroup_ExtraLimit_Types.empty() && !pItemExt->BuildLimitGroup_ExtraLimit_Nums.empty())
{
for (size_t i = 0; i < pItemExt->BuildLimitGroup_ExtraLimit_Types.size(); i ++)
for (size_t i = 0; i < pItemExt->BuildLimitGroup_ExtraLimit_Types.size(); i++)
{
int count = 0;
auto pTmpType = pItemExt->BuildLimitGroup_ExtraLimit_Types[i];
Expand Down Expand Up @@ -754,7 +809,7 @@ CanBuildResult HouseExt::BuildLimitGroupCheck(const HouseClass* pThis, const Tec
{
bool reachedLimit = false;

for (size_t i = 0; i < std::min(pItemExt->BuildLimitGroup_Types.size(), pItemExt->BuildLimitGroup_Nums.size()); i ++)
for (size_t i = 0; i < std::min(pItemExt->BuildLimitGroup_Types.size(), pItemExt->BuildLimitGroup_Nums.size()); i++)
{
TechnoTypeClass* pType = pItemExt->BuildLimitGroup_Types[i];
const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pType);
Expand Down Expand Up @@ -807,7 +862,7 @@ CanBuildResult HouseExt::BuildLimitGroupCheck(const HouseClass* pThis, const Tec
}
else
{
for (size_t i = 0; i < std::min(pItemExt->BuildLimitGroup_Types.size(), limits.size()); i ++)
for (size_t i = 0; i < std::min(pItemExt->BuildLimitGroup_Types.size(), limits.size()); i++)
{
TechnoTypeClass* pType = pItemExt->BuildLimitGroup_Types[i];
const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pType);
Expand Down Expand Up @@ -863,7 +918,7 @@ void RemoveProduction(const HouseClass* pHouse, const TechnoTypeClass* pType, in
if (num >= 0)
queued = Math::min(num, queued);

for (int i = 0; i < queued; i ++)
for (int i = 0; i < queued; i++)
{
pFactory->RemoveOneFromQueue(pType);
}
Expand All @@ -881,7 +936,7 @@ bool HouseExt::ReachedBuildLimit(const HouseClass* pHouse, const TechnoTypeClass

if (!pTypeExt->BuildLimitGroup_ExtraLimit_Types.empty() && !pTypeExt->BuildLimitGroup_ExtraLimit_Nums.empty())
{
for (size_t i = 0; i < pTypeExt->BuildLimitGroup_ExtraLimit_Types.size(); i ++)
for (size_t i = 0; i < pTypeExt->BuildLimitGroup_ExtraLimit_Types.size(); i++)
{
auto pTmpType = pTypeExt->BuildLimitGroup_ExtraLimit_Types[i];
const auto pBuildingType = abstract_cast<BuildingTypeClass*>(pTmpType);
Expand Down Expand Up @@ -953,7 +1008,7 @@ bool HouseExt::ReachedBuildLimit(const HouseClass* pHouse, const TechnoTypeClass
bool reached = true;
bool realReached = true;

for (size_t i = 0; i < size; i ++)
for (size_t i = 0; i < size; i++)
{
TechnoTypeClass* pTmpType = pTypeExt->BuildLimitGroup_Types[i];
const auto pTmpTypeExt = TechnoTypeExt::ExtMap.Find(pTmpType);
Expand Down
5 changes: 5 additions & 0 deletions src/Ext/House/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ class HouseExt
//Read from INI
bool RepairBaseNodes[3];

// FactoryPlants with Allow/DisallowTypes set.
std::vector<BuildingClass*> RestrictedFactoryPlants;

int LastBuiltNavalVehicleType;
int ProducingNavalUnitTypeIndex;

Expand All @@ -64,6 +67,7 @@ class HouseExt
, Factory_AircraftType { nullptr }
, AISuperWeaponDelayTimer {}
, RepairBaseNodes { false,false,false }
, RestrictedFactoryPlants {}
, LastBuiltNavalVehicleType { -1 }
, ProducingNavalUnitTypeIndex { -1 }
, NumAirpads_NonMFB { 0 }
Expand All @@ -79,6 +83,7 @@ class HouseExt
int CountOwnedPresentAndLimboed(TechnoTypeClass* pTechnoType);
void UpdateNonMFBFactoryCounts(AbstractType rtti, bool remove, bool isNaval);
int GetFactoryCountWithoutNonMFB(AbstractType rtti, bool isNaval);
float GetRestrictedFactoryPlantMult(TechnoTypeClass* pTechnoType) const;

virtual ~ExtData() = default;

Expand Down
2 changes: 2 additions & 0 deletions src/Ext/TechnoType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ void TechnoTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
this->UIDescription.Read(exINI, pSection, "UIDescription");
this->LowSelectionPriority.Read(exINI, pSection, "LowSelectionPriority");
this->MindControlRangeLimit.Read(exINI, pSection, "MindControlRangeLimit");
this->FactoryPlant_Multiplier.Read(exINI, pSection, "FactoryPlant.Multiplier");

this->Spawner_LimitRange.Read(exINI, pSection, "Spawner.LimitRange");
this->Spawner_ExtraLimitRange.Read(exINI, pSection, "Spawner.ExtraLimitRange");
Expand Down Expand Up @@ -484,6 +485,7 @@ void TechnoTypeExt::ExtData::Serialize(T& Stm)
.Process(this->UIDescription)
.Process(this->LowSelectionPriority)
.Process(this->MindControlRangeLimit)
.Process(this->FactoryPlant_Multiplier)

.Process(this->InterceptorType)

Expand Down
2 changes: 2 additions & 0 deletions src/Ext/TechnoType/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class TechnoTypeExt
Valueable<int> RadarJamRadius;
Nullable<int> InhibitorRange;
Nullable<int> DesignatorRange;
Valueable<float> FactoryPlant_Multiplier;
Valueable<Leptons> MindControlRangeLimit;

std::unique_ptr<InterceptorTypeClass> InterceptorType;
Expand Down Expand Up @@ -264,6 +265,7 @@ class TechnoTypeExt
, RadarJamRadius { 0 }
, InhibitorRange {}
, DesignatorRange { }
, FactoryPlant_Multiplier { 1.0 }
, MindControlRangeLimit {}

, InterceptorType { nullptr }
Expand Down
29 changes: 29 additions & 0 deletions src/Ext/TechnoType/Hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "Body.h"
#include <Ext/AnimType/Body.h>
#include <Ext/BulletType/Body.h>
#include <Ext/House/Body.h>
#include <Ext/Techno/Body.h>
#include <Ext/WarheadType/Body.h>
#include <Ext/WeaponType/Body.h>
Expand Down Expand Up @@ -761,3 +762,31 @@ DEFINE_HOOK(0x737F05, UnitClass_ReceiveDamage_SinkingWake, 0x6)

return 0x737F0B;
}

DEFINE_HOOK(0x711F39, TechnoTypeClass_CostOf_FactoryPlant, 0x8)
{
GET(TechnoTypeClass*, pThis, ESI);
GET(HouseClass*, pHouse, EDI);
REF_STACK(float, mult, STACK_OFFSET(0x10, -0x8));

auto const pHouseExt = HouseExt::ExtMap.Find(pHouse);

if (pHouseExt->RestrictedFactoryPlants.size() > 0)
mult *= pHouseExt->GetRestrictedFactoryPlantMult(pThis);

return 0;
}

DEFINE_HOOK(0x711FDF, TechnoTypeClass_RefundAmount_FactoryPlant, 0x8)
{
GET(TechnoTypeClass*, pThis, ESI);
GET(HouseClass*, pHouse, EDI);
REF_STACK(float, mult, STACK_OFFSET(0x10, -0x4));

auto const pHouseExt = HouseExt::ExtMap.Find(pHouse);

if (pHouseExt->RestrictedFactoryPlants.size() > 0)
mult *= pHouseExt->GetRestrictedFactoryPlantMult(pThis);

return 0;
}

0 comments on commit 8baebb6

Please sign in to comment.