Add support for the demo version of the game

This allows the demo version of the game to be used, both for playing on demo servers, or for hosting a demo server
This commit is contained in:
smallmodel 2024-11-12 23:09:37 +01:00
parent b0a683c188
commit ab84a6ea58
No known key found for this signature in database
GPG key ID: 9F2D623CEDF08512
11 changed files with 198 additions and 35 deletions

View file

@ -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<MAX_PINGREQUESTS; i++)
{

View file

@ -4986,6 +4986,20 @@ void UI_HideStatistics_f()
statsUpdater.CancelEventsOfType(EV_StatsUpdater_UpdateStats);
}
/*
====================
UI_SalesScreen_f
====================
*/
void UI_SalesScreen_f()
{
if (random() > 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;

View file

@ -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);

View file

@ -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) {
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() {
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) {

View file

@ -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:
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:
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);
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
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);
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

View file

@ -39,6 +39,7 @@ extern "C" {
#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"
@ -49,6 +50,7 @@ extern "C" {
#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"
@ -60,6 +62,8 @@ extern "C" {
#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_VERSION_MOHTT_DEMO "0.31"
#define TARGET_GAME_PROTOCOL_MIN_MOHTT 16
#define TARGET_GAME_PROTOCOL_MOHTT 17
#define TARGET_GAME_NAME_MOHTT "mohaab"
@ -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;

View file

@ -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;

View file

@ -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
@ -338,6 +360,17 @@ void SV_DirectConnect( netadr_t from ) {
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)
compat = qtrue;

View file

@ -615,8 +615,15 @@ void SVC_Info( netadr_t from ) {
Info_SetValueForKey( infostring, "game", gamedir );
}
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 );
}

View file

@ -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

View file

@ -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: