From fd4a828ef0b86c6fca32acbe67012d2cd19b8728 Mon Sep 17 00:00:00 2001 From: Coronia <2217891145@qq.com> Date: Wed, 26 Aug 2026 22:39:32 +0800 Subject: [PATCH 1/6] set mission timer type --- CREDITS.md | 1 + docs/AI-Scripting-and-Mapping.md | 26 ++++++++++++++++ docs/Whats-New.md | 17 ++++++----- src/Ext/Scenario/Body.cpp | 3 ++ src/Ext/Scenario/Body.h | 7 +++++ src/Ext/TAction/Body.cpp | 23 ++++++++++++-- src/Ext/TAction/Body.h | 10 +++++-- src/Misc/Hooks.UI.cpp | 51 ++++++++++++++++++++++++++++++++ 8 files changed, 127 insertions(+), 11 deletions(-) diff --git a/CREDITS.md b/CREDITS.md index 36ad961727..b0ddbc6680 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -782,6 +782,7 @@ This page lists all the individual contributions to the project by their author. - Customize whether or not passenger can fire out when the transport is moving - Show game time - Fix a game crash when parsing string list with null entry + - `521` Set mission timer type - **NaotoYuuki** - Vertical & meteor trajectory projectile prototypes - **handama**: - AI script action to `16005 Jump Back To Previous Script` diff --git a/docs/AI-Scripting-and-Mapping.md b/docs/AI-Scripting-and-Mapping.md index 074d3917e2..b130c26124 100644 --- a/docs/AI-Scripting-and-Mapping.md +++ b/docs/AI-Scripting-and-Mapping.md @@ -716,6 +716,32 @@ ID=ActionCount,[Action1],512,0,0,[FollowerIndex],0,0,0,A,[ActionX] ... ``` +### `521` Set mission timer type + +- Set the method to display mission timer, the variable that should be displayed and if the timer should be displayed reversedly. + - `[Basic] -> InitTime` can be adjusted by `Timer Set...` action. + - If the local/global variable does not exist, 0 will be displayed. + +In `mycampaign.map`: +```ini +[Actions] +... +ID=ActionCount,[Action1],521,0,0,[ShowTimerMethod],[VariableIndex],[ReverseTimer],0,A,[ActionX] +... +``` + +| *Behaviour* | *Description* | +| :---------: | :--------------------------------------------: | +| 0 | Show normal timer | +| 1 | show percentage based on `[Basic] -> InitTime` | +| 2 | Show left timer in digit form | +| 3 | Show value of the selected local variable | +| 4 | Show value of the selected global variable | + +```{note} +This won't affect how the global mission timer really ticks, so it'll still end after `[Basic] -> InitTime` amount of time. +``` + ### `600` Configure Drop Crate - Set or overwrite the `DropCrate` of the affected objects. diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 0cb4b0ff89..847ad016b6 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -263,20 +263,22 @@ HideShakeEffects=false ; boolean 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 + 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 - 600=Configure dropped crate... (Phobos),0,72,31,0,0,0,0,0,0,Set or overwrite what crate is dropped when the attached object is destroyed. Only functions when used as attached triggers within objects. Behaviour -1=default. 1=Overwrites current crate. 0=Clear current crate,0,1,600 + 512=Set Follower for Associated Unit... (Phobos),0,0,73,0,0,0,0,0,0,Sets the follower for the associated object. The parameter is the index of the follower unit.,0,1,512 + 521=Set Mission Timer Type... (Phobos),0,0,73,48,74,0,0,0,0,Set the method to display mission timer, the variable that should be displayed and if the timer should be displayed reversedly. Method 0=default, 1=percentage, 2=digit, 3=local variable, 4=global variable.,0,1,521 + 600=Configure dropped crate... (Phobos),0,72,31,0,0,0,0,0,0,Set or overwrite what crate is dropped when the attached object is destroyed. Only functions when used as attached triggers within objects. Behaviour -1=default. 1=Overwrites current crate. 0=Clear current crate.,0,1,600 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 611=Set next scenario... (Phobos),-4,105,0,0,0,0,0,0,0, Set the next campaign to load after winning the current one. Works only in Campaign Mode and requires setting [Basic] -> SkipMapSelect=yes.,0,1,611 - 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 + 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 ; FOLLOWING ENTRIES REQUIRE FA2SP.DLL (by secsome) [ScriptTypeLists] @@ -422,6 +424,7 @@ HideShakeEffects=false ; boolean - [Customized transport plane for teams](AI-Scripting-and-Mapping.md#customized-transport-plane-for-teams) (by FlyStar) - [Modify ammo on impact](New-or-Enhanced-Logics.md#modify-ammo-on-impact) (by FS-21) - [Customize whether mind-controlled Insignificant technos can be auto-targeted](Fixed-or-Improved-Logics.md#customize-whether-mind-controlled-Insignificant-technos-can-be-auto-targeted) (by Noble_Fish) +- [`521` Set mission timer type](AI-Scripting-and-Mapping.md#set-mission-timer-type) (by Ollerus) #### Vanilla fixes: - Fixed the bug where a building with `Factory=BuildingType` owned by the AI did not play `ProductionAnim` when placing a produced building (by Noble_Fish) diff --git a/src/Ext/Scenario/Body.cpp b/src/Ext/Scenario/Body.cpp index b66a18b123..b82164cfbc 100644 --- a/src/Ext/Scenario/Body.cpp +++ b/src/Ext/Scenario/Body.cpp @@ -192,6 +192,9 @@ void ScenarioExt::ExtData::Serialize(T& Stm) .Process(this->FallingDownTracker) .Process(this->EVAIndex) .Process(this->FiringAnimUpdateCount) + .Process(this->MissionTimer_Type) + .Process(this->MissionTimer_Variable) + .Process(this->MissionTimer_Reverse) ; } diff --git a/src/Ext/Scenario/Body.h b/src/Ext/Scenario/Body.h index af5d345682..88a8ee2034 100644 --- a/src/Ext/Scenario/Body.h +++ b/src/Ext/Scenario/Body.h @@ -52,6 +52,10 @@ class ScenarioExt int FiringAnimUpdateCount; + int MissionTimer_Type; + int MissionTimer_Variable; + bool MissionTimer_Reverse; + ExtData(ScenarioClass* OwnerObject) : Extension(OwnerObject) , ShowBriefing { false } , BriefingTheme { -1 } @@ -71,6 +75,9 @@ class ScenarioExt , FallingDownTracker {} , EVAIndex { -2 } , FiringAnimUpdateCount { 0 } + , MissionTimer_Type { 0 } + , MissionTimer_Variable { 0 } + , MissionTimer_Reverse { false } { } static void SetVariableToByID(bool bIsGlobal, int nIndex, char bState); diff --git a/src/Ext/TAction/Body.cpp b/src/Ext/TAction/Body.cpp index 201e8dfef7..5d493fe8bb 100644 --- a/src/Ext/TAction/Body.cpp +++ b/src/Ext/TAction/Body.cpp @@ -65,13 +65,17 @@ bool TActionExt::Execute(TActionClass* pThis, HouseClass* pHouse, ObjectClass* p case PhobosTriggerAction::ToggleMCVRedeploy: return TActionExt::ToggleMCVRedeploy(pThis, pHouse, pObject, pTrigger, location); - case PhobosTriggerAction::SetDropCrate: - return TActionExt::SetDropCrate(pThis, pHouse, pObject, pTrigger, location); case PhobosTriggerAction::UndeployToWaypoint: return TActionExt::UndeployToWaypoint(pThis, pHouse, pObject, pTrigger, location); case PhobosTriggerAction::SetFollowsIndexForVehicle: return TActionExt::SetFollowsIndexForVehicle(pThis, pHouse, pObject, pTrigger, location); + case PhobosTriggerAction::SetMissionTimerType: + return TActionExt::SetMissionTimerType(pThis, pHouse, pObject, pTrigger, location); + + case PhobosTriggerAction::SetDropCrate: + return TActionExt::SetDropCrate(pThis, pHouse, pObject, pTrigger, location); + case PhobosTriggerAction::EditAngerNode: return TActionExt::EditAngerNode(pThis, pHouse, pObject, pTrigger, location); case PhobosTriggerAction::ClearAngerNode: @@ -777,6 +781,21 @@ bool TActionExt::SetNextScanario(TActionClass* const pThis, HouseClass* const pH return true; } +bool TActionExt::SetMissionTimerType(TActionClass* const pThis, HouseClass* const pHouse, ObjectClass* const pObject, TriggerClass* const pTrigger, const CellStruct& location) +{ + const int type = pThis->Param3; + const int reverse = pThis->Param5; + ScenarioExt::Global()->MissionTimer_Variable = pThis->Param4; + + if (0 <= type && 4 >= type) + ScenarioExt::Global()->MissionTimer_Type = type; + + if (0 <= reverse && 1 >= reverse) + ScenarioExt::Global()->MissionTimer_Reverse = (bool)reverse; + + 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 03f956755d..9696acb5f3 100644 --- a/src/Ext/TAction/Body.h +++ b/src/Ext/TAction/Body.h @@ -17,10 +17,13 @@ enum class PhobosTriggerAction : unsigned int RunSuperWeaponAtLocation = 505, RunSuperWeaponAtWaypoint = 506, ToggleMCVRedeploy = 510, - SetDropCrate = 600, UndeployToWaypoint = 511, SetFollowsIndexForVehicle = 512, + SetMissionTimerType = 521, + + SetDropCrate = 600, + EditAngerNode = 606, ClearAngerNode = 607, SetForceEnemy = 608, @@ -81,10 +84,13 @@ class TActionExt final : public AbstractExt ACTION_FUNC(RunSuperWeaponAtLocation); ACTION_FUNC(RunSuperWeaponAtWaypoint); ACTION_FUNC(ToggleMCVRedeploy); - ACTION_FUNC(SetDropCrate); ACTION_FUNC(UndeployToWaypoint); ACTION_FUNC(SetFollowsIndexForVehicle); + ACTION_FUNC(SetMissionTimerType); + + ACTION_FUNC(SetDropCrate); + ACTION_FUNC(EditAngerNode); ACTION_FUNC(ClearAngerNode); ACTION_FUNC(SetForceEnemy); diff --git a/src/Misc/Hooks.UI.cpp b/src/Misc/Hooks.UI.cpp index c7d3c52847..919fd836c4 100644 --- a/src/Misc/Hooks.UI.cpp +++ b/src/Misc/Hooks.UI.cpp @@ -537,6 +537,7 @@ namespace DrawTimerTemp { bool AdjustLocation = false; bool IsPercentage = false; + bool IsDigit = false; double Percentage = 0.0; int TimeLeft = 0; } @@ -552,6 +553,54 @@ DEFINE_HOOK(0x6D3D10, TacticalClass_Render_BeforeAll, 0x6) DEFINE_HOOK(0x6D4992, TacticalClass_Render_DrawMissionTimer_TimeLeft, 0x6) { DrawTimerTemp::TimeLeft = R->EDX(); + DrawTimerTemp::IsPercentage = false; + DrawTimerTemp::IsDigit = false; + + switch (ScenarioExt::Global()->MissionTimer_Type) + { + case 1: + { + const int initTime = ScenarioClass::Instance->InitTime; + if (ScenarioExt::Global()->MissionTimer_Reverse) + DrawTimerTemp::Percentage = initTime > 0 ? static_cast(DrawTimerTemp::TimeLeft) / initTime : 1.0; + else + DrawTimerTemp::Percentage = initTime > 0 ? static_cast(initTime - DrawTimerTemp::TimeLeft) / initTime : 1.0; + DrawTimerTemp::IsPercentage = true; + break; + } + case 2: + { + if (ScenarioExt::Global()->MissionTimer_Reverse) + DrawTimerTemp::TimeLeft = ScenarioClass::Instance->InitTime - DrawTimerTemp::TimeLeft; + DrawTimerTemp::IsDigit = true; + break; + } + case 3: + { + DrawTimerTemp::IsDigit = true; + const auto& variables = ScenarioExt::Global()->Variables[0]; + const auto& it = variables.find(ScenarioExt::Global()->MissionTimer_Variable); + if (it != variables.end()) + DrawTimerTemp::TimeLeft = it->second.Value; + break; + } + case 4: + { + DrawTimerTemp::IsDigit = true; + const auto& variables = ScenarioExt::Global()->Variables[1]; + const auto& it = variables.find(ScenarioExt::Global()->MissionTimer_Variable); + if (it != variables.end()) + DrawTimerTemp::TimeLeft = it->second.Value; + break; + } + default: + { + if (ScenarioExt::Global()->MissionTimer_Reverse) + DrawTimerTemp::TimeLeft = ScenarioClass::Instance->InitTime - DrawTimerTemp::TimeLeft; + break; + } + } + return 0; } @@ -593,6 +642,8 @@ static int __fastcall TacticalClass_DrawTimer_swprintf(wchar_t* pBuffer, size_t if (IsPercentage) return swprintf(pBuffer, bufferCount, L"%.2lf%s", Percentage * 100, L"%%"); + else if (IsDigit) + return swprintf(pBuffer, bufferCount, L"%d", TimeLeft); else return swprintf(pBuffer, bufferCount, L"%02d:%02d", TimeLeft / 60 % 60, TimeLeft % 60); } From d7eb09c2a25898a2a657f6b7f5c8ec0ec5b16798 Mon Sep 17 00:00:00 2001 From: Coronia <2217891145@qq.com> Date: Wed, 26 Aug 2026 22:40:52 +0800 Subject: [PATCH 2/6] fix doc --- docs/Whats-New.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 847ad016b6..8ef7117936 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -205,6 +205,9 @@ HideShakeEffects=false ; boolean 70=AITargetTypes index,0 71=AttachEffectType,0 72=DropCrate Behavior,0 + 73=Unit Index,0 + 74=Mission Timer Type,0 + 75=Reverse Mission Timer,0 101=BannerType,0 102=Horizontal position,0 103=Vertical position,0 @@ -268,7 +271,7 @@ HideShakeEffects=false ; boolean 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 512=Set Follower for Associated Unit... (Phobos),0,0,73,0,0,0,0,0,0,Sets the follower for the associated object. The parameter is the index of the follower unit.,0,1,512 - 521=Set Mission Timer Type... (Phobos),0,0,73,48,74,0,0,0,0,Set the method to display mission timer, the variable that should be displayed and if the timer should be displayed reversedly. Method 0=default, 1=percentage, 2=digit, 3=local variable, 4=global variable.,0,1,521 + 521=Set Mission Timer Type... (Phobos),0,0,74,48,75,0,0,0,0,Set the method to display mission timer, the variable that should be displayed and if the timer should be displayed reversedly. Method 0=default, 1=percentage, 2=digit, 3=local variable, 4=global variable.,0,1,521 600=Configure dropped crate... (Phobos),0,72,31,0,0,0,0,0,0,Set or overwrite what crate is dropped when the attached object is destroyed. Only functions when used as attached triggers within objects. Behaviour -1=default. 1=Overwrites current crate. 0=Clear current crate.,0,1,600 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 From 7ed91df2c14198e5ccb492b48071e45b6a169de4 Mon Sep 17 00:00:00 2001 From: Coronia <2217891145@qq.com> Date: Thu, 27 Aug 2026 01:33:46 +0800 Subject: [PATCH 3/6] fix --- docs/AI-Scripting-and-Mapping.md | 16 ++++++++-------- src/Misc/Hooks.UI.cpp | 16 ++++++++++------ 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/docs/AI-Scripting-and-Mapping.md b/docs/AI-Scripting-and-Mapping.md index b130c26124..ba75726ee8 100644 --- a/docs/AI-Scripting-and-Mapping.md +++ b/docs/AI-Scripting-and-Mapping.md @@ -719,7 +719,7 @@ ID=ActionCount,[Action1],512,0,0,[FollowerIndex],0,0,0,A,[ActionX] ### `521` Set mission timer type - Set the method to display mission timer, the variable that should be displayed and if the timer should be displayed reversedly. - - `[Basic] -> InitTime` can be adjusted by `Timer Set...` action. + - Total mission timer length can be adjusted by `Timer Set...` action. - If the local/global variable does not exist, 0 will be displayed. In `mycampaign.map`: @@ -730,13 +730,13 @@ ID=ActionCount,[Action1],521,0,0,[ShowTimerMethod],[VariableIndex],[ReverseTimer ... ``` -| *Behaviour* | *Description* | -| :---------: | :--------------------------------------------: | -| 0 | Show normal timer | -| 1 | show percentage based on `[Basic] -> InitTime` | -| 2 | Show left timer in digit form | -| 3 | Show value of the selected local variable | -| 4 | Show value of the selected global variable | +| *Behaviour* | *Description* | +| :---------: | :-------------------------------------------------: | +| 0 | Show normal timer | +| 1 | show percentage based on total mission timer length | +| 2 | Show left timer in digit form | +| 3 | Show value of the selected local variable | +| 4 | Show value of the selected global variable | ```{note} This won't affect how the global mission timer really ticks, so it'll still end after `[Basic] -> InitTime` amount of time. diff --git a/src/Misc/Hooks.UI.cpp b/src/Misc/Hooks.UI.cpp index 919fd836c4..6d0440728b 100644 --- a/src/Misc/Hooks.UI.cpp +++ b/src/Misc/Hooks.UI.cpp @@ -547,6 +547,7 @@ DEFINE_HOOK(0x6D3D10, TacticalClass_Render_BeforeAll, 0x6) using namespace DrawTimerTemp; AdjustLocation = false; IsPercentage = false; + IsDigit = false; return 0; } @@ -555,23 +556,25 @@ DEFINE_HOOK(0x6D4992, TacticalClass_Render_DrawMissionTimer_TimeLeft, 0x6) DrawTimerTemp::TimeLeft = R->EDX(); DrawTimerTemp::IsPercentage = false; DrawTimerTemp::IsDigit = false; + const auto& timer = ScenarioClass::Instance->MissionTimer; + const int timerPassed = (timer.CurrentTime - timer.StartTime) / 15; switch (ScenarioExt::Global()->MissionTimer_Type) { case 1: { - const int initTime = ScenarioClass::Instance->InitTime; + DrawTimerTemp::IsPercentage = true; + const int totalTime = timerPassed + DrawTimerTemp::TimeLeft; if (ScenarioExt::Global()->MissionTimer_Reverse) - DrawTimerTemp::Percentage = initTime > 0 ? static_cast(DrawTimerTemp::TimeLeft) / initTime : 1.0; + DrawTimerTemp::Percentage = totalTime > 0 ? static_cast(DrawTimerTemp::TimeLeft) / totalTime : 1.0; else - DrawTimerTemp::Percentage = initTime > 0 ? static_cast(initTime - DrawTimerTemp::TimeLeft) / initTime : 1.0; - DrawTimerTemp::IsPercentage = true; + DrawTimerTemp::Percentage = totalTime > 0 ? static_cast(totalTime - DrawTimerTemp::TimeLeft) / totalTime : 1.0; break; } case 2: { if (ScenarioExt::Global()->MissionTimer_Reverse) - DrawTimerTemp::TimeLeft = ScenarioClass::Instance->InitTime - DrawTimerTemp::TimeLeft; + DrawTimerTemp::TimeLeft = timerPassed; DrawTimerTemp::IsDigit = true; break; } @@ -596,7 +599,7 @@ DEFINE_HOOK(0x6D4992, TacticalClass_Render_DrawMissionTimer_TimeLeft, 0x6) default: { if (ScenarioExt::Global()->MissionTimer_Reverse) - DrawTimerTemp::TimeLeft = ScenarioClass::Instance->InitTime - DrawTimerTemp::TimeLeft; + DrawTimerTemp::TimeLeft = timerPassed; break; } } @@ -611,6 +614,7 @@ DEFINE_HOOK(0x6D4A10, TacticalClass_Render_DrawSuperTimer_PercentageTimer, 0x6) GET(SuperClass*, pSuper, ECX); DrawTimerTemp::IsPercentage = false; + DrawTimerTemp::IsDigit = false; const int timeLeft = pSuper->RechargeTimer.GetTimeLeft(); const auto pSWTypeExt = SWTypeExt::Fetch(pSuper->Type); From 5b79eb9840cca607ffabbc46cfa321f96b41ed82 Mon Sep 17 00:00:00 2001 From: Coronia <2217891145@qq.com> Date: Thu, 27 Aug 2026 13:19:47 +0800 Subject: [PATCH 4/6] use fixed value for percentage and reversed timer --- docs/AI-Scripting-and-Mapping.md | 24 ++++++++++++------------ docs/Whats-New.md | 4 ++-- src/Ext/TAction/Body.cpp | 6 +++--- src/Ext/TAction/Body.h | 4 ++-- src/Misc/Hooks.UI.cpp | 8 +++----- 5 files changed, 22 insertions(+), 24 deletions(-) diff --git a/docs/AI-Scripting-and-Mapping.md b/docs/AI-Scripting-and-Mapping.md index 3863fd2826..97da0c9c1d 100644 --- a/docs/AI-Scripting-and-Mapping.md +++ b/docs/AI-Scripting-and-Mapping.md @@ -716,27 +716,27 @@ ID=ActionCount,[Action1],512,0,0,[FollowerIndex],0,0,0,A,[ActionX] ... ``` -### `521` Set mission timer type +### `521` Set mission timer properties -- Set the method to display mission timer, the variable that should be displayed and if the timer should be displayed reversedly. - - Total mission timer length can be adjusted by `Timer Set...` action. - - If the local/global variable does not exist, 0 will be displayed. +- Set the method to display mission timer and whether the timer should be displayed reversedly based on given value. + - For behaviours `0`, `1`, and `2`, the second parameter decides the base value for percentage timer type or reversed timer that'll be used for calculation. + - For behaviours `3` and `4`, the second parameter decides the index of variable that'll be displayed. If the local/global variable does not exist, 0 will be displayed. In `mycampaign.map`: ```ini [Actions] ... -ID=ActionCount,[Action1],521,0,0,[ShowTimerMethod],[VariableIndex],[ReverseTimer],0,A,[ActionX] +ID=ActionCount,[Action1],521,0,0,[MissionTimerType],[BaseValue or VariableIndex],[ReverseTimer],0,A,[ActionX] ... ``` -| *Behaviour* | *Description* | -| :---------: | :-------------------------------------------------: | -| 0 | Show normal timer | -| 1 | show percentage based on total mission timer length | -| 2 | Show left timer in digit form | -| 3 | Show value of the selected local variable | -| 4 | Show value of the selected global variable | +| *Behaviour* | *Description* | +| :---------: | :----------------------------------------: | +| 0 | Show normal timer | +| 1 | show percentage based on the given value | +| 2 | Show timer in digit form | +| 3 | Show value of the selected local variable | +| 4 | Show value of the selected global variable | ```{note} This won't affect how the global mission timer really ticks, so it'll still end after the mission tiemr expired. diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 099611b38b..4af32a509e 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -271,7 +271,7 @@ HideShakeEffects=false ; boolean 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 512=Set Follower for Associated Unit... (Phobos),0,0,73,0,0,0,0,0,0,Sets the follower for the associated object. The parameter is the index of the follower unit.,0,1,512 - 521=Set Mission Timer Type... (Phobos),0,0,74,48,75,0,0,0,0,Set the method to display mission timer, the variable that should be displayed and if the timer should be displayed reversedly. Method 0=default, 1=percentage, 2=digit, 3=local variable, 4=global variable.,0,1,521 + 521=Set Mission Timer Properties... (Phobos),0,0,74,48,75,0,0,0,0,Set the method to display mission timer and whether the timer should be displayed reversedly based on given value. Method 0=default, 1=percentage based on given value, 2=digit, 3=local variable, 4=global variable.,0,1,521 600=Configure dropped crate... (Phobos),0,72,31,0,0,0,0,0,0,Set or overwrite what crate is dropped when the attached object is destroyed. Only functions when used as attached triggers within objects. Behaviour -1=default. 1=Overwrites current crate. 0=Clear current crate.,0,1,600 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 @@ -428,7 +428,7 @@ HideShakeEffects=false ; boolean - [Modify ammo on impact](New-or-Enhanced-Logics.md#modify-ammo-on-impact) (by FS-21) - [Customize whether mind-controlled Insignificant technos can be auto-targeted](Fixed-or-Improved-Logics.md#customize-whether-mind-controlled-Insignificant-technos-can-be-auto-targeted) (by Noble_Fish) - [AutoDeath based on player power status and player credits](New-or-Enhanced-Logics.md#kill-object-automatically) (by Flactine) -- [`521` Set mission timer type](AI-Scripting-and-Mapping.md#set-mission-timer-type) (by Ollerus) +- [`521` Set mission timer properties](AI-Scripting-and-Mapping.md#set-mission-timer-properties) (by Ollerus) #### Vanilla fixes: - Fixed the bug where a building with `Factory=BuildingType` owned by the AI did not play `ProductionAnim` when placing a produced building (by Noble_Fish) diff --git a/src/Ext/TAction/Body.cpp b/src/Ext/TAction/Body.cpp index 5d493fe8bb..7909b28b8e 100644 --- a/src/Ext/TAction/Body.cpp +++ b/src/Ext/TAction/Body.cpp @@ -70,8 +70,8 @@ bool TActionExt::Execute(TActionClass* pThis, HouseClass* pHouse, ObjectClass* p case PhobosTriggerAction::SetFollowsIndexForVehicle: return TActionExt::SetFollowsIndexForVehicle(pThis, pHouse, pObject, pTrigger, location); - case PhobosTriggerAction::SetMissionTimerType: - return TActionExt::SetMissionTimerType(pThis, pHouse, pObject, pTrigger, location); + case PhobosTriggerAction::SetMissionTimer: + return TActionExt::SetMissionTimer(pThis, pHouse, pObject, pTrigger, location); case PhobosTriggerAction::SetDropCrate: return TActionExt::SetDropCrate(pThis, pHouse, pObject, pTrigger, location); @@ -781,7 +781,7 @@ bool TActionExt::SetNextScanario(TActionClass* const pThis, HouseClass* const pH return true; } -bool TActionExt::SetMissionTimerType(TActionClass* const pThis, HouseClass* const pHouse, ObjectClass* const pObject, TriggerClass* const pTrigger, const CellStruct& location) +bool TActionExt::SetMissionTimer(TActionClass* const pThis, HouseClass* const pHouse, ObjectClass* const pObject, TriggerClass* const pTrigger, const CellStruct& location) { const int type = pThis->Param3; const int reverse = pThis->Param5; diff --git a/src/Ext/TAction/Body.h b/src/Ext/TAction/Body.h index 9696acb5f3..a2b1df7a0b 100644 --- a/src/Ext/TAction/Body.h +++ b/src/Ext/TAction/Body.h @@ -20,7 +20,7 @@ enum class PhobosTriggerAction : unsigned int UndeployToWaypoint = 511, SetFollowsIndexForVehicle = 512, - SetMissionTimerType = 521, + SetMissionTimer = 521, SetDropCrate = 600, @@ -87,7 +87,7 @@ class TActionExt final : public AbstractExt ACTION_FUNC(UndeployToWaypoint); ACTION_FUNC(SetFollowsIndexForVehicle); - ACTION_FUNC(SetMissionTimerType); + ACTION_FUNC(SetMissionTimer); ACTION_FUNC(SetDropCrate); diff --git a/src/Misc/Hooks.UI.cpp b/src/Misc/Hooks.UI.cpp index 6d0440728b..fc4368eab1 100644 --- a/src/Misc/Hooks.UI.cpp +++ b/src/Misc/Hooks.UI.cpp @@ -556,15 +556,13 @@ DEFINE_HOOK(0x6D4992, TacticalClass_Render_DrawMissionTimer_TimeLeft, 0x6) DrawTimerTemp::TimeLeft = R->EDX(); DrawTimerTemp::IsPercentage = false; DrawTimerTemp::IsDigit = false; - const auto& timer = ScenarioClass::Instance->MissionTimer; - const int timerPassed = (timer.CurrentTime - timer.StartTime) / 15; switch (ScenarioExt::Global()->MissionTimer_Type) { case 1: { DrawTimerTemp::IsPercentage = true; - const int totalTime = timerPassed + DrawTimerTemp::TimeLeft; + const int totalTime = ScenarioExt::Global()->MissionTimer_Variable; if (ScenarioExt::Global()->MissionTimer_Reverse) DrawTimerTemp::Percentage = totalTime > 0 ? static_cast(DrawTimerTemp::TimeLeft) / totalTime : 1.0; else @@ -574,7 +572,7 @@ DEFINE_HOOK(0x6D4992, TacticalClass_Render_DrawMissionTimer_TimeLeft, 0x6) case 2: { if (ScenarioExt::Global()->MissionTimer_Reverse) - DrawTimerTemp::TimeLeft = timerPassed; + DrawTimerTemp::TimeLeft = ScenarioExt::Global()->MissionTimer_Variable - DrawTimerTemp::TimeLeft; DrawTimerTemp::IsDigit = true; break; } @@ -599,7 +597,7 @@ DEFINE_HOOK(0x6D4992, TacticalClass_Render_DrawMissionTimer_TimeLeft, 0x6) default: { if (ScenarioExt::Global()->MissionTimer_Reverse) - DrawTimerTemp::TimeLeft = timerPassed; + DrawTimerTemp::TimeLeft = ScenarioExt::Global()->MissionTimer_Variable - DrawTimerTemp::TimeLeft; break; } } From db553f4b4501d9befc69544557dcd2e45357281e Mon Sep 17 00:00:00 2001 From: Coronia <2217891145@qq.com> Date: Fri, 28 Aug 2026 12:22:43 +0800 Subject: [PATCH 5/6] applied feedbacks --- CREDITS.md | 2 +- docs/AI-Scripting-and-Mapping.md | 4 ++-- docs/Whats-New.md | 4 ++-- src/Ext/TAction/Body.cpp | 2 +- src/Ext/TAction/Body.h | 3 +-- src/Misc/Hooks.UI.cpp | 4 ++++ 6 files changed, 11 insertions(+), 8 deletions(-) diff --git a/CREDITS.md b/CREDITS.md index 104531b5a0..8359238971 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -786,7 +786,7 @@ This page lists all the individual contributions to the project by their author. - Customize whether or not passenger can fire out when the transport is moving - Show game time - Fix a game crash when parsing string list with null entry - - `521` Set mission timer type + - `513` Set mission timer type - **NaotoYuuki** - Vertical & meteor trajectory projectile prototypes - **handama**: - AI script action to `16005 Jump Back To Previous Script` diff --git a/docs/AI-Scripting-and-Mapping.md b/docs/AI-Scripting-and-Mapping.md index 97da0c9c1d..ee54363cb1 100644 --- a/docs/AI-Scripting-and-Mapping.md +++ b/docs/AI-Scripting-and-Mapping.md @@ -716,7 +716,7 @@ ID=ActionCount,[Action1],512,0,0,[FollowerIndex],0,0,0,A,[ActionX] ... ``` -### `521` Set mission timer properties +### `513` Set mission timer properties - Set the method to display mission timer and whether the timer should be displayed reversedly based on given value. - For behaviours `0`, `1`, and `2`, the second parameter decides the base value for percentage timer type or reversed timer that'll be used for calculation. @@ -731,7 +731,7 @@ ID=ActionCount,[Action1],521,0,0,[MissionTimerType],[BaseValue or VariableIndex] ``` | *Behaviour* | *Description* | -| :---------: | :----------------------------------------: | +| :---------: | :----------------------------------------- | | 0 | Show normal timer | | 1 | show percentage based on the given value | | 2 | Show timer in digit form | diff --git a/docs/Whats-New.md b/docs/Whats-New.md index e61759a8d3..7c388c3898 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -271,7 +271,7 @@ HideShakeEffects=false ; boolean 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 512=Set Follower for Associated Unit... (Phobos),0,0,73,0,0,0,0,0,0,Sets the follower for the associated object. The parameter is the index of the follower unit.,0,1,512 - 521=Set Mission Timer Properties... (Phobos),0,0,74,48,75,0,0,0,0,Set the method to display mission timer and whether the timer should be displayed reversedly based on given value. Method 0=default, 1=percentage based on given value, 2=digit, 3=local variable, 4=global variable.,0,1,521 + 513=Set Mission Timer Properties... (Phobos),0,0,74,48,75,0,0,0,0,Set the method to display mission timer and whether the timer should be displayed reversedly based on given value. Method 0=default, 1=percentage based on given value, 2=digit, 3=local variable, 4=global variable.,0,1,521 600=Configure dropped crate... (Phobos),0,72,31,0,0,0,0,0,0,Set or overwrite what crate is dropped when the attached object is destroyed. Only functions when used as attached triggers within objects. Behaviour -1=default. 1=Overwrites current crate. 0=Clear current crate.,0,1,600 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 @@ -430,7 +430,7 @@ HideShakeEffects=false ; boolean - [AutoDeath based on player power status and player credits](New-or-Enhanced-Logics.md#kill-object-automatically) (by Flactine) - [Roof production anim](New-or-Enhanced-Logics.md#roof-production-anim) (by Noble_Fish) - [Customize whether the unit exits from the roof](Fixed-or-Improved-Logics.md#customize-whether-the-unit-exits-from-the-roof) (by Noble_Fish) -- [`521` Set mission timer properties](AI-Scripting-and-Mapping.md#set-mission-timer-properties) (by Ollerus) +- [`513` Set mission timer properties](AI-Scripting-and-Mapping.md#set-mission-timer-properties) (by Ollerus) #### Vanilla fixes: - Fixed the bug where a building with `Factory=BuildingType` owned by the AI did not play `ProductionAnim` when placing a produced building (by Noble_Fish) diff --git a/src/Ext/TAction/Body.cpp b/src/Ext/TAction/Body.cpp index 7909b28b8e..ac83d0b6f5 100644 --- a/src/Ext/TAction/Body.cpp +++ b/src/Ext/TAction/Body.cpp @@ -786,7 +786,7 @@ bool TActionExt::SetMissionTimer(TActionClass* const pThis, HouseClass* const pH const int type = pThis->Param3; const int reverse = pThis->Param5; ScenarioExt::Global()->MissionTimer_Variable = pThis->Param4; - + if (0 <= type && 4 >= type) ScenarioExt::Global()->MissionTimer_Type = type; diff --git a/src/Ext/TAction/Body.h b/src/Ext/TAction/Body.h index a2b1df7a0b..ab393241a4 100644 --- a/src/Ext/TAction/Body.h +++ b/src/Ext/TAction/Body.h @@ -19,8 +19,7 @@ enum class PhobosTriggerAction : unsigned int ToggleMCVRedeploy = 510, UndeployToWaypoint = 511, SetFollowsIndexForVehicle = 512, - - SetMissionTimer = 521, + SetMissionTimer = 513, SetDropCrate = 600, diff --git a/src/Misc/Hooks.UI.cpp b/src/Misc/Hooks.UI.cpp index d57c16c938..901d1a4b82 100644 --- a/src/Misc/Hooks.UI.cpp +++ b/src/Misc/Hooks.UI.cpp @@ -583,6 +583,8 @@ DEFINE_HOOK(0x6D4992, TacticalClass_Render_DrawMissionTimer_TimeLeft, 0x6) const auto& it = variables.find(ScenarioExt::Global()->MissionTimer_Variable); if (it != variables.end()) DrawTimerTemp::TimeLeft = it->second.Value; + else + DrawTimerTemp::TimeLeft = 0; break; } case 4: @@ -592,6 +594,8 @@ DEFINE_HOOK(0x6D4992, TacticalClass_Render_DrawMissionTimer_TimeLeft, 0x6) const auto& it = variables.find(ScenarioExt::Global()->MissionTimer_Variable); if (it != variables.end()) DrawTimerTemp::TimeLeft = it->second.Value; + else + DrawTimerTemp::TimeLeft = 0; break; } default: From 72be9ccf9a5a0e310adc9eea26762888bce11a09 Mon Sep 17 00:00:00 2001 From: Coronia <2217891145@qq.com> Date: Fri, 28 Aug 2026 15:04:21 +0800 Subject: [PATCH 6/6] remove space --- src/Ext/TAction/Body.cpp | 1 - src/Ext/TAction/Body.h | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Ext/TAction/Body.cpp b/src/Ext/TAction/Body.cpp index ac83d0b6f5..aeac5594dd 100644 --- a/src/Ext/TAction/Body.cpp +++ b/src/Ext/TAction/Body.cpp @@ -69,7 +69,6 @@ bool TActionExt::Execute(TActionClass* pThis, HouseClass* pHouse, ObjectClass* p return TActionExt::UndeployToWaypoint(pThis, pHouse, pObject, pTrigger, location); case PhobosTriggerAction::SetFollowsIndexForVehicle: return TActionExt::SetFollowsIndexForVehicle(pThis, pHouse, pObject, pTrigger, location); - case PhobosTriggerAction::SetMissionTimer: return TActionExt::SetMissionTimer(pThis, pHouse, pObject, pTrigger, location); diff --git a/src/Ext/TAction/Body.h b/src/Ext/TAction/Body.h index ab393241a4..c054bd67b0 100644 --- a/src/Ext/TAction/Body.h +++ b/src/Ext/TAction/Body.h @@ -85,7 +85,6 @@ class TActionExt final : public AbstractExt ACTION_FUNC(ToggleMCVRedeploy); ACTION_FUNC(UndeployToWaypoint); ACTION_FUNC(SetFollowsIndexForVehicle); - ACTION_FUNC(SetMissionTimer); ACTION_FUNC(SetDropCrate);