From 04cd31e635ac404b67ef8eb7f57c28227bc7864a Mon Sep 17 00:00:00 2001 From: Coronia <2217891145@qq.com> Date: Thu, 30 Oct 2025 01:27:16 +0800 Subject: [PATCH] distribution mode extension --- docs/User-Interface.md | 10 +++++++++- src/Commands/DistributionMode.cpp | 26 +++++++++++++++++--------- src/Ext/Rules/Body.cpp | 8 +++++++- src/Ext/Rules/Body.h | 6 ++++++ src/Phobos.INI.cpp | 2 +- 5 files changed, 40 insertions(+), 12 deletions(-) diff --git a/docs/User-Interface.md b/docs/User-Interface.md index bfce9074ad..d4a28e50ae 100644 --- a/docs/User-Interface.md +++ b/docs/User-Interface.md @@ -509,11 +509,14 @@ For this command to work in multiplayer - you need to use a version of [YRpp spa - `AllowDistributionCommand.SpreadMode` & `AllowDistributionCommand.FilterMode` allow you to set spread range and target filter by hotkeys, which default to `DefaultDistributionSpreadMode` and `DefaultDistributionFilterMode`. - When the range is 0, it is the original default behavior of the game. The range can be adjusted to 4, 8 or 16 cells by another shortcut key. You can also adjust this by using the mouse wheel while holding down the specific hotkey if `AllowDistributionCommand.SpreadModeScroll` set to true; - The targets within the range will be allocated equally to the selected technos. Only when the behavior to be performed by the current techno is the same as that displayed by the mouse will it be allocated. Otherwise, it will return to the original default behavior of the game (it will not be effective for technos in the air). This will display a range ring. + - You can also set a list of integers in `DistributionMode.SpreadRanges`. In this case, the range of each step will follow these settings instead of being 0, 4, 8 and 16. - When the filter is `None`, it is the default behavior of the game. If the range is not zero at this time, a green ring will be displayed. You can adjust the filter mode to: - `Like` - only targets with the same armor type (Completely identical `Armor`) will be selected among the targets allocated in the range. At this time, a blue ring will be displayed. - `Type` - only targets of the same type (like infantries, vehicles or buildings) will be selected among the targets allocated in the range. At this time, a yellow ring will be displayed. - `Name` - only targets of the same name (or with the same `GroupAs`) will be selected among the targets allocated in the range. At this time, a red ring will be displayed. - `AllowDistributionCommand.AffectsAllies` & `AllowDistributionCommand.AffectsEnemies` allow the distribution command to work on allies (including owner) or enemies target. If picking a target that's not eligible, it'll fallback to vanilla command. +- `DistributionMode.AllowActions` & `DistributionMode.DisallowActions` determine the missions that can or can't be used for distribution command. If picking a target that's not eligible, it'll fallback to vanilla command. + - By default `DistributionMode.AllowActions` is an empty list, which means all missions are eligible for distribution command unless listed in `DistributionMode.DisallowActions`. - It's possible to add a button for distribution mode in the bottom bar by adding `DistributionMode` in the `ButtonList` of `AdvancedCommandBar` and `MultiplayerAdvancedCommandBar`. - The positions of each button are hardcoded, so it'll only decide whether enable this button or not. Distribute Mode button is now always listed after all the vanilla ones. - The asset of these buttons should be added in `sidec0x.mix` files which correspond to different sides, with the name `button12.shp`. @@ -530,6 +533,11 @@ AllowDistributionCommand.FilterMode=true ; boolean AllowDistributionCommand.AffectsAllies=true ; boolean AllowDistributionCommand.AffectsEnemies=true ; boolean +[General] +DistributionMode.AllowActions= ; list of Action +DistributionMode.DisallowActions= ; list of Action +DistributionMode.SpreadRanges=0,4,8,16 ; list of integer + [AudioVisual] StartDistributionModeSound= ; sound entry EndDistributionModeSound= ; sound entry @@ -540,7 +548,7 @@ In `ra2md.ini`: ```ini [Phobos] DefaultApplyNoMoveCommand=true ; boolean -DefaultDistributionSpreadMode=2 ; integer, 0 - r=0 , 1 - r=4 , 2 - r=8 , 3 - r=16 +DefaultDistributionSpreadMode=2 ; integer, index of values in DistributionMode.SpreadRanges DefaultDistributionFilterMode=2 ; integer, 0 - None , 1 - Like , 2 - Type , 3 - Name ``` diff --git a/src/Commands/DistributionMode.cpp b/src/Commands/DistributionMode.cpp index a86bc5566c..a087e90bb0 100644 --- a/src/Commands/DistributionMode.cpp +++ b/src/Commands/DistributionMode.cpp @@ -59,7 +59,8 @@ const wchar_t* DistributionModeSpreadCommandClass::GetUIDescription() const void DistributionModeSpreadCommandClass::Execute(WWKey eInput) const { - Phobos::Config::DistributionSpreadMode = ((Phobos::Config::DistributionSpreadMode + 1) & 3); + const int size = RulesExt::Global()->DistributionMode_SpreadRanges.size() > 0 ? RulesExt::Global()->DistributionMode_SpreadRanges.size() - 1 : 3; + Phobos::Config::DistributionSpreadMode = ((Phobos::Config::DistributionSpreadMode + 1) & size); DistributionModeHoldDownCommandClass::ShowTime = SystemTimer::GetTime(); } @@ -174,7 +175,8 @@ void DistributionModeHoldDownCommandClass::DistributionModeOff() void DistributionModeHoldDownCommandClass::DistributionSpreadModeExpand() { - Phobos::Config::DistributionSpreadMode = std::min(3, Phobos::Config::DistributionSpreadMode + 1); + const int size = RulesExt::Global()->DistributionMode_SpreadRanges.size() > 0 ? RulesExt::Global()->DistributionMode_SpreadRanges.size() - 1 : 3; + Phobos::Config::DistributionSpreadMode = std::min(size, Phobos::Config::DistributionSpreadMode + 1); } void DistributionModeHoldDownCommandClass::DistributionSpreadModeReduce() @@ -238,7 +240,7 @@ DEFINE_HOOK(0x4AE7B3, DisplayClass_ActiveClickWith_Iterate, 0x0) // Distribution mode main if (DistributionModeHoldDownCommandClass::Enabled - && spreadMode + && (spreadMode || RulesExt::Global()->DistributionMode_SpreadRanges.size() > 0) && count > 1 && action != Action::NoMove && !PlanningNodeClass::PlanningModeActive @@ -246,12 +248,17 @@ DEFINE_HOOK(0x4AE7B3, DisplayClass_ActiveClickWith_Iterate, 0x0) && !pTechno->IsInAir() && (HouseClass::CurrentPlayer->IsAlliedWith(pTechno->Owner) ? Phobos::Config::AllowDistributionCommand_AffectsAllies - : Phobos::Config::AllowDistributionCommand_AffectsEnemies)) + : Phobos::Config::AllowDistributionCommand_AffectsEnemies) + && (RulesExt::Global()->DistributionMode_AllowActions.size() > 0 + && std::any_of(RulesExt::Global()->DistributionMode_AllowActions.begin(), RulesExt::Global()->DistributionMode_AllowActions.end(), + [=](Action listedAction) { return action == listedAction; })) + && !std::any_of(RulesExt::Global()->DistributionMode_DisallowActions.begin(), RulesExt::Global()->DistributionMode_DisallowActions.end(), + [=](Action listedAction) { return action == listedAction; })) { VocClass::PlayGlobal(RulesExt::Global()->AddDistributionModeCommandSound, 0x2000, 1.0); const bool targetIsNeutral = pTechno->Owner->IsNeutral(); const auto pType = pTechno->GetTechnoType(); - const int range = (2 << spreadMode); + const int range = RulesExt::Global()->DistributionMode_SpreadRanges.size() > 0 ? RulesExt::Global()->DistributionMode_SpreadRanges[spreadMode] : (2 << spreadMode); const auto center = pTechno->GetCoords(); const auto pItems = Helpers::Alex::getCellSpreadItems(center, range); @@ -410,16 +417,17 @@ DEFINE_HOOK(0x6DBE74, TacticalClass_DrawAllRadialIndicators_DrawDistributionRang if (!DistributionModeHoldDownCommandClass::Enabled && SystemTimer::GetTime() - DistributionModeHoldDownCommandClass::ShowTime > 30) return 0; - const auto spreadMode = Phobos::Config::DistributionSpreadMode; - const auto filterMode = Phobos::Config::DistributionFilterMode; + const int spreadMode = Phobos::Config::DistributionSpreadMode; + const int filterMode = Phobos::Config::DistributionFilterMode; - if (spreadMode || filterMode) + if (spreadMode || RulesExt::Global()->DistributionMode_SpreadRanges.size() > 0 || filterMode) { const auto pCell = MapClass::Instance.GetCellAt(DisplayClass::Instance.CurrentFoundation_CenterCell); const auto color = (filterMode > 1) ? ((filterMode == 3) ? ColorStruct { 255, 0, 0 } : ColorStruct { 200, 200, 0 }) : ((filterMode == 1) ? ColorStruct { 0, 100, 255 } : ColorStruct { 0, 255, 50 }); - Game::DrawRadialIndicator(false, true, pCell->GetCoords(), color, static_cast(spreadMode ? (2 << spreadMode) : 0.5), false, true); + Game::DrawRadialIndicator(false, true, pCell->GetCoords(), color, static_cast(RulesExt::Global()->DistributionMode_SpreadRanges.size() > 0 + ? RulesExt::Global()->DistributionMode_SpreadRanges[spreadMode] : (spreadMode ? (2 << spreadMode) : 0.5)), false, true); } return 0; diff --git a/src/Ext/Rules/Body.cpp b/src/Ext/Rules/Body.cpp index 4ad9881715..8ee81b6727 100644 --- a/src/Ext/Rules/Body.cpp +++ b/src/Ext/Rules/Body.cpp @@ -1,4 +1,4 @@ -#include "Body.h" +#include "Body.h" #include #include #include @@ -263,6 +263,9 @@ void RulesExt::ExtData::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI) this->StartDistributionModeSound.Read(exINI, GameStrings::AudioVisual, "StartDistributionModeSound"); this->EndDistributionModeSound.Read(exINI, GameStrings::AudioVisual, "EndDistributionModeSound"); this->AddDistributionModeCommandSound.Read(exINI, GameStrings::AudioVisual, "AddDistributionModeCommandSound"); + this->DistributionMode_AllowActions.Read(exINI, GameStrings::General, "DistributionMode.AllowActions"); + this->DistributionMode_DisallowActions.Read(exINI, GameStrings::General, "DistributionMode.DisallowActions"); + this->DistributionMode_SpreadRanges.Read(exINI, GameStrings::General, "DistributionMode.SpreadRanges"); this->ReplaceVoxelLightSources(); @@ -558,6 +561,9 @@ void RulesExt::ExtData::Serialize(T& Stm) .Process(this->StartDistributionModeSound) .Process(this->EndDistributionModeSound) .Process(this->AddDistributionModeCommandSound) + .Process(this->DistributionMode_AllowActions) + .Process(this->DistributionMode_DisallowActions) + .Process(this->DistributionMode_SpreadRanges) .Process(this->UseFixedVoxelLighting) .Process(this->AIAutoDeployMCV) .Process(this->AISetBaseCenter) diff --git a/src/Ext/Rules/Body.h b/src/Ext/Rules/Body.h index f7c8e4c2b1..3eb3c92165 100644 --- a/src/Ext/Rules/Body.h +++ b/src/Ext/Rules/Body.h @@ -205,6 +205,9 @@ class RulesExt ValueableIdx StartDistributionModeSound; ValueableIdx EndDistributionModeSound; ValueableIdx AddDistributionModeCommandSound; + ValueableVector DistributionMode_AllowActions; + ValueableVector DistributionMode_DisallowActions; + ValueableVector DistributionMode_SpreadRanges; Nullable> VoxelLightSource; // Nullable> VoxelShadowLightSource; @@ -439,6 +442,9 @@ class RulesExt , StartDistributionModeSound { -1 } , EndDistributionModeSound { -1 } , AddDistributionModeCommandSound { -1 } + , DistributionMode_AllowActions { } + , DistributionMode_DisallowActions { } + , DistributionMode_SpreadRanges { } , UseFixedVoxelLighting { false } , AIAutoDeployMCV { true } , AISetBaseCenter { true } diff --git a/src/Phobos.INI.cpp b/src/Phobos.INI.cpp index 77cb070620..b69b2e0054 100644 --- a/src/Phobos.INI.cpp +++ b/src/Phobos.INI.cpp @@ -121,7 +121,7 @@ DEFINE_HOOK(0x5FACDF, OptionsClass_LoadSettings_LoadPhobosSettings, 0x5) Phobos::Config::ApplyNoMoveCommand = CCINIClass::INI_RA2MD.ReadBool(phobosSection, "DefaultApplyNoMoveCommand", true); Phobos::Config::DistributionSpreadMode = CCINIClass::INI_RA2MD.ReadInteger(phobosSection, "DefaultDistributionSpreadMode", 2); - Phobos::Config::DistributionSpreadMode = std::clamp(Phobos::Config::DistributionSpreadMode, 0, 3); + //Phobos::Config::DistributionSpreadMode = std::clamp(Phobos::Config::DistributionSpreadMode, 0, 3); Phobos::Config::DistributionFilterMode = CCINIClass::INI_RA2MD.ReadInteger(phobosSection, "DefaultDistributionFilterMode", 2); Phobos::Config::DistributionFilterMode = std::clamp(Phobos::Config::DistributionFilterMode, 0, 3);