Fix '-mission' and '-loadlevel' arguments

This commit is contained in:
Louis Gombert
2025-05-11 15:21:54 +02:00
parent ae7d8fbc17
commit 8d39908d88
6 changed files with 56 additions and 47 deletions

View File

@@ -641,6 +641,9 @@
#include <cstdlib>
#include <filesystem>
#include "args.h"
#include "ddio.h"
#include "crossplat.h"
#include "Mission.h"
#include "3d.h"
#include "LoadLevel.h"
@@ -701,12 +704,12 @@ bool mn3_GetInfo(const std::filesystem::path &mn3file, tMissionInfo *msn);
static inline bool IS_MN3_FILE(const std::filesystem::path &fname) {
std::filesystem::path ext = fname.extension();
return (stricmp((const char*)ext.u8string().c_str(), ".mn3") == 0);
return (stricmp((const char *)ext.u8string().c_str(), ".mn3") == 0);
}
static inline std::filesystem::path MN3_TO_MSN_NAME(const std::filesystem::path &mn3name) {
std::filesystem::path fname = std::filesystem::path(mn3name).stem();
if (stricmp((const char*)fname.u8string().c_str(), "d3_2") == 0) {
if (stricmp((const char *)fname.u8string().c_str(), "d3_2") == 0) {
fname = "d3";
}
fname.replace_extension(".msn");
@@ -742,6 +745,26 @@ void InitMission() {
}
atexit(ResetMission);
}
void InitDefaultMissionFromCLI() {
// Load mission on startup
int mission_arg = FindArg("-mission");
if (mission_arg > 0) {
std::filesystem::path filename = std::filesystem::path(GameArgs[mission_arg + 1]).filename().replace_extension(".mn3");
LoadMission((const char*)filename.u8string().c_str());
int level_arg = FindArg("-loadlevel");
if (level_arg > 0) {
int level{std::atoi(GameArgs[level_arg + 1])};
if (level <= 0 || level > Current_mission.num_levels) {
LOG_WARNING << "Invalid level selection, resetting to 1";
level = 1;
}
Current_mission.cur_level = level;
}
}
}
// reset all states for a mission
void ResetMission() {
LOG_INFO << "In ResetMission()";
@@ -1166,9 +1189,9 @@ bool LoadMission(const char *mssn) {
// set up current mission (movies are already set above)
msn->cur_level = 1;
msn->num_levels = numlevels;
msn->filename = mem_strdup((const char*)mission.u8string().c_str());
msn->filename = mem_strdup((const char *)mission.u8string().c_str());
msn->game_state_flags = 0;
strcpy(Net_msn_URLs.msnname, (const char*)mission.u8string().c_str());
strcpy(Net_msn_URLs.msnname, (const char *)mission.u8string().c_str());
res = true; // everything is ok.
// if error, print it out, else end.
@@ -1238,7 +1261,7 @@ void LoadLevelText(const std::filesystem::path &level_filename) {
pathname.replace_extension(".str");
char **goal_strings;
if (CreateStringTable((const char*)pathname.u8string().c_str(), &goal_strings, &n_strings)) {
if (CreateStringTable((const char *)pathname.u8string().c_str(), &goal_strings, &n_strings)) {
int n_goals = Level_goals.GetNumGoals();
ASSERT(n_strings == (n_goals * 3));
for (int i = 0; i < n_goals; i++) {
@@ -1784,24 +1807,26 @@ bool mn3_Open(const std::filesystem::path &mn3file) {
/* Disabled loading scripts from .mn3 files on purpose:
all 64-bit first-party level scripts have already been loaded from `PRIMARY_HOG`.
Mission files contain only Win32 scripts by default, which cannot not be loaded on 64-bit builds.
Reactivate this when we have a proper sandbox system to safely run third-party scripts contained in user-made levels. */
// Osiris_ExtractScriptsFromHog(mn3_handle, true);
Reactivate this when we have a proper sandbox system to safely run third-party scripts contained in user-made
levels. */
// Osiris_ExtractScriptsFromHog(mn3_handle, true);
}
// do table file stuff.
std::filesystem::path filename = mn3file.stem();
std::filesystem::path voice_hog;
if ((stricmp((const char*)filename.u8string().c_str(), "d3") == 0) || (stricmp((const char*)filename.u8string().c_str(), "training") == 0)) {
if ((stricmp((const char *)filename.u8string().c_str(), "d3") == 0) ||
(stricmp((const char *)filename.u8string().c_str(), "training") == 0)) {
// Open audio hog file
voice_hog = std::filesystem::path("missions") / "d3voice1.hog"; // Audio for levels 1-4
Mission_voice_hog_handle = cf_OpenLibrary(voice_hog);
} else if (stricmp((const char*)filename.u8string().c_str(), "d3_2") == 0) {
} else if (stricmp((const char *)filename.u8string().c_str(), "d3_2") == 0) {
// Open audio hog file
voice_hog = std::filesystem::path("missions") / "d3voice2.hog"; // Audio for levels 5-17
Mission_voice_hog_handle = cf_OpenLibrary(voice_hog);
}
filename.replace_extension(".gam");
mng_SetAddonTable((const char*)filename.u8string().c_str());
mng_SetAddonTable((const char *)filename.u8string().c_str());
Current_mission.mn3_handle = mn3_handle;
return true;
}

View File

@@ -294,6 +294,9 @@ const char *GetMissionName(const char *mission);
// initializes mission system.
void InitMission();
// Load the mission and level from CLI arguments
void InitDefaultMissionFromCLI();
// reset all states for a mission
void ResetMission();

View File

@@ -1161,7 +1161,7 @@ bool GameSequencer() {
break;
case RESTORE_GAME_MODE:
case LOADDEMO_MODE:
SetFunctionMode(GAME_MODE); // need to do so sequencer thiks we're in game.
SetFunctionMode(GAME_MODE); // need to do so sequencer thinks we're in game.
break;
}
@@ -1241,14 +1241,6 @@ bool GameSequencer() {
SuspendControls();
EndLevel(1);
SetGameState(GAMESTATE_LVLNEXT);
// This is for HEAT.NET and their tournement mode stuff
// if(FindArg("-doonelevel"))
// SetGameState(GAMESTATE_LVLSTART);
if (FindArg("-doonelevel")) {
SetFunctionMode(QUIT_MODE);
}
break;
case GAMESTATE_LVLNEXT:

View File

@@ -1544,28 +1544,6 @@ void InitIOSystems(bool editor) {
// this one at the end to find our newly build script libraries first
sys_hid = cf_OpenLibrary(PRIMARY_HOG);
// Check to see if there is a -mission command line option
// if there is, attempt to open that hog/mn3 so it can override such
// things as the mainmenu movie, or loading screen
int mission_arg = FindArg("-mission");
if (mission_arg > 0) {
char path_to_mission[_MAX_PATH];
char filename[256];
// get the true filename
ddio_SplitPath(GameArgs[mission_arg + 1], NULL, filename, NULL);
strcat(filename, ".mn3");
// make the full path (it is forced to be on the harddrive since it contains
// textures and stuff).
ddio_MakePath(path_to_mission, LocalD3Dir, "missions", filename, NULL);
if (cfexist(path_to_mission)) {
cf_OpenLibrary(path_to_mission);
} else {
Int3(); // mission not found
}
}
// Initialize debug graph early incase any system uses it in its init
INIT_MESSAGE(("Initializing debug graph."));
DebugGraph_Initialize();
@@ -1864,6 +1842,7 @@ void InitD3Systems1(bool editor) {
// Initialize missions
InitMission();
InitDefaultMissionFromCLI();
// Initializes the ship structure
InitShips();

View File

@@ -1010,13 +1010,13 @@ bool ProcessCommandLine() {
exit_menu = 1;
#endif
}
#ifndef RELEASE
int t = FindArg("-loadlevel");
if (t) {
SimpleStartLevel(GameArgs[t + 1]);
// On first load, enter mission directly if the argument is specified
int missionArg = FindArg("-mission");
static bool missionEntered = false;
if (missionArg && !missionEntered) {
missionEntered = true;
exit_menu = 1;
}
#endif
// at some point the code above sets exit_menu, so we're going to game mode.
if (exit_menu) {
SetFunctionMode(GAME_MODE);

View File

@@ -525,6 +525,16 @@ The following command-line options are available in Descent 3. You can set comma
### Other Options
- `-loadlevel`
**Type:** int
**Default:** Off
**Platform:** all
**Description:** Load a specific level from the mission selected with `-mission`. Only has an effect when `-mission` is specified.
- `-logfile`
**Type:** boolean
@@ -563,7 +573,7 @@ The following command-line options are available in Descent 3. You can set comma
**Platform:** all
**Description:** Loads the specified mission file at startup.
**Description:** Loads the specified mission file at startup. Example: `-mission d3` to load the main campaign. Combine this option with `-loadlevel` to load a specific level from the mission.
- `-pilot <name>`