From ed17c0448967e41adabbc8bb5016e6acfd17a0ea Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Thu, 11 Dec 2025 11:14:07 +0800 Subject: [PATCH 01/20] update --- src/Ext/House/Body.cpp | 2 + src/Ext/House/Body.h | 4 ++ src/Ext/House/Hooks.cpp | 26 +++++++++ src/Ext/TAction/Body.cpp | 123 +++++++++++++++++++++++++++++++++++++++ src/Ext/TAction/Body.h | 6 ++ 5 files changed, 161 insertions(+) diff --git a/src/Ext/House/Body.cpp b/src/Ext/House/Body.cpp index 28f2083b7d..64fd484b81 100644 --- a/src/Ext/House/Body.cpp +++ b/src/Ext/House/Body.cpp @@ -653,6 +653,8 @@ void HouseExt::ExtData::Serialize(T& Stm) .Process(this->SuspendedEMPulseSWs) .Process(this->SuperExts) .Process(this->ForceEnemyIndex) + .Process(this->TeamDelay) + .Process(this->FreeRadar) ; } diff --git a/src/Ext/House/Body.h b/src/Ext/House/Body.h index f455b88098..5404662e7b 100644 --- a/src/Ext/House/Body.h +++ b/src/Ext/House/Body.h @@ -66,6 +66,8 @@ class HouseExt std::vector SuperExts; int ForceEnemyIndex; + int TeamDelay; + bool FreeRadar; ExtData(HouseClass* OwnerObject) : Extension(OwnerObject) , PowerPlantEnhancers {} @@ -95,6 +97,8 @@ class HouseExt , SuspendedEMPulseSWs {} , SuperExts(SuperWeaponTypeClass::Array.Count) , ForceEnemyIndex(-1) + , TeamDelay(-1) + , FreeRadar(ScenarioClass::Instance->FreeRadar) { } bool OwnsLimboDeliveredBuilding(BuildingClass* pBuilding) const; diff --git a/src/Ext/House/Hooks.cpp b/src/Ext/House/Hooks.cpp index 9e8bf145c7..128563c707 100644 --- a/src/Ext/House/Hooks.cpp +++ b/src/Ext/House/Hooks.cpp @@ -457,3 +457,29 @@ DEFINE_HOOK(0x4FD8F7, HouseClass_UpdateAI_OnLastLegs, 0x10) return ret; } + +DEFINE_HOOK(0x4F8ACC, HouseClass_Update_ResetTeamDelay, 0x6) +{ + enum { ResetTeamDelay = 0x4F8AD5 }; + + GET(HouseClass*, pThis, ESI); + + const int teamDelay = HouseExt::ExtMap.Find(pThis)->TeamDelay; + + if (teamDelay >= 0) + { + R->ECX(teamDelay); + return ResetTeamDelay; + } + + return 0; +} + +DEFINE_HOOK(0x508E37, HouseClass_UpdateRadar_FreeRadar, 0x6) +{ + enum { FreeRadar = 0x508F2A, Continue = 0x508E4A }; + + GET(HouseClass*, pThis, ECX); + + return HouseExt::ExtMap.Find(pThis)->FreeRadar ? FreeRadar : Continue; +} diff --git a/src/Ext/TAction/Body.cpp b/src/Ext/TAction/Body.cpp index 9284bebb66..3547e619f3 100644 --- a/src/Ext/TAction/Body.cpp +++ b/src/Ext/TAction/Body.cpp @@ -71,6 +71,8 @@ bool TActionExt::Execute(TActionClass* pThis, HouseClass* pHouse, ObjectClass* p case PhobosTriggerAction::ToggleMCVRedeploy: return TActionExt::ToggleMCVRedeploy(pThis, pHouse, pObject, pTrigger, location); + case PhobosTriggerAction::UndeployToWaypoint: + return TActionExt::UndeployToWaypoint(pThis, pHouse, pObject, pTrigger, location); case PhobosTriggerAction::EditAngerNode: return TActionExt::EditAngerNode(pThis, pHouse, pObject, pTrigger, location); @@ -78,6 +80,10 @@ bool TActionExt::Execute(TActionClass* pThis, HouseClass* pHouse, ObjectClass* p return TActionExt::ClearAngerNode(pThis, pHouse, pObject, pTrigger, location); case PhobosTriggerAction::SetForceEnemy: return TActionExt::SetForceEnemy(pThis, pHouse, pObject, pTrigger, location); + case PhobosTriggerAction::SetFreeRadar: + return TActionExt::SetFreeRadar(pThis, pHouse, pObject, pTrigger, location); + case PhobosTriggerAction::SetTeamDelay: + return TActionExt::SetTeamDelay(pThis, pHouse, pObject, pTrigger, location); case PhobosTriggerAction::CreateBannerLocal: return TActionExt::CreateBannerLocal(pThis, pHouse, pObject, pTrigger, location); @@ -384,6 +390,91 @@ bool TActionExt::ToggleMCVRedeploy(TActionClass* pThis, HouseClass* pHouse, Obje return true; } +bool TActionExt::UndeployToWaypoint(TActionClass* const pThis, HouseClass* const pHouse, ObjectClass* const pObject, TriggerClass* const pTrigger, const CellStruct& location) +{ + const auto& nCell = ScenarioExt::Global()->Waypoints[pThis->Param4]; + CellClass* const pCell = MapClass::Instance.TryGetCellAt(nCell); + + if (!pCell) + return true; + + bool allHouse = false; + HouseClass* vHouse = nullptr; + const int houseIndex = pThis->Param3; + + if (houseIndex >= 0) + { + vHouse = HouseClass::Index_IsMP(houseIndex) ? + HouseClass::FindByIndex(houseIndex) : HouseClass::FindByCountryIndex(houseIndex); + } + else if (houseIndex == -1) + { + allHouse = true; + } + + if (!allHouse && !vHouse) + return true; + + const char* buildingName = pThis->Text; + bool allBuilding = false; + BuildingTypeClass* pBuildingType = nullptr; + + if (!strcmp(buildingName, "")) + { + allBuilding = true; + } + else + { + pBuildingType = BuildingTypeClass::Find(buildingName); + } + + if (!allBuilding && !pBuildingType) + return true; + + // Thanks to chaserli for the relevant code! + // There should be a more perfect way to do this, but I don't know how. + auto canUndeploy = [pThis, pTrigger, allBuilding, allHouse, pBuildingType, vHouse](BuildingClass* pBuilding) + { + auto const pType = pBuilding->Type; + + if (!pType->UndeploysInto || + (!allBuilding && pType != pBuildingType) || + (!allHouse && pBuilding->Owner != vHouse) || + !pBuilding->IsAlive || pBuilding->Health <= 0 || pBuilding->InLimbo) + { + return false; + } + + if (pType->ConstructionYard) + { + // Conyards can't undeploy if MCVRedeploy=no + if (!GameModeOptionsClass::Instance.MCVRedeploy) + return false; + // or MindControlledBy YURIX (why? for balance?) + if (!RulesExt::Global()->AllowDeployControlledMCV && pBuilding->MindControlledBy) + return false; + } + + return true; + }; + + for (const auto pBuilding : BuildingClass::Array) + { + if (!canUndeploy(pBuilding)) + continue; + + // Why does having this allow it to undeploy? + // Why don't vehicles move when waypoints are placed off the map? + + const auto old = std::exchange(VocClass::VoicesEnabled, false); + pBuilding->SetArchiveTarget(pCell); + pBuilding->Sell(true); + VocClass::VoicesEnabled = old; + } + + return true; +} + bool TActionExt::EditAngerNode(TActionClass* pThis, HouseClass* pHouse, ObjectClass* pObject, TriggerClass* pTrigger, CellStruct const& location) { if (pHouse->AngerNodes.Count <= 0) @@ -519,6 +610,38 @@ bool TActionExt::SetForceEnemy(TActionClass* pThis, HouseClass* pHouse, ObjectCl return true; } +bool TActionExt::SetFreeRadar(TActionClass* const pThis, HouseClass* const pHouse, ObjectClass* const pObject, TriggerClass* const pTrigger, const CellStruct& location) +{ + if (pHouse->IsControlledByHuman() && + (!SessionClass::Instance.IsCampaign() || pHouse == HouseClass::CurrentPlayer)) + { + HouseExt::ExtMap.Find(pHouse)->FreeRadar = pThis->Param3 != 0; + pHouse->RecheckRadar = true; + } + + return true; +} + +bool TActionExt::SetTeamDelay(TActionClass* const pThis, HouseClass* const pHouse, ObjectClass* const pObject, TriggerClass* const pTrigger, const CellStruct& location) +{ + const int timer = Math::max(pThis->Param3, 0); + HouseExt::ExtMap.Find(pHouse)->TeamDelay = timer; + + auto& Timer = pHouse->TeamDelayTimer; + const int time = Math::min(Timer.TimeLeft, timer); + + if (Timer.StartTime == -1 && Timer.TimeLeft != 0 && time > 0) + { + Timer.TimeLeft = time; + } + else if (Timer.InProgress() || time >= 0) + { + Timer.Start(time); + } + + return true; +} + static void CreateOrReplaceBanner(TActionClass* pTAction, bool isGlobal) { const auto pBannerType = BannerTypeClass::Find(pTAction->Text); diff --git a/src/Ext/TAction/Body.h b/src/Ext/TAction/Body.h index 72bf78126f..e7ddc5ba58 100644 --- a/src/Ext/TAction/Body.h +++ b/src/Ext/TAction/Body.h @@ -19,10 +19,13 @@ enum class PhobosTriggerAction : unsigned int RunSuperWeaponAtLocation = 505, RunSuperWeaponAtWaypoint = 506, ToggleMCVRedeploy = 510, + UndeployToWaypoint = 511, EditAngerNode = 606, ClearAngerNode = 607, SetForceEnemy = 608, + SetFreeRadar = 609, + SetTeamDelay = 610, CreateBannerLocal = 800, // any banner w/ local variable CreateBannerGlobal = 801, // any banner w/ global variable @@ -71,10 +74,13 @@ class TActionExt ACTION_FUNC(RunSuperWeaponAtLocation); ACTION_FUNC(RunSuperWeaponAtWaypoint); ACTION_FUNC(ToggleMCVRedeploy); + ACTION_FUNC(UndeployToWaypoint); ACTION_FUNC(EditAngerNode); ACTION_FUNC(ClearAngerNode); ACTION_FUNC(SetForceEnemy); + ACTION_FUNC(SetFreeRadar); + ACTION_FUNC(SetTeamDelay); ACTION_FUNC(CreateBannerLocal); ACTION_FUNC(CreateBannerGlobal); From baae3dc16ba9831bea884560bf120460a0834fd8 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Thu, 11 Dec 2025 11:27:12 +0800 Subject: [PATCH 02/20] ok --- src/Ext/House/Body.h | 2 +- src/Ext/Scenario/Body.cpp | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Ext/House/Body.h b/src/Ext/House/Body.h index 5404662e7b..b963fd031a 100644 --- a/src/Ext/House/Body.h +++ b/src/Ext/House/Body.h @@ -98,7 +98,7 @@ class HouseExt , SuperExts(SuperWeaponTypeClass::Array.Count) , ForceEnemyIndex(-1) , TeamDelay(-1) - , FreeRadar(ScenarioClass::Instance->FreeRadar) + , FreeRadar(false) { } bool OwnsLimboDeliveredBuilding(BuildingClass* pBuilding) const; diff --git a/src/Ext/Scenario/Body.cpp b/src/Ext/Scenario/Body.cpp index a2135dfa35..3236b582d4 100644 --- a/src/Ext/Scenario/Body.cpp +++ b/src/Ext/Scenario/Body.cpp @@ -3,6 +3,8 @@ #include #include +#include + std::unique_ptr ScenarioExt::Data = nullptr; bool ScenarioExt::CellParsed = false; @@ -90,6 +92,11 @@ void ScenarioExt::Remove(ScenarioClass* pThis) void ScenarioExt::LoadFromINIFile(ScenarioClass* pThis, CCINIClass* pINI) { Data->LoadFromINI(pINI); + + for (auto const pHouse : HouseClass::Array) + { + HouseExt::ExtMap.Find(pHouse)->FreeRadar = ScenarioClass::Instance->FreeRadar; + } } void ScenarioExt::ExtData::UpdateAutoDeathObjectsInLimbo() From 2a778efc52e0a11a68aeb97996f46632d9adcc95 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Thu, 11 Dec 2025 11:38:55 +0800 Subject: [PATCH 03/20] ok --- src/Ext/TAction/Body.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ext/TAction/Body.cpp b/src/Ext/TAction/Body.cpp index 3547e619f3..e7910ad8db 100644 --- a/src/Ext/TAction/Body.cpp +++ b/src/Ext/TAction/Body.cpp @@ -392,7 +392,7 @@ bool TActionExt::ToggleMCVRedeploy(TActionClass* pThis, HouseClass* pHouse, Obje bool TActionExt::UndeployToWaypoint(TActionClass* const pThis, HouseClass* const pHouse, ObjectClass* const pObject, TriggerClass* const pTrigger, const CellStruct& location) { - const auto& nCell = ScenarioExt::Global()->Waypoints[pThis->Param4]; + const auto& nCell = ScenarioExt::Global()->Waypoints[pThis->Waypoint]; CellClass* const pCell = MapClass::Instance.TryGetCellAt(nCell); if (!pCell) @@ -415,7 +415,7 @@ bool TActionExt::UndeployToWaypoint(TActionClass* const pThis, HouseClass* const if (!allHouse && !vHouse) return true; - const char* buildingName = pThis->Text; + const char* buildingName = pThis->TechnoID; bool allBuilding = false; BuildingTypeClass* pBuildingType = nullptr; From 536cee5fc79684ad652b23ff8d8556d87dbd9f36 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Thu, 11 Dec 2025 11:50:18 +0800 Subject: [PATCH 04/20] update doc --- CREDITS.md | 1 + docs/Whats-New.md | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CREDITS.md b/CREDITS.md index 6a2035cd83..5b76a6e433 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -400,6 +400,7 @@ This page lists all the individual contributions to the project by their author. - Fast access structure - Iron Curtain/Custom Tint Support for SHP Turreted Vehicles - Reactivate unused trigger events 2, 53, and 54 + - Map Action 511,609,610 - **NetsuNegi**: - Forbidding parallel AI queues by type - Jumpjet crash speed fix when crashing onto building diff --git a/docs/Whats-New.md b/docs/Whats-New.md index f550b9df7d..203219b908 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -193,9 +193,12 @@ HideShakeEffects=false ; boolean 505=Fire Super Weapon at specified location (Phobos),0,0,20,2,21,22,0,0,0,Launch a Super Weapon from [SuperWeaponTypes] list at a specified location. House=-1 means random target that isn't neutral. House=-2 means the first neutral house. House=-3 means random human target. Coordinate X=-1 means random. Coordinate Y=-1 means random,0,1,505 506=Fire Super Weapon at specified waypoint (Phobos),0,0,20,2,30,0,0,0,0,Launch a Super Weapon from [SuperWeaponTypes] list at a specified waypoint. House=-1 means random target that isn't neutral. House=-2 means the first neutral house. House=-3 means random human target. Coordinate X=-1 means random. Coordinate Y=-1 means random,0,1,506 510=Toggle MCV Redeployablility (Phobos),0,0,15,0,0,0,0,0,0, Set MCVRedeploys to the given value,0,1,510 + 511=Building Type undeploy at...,-10,47,2,0,0,0,1,0,0,Recycle the building type into a vehicle and move it to the specified waypoint. If the type is "", recycle all buildings.,0,1,511 606=Edit hate-value (Phobos),0,2,55,6,0,0,0,0,0, Edit the hate-value that trigger houses to other houses. -1 works for all houses.,0,1,606 607=Clear hate-value (Phobos),0,2,0,0,0,0,0,0,0, Clear the hate-value that trigger houses to other houses. -1 works for all houses.,0,1,607 608=Set force enemy (Phobos),0,0,2,0,0,0,0,0,0, Force an enemy, it will not change with the change of hate-value. -1 will remove the forced enemy, -2 will never have any enemies.,0,1,608 + 609=Set free radar (Phobos),0,0,15,0,0,0,0,0,0, Trigger's house can enable/disable the free radar.,0,1,609 + 610=Set team delay (Phobos),0,0,2,0,0,0,0,0,0, Trigger's house can customize TeamDelay.,0,1,610 800=Display banner and local variable (Phobos),-4,101,104,102,103,3,0,0,0,Draw banner on screen and replace banner with same ID,0,1,800 801=Display banner and global variable (Phobos),-4,101,104,102,103,35,0,0,0,Draw banner on screen and replace banner with same ID,0,1,801 802=Delete banner (Phobos),0,104,0,0,0,0,0,0,0,Delete banner with ID,0,1,802 @@ -466,6 +469,7 @@ New: - [Customize type selection for IFV](Fixed-or-Improved-Logics.md#customize-type-selection-for-ifv) (by NetsuNegi) - CellSpread in cylinder shape (by TaranDahl) - CellSpread damage check if victim is in air or on floor (by TaranDahl) +- Map Action 511,609,610 (by FlyStar) Vanilla fixes: - Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya) From 657f53307fa230f2f80c957934a00a86a3fa257b Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Thu, 11 Dec 2025 11:53:22 +0800 Subject: [PATCH 05/20] Update Whats-New.md --- docs/Whats-New.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 203219b908..bd6392db21 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -198,7 +198,7 @@ HideShakeEffects=false ; boolean 607=Clear hate-value (Phobos),0,2,0,0,0,0,0,0,0, Clear the hate-value that trigger houses to other houses. -1 works for all houses.,0,1,607 608=Set force enemy (Phobos),0,0,2,0,0,0,0,0,0, Force an enemy, it will not change with the change of hate-value. -1 will remove the forced enemy, -2 will never have any enemies.,0,1,608 609=Set free radar (Phobos),0,0,15,0,0,0,0,0,0, Trigger's house can enable/disable the free radar.,0,1,609 - 610=Set team delay (Phobos),0,0,2,0,0,0,0,0,0, Trigger's house can customize TeamDelay.,0,1,610 + 610=Set team delay (Phobos),0,0,6,0,0,0,0,0,0, Trigger's house can customize TeamDelay.,0,1,610 800=Display banner and local variable (Phobos),-4,101,104,102,103,3,0,0,0,Draw banner on screen and replace banner with same ID,0,1,800 801=Display banner and global variable (Phobos),-4,101,104,102,103,35,0,0,0,Draw banner on screen and replace banner with same ID,0,1,801 802=Delete banner (Phobos),0,104,0,0,0,0,0,0,0,Delete banner with ID,0,1,802 From 5855185bb0fcfef1ec073cfe6abf29fdcdd94775 Mon Sep 17 00:00:00 2001 From: Noble Fish <89088785+DeathFishAtEase@users.noreply.github.com> Date: Thu, 11 Dec 2025 18:33:50 +0800 Subject: [PATCH 06/20] Complete Phobos action marks --- docs/Whats-New.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/Whats-New.md b/docs/Whats-New.md index bd6392db21..62cba6d610 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -185,15 +185,15 @@ HideShakeEffects=false ; boolean [ActionsRA2] 41=Play animation at a waypoint...,0,25,69,0,0,0,1,0,0,[LONG DESC].,0,1,41 125=Build at...,-10,47,0,65,0,0,1,0,0,[LONG DESC],0,1,125 - 500=Save game,-4,13,0,0,0,0,0,0,0,[LONG DESC],0,1,500,1 - 501=Edit variable,0,56,55,6,54,0,0,0,0,[LONG DESC],0,1,501,1 - 502=Generate random number,0,56,57,58,54,0,0,0,0,[LONG DESC],0,1,502,1 - 503=Print variable value,0,56,54,0,0,0,0,0,0,[LONG DESC],0,1,503,0 - 504=Binary operation,0,56,55,60,54,59,0,0,0,[LONG DESC],0,1,504,1 + 500=Save game (Phobos),-4,13,0,0,0,0,0,0,0,[LONG DESC],0,1,500,1 + 501=Edit variable (Phobos),0,56,55,6,54,0,0,0,0,[LONG DESC],0,1,501,1 + 502=Generate random number (Phobos),0,56,57,58,54,0,0,0,0,[LONG DESC],0,1,502,1 + 503=Print variable value (Phobos),0,56,54,0,0,0,0,0,0,[LONG DESC],0,1,503,0 + 504=Binary operation (Phobos),0,56,55,60,54,59,0,0,0,[LONG DESC],0,1,504,1 505=Fire Super Weapon at specified location (Phobos),0,0,20,2,21,22,0,0,0,Launch a Super Weapon from [SuperWeaponTypes] list at a specified location. House=-1 means random target that isn't neutral. House=-2 means the first neutral house. House=-3 means random human target. Coordinate X=-1 means random. Coordinate Y=-1 means random,0,1,505 506=Fire Super Weapon at specified waypoint (Phobos),0,0,20,2,30,0,0,0,0,Launch a Super Weapon from [SuperWeaponTypes] list at a specified waypoint. House=-1 means random target that isn't neutral. House=-2 means the first neutral house. House=-3 means random human target. Coordinate X=-1 means random. Coordinate Y=-1 means random,0,1,506 510=Toggle MCV Redeployablility (Phobos),0,0,15,0,0,0,0,0,0, Set MCVRedeploys to the given value,0,1,510 - 511=Building Type undeploy at...,-10,47,2,0,0,0,1,0,0,Recycle the building type into a vehicle and move it to the specified waypoint. If the type is "", recycle all buildings.,0,1,511 + 511=Building Type undeploy at... (Phobos),-10,47,2,0,0,0,1,0,0,Recycle the building type into a vehicle and move it to the specified waypoint. If the type is "", recycle all buildings.,0,1,511 606=Edit hate-value (Phobos),0,2,55,6,0,0,0,0,0, Edit the hate-value that trigger houses to other houses. -1 works for all houses.,0,1,606 607=Clear hate-value (Phobos),0,2,0,0,0,0,0,0,0, Clear the hate-value that trigger houses to other houses. -1 works for all houses.,0,1,607 608=Set force enemy (Phobos),0,0,2,0,0,0,0,0,0, Force an enemy, it will not change with the change of hate-value. -1 will remove the forced enemy, -2 will never have any enemies.,0,1,608 From 2ecfd310ffd9d69c68ee0026fd9bb655d526954d Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Sun, 14 Dec 2025 11:22:41 +0800 Subject: [PATCH 07/20] update again --- docs/Whats-New.md | 10 +++++----- src/Ext/House/Body.cpp | 1 + src/Ext/House/Body.h | 2 ++ src/Ext/House/Hooks.cpp | 24 +++++++++++++++++++--- src/Ext/TAction/Body.cpp | 43 +++++++++++++++++++++++++++------------- 5 files changed, 58 insertions(+), 22 deletions(-) diff --git a/docs/Whats-New.md b/docs/Whats-New.md index e7fc5c71dd..a315618028 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -194,11 +194,11 @@ HideShakeEffects=false ; boolean 506=Fire Super Weapon at specified waypoint (Phobos),0,0,20,2,30,0,0,0,0,Launch a Super Weapon from [SuperWeaponTypes] list at a specified waypoint. House=-1 means random target that isn't neutral. House=-2 means the first neutral house. House=-3 means random human target. Coordinate X=-1 means random. Coordinate Y=-1 means random,0,1,506 510=Toggle MCV Redeployablility (Phobos),0,0,15,0,0,0,0,0,0, Set MCVRedeploys to the given value,0,1,510 511=Building Type undeploy at... (Phobos),-10,47,2,0,0,0,1,0,0,Recycle the building type into a vehicle and move it to the specified waypoint. If the type is "", recycle all buildings.,0,1,511 - 606=Edit hate-value (Phobos),0,2,55,6,0,0,0,0,0, Edit the hate-value that trigger houses to other houses. -1 works for all houses.,0,1,606 - 607=Clear hate-value (Phobos),0,2,0,0,0,0,0,0,0, Clear the hate-value that trigger houses to other houses. -1 works for all houses.,0,1,607 - 608=Set force enemy (Phobos),0,0,2,0,0,0,0,0,0, Force an enemy, it will not change with the change of hate-value. -1 will remove the forced enemy, -2 will never have any enemies.,0,1,608 - 609=Set free radar (Phobos),0,0,15,0,0,0,0,0,0, Trigger's house can enable/disable the free radar.,0,1,609 - 610=Set team delay (Phobos),0,0,6,0,0,0,0,0,0, Trigger's house can customize TeamDelay.,0,1,610 + 606=Edit hate-value... (Phobos),0,2,55,6,0,0,0,0,0, Edit the hate-value that trigger houses to other houses. -1 works for all houses.,0,1,606 + 607=Clear hate-value... (Phobos),0,2,0,0,0,0,0,0,0, Clear the hate-value that trigger houses to other houses. -1 works for all houses.,0,1,607 + 608=Set force enemy... (Phobos),0,0,2,0,0,0,0,0,0, Force an enemy, it will not change with the change of hate-value. -1 will remove the forced enemy, -2 will never have any enemies.,0,1,608 + 609=Set free radar... (Phobos),0,0,15,0,0,0,0,0,0, Trigger's house can enable/disable the free radar. 0 for requires full-power and building, 1 for free radar, -1 for forced enable, -2 for forced disable.,0,1,609 + 610=Set team delay... (Phobos),0,0,6,0,0,0,0,0,0, Trigger's house can customize TeamDelay. When the value is less than 0 in [General]>TeamDelays.,0,1,610 800=Display banner and local variable (Phobos),-4,101,104,102,103,3,0,0,0,Draw banner on screen and replace banner with same ID,0,1,800 801=Display banner and global variable (Phobos),-4,101,104,102,103,35,0,0,0,Draw banner on screen and replace banner with same ID,0,1,801 802=Delete banner (Phobos),0,104,0,0,0,0,0,0,0,Delete banner with ID,0,1,802 diff --git a/src/Ext/House/Body.cpp b/src/Ext/House/Body.cpp index 64fd484b81..b12bb711c0 100644 --- a/src/Ext/House/Body.cpp +++ b/src/Ext/House/Body.cpp @@ -655,6 +655,7 @@ void HouseExt::ExtData::Serialize(T& Stm) .Process(this->ForceEnemyIndex) .Process(this->TeamDelay) .Process(this->FreeRadar) + .Process(this->ForceRadar) ; } diff --git a/src/Ext/House/Body.h b/src/Ext/House/Body.h index b963fd031a..262833fcc4 100644 --- a/src/Ext/House/Body.h +++ b/src/Ext/House/Body.h @@ -68,6 +68,7 @@ class HouseExt int ForceEnemyIndex; int TeamDelay; bool FreeRadar; + bool ForceRadar; ExtData(HouseClass* OwnerObject) : Extension(OwnerObject) , PowerPlantEnhancers {} @@ -99,6 +100,7 @@ class HouseExt , ForceEnemyIndex(-1) , TeamDelay(-1) , FreeRadar(false) + , ForceRadar(false) { } bool OwnsLimboDeliveredBuilding(BuildingClass* pBuilding) const; diff --git a/src/Ext/House/Hooks.cpp b/src/Ext/House/Hooks.cpp index 128563c707..3179ef1070 100644 --- a/src/Ext/House/Hooks.cpp +++ b/src/Ext/House/Hooks.cpp @@ -475,11 +475,29 @@ DEFINE_HOOK(0x4F8ACC, HouseClass_Update_ResetTeamDelay, 0x6) return 0; } -DEFINE_HOOK(0x508E37, HouseClass_UpdateRadar_FreeRadar, 0x6) +DEFINE_HOOK(0x508E17, HouseClass_UpdateRadar_FreeRadar, 0x8) { - enum { FreeRadar = 0x508F2A, Continue = 0x508E4A }; + enum { ForceRadar = 0x508F2F, Continue = 0x508E4A }; GET(HouseClass*, pThis, ECX); - return HouseExt::ExtMap.Find(pThis)->FreeRadar ? FreeRadar : Continue; + auto const pExt = HouseExt::ExtMap.Find(pThis); + + if (pExt->ForceRadar) + { + R->Stack(STACK_OFFSET(0x1C, -0xC), pExt->FreeRadar); + return ForceRadar; + } + else if (pThis->PowerBlackoutTimer.InProgress()) + { + R->Stack(STACK_OFFSET(0x1C, -0xC), false); + return ForceRadar; + } + else if (pExt->FreeRadar) + { + R->Stack(STACK_OFFSET(0x1C, -0xC), true); + return ForceRadar; + } + + return Continue; } diff --git a/src/Ext/TAction/Body.cpp b/src/Ext/TAction/Body.cpp index e7910ad8db..80fbd5e57c 100644 --- a/src/Ext/TAction/Body.cpp +++ b/src/Ext/TAction/Body.cpp @@ -398,7 +398,6 @@ bool TActionExt::UndeployToWaypoint(TActionClass* const pThis, HouseClass* const if (!pCell) return true; - bool allHouse = false; HouseClass* vHouse = nullptr; const int houseIndex = pThis->Param3; @@ -407,12 +406,8 @@ bool TActionExt::UndeployToWaypoint(TActionClass* const pThis, HouseClass* const vHouse = HouseClass::Index_IsMP(houseIndex) ? HouseClass::FindByIndex(houseIndex) : HouseClass::FindByCountryIndex(houseIndex); } - else if (houseIndex == -1) - { - allHouse = true; - } - if (!allHouse && !vHouse) + if (!vHouse) return true; const char* buildingName = pThis->TechnoID; @@ -433,14 +428,14 @@ bool TActionExt::UndeployToWaypoint(TActionClass* const pThis, HouseClass* const // Thanks to chaserli for the relevant code! // There should be a more perfect way to do this, but I don't know how. - auto canUndeploy = [pThis, pTrigger, allBuilding, allHouse, pBuildingType, vHouse](BuildingClass* pBuilding) + auto canUndeploy = [pThis, pTrigger, allBuilding, pBuildingType, vHouse](BuildingClass* pBuilding) { auto const pType = pBuilding->Type; - if (!pType->UndeploysInto || - (!allBuilding && pType != pBuildingType) || - (!allHouse && pBuilding->Owner != vHouse) || - !pBuilding->IsAlive || pBuilding->Health <= 0 || pBuilding->InLimbo) + if (!pType->UndeploysInto + || (pBuilding->Owner != vHouse) + || (!allBuilding && pType != pBuildingType) + || !pBuilding->IsAlive || pBuilding->Health <= 0 || pBuilding->InLimbo) { return false; } @@ -612,10 +607,30 @@ bool TActionExt::SetForceEnemy(TActionClass* pThis, HouseClass* pHouse, ObjectCl bool TActionExt::SetFreeRadar(TActionClass* const pThis, HouseClass* const pHouse, ObjectClass* const pObject, TriggerClass* const pTrigger, const CellStruct& location) { - if (pHouse->IsControlledByHuman() && - (!SessionClass::Instance.IsCampaign() || pHouse == HouseClass::CurrentPlayer)) + if (pHouse->IsControlledByHuman()) { - HouseExt::ExtMap.Find(pHouse)->FreeRadar = pThis->Param3 != 0; + auto const pHouseExt = HouseExt::ExtMap.Find(pHouse); + + switch (pThis->Param3) + { + case 1: + pHouseExt->FreeRadar = true; + pHouseExt->ForceRadar = false; + break; + case -1: + pHouseExt->FreeRadar = true; + pHouseExt->ForceRadar = true; + break; + case -2: + pHouseExt->FreeRadar = false; + pHouseExt->ForceRadar = true; + break; + default: + pHouseExt->FreeRadar = false; + pHouseExt->ForceRadar = false; + break; + } + pHouse->RecheckRadar = true; } From afeec251f2bd2e60f6ddd6cd83146c932f97e352 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Sun, 14 Dec 2025 11:28:13 +0800 Subject: [PATCH 08/20] Update Body.cpp --- src/Ext/TAction/Body.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Ext/TAction/Body.cpp b/src/Ext/TAction/Body.cpp index 80fbd5e57c..39ea8e42a7 100644 --- a/src/Ext/TAction/Body.cpp +++ b/src/Ext/TAction/Body.cpp @@ -403,8 +403,8 @@ bool TActionExt::UndeployToWaypoint(TActionClass* const pThis, HouseClass* const if (houseIndex >= 0) { - vHouse = HouseClass::Index_IsMP(houseIndex) ? - HouseClass::FindByIndex(houseIndex) : HouseClass::FindByCountryIndex(houseIndex); + vHouse = HouseClass::Index_IsMP(houseIndex) + ? HouseClass::FindByIndex(houseIndex) : HouseClass::FindByCountryIndex(houseIndex); } if (!vHouse) @@ -639,17 +639,17 @@ bool TActionExt::SetFreeRadar(TActionClass* const pThis, HouseClass* const pHous bool TActionExt::SetTeamDelay(TActionClass* const pThis, HouseClass* const pHouse, ObjectClass* const pObject, TriggerClass* const pTrigger, const CellStruct& location) { - const int timer = Math::max(pThis->Param3, 0); + const int timer = std::max(pThis->Param3, 0); HouseExt::ExtMap.Find(pHouse)->TeamDelay = timer; auto& Timer = pHouse->TeamDelayTimer; - const int time = Math::min(Timer.TimeLeft, timer); + const int time = std::min(Timer.GetTimeLeft(), timer); if (Timer.StartTime == -1 && Timer.TimeLeft != 0 && time > 0) { Timer.TimeLeft = time; } - else if (Timer.InProgress() || time >= 0) + else if (Timer.InProgress()) { Timer.Start(time); } From 4bc64322f8cf09adb38dc717f2cb238ccdee4795 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Sun, 14 Dec 2025 11:29:53 +0800 Subject: [PATCH 09/20] Update Whats-New.md --- docs/Whats-New.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Whats-New.md b/docs/Whats-New.md index a315618028..2628e76df7 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -197,7 +197,7 @@ HideShakeEffects=false ; boolean 606=Edit hate-value... (Phobos),0,2,55,6,0,0,0,0,0, Edit the hate-value that trigger houses to other houses. -1 works for all houses.,0,1,606 607=Clear hate-value... (Phobos),0,2,0,0,0,0,0,0,0, Clear the hate-value that trigger houses to other houses. -1 works for all houses.,0,1,607 608=Set force enemy... (Phobos),0,0,2,0,0,0,0,0,0, Force an enemy, it will not change with the change of hate-value. -1 will remove the forced enemy, -2 will never have any enemies.,0,1,608 - 609=Set free radar... (Phobos),0,0,15,0,0,0,0,0,0, Trigger's house can enable/disable the free radar. 0 for requires full-power and building, 1 for free radar, -1 for forced enable, -2 for forced disable.,0,1,609 + 609=Set radar mode... (Phobos),0,0,15,0,0,0,0,0,0, Trigger's house can modify the current radar mode. 0 for requires full-power and building, 1 for free radar, -1 for forced enable, -2 for forced disable.,0,1,609 610=Set team delay... (Phobos),0,0,6,0,0,0,0,0,0, Trigger's house can customize TeamDelay. When the value is less than 0 in [General]>TeamDelays.,0,1,610 800=Display banner and local variable (Phobos),-4,101,104,102,103,3,0,0,0,Draw banner on screen and replace banner with same ID,0,1,800 801=Display banner and global variable (Phobos),-4,101,104,102,103,35,0,0,0,Draw banner on screen and replace banner with same ID,0,1,801 From 6fc50473b23ce4316a9f537f581c5f60017ec0a5 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Sun, 14 Dec 2025 11:40:57 +0800 Subject: [PATCH 10/20] It seems unnecessary to use negative numbers --- docs/Whats-New.md | 2 +- src/Ext/TAction/Body.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 2628e76df7..01f4665f94 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -197,7 +197,7 @@ HideShakeEffects=false ; boolean 606=Edit hate-value... (Phobos),0,2,55,6,0,0,0,0,0, Edit the hate-value that trigger houses to other houses. -1 works for all houses.,0,1,606 607=Clear hate-value... (Phobos),0,2,0,0,0,0,0,0,0, Clear the hate-value that trigger houses to other houses. -1 works for all houses.,0,1,607 608=Set force enemy... (Phobos),0,0,2,0,0,0,0,0,0, Force an enemy, it will not change with the change of hate-value. -1 will remove the forced enemy, -2 will never have any enemies.,0,1,608 - 609=Set radar mode... (Phobos),0,0,15,0,0,0,0,0,0, Trigger's house can modify the current radar mode. 0 for requires full-power and building, 1 for free radar, -1 for forced enable, -2 for forced disable.,0,1,609 + 609=Set radar mode... (Phobos),0,0,15,0,0,0,0,0,0, Trigger's house can modify the current radar mode. 0 for requires full-power and building, 1 for free radar, 2 for forced enable, 3 for forced disable.,0,1,609 610=Set team delay... (Phobos),0,0,6,0,0,0,0,0,0, Trigger's house can customize TeamDelay. When the value is less than 0 in [General]>TeamDelays.,0,1,610 800=Display banner and local variable (Phobos),-4,101,104,102,103,3,0,0,0,Draw banner on screen and replace banner with same ID,0,1,800 801=Display banner and global variable (Phobos),-4,101,104,102,103,35,0,0,0,Draw banner on screen and replace banner with same ID,0,1,801 diff --git a/src/Ext/TAction/Body.cpp b/src/Ext/TAction/Body.cpp index 39ea8e42a7..6a85f8d639 100644 --- a/src/Ext/TAction/Body.cpp +++ b/src/Ext/TAction/Body.cpp @@ -617,11 +617,11 @@ bool TActionExt::SetFreeRadar(TActionClass* const pThis, HouseClass* const pHous pHouseExt->FreeRadar = true; pHouseExt->ForceRadar = false; break; - case -1: + case 2: pHouseExt->FreeRadar = true; pHouseExt->ForceRadar = true; break; - case -2: + case 3: pHouseExt->FreeRadar = false; pHouseExt->ForceRadar = true; break; From 96d638d7014aeca39bc4c30997a792c25093a7fa Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Tue, 23 Dec 2025 13:26:37 +0800 Subject: [PATCH 11/20] update doc --- docs/AI-Scripting-and-Mapping.md | 42 ++++++++++++++++++++++++++++++++ docs/Whats-New.md | 4 +-- src/Ext/House/Body.cpp | 28 ++++++++++----------- src/Ext/House/Body.h | 2 +- 4 files changed, 59 insertions(+), 17 deletions(-) diff --git a/docs/AI-Scripting-and-Mapping.md b/docs/AI-Scripting-and-Mapping.md index c1ac78ce80..8bc5021d44 100644 --- a/docs/AI-Scripting-and-Mapping.md +++ b/docs/AI-Scripting-and-Mapping.md @@ -652,6 +652,19 @@ ID=ActionCount,[Action1],510,0,0,[MCVRedeploy],0,0,0,A,[ActionX] ... ``` +### `511` Building Type undeploy at + +- Recycle the building type into a vehicle and move it to the specified waypoint. + - If the type is ``, recycle all buildings. + +In `mycampaign.map`: +```ini +[Actions] +... +ID=ActionCount,[Action1],511,-10,[BuildingTypesID],[HouseIndex],0,0,0,[WaypointIndex],[ActionX] +... +``` + ### `606` Edit Hate-Value - Edit the hate-value that trigger houses to other houses. @@ -707,6 +720,35 @@ ID=ActionCount,[Action1],608,0,0,[HouseIndex],0,0,0,A,[ActionX] ... ``` +### `609` Set radar mode + +- Trigger's house can modify the current radar mode. + - 0 for requires full-power and building. + - 1 for free radar. + - 2 for forced enable. + - 3 for forced disable. + +In `mycampaign.map`: +```ini +[Actions] +... +ID=ActionCount,[Action1],609,0,0,[RadarMode],0,0,0,A,[ActionX] +... +``` + +### `610` Set team delay + +- Trigger's house can customize TeamDelay. + - When the value is less than 0 in `[General]>TeamDelays`. + +In `mycampaign.map`: +```ini +[Actions] +... +ID=ActionCount,[Action1],610,0,0,[Number],0,0,0,A,[ActionX] +... +``` + ### `800-802` Display Banner - Display a 'banner' at a fixed location that is relative to the screen. diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 17fc02ed8a..5ab11ffb0a 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -193,12 +193,12 @@ HideShakeEffects=false ; boolean 505=Fire Super Weapon at specified location (Phobos),0,0,20,2,21,22,0,0,0,Launch a Super Weapon from [SuperWeaponTypes] list at a specified location. House=-1 means random target that isn't neutral. House=-2 means the first neutral house. House=-3 means random human target. Coordinate X=-1 means random. Coordinate Y=-1 means random,0,1,505 506=Fire Super Weapon at specified waypoint (Phobos),0,0,20,2,30,0,0,0,0,Launch a Super Weapon from [SuperWeaponTypes] list at a specified waypoint. House=-1 means random target that isn't neutral. House=-2 means the first neutral house. House=-3 means random human target. Coordinate X=-1 means random. Coordinate Y=-1 means random,0,1,506 510=Toggle MCV Redeployablility (Phobos),0,0,15,0,0,0,0,0,0, Set MCVRedeploys to the given value,0,1,510 - 511=Building Type undeploy at... (Phobos),-10,47,2,0,0,0,1,0,0,Recycle the building type into a vehicle and move it to the specified waypoint. If the type is "", recycle all buildings.,0,1,511 + 511=Building Type undeploy at... (Phobos),-10,47,2,0,0,0,1,0,0,Recycle the building type into a vehicle and move it to the specified waypoint. If the type is ``, recycle all buildings.,0,1,511 606=Edit hate-value... (Phobos),0,2,55,6,0,0,0,0,0, Edit the hate-value that trigger houses to other houses. -1 works for all houses.,0,1,606 607=Clear hate-value... (Phobos),0,2,0,0,0,0,0,0,0, Clear the hate-value that trigger houses to other houses. -1 works for all houses.,0,1,607 608=Set force enemy... (Phobos),0,0,2,0,0,0,0,0,0, Force an enemy, it will not change with the change of hate-value. -1 will remove the forced enemy, -2 will never have any enemies.,0,1,608 609=Set radar mode... (Phobos),0,0,15,0,0,0,0,0,0, Trigger's house can modify the current radar mode. 0 for requires full-power and building, 1 for free radar, 2 for forced enable, 3 for forced disable.,0,1,609 - 610=Set team delay... (Phobos),0,0,6,0,0,0,0,0,0, Trigger's house can customize TeamDelay. When the value is less than 0 in [General]>TeamDelays.,0,1,610 + 610=Set team delay... (Phobos),0,0,6,0,0,0,0,0,0, Trigger's house can customize TeamDelay. When the value is less than 0 in `[General]>TeamDelays`.,0,1,610 800=Display banner and local variable (Phobos),-4,101,104,102,103,3,0,0,0,Draw banner on screen and replace banner with same ID,0,1,800 801=Display banner and global variable (Phobos),-4,101,104,102,103,35,0,0,0,Draw banner on screen and replace banner with same ID,0,1,801 802=Delete banner (Phobos),0,104,0,0,0,0,0,0,0,Delete banner with ID,0,1,802 diff --git a/src/Ext/House/Body.cpp b/src/Ext/House/Body.cpp index f72d8bb3ca..ab90724240 100644 --- a/src/Ext/House/Body.cpp +++ b/src/Ext/House/Body.cpp @@ -590,26 +590,26 @@ void HouseExt::ForceOnlyTargetHouseEnemy(HouseClass* pThis, int mode) if (mode < 0 || mode > 2) mode = -1; - enum { ForceFalse = 0, ForceTrue = 1, ForceRandom = 2}; + enum { ForceFalse = 0, ForceTrue = 1, ForceRandom = 2 }; pHouseExt->ForceOnlyTargetHouseEnemyMode = mode; switch (mode) { - case ForceFalse: - pHouseExt->ForceOnlyTargetHouseEnemy = false; - break; + case ForceFalse: + pHouseExt->ForceOnlyTargetHouseEnemy = false; + break; - case ForceTrue: - pHouseExt->ForceOnlyTargetHouseEnemy = true; - break; + case ForceTrue: + pHouseExt->ForceOnlyTargetHouseEnemy = true; + break; - case ForceRandom: - pHouseExt->ForceOnlyTargetHouseEnemy = (bool)ScenarioClass::Instance->Random.RandomRanged(0, 1);; - break; + case ForceRandom: + pHouseExt->ForceOnlyTargetHouseEnemy = (bool)ScenarioClass::Instance->Random.RandomRanged(0, 1);; + break; - default: - pHouseExt->ForceOnlyTargetHouseEnemy = false; - break; + default: + pHouseExt->ForceOnlyTargetHouseEnemy = false; + break; } } @@ -685,7 +685,7 @@ void HouseExt::ExtData::Serialize(T& Stm) .Process(this->ForceEnemyIndex) .Process(this->ForceOnlyTargetHouseEnemy) .Process(this->ForceOnlyTargetHouseEnemyMode) - .Process(this->TeamDelay) + .Process(this->TeamDelay) .Process(this->FreeRadar) .Process(this->ForceRadar) ; diff --git a/src/Ext/House/Body.h b/src/Ext/House/Body.h index 73c13fddcb..8d1e60518c 100644 --- a/src/Ext/House/Body.h +++ b/src/Ext/House/Body.h @@ -102,7 +102,7 @@ class HouseExt , ForceEnemyIndex(-1) , ForceOnlyTargetHouseEnemy { false } , ForceOnlyTargetHouseEnemyMode { -1 } - , TeamDelay(-1) + , TeamDelay(-1) , FreeRadar(false) , ForceRadar(false) { } From 858d156cb41a3b6411fd3d067737cb642028ff13 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Tue, 23 Dec 2025 13:29:22 +0800 Subject: [PATCH 12/20] mini --- src/Ext/House/Hooks.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Ext/House/Hooks.cpp b/src/Ext/House/Hooks.cpp index f019eab453..0489338586 100644 --- a/src/Ext/House/Hooks.cpp +++ b/src/Ext/House/Hooks.cpp @@ -508,10 +508,11 @@ DEFINE_HOOK(0x508E17, HouseClass_UpdateRadar_FreeRadar, 0x8) GET(HouseClass*, pThis, ECX); auto const pExt = HouseExt::ExtMap.Find(pThis); + const bool freeRadar = pExt->FreeRadar; if (pExt->ForceRadar) { - R->Stack(STACK_OFFSET(0x1C, -0xC), pExt->FreeRadar); + R->Stack(STACK_OFFSET(0x1C, -0xC), freeRadar); return ForceRadar; } else if (pThis->PowerBlackoutTimer.InProgress()) @@ -519,7 +520,7 @@ DEFINE_HOOK(0x508E17, HouseClass_UpdateRadar_FreeRadar, 0x8) R->Stack(STACK_OFFSET(0x1C, -0xC), false); return ForceRadar; } - else if (pExt->FreeRadar) + else if (freeRadar) { R->Stack(STACK_OFFSET(0x1C, -0xC), true); return ForceRadar; From 8021f8844c55bc798b3369022943607cce1d5671 Mon Sep 17 00:00:00 2001 From: Noble Fish <89088785+DeathFishAtEase@users.noreply.github.com> Date: Mon, 29 Dec 2025 16:24:44 +0800 Subject: [PATCH 13/20] Update AI-Scripting-and-Mapping.md --- docs/AI-Scripting-and-Mapping.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/AI-Scripting-and-Mapping.md b/docs/AI-Scripting-and-Mapping.md index 8bc5021d44..c803d590f3 100644 --- a/docs/AI-Scripting-and-Mapping.md +++ b/docs/AI-Scripting-and-Mapping.md @@ -738,8 +738,8 @@ ID=ActionCount,[Action1],609,0,0,[RadarMode],0,0,0,A,[ActionX] ### `610` Set team delay -- Trigger's house can customize TeamDelay. - - When the value is less than 0 in `[General]>TeamDelays`. +- Trigger's house can customize `TeamDelay`. + - When the value is less than 0 in `[General] -> TeamDelays`. In `mycampaign.map`: ```ini From f98b287f07ba2c3b904ec1b0a5b04080b481325a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B9=9D=E5=8D=83=E5=A4=A9=E5=8D=8E?= <1065703286@qq.com> Date: Mon, 29 Dec 2025 16:30:16 +0800 Subject: [PATCH 14/20] Remove unnecessary format changes to simplify the diff view --- src/Ext/House/Body.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Ext/House/Body.cpp b/src/Ext/House/Body.cpp index ab90724240..3adeb78310 100644 --- a/src/Ext/House/Body.cpp +++ b/src/Ext/House/Body.cpp @@ -590,26 +590,26 @@ void HouseExt::ForceOnlyTargetHouseEnemy(HouseClass* pThis, int mode) if (mode < 0 || mode > 2) mode = -1; - enum { ForceFalse = 0, ForceTrue = 1, ForceRandom = 2 }; + enum { ForceFalse = 0, ForceTrue = 1, ForceRandom = 2}; pHouseExt->ForceOnlyTargetHouseEnemyMode = mode; switch (mode) { - case ForceFalse: - pHouseExt->ForceOnlyTargetHouseEnemy = false; - break; + case ForceFalse: + pHouseExt->ForceOnlyTargetHouseEnemy = false; + break; - case ForceTrue: - pHouseExt->ForceOnlyTargetHouseEnemy = true; - break; + case ForceTrue: + pHouseExt->ForceOnlyTargetHouseEnemy = true; + break; - case ForceRandom: - pHouseExt->ForceOnlyTargetHouseEnemy = (bool)ScenarioClass::Instance->Random.RandomRanged(0, 1);; - break; + case ForceRandom: + pHouseExt->ForceOnlyTargetHouseEnemy = (bool)ScenarioClass::Instance->Random.RandomRanged(0, 1);; + break; - default: - pHouseExt->ForceOnlyTargetHouseEnemy = false; - break; + default: + pHouseExt->ForceOnlyTargetHouseEnemy = false; + break; } } From 7b3b1c2b48cf3383784554279bbcf01acb6b16a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B9=9D=E5=8D=83=E5=A4=A9=E5=8D=8E?= <1065703286@qq.com> Date: Mon, 29 Dec 2025 17:38:13 +0800 Subject: [PATCH 15/20] Refactoring PR Documentation --- CREDITS.md | 2 +- docs/AI-Scripting-and-Mapping.md | 29 +++++++++++++++++------------ docs/Whats-New.md | 2 +- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/CREDITS.md b/CREDITS.md index 0fb60e8f35..89f8b1d088 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -401,7 +401,7 @@ This page lists all the individual contributions to the project by their author. - Fast access structure - Iron Curtain/Custom Tint Support for SHP Turreted Vehicles - Reactivate unused trigger events 2, 53, and 54 - - Map Action 511,609,610 + - Map Action 511, 609, 610 - **NetsuNegi**: - Forbidding parallel AI queues by type - Jumpjet crash speed fix when crashing onto building diff --git a/docs/AI-Scripting-and-Mapping.md b/docs/AI-Scripting-and-Mapping.md index c803d590f3..f3418c4c05 100644 --- a/docs/AI-Scripting-and-Mapping.md +++ b/docs/AI-Scripting-and-Mapping.md @@ -652,10 +652,10 @@ ID=ActionCount,[Action1],510,0,0,[MCVRedeploy],0,0,0,A,[ActionX] ... ``` -### `511` Building Type undeploy at +### `511` Undeploy Building to Waypoint -- Recycle the building type into a vehicle and move it to the specified waypoint. - - If the type is ``, recycle all buildings. +- Undeploy specific BuildingTypes into VehicleTypes and move them to a specific Waypoint. + - If `` is entered for the Building Type here, then undeploy all BuildingTypes. In `mycampaign.map`: ```ini @@ -720,13 +720,9 @@ ID=ActionCount,[Action1],608,0,0,[HouseIndex],0,0,0,A,[ActionX] ... ``` -### `609` Set radar mode +### `609` Set Radar Mode -- Trigger's house can modify the current radar mode. - - 0 for requires full-power and building. - - 1 for free radar. - - 2 for forced enable. - - 3 for forced disable. +- Change the current radar mode of the trigger house. In `mycampaign.map`: ```ini @@ -736,10 +732,19 @@ ID=ActionCount,[Action1],609,0,0,[RadarMode],0,0,0,A,[ActionX] ... ``` -### `610` Set team delay +- The possible argument values are: + +| *Argument* | *Description* | +| :--------: | :-----------------------------------------------------------------------: | +| 0 | Normal mode, requires buildings that provide radar and sufficient power | +| 1 | Change to [FreeRadar](https://modenc.renegadeprojects.com/FreeRadar) mode | +| 2 | Force enable radar | +| 3 | Force disable radar | + +### `610` Set house's `TeamDelays` value -- Trigger's house can customize `TeamDelay`. - - When the value is less than 0 in `[General] -> TeamDelays`. +- Set the `TeamDelays` value of the trigger's house. + - If this value is less than 0, then use the value of `[General] -> TeamDelays`. In `mycampaign.map`: ```ini diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 5925fb34a5..2af2fa4acd 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -475,7 +475,7 @@ New: - [Script Action 14004 for forcing all new actions to target only the main owner's enemy](AI-Scripting-and-Mapping.md#force-global-onlytargethouseenemy-value-in-teams-for-new-attack-move-actions-introduced-by-phobos) (by FS-21) - [Allow merging AOE damage to buildings into one](New-or-Enhanced-Logics.md#allow-merging-aoe-damage-to-buildings-into-one) (by CrimRecya) - [Allow customizing whether to synchronously change the owner of the RadioLink-linked units when the owner of a building changes](Fixed-or-Improved-Logics.md#custom-whether-to-synchronously-change-the-owner-of-the-radiolink-linked-units-when-the-owner-of-a-building-changes) (by TaranDahl) -- Map Action 511,609,610 (by FlyStar) +- Map Action [`511` Undeploy Building to Waypoint](AI-Scripting-and-Mapping.md#undeploy-building-to-waypoint), [`609` Set Radar Mode](AI-Scripting-and-Mapping.md#set-radar-mode), [`610` Set house's `TeamDelays` value](AI-Scripting-and-Mapping.md#set-house-s-teamdelays-value) (by FlyStar) Vanilla fixes: - Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya) From 5d0832592f0d0d7fb956e34d89baf2fe923abf91 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Mon, 29 Dec 2025 17:53:26 +0800 Subject: [PATCH 16/20] Add missing information --- src/Ext/TAction/Body.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ext/TAction/Body.cpp b/src/Ext/TAction/Body.cpp index 6a85f8d639..b5e7baaa91 100644 --- a/src/Ext/TAction/Body.cpp +++ b/src/Ext/TAction/Body.cpp @@ -639,7 +639,7 @@ bool TActionExt::SetFreeRadar(TActionClass* const pThis, HouseClass* const pHous bool TActionExt::SetTeamDelay(TActionClass* const pThis, HouseClass* const pHouse, ObjectClass* const pObject, TriggerClass* const pTrigger, const CellStruct& location) { - const int timer = std::max(pThis->Param3, 0); + const int timer = pThis->Param3 < 0 ? RulesClass::Instance->TeamDelays.Items[static_cast(pHouse->AIDifficulty)] : pThis->Param3; HouseExt::ExtMap.Find(pHouse)->TeamDelay = timer; auto& Timer = pHouse->TeamDelayTimer; From 246fded0d276d73fa71ed28225f5f092b1221008 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Mon, 29 Dec 2025 17:56:12 +0800 Subject: [PATCH 17/20] Update Body.cpp --- src/Ext/TAction/Body.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ext/TAction/Body.cpp b/src/Ext/TAction/Body.cpp index b5e7baaa91..dab240c446 100644 --- a/src/Ext/TAction/Body.cpp +++ b/src/Ext/TAction/Body.cpp @@ -461,7 +461,7 @@ bool TActionExt::UndeployToWaypoint(TActionClass* const pThis, HouseClass* const // Why does having this allow it to undeploy? // Why don't vehicles move when waypoints are placed off the map? - const auto old = std::exchange(VocClass::VoicesEnabled, false); + const bool old = std::exchange(VocClass::VoicesEnabled, false); pBuilding->SetArchiveTarget(pCell); pBuilding->Sell(true); VocClass::VoicesEnabled = old; From 26ff67461ce7e454e4a8e44a5c1157d28aaf54db Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Mon, 29 Dec 2025 17:58:25 +0800 Subject: [PATCH 18/20] Update Body.cpp --- src/Ext/TAction/Body.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Ext/TAction/Body.cpp b/src/Ext/TAction/Body.cpp index dab240c446..1c96c9a348 100644 --- a/src/Ext/TAction/Body.cpp +++ b/src/Ext/TAction/Body.cpp @@ -639,8 +639,9 @@ bool TActionExt::SetFreeRadar(TActionClass* const pThis, HouseClass* const pHous bool TActionExt::SetTeamDelay(TActionClass* const pThis, HouseClass* const pHouse, ObjectClass* const pObject, TriggerClass* const pTrigger, const CellStruct& location) { - const int timer = pThis->Param3 < 0 ? RulesClass::Instance->TeamDelays.Items[static_cast(pHouse->AIDifficulty)] : pThis->Param3; - HouseExt::ExtMap.Find(pHouse)->TeamDelay = timer; + const int value = pThis->Param3; + const int timer = value < 0 ? RulesClass::Instance->TeamDelays.Items[static_cast(pHouse->AIDifficulty)] : value; + HouseExt::ExtMap.Find(pHouse)->TeamDelay = value; auto& Timer = pHouse->TeamDelayTimer; const int time = std::min(Timer.GetTimeLeft(), timer); From 6e07c2f32bd0a8ac05fe3bee73f626e5f240ac3e Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Mon, 29 Dec 2025 18:00:18 +0800 Subject: [PATCH 19/20] ok --- src/Ext/TAction/Body.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ext/TAction/Body.cpp b/src/Ext/TAction/Body.cpp index 1c96c9a348..d4f0f95350 100644 --- a/src/Ext/TAction/Body.cpp +++ b/src/Ext/TAction/Body.cpp @@ -433,7 +433,7 @@ bool TActionExt::UndeployToWaypoint(TActionClass* const pThis, HouseClass* const auto const pType = pBuilding->Type; if (!pType->UndeploysInto - || (pBuilding->Owner != vHouse) + || pBuilding->Owner != vHouse || (!allBuilding && pType != pBuildingType) || !pBuilding->IsAlive || pBuilding->Health <= 0 || pBuilding->InLimbo) { From 5992eddfb9020744b8d12ab7563e02de8aea8623 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Mon, 29 Dec 2025 18:20:39 +0800 Subject: [PATCH 20/20] Update Body.cpp --- src/Ext/TAction/Body.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Ext/TAction/Body.cpp b/src/Ext/TAction/Body.cpp index d4f0f95350..8a96324b4d 100644 --- a/src/Ext/TAction/Body.cpp +++ b/src/Ext/TAction/Body.cpp @@ -426,20 +426,34 @@ bool TActionExt::UndeployToWaypoint(TActionClass* const pThis, HouseClass* const if (!allBuilding && !pBuildingType) return true; + const auto& limboDelivereds = HouseExt::ExtMap.Find(vHouse)->OwnedLimboDeliveredBuildings; + const bool existLimboBuilding = !limboDelivereds.empty(); + // Thanks to chaserli for the relevant code! // There should be a more perfect way to do this, but I don't know how. - auto canUndeploy = [pThis, pTrigger, allBuilding, pBuildingType, vHouse](BuildingClass* pBuilding) + auto canUndeploy = [&](BuildingClass* const pBuilding) { auto const pType = pBuilding->Type; if (!pType->UndeploysInto || pBuilding->Owner != vHouse || (!allBuilding && pType != pBuildingType) + || pBuilding->CurrentMission == Mission::Selling || !pBuilding->IsAlive || pBuilding->Health <= 0 || pBuilding->InLimbo) { return false; } + // verify whether the building's source is LimboDelivery. + if (existLimboBuilding) + { + for (auto const pLimboBuilding : limboDelivereds) + { + if (pLimboBuilding == pBuilding) + return false; + } + } + if (pType->ConstructionYard) { // Conyards can't undeploy if MCVRedeploy=no