diff --git a/code/client/cl_main.cpp b/code/client/cl_main.cpp index 839761d0..5a6ec07b 100644 --- a/code/client/cl_main.cpp +++ b/code/client/cl_main.cpp @@ -3689,6 +3689,8 @@ void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) { char *infoString; int prot; char *gamename; + char *pszVersion; + char *pszServerType; qboolean gameMismatch; infoString = MSG_ReadString( msg ); @@ -3717,12 +3719,44 @@ void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) { #ifdef LEGACY_PROTOCOL && prot != com_legacyprotocol->integer #endif + && (com_target_demo->integer || prot != protocol_version_demo) ) { Com_DPrintf( "Different protocol info packet: %s\n", infoString ); return; } + if (!com_target_demo->integer && prot == protocol_version_demo) { + Com_DPrintf("Full version found compatible demo protocol version. %s\n", infoString); + } + + pszVersion = Info_ValueForKey(infoString, "gamever"); + pszServerType = Info_ValueForKey(infoString, "serverType"); + + if (!*pszVersion) { + return; + } + + if (*pszVersion == 'd') { + pszVersion++; + } + + if (com_target_game->integer >= target_game_e::TG_MOHTT) { + if (atoi(pszServerType) == target_game_e::TG_MOHTT) { + if (fabs(atof(pszVersion)) < 2.3f) { + return; + } + } else { + if (fabs(atof(pszVersion)) < 2.1f) { + return; + } + } + } else { + if (fabs(atof(pszVersion) - com_target_version->value) > 0.1f) { + return; + } + } + // iterate servers waiting for ping response for (i=0; i 0.5) { + Cbuf_AddText("pushmenu sales_splash1\n"); + } else { + Cbuf_AddText("pushmenu sales_splash2\n"); + } +} + /* ==================== CL_ShutdownUI @@ -5256,6 +5270,7 @@ void CL_InitializeUI(void) Cmd_AddCommand("-statistics", UI_HideStatistics_f); Cmd_AddCommand("setreturnmenu", UI_SetReturnMenuToCurrent); Cmd_AddCommand("gotoreturnmenu", UI_PushReturnMenu_f); + Cmd_AddCommand("salesscreen", UI_SalesScreen_f); if (developer->integer) { UColor bgColor; diff --git a/code/client/cl_uiserverlist.cpp b/code/client/cl_uiserverlist.cpp index 7376f417..8a4e88d2 100644 --- a/code/client/cl_uiserverlist.cpp +++ b/code/client/cl_uiserverlist.cpp @@ -1040,6 +1040,7 @@ void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, v { const char* pszHostName; bool bDiffVersion; + bool bIsDemo; str sServerName; str sPlayers; const char* pszGameVer; @@ -1047,12 +1048,14 @@ void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, v pszHostName = ServerGetStringValue(server, "hostname", "(NONE)"); bDiffVersion = false; + bIsDemo = false; pszGameVer = ServerGetStringValue(server, "gamever", "1.00"); pszGameVerNumber = pszGameVer; if (pszGameVerNumber[0] == 'd') { // demo server pszGameVerNumber++; + bIsDemo = true; } if (com_target_game->integer >= target_game_e::TG_MOHTT) { @@ -1077,7 +1080,11 @@ void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, v } } // always show the version - sServerName = va(" (%s) %s", pszGameVer, pszHostName); + if (!bIsDemo) { + sServerName = va(" (%s) %s", pszGameVerNumber, pszHostName); + } else { + sServerName = va(" (d%s) %s", pszGameVerNumber, pszHostName); + } iRealIP = inet_addr(ServerGetAddress(server)); iPort = ServerGetIntValue(server, "hostport", PORT_SERVER); diff --git a/code/gamespy/sv_gamespy.c b/code/gamespy/sv_gamespy.c index e72c26b7..8a7cbe63 100644 --- a/code/gamespy/sv_gamespy.c +++ b/code/gamespy/sv_gamespy.c @@ -55,6 +55,13 @@ static const char *GS_GAME_NAME[] = "mohaab" }; +static const char *GS_GAME_NAME_DEMO[] = +{ + "mohaa", + "mohaas", + "mohaabd" +}; + static const char *GS_GAME_VERSION[] = { TARGET_GAME_VERSION_MOH, @@ -98,7 +105,11 @@ unsigned int GS_GetCurrentGameID() { } const char* GS_GetGameName(unsigned int index) { - return GS_GAME_NAME[index]; + if (!com_target_demo->integer) { + return GS_GAME_NAME[index]; + } else { + return GS_GAME_NAME_DEMO[index]; + } } const char* GS_GetCurrentGameName() { @@ -110,7 +121,11 @@ const char* GS_GetGameVersion(unsigned int index) { } const char* GS_GetCurrentGameVersion() { - return GS_GetGameVersion(com_target_game->integer); + if (!com_target_demo->integer || com_target_game->integer <= TG_MOH) { + return GS_GetGameVersion(com_target_game->integer); + } else { + return va("d%s", GS_GetGameVersion(com_target_game->integer)); + } } static const char *ConvertMapFilename(const char *mapname) @@ -130,7 +145,6 @@ static void basic_callback(char *outbuf, int maxlen, void *userdata) { Info_SetValueForKey(outbuf, "gamename", GS_GetCurrentGameName()); Info_SetValueForKey(outbuf, "gamever", GS_GetCurrentGameVersion()); - Info_SetValueForKey(outbuf, "location", va("%i", sv_location->integer)); if (sv_debug_gamespy->integer) { diff --git a/code/qcommon/common.c b/code/qcommon/common.c index ccc3a757..937f7420 100644 --- a/code/qcommon/common.c +++ b/code/qcommon/common.c @@ -123,6 +123,10 @@ cvar_t *con_autochat; cvar_t *precache; cvar_t *com_target_game; cvar_t *com_target_version; +cvar_t *com_target_demo; + +int protocol_version_demo; +int protocol_version_full; // com_speeds times int time_game; @@ -1652,6 +1656,7 @@ void Com_Init( char *commandLine ) { CL_InitKeyCommands(); com_target_game = Cvar_Get("com_target_game", "0", CVAR_LATCH | CVAR_PROTECTED); + com_target_demo = Cvar_Get("com_target_demo", "0", CVAR_LATCH | CVAR_PROTECTED); com_target_version = Cvar_Get("com_target_version", "0.00", CVAR_ROM); com_standalone = Cvar_Get("com_standalone", "0", CVAR_ROM); com_basegame = Cvar_Get("com_basegame", BASEGAME, CVAR_INIT); @@ -2996,15 +3001,21 @@ int QDECL Com_strCompare( const void *a, const void *b ) return strcmp( *pa, *pb ); } -void Com_InitTargetGameWithType(target_game_e target_game) +void Com_InitTargetGameWithType(target_game_e target_game, qboolean bIsDemo) { const char* protocol; switch (target_game) { case TG_MOH: - Cvar_Set("com_protocol", va("%i", PROTOCOL_MOH)); - Cvar_Set("com_legacyprotocol", va("%i", PROTOCOL_MOH)); + if (!bIsDemo) { + Cvar_Set("com_protocol", va("%i", PROTOCOL_MOH)); + Cvar_Set("com_legacyprotocol", va("%i", PROTOCOL_MOH)); + } else { + Cvar_Set("com_protocol", va("%i", PROTOCOL_MOH_DEMO)); + Cvar_Set("com_legacyprotocol", va("%i", PROTOCOL_MOH_DEMO)); + } + protocol_version_demo = protocol_version_full = PROTOCOL_MOH; Cvar_Set("com_target_version", TARGET_GAME_VERSION_MOH); Cvar_Set("com_target_extension", PRODUCT_EXTENSION_MOH); Cvar_Set("com_gamename", TARGET_GAME_NAME_MOH); @@ -3013,22 +3024,50 @@ void Com_InitTargetGameWithType(target_game_e target_game) break; case TG_MOHTA: - Cvar_Set("com_protocol", va("%i", PROTOCOL_MOHTA)); - Cvar_Set("com_legacyprotocol", va("%i", PROTOCOL_MOHTA)); + if (!bIsDemo) { + Cvar_Set("com_protocol", va("%i", PROTOCOL_MOHTA)); + Cvar_Set("com_legacyprotocol", va("%i", PROTOCOL_MOHTA)); + } else { + Cvar_Set("com_protocol", va("%i", PROTOCOL_MOHTA_DEMO)); + Cvar_Set("com_legacyprotocol", va("%i", PROTOCOL_MOHTA_DEMO)); + } + protocol_version_demo = PROTOCOL_MOHTA_DEMO; + protocol_version_full = PROTOCOL_MOHTA; Cvar_Set("com_target_version", TARGET_GAME_VERSION_MOHTA); Cvar_Set("com_target_extension", PRODUCT_EXTENSION_MOHTA); Cvar_Set("com_gamename", TARGET_GAME_NAME_MOHTA); - Cvar_Set("fs_basegame", "mainta"); + if (!bIsDemo) { + Cvar_Set("fs_basegame", "mainta"); + } else { + // Targeting a demo + Cvar_Set("fs_basegame", "demota"); + } break; case TG_MOHTT: // mohta and mohtt use the same protocol version number - Cvar_Set("com_protocol", va("%i", PROTOCOL_MOHTA)); - Cvar_Set("com_legacyprotocol", va("%i", PROTOCOL_MOHTA)); - Cvar_Set("com_target_version", TARGET_GAME_VERSION_MOHTT); + if (!bIsDemo) { + Cvar_Set("com_protocol", va("%i", PROTOCOL_MOHTA)); + Cvar_Set("com_legacyprotocol", va("%i", PROTOCOL_MOHTA)); + Cvar_Set("com_protocol_alt", va("%i", PROTOCOL_MOHTA_DEMO)); + Cvar_Set("com_target_version", TARGET_GAME_VERSION_MOHTT); + } else { + Cvar_Set("com_protocol", va("%i", PROTOCOL_MOHTA_DEMO)); + Cvar_Set("com_legacyprotocol", va("%i", PROTOCOL_MOHTA_DEMO)); + Cvar_Set("com_protocol_alt", va("%i", PROTOCOL_MOHTA)); + Cvar_Set("com_target_version", TARGET_GAME_VERSION_MOHTT_DEMO); + } + protocol_version_demo = PROTOCOL_MOHTA_DEMO; + protocol_version_full = PROTOCOL_MOHTA; + Cvar_Set("com_protocol_alt", va("%i", PROTOCOL_MOHTA)); Cvar_Set("com_target_extension", PRODUCT_EXTENSION_MOHTT); Cvar_Set("com_gamename", TARGET_GAME_NAME_MOHTT); - Cvar_Set("fs_basegame", "maintt"); + if (!bIsDemo) { + Cvar_Set("fs_basegame", "maintt"); + } else { + // Targeting a demo + Cvar_Set("fs_basegame", "demott"); + } break; default: @@ -3045,7 +3084,7 @@ Com_InitTargetGame =============== */ void Com_InitTargetGame() { - Com_InitTargetGameWithType((target_game_e)com_target_game->integer); + Com_InitTargetGameWithType((target_game_e)com_target_game->integer, com_target_demo->integer); } #ifdef __cplusplus diff --git a/code/qcommon/q_shared.h b/code/qcommon/q_shared.h index fc48d757..eaf3eb75 100644 --- a/code/qcommon/q_shared.h +++ b/code/qcommon/q_shared.h @@ -36,32 +36,36 @@ extern "C" { // We're always legacy #define LEGACY_PROTOCOL -#define GAME_EXTENSION_MOH "main" -#define PRODUCT_EXTENSION_MOH "Allied Assault" -#define TARGET_GAME_VERSION_MOH "1.12" -#define TARGET_GAME_PROTOCOL_MOH 8 -#define TARGET_GAME_NAME_MOH "mohaa" +#define GAME_EXTENSION_MOH "main" +#define PRODUCT_EXTENSION_MOH "Allied Assault" +#define TARGET_GAME_VERSION_MOH "1.12" +#define TARGET_GAME_PROTOCOL_DEMO_MOH 6 +#define TARGET_GAME_PROTOCOL_MOH 8 +#define TARGET_GAME_NAME_MOH "mohaa" #define HOMEPATH_NAME_UNIX_MOH ".moh" #define HOMEPATH_NAME_WIN_MOH "moh" #define HOMEPATH_NAME_MACOSX_MOH HOMEPATH_NAME_WIN_MOH -#define GAME_EXTENSION_MOHTA "mainta" -#define PRODUCT_EXTENSION_MOHTA "Spearhead" -#define TARGET_GAME_VERSION_MOHTA "2.16" -#define TARGET_GAME_PROTOCOL_MOHTA 17 -#define TARGET_GAME_NAME_MOHTA "mohaas" +#define GAME_EXTENSION_MOHTA "mainta" +#define PRODUCT_EXTENSION_MOHTA "Spearhead" +#define TARGET_GAME_VERSION_MOHTA "2.16" +#define TARGET_GAME_PROTOCOL_MIN_MOHTA 16 +#define TARGET_GAME_PROTOCOL_MOHTA 17 +#define TARGET_GAME_NAME_MOHTA "mohaas" #define HOMEPATH_NAME_UNIX_MOHTA ".mohta" #define HOMEPATH_NAME_WIN_MOHTA "mohta" #define HOMEPATH_NAME_MACOSX_MOHTA HOMEPATH_NAME_WIN_MOHTA -#define GAME_EXTENSION_BASE_MOHTT "maintt" -#define PRODUCT_EXTENSION_MOHTT "Breakthrough" +#define GAME_EXTENSION_BASE_MOHTT "maintt" +#define PRODUCT_EXTENSION_MOHTT "Breakthrough" // The version string must be equal or above 2.0 to be able to connect to breakthrough servers -#define TARGET_GAME_VERSION_MOHTT "2.41" -#define TARGET_GAME_PROTOCOL_MOHTT 17 -#define TARGET_GAME_NAME_MOHTT "mohaab" +#define TARGET_GAME_VERSION_MOHTT "2.41" +#define TARGET_GAME_VERSION_MOHTT_DEMO "0.31" +#define TARGET_GAME_PROTOCOL_MIN_MOHTT 16 +#define TARGET_GAME_PROTOCOL_MOHTT 17 +#define TARGET_GAME_NAME_MOHTT "mohaab" #define HOMEPATH_NAME_UNIX_MOHTT ".mohtt" #define HOMEPATH_NAME_WIN_MOHTT "mohtt" @@ -264,8 +268,10 @@ typedef enum { typedef enum { PROTOCOL_MOH_MIN = 6, + PROTOCOL_MOH_DEMO = 6, PROTOCOL_MOH = 8, PROTOCOL_MOHTA_MIN = 15, + PROTOCOL_MOHTA_DEMO = 16, PROTOCOL_MOHTA = 17, } protocol_e; diff --git a/code/qcommon/qcommon.h b/code/qcommon/qcommon.h index 3d349e61..5cc94fe0 100644 --- a/code/qcommon/qcommon.h +++ b/code/qcommon/qcommon.h @@ -1056,6 +1056,10 @@ extern cvar_t* con_autochat; #endif extern cvar_t* com_target_version; extern cvar_t* com_target_game; +extern cvar_t* com_target_demo; + +extern int protocol_version_demo; +extern int protocol_version_full; // com_speeds times extern int time_game; diff --git a/code/server/sv_client.c b/code/server/sv_client.c index 31c42697..dce9288e 100644 --- a/code/server/sv_client.c +++ b/code/server/sv_client.c @@ -284,6 +284,28 @@ challenge_t* FindChallenge(netadr_t from, qboolean connecting) { return challenge; } +/* +================== +SV_IsDemoClient + +Returns whether or not the client is using the demo version of the game +================== +*/ + +qboolean SV_IsDemoClient(const char *userinfo) +{ + int version; + + if (protocol_version_demo == protocol_version_full) { + // Older versions don't check for network demo + return qfalse; + } + + version = atoi(Info_ValueForKey(userinfo, "protocol")); + + return version == protocol_version_demo; +} + /* ================== SV_DirectConnect @@ -334,9 +356,20 @@ void SV_DirectConnect( netadr_t from ) { Com_DPrintf(" rejected connect - only Breakthrough clients allowed.\n"); return; } - } + } - version = atoi(Info_ValueForKey(userinfo, "protocol")); + version = atoi(Info_ValueForKey(userinfo, "protocol")); + + if (!com_target_demo->integer && SV_IsDemoClient(userinfo)) { + SV_NET_OutOfBandPrint(&svs.netprofile, from, "print\nThe Multiplayer Demo can not connect to full version games.\n"); + Com_DPrintf(" rejected connect from version %i\n", version); + return; + } + + if (com_target_demo->integer && version == protocol_version_full) { + // Make sure to make the full game compatible with the demo game protocol + version = com_protocol->integer; + } #ifdef LEGACY_PROTOCOL if(version > 0 && com_legacyprotocol->integer == version) diff --git a/code/server/sv_main.c b/code/server/sv_main.c index bd3893a6..a8fd9123 100644 --- a/code/server/sv_main.c +++ b/code/server/sv_main.c @@ -615,8 +615,15 @@ void SVC_Info( netadr_t from ) { Info_SetValueForKey( infostring, "game", gamedir ); } - Info_SetValueForKey(infostring, "gamever", com_target_version->string); - Info_SetValueForKey(infostring, "serverType", va("%i", com_target_game->integer)); + if (!com_target_demo->integer || com_target_game->integer <= TG_MOH) { + Info_SetValueForKey(infostring, "gamever", com_target_version->string); + } else { + Info_SetValueForKey(infostring, "gamever", va("d%s", com_target_version->string)); + } + + if (com_target_game->integer >= TG_MOHTT) { + Info_SetValueForKey(infostring, "serverType", va("%i", com_target_game->integer)); + } SV_NET_OutOfBandPrint( &svs.netprofile, from, "infoResponse\n%s", infostring ); } diff --git a/docs/getting_started_installation.md b/docs/getting_started_installation.md index 2a45f8a4..1c28354f 100644 --- a/docs/getting_started_installation.md +++ b/docs/getting_started_installation.md @@ -14,7 +14,7 @@ Ensure that you download the binaries compatible with your platform in the [rele ## Requirements - A valid MOH:AA installation, a MOH:AA Warchest copy can be acquired from GOG [here](https://www.gog.com/en/game/medal_of_honor_allied_assault_war_chest). - - [Extracting GOG Installer on Linux and macOS](#extracting-gog-setup-file-on-linux-and-macos) + - [Extracting GOG Installer on Linux and macOS](#extracting-gog-setup-file-on-linux-and-macos). The demo version can also be used. - On Windows, Microsoft Visual C++ 2015/2017/2019/2022 Redistributable from https://learn.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist?view=msvc-170 may be required. ## System requirements diff --git a/docs/getting_started_running.md b/docs/getting_started_running.md index 44344c33..4e5d1c92 100644 --- a/docs/getting_started_running.md +++ b/docs/getting_started_running.md @@ -19,6 +19,10 @@ On Windows, a shortcut can be created to the `openmohaa` executable, with the co You can now start a local OpenMOHAA server or play on a server. +### Playing with the downloadable demo + +The argument `+set com_target_demo 1` must be appended to command-line to play the game/host a server using demo assets: Allied Assault, Spearhead and Breakthrough demo are supported. + ### From the launchers For simplicity, there are 3 launchers for the standalone game: