mirror of
https://github.com/UberGames/RPG-X2.git
synced 2024-11-24 21:32:36 +00:00
770 lines
15 KiB
C
770 lines
15 KiB
C
// Copyright (C) 1999-2000 Id Software, Inc.
|
|
//
|
|
//
|
|
// gameinfo.c
|
|
//
|
|
|
|
#include "ui_local.h"
|
|
|
|
|
|
//
|
|
// arena and bot info
|
|
//
|
|
|
|
#define DIRLIST_SIZE 16384
|
|
#define POOLSIZE 48 * DIRLIST_SIZE
|
|
|
|
//#define POOLSIZE 128 * 1024
|
|
|
|
int ui_numBots;
|
|
static char *ui_botInfos[MAX_BOTS];
|
|
|
|
static int ui_numArenas;
|
|
static char *ui_arenaInfos[MAX_ARENAS];
|
|
|
|
static int ui_numSinglePlayerArenas;
|
|
static int ui_numSpecialSinglePlayerArenas;
|
|
|
|
static char dirlist[DIRLIST_SIZE];
|
|
|
|
static char memoryPool[POOLSIZE];
|
|
static int allocPoint, outOfMemory;
|
|
|
|
|
|
/*
|
|
===============
|
|
UI_Alloc
|
|
===============
|
|
*/
|
|
void *UI_Alloc( int size ) {
|
|
char *p;
|
|
|
|
if ( allocPoint + size > POOLSIZE ) {
|
|
outOfMemory = qtrue;
|
|
return NULL;
|
|
}
|
|
|
|
p = &memoryPool[allocPoint];
|
|
|
|
allocPoint += ( size + 31 ) & ~31;
|
|
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
UI_InitMemory
|
|
===============
|
|
*/
|
|
void UI_InitMemory( void ) {
|
|
allocPoint = 0;
|
|
outOfMemory = qfalse;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
UI_ParseInfos
|
|
===============
|
|
*/
|
|
int UI_ParseInfos( char *buf, int max, char *infos[] ) {
|
|
char *token;
|
|
int count;
|
|
char key[MAX_TOKEN_CHARS];
|
|
char info[MAX_INFO_STRING];
|
|
|
|
count = 0;
|
|
|
|
while ( 1 ) {
|
|
token = COM_Parse( &buf );
|
|
if ( !token[0] ) {
|
|
break;
|
|
}
|
|
if ( strcmp( token, "{" ) ) {
|
|
Com_Printf( "Missing { in info file\n" );
|
|
break;
|
|
}
|
|
|
|
if ( count == max ) {
|
|
Com_Printf( "Max infos exceeded\n" );
|
|
break;
|
|
}
|
|
|
|
info[0] = '\0';
|
|
while ( 1 ) {
|
|
token = COM_ParseExt( &buf, qtrue );
|
|
if ( !token[0] ) {
|
|
Com_Printf( "Unexpected end of info file\n" );
|
|
break;
|
|
}
|
|
if ( !strcmp( token, "}" ) ) {
|
|
break;
|
|
}
|
|
Q_strncpyz( key, token, sizeof( key ) );
|
|
|
|
token = COM_ParseExt( &buf, qfalse );
|
|
if ( !token[0] ) {
|
|
strcpy( token, "<NULL>" );
|
|
}
|
|
Info_SetValueForKey( info, key, token );
|
|
}
|
|
//NOTE: extra space for arena number
|
|
infos[count] = UI_Alloc(strlen(info) + strlen("\\num\\") + strlen(va("%d", MAX_ARENAS)) + 1);
|
|
if (infos[count]) {
|
|
strcpy(infos[count], info);
|
|
count++;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
UI_LoadArenasFromFile
|
|
===============
|
|
*/
|
|
static void UI_LoadArenasFromFile( char *filename ) {
|
|
int len;
|
|
fileHandle_t f;
|
|
char buf[MAX_ARENAS_TEXT];
|
|
|
|
len = trap_FS_FOpenFile( filename, &f, FS_READ );
|
|
if ( !f ) {
|
|
trap_Print( va( S_COLOR_RED "file not found: %s\n", filename ) );
|
|
return;
|
|
}
|
|
if ( len >= MAX_ARENAS_TEXT ) {
|
|
trap_Print( va( S_COLOR_RED "file too large: %s is %i, max allowed is %i", filename, len, MAX_ARENAS_TEXT ) );
|
|
trap_FS_FCloseFile( f );
|
|
return;
|
|
}
|
|
|
|
trap_FS_Read( buf, len, f );
|
|
buf[len] = 0;
|
|
trap_FS_FCloseFile( f );
|
|
|
|
ui_numArenas += UI_ParseInfos( buf, MAX_ARENAS - ui_numArenas, &ui_arenaInfos[ui_numArenas] );
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
UI_LoadArenas
|
|
===============
|
|
*/
|
|
static void UI_LoadArenas( void ) {
|
|
int numdirs;
|
|
vmCvar_t arenasFile;
|
|
char filename[128];
|
|
char* dirptr;
|
|
int i, n;
|
|
int dirlen;
|
|
char *type;
|
|
char *tag;
|
|
int singlePlayerNum, specialNum, otherNum;
|
|
|
|
ui_numArenas = 0;
|
|
|
|
trap_Cvar_Register( &arenasFile, "g_arenasFile", "", CVAR_INIT|CVAR_ROM );
|
|
if( *arenasFile.string )
|
|
{
|
|
UI_LoadArenasFromFile(arenasFile.string);
|
|
}
|
|
else
|
|
{
|
|
UI_LoadArenasFromFile("scripts/arenas.txt");
|
|
}
|
|
|
|
// get all arenas from .arena files
|
|
numdirs = trap_FS_GetFileList("scripts", ".arena", dirlist, DIRLIST_SIZE );
|
|
dirptr = dirlist;
|
|
for (i = 0; i < numdirs && ui_numArenas < 1024; i++, dirptr += dirlen+1)
|
|
{
|
|
dirlen = strlen(dirptr);
|
|
strcpy(filename, "scripts/");
|
|
strcat(filename, dirptr);
|
|
UI_LoadArenasFromFile(filename);
|
|
}
|
|
trap_Print( va( "%i arenas parsed\n", ui_numArenas ) );
|
|
if (outOfMemory) trap_Print(S_COLOR_YELLOW"WARNING: not enough memory in pool to load all arenas\n");
|
|
|
|
// set initial numbers
|
|
for( n = 0; n < ui_numArenas; n++ ) {
|
|
Info_SetValueForKey( ui_arenaInfos[n], "num", va( "%i", n ) );
|
|
}
|
|
|
|
// go through and count single players levels
|
|
ui_numSinglePlayerArenas = 0;
|
|
ui_numSpecialSinglePlayerArenas = 0;
|
|
for( n = 0; n < ui_numArenas; n++ ) {
|
|
// determine type
|
|
type = Info_ValueForKey( ui_arenaInfos[n], "type" );
|
|
|
|
// if no type specified, it will be treated as "ffa"
|
|
if( !*type ) {
|
|
continue;
|
|
}
|
|
|
|
if( strstr( type, "single" ) ) {
|
|
// check for special single player arenas (training, final)
|
|
tag = Info_ValueForKey( ui_arenaInfos[n], "special" );
|
|
if( *tag ) {
|
|
ui_numSpecialSinglePlayerArenas++;
|
|
continue;
|
|
}
|
|
|
|
ui_numSinglePlayerArenas++;
|
|
}
|
|
}
|
|
|
|
// n = ui_numSinglePlayerArenas % ARENAS_PER_TIER;
|
|
// if( n != 0 ) {
|
|
// ui_numSinglePlayerArenas -= n;
|
|
// trap_Print( va( "%i arenas ignored to make count divisible by %i\n", n, ARENAS_PER_TIER ) );
|
|
// }
|
|
|
|
// go through once more and assign number to the levels
|
|
singlePlayerNum = 0;
|
|
specialNum = singlePlayerNum + ui_numSinglePlayerArenas;
|
|
otherNum = specialNum + ui_numSpecialSinglePlayerArenas;
|
|
for( n = 0; n < ui_numArenas; n++ ) {
|
|
// determine type
|
|
type = Info_ValueForKey( ui_arenaInfos[n], "type" );
|
|
|
|
// if no type specified, it will be treated as "ffa"
|
|
if( *type ) {
|
|
if( strstr( type, "single" ) ) {
|
|
// check for special single player arenas (training, final)
|
|
tag = Info_ValueForKey( ui_arenaInfos[n], "special" );
|
|
if( *tag ) {
|
|
Info_SetValueForKey( ui_arenaInfos[n], "num", va( "%i", specialNum++ ) );
|
|
continue;
|
|
}
|
|
|
|
Info_SetValueForKey( ui_arenaInfos[n], "num", va( "%i", singlePlayerNum++ ) );
|
|
continue;
|
|
}
|
|
}
|
|
|
|
Info_SetValueForKey( ui_arenaInfos[n], "num", va( "%i", otherNum++ ) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
UI_GetArenaInfoByNumber
|
|
===============
|
|
*/
|
|
const char *UI_GetArenaInfoByNumber( int num ) {
|
|
int n;
|
|
char *value;
|
|
|
|
if( num < 0 || num >= ui_numArenas ) {
|
|
trap_Print( va( S_COLOR_RED "Invalid arena number: %i\n", num ) );
|
|
return NULL;
|
|
}
|
|
|
|
for( n = 0; n < ui_numArenas; n++ ) {
|
|
value = Info_ValueForKey( ui_arenaInfos[n], "num" );
|
|
if( *value && atoi(value) == num ) {
|
|
return ui_arenaInfos[n];
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
UI_GetArenaInfoByMap
|
|
===============
|
|
*/
|
|
const char *UI_GetArenaInfoByMap( const char *map ) {
|
|
int n;
|
|
|
|
for( n = 0; n < ui_numArenas; n++ ) {
|
|
if( Q_stricmp( Info_ValueForKey( ui_arenaInfos[n], "map" ), map ) == 0 ) {
|
|
return ui_arenaInfos[n];
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
UI_GetSpecialArenaInfo
|
|
===============
|
|
*/
|
|
const char *UI_GetSpecialArenaInfo( const char *tag ) {
|
|
int n;
|
|
|
|
for( n = 0; n < ui_numArenas; n++ ) {
|
|
if( Q_stricmp( Info_ValueForKey( ui_arenaInfos[n], "special" ), tag ) == 0 ) {
|
|
return ui_arenaInfos[n];
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
UI_LoadBotsFromFile
|
|
===============
|
|
*/
|
|
static void UI_LoadBotsFromFile( char *filename ) {
|
|
int len;
|
|
fileHandle_t f;
|
|
char buf[MAX_BOTS_TEXT];
|
|
|
|
len = trap_FS_FOpenFile( filename, &f, FS_READ );
|
|
if ( !f ) {
|
|
trap_Print( va( S_COLOR_RED "file not found: %s\n", filename ) );
|
|
return;
|
|
}
|
|
if ( len >= MAX_BOTS_TEXT ) {
|
|
trap_Print( va( S_COLOR_RED "file too large: %s is %i, max allowed is %i", filename, len, MAX_BOTS_TEXT ) );
|
|
trap_FS_FCloseFile( f );
|
|
return;
|
|
}
|
|
|
|
trap_FS_Read( buf, len, f );
|
|
buf[len] = 0;
|
|
trap_FS_FCloseFile( f );
|
|
|
|
ui_numBots += UI_ParseInfos( buf, MAX_BOTS - ui_numBots, &ui_botInfos[ui_numBots] );
|
|
if (outOfMemory) trap_Print(S_COLOR_YELLOW"WARNING: not enough memory in pool to load all bots\n");
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
UI_LoadBots
|
|
===============
|
|
*/
|
|
static void UI_LoadBots( void ) {
|
|
vmCvar_t botsFile;
|
|
int numdirs;
|
|
char filename[128];
|
|
char* dirptr;
|
|
int i;
|
|
int dirlen;
|
|
|
|
ui_numBots = 0;
|
|
|
|
trap_Cvar_Register( &botsFile, "g_botsFile", "", CVAR_INIT|CVAR_ROM );
|
|
if( *botsFile.string ) {
|
|
UI_LoadBotsFromFile(botsFile.string);
|
|
}
|
|
else {
|
|
UI_LoadBotsFromFile("scripts/bots.txt");
|
|
}
|
|
|
|
// get all bots from .bot files
|
|
numdirs = trap_FS_GetFileList("scripts", ".bot", dirlist, DIRLIST_SIZE );
|
|
dirptr = dirlist;
|
|
for (i = 0; i < numdirs; i++, dirptr += dirlen+1)
|
|
{
|
|
dirlen = strlen(dirptr);
|
|
strcpy(filename, "scripts/");
|
|
strcat(filename, dirptr);
|
|
UI_LoadBotsFromFile(filename);
|
|
}
|
|
trap_Print( va( "%i bots parsed\n", ui_numBots ) );
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
UI_GetBotInfoByNumber
|
|
===============
|
|
*/
|
|
char *UI_GetBotInfoByNumber( int num ) {
|
|
if( num < 0 || num >= ui_numBots ) {
|
|
trap_Print( va( S_COLOR_RED "Invalid bot number: %i\n", num ) );
|
|
return NULL;
|
|
}
|
|
return ui_botInfos[num];
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
UI_GetBotInfoByName
|
|
===============
|
|
*/
|
|
char *UI_GetBotInfoByName( const char *name ) {
|
|
int n;
|
|
char *value;
|
|
|
|
for ( n = 0; n < ui_numBots ; n++ ) {
|
|
value = Info_ValueForKey( ui_botInfos[n], "name" );
|
|
if ( !Q_stricmp( value, name ) ) {
|
|
return ui_botInfos[n];
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//
|
|
// single player game info
|
|
//
|
|
|
|
/*
|
|
===============
|
|
UI_GetBestScore
|
|
|
|
Returns the player's best finish on a given level, 0 if the have not played the level
|
|
===============
|
|
*/
|
|
void UI_GetBestScore( int level, int *score, int *skill ) {
|
|
int n;
|
|
int skillScore;
|
|
int bestScore;
|
|
int bestScoreSkill;
|
|
char arenaKey[16];
|
|
char scores[MAX_INFO_VALUE];
|
|
|
|
if( !score || !skill ) {
|
|
return;
|
|
}
|
|
|
|
if( level < 0 || level > ui_numArenas ) {
|
|
return;
|
|
}
|
|
|
|
bestScore = 0;
|
|
bestScoreSkill = 0;
|
|
|
|
for( n = 1; n <= 5; n++ ) {
|
|
trap_Cvar_VariableStringBuffer( va( "g_spScores%i", n ), scores, MAX_INFO_VALUE );
|
|
|
|
Com_sprintf( arenaKey, sizeof( arenaKey ), "l%i", level );
|
|
skillScore = atoi( Info_ValueForKey( scores, arenaKey ) );
|
|
|
|
if( skillScore < 1 || skillScore > 8 ) {
|
|
continue;
|
|
}
|
|
|
|
if( !bestScore || skillScore <= bestScore ) {
|
|
bestScore = skillScore;
|
|
bestScoreSkill = n;
|
|
}
|
|
}
|
|
|
|
*score = bestScore;
|
|
*skill = bestScoreSkill;
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
UI_SetBestScore
|
|
|
|
Set the player's best finish for a level
|
|
===============
|
|
*/
|
|
void UI_SetBestScore( int level, int score ) {
|
|
int skill;
|
|
int oldScore;
|
|
char arenaKey[16];
|
|
char scores[MAX_INFO_VALUE];
|
|
|
|
// validate score
|
|
if( score < 1 || score > 8 ) {
|
|
return;
|
|
}
|
|
|
|
// validate skill
|
|
skill = (int)trap_Cvar_VariableValue( "g_spSkill" );
|
|
if( skill < 1 || skill > 5 ) {
|
|
return;
|
|
}
|
|
|
|
// get scores
|
|
trap_Cvar_VariableStringBuffer( va( "g_spScores%i", skill ), scores, MAX_INFO_VALUE );
|
|
|
|
// see if this is better
|
|
Com_sprintf( arenaKey, sizeof( arenaKey ), "l%i", level );
|
|
oldScore = atoi( Info_ValueForKey( scores, arenaKey ) );
|
|
if( oldScore && oldScore <= score ) {
|
|
return;
|
|
}
|
|
|
|
// update scores
|
|
Info_SetValueForKey( scores, arenaKey, va( "%i", score ) );
|
|
trap_Cvar_Set( va( "g_spScores%i", skill ), scores );
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
UI_LogAwardData
|
|
===============
|
|
*/
|
|
void UI_LogAwardData( int award, int data ) {
|
|
char key[16];
|
|
char awardData[MAX_INFO_VALUE];
|
|
int oldValue;
|
|
|
|
if( data == 0 ) {
|
|
return;
|
|
}
|
|
|
|
if( award >= AWARD_MAX ) {
|
|
trap_Print( va( S_COLOR_RED "Bad award %i in UI_LogAwardData\n", award ) );
|
|
return;
|
|
}
|
|
|
|
trap_Cvar_VariableStringBuffer( "g_spAwards", awardData, sizeof(awardData) );
|
|
|
|
Com_sprintf( key, sizeof(key), "a%i", award );
|
|
oldValue = atoi( Info_ValueForKey( awardData, key ) );
|
|
|
|
Info_SetValueForKey( awardData, key, va( "%i", oldValue + data ) );
|
|
trap_Cvar_Set( "g_spAwards", awardData );
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
UI_GetAwardLevel
|
|
===============
|
|
*/
|
|
int UI_GetAwardLevel( int award ) {
|
|
char key[16];
|
|
char awardData[MAX_INFO_VALUE];
|
|
|
|
trap_Cvar_VariableStringBuffer( "g_spAwards", awardData, sizeof(awardData) );
|
|
|
|
Com_sprintf( key, sizeof(key), "a%i", award );
|
|
return atoi( Info_ValueForKey( awardData, key ) );
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
UI_TierCompleted
|
|
===============
|
|
*/
|
|
int UI_TierCompleted( int levelWon ) {
|
|
int level;
|
|
int n;
|
|
int tier;
|
|
int score;
|
|
int skill;
|
|
int maxarenas;
|
|
const char *info;
|
|
|
|
tier = levelWon / ARENAS_PER_TIER;
|
|
level = tier * ARENAS_PER_TIER;
|
|
|
|
if( tier == UI_GetNumSPTiers() ) {
|
|
info = UI_GetSpecialArenaInfo( "training" );
|
|
if( levelWon == atoi( Info_ValueForKey( info, "num" ) ) ) {
|
|
return 0;
|
|
}
|
|
info = UI_GetSpecialArenaInfo( "final" );
|
|
if( !info || levelWon == atoi( Info_ValueForKey( info, "num" ) ) ) {
|
|
return tier + 1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
if (uis.demoversion) {
|
|
maxarenas = 2;
|
|
} else {
|
|
maxarenas = ARENAS_PER_TIER;
|
|
}
|
|
for( n = 0; n < maxarenas; n++, level++ ) {
|
|
UI_GetBestScore( level, &score, &skill );
|
|
if ( score != 1 ) {
|
|
return -1;
|
|
}
|
|
}
|
|
return tier + 1;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
===============
|
|
UI_GetCurrentGame
|
|
|
|
Returns the next level the player has not won
|
|
===============
|
|
*/
|
|
int UI_GetCurrentGame( int curLevel ) {
|
|
int level;
|
|
int rank;
|
|
int skill;
|
|
const char *info;
|
|
|
|
info = UI_GetSpecialArenaInfo( "training" );
|
|
if( info ) {
|
|
level = atoi( Info_ValueForKey( info, "num" ) );
|
|
UI_GetBestScore( level, &rank, &skill );
|
|
if ( !rank || rank > 1 ) {
|
|
return level;
|
|
}
|
|
}
|
|
|
|
// kef 7/31/00 -- we think we'd like to just send you to the next map, not the first map you haven't won
|
|
|
|
if (curLevel == -1)
|
|
{
|
|
// -1 is a special value, the meaning of which is not currently clear to me
|
|
for( level = 0; level < ui_numSinglePlayerArenas; level++ ) {
|
|
UI_GetBestScore( level, &rank, &skill );
|
|
if ( !rank || rank > 1 )
|
|
{
|
|
return level;
|
|
}
|
|
}
|
|
info = UI_GetSpecialArenaInfo( "final" );
|
|
if( !info ) {
|
|
return -1;
|
|
}
|
|
return atoi( Info_ValueForKey( info, "num" ) );
|
|
}
|
|
else if ((curLevel >= 0) && (curLevel < (ui_numSinglePlayerArenas-1)))
|
|
{
|
|
// go to next map
|
|
return curLevel+1;
|
|
}
|
|
else if (curLevel == (ui_numSinglePlayerArenas-1))
|
|
{
|
|
// finished final map...back to the beginning
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
// bogus value for curLevel
|
|
info = UI_GetSpecialArenaInfo( "final" );
|
|
if( !info ) {
|
|
return -1;
|
|
}
|
|
return atoi( Info_ValueForKey( info, "num" ) );
|
|
}
|
|
|
|
/*
|
|
if ((curLevel != -1) && (curLevel == (ui_numSinglePlayerArenas-1)))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
for( level = 0; level < ui_numSinglePlayerArenas; level++ ) {
|
|
UI_GetBestScore( level, &rank, &skill );
|
|
if ( !rank || rank > 1 )
|
|
{
|
|
if (curLevel != -1)
|
|
{
|
|
if (level > curLevel)
|
|
{
|
|
return level;
|
|
}
|
|
continue;
|
|
}
|
|
return level;
|
|
}
|
|
}
|
|
|
|
info = UI_GetSpecialArenaInfo( "final" );
|
|
if( !info ) {
|
|
return -1;
|
|
}
|
|
return atoi( Info_ValueForKey( info, "num" ) );
|
|
*/
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
UI_NewGame
|
|
|
|
Clears the scores and sets the difficutly level
|
|
===============
|
|
*/
|
|
void UI_NewGame( void ) {
|
|
trap_Cvar_Set( "g_spScores1", "" );
|
|
trap_Cvar_Set( "g_spScores2", "" );
|
|
trap_Cvar_Set( "g_spScores3", "" );
|
|
trap_Cvar_Set( "g_spScores4", "" );
|
|
trap_Cvar_Set( "g_spScores5", "" );
|
|
trap_Cvar_Set( "g_spAwards", "" );
|
|
trap_Cvar_Set( "g_spVideos", "" );
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
UI_GetNumArenas
|
|
===============
|
|
*/
|
|
int UI_GetNumArenas( void ) {
|
|
return ui_numArenas;
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
UI_GetNumSPArenas
|
|
===============
|
|
*/
|
|
int UI_GetNumSPArenas( void ) {
|
|
return ui_numSinglePlayerArenas;
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
UI_GetNumSPTiers
|
|
===============
|
|
*/
|
|
int UI_GetNumSPTiers( void )
|
|
{
|
|
int remainder;
|
|
|
|
remainder = ui_numSinglePlayerArenas % ARENAS_PER_TIER;
|
|
|
|
if (remainder)
|
|
{
|
|
remainder = 1;
|
|
}
|
|
|
|
return ((ui_numSinglePlayerArenas / ARENAS_PER_TIER) + remainder);
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
UI_GetNumBots
|
|
===============
|
|
*/
|
|
int UI_GetNumBots( void ) {
|
|
return ui_numBots;
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
UI_InitGameinfo
|
|
===============
|
|
*/
|
|
void UI_InitGameinfo( void ) {
|
|
|
|
UI_InitMemory();
|
|
UI_LoadArenas();
|
|
UI_LoadBots();
|
|
|
|
if( (trap_Cvar_VariableValue( "fs_restrict" )) || (ui_numSpecialSinglePlayerArenas == 0 && ui_numSinglePlayerArenas == 2) ) {
|
|
uis.demoversion = qtrue;
|
|
}
|
|
else {
|
|
uis.demoversion = qfalse;
|
|
}
|
|
}
|