Skip to content

Commit 79a026c

Browse files
[Map] SkipMapSelect Enhancement (#2329)
Using `SkipMapSelect=yes` in the map file allows you to bypass the restriction in `mapselmd.ini`—which requires that the player's faction in the current campaign must match the faction in the next new campaign. You can use `NextScenario` and `AltNextScenario` to specify the map names required to enter a new campaign, thereby forcing the game to proceed to the next campaign. 现在在地图文件中使用`SkipMapSelect=yes`可以绕过`mapselmd.ini`中的限制——该限制要求当前战役中玩家所属的阵营必须与下一个新战役中的阵营一致。你可以使用`NextScenario`和`AltNextScenario`来指定进入新战役所需的地图名称强制游戏进入下一个战役。 Now, setting a local variable named `<Alternate Next Scenario>` will also trigger `AltNextScenario`. 现在启用一个名为`<Alternate Next Scenario>`的局部变量也可以触发`AltNextScenario`。 --------- ### `611` Set Next Scenario - Set the next campaign to load after winning the current one. - Works only in `Campaign Mode` and requires setting `[Basic]>SkipMapSelect=yes`. In `mycampaign.map`: ```ini [Actions] ... ID=ActionCount,[Action1],611,4,[Map Filename],0,0,0,0,A,[ActionX] ... ``` --------- Co-authored-by: Fly-Star <100747645+a851903106@users.noreply.github.com> Co-authored-by: Noble_Fish <1065703286@qq.com>
1 parent a091935 commit 79a026c

7 files changed

Lines changed: 109 additions & 29 deletions

File tree

CREDITS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,7 @@ This page lists all the individual contributions to the project by their author.
441441
- DeployFire supports buildings
442442
- `OmniFire` supports buildings with `Turret=yes`
443443
- Fixed an issue where setting a production building as `Primary` could cause it to enter an unload state
444+
- SkipMapSelect Enhancement
444445
- **NetsuNegi**:
445446
- Forbidding parallel AI queues by type
446447
- Jumpjet crash speed fix when crashing onto building

YRpp

Submodule YRpp updated 1 file

docs/AI-Scripting-and-Mapping.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,12 @@ In `RA2MD.INI`:
159159
ShowBriefing=true ; boolean
160160
```
161161

162+
### SkipMapSelect Enhancement
163+
164+
- Using `SkipMapSelect=yes` in the map file allows you to bypass the restriction in mapselmd.ini—which requires that the player's faction in the current campaign must match the faction in the next new campaign.
165+
- You can use `NextScenario` and `AltNextScenario` to specify the map names required to enter a new campaign, thereby forcing the game to proceed to the next campaign.
166+
- Now, setting a local variable named `<Alternate Next Scenario>` will also trigger `AltNextScenario`.
167+
162168
## Script Actions
163169

164170
### Below `10000`
@@ -834,6 +840,19 @@ ID=ActionCount,[Action1],610,0,0,[Number],0,0,0,A,[ActionX]
834840
Team delay change will take effect for a house after its next AI team is created.
835841
```
836842

843+
### `611` Set Next Scenario
844+
845+
- Set the next campaign to load after winning the current one.
846+
- Works only in `Campaign Mode` and requires setting `[Basic] -> SkipMapSelect=yes`.
847+
848+
In `mycampaign.map`:
849+
```ini
850+
[Actions]
851+
...
852+
ID=ActionCount,[Action1],611,4,[Map Filename],0,0,0,0,A,[ActionX]
853+
...
854+
```
855+
837856
### `800-802` Display Banner
838857

839858
- Display a 'banner' at a fixed location that is relative to the screen.

docs/Whats-New.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ HideShakeEffects=false ; boolean
194194
102=Horizontal position,0
195195
103=Vertical position,0
196196
104=Banner ID,0
197+
105=Map Filename,0
197198
198199
[EventsRA2]
199200
500=Local variable is greater than...,48,6,0,0,[LONG DESC],0,1,500,1
@@ -256,7 +257,8 @@ HideShakeEffects=false ; boolean
256257
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
257258
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
258259
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
259-
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
260+
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
261+
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
260262
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
261263
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
262264
802=Delete banner... (Phobos),0,104,0,0,0,0,0,0,0,Delete banner with ID,0,1,802
@@ -651,12 +653,13 @@ HideShakeEffects=false ; boolean
651653
- Keep Syringe open until the game exits (by 11EJDE11, ported from Vinifera, original by ZivDero & secsome)
652654
- [Drop crates on death](New-or-Enhanced-Logics.md#drop-crates-on-death) (by FS-21)
653655
- [`600` Configure Drop Crate](AI-Scripting-and-Mapping.md#configure-drop-crate) (by FS-21)
654-
- [DeployFire supports buildings](New-or-Enhanced-Logics.md#deployfire-supports) (By FlyStar)
656+
- [DeployFire supports buildings](New-or-Enhanced-Logics.md#deployfire-supports) (by FlyStar)
655657
- `OmniFire` supports buildings with `Turret=yes` (by FlyStar)
656658
- [Automatic conversion based on health](New-or-Enhanced-Logics.md#automatic-conversion-based-on-health) (by obsidianus)
657659
- Add `ammo`, `health`, `mission`, `landtype` and `sequence` conditions to `DiscardOn` (by Noble_Fish)
658660
- [Berzerk / `Psychedelic` duration stacking customization](Fixed-or-Improved-Logics.md#berzerk-psychedelic-duration-stacking-customization) (by Starkku)
659661
- ScriptType action `Play speech` (by FS-21)
662+
- SkipMapSelect Enhancement (by FlyStar)
660663
661664
#### Vanilla fixes:
662665
- Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya)

src/Ext/Scenario/Hooks.Variables.cpp

Lines changed: 60 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -114,46 +114,80 @@ DEFINE_HOOK(0x685EB1, PhobosSaveVariables, 0x5)//Lose
114114
return 0;
115115
}
116116

117-
DEFINE_HOOK(0x685A38, ScenarioClass_sub_685670_SetNextScenario, 0x6)
118-
{
119-
enum { AltNextScenario = 0x685A4C, NextScenario = 0x685A59, Continue = 0x685A63 };
117+
#pragma region MapSelectExtension
120118

121-
if (ScenarioClass::Instance->SkipMapSelect)
119+
static bool __fastcall MapSelectClass_SetNextScenario_CustomMission(MapSelectClass* pThis, void* _, ScenarioClass* pItem)
120+
{
121+
// It can be directly filled in the map file name without being restricted by mapselmd.ini.
122+
if (pItem->SkipMapSelect)
122123
{
123-
if (strcmp(ScenarioClass::Instance->AltNextScenario, ""))
124-
{
125-
auto const& LocalVariables = ScenarioExt::Global()->Variables[false];
126-
auto const& GlobalVariables = ScenarioExt::Global()->Variables[true];
124+
std::string scenario {};
125+
auto const pGlobal = ScenarioExt::Global();
127126

128-
if (!LocalVariables.empty())
127+
do
128+
{
129+
if (strcmp(ScenarioClass::Instance->AltNextScenario, ""))
129130
{
130-
for (auto const& itr : LocalVariables)
131-
{
132-
if (strcmp(itr.second.Name, "<Alternate Next Scenario>") || itr.second.Value <= 0)
133-
continue;
131+
const auto& localVariables = pGlobal->Variables[false];
132+
const auto& globalVariables = pGlobal->Variables[true];
133+
bool success = false;
134134

135-
return AltNextScenario;
135+
if (!localVariables.empty())
136+
{
137+
for (const auto& itr : localVariables)
138+
{
139+
if (strcmp(itr.second.Name, "<Alternate Next Scenario>") || itr.second.Value <= 0)
140+
continue;
141+
142+
success = true;
143+
break;
144+
}
136145
}
137-
}
138146

139-
if (!GlobalVariables.empty())
140-
{
141-
for (auto const& itr : GlobalVariables)
147+
if (!success && !globalVariables.empty())
142148
{
143-
if (strcmp(itr.second.Name, "<Alternate Next Scenario>") || itr.second.Value <= 0)
144-
continue;
149+
for (const auto& itr : globalVariables)
150+
{
151+
if (strcmp(itr.second.Name, "<Alternate Next Scenario>") || itr.second.Value <= 0)
152+
continue;
153+
154+
success = true;
155+
break;
156+
}
145157

146-
return AltNextScenario;
158+
if (!success && globalVariables.contains(1) && globalVariables.find(1)->second.Value > 0)
159+
success = true;
147160
}
148161

149-
if (GlobalVariables.contains(1) && GlobalVariables.find(1)->second.Value > 0)
150-
return AltNextScenario;
162+
if (success)
163+
{
164+
scenario = pItem->AltNextScenario;
165+
break;
166+
}
151167
}
168+
169+
scenario = pItem->NextScenario;
152170
}
171+
while (false);
172+
173+
if (!scenario.empty())
174+
{
175+
// Does this Stage have any function ? If anyone knows, please let me know.
176+
pItem->Stage = 0;
177+
strncpy(pItem->FileName, scenario.c_str(), 0x104u);
178+
pItem->FileName[259] = '\0';
153179

154-
if (strcmp(ScenarioClass::Instance->NextScenario, ""))
155-
return NextScenario;
180+
return true;
181+
}
182+
183+
return false;
156184
}
157185

158-
return Continue;
186+
// Return to the original function.
187+
return pThis->SetNextScenario(pItem);
159188
}
189+
190+
DEFINE_JUMP(LJMP, 0x685A38, 0x685A63) // Skip the original code
191+
DEFINE_FUNCTION_JUMP(CALL, 0x5ADD63, MapSelectClass_SetNextScenario_CustomMission)
192+
193+
#pragma endregion

src/Ext/TAction/Body.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "Body.h"
22

3+
#include <ScenarioClass.h>
34
#include <TriggerTypeClass.h>
45
#include <Ext/House/Body.h>
56
#include <Ext/Scenario/Body.h>
@@ -81,6 +82,8 @@ bool TActionExt::Execute(TActionClass* pThis, HouseClass* pHouse, ObjectClass* p
8182
return TActionExt::SetFreeRadar(pThis, pHouse, pObject, pTrigger, location);
8283
case PhobosTriggerAction::SetTeamDelay:
8384
return TActionExt::SetTeamDelay(pThis, pHouse, pObject, pTrigger, location);
85+
case PhobosTriggerAction::SetNextScanario:
86+
return TActionExt::SetNextScanario(pThis, pHouse, pObject, pTrigger, location);
8487

8588
case PhobosTriggerAction::CreateBannerLocal:
8689
return TActionExt::CreateBannerLocal(pThis, pHouse, pObject, pTrigger, location);
@@ -756,6 +759,24 @@ bool TActionExt::SetTeamDelay(TActionClass* const pThis, HouseClass* const pHous
756759
return true;
757760
}
758761

762+
bool TActionExt::SetNextScanario(TActionClass* const pThis, HouseClass* const pHouse, ObjectClass* const pObject, TriggerClass* const pTrigger, const CellStruct& location)
763+
{
764+
if (SessionClass::Instance.IsCampaign())
765+
{
766+
const char* pText = pThis->Text;
767+
768+
if (strcmp(pText, "") && strcmp(pText, "0"))
769+
{
770+
// When you can customize it as you like, there’s no longer a need for additional branches.
771+
ScenarioClass* const pScenario = ScenarioClass::Instance;
772+
_snprintf_s(pScenario->AltNextScenario, sizeof(pScenario->AltNextScenario), pText);
773+
_snprintf_s(pScenario->NextScenario, sizeof(pScenario->NextScenario), pText);
774+
}
775+
}
776+
777+
return true;
778+
}
779+
759780
static void CreateOrReplaceBanner(TActionClass* pTAction, bool isGlobal)
760781
{
761782
const auto pBannerType = BannerTypeClass::Find(pTAction->Text);

src/Ext/TAction/Body.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ enum class PhobosTriggerAction : unsigned int
2626
SetForceEnemy = 608,
2727
SetFreeRadar = 609,
2828
SetTeamDelay = 610,
29+
SetNextScanario = 611,
2930

3031
CreateBannerLocal = 800, // any banner w/ local variable
3132
CreateBannerGlobal = 801, // any banner w/ global variable
@@ -89,6 +90,7 @@ class TActionExt final : public AbstractExt
8990
ACTION_FUNC(SetForceEnemy);
9091
ACTION_FUNC(SetFreeRadar);
9192
ACTION_FUNC(SetTeamDelay);
93+
ACTION_FUNC(SetNextScanario);
9294

9395
ACTION_FUNC(CreateBannerLocal);
9496
ACTION_FUNC(CreateBannerGlobal);

0 commit comments

Comments
 (0)