From cd2fe73c88fd78d27a975093fe1bae12fc686ff8 Mon Sep 17 00:00:00 2001 From: RT Date: Fri, 24 Jul 2026 10:35:11 -0500 Subject: [PATCH] Fix Load File: separate Auto globals; fix team/FFA double-press MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue 1 — double press to fix team/FFA display: cur_team_val is updated by ConLobbyMission's -9998 signal which was async. Fix: call SetNetworkMissionParamater(team_allowed, ...) directly in ConLobby before the slot loop, then re-read cur_team_val via CTCL_GetTeamParams. This is synchronous so the slot display is correct on the first click. New file keys: TeamAllowed=0/1, TeamCount=2 (default 2 teams). Issue 2 — Default button broken after Load File click: CTCL_LoadAutoFile was overwriting g_nRookieGameType/g_szRookieMission etc. so the Default button loaded the last auto-file params instead of defaults. Fix: 14 new dedicated g_nAutoXxx/g_szAutoMission globals. CTCL_LoadAutoFile populates ONLY these. Rookie Mission globals are never touched. New MAIL_LOAD_AUTO_MISSION (-6666) sent to ConLobbyMission applies the Auto globals (mirrors MAIL_SET_ROOKIE_MISSION_PARAMS but uses g_nAutoXxx). ConLobby reads game type/mission from Auto globals directly into the ConLobbyMission dropdowns (@ConLobbyMission@o_game_options[N].nselected). Files changed: MW4Shell.cpp: 16 new globals, StartUp/ShutDown registration, CTCL_LoadAutoFile ConLobby.script: MAIL_LOAD_AUTO_MISSION define, updated handler ConLobbyMission.script: MAIL_LOAD_AUTO_MISSION define + handler autoconfig-file-spec.html: document TeamAllowed + TeamCount fields Rebuild required: MW4.exe (Release + Profile). --- BTFrstrm/autoconfig-file-spec.html | 11 +++ Gameleap/code/mw4/Code/MW4/MW4Shell.cpp | 95 +++++++++++++++---- .../mw4/Content/ShellScripts/ConLobby.script | 25 ++++- .../Multiplayer/ConLobbyMission.script | 77 +++++++++++++++ 4 files changed, 189 insertions(+), 19 deletions(-) diff --git a/BTFrstrm/autoconfig-file-spec.html b/BTFrstrm/autoconfig-file-spec.html index 018ee99b..29ac1be1 100644 --- a/BTFrstrm/autoconfig-file-spec.html +++ b/BTFrstrm/autoconfig-file-spec.html @@ -266,6 +266,17 @@ Match is exact string equality, case-sensitive. Trailing/leading spaces are stri 1On +

4.15  TeamAllowed — integer (required for correct team/FFA slot display on first click)

+

Must match the GameType selected. Controls whether Team or Skin is applied to slots, and whether team dropdowns are shown.

+ + + + +
ValueDescription
0FFA mode ? slot Skin field is used DEFAULT
1Team game ? slot Team field is used
+ +

4.16  TeamCount — integer (optional, only when TeamAllowed=1)

+

Number of teams. Valid range: 2–8. Default: 2.

+

5. Sections: [slot0] through [slot15]

