From c1ea9b406ba6afb7671b746e15218afdb5ea1826 Mon Sep 17 00:00:00 2001 From: Otamaa Date: Sun, 18 Apr 2021 17:39:21 +0700 Subject: [PATCH 1/8] Implementing RadType Enumeration --- src/Enum/RadTypes.cpp | 105 +++++++++++++++++++++++++----------- src/Enum/RadTypes.h | 105 ++++++++++++++++++++++++------------ src/Ext/Bullet/Body.cpp | 6 +-- src/Ext/RadSite/Body.cpp | 52 ++++++++---------- src/Ext/RadSite/Body.h | 10 ++-- src/Ext/RadSite/Hooks.cpp | 97 ++++++++++++++++++++++++--------- src/Ext/Rules/Body.cpp | 1 + src/Ext/Rules/Body.h | 1 + src/Ext/WeaponType/Body.cpp | 20 +++---- src/Ext/WeaponType/Body.h | 2 +- src/Phobos.Ext.cpp | 4 +- 11 files changed, 264 insertions(+), 139 deletions(-) diff --git a/src/Enum/RadTypes.cpp b/src/Enum/RadTypes.cpp index 3d85bc72f9..93bc552ecf 100644 --- a/src/Enum/RadTypes.cpp +++ b/src/Enum/RadTypes.cpp @@ -1,28 +1,82 @@ #include "RadTypes.h" -#include -void RadType::Read(CCINIClass* const pINI, const char* pSection, const char* pKey) { - INI_EX exINI(pINI); +#include "../Utilities/TemplateDef.h" + +#include + +Enumerable::container_t Enumerable::Array; + +// pretty nice, eh +const char * Enumerable::GetMainSection() +{ + return "RadiationTypes"; +} + +RadType::RadType(const char* const pTitle) + : Enumerable(pTitle), + LevelDelay(), + LightDelay(), + RadSiteColor(), + LevelMax(), + LevelFactor(), + LightFactor(), + TintFactor(), + RadWarhead(), + DurationMultiple(), + ApplicationDelay(), + BuildingApplicationDelay() +{ } - this->ID.Read(pINI, pSection, "RadType"); - const char* section = this->ID; - - if (pINI->GetSection(section)) { - this->DurationMultiple.Read(exINI, section, "RadDurationMultiple"); - this->ApplicationDelay.Read(exINI, section, "RadApplicationDelay"); - this->BuildingApplicationDelay.Read(exINI, section, "RadApplicationDelay.Building"); - this->LevelMax.Read(exINI, section, "RadLevelMax"); - this->LevelDelay.Read(exINI, section, "RadLevelDelay"); - GeneralUtils::IntValidCheck(this->LevelDelay.GetEx(), section, "RadLevelDelay", 90, 1); - this->LightDelay.Read(exINI, section, "RadLightDelay"); - this->LevelFactor.Read(exINI, section, "RadLevelFactor"); - this->LightFactor.Read(exINI, section, "RadLightFactor"); - this->TintFactor.Read(exINI, section, "RadTintFactor"); - this->RadWarhead.Read(exINI, section, "RadSiteWarhead"); - this->RadSiteColor.Read(exINI, section, "RadColor"); +RadType::~RadType() = default; + +void RadType::AddDefaults() +{ + FindOrAllocate("Radiation"); +} + +void RadType::LoadListSection(CCINIClass *pINI) +{ + const char *section = GetMainSection(); + int len = pINI->GetKeyCount(section); + for (int i = 0; i < len; ++i) + { + const char *key = pINI->GetKeyName(section, i); + if (pINI->ReadString(section, key, "", Phobos::readBuffer)) + { + FindOrAllocate(Phobos::readBuffer); + Debug::Log("RadTypes :: LoadListSection check [%s] \n", Phobos::readBuffer); + } + } + + for (size_t i = 0; i < Array.size(); ++i) + { + Array[i]->LoadFromINI(pINI); } } +void RadType::LoadFromINI(CCINIClass *pINI) +{ + const char *section = this->Name; + + INI_EX exINI(pINI); + + this->RadWarhead.Read(exINI, section, "RadSiteWarhead" , true); + this->RadSiteColor.Read(exINI, section, "RadColor"); + this->DurationMultiple.Read(exINI, section, "RadDurationMultiple"); + this->ApplicationDelay.Read(exINI, section, "RadApplicationDelay"); + this->BuildingApplicationDelay.Read(exINI, section, "RadApplicationDelay.Building"); + this->LevelMax.Read(exINI, section, "RadLevelMax"); + this->LevelDelay.Read(exINI, section, "RadLevelDelay"); + this->LightDelay.Read(exINI, section, "RadLightDelay"); + this->LevelFactor.Read(exINI, section, "RadLevelFactor"); + this->LightFactor.Read(exINI, section, "RadLightFactor"); + this->TintFactor.Read(exINI, section, "RadTintFactor"); + + Debug::Log("RadTypes :: LoadFromINI check [%s] \n", section); +// Debug::Log("RadTypes :: LoadFromINI check [%s]->Warhead \n", this->GetWarhead()->Name); +// Debug::Log("RadTypes :: LoadFromINI check [%d %d %d]->Color \n", this->GetColor().R , this->GetColor().G, this->GetColor().B); +} + template void RadType::Serialize(T& Stm) { Stm @@ -36,27 +90,16 @@ void RadType::Serialize(T& Stm) { .Process(this->LightFactor) .Process(this->TintFactor) .Process(this->RadSiteColor) + .Process(this->RadWarhead) ; }; void RadType::LoadFromStream(PhobosStreamReader & Stm) { - Stm.Process(this->ID); - if (GeneralUtils::IsValidString(this->ID)) - { - char warheadID[sizeof(this->RadWarhead->ID)]; - Stm.Process(warheadID); - RadWarhead = WarheadTypeClass::FindOrAllocate(warheadID); this->Serialize(Stm); - } } void RadType::SaveToStream(PhobosStreamWriter & Stm) { - Stm.Process(this->ID); - if (GeneralUtils::IsValidString(this->ID)) - { - Stm.Process(this->RadWarhead->ID); this->Serialize(Stm); - } } diff --git a/src/Enum/RadTypes.h b/src/Enum/RadTypes.h index a7121037ab..fb6ea4d6b6 100644 --- a/src/Enum/RadTypes.h +++ b/src/Enum/RadTypes.h @@ -1,49 +1,86 @@ #pragma once +#include "_Enumerator.hpp" #include "../Utilities/Template.h" -#include "../Utilities/TemplateDef.h" #include "../Utilities/GeneralUtils.h" +#include "../Phobos.h" -#include +class CCINIClass; +class WarheadTypeClass; + +class RadType final : public Enumerable +{ +private: + Nullable DurationMultiple; + Nullable ApplicationDelay; + Nullable LevelFactor; + Nullable LevelMax; + Nullable LevelDelay; + Nullable LightDelay; + Nullable BuildingApplicationDelay; + Nullable RadWarhead; + Nullable RadSiteColor; + Nullable LightFactor; + Nullable TintFactor; -class RadType { public: - PhobosFixedString<0x20> ID; - Valueable DurationMultiple; - Valueable ApplicationDelay; - Valueable LevelMax; - Valueable LevelDelay; - Valueable LightDelay; - Valueable BuildingApplicationDelay; - Valueable LevelFactor; - Valueable LightFactor; - Valueable TintFactor; - Valueable RadSiteColor; - Valueable RadWarhead; - - // Set default values - // RadType::Read method will later read the new values from the section specified in the ID field - RadType(const char* id = "Radiation") : - ID(id), - DurationMultiple(1), - ApplicationDelay(16), - LevelMax(500), - LevelDelay(90), - LightDelay(90), - BuildingApplicationDelay(0), - LevelFactor(0.2f), - LightFactor(0.1f), - TintFactor(1.0f), - RadSiteColor(ColorStruct{ 0,255,0 }), - RadWarhead(nullptr) + + RadType(const char* pTitle); + + static void AddDefaults(); + + static void LoadListSection(CCINIClass * pINI); + + WarheadTypeClass* GetWarhead() const { - RadWarhead = WarheadTypeClass::FindOrAllocate("RadSite"); + return this->RadWarhead.Get(RulesClass::Instance->RadSiteWarhead); + } + + const ColorStruct& GetColor() const { + return *this->RadSiteColor.GetEx(&RulesClass::Instance->RadColor); + } + + int GetDurationMultiple() const { + return this->DurationMultiple.Get(RulesClass::Instance->RadDurationMultiple); + } + + int GetApplicationDelay() const { + return this->ApplicationDelay.Get(RulesClass::Instance->RadApplicationDelay); + } + + int GetBuildingApplicationDelay() const { + return this->BuildingApplicationDelay.Get(0); + } + + int GetLevelMax() const { + return this->LevelMax.Get(RulesClass::Instance->RadLevelMax); + } + + int GetLevelDelay() const { + return this->LevelDelay.Get(RulesClass::Instance->RadLevelDelay); + } + + int GetLightDelay() const { + return this->LightDelay.Get(RulesClass::Instance->RadLightDelay); + } + + double GetLevelFactor() const { + return this->LevelFactor.Get(RulesClass::Instance->RadLevelFactor); + } + + double GetLightFactor() const { + return this->LightFactor.Get(RulesClass::Instance->RadLightFactor); + } + + double GetTintFactor() const { + return this->TintFactor.Get(RulesClass::Instance->RadTintFactor); } - void Read(CCINIClass* const pINI, const char* section, const char* pKey); + virtual ~RadType() override; + virtual void LoadFromINI(CCINIClass *pINI) override; virtual void LoadFromStream(PhobosStreamReader& Stm); virtual void SaveToStream(PhobosStreamWriter& Stm); private: template void Serialize(T& Stm); -}; +}; \ No newline at end of file diff --git a/src/Ext/Bullet/Body.cpp b/src/Ext/Bullet/Body.cpp index a2a15e4dc1..8f117825fd 100644 --- a/src/Ext/Bullet/Body.cpp +++ b/src/Ext/Bullet/Body.cpp @@ -10,7 +10,7 @@ void BulletExt::ExtData::ApplyRadiationToCell(CellStruct Cell, int Spread, int R auto const& Instances = RadSiteExt::RadSiteInstance; auto const pWeapon = pThis->GetWeaponType(); auto const pWeaponExt = WeaponTypeExt::ExtMap.FindOrAllocate(pWeapon); - auto const pRadType = &pWeaponExt->RadType; + auto const pRadType = pWeaponExt->RadType; auto const pThisHouse = pThis->Owner ? pThis->Owner->Owner : nullptr; if (Instances.Count > 0) @@ -32,9 +32,9 @@ void BulletExt::ExtData::ApplyRadiationToCell(CellStruct Cell, int Spread, int R auto pRadExt = *it; auto pRadSite = pRadExt->OwnerObject(); - if (pRadSite->GetRadLevel() + RadLevel > pRadType->LevelMax) + if (pRadSite->GetRadLevel() + RadLevel > pRadType->GetLevelMax()) { - RadLevel = pRadType->LevelMax - pRadSite->GetRadLevel(); + RadLevel = pRadType->GetLevelMax() - pRadSite->GetRadLevel(); } // Handle It diff --git a/src/Ext/RadSite/Body.cpp b/src/Ext/RadSite/Body.cpp index d39df33e12..a36e660deb 100644 --- a/src/Ext/RadSite/Body.cpp +++ b/src/Ext/RadSite/Body.cpp @@ -7,53 +7,54 @@ RadSiteExt::ExtContainer RadSiteExt::ExtMap; DynamicVectorClass RadSiteExt::RadSiteInstance; -void RadSiteExt::CreateInstance(CellStruct location, int spread, int amount, WeaponTypeExt::ExtData* pWeaponExt, HouseClass* const pOwner) { +void RadSiteExt::CreateInstance(CellStruct location, int spread, int amount, WeaponTypeExt::ExtData* pWeaponExt, HouseClass* const pOwner) +{ // use real ctor auto const pRadSite = GameCreate(); - auto const cell = MapClass::Instance->TryGetCellAt(location); + // auto const cell = MapClass::Instance->TryGetCellAt(location); auto pRadExt = RadSiteExt::ExtMap.FindOrAllocate(pRadSite); //Adding Owner to RadSite , from bullet - if (!pWeaponExt->Rad_NoOwner && pRadExt->RadHouse != pOwner) { + if (!pWeaponExt->Rad_NoOwner && pRadExt->RadHouse != pOwner) + { pRadExt->RadHouse = pOwner; } pRadExt->Weapon = pWeaponExt->OwnerObject(); - pRadExt->Type = &pWeaponExt->RadType; - + pRadExt->Type = pWeaponExt->RadType; pRadSite->SetBaseCell(&location); pRadSite->SetSpread(spread); - pRadExt->SetRadLevel(amount); - pRadSite->Activate(); - cell->SetRadSite(pRadSite); RadSiteInstance.AddUnique(pRadExt); } /* Including them as EXT so it keep tracked at save/load */ // Rewrite because of crashing craziness -void RadSiteExt::ExtData::Add(int amount) { +void RadSiteExt::ExtData::Add(int amount) +{ auto pRad = this->OwnerObject(); int value = pRad->RadLevel * pRad->RadTimeLeft / pRad->RadDuration; pRad->Deactivate(); pRad->RadLevel = value + amount; - pRad->RadDuration = pRad->RadLevel * this->Type->DurationMultiple; + pRad->RadDuration = pRad->RadLevel * this->Type->GetDurationMultiple(); pRad->RadTimeLeft = pRad->RadDuration; pRad->Activate(); } -void RadSiteExt::ExtData::SetRadLevel(int amount) { +void RadSiteExt::ExtData::SetRadLevel(int amount) +{ auto pRad = this->OwnerObject(); - const int mult = this->Type->DurationMultiple; + const int mult = this->Type->GetDurationMultiple(); pRad->RadLevel = amount; pRad->RadDuration = mult * amount; pRad->RadTimeLeft = mult * amount; } // helper function provided by AlexB -double RadSiteExt::ExtData::GetRadLevelAt(CellStruct const& cell) { +double RadSiteExt::ExtData::GetRadLevelAt(CellStruct const& cell) +{ auto pThis = this->OwnerObject(); const auto base = MapClass::Instance->GetCellAt(pThis->BaseCell)->GetCoords(); const auto coords = MapClass::Instance->GetCellAt(cell)->GetCoords(); @@ -68,32 +69,25 @@ double RadSiteExt::ExtData::GetRadLevelAt(CellStruct const& cell) { // load / save template -void RadSiteExt::ExtData::Serialize(T& Stm) { +void RadSiteExt::ExtData::Serialize(T& Stm) +{ Stm + .Process(this->Weapon) .Process(this->RadHouse) + .Process(this->Type) ; } -void RadSiteExt::ExtData::LoadFromStream(PhobosStreamReader& Stm) { - //initialize weapon then set type - char weaponID[sizeof(this->Weapon->ID)]; - Stm.Process(weaponID); - this->Weapon = WeaponTypeClass::Find(weaponID); - - if (this->Weapon) { - auto pWeaponTypeExt = WeaponTypeExt::ExtMap.FindOrAllocate(Weapon); +void RadSiteExt::ExtData::LoadFromStream(PhobosStreamReader& Stm) +{ - if (pWeaponTypeExt) { - this->Type = &pWeaponTypeExt->RadType; - } - } Extension::LoadFromStream(Stm); this->Serialize(Stm); } -void RadSiteExt::ExtData::SaveToStream(PhobosStreamWriter& Stm) { - //Save weapon ID instead - Stm.Process(this->Weapon->ID); +void RadSiteExt::ExtData::SaveToStream(PhobosStreamWriter& Stm) +{ + Extension::SaveToStream(Stm); this->Serialize(Stm); } diff --git a/src/Ext/RadSite/Body.h b/src/Ext/RadSite/Body.h index a54ed430b2..bc93fc5cf7 100644 --- a/src/Ext/RadSite/Body.h +++ b/src/Ext/RadSite/Body.h @@ -16,12 +16,14 @@ class RadSiteExt { class ExtData final : public Extension { public: - WeaponTypeClass* Weapon; - RadType* Type; - HouseClass* RadHouse; + Valueable Weapon; + Valueable Type; + Valueable RadHouse; ExtData(RadSiteClass* OwnerObject) : Extension(OwnerObject), - RadHouse(nullptr) + RadHouse(nullptr), + Type(), + Weapon(nullptr) { }; virtual ~ExtData() { } diff --git a/src/Ext/RadSite/Hooks.cpp b/src/Ext/RadSite/Hooks.cpp index 5fae11b335..ccf1d72494 100644 --- a/src/Ext/RadSite/Hooks.cpp +++ b/src/Ext/RadSite/Hooks.cpp @@ -1,6 +1,8 @@ #include "Body.h" #include #include +#include +#include #include "../BuildingType/Body.h" #include "../Bullet/Body.h" @@ -28,7 +30,8 @@ DEFINE_HOOK(469150, B_Detonate_ApplyRad, 5) auto const pWeapon = pThis->GetWeaponType(); auto const pWH = pThis->WH; - if (pWeapon && pWeapon->RadLevel > 0) { + if (pWeapon && pWeapon->RadLevel > 0) + { auto const cell = CellClass::Coord2Cell(*pCoords); auto const spread = static_cast(pWH->CellSpread); pExt->ApplyRadiationToCell(cell, spread, pWeapon->RadLevel); @@ -82,21 +85,60 @@ DEFINE_HOOK(46ADE0, BulletClass_ApplyRadiation, 5) return 0x46AE5E; } */ +DEFINE_HOOK(5213E3, InfantryClass_AIDeployment_CheckRad, 4) +{ + GET(InfantryClass*, D, ESI); + GET(int, WeaponRadLevel, EBX); + + auto const& Instances = RadSiteExt::RadSiteInstance; + auto const pWeapon = D->GetWeapon(1)->WeaponType; + + int RadLevel = 0; + if (Instances.Count > 0 && pWeapon) + { + auto const pWeaponExt = WeaponTypeExt::ExtMap.FindOrAllocate(pWeapon); + auto const pRadType = pWeaponExt->RadType; + auto const WH = pWeapon->Warhead; + auto CurrentCoord = D->GetCell()->MapCoords; + + auto const it = std::find_if(Instances.begin(), Instances.end(), + [=](RadSiteExt::ExtData* const pSite) // Lambda + {// find + return + pSite->Type == pRadType && + pSite->OwnerObject()->BaseCell == CurrentCoord && + pSite->OwnerObject()->Spread == static_cast(WH->CellSpread) + ; + }); + + if (it != Instances.end()) + { + auto pRadExt = *it; + auto pRadSite = pRadExt->OwnerObject(); + RadLevel = pRadSite->GetRadLevel(); + } + } + + return (RadLevel < WeaponRadLevel) ? 0x5213F4 : 0x521484; +} + // Too OP, be aware DEFINE_HOOK(43FB23, BuildingClass_AI, 5) { GET(BuildingClass* const, pBuilding, ECX); - if (pBuilding->IsIronCurtained() || pBuilding->Type->ImmuneToRadiation || pBuilding->InLimbo) { + if (pBuilding->IsIronCurtained() || pBuilding->Type->ImmuneToRadiation || pBuilding->InLimbo || !pBuilding->BeingWarpedOut) { return 0; } auto const MainCoords = pBuilding->GetMapCoords(); - for (auto pFoundation = pBuilding->GetFoundationData(false); *pFoundation != CellStruct{ 0x7FFF, 0x7FFF }; ++pFoundation) { + for (auto pFoundation = pBuilding->GetFoundationData(false); *pFoundation != CellStruct{ 0x7FFF, 0x7FFF }; ++pFoundation) + { CellStruct CurrentCoord = MainCoords + *pFoundation; - for (auto pRadExt : RadSiteExt::RadSiteInstance) { + for (auto pRadExt : RadSiteExt::RadSiteInstance) + { RadSiteClass* pRadSite = pRadExt->OwnerObject(); // Check the distance, if not in range, just skip this one @@ -105,25 +147,26 @@ DEFINE_HOOK(43FB23, BuildingClass_AI, 5) continue; RadType* pType = pRadExt->Type; - int RadApplicationDelay = pType->BuildingApplicationDelay; + int RadApplicationDelay = pType->GetBuildingApplicationDelay(); if ((RadApplicationDelay == 0) || (Unsorted::CurrentFrame % RadApplicationDelay != 0)) continue; // for more precise dmg calculation double RadLevel = pRadExt->GetRadLevelAt(CurrentCoord); - if (RadLevel <= 0 || !pType->RadWarhead) + auto WH = pType->GetWarhead(); + if (RadLevel <= 0 || !WH) continue; // will prevent passanger escapes - bool absolute = pType->RadWarhead->WallAbsoluteDestroyer; + bool absolute = WH->WallAbsoluteDestroyer; // will ignore verses bool ignore = pBuilding->Type->Wall && absolute; - int damage = static_cast((RadLevel / 2) * pType->LevelFactor); + int damage = static_cast((RadLevel / 2) * pType->GetLevelFactor()); int distance = static_cast(orDistance); - pBuilding->ReceiveDamage(&damage, distance, pType->RadWarhead, nullptr, ignore, absolute, pRadExt->RadHouse); + pBuilding->ReceiveDamage(&damage, distance, WH, nullptr, ignore, absolute, pRadExt->RadHouse); } } @@ -136,12 +179,14 @@ DEFINE_HOOK(4DA554, FootClass_AI_RadSiteClass, 5) { GET(FootClass* const, pFoot, ESI); - if (!pFoot->IsIronCurtained() && !pFoot->GetTechnoType()->ImmuneToRadiation && !pFoot->InLimbo && !pFoot->IsInAir()) { + if (!pFoot->IsIronCurtained() && !pFoot->GetTechnoType()->ImmuneToRadiation && !pFoot->InLimbo && !pFoot->IsInAir()) + { CellStruct CurrentCoord = pFoot->GetCell()->MapCoords; // Loop for each different radiation stored in the RadSites container - for (auto const pRadExt : RadSiteExt::RadSiteInstance) { + for (auto const pRadExt : RadSiteExt::RadSiteInstance) + { RadSiteClass* pRadSite = pRadExt->OwnerObject(); @@ -151,22 +196,23 @@ DEFINE_HOOK(4DA554, FootClass_AI_RadSiteClass, 5) continue; RadType* pType = pRadExt->Type; - int RadApplicationDelay = pType->ApplicationDelay; + int RadApplicationDelay = pType->GetApplicationDelay(); if ((RadApplicationDelay == 0) || (Unsorted::CurrentFrame % RadApplicationDelay != 0)) continue; // for more precise dmg calculation double RadLevel = pRadExt->GetRadLevelAt(CurrentCoord); - if (RadLevel <= 0 || !pType->RadWarhead) + auto WH = pType->GetWarhead(); + if (RadLevel <= 0 || !WH) continue; // will prevent passenger escapes - bool absolute = pType->RadWarhead->WallAbsoluteDestroyer; + bool absolute = WH->WallAbsoluteDestroyer; - int Damage = static_cast(RadLevel * pType->LevelFactor); + int Damage = static_cast(RadLevel * pType->GetLevelFactor()); int Distance = static_cast(orDistance); - pFoot->ReceiveDamage(&Damage, Distance, pType->RadWarhead, nullptr, false, absolute, pRadExt->RadHouse); + pFoot->ReceiveDamage(&Damage, Distance, WH, nullptr, false, absolute, pRadExt->RadHouse); } } @@ -179,10 +225,11 @@ DEFINE_HOOK(65B593, RadSiteClass_Activate_Delay, 6) auto const pExt = RadSiteExt::ExtMap.Find(pThis); auto const CurrentLevel = pThis->GetRadLevel(); - auto LevelDelay = pExt->Type->LevelDelay; - auto LightDelay = pExt->Type->LightDelay; + auto LevelDelay = pExt->Type->GetLevelDelay(); + auto LightDelay = pExt->Type->GetLightDelay(); - if (CurrentLevel < LevelDelay) { + if (CurrentLevel < LevelDelay) + { LevelDelay = CurrentLevel; LightDelay = CurrentLevel; } @@ -198,7 +245,7 @@ DEFINE_HOOK(65B5CE, RadSiteClass_Activate_Color, 6) GET(RadSiteClass* const, pThis, ESI); auto pExt = RadSiteExt::ExtMap.Find(pThis); - ColorStruct pRadColor = pExt->Type->RadSiteColor; + ColorStruct pRadColor = pExt->Type->GetColor(); R->EAX(0); R->EDX(0); @@ -221,7 +268,7 @@ DEFINE_HOOK(65B63E, RadSiteClass_Activate_LightFactor, 6) GET(RadSiteClass* const, Rad, ESI); auto pRadExt = RadSiteExt::ExtMap.Find(Rad); - auto lightFactor = pRadExt->Type->LightFactor; + auto lightFactor = pRadExt->Type->GetLightFactor(); __asm fmul lightFactor; @@ -235,7 +282,7 @@ DEFINE_HOOK(65B6F2, RadSiteClass_Activate_TintFactor, 6) GET(RadSiteClass* const, Rad, ESI); auto pRadExt = RadSiteExt::ExtMap.Find(Rad); - double tintFactor = pRadExt->Type->TintFactor; + double tintFactor = pRadExt->Type->GetTintFactor(); __asm fmul tintFactor; @@ -247,7 +294,7 @@ DEFINE_HOOK(65B843, RadSiteClass_AI_LevelDelay, 6) GET(RadSiteClass* const, Rad, ESI); auto pRadExt = RadSiteExt::ExtMap.Find(Rad); - auto delay = pRadExt->Type->LevelDelay; + auto delay = pRadExt->Type->GetLevelDelay(); R->ECX(delay); @@ -259,7 +306,7 @@ DEFINE_HOOK(65B8B9, RadSiteClass_AI_LightDelay, 6) GET(RadSiteClass* const, Rad, ESI); auto pRadExt = RadSiteExt::ExtMap.Find(Rad); - auto delay = pRadExt->Type->LightDelay; + auto delay = pRadExt->Type->GetLightDelay(); R->ECX(delay); @@ -272,7 +319,7 @@ DEFINE_HOOK(65BB67, RadSite_Deactivate, 6) GET(const RadSiteClass*, Rad, ECX); auto pRadExt = RadSiteExt::ExtMap.Find(Rad); - auto delay = pRadExt->Type->LevelDelay; + auto delay = pRadExt->Type->GetLevelDelay(); R->ESI(delay); diff --git a/src/Ext/Rules/Body.cpp b/src/Ext/Rules/Body.cpp index cf10c66ae4..32b3c2f31d 100644 --- a/src/Ext/Rules/Body.cpp +++ b/src/Ext/Rules/Body.cpp @@ -22,6 +22,7 @@ void RulesExt::LoadFromINIFile(RulesClass* pThis, CCINIClass* pINI) { void RulesExt::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI) { + RadType::LoadListSection(pINI); Data->LoadBeforeTypeData(pThis, pINI); } diff --git a/src/Ext/Rules/Body.h b/src/Ext/Rules/Body.h index b0ca36f50c..f3b509f0fb 100644 --- a/src/Ext/Rules/Body.h +++ b/src/Ext/Rules/Body.h @@ -7,6 +7,7 @@ #include "../../Utilities/Constructs.h" #include "../../Utilities/Template.h" +#include "../../Enum/RadTypes.h" #include "../../Misc/Debug.h" diff --git a/src/Ext/WeaponType/Body.cpp b/src/Ext/WeaponType/Body.cpp index 114ed74326..7460281b86 100644 --- a/src/Ext/WeaponType/Body.cpp +++ b/src/Ext/WeaponType/Body.cpp @@ -3,7 +3,10 @@ template<> const DWORD Extension::Canary = 0x22222222; WeaponTypeExt::ExtContainer WeaponTypeExt::ExtMap; -void WeaponTypeExt::ExtData::Initialize() { } +void WeaponTypeExt::ExtData::Initialize() +{ + this->RadType = RadType::FindOrAllocate("Radiation"); +} // ============================= // load / save @@ -28,11 +31,12 @@ void WeaponTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) this->Bolt_Disable3.Read(exINI, pSection, "Bolt.Disable3"); // RadType - if (this->OwnerObject()->RadLevel > 0) - { - this->RadType.Read(pINI, pSection, "RadType"); +// if (this->OwnerObject()->RadLevel > 0) +// { + this->RadType.Read(exINI, pSection, "RadType", true); + // Debug::Log("Weapon[%s] :: Has RadLevel[%d] Rad check [%s] \n", pSection , this->OwnerObject()->RadLevel , this->RadType->Name.data()); this->Rad_NoOwner.Read(exINI, pSection, "Rad.NoOwner"); - } +// } this->Strafing_Shots.Read(exINI, pSection, "Strafing.Shots"); this->Strafing_SimulateBurst.Read(exINI, pSection, "Strafing.SimulateBurst"); @@ -50,6 +54,7 @@ void WeaponTypeExt::ExtData::Serialize(T& Stm) .Process(this->Bolt_Disable3) .Process(this->Strafing_Shots) .Process(this->Strafing_SimulateBurst) + .Process(this->RadType) ; }; @@ -58,17 +63,12 @@ void WeaponTypeExt::ExtData::LoadFromStream(PhobosStreamReader& Stm) Extension::LoadFromStream(Stm); this->Serialize(Stm); - if (this->OwnerObject()->RadLevel > 0) - this->RadType.LoadFromStream(Stm); } void WeaponTypeExt::ExtData::SaveToStream(PhobosStreamWriter& Stm) { Extension::SaveToStream(Stm); this->Serialize(Stm); - - if (this->OwnerObject()->RadLevel > 0) - this->RadType.SaveToStream(Stm); } bool WeaponTypeExt::LoadGlobals(PhobosStreamReader& Stm) diff --git a/src/Ext/WeaponType/Body.h b/src/Ext/WeaponType/Body.h index 0b5ca5448e..f2b3a584bb 100644 --- a/src/Ext/WeaponType/Body.h +++ b/src/Ext/WeaponType/Body.h @@ -18,7 +18,7 @@ class WeaponTypeExt Valueable DiskLaser_Radius; Valueable DiskLaser_Circumference; - RadType RadType; + Valueable RadType; Valueable Rad_NoOwner; Valueable Bolt_Disable1; Valueable Bolt_Disable2; diff --git a/src/Phobos.Ext.cpp b/src/Phobos.Ext.cpp index b52dde0dfd..aa1ccd2f48 100644 --- a/src/Phobos.Ext.cpp +++ b/src/Phobos.Ext.cpp @@ -228,9 +228,9 @@ auto MassActions = MassAction < TechnoTypeExt, TerrainTypeExt, WarheadTypeExt, - WeaponTypeExt + WeaponTypeExt, // enum classes - + RadType // other classes > (); From bcf1ee729cfec7e4ad4f2eadc1535673d49b34f1 Mon Sep 17 00:00:00 2001 From: Otamaa Date: Mon, 19 Apr 2021 06:12:35 +0700 Subject: [PATCH 2/8] Bug fix Multiple RadSite on same area causing inf play mutiple death animation/generating multiple UnitToInf --- src/Ext/RadSite/Hooks.cpp | 110 +++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 44 deletions(-) diff --git a/src/Ext/RadSite/Hooks.cpp b/src/Ext/RadSite/Hooks.cpp index ccf1d72494..e32f55ac29 100644 --- a/src/Ext/RadSite/Hooks.cpp +++ b/src/Ext/RadSite/Hooks.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "../BuildingType/Body.h" #include "../Bullet/Body.h" @@ -57,7 +58,7 @@ DEFINE_HOOK(46ADE0, BulletClass_ApplyRadiation, 5) if (Instances.Count > 0) { auto const it = std::find_if(Instances.begin(), Instances.end(), [=](RadSiteExt::ExtData* const pSite) // Lambda - {// find + {// find return pSite->Type == pRadType && pSite->OwnerObject()->BaseCell == location && spread == pSite->OwnerObject()->Spread; @@ -74,7 +75,7 @@ DEFINE_HOOK(46ADE0, BulletClass_ApplyRadiation, 5) amount = pRadType->LevelMax - pRadSite->GetRadLevel(); } - // Handle It + // Handle It pRadExt->Add(amount); } } @@ -127,46 +128,50 @@ DEFINE_HOOK(43FB23, BuildingClass_AI, 5) { GET(BuildingClass* const, pBuilding, ECX); - if (pBuilding->IsIronCurtained() || pBuilding->Type->ImmuneToRadiation || pBuilding->InLimbo || !pBuilding->BeingWarpedOut) { - return 0; - } - - auto const MainCoords = pBuilding->GetMapCoords(); - - for (auto pFoundation = pBuilding->GetFoundationData(false); *pFoundation != CellStruct{ 0x7FFF, 0x7FFF }; ++pFoundation) + if (!pBuilding->IsIronCurtained() || !pBuilding->Type->ImmuneToRadiation || !pBuilding->InLimbo || !pBuilding->BeingWarpedOut) { - CellStruct CurrentCoord = MainCoords + *pFoundation; + auto const MainCoords = pBuilding->GetMapCoords(); + DynamicVectorClass eligible; - for (auto pRadExt : RadSiteExt::RadSiteInstance) + for (auto pFoundation = pBuilding->GetFoundationData(false); *pFoundation != CellStruct{ 0x7FFF, 0x7FFF }; ++pFoundation) { - RadSiteClass* pRadSite = pRadExt->OwnerObject(); - - // Check the distance, if not in range, just skip this one - double orDistance = pRadSite->BaseCell.DistanceFrom(CurrentCoord); - if (pRadSite->Spread < orDistance - 0.5) - continue; + CellStruct CurrentCoord = MainCoords + *pFoundation; - RadType* pType = pRadExt->Type; - int RadApplicationDelay = pType->GetBuildingApplicationDelay(); - if ((RadApplicationDelay == 0) || (Unsorted::CurrentFrame % RadApplicationDelay != 0)) - continue; + for (auto pRadExt : RadSiteExt::RadSiteInstance) + { + RadSiteClass* pRadSite = pRadExt->OwnerObject(); - // for more precise dmg calculation - double RadLevel = pRadExt->GetRadLevelAt(CurrentCoord); - auto WH = pType->GetWarhead(); - if (RadLevel <= 0 || !WH) - continue; + // Check the distance, if not in range, just skip this one + double orDistance = pRadSite->BaseCell.DistanceFrom(CurrentCoord); + if (pRadSite->Spread < orDistance - 0.5) + continue; - // will prevent passanger escapes - bool absolute = WH->WallAbsoluteDestroyer; + RadType* pType = pRadExt->Type; + int RadApplicationDelay = pType->GetBuildingApplicationDelay(); + if ((RadApplicationDelay == 0) || (Unsorted::CurrentFrame % RadApplicationDelay != 0)) + continue; - // will ignore verses - bool ignore = pBuilding->Type->Wall && absolute; + // for more precise dmg calculation + double RadLevel = pRadExt->GetRadLevelAt(CurrentCoord); + if (RadLevel <= 0.0 || !pType->GetWarhead()) + continue; - int damage = static_cast((RadLevel / 2) * pType->GetLevelFactor()); - int distance = static_cast(orDistance); + eligible.AddUnique(pRadSite); + } - pBuilding->ReceiveDamage(&damage, distance, WH, nullptr, ignore, absolute, pRadExt->RadHouse); + if (eligible.Count > 0) + { + auto eligibleRad = eligible.GetItem(ScenarioClass::Instance->Random.Random() % eligible.Count); + auto eligibleext = RadSiteExt::ExtMap.Find(eligibleRad); + auto WH = eligibleext->Type->GetWarhead(); + auto absolute = WH->WallAbsoluteDestroyer; + int Damage = static_cast((eligibleext->GetRadLevelAt(CurrentCoord) / 2) * eligibleext->Type->GetLevelFactor()); + int Distance = static_cast(eligibleRad->BaseCell.DistanceFrom(CurrentCoord)); + auto Radhouse = eligibleext->RadHouse; + bool ignore = pBuilding->Type->Wall && absolute; + + pBuilding->ReceiveDamage(&Damage, Distance, WH, nullptr, ignore, absolute, Radhouse); + } } } @@ -179,9 +184,9 @@ DEFINE_HOOK(4DA554, FootClass_AI_RadSiteClass, 5) { GET(FootClass* const, pFoot, ESI); - if (!pFoot->IsIronCurtained() && !pFoot->GetTechnoType()->ImmuneToRadiation && !pFoot->InLimbo && !pFoot->IsInAir()) + if (!pFoot->IsIronCurtained() && !pFoot->GetTechnoType()->ImmuneToRadiation && !pFoot->InLimbo && !pFoot->IsInAir() && pFoot->IsAlive) { - + DynamicVectorClass eligible; CellStruct CurrentCoord = pFoot->GetCell()->MapCoords; // Loop for each different radiation stored in the RadSites container @@ -202,21 +207,38 @@ DEFINE_HOOK(4DA554, FootClass_AI_RadSiteClass, 5) // for more precise dmg calculation double RadLevel = pRadExt->GetRadLevelAt(CurrentCoord); - auto WH = pType->GetWarhead(); - if (RadLevel <= 0 || !WH) + if (RadLevel <= 0.0 || !pType->GetWarhead()) continue; - // will prevent passenger escapes - bool absolute = WH->WallAbsoluteDestroyer; - - int Damage = static_cast(RadLevel * pType->GetLevelFactor()); - int Distance = static_cast(orDistance); + //put eligible RadSite inside DynamicVector + eligible.AddUnique(pRadSite); + } - pFoot->ReceiveDamage(&Damage, Distance, WH, nullptr, false, absolute, pRadExt->RadHouse); + //put this outsise the loop + //fixing bugs that cause multiple rad site on single area generating multiple animtoinf/death anims + if (eligible.Count > 0) + { + auto eligibleRad = eligible.GetItem(ScenarioClass::Instance->Random.Random() % eligible.Count); + auto eligibleext = RadSiteExt::ExtMap.Find(eligibleRad); + auto WH = eligibleext->Type->GetWarhead(); + auto absolute = WH->WallAbsoluteDestroyer; + int Damage = static_cast(eligibleext->GetRadLevelAt(CurrentCoord) * eligibleext->Type->GetLevelFactor()); + int Distance = static_cast(eligibleRad->BaseCell.DistanceFrom(CurrentCoord)); + auto Radhouse = eligibleext->RadHouse; + + pFoot->ReceiveDamage(&Damage, Distance, WH, nullptr, false, absolute, Radhouse); } } - return pFoot->IsAlive ? 0x4DA63Bu : 0x4DAF00; + if (pFoot->IsAlive) + { + return 0x4DA63B; + } + else + { + R->EAX(DamageState::NowDead); + return 0x4DAF00; + } } DEFINE_HOOK(65B593, RadSiteClass_Activate_Delay, 6) From bb31ee0eb1426ea7d7a36560b420bf37b31ef981 Mon Sep 17 00:00:00 2001 From: Otamaa Date: Mon, 19 Apr 2021 17:34:57 +0700 Subject: [PATCH 3/8] New Instances without Rely on Wepon experimental stuffs , it breaks Inf_AIDeploy_Check rad fix --- src/Enum/RadTypes.cpp | 4 +- src/Enum/RadTypes.h | 6 +-- src/Ext/RadSite/Body.cpp | 18 ++++++++ src/Ext/RadSite/Body.h | 2 +- src/Ext/RadSite/Hooks.cpp | 90 +++++++++++++++++++++------------------ src/Ext/Rules/Body.cpp | 5 ++- src/Ext/Rules/Body.h | 2 + 7 files changed, 76 insertions(+), 51 deletions(-) diff --git a/src/Enum/RadTypes.cpp b/src/Enum/RadTypes.cpp index 93bc552ecf..87ecc03d8b 100644 --- a/src/Enum/RadTypes.cpp +++ b/src/Enum/RadTypes.cpp @@ -49,9 +49,7 @@ void RadType::LoadListSection(CCINIClass *pINI) } for (size_t i = 0; i < Array.size(); ++i) - { - Array[i]->LoadFromINI(pINI); - } + { Array[i]->LoadFromINI(pINI); } } void RadType::LoadFromINI(CCINIClass *pINI) diff --git a/src/Enum/RadTypes.h b/src/Enum/RadTypes.h index fb6ea4d6b6..1bba8928c8 100644 --- a/src/Enum/RadTypes.h +++ b/src/Enum/RadTypes.h @@ -17,7 +17,7 @@ class RadType final : public Enumerable Nullable LevelMax; Nullable LevelDelay; Nullable LightDelay; - Nullable BuildingApplicationDelay; + Nullable RadWarhead; Nullable RadSiteColor; Nullable LightFactor; @@ -48,9 +48,7 @@ class RadType final : public Enumerable return this->ApplicationDelay.Get(RulesClass::Instance->RadApplicationDelay); } - int GetBuildingApplicationDelay() const { - return this->BuildingApplicationDelay.Get(0); - } + Nullable BuildingApplicationDelay; int GetLevelMax() const { return this->LevelMax.Get(RulesClass::Instance->RadLevelMax); diff --git a/src/Ext/RadSite/Body.cpp b/src/Ext/RadSite/Body.cpp index a36e660deb..2f8d5c4be9 100644 --- a/src/Ext/RadSite/Body.cpp +++ b/src/Ext/RadSite/Body.cpp @@ -29,6 +29,24 @@ void RadSiteExt::CreateInstance(CellStruct location, int spread, int amount, Wea RadSiteInstance.AddUnique(pRadExt); } +void RadSiteExt::CreateInstance(CellStruct location, int spread, int amount, RadType* pType, HouseClass* const pOwner) +{ + // use real ctor + auto const pRadSite = GameCreate(); + + auto pRadExt = RadSiteExt::ExtMap.FindOrAllocate(pRadSite); + + pRadExt->RadHouse = pOwner; + + + pRadExt->Type = pType; + pRadSite->SetBaseCell(&location); + pRadSite->SetSpread(spread); + pRadExt->SetRadLevel(amount); + pRadSite->Activate(); + RadSiteInstance.AddUnique(pRadExt); +} + /* Including them as EXT so it keep tracked at save/load */ // Rewrite because of crashing craziness diff --git a/src/Ext/RadSite/Body.h b/src/Ext/RadSite/Body.h index bc93fc5cf7..caf873acf6 100644 --- a/src/Ext/RadSite/Body.h +++ b/src/Ext/RadSite/Body.h @@ -48,7 +48,7 @@ class RadSiteExt { static DynamicVectorClass RadSiteInstance; static void CreateInstance(CellStruct location, int spread, int amount, WeaponTypeExt::ExtData *pWeaponExt, HouseClass* const pOwner); - + static void CreateInstance(CellStruct location, int spread, int amount, RadType* pType, HouseClass* const pOwner); class ExtContainer final : public Container { public: ExtContainer(); diff --git a/src/Ext/RadSite/Hooks.cpp b/src/Ext/RadSite/Hooks.cpp index e32f55ac29..13b3b1df87 100644 --- a/src/Ext/RadSite/Hooks.cpp +++ b/src/Ext/RadSite/Hooks.cpp @@ -7,6 +7,7 @@ #include "../BuildingType/Body.h" #include "../Bullet/Body.h" +#include "../Rules/Body.h" /* Custom Radiations @@ -22,17 +23,17 @@ //4DA584 = FootClass_AI_RadImmune, 7 */ -DEFINE_HOOK(469150, B_Detonate_ApplyRad, 5) +DEFINE_HOOK(469150, BulletClass_Detonate_ApplyRadiation, 5) { GET(BulletClass* const, pThis, ESI); GET_BASE(CoordStruct const*, pCoords, 0x8); - auto const pExt = BulletExt::ExtMap.Find(pThis); auto const pWeapon = pThis->GetWeaponType(); - auto const pWH = pThis->WH; if (pWeapon && pWeapon->RadLevel > 0) { + auto const pExt = BulletExt::ExtMap.Find(pThis); + auto const pWH = pThis->WH; auto const cell = CellClass::Coord2Cell(*pCoords); auto const spread = static_cast(pWH->CellSpread); pExt->ApplyRadiationToCell(cell, spread, pWeapon->RadLevel); @@ -40,11 +41,13 @@ DEFINE_HOOK(469150, B_Detonate_ApplyRad, 5) return 0x46920B; } + /* // hack it here so we can use this globally if needed +// *Prototype* +//able to manually set the RadType instead rely on Weapon RadType DEFINE_HOOK(46ADE0, BulletClass_ApplyRadiation, 5) { - GET(BulletClass* const, pThis, ECX); GET_STACK(CellStruct, location, 0x4); GET_STACK(int, spread, 0x8); GET_STACK(int, amount, 0xC); @@ -86,6 +89,7 @@ DEFINE_HOOK(46ADE0, BulletClass_ApplyRadiation, 5) return 0x46AE5E; } */ + DEFINE_HOOK(5213E3, InfantryClass_AIDeployment_CheckRad, 4) { GET(InfantryClass*, D, ESI); @@ -128,53 +132,55 @@ DEFINE_HOOK(43FB23, BuildingClass_AI, 5) { GET(BuildingClass* const, pBuilding, ECX); - if (!pBuilding->IsIronCurtained() || !pBuilding->Type->ImmuneToRadiation || !pBuilding->InLimbo || !pBuilding->BeingWarpedOut) + if (pBuilding->IsIronCurtained() || pBuilding->Type->ImmuneToRadiation || pBuilding->InLimbo || pBuilding->BeingWarpedOut) { - auto const MainCoords = pBuilding->GetMapCoords(); - DynamicVectorClass eligible; + return 0; + } - for (auto pFoundation = pBuilding->GetFoundationData(false); *pFoundation != CellStruct{ 0x7FFF, 0x7FFF }; ++pFoundation) + auto const MainCoords = pBuilding->GetMapCoords(); + DynamicVectorClass eligible; + + for (auto pFoundation = pBuilding->GetFoundationData(false); *pFoundation != CellStruct{ 0x7FFF, 0x7FFF }; ++pFoundation) + { + CellStruct CurrentCoord = MainCoords + *pFoundation; + + for (auto pRadExt : RadSiteExt::RadSiteInstance) { - CellStruct CurrentCoord = MainCoords + *pFoundation; + RadSiteClass* pRadSite = pRadExt->OwnerObject(); - for (auto pRadExt : RadSiteExt::RadSiteInstance) - { - RadSiteClass* pRadSite = pRadExt->OwnerObject(); + // Check the distance, if not in range, just skip this one + double orDistance = pRadSite->BaseCell.DistanceFrom(CurrentCoord); + if (pRadSite->Spread < orDistance - 0.5) + continue; + + RadType* pType = pRadExt->Type; + int RadApplicationDelay = pType->BuildingApplicationDelay.Get(RulesExt::Global()->RadApplDelayBuilding); + if ((RadApplicationDelay == 0) || (Unsorted::CurrentFrame % RadApplicationDelay != 0)) + continue; - // Check the distance, if not in range, just skip this one - double orDistance = pRadSite->BaseCell.DistanceFrom(CurrentCoord); - if (pRadSite->Spread < orDistance - 0.5) - continue; + if (pRadExt->GetRadLevelAt(CurrentCoord) <= 0.0 || !pType->GetWarhead()) + continue; - RadType* pType = pRadExt->Type; - int RadApplicationDelay = pType->GetBuildingApplicationDelay(); - if ((RadApplicationDelay == 0) || (Unsorted::CurrentFrame % RadApplicationDelay != 0)) - continue; - // for more precise dmg calculation - double RadLevel = pRadExt->GetRadLevelAt(CurrentCoord); - if (RadLevel <= 0.0 || !pType->GetWarhead()) - continue; + eligible.AddUnique(pRadSite); + } - eligible.AddUnique(pRadSite); - } + if (eligible.Count > 0) + { + auto eligibleRad = eligible.GetItem(ScenarioClass::Instance->Random.Random() % eligible.Count); + auto eligibleext = RadSiteExt::ExtMap.Find(eligibleRad); + auto WH = eligibleext->Type->GetWarhead(); + auto absolute = WH->WallAbsoluteDestroyer; + int Damage = static_cast((eligibleext->GetRadLevelAt(CurrentCoord) / 2) * eligibleext->Type->GetLevelFactor()); + int Distance = static_cast(eligibleRad->BaseCell.DistanceFrom(CurrentCoord)); + auto Radhouse = eligibleext->RadHouse; + bool ignore = pBuilding->Type->Wall && absolute; - if (eligible.Count > 0) - { - auto eligibleRad = eligible.GetItem(ScenarioClass::Instance->Random.Random() % eligible.Count); - auto eligibleext = RadSiteExt::ExtMap.Find(eligibleRad); - auto WH = eligibleext->Type->GetWarhead(); - auto absolute = WH->WallAbsoluteDestroyer; - int Damage = static_cast((eligibleext->GetRadLevelAt(CurrentCoord) / 2) * eligibleext->Type->GetLevelFactor()); - int Distance = static_cast(eligibleRad->BaseCell.DistanceFrom(CurrentCoord)); - auto Radhouse = eligibleext->RadHouse; - bool ignore = pBuilding->Type->Wall && absolute; - - pBuilding->ReceiveDamage(&Damage, Distance, WH, nullptr, ignore, absolute, Radhouse); - } + pBuilding->ReceiveDamage(&Damage, Distance, WH, nullptr, ignore, absolute, Radhouse); } } + return 0; } @@ -184,7 +190,7 @@ DEFINE_HOOK(4DA554, FootClass_AI_RadSiteClass, 5) { GET(FootClass* const, pFoot, ESI); - if (!pFoot->IsIronCurtained() && !pFoot->GetTechnoType()->ImmuneToRadiation && !pFoot->InLimbo && !pFoot->IsInAir() && pFoot->IsAlive) + if (!pFoot->IsIronCurtained() && !pFoot->GetTechnoType()->ImmuneToRadiation && !pFoot->InLimbo && !pFoot->IsInAir()) { DynamicVectorClass eligible; CellStruct CurrentCoord = pFoot->GetCell()->MapCoords; @@ -216,7 +222,7 @@ DEFINE_HOOK(4DA554, FootClass_AI_RadSiteClass, 5) //put this outsise the loop //fixing bugs that cause multiple rad site on single area generating multiple animtoinf/death anims - if (eligible.Count > 0) + if (eligible.Count > 0 && pFoot->IsAlive) { auto eligibleRad = eligible.GetItem(ScenarioClass::Instance->Random.Random() % eligible.Count); auto eligibleext = RadSiteExt::ExtMap.Find(eligibleRad); @@ -236,7 +242,7 @@ DEFINE_HOOK(4DA554, FootClass_AI_RadSiteClass, 5) } else { - R->EAX(DamageState::NowDead); + R->EAX(DamageState::NowDead); return 0x4DAF00; } } diff --git a/src/Ext/Rules/Body.cpp b/src/Ext/Rules/Body.cpp index 32b3c2f31d..835b73b386 100644 --- a/src/Ext/Rules/Body.cpp +++ b/src/Ext/Rules/Body.cpp @@ -41,7 +41,8 @@ void RulesExt::ExtData::LoadFromINIFile(CCINIClass* pINI) { // earliest loader - can't really do much because nothing else is initialized yet, so lookups won't work } -void RulesExt::ExtData::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI) { +void RulesExt::ExtData::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI) +{ RulesExt::ExtData* pData = RulesExt::Global(); if (!pData) { @@ -50,6 +51,7 @@ void RulesExt::ExtData::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI) INI_EX exINI(pINI); + this->RadApplDelayBuilding.Read(exINI, "Radiation", "RadApplicationDelay.Building"); this->Pips_Shield.Read(exINI, "AudioVisual", "Pips.Shield"); this->Pips_Shield_Buildings.Read(exINI, "AudioVisual", "Pips.Shield.Building"); } @@ -95,6 +97,7 @@ void RulesExt::ExtData::Serialize(T& Stm) { Stm .Process(this->Pips_Shield) .Process(this->Pips_Shield_Buildings) + .Process(this->RadApplDelayBuilding) ; } diff --git a/src/Ext/Rules/Body.h b/src/Ext/Rules/Body.h index f3b509f0fb..0e1504486f 100644 --- a/src/Ext/Rules/Body.h +++ b/src/Ext/Rules/Body.h @@ -28,9 +28,11 @@ class RulesExt Valueable> Pips_Shield; Valueable> Pips_Shield_Buildings; + Valueable RadApplDelayBuilding; ExtData(RulesClass* OwnerObject) : Extension(OwnerObject) , Pips_Shield({ -1,-1,-1 }) , Pips_Shield_Buildings({ -1,-1,-1 }) + , RadApplDelayBuilding(0) { } virtual ~ExtData() = default; From 37bf6bf4b31f98ca459cadcd1d2720464605229e Mon Sep 17 00:00:00 2001 From: Otamaa Date: Tue, 20 Apr 2021 18:29:27 +0700 Subject: [PATCH 4/8] Attempt to fix some known vanilla bugs -Deso cannot fire his weapon when cloaked (partialy fixed) -Unit with Death Weapon able to die twices (not affect yet) --- docs/New-or-Enhanced-Logics.md | 4 + src/Enum/RadTypes.cpp | 9 +- src/Enum/RadTypes.h | 33 ++++-- src/Ext/RadSite/Body.cpp | 2 - src/Ext/RadSite/Hooks.cpp | 210 +++++++++++++++++++-------------- src/Ext/Techno/Body.cpp | 9 +- src/Ext/Techno/Body.h | 10 +- 7 files changed, 159 insertions(+), 118 deletions(-) diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index 8e9c13f4fb..232e71bd8d 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -147,6 +147,10 @@ Strafing.SimulateBurst=false ; bool In `rulesmd.ini` ```ini +[RadiationTypes] ; List of New Radiation goes here +0=SOMERADTYPE +1=etc.. + [SOMEWEAPON] ; WeaponType RadLevel=0 ; integer, vanilla tag; used to activate the feature RadType=Radiation ; RadType to use instead diff --git a/src/Enum/RadTypes.cpp b/src/Enum/RadTypes.cpp index 87ecc03d8b..244944e535 100644 --- a/src/Enum/RadTypes.cpp +++ b/src/Enum/RadTypes.cpp @@ -36,12 +36,9 @@ void RadType::AddDefaults() void RadType::LoadListSection(CCINIClass *pINI) { - const char *section = GetMainSection(); - int len = pINI->GetKeyCount(section); - for (int i = 0; i < len; ++i) + for (int i = 0; i < pINI->GetKeyCount(GetMainSection()); ++i) { - const char *key = pINI->GetKeyName(section, i); - if (pINI->ReadString(section, key, "", Phobos::readBuffer)) + if (pINI->ReadString(GetMainSection(), pINI->GetKeyName(GetMainSection(), i), "", Phobos::readBuffer)) { FindOrAllocate(Phobos::readBuffer); Debug::Log("RadTypes :: LoadListSection check [%s] \n", Phobos::readBuffer); @@ -49,7 +46,7 @@ void RadType::LoadListSection(CCINIClass *pINI) } for (size_t i = 0; i < Array.size(); ++i) - { Array[i]->LoadFromINI(pINI); } + Array[i]->LoadFromINI(pINI); } void RadType::LoadFromINI(CCINIClass *pINI) diff --git a/src/Enum/RadTypes.h b/src/Enum/RadTypes.h index 1bba8928c8..7af6775afb 100644 --- a/src/Enum/RadTypes.h +++ b/src/Enum/RadTypes.h @@ -5,7 +5,6 @@ #include "../Utilities/GeneralUtils.h" #include "../Phobos.h" -class CCINIClass; class WarheadTypeClass; class RadType final : public Enumerable @@ -17,7 +16,6 @@ class RadType final : public Enumerable Nullable LevelMax; Nullable LevelDelay; Nullable LightDelay; - Nullable RadWarhead; Nullable RadSiteColor; Nullable LightFactor; @@ -31,46 +29,55 @@ class RadType final : public Enumerable static void LoadListSection(CCINIClass * pINI); - WarheadTypeClass* GetWarhead() const + WarheadTypeClass* GetWarhead() const { return this->RadWarhead.Get(RulesClass::Instance->RadSiteWarhead); } - - const ColorStruct& GetColor() const { + + const ColorStruct& GetColor() const + { return *this->RadSiteColor.GetEx(&RulesClass::Instance->RadColor); } - int GetDurationMultiple() const { + int GetDurationMultiple() const + { return this->DurationMultiple.Get(RulesClass::Instance->RadDurationMultiple); } - int GetApplicationDelay() const { + int GetApplicationDelay() const + { return this->ApplicationDelay.Get(RulesClass::Instance->RadApplicationDelay); } Nullable BuildingApplicationDelay; - int GetLevelMax() const { + int GetLevelMax() const + { return this->LevelMax.Get(RulesClass::Instance->RadLevelMax); } - int GetLevelDelay() const { + int GetLevelDelay() const + { return this->LevelDelay.Get(RulesClass::Instance->RadLevelDelay); } - int GetLightDelay() const { + int GetLightDelay() const + { return this->LightDelay.Get(RulesClass::Instance->RadLightDelay); } - double GetLevelFactor() const { + double GetLevelFactor() const + { return this->LevelFactor.Get(RulesClass::Instance->RadLevelFactor); } - double GetLightFactor() const { + double GetLightFactor() const + { return this->LightFactor.Get(RulesClass::Instance->RadLightFactor); } - double GetTintFactor() const { + double GetTintFactor() const + { return this->TintFactor.Get(RulesClass::Instance->RadTintFactor); } diff --git a/src/Ext/RadSite/Body.cpp b/src/Ext/RadSite/Body.cpp index 2f8d5c4be9..2fa3b897c4 100644 --- a/src/Ext/RadSite/Body.cpp +++ b/src/Ext/RadSite/Body.cpp @@ -16,9 +16,7 @@ void RadSiteExt::CreateInstance(CellStruct location, int spread, int amount, Wea //Adding Owner to RadSite , from bullet if (!pWeaponExt->Rad_NoOwner && pRadExt->RadHouse != pOwner) - { pRadExt->RadHouse = pOwner; - } pRadExt->Weapon = pWeaponExt->OwnerObject(); pRadExt->Type = pWeaponExt->RadType; diff --git a/src/Ext/RadSite/Hooks.cpp b/src/Ext/RadSite/Hooks.cpp index 13b3b1df87..3a9d836703 100644 --- a/src/Ext/RadSite/Hooks.cpp +++ b/src/Ext/RadSite/Hooks.cpp @@ -8,6 +8,7 @@ #include "../BuildingType/Body.h" #include "../Bullet/Body.h" #include "../Rules/Body.h" +#include "../Techno/Body.h" /* Custom Radiations @@ -44,8 +45,9 @@ DEFINE_HOOK(469150, BulletClass_Detonate_ApplyRadiation, 5) /* // hack it here so we can use this globally if needed -// *Prototype* +// *Prototype* //able to manually set the RadType instead rely on Weapon RadType +//Break InfantryClass_AIDeployment_CheckRad atm , will fix later DEFINE_HOOK(46ADE0, BulletClass_ApplyRadiation, 5) { GET_STACK(CellStruct, location, 0x4); @@ -53,50 +55,56 @@ DEFINE_HOOK(46ADE0, BulletClass_ApplyRadiation, 5) GET_STACK(int, amount, 0xC); auto const& Instances = RadSiteExt::RadSiteInstance; - auto const pWeapon = pThis->GetWeaponType(); - auto const pWeaponExt = WeaponTypeExt::ExtMap.FindOrAllocate(pWeapon); - auto const pRadType = &pWeaponExt->RadType; - auto const pThisHouse = pThis->Owner ? pThis->Owner->Owner : nullptr; + auto const pType = RadType::FindOrAllocate("Radiation"); - if (Instances.Count > 0) { + if (Instances.Count > 0) + { auto const it = std::find_if(Instances.begin(), Instances.end(), [=](RadSiteExt::ExtData* const pSite) // Lambda - {// find - return pSite->Type == pRadType && - pSite->OwnerObject()->BaseCell == location && - spread == pSite->OwnerObject()->Spread; - }); - - if (it == Instances.end()) { - RadSiteExt::CreateInstance(location, spread, amount, pWeaponExt, pThisHouse); + {// find + return + pSite->Type == pType && + pSite->OwnerObject()->BaseCell == location && + spread == pSite->OwnerObject()->Spread; + }); + + if (it == Instances.end()) + { + RadSiteExt::CreateInstance(location, spread, amount, pType, nullptr); } - else { + else + { auto pRadExt = *it; auto pRadSite = pRadExt->OwnerObject(); - if (pRadSite->GetRadLevel() + amount > pRadType->LevelMax) { - amount = pRadType->LevelMax - pRadSite->GetRadLevel(); + if (pRadSite->GetRadLevel() + amount > pType->GetLevelMax()) + { + amount = pType->GetLevelMax() - pRadSite->GetRadLevel(); } // Handle It pRadExt->Add(amount); } } - else { - RadSiteExt::CreateInstance(location, spread, amount, pWeaponExt, pThisHouse); + else + { + RadSiteExt::CreateInstance(location, spread, amount, pType, nullptr); } return 0x46AE5E; } */ +//Desolator cannot fire his deploy weapon when cloaked +//force de-cloak for now +//dunno where to put when it is undeployed DEFINE_HOOK(5213E3, InfantryClass_AIDeployment_CheckRad, 4) { GET(InfantryClass*, D, ESI); GET(int, WeaponRadLevel, EBX); auto const& Instances = RadSiteExt::RadSiteInstance; - auto const pWeapon = D->GetWeapon(1)->WeaponType; + auto const pWeapon = D->GetDeployWeapon()->WeaponType; int RadLevel = 0; if (Instances.Count > 0 && pWeapon) @@ -123,10 +131,71 @@ DEFINE_HOOK(5213E3, InfantryClass_AIDeployment_CheckRad, 4) RadLevel = pRadSite->GetRadLevel(); } } + //Pre-Fix ,need to look for right Un-deploy function to restore cloaked state + if (D->CloakState == CloakState::Cloaked) + { + D->Uncloak(false); + D->Cloakable = false; + D->NeedsRedraw = true; + auto Text = TechnoExt::ExtMap.Find(D); + Text->WasCloaked = true; + } return (RadLevel < WeaponRadLevel) ? 0x5213F4 : 0x521484; } +//not relevan hooks +/*need to find +DEFINE_HOOK(51F723, InfantryClass_unload_check, 4) +{ + GET(InfantryClass*, D, ESI); + auto Text = TechnoExt::ExtMap.Find(D); + Debug::Log("[%s] Undeploy \n", D->get_ID()); + if (Text->WasCloaked) + { + D->Cloakable = true; + D->UpdateCloak(); + D->NeedsRedraw = true; + } + + return 0; +} + +DEFINE_HOOK(52135D, InfantryClass_AIDeployment_Undeploy, 8) +{ + GET(InfantryClass*, D, ESI); + Debug::Log("[%s] Undeploy \n", D->get_ID()); + + auto Text = TechnoExt::ExtMap.Find(D); + if (Text->WasCloaked) + { + D->Cloakable = true; + D->UpdateCloak(); + D->NeedsRedraw = true; + } + + return 0; +} + +DEFINE_HOOK(70D724, TechnoClass_FireDeathWeapon_test, 4) +{ + GET(TechnoClass*, T, ESI); + GET(WeaponTypeClass*, W, EDI); + + if (T->GetTechnoType()->WhatAmI() == AbstractType::Infantry && W) + { + T->IsAlive = false; //this got ignored + if (!T->IsAlive && T->IsRedHP()) + T->GetTechnoType()->ImmuneToRadiation = true; //put immune radiation so it wont die twice + GameDelete(T);//force delete before die again + } + + R->EDI(W); + R->EBP(R->EAX()); + + return W ? 0x70D735: 0x70D72A; +}*/ + // Too OP, be aware DEFINE_HOOK(43FB23, BuildingClass_AI, 5) { @@ -138,7 +207,6 @@ DEFINE_HOOK(43FB23, BuildingClass_AI, 5) } auto const MainCoords = pBuilding->GetMapCoords(); - DynamicVectorClass eligible; for (auto pFoundation = pBuilding->GetFoundationData(false); *pFoundation != CellStruct{ 0x7FFF, 0x7FFF }; ++pFoundation) { @@ -161,26 +229,16 @@ DEFINE_HOOK(43FB23, BuildingClass_AI, 5) if (pRadExt->GetRadLevelAt(CurrentCoord) <= 0.0 || !pType->GetWarhead()) continue; - - eligible.AddUnique(pRadSite); - } - - if (eligible.Count > 0) - { - auto eligibleRad = eligible.GetItem(ScenarioClass::Instance->Random.Random() % eligible.Count); - auto eligibleext = RadSiteExt::ExtMap.Find(eligibleRad); - auto WH = eligibleext->Type->GetWarhead(); + auto WH = pType->GetWarhead(); auto absolute = WH->WallAbsoluteDestroyer; - int Damage = static_cast((eligibleext->GetRadLevelAt(CurrentCoord) / 2) * eligibleext->Type->GetLevelFactor()); - int Distance = static_cast(eligibleRad->BaseCell.DistanceFrom(CurrentCoord)); - auto Radhouse = eligibleext->RadHouse; bool ignore = pBuilding->Type->Wall && absolute; + auto damage = static_cast((pRadExt->GetRadLevelAt(CurrentCoord) / 2) * pType->GetLevelFactor()); - pBuilding->ReceiveDamage(&Damage, Distance, WH, nullptr, ignore, absolute, Radhouse); + if (pBuilding->IsAlive)// simple fix for previous issues + pBuilding->ReceiveDamage(&damage, static_cast(orDistance), WH, nullptr, ignore, absolute, pRadExt->RadHouse.Get()); } } - return 0; } @@ -192,7 +250,6 @@ DEFINE_HOOK(4DA554, FootClass_AI_RadSiteClass, 5) if (!pFoot->IsIronCurtained() && !pFoot->GetTechnoType()->ImmuneToRadiation && !pFoot->InLimbo && !pFoot->IsInAir()) { - DynamicVectorClass eligible; CellStruct CurrentCoord = pFoot->GetCell()->MapCoords; // Loop for each different radiation stored in the RadSites container @@ -216,35 +273,23 @@ DEFINE_HOOK(4DA554, FootClass_AI_RadSiteClass, 5) if (RadLevel <= 0.0 || !pType->GetWarhead()) continue; - //put eligible RadSite inside DynamicVector - eligible.AddUnique(pRadSite); - } - - //put this outsise the loop - //fixing bugs that cause multiple rad site on single area generating multiple animtoinf/death anims - if (eligible.Count > 0 && pFoot->IsAlive) - { - auto eligibleRad = eligible.GetItem(ScenarioClass::Instance->Random.Random() % eligible.Count); - auto eligibleext = RadSiteExt::ExtMap.Find(eligibleRad); - auto WH = eligibleext->Type->GetWarhead(); + int Damage = static_cast(RadLevel* pType->GetLevelFactor()); + int Distance = static_cast(orDistance); + auto WH = pType->GetWarhead(); auto absolute = WH->WallAbsoluteDestroyer; - int Damage = static_cast(eligibleext->GetRadLevelAt(CurrentCoord) * eligibleext->Type->GetLevelFactor()); - int Distance = static_cast(eligibleRad->BaseCell.DistanceFrom(CurrentCoord)); - auto Radhouse = eligibleext->RadHouse; - pFoot->ReceiveDamage(&Damage, Distance, WH, nullptr, false, absolute, Radhouse); + if (pFoot->IsAlive)// simple fix for previous issues + pFoot->ReceiveDamage(&Damage, Distance, WH, nullptr, false, absolute, pRadExt->RadHouse.Get()); } } - if (pFoot->IsAlive) - { - return 0x4DA63B; - } - else + if (!pFoot->IsAlive) { R->EAX(DamageState::NowDead); return 0x4DAF00; } + + return 0x4DA63B; } DEFINE_HOOK(65B593, RadSiteClass_Activate_Delay, 6) @@ -268,37 +313,36 @@ DEFINE_HOOK(65B593, RadSiteClass_Activate_Delay, 6) return 0x65B59F; } +#define GET_RADSITE(reg , value)\ + GET(RadSiteClass* const, pThis, reg);\ + RadSiteExt::ExtData *pExt = RadSiteExt::ExtMap.Find(pThis);\ + auto Output = pExt->Type->## value ##; + DEFINE_HOOK(65B5CE, RadSiteClass_Activate_Color, 6) { - GET(RadSiteClass* const, pThis, ESI); - - auto pExt = RadSiteExt::ExtMap.Find(pThis); - ColorStruct pRadColor = pExt->Type->GetColor(); + GET_RADSITE(ESI, GetColor()); R->EAX(0); R->EDX(0); R->EBX(0); - R->DL(pRadColor.G); + R->DL(Output.G); R->EBP(R->EDX()); - R->BL(pRadColor.B); - R->AL(pRadColor.R); + R->BL(Output.B); + R->AL(Output.R); // point out the missing register -Otamaa - R->EDI(RulesClass::Instance); + R->EDI(pThis); return 0x65B604; } DEFINE_HOOK(65B63E, RadSiteClass_Activate_LightFactor, 6) { - GET(RadSiteClass* const, Rad, ESI); - - auto pRadExt = RadSiteExt::ExtMap.Find(Rad); - auto lightFactor = pRadExt->Type->GetLightFactor(); + GET_RADSITE(ESI, GetLightFactor()); - __asm fmul lightFactor; + __asm fmul Output; return 0x65B644; } @@ -307,36 +351,27 @@ DEFINE_HOOK_AGAIN(65B6A0, RadSiteClass_Activate_TintFactor, 6) DEFINE_HOOK_AGAIN(65B6CA, RadSiteClass_Activate_TintFactor, 6) DEFINE_HOOK(65B6F2, RadSiteClass_Activate_TintFactor, 6) { - GET(RadSiteClass* const, Rad, ESI); - - auto pRadExt = RadSiteExt::ExtMap.Find(Rad); - double tintFactor = pRadExt->Type->GetTintFactor(); + GET_RADSITE(ESI, GetTintFactor()); - __asm fmul tintFactor; + __asm fmul Output; return R->Origin() + 6; } DEFINE_HOOK(65B843, RadSiteClass_AI_LevelDelay, 6) { - GET(RadSiteClass* const, Rad, ESI); + GET_RADSITE(ESI, GetLevelDelay()); - auto pRadExt = RadSiteExt::ExtMap.Find(Rad); - auto delay = pRadExt->Type->GetLevelDelay(); - - R->ECX(delay); + R->ECX(Output); return 0x65B849; } DEFINE_HOOK(65B8B9, RadSiteClass_AI_LightDelay, 6) { - GET(RadSiteClass* const, Rad, ESI); - - auto pRadExt = RadSiteExt::ExtMap.Find(Rad); - auto delay = pRadExt->Type->GetLightDelay(); + GET_RADSITE(ESI, GetLightDelay()); - R->ECX(delay); + R->ECX(Output); return 0x65B8BF; } @@ -344,12 +379,9 @@ DEFINE_HOOK(65B8B9, RadSiteClass_AI_LightDelay, 6) // Additional Hook below DEFINE_HOOK(65BB67, RadSite_Deactivate, 6) { - GET(const RadSiteClass*, Rad, ECX); - - auto pRadExt = RadSiteExt::ExtMap.Find(Rad); - auto delay = pRadExt->Type->GetLevelDelay(); + GET_RADSITE(ECX, GetLevelDelay()); - R->ESI(delay); + R->ESI(Output); __asm xor edx, edx; // fixing integer overflow crash __asm idiv esi; diff --git a/src/Ext/Techno/Body.cpp b/src/Ext/Techno/Body.cpp index 7cd3ce8595..9e1528008b 100644 --- a/src/Ext/Techno/Body.cpp +++ b/src/Ext/Techno/Body.cpp @@ -163,10 +163,11 @@ bool TechnoExt::HasAvailableDock(TechnoClass* pThis) template void TechnoExt::ExtData::Serialize(T& Stm) { - Stm - .Process(this->InterceptedBullet) - .Process(this->ShieldData) - ; + Stm + .Process(this->InterceptedBullet) + .Process(this->ShieldData) + .Process(this->WasCloaked) + ; } void TechnoExt::ExtData::LoadFromStream(PhobosStreamReader& Stm) diff --git a/src/Ext/Techno/Body.h b/src/Ext/Techno/Body.h index 8ab3b020aa..31cf00f9e3 100644 --- a/src/Ext/Techno/Body.h +++ b/src/Ext/Techno/Body.h @@ -20,10 +20,12 @@ class TechnoExt Valueable InterceptedBullet; std::unique_ptr ShieldData; - ExtData(TechnoClass* OwnerObject) : Extension(OwnerObject) - ,InterceptedBullet(nullptr) - ,ShieldData() - { } + Valueable WasCloaked; + ExtData(TechnoClass* OwnerObject) : Extension(OwnerObject), + InterceptedBullet(nullptr), + ShieldData(), + WasCloaked(false) + { } virtual ~ExtData() = default; From 681392de39cfd3cfea559220ac9dd15bbbc40744 Mon Sep 17 00:00:00 2001 From: Otamaa Date: Wed, 21 Apr 2021 22:34:15 +0700 Subject: [PATCH 5/8] Re-Cloak Deso when Undeployed -Deso cannot fire his Deploy weapon when cloaked (fixed) --- src/Ext/Techno/Hooks.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Ext/Techno/Hooks.cpp b/src/Ext/Techno/Hooks.cpp index 6a8aafaea0..cb103bcd34 100644 --- a/src/Ext/Techno/Hooks.cpp +++ b/src/Ext/Techno/Hooks.cpp @@ -1,3 +1,5 @@ +#include + #include "Body.h" #include "../TechnoType/Body.h" @@ -15,5 +17,18 @@ DEFINE_HOOK(6F9E50, TechnoClass_AI, 5) // Spawner.LimitRange & Spawner.ExtraLimitRange TechnoExt::ApplySpawn_LimitRange(pThis); + if (auto pinf = static_cast(pThis)) + { + auto Text = TechnoExt::ExtMap.Find(pThis); + + if (Text->WasCloaked && pinf->SequenceAnim == Sequence::Undeploy) + { + pThis->Cloakable = true; + pThis->UpdateCloak(); + pThis->NeedsRedraw = true; + Text->WasCloaked = false; + } + } + return 0; } \ No newline at end of file From a3713dad8e6a26f6e5a9bb9bc984f249c4de46a4 Mon Sep 17 00:00:00 2001 From: Otamaa Date: Sat, 24 Apr 2021 22:50:00 +0700 Subject: [PATCH 6/8] Further changes --- docs/Fixed-or-Improved-Logics.md | 1 + docs/Whats-New.md | 4 ++-- src/Ext/Techno/Body.cpp | 16 ++++++++++++++++ src/Ext/Techno/Body.h | 1 + 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index 5b099a0fa0..e3a079cf56 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -6,6 +6,7 @@ This page describes all ingame logics that are fixed or improved in Phobos witho - Fixed the bug when deploying mindcontrolled vehicle into a building permanently trasferred the control to the house which mindcontrolled it. - Fixed the bug when units are already dead but still in map (for sinking, crashing, dying animation, etc.), they could die again. +- Fixed the bug when cloaked Desolator uneable to fire his deploy weapon. - SHP debris shadows now respect the `Shadow` tag. - Allowed usage of TileSet of 255 and above without making NE-SW broken bridges unrepairable. - `TurretOffset` tag for voxel turreted technos now accepts FLH (forward, lateral, height) values like `TurretOffset=F,L` or `TurretOffset=F,L,H`, which means turret location can be adjusted in all three axes. diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 056f863009..bba9c143c3 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -12,7 +12,6 @@ This page lists the history of changes across stable Phobos releases and also al ### From older Phobos versions - Tag `rulesmd.ini->[SOMETECHNOTYPE]->Deployed.RememberTarget` is deprecated and can be removed now, the bugfix for `DeployToFire` deployers is now always on. - ## Changelog ### 0.2 @@ -45,6 +44,7 @@ Vanilla fixes: - Fixed fatal errors when `Blowfish.dll` couldn't be registered in the system properly due to missing admin rights (by Belonit) - Fix to take Burst into account for aircraft weapon shots beyond the first one (by Starkku) - Fixed the bug when units are already dead but still in map (for sinking, crashing, dying animation, etc.), they could die again (by Uranusian) +- Fixed the bug when cloaked Desolator uneable to fire his deploy weapon (by Otamaa) Phobos fixes: - Properly rewritten a fix for mind-controlled vehicles deploying into buildings (by FS-21) @@ -74,4 +74,4 @@ Vanilla fixes: - `DeployToFire` vehicles won't lose target on deploy anymore (unfinished fix by DCoder) - Fixed QWER hotkey tab switching not hiding the displayed tooltip as it should (by Belonit) - Sidebar tooltips now can go over sidebar bounds (by Belonit) -- Lifted stupidly small limit for tooltip character amount (by Belonit) \ No newline at end of file +- Lifted stupidly small limit for tooltip character amount (by Belonit) diff --git a/src/Ext/Techno/Body.cpp b/src/Ext/Techno/Body.cpp index 9e1528008b..a5578f52be 100644 --- a/src/Ext/Techno/Body.cpp +++ b/src/Ext/Techno/Body.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "../BulletType/Body.h" @@ -157,6 +158,21 @@ bool TechnoExt::HasAvailableDock(TechnoClass* pThis) return false; } +void TechnoExt::ApplyCloak_Undeployed(TechnoClass* pThis) +{ + if (auto pinf = static_cast(pThis)) + { + auto Text = TechnoExt::ExtMap.Find(pThis); + + if (Text->WasCloaked && pinf->SequenceAnim == Sequence::Undeploy && pinf->IsDeployed()) + { + pThis->Cloakable = true; + pThis->UpdateCloak(); + pThis->NeedsRedraw = true; + Text->WasCloaked = false; + } + } +} // ============================= // load / save diff --git a/src/Ext/Techno/Body.h b/src/Ext/Techno/Body.h index 31cf00f9e3..c56a9ab962 100644 --- a/src/Ext/Techno/Body.h +++ b/src/Ext/Techno/Body.h @@ -65,4 +65,5 @@ class TechnoExt static void ApplyInterceptor(TechnoClass* pThis); static void ApplyPowered_KillSpawns(TechnoClass* pThis); static void ApplySpawn_LimitRange(TechnoClass* pThis); + static void ApplyCloak_Undeployed(TechnoClass* pThis); }; From 16197a6540850f5d208311d5e71f253286c41346 Mon Sep 17 00:00:00 2001 From: Otamaa Date: Sat, 24 Apr 2021 23:19:18 +0700 Subject: [PATCH 7/8] Removing unnessesary codes , fix some style , Doc --- docs/New-or-Enhanced-Logics.md | 4 +- src/Enum/RadTypes.cpp | 3 -- src/Ext/RadSite/Hooks.cpp | 71 ++++------------------------------ src/Ext/Techno/Hooks.cpp | 15 +------ 4 files changed, 12 insertions(+), 81 deletions(-) diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index 232e71bd8d..e2e3973bd9 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -147,7 +147,7 @@ Strafing.SimulateBurst=false ; bool In `rulesmd.ini` ```ini -[RadiationTypes] ; List of New Radiation goes here +[RadiationTypes] ; List of New Radiation goes here 0=SOMERADTYPE 1=etc.. @@ -175,6 +175,8 @@ RadSiteWarhead=RadSite ; WarheadType - Radiation now has owner by default, so any rad-kills will be scored. - `AffectsAllies`, `AffectsOwner` and `AffectsEnemies` on `RadSiteWarhead` are respected. - Currently the rad maker doesn't gain experience from kills, this may change in future. +- Radiation now able to deal damage to Building .To enable set `RadApplicationDelay.Building` value more than 0. + - Dealing damage using `RadSiteWarhead` and respect `Verses` values In `rulesmd.ini`: ```ini diff --git a/src/Enum/RadTypes.cpp b/src/Enum/RadTypes.cpp index 244944e535..0638903aba 100644 --- a/src/Enum/RadTypes.cpp +++ b/src/Enum/RadTypes.cpp @@ -67,9 +67,6 @@ void RadType::LoadFromINI(CCINIClass *pINI) this->LightFactor.Read(exINI, section, "RadLightFactor"); this->TintFactor.Read(exINI, section, "RadTintFactor"); - Debug::Log("RadTypes :: LoadFromINI check [%s] \n", section); -// Debug::Log("RadTypes :: LoadFromINI check [%s]->Warhead \n", this->GetWarhead()->Name); -// Debug::Log("RadTypes :: LoadFromINI check [%d %d %d]->Color \n", this->GetColor().R , this->GetColor().G, this->GetColor().B); } template diff --git a/src/Ext/RadSite/Hooks.cpp b/src/Ext/RadSite/Hooks.cpp index 3a9d836703..cf6266d002 100644 --- a/src/Ext/RadSite/Hooks.cpp +++ b/src/Ext/RadSite/Hooks.cpp @@ -96,8 +96,6 @@ DEFINE_HOOK(46ADE0, BulletClass_ApplyRadiation, 5) */ //Desolator cannot fire his deploy weapon when cloaked -//force de-cloak for now -//dunno where to put when it is undeployed DEFINE_HOOK(5213E3, InfantryClass_AIDeployment_CheckRad, 4) { GET(InfantryClass*, D, ESI); @@ -131,7 +129,7 @@ DEFINE_HOOK(5213E3, InfantryClass_AIDeployment_CheckRad, 4) RadLevel = pRadSite->GetRadLevel(); } } - //Pre-Fix ,need to look for right Un-deploy function to restore cloaked state + if (D->CloakState == CloakState::Cloaked) { D->Uncloak(false); @@ -144,58 +142,6 @@ DEFINE_HOOK(5213E3, InfantryClass_AIDeployment_CheckRad, 4) return (RadLevel < WeaponRadLevel) ? 0x5213F4 : 0x521484; } -//not relevan hooks -/*need to find -DEFINE_HOOK(51F723, InfantryClass_unload_check, 4) -{ - GET(InfantryClass*, D, ESI); - auto Text = TechnoExt::ExtMap.Find(D); - Debug::Log("[%s] Undeploy \n", D->get_ID()); - if (Text->WasCloaked) - { - D->Cloakable = true; - D->UpdateCloak(); - D->NeedsRedraw = true; - } - - return 0; -} - -DEFINE_HOOK(52135D, InfantryClass_AIDeployment_Undeploy, 8) -{ - GET(InfantryClass*, D, ESI); - Debug::Log("[%s] Undeploy \n", D->get_ID()); - - auto Text = TechnoExt::ExtMap.Find(D); - if (Text->WasCloaked) - { - D->Cloakable = true; - D->UpdateCloak(); - D->NeedsRedraw = true; - } - - return 0; -} - -DEFINE_HOOK(70D724, TechnoClass_FireDeathWeapon_test, 4) -{ - GET(TechnoClass*, T, ESI); - GET(WeaponTypeClass*, W, EDI); - - if (T->GetTechnoType()->WhatAmI() == AbstractType::Infantry && W) - { - T->IsAlive = false; //this got ignored - if (!T->IsAlive && T->IsRedHP()) - T->GetTechnoType()->ImmuneToRadiation = true; //put immune radiation so it wont die twice - GameDelete(T);//force delete before die again - } - - R->EDI(W); - R->EBP(R->EAX()); - - return W ? 0x70D735: 0x70D72A; -}*/ - // Too OP, be aware DEFINE_HOOK(43FB23, BuildingClass_AI, 5) { @@ -248,6 +194,8 @@ DEFINE_HOOK(4DA554, FootClass_AI_RadSiteClass, 5) { GET(FootClass* const, pFoot, ESI); + auto state = static_cast(R->AL()); + if (!pFoot->IsIronCurtained() && !pFoot->GetTechnoType()->ImmuneToRadiation && !pFoot->InLimbo && !pFoot->IsInAir()) { CellStruct CurrentCoord = pFoot->GetCell()->MapCoords; @@ -278,18 +226,13 @@ DEFINE_HOOK(4DA554, FootClass_AI_RadSiteClass, 5) auto WH = pType->GetWarhead(); auto absolute = WH->WallAbsoluteDestroyer; - if (pFoot->IsAlive)// simple fix for previous issues - pFoot->ReceiveDamage(&Damage, Distance, WH, nullptr, false, absolute, pRadExt->RadHouse.Get()); + if (pFoot->IsAlive || !pFoot->IsSinking)// simple fix for previous issues + state = pFoot->ReceiveDamage(&Damage, Distance, WH, nullptr, false, absolute, pRadExt->RadHouse.Get()); } } - if (!pFoot->IsAlive) - { - R->EAX(DamageState::NowDead); - return 0x4DAF00; - } - - return 0x4DA63B; + R->EAX(state); + return pFoot->IsAlive ? 0x4DA63B : 0x4DAF00; } DEFINE_HOOK(65B593, RadSiteClass_Activate_Delay, 6) diff --git a/src/Ext/Techno/Hooks.cpp b/src/Ext/Techno/Hooks.cpp index cb103bcd34..e7eadee96d 100644 --- a/src/Ext/Techno/Hooks.cpp +++ b/src/Ext/Techno/Hooks.cpp @@ -16,19 +16,8 @@ DEFINE_HOOK(6F9E50, TechnoClass_AI, 5) TechnoExt::ApplyPowered_KillSpawns(pThis); // Spawner.LimitRange & Spawner.ExtraLimitRange TechnoExt::ApplySpawn_LimitRange(pThis); - - if (auto pinf = static_cast(pThis)) - { - auto Text = TechnoExt::ExtMap.Find(pThis); - - if (Text->WasCloaked && pinf->SequenceAnim == Sequence::Undeploy) - { - pThis->Cloakable = true; - pThis->UpdateCloak(); - pThis->NeedsRedraw = true; - Text->WasCloaked = false; - } - } + // + TechnoExt::ApplyCloak_Undeployed(pThis); return 0; } \ No newline at end of file From f3813bac6366c1457e99022f7d4e209954bffc2c Mon Sep 17 00:00:00 2001 From: "Meta (X230T)" Date: Sun, 25 Apr 2021 11:44:29 +0300 Subject: [PATCH 8/8] Refactorings --- Phobos.vcxproj | 4 +- docs/Fixed-or-Improved-Logics.md | 2 +- docs/New-or-Enhanced-Logics.md | 11 +- docs/Whats-New.md | 3 +- src/Enum/RadTypeClass.cpp | 80 +++++ src/Enum/{RadTypes.h => RadTypeClass.h} | 198 +++++----- src/Enum/RadTypes.cpp | 97 ----- src/Ext/Bullet/Body.cpp | 2 +- src/Ext/RadSite/Body.cpp | 163 ++++----- src/Ext/RadSite/Body.h | 107 +++--- src/Ext/RadSite/Hooks.cpp | 456 ++++++++++++------------ src/Ext/Rules/Body.cpp | 222 ++++++------ src/Ext/Rules/Body.h | 13 +- src/Ext/Techno/Body.cpp | 41 +-- src/Ext/WeaponType/Body.cpp | 4 +- src/Ext/WeaponType/Body.h | 4 +- src/Phobos.Ext.cpp | 4 +- 17 files changed, 717 insertions(+), 694 deletions(-) create mode 100644 src/Enum/RadTypeClass.cpp rename src/Enum/{RadTypes.h => RadTypeClass.h} (70%) delete mode 100644 src/Enum/RadTypes.cpp diff --git a/Phobos.vcxproj b/Phobos.vcxproj index f24a7a6df3..11608e16aa 100644 --- a/Phobos.vcxproj +++ b/Phobos.vcxproj @@ -13,7 +13,7 @@ - + @@ -76,7 +76,7 @@ - + diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index e3a079cf56..ef388c8139 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -6,7 +6,7 @@ This page describes all ingame logics that are fixed or improved in Phobos witho - Fixed the bug when deploying mindcontrolled vehicle into a building permanently trasferred the control to the house which mindcontrolled it. - Fixed the bug when units are already dead but still in map (for sinking, crashing, dying animation, etc.), they could die again. -- Fixed the bug when cloaked Desolator uneable to fire his deploy weapon. +- Fixed the bug when cloaked Desolator was unable to fire his deploy weapon. - SHP debris shadows now respect the `Shadow` tag. - Allowed usage of TileSet of 255 and above without making NE-SW broken bridges unrepairable. - `TurretOffset` tag for voxel turreted technos now accepts FLH (forward, lateral, height) values like `TurretOffset=F,L` or `TurretOffset=F,L,H`, which means turret location can be adjusted in all three axes. diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index e2e3973bd9..dfe75267db 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -102,7 +102,7 @@ In `rulesmd.ini`: Pips.Shield=-1,-1,-1 ; int, frames of pips.shp for Green, Yellow, Red Pips.Shield.Building=-1,-1,-1 ; int, frames of pips.shp for Green, Yellow, Red -[SOMETECHNO] ; TechnoType +[SOMETECHNO] ; TechnoType Shield.Strength=0 ; integer Shield.Armor=none ; ArmorType Shield.AbsorbOverDamage=false ; boolean @@ -147,12 +147,10 @@ Strafing.SimulateBurst=false ; bool In `rulesmd.ini` ```ini -[RadiationTypes] ; List of New Radiation goes here +[RadiationTypes] 0=SOMERADTYPE -1=etc.. [SOMEWEAPON] ; WeaponType -RadLevel=0 ; integer, vanilla tag; used to activate the feature RadType=Radiation ; RadType to use instead ; of default [Radiation] @@ -172,11 +170,10 @@ RadSiteWarhead=RadSite ; WarheadType ### Radiation enhancements -- Radiation now has owner by default, so any rad-kills will be scored. +- Radiation now has owner by default, so any rad-kills will be scored. This behaviour can be reverted by a corresponding tag. - `AffectsAllies`, `AffectsOwner` and `AffectsEnemies` on `RadSiteWarhead` are respected. - Currently the rad maker doesn't gain experience from kills, this may change in future. -- Radiation now able to deal damage to Building .To enable set `RadApplicationDelay.Building` value more than 0. - - Dealing damage using `RadSiteWarhead` and respect `Verses` values +- Radiation is now able to deal damage to Buildings. To enable set `RadApplicationDelay.Building` value more than 0. In `rulesmd.ini`: ```ini diff --git a/docs/Whats-New.md b/docs/Whats-New.md index bba9c143c3..617e7d798e 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -12,6 +12,7 @@ This page lists the history of changes across stable Phobos releases and also al ### From older Phobos versions - Tag `rulesmd.ini->[SOMETECHNOTYPE]->Deployed.RememberTarget` is deprecated and can be removed now, the bugfix for `DeployToFire` deployers is now always on. + ## Changelog ### 0.2 @@ -44,7 +45,7 @@ Vanilla fixes: - Fixed fatal errors when `Blowfish.dll` couldn't be registered in the system properly due to missing admin rights (by Belonit) - Fix to take Burst into account for aircraft weapon shots beyond the first one (by Starkku) - Fixed the bug when units are already dead but still in map (for sinking, crashing, dying animation, etc.), they could die again (by Uranusian) -- Fixed the bug when cloaked Desolator uneable to fire his deploy weapon (by Otamaa) +- Fixed the bug when cloaked Desolator was unable to fire his deploy weapon (by Otamaa) Phobos fixes: - Properly rewritten a fix for mind-controlled vehicles deploying into buildings (by FS-21) diff --git a/src/Enum/RadTypeClass.cpp b/src/Enum/RadTypeClass.cpp new file mode 100644 index 0000000000..3a7f0ec232 --- /dev/null +++ b/src/Enum/RadTypeClass.cpp @@ -0,0 +1,80 @@ +#include "RadTypeClass.h" + +#include + +#include + +Enumerable::container_t Enumerable::Array; + +// pretty nice, eh +const char* Enumerable::GetMainSection() +{ + return "RadiationTypes"; +} + +void RadTypeClass::AddDefaults() +{ + FindOrAllocate("Radiation"); +} + +void RadTypeClass::LoadListSection(CCINIClass * pINI) +{ + for (int i = 0; i < pINI->GetKeyCount(GetMainSection()); ++i) + { + if (pINI->ReadString(GetMainSection(), pINI->GetKeyName(GetMainSection(), i), "", Phobos::readBuffer)) + { + FindOrAllocate(Phobos::readBuffer); + Debug::Log("RadTypeClass :: LoadListSection check [%s] \n", Phobos::readBuffer); + } + } + + for (auto &radType: Array) + radType->LoadFromINI(pINI); +} + +void RadTypeClass::LoadFromINI(CCINIClass * pINI) +{ + const char* section = this->Name; + + INI_EX exINI(pINI); + + this->RadWarhead.Read(exINI, section, "RadSiteWarhead", true); + this->RadSiteColor.Read(exINI, section, "RadColor"); + this->DurationMultiple.Read(exINI, section, "RadDurationMultiple"); + this->ApplicationDelay.Read(exINI, section, "RadApplicationDelay"); + this->BuildingApplicationDelay.Read(exINI, section, "RadApplicationDelay.Building"); + this->LevelMax.Read(exINI, section, "RadLevelMax"); + this->LevelDelay.Read(exINI, section, "RadLevelDelay"); + this->LightDelay.Read(exINI, section, "RadLightDelay"); + this->LevelFactor.Read(exINI, section, "RadLevelFactor"); + this->LightFactor.Read(exINI, section, "RadLightFactor"); + this->TintFactor.Read(exINI, section, "RadTintFactor"); +} + +template +void RadTypeClass::Serialize(T & Stm) +{ + Stm + .Process(this->DurationMultiple) + .Process(this->ApplicationDelay) + .Process(this->LevelMax) + .Process(this->LevelDelay) + .Process(this->LightDelay) + .Process(this->BuildingApplicationDelay) + .Process(this->LevelFactor) + .Process(this->LightFactor) + .Process(this->TintFactor) + .Process(this->RadSiteColor) + .Process(this->RadWarhead) + ; +}; + +void RadTypeClass::LoadFromStream(PhobosStreamReader & Stm) +{ + this->Serialize(Stm); +} + +void RadTypeClass::SaveToStream(PhobosStreamWriter & Stm) +{ + this->Serialize(Stm); +} diff --git a/src/Enum/RadTypes.h b/src/Enum/RadTypeClass.h similarity index 70% rename from src/Enum/RadTypes.h rename to src/Enum/RadTypeClass.h index 7af6775afb..4672317ede 100644 --- a/src/Enum/RadTypes.h +++ b/src/Enum/RadTypeClass.h @@ -1,91 +1,109 @@ -#pragma once - -#include "_Enumerator.hpp" -#include "../Utilities/Template.h" -#include "../Utilities/GeneralUtils.h" -#include "../Phobos.h" - -class WarheadTypeClass; - -class RadType final : public Enumerable -{ -private: - Nullable DurationMultiple; - Nullable ApplicationDelay; - Nullable LevelFactor; - Nullable LevelMax; - Nullable LevelDelay; - Nullable LightDelay; - Nullable RadWarhead; - Nullable RadSiteColor; - Nullable LightFactor; - Nullable TintFactor; - -public: - - RadType(const char* pTitle); - - static void AddDefaults(); - - static void LoadListSection(CCINIClass * pINI); - - WarheadTypeClass* GetWarhead() const - { - return this->RadWarhead.Get(RulesClass::Instance->RadSiteWarhead); - } - - const ColorStruct& GetColor() const - { - return *this->RadSiteColor.GetEx(&RulesClass::Instance->RadColor); - } - - int GetDurationMultiple() const - { - return this->DurationMultiple.Get(RulesClass::Instance->RadDurationMultiple); - } - - int GetApplicationDelay() const - { - return this->ApplicationDelay.Get(RulesClass::Instance->RadApplicationDelay); - } - - Nullable BuildingApplicationDelay; - - int GetLevelMax() const - { - return this->LevelMax.Get(RulesClass::Instance->RadLevelMax); - } - - int GetLevelDelay() const - { - return this->LevelDelay.Get(RulesClass::Instance->RadLevelDelay); - } - - int GetLightDelay() const - { - return this->LightDelay.Get(RulesClass::Instance->RadLightDelay); - } - - double GetLevelFactor() const - { - return this->LevelFactor.Get(RulesClass::Instance->RadLevelFactor); - } - - double GetLightFactor() const - { - return this->LightFactor.Get(RulesClass::Instance->RadLightFactor); - } - - double GetTintFactor() const - { - return this->TintFactor.Get(RulesClass::Instance->RadTintFactor); - } - - virtual ~RadType() override; - virtual void LoadFromINI(CCINIClass *pINI) override; - virtual void LoadFromStream(PhobosStreamReader& Stm); - virtual void SaveToStream(PhobosStreamWriter& Stm); -private: - template - void Serialize(T& Stm); +#pragma once + +#include "_Enumerator.hpp" +#include +#include +#include + +class WarheadTypeClass; + +class RadTypeClass final : public Enumerable +{ +private: + Nullable DurationMultiple; + Nullable ApplicationDelay; + Nullable BuildingApplicationDelay; + Nullable LevelFactor; + Nullable LevelMax; + Nullable LevelDelay; + Nullable LightDelay; + Nullable RadWarhead; + Nullable RadSiteColor; + Nullable LightFactor; + Nullable TintFactor; + +public: + + RadTypeClass(const char* const pTitle) : Enumerable(pTitle), + LevelDelay(), + LightDelay(), + RadSiteColor(), + LevelMax(), + LevelFactor(), + LightFactor(), + TintFactor(), + RadWarhead(), + DurationMultiple(), + ApplicationDelay(), + BuildingApplicationDelay() + { } + + virtual ~RadTypeClass() override = default; + + static void AddDefaults(); + + static void LoadListSection(CCINIClass * pINI); + + WarheadTypeClass* GetWarhead() const + { + return this->RadWarhead.Get(RulesClass::Instance->RadSiteWarhead); + } + + const ColorStruct& GetColor() const + { + return *this->RadSiteColor.GetEx(&RulesClass::Instance->RadColor); + } + + int GetDurationMultiple() const + { + return this->DurationMultiple.Get(RulesClass::Instance->RadDurationMultiple); + } + + int GetApplicationDelay() const + { + return this->ApplicationDelay.Get(RulesClass::Instance->RadApplicationDelay); + } + + int GetBuildingApplicationDelay() const + { + return this->BuildingApplicationDelay.Get(RulesExt::Global()->RadApplicationDelay_Building); + } + + int GetLevelMax() const + { + return this->LevelMax.Get(RulesClass::Instance->RadLevelMax); + } + + int GetLevelDelay() const + { + return this->LevelDelay.Get(RulesClass::Instance->RadLevelDelay); + } + + int GetLightDelay() const + { + return this->LightDelay.Get(RulesClass::Instance->RadLightDelay); + } + + double GetLevelFactor() const + { + return this->LevelFactor.Get(RulesClass::Instance->RadLevelFactor); + } + + double GetLightFactor() const + { + return this->LightFactor.Get(RulesClass::Instance->RadLightFactor); + } + + double GetTintFactor() const + { + return this->TintFactor.Get(RulesClass::Instance->RadTintFactor); + } + + virtual void LoadFromINI(CCINIClass *pINI) override; + virtual void LoadFromStream(PhobosStreamReader& Stm); + virtual void SaveToStream(PhobosStreamWriter& Stm); + +private: + template + void Serialize(T& Stm); }; \ No newline at end of file diff --git a/src/Enum/RadTypes.cpp b/src/Enum/RadTypes.cpp deleted file mode 100644 index 0638903aba..0000000000 --- a/src/Enum/RadTypes.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "RadTypes.h" - -#include "../Utilities/TemplateDef.h" - -#include - -Enumerable::container_t Enumerable::Array; - -// pretty nice, eh -const char * Enumerable::GetMainSection() -{ - return "RadiationTypes"; -} - -RadType::RadType(const char* const pTitle) - : Enumerable(pTitle), - LevelDelay(), - LightDelay(), - RadSiteColor(), - LevelMax(), - LevelFactor(), - LightFactor(), - TintFactor(), - RadWarhead(), - DurationMultiple(), - ApplicationDelay(), - BuildingApplicationDelay() -{ } - -RadType::~RadType() = default; - -void RadType::AddDefaults() -{ - FindOrAllocate("Radiation"); -} - -void RadType::LoadListSection(CCINIClass *pINI) -{ - for (int i = 0; i < pINI->GetKeyCount(GetMainSection()); ++i) - { - if (pINI->ReadString(GetMainSection(), pINI->GetKeyName(GetMainSection(), i), "", Phobos::readBuffer)) - { - FindOrAllocate(Phobos::readBuffer); - Debug::Log("RadTypes :: LoadListSection check [%s] \n", Phobos::readBuffer); - } - } - - for (size_t i = 0; i < Array.size(); ++i) - Array[i]->LoadFromINI(pINI); -} - -void RadType::LoadFromINI(CCINIClass *pINI) -{ - const char *section = this->Name; - - INI_EX exINI(pINI); - - this->RadWarhead.Read(exINI, section, "RadSiteWarhead" , true); - this->RadSiteColor.Read(exINI, section, "RadColor"); - this->DurationMultiple.Read(exINI, section, "RadDurationMultiple"); - this->ApplicationDelay.Read(exINI, section, "RadApplicationDelay"); - this->BuildingApplicationDelay.Read(exINI, section, "RadApplicationDelay.Building"); - this->LevelMax.Read(exINI, section, "RadLevelMax"); - this->LevelDelay.Read(exINI, section, "RadLevelDelay"); - this->LightDelay.Read(exINI, section, "RadLightDelay"); - this->LevelFactor.Read(exINI, section, "RadLevelFactor"); - this->LightFactor.Read(exINI, section, "RadLightFactor"); - this->TintFactor.Read(exINI, section, "RadTintFactor"); - -} - -template -void RadType::Serialize(T& Stm) { - Stm - .Process(this->DurationMultiple) - .Process(this->ApplicationDelay) - .Process(this->LevelMax) - .Process(this->LevelDelay) - .Process(this->LightDelay) - .Process(this->BuildingApplicationDelay) - .Process(this->LevelFactor) - .Process(this->LightFactor) - .Process(this->TintFactor) - .Process(this->RadSiteColor) - .Process(this->RadWarhead) - ; -}; - -void RadType::LoadFromStream(PhobosStreamReader & Stm) -{ - this->Serialize(Stm); -} - -void RadType::SaveToStream(PhobosStreamWriter & Stm) -{ - this->Serialize(Stm); -} diff --git a/src/Ext/Bullet/Body.cpp b/src/Ext/Bullet/Body.cpp index 8f117825fd..9167c4412e 100644 --- a/src/Ext/Bullet/Body.cpp +++ b/src/Ext/Bullet/Body.cpp @@ -7,7 +7,7 @@ BulletExt::ExtContainer BulletExt::ExtMap; void BulletExt::ExtData::ApplyRadiationToCell(CellStruct Cell, int Spread, int RadLevel) { auto pThis = this->OwnerObject(); - auto const& Instances = RadSiteExt::RadSiteInstance; + auto const& Instances = RadSiteExt::Array; auto const pWeapon = pThis->GetWeaponType(); auto const pWeaponExt = WeaponTypeExt::ExtMap.FindOrAllocate(pWeapon); auto const pRadType = pWeaponExt->RadType; diff --git a/src/Ext/RadSite/Body.cpp b/src/Ext/RadSite/Body.cpp index 2fa3b897c4..9a1a93e8f6 100644 --- a/src/Ext/RadSite/Body.cpp +++ b/src/Ext/RadSite/Body.cpp @@ -1,48 +1,48 @@ #include "Body.h" -#include "../../Enum/RadTypes.h" +#include "../../Enum/RadTypeClass.h" template<> const DWORD Extension::Canary = 0x87654321; RadSiteExt::ExtContainer RadSiteExt::ExtMap; -DynamicVectorClass RadSiteExt::RadSiteInstance; +DynamicVectorClass RadSiteExt::Array; -void RadSiteExt::CreateInstance(CellStruct location, int spread, int amount, WeaponTypeExt::ExtData* pWeaponExt, HouseClass* const pOwner) +void RadSiteExt::CreateInstance(CellStruct location, int spread, int amount, WeaponTypeExt::ExtData* pWeaponExt, HouseClass* const pOwner) { - // use real ctor - auto const pRadSite = GameCreate(); - // auto const cell = MapClass::Instance->TryGetCellAt(location); - auto pRadExt = RadSiteExt::ExtMap.FindOrAllocate(pRadSite); - - //Adding Owner to RadSite , from bullet - if (!pWeaponExt->Rad_NoOwner && pRadExt->RadHouse != pOwner) - pRadExt->RadHouse = pOwner; - - pRadExt->Weapon = pWeaponExt->OwnerObject(); - pRadExt->Type = pWeaponExt->RadType; - pRadSite->SetBaseCell(&location); - pRadSite->SetSpread(spread); - pRadExt->SetRadLevel(amount); - pRadSite->Activate(); - RadSiteInstance.AddUnique(pRadExt); + // use real ctor + auto const pRadSite = GameCreate(); + auto pRadExt = RadSiteExt::ExtMap.FindOrAllocate(pRadSite); + + //Adding Owner to RadSite, from bullet + if (!pWeaponExt->Rad_NoOwner && pRadExt->RadHouse != pOwner) + pRadExt->RadHouse = pOwner; + + pRadExt->Weapon = pWeaponExt->OwnerObject(); + pRadExt->Type = pWeaponExt->RadType; + pRadSite->SetBaseCell(&location); + pRadSite->SetSpread(spread); + pRadExt->SetRadLevel(amount); + pRadSite->Activate(); + + Array.AddUnique(pRadExt); } -void RadSiteExt::CreateInstance(CellStruct location, int spread, int amount, RadType* pType, HouseClass* const pOwner) +void RadSiteExt::CreateInstance(CellStruct location, int spread, int amount, RadTypeClass* pType, HouseClass* const pOwner) { - // use real ctor - auto const pRadSite = GameCreate(); + // use real ctor + auto const pRadSite = GameCreate(); - auto pRadExt = RadSiteExt::ExtMap.FindOrAllocate(pRadSite); + auto pRadExt = RadSiteExt::ExtMap.FindOrAllocate(pRadSite); - pRadExt->RadHouse = pOwner; + pRadExt->RadHouse = pOwner; + pRadExt->Type = pType; + pRadSite->SetBaseCell(&location); + pRadSite->SetSpread(spread); + pRadExt->SetRadLevel(amount); + pRadSite->Activate(); - pRadExt->Type = pType; - pRadSite->SetBaseCell(&location); - pRadSite->SetSpread(spread); - pRadExt->SetRadLevel(amount); - pRadSite->Activate(); - RadSiteInstance.AddUnique(pRadExt); + Array.AddUnique(pRadExt); } /* Including them as EXT so it keep tracked at save/load */ @@ -50,68 +50,66 @@ void RadSiteExt::CreateInstance(CellStruct location, int spread, int amount, Rad // Rewrite because of crashing craziness void RadSiteExt::ExtData::Add(int amount) { - auto pRad = this->OwnerObject(); - int value = pRad->RadLevel * pRad->RadTimeLeft / pRad->RadDuration; - pRad->Deactivate(); - pRad->RadLevel = value + amount; - pRad->RadDuration = pRad->RadLevel * this->Type->GetDurationMultiple(); - pRad->RadTimeLeft = pRad->RadDuration; - pRad->Activate(); + auto pRad = this->OwnerObject(); + int value = pRad->RadLevel * pRad->RadTimeLeft / pRad->RadDuration; + pRad->Deactivate(); + pRad->RadLevel = value + amount; + pRad->RadDuration = pRad->RadLevel * this->Type->GetDurationMultiple(); + pRad->RadTimeLeft = pRad->RadDuration; + pRad->Activate(); } -void RadSiteExt::ExtData::SetRadLevel(int amount) +void RadSiteExt::ExtData::SetRadLevel(int amount) { - auto pRad = this->OwnerObject(); - const int mult = this->Type->GetDurationMultiple(); - pRad->RadLevel = amount; - pRad->RadDuration = mult * amount; - pRad->RadTimeLeft = mult * amount; + auto pRad = this->OwnerObject(); + const int mult = this->Type->GetDurationMultiple(); + pRad->RadLevel = amount; + pRad->RadDuration = mult * amount; + pRad->RadTimeLeft = mult * amount; } // helper function provided by AlexB double RadSiteExt::ExtData::GetRadLevelAt(CellStruct const& cell) { - auto pThis = this->OwnerObject(); - const auto base = MapClass::Instance->GetCellAt(pThis->BaseCell)->GetCoords(); - const auto coords = MapClass::Instance->GetCellAt(cell)->GetCoords(); + auto pThis = this->OwnerObject(); + const auto base = MapClass::Instance->GetCellAt(pThis->BaseCell)->GetCoords(); + const auto coords = MapClass::Instance->GetCellAt(cell)->GetCoords(); - const auto max = static_cast(pThis->SpreadInLeptons); - const auto dist = coords.DistanceFrom(base); + const auto max = static_cast(pThis->SpreadInLeptons); + const auto dist = coords.DistanceFrom(base); - return (dist > max) ? 0.0 : (max - dist) / max * pThis->RadLevel; + return (dist > max) ? 0.0 : (max - dist) / max * pThis->RadLevel; } - + // ============================= // load / save template -void RadSiteExt::ExtData::Serialize(T& Stm) +void RadSiteExt::ExtData::Serialize(T& Stm) { - Stm - .Process(this->Weapon) - .Process(this->RadHouse) - .Process(this->Type) - ; + Stm + .Process(this->Weapon) + .Process(this->RadHouse) + .Process(this->Type) + ; } -void RadSiteExt::ExtData::LoadFromStream(PhobosStreamReader& Stm) +void RadSiteExt::ExtData::LoadFromStream(PhobosStreamReader& Stm) { - - Extension::LoadFromStream(Stm); - this->Serialize(Stm); + Extension::LoadFromStream(Stm); + this->Serialize(Stm); } void RadSiteExt::ExtData::SaveToStream(PhobosStreamWriter& Stm) { - - Extension::SaveToStream(Stm); - this->Serialize(Stm); + Extension::SaveToStream(Stm); + this->Serialize(Stm); } // ============================= // container -RadSiteExt::ExtContainer::ExtContainer() : Container("RadSiteClass") {}; +RadSiteExt::ExtContainer::ExtContainer() : Container("RadSiteClass") { }; RadSiteExt::ExtContainer::~ExtContainer() = default; @@ -120,43 +118,46 @@ RadSiteExt::ExtContainer::~ExtContainer() = default; DEFINE_HOOK(65B28D, RadSiteClass_CTOR, 6) { - GET(RadSiteClass*, pThis, ESI); - auto pRadSiteExt = RadSiteExt::ExtMap.FindOrAllocate(pThis); + GET(RadSiteClass*, pThis, ESI); + auto pRadSiteExt = RadSiteExt::ExtMap.FindOrAllocate(pThis); - RadSiteExt::RadSiteInstance.AddUnique(pRadSiteExt); + RadSiteExt::Array.AddUnique(pRadSiteExt); - return 0; + return 0; } DEFINE_HOOK(65B2F4, RadSiteClass_DTOR, 5) { - GET(RadSiteClass*, pThis, ECX); - auto pRadExt = RadSiteExt::ExtMap.Find(pThis); + GET(RadSiteClass*, pThis, ECX); + auto pRadExt = RadSiteExt::ExtMap.Find(pThis); - RadSiteExt::ExtMap.Remove(pThis); - RadSiteExt::RadSiteInstance.Remove(pRadExt); + RadSiteExt::ExtMap.Remove(pThis); + RadSiteExt::Array.Remove(pRadExt); - return 0; + return 0; } DEFINE_HOOK_AGAIN(65B3D0, RadSiteClass_SaveLoad_Prefix, 5) DEFINE_HOOK(65B450, RadSiteClass_SaveLoad_Prefix, 8) { - GET_STACK(RadSiteClass*, pItem, 0x4); - GET_STACK(IStream*, pStm, 0x8); + GET_STACK(RadSiteClass*, pItem, 0x4); + GET_STACK(IStream*, pStm, 0x8); - RadSiteExt::ExtMap.PrepareStream(pItem, pStm); - return 0; + RadSiteExt::ExtMap.PrepareStream(pItem, pStm); + + return 0; } DEFINE_HOOK(65B43F, RadSiteClass_Load_Suffix, 7) { - RadSiteExt::ExtMap.LoadStatic(); - return 0; + RadSiteExt::ExtMap.LoadStatic(); + + return 0; } DEFINE_HOOK(65B464, RadSiteClass_Save_Suffix, 5) { - RadSiteExt::ExtMap.SaveStatic(); - return 0; + RadSiteExt::ExtMap.SaveStatic(); + + return 0; } \ No newline at end of file diff --git a/src/Ext/RadSite/Body.h b/src/Ext/RadSite/Body.h index caf873acf6..d11bac3310 100644 --- a/src/Ext/RadSite/Body.h +++ b/src/Ext/RadSite/Body.h @@ -1,59 +1,66 @@ #pragma once + #include #include -#include "../_Container.hpp" -#include "../../Utilities/TemplateDef.h" +#include +#include -#include "../WeaponType/Body.h" +#include -class RadType; +class RadTypeClass; -class RadSiteExt { +class RadSiteExt +{ public: - using base_type = RadSiteClass; - - class ExtData final : public Extension - { - public: - Valueable Weapon; - Valueable Type; - Valueable RadHouse; - - ExtData(RadSiteClass* OwnerObject) : Extension(OwnerObject), - RadHouse(nullptr), - Type(), - Weapon(nullptr) - { }; - - virtual ~ExtData() { } - - virtual size_t Size() const { return sizeof(*this); }; - - virtual void InvalidatePointer(void *ptr, bool bRemoved) { } - - virtual void LoadFromStream(PhobosStreamReader& Stm) override; - - virtual void SaveToStream(PhobosStreamWriter& Stm) override; - - virtual void Add(int amount); - virtual void SetRadLevel(int amount); - virtual double GetRadLevelAt(CellStruct const& cell); - - private: - template - void Serialize(T& Stm); - }; - - static DynamicVectorClass RadSiteInstance; - - static void CreateInstance(CellStruct location, int spread, int amount, WeaponTypeExt::ExtData *pWeaponExt, HouseClass* const pOwner); - static void CreateInstance(CellStruct location, int spread, int amount, RadType* pType, HouseClass* const pOwner); - class ExtContainer final : public Container { - public: - ExtContainer(); - ~ExtContainer(); - }; - - static ExtContainer ExtMap; + using base_type = RadSiteClass; + + class ExtData final : public Extension + { + public: + Valueable Weapon; + Valueable Type; + Valueable RadHouse; + + ExtData(RadSiteClass* OwnerObject) : Extension(OwnerObject), + RadHouse(nullptr), + Type(), + Weapon(nullptr) + { + } + + virtual ~ExtData() = default; + + virtual size_t Size() const + { + return sizeof(*this); + }; + + virtual void InvalidatePointer(void* ptr, bool bRemoved) { } + + virtual void LoadFromStream(PhobosStreamReader& Stm) override; + virtual void SaveToStream(PhobosStreamWriter& Stm) override; + + virtual void Add(int amount); + virtual void SetRadLevel(int amount); + virtual double GetRadLevelAt(CellStruct const& cell); + + private: + template + void Serialize(T& Stm); + }; + + static DynamicVectorClass Array; + + static void CreateInstance(CellStruct location, int spread, int amount, WeaponTypeExt::ExtData* pWeaponExt, HouseClass* const pOwner); + static void CreateInstance(CellStruct location, int spread, int amount, RadTypeClass* pType, HouseClass* const pOwner); + + class ExtContainer final : public Container + { + public: + ExtContainer(); + ~ExtContainer(); + }; + + static ExtContainer ExtMap; }; diff --git a/src/Ext/RadSite/Hooks.cpp b/src/Ext/RadSite/Hooks.cpp index cf6266d002..2baa6ff29f 100644 --- a/src/Ext/RadSite/Hooks.cpp +++ b/src/Ext/RadSite/Hooks.cpp @@ -1,46 +1,48 @@ #include "Body.h" + #include #include #include #include #include -#include "../BuildingType/Body.h" -#include "../Bullet/Body.h" -#include "../Rules/Body.h" -#include "../Techno/Body.h" +#include +#include +#include +#include /* - Custom Radiations - Worked out from old uncommented Ares RadSite Hook , adding some more hook - and rewriting some in order to make this working perfecly - Credit : Ares Team , for unused/uncommented source of Hook.RadSite - ,RulesData_LoadBeforeTypeData Hook - Alex-B : GetRadSiteAt ,Helper that used at FootClass_AI & BuildingClass_AI - Radiate , Uncommented - me(Otamaa) adding some more stuffs and rewriting hook that cause crash - TODO : -Testings - // Do this Ares Hook will cause a problem ? - //4DA584 = FootClass_AI_RadImmune, 7 + Custom Radiations + Worked out from old uncommented Ares RadSite Hook , adding some more hook + and rewriting some in order to make this working perfecly + Credit : Ares Team , for unused/uncommented source of Hook.RadSite + ,RulesData_LoadBeforeTypeData Hook + Alex-B : GetRadSiteAt ,Helper that used at FootClass_AI & BuildingClass_AI + Radiate , Uncommented + me(Otamaa) adding some more stuffs and rewriting hook that cause crash + TODO : -Testings + // Do this Ares Hook will cause a problem ? + //4DA584 = FootClass_AI_RadImmune, 7 */ DEFINE_HOOK(469150, BulletClass_Detonate_ApplyRadiation, 5) { - GET(BulletClass* const, pThis, ESI); - GET_BASE(CoordStruct const*, pCoords, 0x8); + GET(BulletClass* const, pThis, ESI); + GET_BASE(CoordStruct const*, pCoords, 0x8); + + auto const pWeapon = pThis->GetWeaponType(); - auto const pWeapon = pThis->GetWeaponType(); + if (pWeapon && pWeapon->RadLevel > 0) + { + auto const pExt = BulletExt::ExtMap.Find(pThis); + auto const pWH = pThis->WH; + auto const cell = CellClass::Coord2Cell(*pCoords); + auto const spread = static_cast(pWH->CellSpread); - if (pWeapon && pWeapon->RadLevel > 0) - { - auto const pExt = BulletExt::ExtMap.Find(pThis); - auto const pWH = pThis->WH; - auto const cell = CellClass::Coord2Cell(*pCoords); - auto const spread = static_cast(pWH->CellSpread); - pExt->ApplyRadiationToCell(cell, spread, pWeapon->RadLevel); - } + pExt->ApplyRadiationToCell(cell, spread, pWeapon->RadLevel); + } - return 0x46920B; + return 0x46920B; } /* @@ -50,284 +52,280 @@ DEFINE_HOOK(469150, BulletClass_Detonate_ApplyRadiation, 5) //Break InfantryClass_AIDeployment_CheckRad atm , will fix later DEFINE_HOOK(46ADE0, BulletClass_ApplyRadiation, 5) { - GET_STACK(CellStruct, location, 0x4); - GET_STACK(int, spread, 0x8); - GET_STACK(int, amount, 0xC); - - auto const& Instances = RadSiteExt::RadSiteInstance; - auto const pType = RadType::FindOrAllocate("Radiation"); - - if (Instances.Count > 0) - { - auto const it = std::find_if(Instances.begin(), Instances.end(), - [=](RadSiteExt::ExtData* const pSite) // Lambda - {// find - return - pSite->Type == pType && - pSite->OwnerObject()->BaseCell == location && - spread == pSite->OwnerObject()->Spread; - }); - - if (it == Instances.end()) - { - RadSiteExt::CreateInstance(location, spread, amount, pType, nullptr); - } - else - { - auto pRadExt = *it; - auto pRadSite = pRadExt->OwnerObject(); - - if (pRadSite->GetRadLevel() + amount > pType->GetLevelMax()) - { - amount = pType->GetLevelMax() - pRadSite->GetRadLevel(); - } - - // Handle It - pRadExt->Add(amount); - } - } - else - { - RadSiteExt::CreateInstance(location, spread, amount, pType, nullptr); - } - - return 0x46AE5E; + GET_STACK(CellStruct, location, 0x4); + GET_STACK(int, spread, 0x8); + GET_STACK(int, amount, 0xC); + + auto const& Instances = RadSiteExt::Array; + auto const pType = RadTypeClass::FindOrAllocate("Radiation"); + + if (Instances.Count > 0) + { + auto const it = std::find_if(Instances.begin(), Instances.end(), + [=](RadSiteExt::ExtData* const pSite) // Lambda + {// find + return + pSite->Type == pType && + pSite->OwnerObject()->BaseCell == location && + spread == pSite->OwnerObject()->Spread; + }); + + if (it == Instances.end()) + { + RadSiteExt::CreateInstance(location, spread, amount, pType, nullptr); + } + else + { + auto pRadExt = *it; + auto pRadSite = pRadExt->OwnerObject(); + + if (pRadSite->GetRadLevel() + amount > pType->GetLevelMax()) + { + amount = pType->GetLevelMax() - pRadSite->GetRadLevel(); + } + + // Handle It + pRadExt->Add(amount); + } + } + else + { + RadSiteExt::CreateInstance(location, spread, amount, pType, nullptr); + } + + return 0x46AE5E; } */ -//Desolator cannot fire his deploy weapon when cloaked +// Fix for desolator unable to fire his deploy weapon when cloaked DEFINE_HOOK(5213E3, InfantryClass_AIDeployment_CheckRad, 4) { - GET(InfantryClass*, D, ESI); - GET(int, WeaponRadLevel, EBX); - - auto const& Instances = RadSiteExt::RadSiteInstance; - auto const pWeapon = D->GetDeployWeapon()->WeaponType; - - int RadLevel = 0; - if (Instances.Count > 0 && pWeapon) - { - auto const pWeaponExt = WeaponTypeExt::ExtMap.FindOrAllocate(pWeapon); - auto const pRadType = pWeaponExt->RadType; - auto const WH = pWeapon->Warhead; - auto CurrentCoord = D->GetCell()->MapCoords; - - auto const it = std::find_if(Instances.begin(), Instances.end(), - [=](RadSiteExt::ExtData* const pSite) // Lambda - {// find - return - pSite->Type == pRadType && - pSite->OwnerObject()->BaseCell == CurrentCoord && - pSite->OwnerObject()->Spread == static_cast(WH->CellSpread) - ; - }); - - if (it != Instances.end()) - { - auto pRadExt = *it; - auto pRadSite = pRadExt->OwnerObject(); - RadLevel = pRadSite->GetRadLevel(); - } - } - - if (D->CloakState == CloakState::Cloaked) - { - D->Uncloak(false); - D->Cloakable = false; - D->NeedsRedraw = true; - auto Text = TechnoExt::ExtMap.Find(D); - Text->WasCloaked = true; - } - - return (RadLevel < WeaponRadLevel) ? 0x5213F4 : 0x521484; + GET(InfantryClass*, pInf, ESI); + GET(int, weaponRadLevel, EBX); + + auto const pWeapon = pInf->GetDeployWeapon()->WeaponType; + + int radLevel = 0; + if (RadSiteExt::Array.Count > 0 && pWeapon) + { + auto const pWeaponExt = WeaponTypeExt::ExtMap.FindOrAllocate(pWeapon); + auto const pRadType = pWeaponExt->RadType; + auto const wh = pWeapon->Warhead; + auto currentCoord = pInf->GetCell()->MapCoords; + + auto const it = std::find_if(RadSiteExt::Array.begin(), RadSiteExt::Array.end(), + [=](RadSiteExt::ExtData* const pSite) + { + return + pSite->Type == pRadType && + pSite->OwnerObject()->BaseCell == currentCoord && + pSite->OwnerObject()->Spread == static_cast(wh->CellSpread) + ; + }); + + if (it != RadSiteExt::Array.end()) + { + auto pRadExt = *it; + auto pRadSite = pRadExt->OwnerObject(); + radLevel = pRadSite->GetRadLevel(); + } + } + + if (pInf->CloakState == CloakState::Cloaked) + { + pInf->Uncloak(false); + pInf->Cloakable = false; + pInf->NeedsRedraw = true; + auto pExt = TechnoExt::ExtMap.Find(pInf); + pExt->WasCloaked = true; + } + + return (radLevel < weaponRadLevel) ? + 0x5213F4 : 0x521484; } // Too OP, be aware DEFINE_HOOK(43FB23, BuildingClass_AI, 5) { - GET(BuildingClass* const, pBuilding, ECX); + GET(BuildingClass* const, pBuilding, ECX); - if (pBuilding->IsIronCurtained() || pBuilding->Type->ImmuneToRadiation || pBuilding->InLimbo || pBuilding->BeingWarpedOut) - { - return 0; - } + if (pBuilding->IsIronCurtained() || pBuilding->Type->ImmuneToRadiation || pBuilding->InLimbo || pBuilding->BeingWarpedOut) + return 0; - auto const MainCoords = pBuilding->GetMapCoords(); + auto const buildingCoords = pBuilding->GetMapCoords(); + for (auto pFoundation = pBuilding->GetFoundationData(false); *pFoundation != CellStruct { 0x7FFF, 0x7FFF }; ++pFoundation) + { + CellStruct CurrentCoord = buildingCoords + *pFoundation; - for (auto pFoundation = pBuilding->GetFoundationData(false); *pFoundation != CellStruct{ 0x7FFF, 0x7FFF }; ++pFoundation) - { - CellStruct CurrentCoord = MainCoords + *pFoundation; + for (auto pRadExt : RadSiteExt::Array) + { + RadSiteClass* pRadSite = pRadExt->OwnerObject(); + RadTypeClass* pType = pRadExt->Type; - for (auto pRadExt : RadSiteExt::RadSiteInstance) - { - RadSiteClass* pRadSite = pRadExt->OwnerObject(); + // Check the distance, if not in range, just skip this one + double orDistance = pRadSite->BaseCell.DistanceFrom(CurrentCoord); + if (pRadSite->Spread < orDistance - 0.5) + continue; - // Check the distance, if not in range, just skip this one - double orDistance = pRadSite->BaseCell.DistanceFrom(CurrentCoord); - if (pRadSite->Spread < orDistance - 0.5) - continue; + int delay = pType->GetBuildingApplicationDelay(); + if ((delay == 0) || (Unsorted::CurrentFrame % delay != 0)) + continue; - RadType* pType = pRadExt->Type; - int RadApplicationDelay = pType->BuildingApplicationDelay.Get(RulesExt::Global()->RadApplDelayBuilding); - if ((RadApplicationDelay == 0) || (Unsorted::CurrentFrame % RadApplicationDelay != 0)) - continue; + if (pRadExt->GetRadLevelAt(CurrentCoord) <= 0.0 || !pType->GetWarhead()) + continue; - if (pRadExt->GetRadLevelAt(CurrentCoord) <= 0.0 || !pType->GetWarhead()) - continue; + auto wh = pType->GetWarhead(); + auto absolute = wh->WallAbsoluteDestroyer; + bool ignore = pBuilding->Type->Wall && absolute; + auto damage = static_cast((pRadExt->GetRadLevelAt(CurrentCoord) / 2) * pType->GetLevelFactor()); - auto WH = pType->GetWarhead(); - auto absolute = WH->WallAbsoluteDestroyer; - bool ignore = pBuilding->Type->Wall && absolute; - auto damage = static_cast((pRadExt->GetRadLevelAt(CurrentCoord) / 2) * pType->GetLevelFactor()); + if (pBuilding->IsAlive) // simple fix for previous issues + pBuilding->ReceiveDamage(&damage, static_cast(orDistance), wh, nullptr, ignore, absolute, pRadExt->RadHouse.Get()); + } + } - if (pBuilding->IsAlive)// simple fix for previous issues - pBuilding->ReceiveDamage(&damage, static_cast(orDistance), WH, nullptr, ignore, absolute, pRadExt->RadHouse.Get()); - } - } - - return 0; + return 0; } // be aware that this function is updated every frame // putting debug log here can become mess because it gonna print bunch of debug line DEFINE_HOOK(4DA554, FootClass_AI_RadSiteClass, 5) { - GET(FootClass* const, pFoot, ESI); - - auto state = static_cast(R->AL()); - - if (!pFoot->IsIronCurtained() && !pFoot->GetTechnoType()->ImmuneToRadiation && !pFoot->InLimbo && !pFoot->IsInAir()) - { - CellStruct CurrentCoord = pFoot->GetCell()->MapCoords; - - // Loop for each different radiation stored in the RadSites container - for (auto const pRadExt : RadSiteExt::RadSiteInstance) - { - - RadSiteClass* pRadSite = pRadExt->OwnerObject(); - - // Check the distance, if not in range, just skip this one - double orDistance = pRadSite->BaseCell.DistanceFrom(CurrentCoord); - if (pRadSite->Spread < orDistance - 0.7) - continue; - - RadType* pType = pRadExt->Type; - int RadApplicationDelay = pType->GetApplicationDelay(); - if ((RadApplicationDelay == 0) || (Unsorted::CurrentFrame % RadApplicationDelay != 0)) - continue; - - // for more precise dmg calculation - double RadLevel = pRadExt->GetRadLevelAt(CurrentCoord); - if (RadLevel <= 0.0 || !pType->GetWarhead()) - continue; - - int Damage = static_cast(RadLevel* pType->GetLevelFactor()); - int Distance = static_cast(orDistance); - auto WH = pType->GetWarhead(); - auto absolute = WH->WallAbsoluteDestroyer; - - if (pFoot->IsAlive || !pFoot->IsSinking)// simple fix for previous issues - state = pFoot->ReceiveDamage(&Damage, Distance, WH, nullptr, false, absolute, pRadExt->RadHouse.Get()); - } - } - - R->EAX(state); - return pFoot->IsAlive ? 0x4DA63B : 0x4DAF00; + GET(FootClass* const, pFoot, ESI); + auto state = static_cast(R->AL()); + + if (!pFoot->IsIronCurtained() && !pFoot->GetTechnoType()->ImmuneToRadiation && !pFoot->InLimbo && !pFoot->IsInAir()) + { + CellStruct CurrentCoord = pFoot->GetCell()->MapCoords; + + // Loop for each different radiation stored in the RadSites container + for (auto const pRadExt : RadSiteExt::Array) + { + RadSiteClass* pRadSite = pRadExt->OwnerObject(); + + // Check the distance, if not in range, just skip this one + double orDistance = pRadSite->BaseCell.DistanceFrom(CurrentCoord); + if (pRadSite->Spread < orDistance - 0.7) + continue; + + RadTypeClass* pType = pRadExt->Type; + int RadApplicationDelay = pType->GetApplicationDelay(); + if ((RadApplicationDelay == 0) || (Unsorted::CurrentFrame % RadApplicationDelay != 0)) + continue; + + // for more precise dmg calculation + double RadLevel = pRadExt->GetRadLevelAt(CurrentCoord); + if (RadLevel <= 0.0 || !pType->GetWarhead()) + continue; + + int damage = static_cast(RadLevel * pType->GetLevelFactor()); + int distance = static_cast(orDistance); + auto wh = pType->GetWarhead(); + auto absolute = wh->WallAbsoluteDestroyer; + + if (pFoot->IsAlive || !pFoot->IsSinking)// simple fix for previous issues + state = pFoot->ReceiveDamage(&damage, distance, wh, nullptr, false, absolute, pRadExt->RadHouse.Get()); + } + } + + R->EAX(state); + + return pFoot->IsAlive ? 0x4DA63B : 0x4DAF00; } DEFINE_HOOK(65B593, RadSiteClass_Activate_Delay, 6) { - GET(RadSiteClass* const, pThis, ECX); - auto const pExt = RadSiteExt::ExtMap.Find(pThis); + GET(RadSiteClass* const, pThis, ECX); + auto const pExt = RadSiteExt::ExtMap.Find(pThis); - auto const CurrentLevel = pThis->GetRadLevel(); - auto LevelDelay = pExt->Type->GetLevelDelay(); - auto LightDelay = pExt->Type->GetLightDelay(); + auto const currentLevel = pThis->GetRadLevel(); + auto levelDelay = pExt->Type->GetLevelDelay(); + auto lightDelay = pExt->Type->GetLightDelay(); - if (CurrentLevel < LevelDelay) - { - LevelDelay = CurrentLevel; - LightDelay = CurrentLevel; - } + if (currentLevel < levelDelay) + { + levelDelay = currentLevel; + lightDelay = currentLevel; + } - R->ECX(LevelDelay); - R->EAX(LightDelay); + R->ECX(levelDelay); + R->EAX(lightDelay); - return 0x65B59F; + return 0x65B59F; } -#define GET_RADSITE(reg , value)\ +#define GET_RADSITE(reg, value)\ GET(RadSiteClass* const, pThis, reg);\ - RadSiteExt::ExtData *pExt = RadSiteExt::ExtMap.Find(pThis);\ - auto Output = pExt->Type->## value ##; + RadSiteExt::ExtData* pExt = RadSiteExt::ExtMap.Find(pThis);\ + auto output = pExt->Type->## value ##; DEFINE_HOOK(65B5CE, RadSiteClass_Activate_Color, 6) { - GET_RADSITE(ESI, GetColor()); + GET_RADSITE(ESI, GetColor()); - R->EAX(0); - R->EDX(0); - R->EBX(0); + R->EAX(0); + R->EDX(0); + R->EBX(0); - R->DL(Output.G); - R->EBP(R->EDX()); + R->DL(output.G); + R->EBP(R->EDX()); - R->BL(Output.B); - R->AL(Output.R); + R->BL(output.B); + R->AL(output.R); - // point out the missing register -Otamaa - R->EDI(pThis); + // point out the missing register - Otamaa + R->EDI(pThis); - return 0x65B604; + return 0x65B604; } DEFINE_HOOK(65B63E, RadSiteClass_Activate_LightFactor, 6) { - GET_RADSITE(ESI, GetLightFactor()); + GET_RADSITE(ESI, GetLightFactor()); - __asm fmul Output; + __asm fmul output; - return 0x65B644; + return 0x65B644; } DEFINE_HOOK_AGAIN(65B6A0, RadSiteClass_Activate_TintFactor, 6) DEFINE_HOOK_AGAIN(65B6CA, RadSiteClass_Activate_TintFactor, 6) DEFINE_HOOK(65B6F2, RadSiteClass_Activate_TintFactor, 6) { - GET_RADSITE(ESI, GetTintFactor()); + GET_RADSITE(ESI, GetTintFactor()); - __asm fmul Output; + __asm fmul output; - return R->Origin() + 6; + return R->Origin() + 6; } DEFINE_HOOK(65B843, RadSiteClass_AI_LevelDelay, 6) { - GET_RADSITE(ESI, GetLevelDelay()); + GET_RADSITE(ESI, GetLevelDelay()); - R->ECX(Output); + R->ECX(output); - return 0x65B849; + return 0x65B849; } DEFINE_HOOK(65B8B9, RadSiteClass_AI_LightDelay, 6) { - GET_RADSITE(ESI, GetLightDelay()); + GET_RADSITE(ESI, GetLightDelay()); - R->ECX(Output); + R->ECX(output); - return 0x65B8BF; + return 0x65B8BF; } // Additional Hook below DEFINE_HOOK(65BB67, RadSite_Deactivate, 6) { - GET_RADSITE(ECX, GetLevelDelay()); + GET_RADSITE(ECX, GetLevelDelay()); - R->ESI(Output); + R->ESI(output); - __asm xor edx, edx; // fixing integer overflow crash - __asm idiv esi; + __asm xor edx, edx; // fixing integer overflow crash + __asm idiv esi; - return 0x65BB6D; + return 0x65BB6D; } \ No newline at end of file diff --git a/src/Ext/Rules/Body.cpp b/src/Ext/Rules/Body.cpp index 835b73b386..e47f8c8ba4 100644 --- a/src/Ext/Rules/Body.cpp +++ b/src/Ext/Rules/Body.cpp @@ -1,122 +1,135 @@ #include "Body.h" #include "../Side/Body.h" -#include "../../Enum/RadTypes.h" #include "../../Utilities/TemplateDef.h" +#include #include #include template<> const DWORD Extension::Canary = 0x12341234; std::unique_ptr RulesExt::Data = nullptr; -void RulesExt::Allocate(RulesClass* pThis) { - Data = std::make_unique(pThis); +void RulesExt::Allocate(RulesClass* pThis) +{ + Data = std::make_unique(pThis); } -void RulesExt::Remove(RulesClass* pThis) { - Data = nullptr; +void RulesExt::Remove(RulesClass* pThis) +{ + Data = nullptr; } -void RulesExt::LoadFromINIFile(RulesClass* pThis, CCINIClass* pINI) { - Data->LoadFromINI(pINI); +void RulesExt::LoadFromINIFile(RulesClass* pThis, CCINIClass* pINI) +{ + Data->LoadFromINI(pINI); } -void RulesExt::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI) { - - RadType::LoadListSection(pINI); - Data->LoadBeforeTypeData(pThis, pINI); +void RulesExt::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI) +{ + RadTypeClass::LoadListSection(pINI); + Data->LoadBeforeTypeData(pThis, pINI); } -void RulesExt::LoadAfterTypeData(RulesClass* pThis, CCINIClass* pINI) { - if (pINI == CCINIClass::INI_Rules) { - Data->InitializeAfterTypeData(pThis); - } - Data->LoadAfterTypeData(pThis, pINI); +void RulesExt::LoadAfterTypeData(RulesClass* pThis, CCINIClass* pINI) +{ + if (pINI == CCINIClass::INI_Rules) + Data->InitializeAfterTypeData(pThis); + + Data->LoadAfterTypeData(pThis, pINI); } -void RulesExt::ExtData::InitializeConstants() { +void RulesExt::ExtData::InitializeConstants() +{ } -void RulesExt::ExtData::LoadFromINIFile(CCINIClass* pINI) { - // earliest loader - can't really do much because nothing else is initialized yet, so lookups won't work +void RulesExt::ExtData::LoadFromINIFile(CCINIClass* pINI) +{ + // earliest loader - can't really do much because nothing else is initialized yet, so lookups won't work } void RulesExt::ExtData::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI) { - RulesExt::ExtData* pData = RulesExt::Global(); + RulesExt::ExtData* pData = RulesExt::Global(); - if (!pData) { - return; - } + if (!pData) + return; - INI_EX exINI(pINI); + INI_EX exINI(pINI); - this->RadApplDelayBuilding.Read(exINI, "Radiation", "RadApplicationDelay.Building"); - this->Pips_Shield.Read(exINI, "AudioVisual", "Pips.Shield"); - this->Pips_Shield_Buildings.Read(exINI, "AudioVisual", "Pips.Shield.Building"); + this->RadApplicationDelay_Building.Read(exINI, "Radiation", "RadApplicationDelay.Building"); + this->Pips_Shield.Read(exINI, "AudioVisual", "Pips.Shield"); + this->Pips_Shield_Buildings.Read(exINI, "AudioVisual", "Pips.Shield.Building"); } // this runs between the before and after type data loading methods for rules ini -void RulesExt::ExtData::InitializeAfterTypeData(RulesClass* const pThis) { - +void RulesExt::ExtData::InitializeAfterTypeData(RulesClass* const pThis) +{ + } // this should load everything that TypeData is not dependant on // i.e. InfantryElectrocuted= can go here since nothing refers to it // but [GenericPrerequisites] have to go earlier because they're used in parsing TypeData -void RulesExt::ExtData::LoadAfterTypeData(RulesClass* pThis, CCINIClass* pINI) { - RulesExt::ExtData* pData = RulesExt::Global(); +void RulesExt::ExtData::LoadAfterTypeData(RulesClass* pThis, CCINIClass* pINI) +{ + RulesExt::ExtData* pData = RulesExt::Global(); - if (!pData) { - return; - } + if (!pData) + return; - INI_EX exINI(pINI); + INI_EX exINI(pINI); } -bool RulesExt::DetailsCurrentlyEnabled() { - // not only checks for the min frame rate from the rules, but also whether - // the low frame rate is actually desired. in that case, don't reduce. - auto const current = FPSCounter::CurrentFrameRate; - auto const wanted = static_cast( - 60 / Math::clamp(GameOptionsClass::Instance->GameSpeed, 1, 6)); +bool RulesExt::DetailsCurrentlyEnabled() +{ + // not only checks for the min frame rate from the rules, but also whether + // the low frame rate is actually desired. in that case, don't reduce. + auto const current = FPSCounter::CurrentFrameRate; + auto const wanted = static_cast( + 60 / Math::clamp(GameOptionsClass::Instance->GameSpeed, 1, 6)); - return current >= wanted || current >= Detail::GetMinFrameRate(); + return current >= wanted || current >= Detail::GetMinFrameRate(); } -bool RulesExt::DetailsCurrentlyEnabled(int const minDetailLevel) { - return GameOptionsClass::Instance->DetailLevel >= minDetailLevel - && DetailsCurrentlyEnabled(); +bool RulesExt::DetailsCurrentlyEnabled(int const minDetailLevel) +{ + return GameOptionsClass::Instance->DetailLevel >= minDetailLevel + && DetailsCurrentlyEnabled(); } // ============================= // load / save template -void RulesExt::ExtData::Serialize(T& Stm) { - Stm - .Process(this->Pips_Shield) - .Process(this->Pips_Shield_Buildings) - .Process(this->RadApplDelayBuilding) - ; +void RulesExt::ExtData::Serialize(T& Stm) +{ + Stm + .Process(this->Pips_Shield) + .Process(this->Pips_Shield_Buildings) + .Process(this->RadApplicationDelay_Building) + ; } -void RulesExt::ExtData::LoadFromStream(PhobosStreamReader& Stm) { - Extension::LoadFromStream(Stm); - this->Serialize(Stm); +void RulesExt::ExtData::LoadFromStream(PhobosStreamReader& Stm) +{ + Extension::LoadFromStream(Stm); + this->Serialize(Stm); } -void RulesExt::ExtData::SaveToStream(PhobosStreamWriter& Stm) { - Extension::SaveToStream(Stm); - this->Serialize(Stm); +void RulesExt::ExtData::SaveToStream(PhobosStreamWriter& Stm) +{ + Extension::SaveToStream(Stm); + this->Serialize(Stm); } -bool RulesExt::LoadGlobals(PhobosStreamReader& Stm) { - return Stm.Success(); +bool RulesExt::LoadGlobals(PhobosStreamReader& Stm) +{ + return Stm.Success(); } -bool RulesExt::SaveGlobals(PhobosStreamWriter& Stm) { - return Stm.Success(); +bool RulesExt::SaveGlobals(PhobosStreamWriter& Stm) +{ + return Stm.Success(); } // ============================= @@ -124,18 +137,20 @@ bool RulesExt::SaveGlobals(PhobosStreamWriter& Stm) { DEFINE_HOOK(667A1D, RulesClass_CTOR, 5) { - GET(RulesClass*, pItem, ESI); + GET(RulesClass*, pItem, ESI); + + RulesExt::Allocate(pItem); - RulesExt::Allocate(pItem); - return 0; + return 0; } DEFINE_HOOK(667A30, RulesClass_DTOR, 5) { - GET(RulesClass*, pItem, ECX); + GET(RulesClass*, pItem, ECX); + + RulesExt::Remove(pItem); - RulesExt::Remove(pItem); - return 0; + return 0; } IStream* g_pStm = nullptr; @@ -143,70 +158,73 @@ IStream* g_pStm = nullptr; DEFINE_HOOK_AGAIN(674730, RulesClass_SaveLoad_Prefix, 6) DEFINE_HOOK(675210, RulesClass_SaveLoad_Prefix, 5) { - //GET(RulesClass*, pItem, ECX); - GET_STACK(IStream*, pStm, 0x4); + //GET(RulesClass*, pItem, ECX); + GET_STACK(IStream*, pStm, 0x4); - g_pStm = pStm; + g_pStm = pStm; - return 0; + return 0; } DEFINE_HOOK(678841, RulesClass_Load_Suffix, 7) { - auto buffer = RulesExt::Global(); + auto buffer = RulesExt::Global(); - PhobosByteStream Stm(0); - if (Stm.ReadBlockFromStream(g_pStm)) { - PhobosStreamReader Reader(Stm); + PhobosByteStream Stm(0); + if (Stm.ReadBlockFromStream(g_pStm)) + { + PhobosStreamReader Reader(Stm); - if (Reader.Expect(RulesExt::ExtData::Canary) && Reader.RegisterChange(buffer)) { - buffer->LoadFromStream(Reader); - } - } + if (Reader.Expect(RulesExt::ExtData::Canary) && Reader.RegisterChange(buffer)) + buffer->LoadFromStream(Reader); + } - return 0; + return 0; } DEFINE_HOOK(675205, RulesClass_Save_Suffix, 8) { - auto buffer = RulesExt::Global(); - PhobosByteStream saver(sizeof(*buffer)); - PhobosStreamWriter writer(saver); + auto buffer = RulesExt::Global(); + PhobosByteStream saver(sizeof(*buffer)); + PhobosStreamWriter writer(saver); - writer.Expect(RulesExt::ExtData::Canary); - writer.RegisterChange(buffer); + writer.Expect(RulesExt::ExtData::Canary); + writer.RegisterChange(buffer); - buffer->SaveToStream(writer); - saver.WriteBlockToStream(g_pStm); + buffer->SaveToStream(writer); + saver.WriteBlockToStream(g_pStm); - return 0; + return 0; } DEFINE_HOOK(668BF0, RulesClass_Addition, 5) { - GET(RulesClass*, pItem, ECX); - GET_STACK(CCINIClass*, pINI, 0x4); + GET(RulesClass*, pItem, ECX); + GET_STACK(CCINIClass*, pINI, 0x4); - // RulesClass::Initialized = false; - RulesExt::LoadFromINIFile(pItem, pINI); - return 0; + // RulesClass::Initialized = false; + RulesExt::LoadFromINIFile(pItem, pINI); + + return 0; } DEFINE_HOOK(679A15, RulesData_LoadBeforeTypeData, 6) { - GET(RulesClass*, pItem, ECX); - GET_STACK(CCINIClass*, pINI, 0x4); + GET(RulesClass*, pItem, ECX); + GET_STACK(CCINIClass*, pINI, 0x4); + + // RulesClass::Initialized = true; + RulesExt::LoadBeforeTypeData(pItem, pINI); - // RulesClass::Initialized = true; - RulesExt::LoadBeforeTypeData(pItem, pINI); - return 0; + return 0; } DEFINE_HOOK(679CAF, RulesData_LoadAfterTypeData, 5) { - RulesClass* pItem = RulesClass::Global(); - GET(CCINIClass*, pINI, ESI); + RulesClass* pItem = RulesClass::Global(); + GET(CCINIClass*, pINI, ESI); + + RulesExt::LoadAfterTypeData(pItem, pINI); - RulesExt::LoadAfterTypeData(pItem, pINI); - return 0; + return 0; } \ No newline at end of file diff --git a/src/Ext/Rules/Body.h b/src/Ext/Rules/Body.h index 0e1504486f..998f3ea985 100644 --- a/src/Ext/Rules/Body.h +++ b/src/Ext/Rules/Body.h @@ -3,12 +3,11 @@ #include #include -#include "../_Container.hpp" -#include "../../Utilities/Constructs.h" -#include "../../Utilities/Template.h" +#include +#include +#include -#include "../../Enum/RadTypes.h" -#include "../../Misc/Debug.h" +#include class AnimTypeClass; @@ -27,12 +26,12 @@ class RulesExt public: Valueable> Pips_Shield; Valueable> Pips_Shield_Buildings; + Valueable RadApplicationDelay_Building; - Valueable RadApplDelayBuilding; ExtData(RulesClass* OwnerObject) : Extension(OwnerObject) , Pips_Shield({ -1,-1,-1 }) , Pips_Shield_Buildings({ -1,-1,-1 }) - , RadApplDelayBuilding(0) + , RadApplicationDelay_Building(0) { } virtual ~ExtData() = default; diff --git a/src/Ext/Techno/Body.cpp b/src/Ext/Techno/Body.cpp index a5578f52be..a2f376b789 100644 --- a/src/Ext/Techno/Body.cpp +++ b/src/Ext/Techno/Body.cpp @@ -125,6 +125,22 @@ void TechnoExt::ApplySpawn_LimitRange(TechnoClass* pThis) } } +// TODO: move the hook to InfantryExt::AI +void TechnoExt::ApplyCloak_Undeployed(TechnoClass* pThis) +{ + if (auto pInf = static_cast(pThis)) + { + auto pTypeData = TechnoExt::ExtMap.Find(pThis); + if (pTypeData->WasCloaked && pInf->SequenceAnim == Sequence::Undeploy && pInf->IsDeployed()) + { + pThis->Cloakable = true; + pThis->UpdateCloak(); + pThis->NeedsRedraw = true; + pTypeData->WasCloaked = false; + } + } +} + bool TechnoExt::IsHarvesting(TechnoClass* pThis) { if (!pThis || pThis->InLimbo) @@ -158,32 +174,17 @@ bool TechnoExt::HasAvailableDock(TechnoClass* pThis) return false; } -void TechnoExt::ApplyCloak_Undeployed(TechnoClass* pThis) -{ - if (auto pinf = static_cast(pThis)) - { - auto Text = TechnoExt::ExtMap.Find(pThis); - - if (Text->WasCloaked && pinf->SequenceAnim == Sequence::Undeploy && pinf->IsDeployed()) - { - pThis->Cloakable = true; - pThis->UpdateCloak(); - pThis->NeedsRedraw = true; - Text->WasCloaked = false; - } - } -} // ============================= // load / save template void TechnoExt::ExtData::Serialize(T& Stm) { - Stm - .Process(this->InterceptedBullet) - .Process(this->ShieldData) - .Process(this->WasCloaked) - ; + Stm + .Process(this->InterceptedBullet) + .Process(this->ShieldData) + .Process(this->WasCloaked) + ; } void TechnoExt::ExtData::LoadFromStream(PhobosStreamReader& Stm) diff --git a/src/Ext/WeaponType/Body.cpp b/src/Ext/WeaponType/Body.cpp index 7460281b86..d4d16137d5 100644 --- a/src/Ext/WeaponType/Body.cpp +++ b/src/Ext/WeaponType/Body.cpp @@ -5,7 +5,7 @@ WeaponTypeExt::ExtContainer WeaponTypeExt::ExtMap; void WeaponTypeExt::ExtData::Initialize() { - this->RadType = RadType::FindOrAllocate("Radiation"); + this->RadType = RadTypeClass::FindOrAllocate("Radiation"); } // ============================= @@ -30,7 +30,7 @@ void WeaponTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) this->Bolt_Disable2.Read(exINI, pSection, "Bolt.Disable2"); this->Bolt_Disable3.Read(exINI, pSection, "Bolt.Disable3"); - // RadType + // RadTypeClass // if (this->OwnerObject()->RadLevel > 0) // { this->RadType.Read(exINI, pSection, "RadType", true); diff --git a/src/Ext/WeaponType/Body.h b/src/Ext/WeaponType/Body.h index f2b3a584bb..40a1f6bc29 100644 --- a/src/Ext/WeaponType/Body.h +++ b/src/Ext/WeaponType/Body.h @@ -5,7 +5,7 @@ #include "../_Container.hpp" #include "../../Utilities/TemplateDef.h" -#include "../../Enum/RadTypes.h" +#include "../../Enum/RadTypeClass.h" class WeaponTypeExt { @@ -18,7 +18,7 @@ class WeaponTypeExt Valueable DiskLaser_Radius; Valueable DiskLaser_Circumference; - Valueable RadType; + Valueable RadType; Valueable Rad_NoOwner; Valueable Bolt_Disable1; Valueable Bolt_Disable2; diff --git a/src/Phobos.Ext.cpp b/src/Phobos.Ext.cpp index aa1ccd2f48..ee60297be7 100644 --- a/src/Phobos.Ext.cpp +++ b/src/Phobos.Ext.cpp @@ -16,7 +16,7 @@ #include "Ext/WarheadType/Body.h" #include "Ext/WeaponType/Body.h" -#include "Enum/RadTypes.h" +#include "Enum/RadTypeClass.h" #include @@ -230,7 +230,7 @@ auto MassActions = MassAction < WarheadTypeExt, WeaponTypeExt, // enum classes - RadType + RadTypeClass // other classes > ();