diff --git a/Gameleap/code/mw4/Code/MW4/MW4Shell.cpp b/Gameleap/code/mw4/Code/MW4/MW4Shell.cpp index 945c6665..fe8fff76 100644 --- a/Gameleap/code/mw4/Code/MW4/MW4Shell.cpp +++ b/Gameleap/code/mw4/Code/MW4/MW4Shell.cpp @@ -191,6 +191,24 @@ static SAutoFileSlot g_aAutoSlots[16]; static int g_nAutoSlotsCount = 0; static int g_bAutomaticMode = 0; static char g_szAutomaticFile[MAX_PATH] = ""; +// [automaticmode] game option globals ? separate from Rookie Mission defaults to preserve Default button behavior +static char g_szAutoMission[256] = ""; +static char* g_pszAutoMission = g_szAutoMission; +static int g_nAutoGameType = 2; // Attrition +static int g_nAutoVisibility = 0; +static int g_nAutoWeather = 0; +static int g_nAutoTimeOfDay = 0; +static int g_nAutoTimeLimit = -1; // -1 = server default +static int g_nAutoRadar = 0; +static int g_nAutoHeat = 0; +static int g_nAutoFriendlyFire = 0; +static int g_nAutoSplash = 0; +static int g_nAutoUnlimitedAmmo = 1; +static int g_nAutoWeaponJam = 0; +static int g_nAutoAdvanceMode = 0; +static int g_nAutoArmorMode = 0; +static int g_nAutoTeamAllowed = 0; // 0=FFA 1=team game; set via TeamAllowed= in [mission] +static int g_nAutoTeamCount = 2; // number of teams when TeamAllowed=1 // MSL 5.06 int g_nMechVariant = 0; int g_nMechLabOp = 0; @@ -791,6 +809,23 @@ void MW4Shell::StartUp() strncpy(g_szAutomaticFile, sz, sizeof(g_szAutomaticFile)-1); } } + // [automaticmode] game option variables (separate from Rookie globals) + gosScript_RegisterVariable("g_szAutoMission", &g_pszAutoMission, GOSVAR_STRING, 0, NULL); + gosScript_RegisterVariable("g_nAutoGameType", &g_nAutoGameType, GOSVAR_INT, 0, NULL); + gosScript_RegisterVariable("g_nAutoVisibility", &g_nAutoVisibility, GOSVAR_INT, 0, NULL); + gosScript_RegisterVariable("g_nAutoWeather", &g_nAutoWeather, GOSVAR_INT, 0, NULL); + gosScript_RegisterVariable("g_nAutoTimeOfDay", &g_nAutoTimeOfDay, GOSVAR_INT, 0, NULL); + gosScript_RegisterVariable("g_nAutoTimeLimit", &g_nAutoTimeLimit, GOSVAR_INT, 0, NULL); + gosScript_RegisterVariable("g_nAutoRadar", &g_nAutoRadar, GOSVAR_INT, 0, NULL); + gosScript_RegisterVariable("g_nAutoHeat", &g_nAutoHeat, GOSVAR_INT, 0, NULL); + gosScript_RegisterVariable("g_nAutoFriendlyFire", &g_nAutoFriendlyFire, GOSVAR_INT, 0, NULL); + gosScript_RegisterVariable("g_nAutoSplash", &g_nAutoSplash, GOSVAR_INT, 0, NULL); + gosScript_RegisterVariable("g_nAutoUnlimitedAmmo",&g_nAutoUnlimitedAmmo, GOSVAR_INT, 0, NULL); + gosScript_RegisterVariable("g_nAutoWeaponJam", &g_nAutoWeaponJam, GOSVAR_INT, 0, NULL); + gosScript_RegisterVariable("g_nAutoAdvanceMode", &g_nAutoAdvanceMode, GOSVAR_INT, 0, NULL); + gosScript_RegisterVariable("g_nAutoArmorMode", &g_nAutoArmorMode, GOSVAR_INT, 0, NULL); + gosScript_RegisterVariable("g_nAutoTeamAllowed", &g_nAutoTeamAllowed, GOSVAR_INT, 0, NULL); + gosScript_RegisterVariable("g_nAutoTeamCount", &g_nAutoTeamCount, GOSVAR_INT, 0, NULL); // MSL 5.06 gosScript_RegisterVariable("g_nMechVariant", &g_nMechVariant, GOSVAR_INT, 0, NULL); gosScript_RegisterVariable("g_nMechLabOp", &g_nMechLabOp, GOSVAR_INT, 0, NULL); @@ -1193,6 +1228,23 @@ void MW4Shell::ShutDown() gosScript_UnregisterCallback("CTCL_GetAutoSlotName"); gosScript_UnregisterCallback("CTCL_LoadAutoFile"); gosScript_UnregisterVariable("g_bAutomaticMode"); + // [automaticmode] game option variables + gosScript_UnregisterVariable("g_nAutoTeamCount"); + gosScript_UnregisterVariable("g_nAutoTeamAllowed"); + gosScript_UnregisterVariable("g_nAutoArmorMode"); + gosScript_UnregisterVariable("g_nAutoAdvanceMode"); + gosScript_UnregisterVariable("g_nAutoWeaponJam"); + gosScript_UnregisterVariable("g_nAutoUnlimitedAmmo"); + gosScript_UnregisterVariable("g_nAutoSplash"); + gosScript_UnregisterVariable("g_nAutoFriendlyFire"); + gosScript_UnregisterVariable("g_nAutoHeat"); + gosScript_UnregisterVariable("g_nAutoRadar"); + gosScript_UnregisterVariable("g_nAutoTimeLimit"); + gosScript_UnregisterVariable("g_nAutoTimeOfDay"); + gosScript_UnregisterVariable("g_nAutoWeather"); + gosScript_UnregisterVariable("g_nAutoVisibility"); + gosScript_UnregisterVariable("g_nAutoGameType"); + gosScript_UnregisterVariable("g_szAutoMission"); // MSL 5.06 gosScript_UnregisterVariable("g_nBlackMech"); gosScript_UnregisterVariable("g_nMechVariant"); @@ -12859,28 +12911,37 @@ int __stdcall CTCL_LoadAutoFile(void* instance, int args, void* data[]) NotationFile autofile(g_szAutomaticFile, NotationFile::Standard, true); - // Game options ? overwrite Rookie Mission globals so the existing - // MAIL_SET_ROOKIE_MISSION script flow picks them up automatically. + // Game options ? stored in dedicated Auto globals, NOT Rookie Mission globals, + // so the Default button continues to use the original [RookieMission] defaults. + g_szAutoMission[0] = '\0'; + g_nAutoGameType = 2; g_nAutoVisibility = 0; g_nAutoWeather = 0; + g_nAutoTimeOfDay = 0; g_nAutoTimeLimit = -1; g_nAutoRadar = 0; + g_nAutoHeat = 0; g_nAutoFriendlyFire = 0; g_nAutoSplash = 0; + g_nAutoUnlimitedAmmo = 1; g_nAutoWeaponJam = 0; g_nAutoAdvanceMode = 0; + g_nAutoArmorMode = 0; g_nAutoTeamAllowed = 0; g_nAutoTeamCount = 2; + Page *pMission = autofile.FindPage("mission"); if (pMission) { const char *sz = NULL; if (pMission->GetEntry("MissionName", &sz) && sz) { - strncpy(g_szRookieMission, sz, sizeof(g_szRookieMission)-1); - g_szRookieMission[sizeof(g_szRookieMission)-1] = '\0'; + strncpy(g_szAutoMission, sz, sizeof(g_szAutoMission)-1); + g_szAutoMission[sizeof(g_szAutoMission)-1] = '\0'; } - pMission->GetEntry("GameType", &g_nRookieGameType); - pMission->GetEntry("Visibility", &g_nRookieVisibility); - pMission->GetEntry("Weather", &g_nRookieWeather); - pMission->GetEntry("TimeOfDay", &g_nRookieTimeOfDay); - pMission->GetEntry("TimeLimit", &g_nRookieTimeLimit); - pMission->GetEntry("Radar", &g_nRookieRadar); - pMission->GetEntry("HeatOn", &g_nRookieHeat); - pMission->GetEntry("FriendlyFire", &g_nRookieFriendlyFire); - pMission->GetEntry("SplashDamage", &g_nRookieSplash); - pMission->GetEntry("UnlimitedAmmo", &g_nRookieUnlimitedAmmo); - pMission->GetEntry("WeaponJam", &g_nRookieWeaponJam); - pMission->GetEntry("AdvanceMode", &g_nRookieAdvanceMode); - pMission->GetEntry("ArmorMode", &g_nRookieArmorMode); + pMission->GetEntry("GameType", &g_nAutoGameType); + pMission->GetEntry("Visibility", &g_nAutoVisibility); + pMission->GetEntry("Weather", &g_nAutoWeather); + pMission->GetEntry("TimeOfDay", &g_nAutoTimeOfDay); + pMission->GetEntry("TimeLimit", &g_nAutoTimeLimit); + pMission->GetEntry("Radar", &g_nAutoRadar); + pMission->GetEntry("HeatOn", &g_nAutoHeat); + pMission->GetEntry("FriendlyFire", &g_nAutoFriendlyFire); + pMission->GetEntry("SplashDamage", &g_nAutoSplash); + pMission->GetEntry("UnlimitedAmmo", &g_nAutoUnlimitedAmmo); + pMission->GetEntry("WeaponJam", &g_nAutoWeaponJam); + pMission->GetEntry("AdvanceMode", &g_nAutoAdvanceMode); + pMission->GetEntry("ArmorMode", &g_nAutoArmorMode); + pMission->GetEntry("TeamAllowed", &g_nAutoTeamAllowed); + pMission->GetEntry("TeamCount", &g_nAutoTeamCount); } // Per-slot data (up to 16 slots via [slot0]..[slot15] pages) diff --git a/Gameleap/mw4/Content/ShellScripts/ConLobby.script b/Gameleap/mw4/Content/ShellScripts/ConLobby.script index 079e1e39..934bb26c 100644 --- a/Gameleap/mw4/Content/ShellScripts/ConLobby.script +++ b/Gameleap/mw4/Content/ShellScripts/ConLobby.script @@ -190,6 +190,7 @@ #define MAIL_PREVIOUS_MISSION -2222 #define MAIL_RECORD_MISSION -4444 #define MAIL_PREVIOUS_MISSION_PARAMS -5555 +#define MAIL_LOAD_AUTO_MISSION -6666 // [automaticmode] sync with Multiplayer/ConLobbyMission.script // MSL 5.06 // MSL ADD MECH @@ -1682,9 +1683,29 @@ main play press, 1 if callback($$CTCL_LoadAutoFile$$) { - // Apply mission + game options via existing Rookie Mission flow + // Apply game options using dedicated Auto globals. + // Rookie Mission globals are NOT touched so the Default button keeps working. + int m if exists(@ConLobbyMission@) - mail(MAIL_SET_ROOKIE_MISSION, @ConLobbyMission@) + { + @ConLobbyMission@o_game_options[0].nselected = $$g_nAutoGameType$$ + for (m = 0; m < @ConLobbyMission@o_game_options[1].list_size; m++) + { + if equal$(@ConLobbyMission@o_game_options[1].list_item[m], $$g_szAutoMission$$) + { + @ConLobbyMission@o_game_options[1].nselected = m + break + } + } + mail(MAIL_LOAD_AUTO_MISSION, @ConLobbyMission@) + } + // Update team state synchronously so slot display is correct on the first click. + // MAIL_LOAD_AUTO_MISSION is async; setting team_allowed directly here lets + // CTCL_GetTeamParams return the correct cur_team_val before the slot loop runs. + callback($$SetNetworkMissionParamater$$, team_allowed, $$g_nAutoTeamAllowed$$) + if $$g_nAutoTeamAllowed$$ + callback($$SetNetworkMissionParamater$$, num_of_teams, $$g_nAutoTeamCount$$) + cur_team_val = callback($$CTCL_GetTeamParams$$, cur_team_count[0]) // Clear all slots o_cam_list.nselected = 0 for (k = 0; k < nRosterCount; k++) diff --git a/Gameleap/mw4/Content/ShellScripts/Multiplayer/ConLobbyMission.script b/Gameleap/mw4/Content/ShellScripts/Multiplayer/ConLobbyMission.script index f72182d7..6d78e535 100644 --- a/Gameleap/mw4/Content/ShellScripts/Multiplayer/ConLobbyMission.script +++ b/Gameleap/mw4/Content/ShellScripts/Multiplayer/ConLobbyMission.script @@ -52,6 +52,7 @@ #define MAIL_PREVIOUS_MISSION -2222 #define MAIL_RECORD_MISSION -4444 #define MAIL_PREVIOUS_MISSION_PARAMS -5555 +#define MAIL_LOAD_AUTO_MISSION -6666 // [automaticmode] sync with ConLobby.script #define ROOKIE_MISSION "ScarabStronghold - Attrition" @@ -1006,6 +1007,82 @@ main initialize(this) return } + // [automaticmode] Load File button: apply Auto globals, separate from Rookie Mission defaults + if (getmessage() == MAIL_LOAD_AUTO_MISSION) + { + callback($$SetNetworkMissionParamater$$, game_type, selection_to_standard[$$g_nAutoGameType$$]) + // visibility + o_game_options[2].nselected = $$g_nAutoVisibility$$ + callback($$SetNetworkMissionParamater$$, visibility, o_game_options[2].nselected) + // weather + o_game_options[3].nselected = $$g_nAutoWeather$$ + callback($$SetNetworkMissionParamater$$, weather, o_game_options[3].nselected) + // time of day + o_game_options[4].nselected = $$g_nAutoTimeOfDay$$ + callback($$SetNetworkMissionParamater$$, night_parameter, o_game_options[4].nselected) + callback($$Shell_CallbackHandler$$, ShellSetTime, o_game_options[4].nselected) + // time limit + int nAutoTL = $$g_nAutoTimeLimit$$ + int temp_num + if nAutoTL >= 0 + temp_num = nAutoTL + else + temp_num = TIME_VALUE_DEFAULT + int m + for (m = 0; m < o_game_options[5].list_size; m++) + { + if (makeint(o_game_options[5].list_item[m]) == temp_num) + { + o_game_options[5].nselected = m + break + } + } + callback($$SetNetworkMissionParamater$$, time_limit, temp_num) + // radar + int nTempParam = radar + int nTempValue = $$g_nAutoRadar$$ + o_game_options[6].nselected = nTempValue + callback($$SetNetworkMissionParamater$$, nTempParam, nTempValue) + // heat + nTempParam = HEAT_PARAMETER + nTempValue = $$g_nAutoHeat$$ + o_game_options[7].state = 0 + callback($$SetNetworkMissionParamater$$, nTempParam, nTempValue) + // friendly fire + nTempParam = FRIENDLY_FIRE_PERCENTGE_PARAMETER + nTempValue = $$g_nAutoFriendlyFire$$ + o_game_options[8].state = 0 + callback($$SetNetworkMissionParamater$$, nTempParam, nTempValue) + // splash + nTempParam = SPLASH_ON_PARAMETER + nTempValue = $$g_nAutoSplash$$ + o_game_options[9].state = 0 + callback($$SetNetworkMissionParamater$$, nTempParam, nTempValue) + // unlimited ammo + nTempParam = UNLIMITED_AMMO_PARAMETER + nTempValue = $$g_nAutoUnlimitedAmmo$$ + o_game_options[10].state = 0 + callback($$SetNetworkMissionParamater$$, nTempParam, nTempValue) + // weapon jam + nTempParam = WEAPON_JAM_PARAMETER + nTempValue = $$g_nAutoWeaponJam$$ + o_game_options[14].state = 0 + callback($$SetNetworkMissionParamater$$, nTempParam, nTempValue) + // advance mode + nTempParam = ADVANCE_MODE_PARAMETER + nTempValue = $$g_nAutoAdvanceMode$$ + o_game_options[15].state = 0 + callback($$SetNetworkMissionParamater$$, nTempParam, nTempValue) + // armor mode + nTempParam = ARMOR_MODE_PARAMETER + nTempValue = $$g_nAutoArmorMode$$ + o_game_options[16].state = 0 + callback($$SetNetworkMissionParamater$$, nTempParam, nTempValue) + initialize(this) + // notify ConLobby: game type/params changed (updates cur_game_type, cur_team_val display) + mail(-9998, parent) + return + } if (getmessage() == MAIL_PREVIOUS_MISSION_PARAMS) { // visibility