// Note that the pmenu entries are duplicated // this is so that a static set of pmenu entries can be used // for multiple clients and changed without interference // note that arg will be freed when the menu is closed, it must be allocated memory pmenuhnd_t *PMenu_Open(edict_t *ent, pmenu_t *entries, int cur, int num, void *arg) { pmenuhnd_t *hnd; pmenu_t *p; int i; if (!ent->client) return NULL; if (ent->client->menu) { gi.dprintf("warning, ent already has a menu\n"); PMenu_Close(ent); } hnd = (pmenuhnd_t*)G_Malloc(sizeof(*hnd)); hnd->arg = arg; hnd->entries = (struct pmenu_s*)G_Malloc(sizeof(pmenu_t) * num); memcpy(hnd->entries, entries, sizeof(pmenu_t) * num); // duplicate the strings since they may be from static memory for (i = 0; i < num; i++) if (entries[i].text) hnd->entries[i].text = G_CopyString(entries[i].text); hnd->num = num; if (cur < 0 || !entries[cur].SelectFunc) { for (i = 0, p = entries; i < num; i++, p++) if (p->SelectFunc) break; } else i = cur; if (i >= num) hnd->cur = -1; else hnd->cur = i; ent->client->showscores = true; ent->client->inmenu = true; ent->client->menu = hnd; PMenu_Update(ent); gi.unicast (ent, true); return hnd; // Knightmare added }
/* * G_SanitizeUserString */ static int G_SanitizeUserString( char *string, size_t size ) { static char *colorless = NULL; static size_t colorless_size = 0; int i, c_ascii; // life is hard, UTF-8 will have to go strip_highchars( string ); COM_SanitizeColorString( va( "%s", string ), string, size, -1, COLOR_WHITE ); Q_trim( string ); if( colorless_size < strlen( string ) + 1 ) { colorless_size = strlen( string ) + 1; G_Free( colorless ); colorless = ( char * )G_Malloc( colorless_size ); } Q_strncpyz( colorless, COM_RemoveColorTokens( string ), colorless_size ); // require at least one non-whitespace ascii char in the string // (this will upset people who would like to have a name entirely in a non-latin // script, but it makes damn sure you can't get an empty name by exploiting some // utf-8 decoder quirk) c_ascii = 0; for( i = 0; colorless[i]; i++ ) if( colorless[i] > 32 && colorless[i] < 127 ) c_ascii++; return c_ascii; }
void CheckChasecam_Viewent (edict_t *ent) { // Added by WarZone - Begin gclient_t *cl; if (!ent->client->oldplayer->client) { cl = (gclient_t *) G_Malloc(sizeof(gclient_t)); ent->client->oldplayer->client = cl; } // Added by WarZone - End // if ((ent->client->chasetoggle == 1) && (ent->client->oldplayer)) if ((ent->client->chasetoggle == 1) && (ent->client->oldplayer)) if ((ent->client->chaseactive == 1) && (ent->client->oldplayer)) { ent->client->oldplayer->s.frame = ent->s.frame; /* Copy the origin, the speed, and the model angle, NOT * literal angle to the display entity */ VectorCopy (ent->s.origin, ent->client->oldplayer->s.origin); VectorCopy (ent->velocity, ent->client->oldplayer->velocity); VectorCopy (ent->s.angles, ent->client->oldplayer->s.angles); /* Make sure we are using the same model + skin as selected, * as well as the weapon model the player model is holding. * For customized deathmatch weapon displaying, you can * use the modelindex2 for different weapon changing, as you * can read in forthcoming tutorials */ ent->client->oldplayer->s.modelindex = ent->s.modelindex; ent->client->oldplayer->s.modelindex2 = ent->s.modelindex2; ent->client->oldplayer->s.modelindex3 = ent->s.modelindex3; ent->client->oldplayer->s = ent->s; gi.linkentity (ent->client->oldplayer); } }
AiBaseTeamBrain *AiBaseTeamBrain::InstantiateTeamBrain( int team, const char *gametype ) { // Delegate construction to AiSquadBasedTeamBrain if( GS_TeamBasedGametype() && !GS_InvidualGameType() ) { return AiSquadBasedTeamBrain::InstantiateTeamBrain( team, gametype ); } void *mem = G_Malloc( sizeof( AiBaseTeamBrain ) ); return new(mem)AiBaseTeamBrain( team ); }
//========================================== // G_SpawnAI // allocate ai_handle_t for this entity //========================================== void G_SpawnAI( edict_t *ent ) { if( !ent->ai ) { ent->ai = ( ai_handle_t * )G_Malloc( sizeof( ai_handle_t ) ); } else { memset( &ent->ai, 0, sizeof( ai_handle_t ) ); } if( ent->r.svflags & SVF_FAKECLIENT ) ent->ai->type = AI_ISBOT; else ent->ai->type = AI_ISMONSTER; }
static clientRating_t *g_ratingAlloc( const char *gametype, float rating, float deviation, int uuid ) { clientRating_t *cr; cr = (clientRating_t*)G_Malloc( sizeof(*cr) ); if( !cr ) return NULL; Q_strncpyz( cr->gametype, gametype, sizeof( cr->gametype ) - 1 ); cr->rating = rating; cr->deviation = deviation; cr->next = 0; cr->uuid = uuid; return cr; }
static void add_filter(ipaction_t action, unsigned mask, unsigned compare, unsigned duration, edict_t *ent) { ipfilter_t *ip; char *s; ip = G_Malloc(sizeof(*ip)); ip->action = action; ip->mask = mask; ip->compare = compare; ip->added = time(NULL); ip->duration = duration; if (ent) { strcpy(ip->adder, ent->client->pers.ip); s = strchr(ip->adder, ':'); if (s) { *s = 0; } } else { strcpy(ip->adder, "console"); } List_Append(&ipfilters, &ip->list); numipfilters++; }
void G_SpawnAI( edict_t *ent, float skillLevel ) { if (ent->ai) AI_FailWith("G_SpawnAI()", "Entity AI has been already initialized\n"); if (!(ent->r.svflags & SVF_FAKECLIENT)) AI_FailWith("G_SpawnAI()", "Only fake clients are supported\n"); size_t memSize = sizeof(ai_handle_t) + sizeof(Bot); size_t alignmentBytes = 0; if (sizeof(ai_handle_t) % 16) alignmentBytes = 16 - sizeof(ai_handle_t) % 16; memSize += alignmentBytes; char *mem = (char *)G_Malloc(memSize); ent->ai = (ai_handle_t *)mem; ent->ai->type = AI_ISBOT; char *botMem = mem + sizeof(ai_handle_t) + alignmentBytes; ent->ai->botRef = new(botMem) Bot(ent, skillLevel); ent->ai->aiRef = ent->ai->botRef; AiManager::Instance()->LinkAi(ent->ai); }
/* * SpawnEntities * * Creates a server's entity / program execution context by * parsing textual entity definitions out of an ent file. */ void G_InitLevel( char *mapname, char *entities, int entstrlen, unsigned int levelTime, unsigned int serverTime, unsigned int realTime ) { char *mapString = NULL; char name[MAX_CONFIGSTRING_CHARS]; int i; edict_t *ent; char *token; const gsitem_t *item; G_asGarbageCollect( true ); GT_asCallShutdown(); G_asCallMapExit(); G_asShutdownMapScript(); GT_asShutdownScript(); G_FreeCallvotes(); game.serverTime = serverTime; game.realtime = realTime; game.levelSpawnCount++; GClip_ClearWorld(); // clear areas links if( !entities ) G_Error( "G_SpawnLevel: NULL entities string\n" ); // make a copy of the raw entities string so it's not freed with the pool mapString = ( char * )G_Malloc( entstrlen + 1 ); memcpy( mapString, entities, entstrlen ); Q_strncpyz( name, mapname, sizeof( name ) ); // clear old data G_LevelInitPool( strlen( mapname ) + 1 + ( entstrlen + 1 ) * 2 + G_LEVELPOOL_BASE_SIZE ); G_StringPoolInit(); memset( &level, 0, sizeof( level_locals_t ) ); memset( &gs.gameState, 0, sizeof( gs.gameState ) ); level.spawnedTimeStamp = game.realtime; level.time = levelTime; level.gravity = g_gravity->value; // get the strings back Q_strncpyz( level.mapname, name, sizeof( level.mapname ) ); level.mapString = ( char * )G_LevelMalloc( entstrlen + 1 ); level.mapStrlen = entstrlen; memcpy( level.mapString, mapString, entstrlen ); G_Free( mapString ); mapString = NULL; // make a copy of the raw entities string for parsing level.map_parsed_ents = ( char * )G_LevelMalloc( entstrlen + 1 ); level.map_parsed_ents[0] = 0; if( !level.time ) memset( game.edicts, 0, game.maxentities * sizeof( game.edicts[0] ) ); else { G_FreeEdict( world ); for( i = gs.maxclients + 1; i < game.maxentities; i++ ) { if( game.edicts[i].r.inuse ) G_FreeEdict( game.edicts + i ); } } game.numentities = gs.maxclients + 1; // link client fields on player ents for( i = 0; i < gs.maxclients; i++ ) { game.edicts[i+1].s.number = i+1; game.edicts[i+1].r.client = &game.clients[i]; game.edicts[i+1].r.inuse = ( trap_GetClientState( i ) >= CS_CONNECTED ) ? true : false; memset( &game.clients[i].level, 0, sizeof( game.clients[0].level ) ); game.clients[i].level.timeStamp = level.time; } // initialize game subsystems trap_ConfigString( CS_MAPNAME, level.mapname ); trap_ConfigString( CS_SKYBOX, "" ); trap_ConfigString( CS_AUDIOTRACK, "" ); trap_ConfigString( CS_STATNUMS, va( "%i %i %i", STAT_SCORE, STAT_HEALTH, STAT_LAST_KILLER ) ); trap_ConfigString( CS_POWERUPEFFECTS, va( "%i %i %i %i", EF_QUAD, EF_SHELL, EF_CARRIER, EF_REGEN ) ); trap_ConfigString( CS_SCB_PLAYERTAB_LAYOUT, "" ); trap_ConfigString( CS_SCB_PLAYERTAB_TITLES, "" ); trap_ConfigString( CS_MATCHNAME, "" ); trap_ConfigString( CS_MATCHSCORE, "" ); // reset map messages for( i = 0; i < MAX_HELPMESSAGES; i++ ) { trap_ConfigString( CS_HELPMESSAGES + i, "" ); } G_InitGameCommands(); G_MapLocations_Init(); G_CallVotes_Init(); G_SpawnQueue_Init(); G_Teams_Init(); // load map script G_asLoadMapScript( level.mapname ); G_Gametype_Init(); // ch : this would be the location to "transfer ratings" G_PrecacheItems(); // set configstrings for items (gametype must be initialized) G_PrecacheMedia(); G_PrecacheGameCommands(); // adding commands after this point won't update them to the client AI_InitLevel(); // load navigation file of the current map // start spawning entities level.canSpawnEntities = true; G_InitBodyQueue(); // reserve some spots for dead player bodies entities = level.mapString; i = 0; ent = NULL; while( 1 ) { level.spawning_entity = NULL; // parse the opening brace token = COM_Parse( &entities ); if( !entities ) break; if( token[0] != '{' ) G_Error( "G_SpawnMapEntities: found %s when expecting {", token ); if( !ent ) { ent = world; G_InitEdict( world ); } else ent = G_Spawn(); ent->spawnString = entities; // keep track of string definition of this entity entities = ED_ParseEdict( entities, ent ); if( !ent->classname ) { i++; // racesow - introducing the freestyle map bug again in // order to make some freestyle maps work if( !level.gametype.freestyleMapFix ) G_FreeEdict( ent ); // !racesow G_FreeEdict( ent ); continue; } if( !G_CanSpawnEntity( ent ) ) { i++; G_FreeEdict( ent ); continue; } if( !G_CallSpawn( ent ) ) { i++; G_FreeEdict( ent ); continue; } // check whether an item is allowed to spawn if( ( item = ent->item ) ) { // not pickable items aren't spawnable if( item->flags & ITFLAG_PICKABLE ) { if( G_Gametype_CanSpawnItem( item ) ) { // override entity's classname with whatever item specifies ent->classname = item->classname; PrecacheItem( item ); continue; } } i++; G_FreeEdict( ent ); continue; } } G_FindTeams(); // is the parsing string sane? assert( (int)level.map_parsed_len < entstrlen ); level.map_parsed_ents[level.map_parsed_len] = 0; // make sure server got the edicts data trap_LocateEntities( game.edicts, sizeof( game.edicts[0] ), game.numentities, game.maxentities ); // items need brush model entities spawned before they are linked G_Items_FinishSpawningItems(); // // initialize game subsystems which require entities initialized // // call gametype specific GT_asCallSpawn(); // call map specific G_asCallMapInit(); AI_InitEntitiesData(); // always start in warmup match state and let the thinking code // revert it to wait state if empty ( so gametype based item masks are setup ) G_Match_LaunchState( MATCH_STATE_WARMUP ); G_asGarbageCollect( true ); // racesow RS_Init(); }
//========================================== // BOT_GetUnusedSkin // Retrieve a random unused skin & name //========================================== static bool BOT_GetUnusedSkin( char *bot_model, char *bot_skin, char *bot_name ) { bool inuse; int skinnumber; char *model, *skin; char scratch[MAX_INFO_STRING]; int i, freeskins; edict_t *ent; localbotskin_t *botskins; localbotskin_t *localbotskin; //count the unused skins, and make sure there is at least 1 of them skinnumber = freeskins = 0; while( LocalBotSkins[skinnumber] != NULL ) { inuse = false; for( i = 0, ent = game.edicts + 1; i < gs.maxclients; i++, ent++ ) { if( !( ent->r.svflags & SVF_FAKECLIENT ) || !ent->r.client ) continue; model = Info_ValueForKey( ent->r.client->userinfo, "model" ); skin = Info_ValueForKey( ent->r.client->userinfo, "skinl" ); if( model && skin ) { Q_snprintfz( scratch, sizeof( scratch ), "%s/%s", model, skin ); if( !Q_stricmp( scratch, LocalBotSkins[skinnumber] ) ) { inuse = true; break; } } } if( inuse == false ) freeskins++; skinnumber++; } //fallback to old method if( !freeskins ) return false; //assign tmp memory for storing unused skins botskins = (localbotskin_t *)G_Malloc( sizeof( localbotskin_t ) * freeskins ); //create a list of unused skins skinnumber = freeskins = 0; while( LocalBotSkins[skinnumber] != NULL ) { inuse = false; for( i = 0, ent = game.edicts + 1; i < gs.maxclients; i++, ent++ ) { if( !( ent->r.svflags & SVF_FAKECLIENT ) || !ent->r.client ) continue; model = Info_ValueForKey( ent->r.client->userinfo, "model" ); skin = Info_ValueForKey( ent->r.client->userinfo, "skinl" ); if( model && skin ) { Q_snprintfz( scratch, sizeof( scratch ), "%s/%s", model, skin ); if( !Q_stricmp( scratch, LocalBotSkins[skinnumber] ) ) { inuse = true; break; } } } //store and advance if( inuse == false ) { const char *p; localbotskin = botskins + freeskins; p = strchr( LocalBotSkins[skinnumber], '/' ); if( !strlen( p ) ) continue; p++; Q_strncpyz( localbotskin->bot_model, LocalBotSkins[skinnumber], strlen( LocalBotSkins[skinnumber] ) - strlen( p ) ); Q_strncpyz( localbotskin->bot_skin, p, sizeof( localbotskin->bot_skin ) ); Q_strncpyz( localbotskin->bot_name, LocalBotNames[skinnumber], sizeof( localbotskin->bot_name ) ); if( nav.debugMode ) Com_Printf( "Free skin: %i: %s %s\n", freeskins, localbotskin->bot_skin, localbotskin->bot_name ); freeskins++; } skinnumber++; } //now get a random skin from the list skinnumber = (int)( random()*freeskins ); localbotskin = botskins + skinnumber; Q_strncpyz( bot_model, localbotskin->bot_model, sizeof( localbotskin->bot_model ) ); Q_strncpyz( bot_skin, localbotskin->bot_skin, sizeof( localbotskin->bot_skin ) ); Q_strncpyz( bot_name, localbotskin->bot_name, sizeof( localbotskin->bot_name ) ); if( nav.debugMode ) Com_Printf( "Assigned bot character: %i: %s %s %s\n", skinnumber, bot_model, bot_skin, bot_name ); G_Free( botskins ); return true; }
/* * G_UpdateServerInfo * update the cvars which show the match state at server browsers */ static void G_UpdateServerInfo( void ) { // g_match_time if( GS_MatchState() <= MATCH_STATE_WARMUP ) { trap_Cvar_ForceSet( "g_match_time", "Warmup" ); } else if( GS_MatchState() == MATCH_STATE_COUNTDOWN ) { trap_Cvar_ForceSet( "g_match_time", "Countdown" ); } else if( GS_MatchState() == MATCH_STATE_PLAYTIME ) { // partly from G_GetMatchState char extra[MAX_INFO_VALUE]; int clocktime, timelimit, mins, secs; if( GS_MatchDuration() ) timelimit = ( ( GS_MatchDuration() ) * 0.001 ) / 60; else timelimit = 0; clocktime = (float)( game.serverTime - GS_MatchStartTime() ) * 0.001f; if( clocktime <= 0 ) { mins = 0; secs = 0; } else { mins = clocktime / 60; secs = clocktime - mins * 60; } extra[0] = 0; if( GS_MatchExtended() ) { if( timelimit ) Q_strncatz( extra, " overtime", sizeof( extra ) ); else Q_strncatz( extra, " suddendeath", sizeof( extra ) ); } if( GS_MatchPaused() ) Q_strncatz( extra, " (in timeout)", sizeof( extra ) ); if( timelimit ) trap_Cvar_ForceSet( "g_match_time", va( "%02i:%02i / %02i:00%s", mins, secs, timelimit, extra ) ); else trap_Cvar_ForceSet( "g_match_time", va( "%02i:%02i%s", mins, secs, extra ) ); } else { trap_Cvar_ForceSet( "g_match_time", "Finished" ); } // g_match_score if( GS_MatchState() >= MATCH_STATE_PLAYTIME && GS_TeamBasedGametype() ) { char score[MAX_INFO_STRING]; score[0] = 0; Q_strncatz( score, va( " %s: %i", GS_TeamName( TEAM_ALPHA ), teamlist[TEAM_ALPHA].stats.score ), sizeof( score ) ); Q_strncatz( score, va( " %s: %i", GS_TeamName( TEAM_BETA ), teamlist[TEAM_BETA].stats.score ), sizeof( score ) ); if( strlen( score ) >= MAX_INFO_VALUE ) { // prevent "invalid info cvar value" flooding score[0] = '\0'; } trap_Cvar_ForceSet( "g_match_score", score ); } else { trap_Cvar_ForceSet( "g_match_score", "" ); } // g_needpass if( password->modified ) { if( password->string && strlen( password->string ) ) { trap_Cvar_ForceSet( "g_needpass", "1" ); } else { trap_Cvar_ForceSet( "g_needpass", "0" ); } password->modified = false; } // g_gametypes_available if( g_votable_gametypes->modified || g_disable_vote_gametype->modified ) { if( g_disable_vote_gametype->integer || !g_votable_gametypes->string || !strlen( g_votable_gametypes->string ) ) { trap_Cvar_ForceSet( "g_gametypes_available", "" ); } else { char *votable; char *name; size_t len; int count; len = 0; for( count = 0; ( name = G_ListNameForPosition( g_gametypes_list->string, count, CHAR_GAMETYPE_SEPARATOR ) ) != NULL; count++ ) { if( G_Gametype_IsVotable( name ) ) len += strlen( name ) + 1; } len++; votable = ( char * )G_Malloc( len ); votable[0] = 0; for( count = 0; ( name = G_ListNameForPosition( g_gametypes_list->string, count, CHAR_GAMETYPE_SEPARATOR ) ) != NULL; count++ ) { if( G_Gametype_IsVotable( name ) ) { Q_strncatz( votable, name, len ); Q_strncatz( votable, " ", len ); } } //votable[ strlen( votable )-2 ] = 0; // remove the last space trap_Cvar_ForceSet( "g_gametypes_available", votable ); G_Free( votable ); } g_votable_gametypes->modified = false; g_disable_vote_gametype->modified = false; } if( GS_RaceGametype() ) { trap_Cvar_ForceSet( "g_race_gametype", "1" ); } else { trap_Cvar_ForceSet( "g_race_gametype", "0" ); } }
/* * G_UpdateMapRotation * * Reads current map rotation into internal list */ static void G_UpdateMapRotation( void ) { int count, i; bool thiswhitespace, lastwhitespace, found; char *p, *start; static const char *seps = " ,\n\r"; if( g_maplist->modified || !map_rotation_s || !map_rotation_p ) { g_maplist->modified = false; // reread the maplist if( map_rotation_s ) G_Free( map_rotation_s ); if( map_rotation_p ) G_Free( map_rotation_p ); map_rotation_s = G_CopyString( g_maplist->string ); map_rotation_p = NULL; map_rotation_current = -1; // reset the mapcounter too map_rotation_count = 0; // count the number of tokens p = map_rotation_s; count = 0; lastwhitespace = true; start = NULL; found = false; while( *p ) { thiswhitespace = ( strchr( seps, *p ) != NULL ) ? true : false; if( lastwhitespace && !thiswhitespace ) { start = p; count++; } else if( thiswhitespace && !lastwhitespace && !found && start ) { found = true; for( i = 0; start + i < p; i++ ) { if( tolower( start[i] ) != tolower( level.mapname[i] ) ) found = false; } if( found ) map_rotation_current = count - 1; } lastwhitespace = thiswhitespace; p++; } if( !count ) return; // allocate the array of pointers map_rotation_p = ( char ** )G_Malloc( ( count + 1 ) * sizeof( *map_rotation_p ) ); // now convert the string to tokens by nulling the separators p = map_rotation_s; count = 0; lastwhitespace = true; while( *p ) { thiswhitespace = ( strchr( seps, *p ) != NULL ) ? true : false; if( lastwhitespace && !thiswhitespace ) map_rotation_p[count++] = p; if( thiswhitespace ) *p = 0; lastwhitespace = thiswhitespace; p++; } // final null pointer to mark the end map_rotation_p[count] = NULL; map_rotation_count = count; } }
/* * G_Init * * This will be called when the dll is first loaded, which * only happens when a new game is started or a save game is loaded. */ void G_Init( unsigned int seed, unsigned int framemsec, int protocol, const char *demoExtension ) { cvar_t *g_maxentities; G_Printf( "==== G_Init ====\n" ); srand( seed ); G_InitGameShared(); SV_ReadIPList (); game.snapFrameTime = framemsec; game.frametime = game.snapFrameTime; game.protocol = protocol; Q_strncpyz( game.demoExtension, demoExtension, sizeof( game.demoExtension ) ); game.levelSpawnCount = 0; g_maxvelocity = trap_Cvar_Get( "g_maxvelocity", "16000", 0 ); if( g_maxvelocity->value < 20 ) { trap_Cvar_SetValue( "g_maxvelocity", 20 ); } g_gravity = trap_Cvar_Get( "g_gravity", va( "%i", GRAVITY ), 0 ); developer = trap_Cvar_Get( "developer", "0", 0 ); // noset vars dedicated = trap_Cvar_Get( "dedicated", "0", CVAR_NOSET ); // latched vars sv_cheats = trap_Cvar_Get( "sv_cheats", "0", CVAR_SERVERINFO | CVAR_LATCH ); sv_mm_enable = trap_Cvar_Get( "sv_mm_enable", "0", CVAR_ARCHIVE | CVAR_NOSET | CVAR_SERVERINFO ); // hack in CVAR_SERVERINFO flag trap_Cvar_Get( "gamename", trap_Cvar_String( "gamename" ), CVAR_SERVERINFO ); trap_Cvar_Get( "gamedate", __DATE__, CVAR_SERVERINFO | CVAR_LATCH ); password = trap_Cvar_Get( "password", "", CVAR_USERINFO ); password->modified = true; // force an update of g_needpass in G_UpdateServerInfo g_operator_password = trap_Cvar_Get( "g_operator_password", "", CVAR_ARCHIVE ); filterban = trap_Cvar_Get( "filterban", "1", 0 ); cm_mapHeader = trap_Cvar_Get( "cm_mapHeader", "", 0 ); cm_mapVersion = trap_Cvar_Get( "cm_mapVersion", "", 0 ); g_ammo_respawn = trap_Cvar_Get( "g_ammo_respawn", "0", CVAR_ARCHIVE ); g_weapon_respawn = trap_Cvar_Get( "g_weapon_respawn", "0", CVAR_ARCHIVE ); g_health_respawn = trap_Cvar_Get( "g_health_respawn", "0", CVAR_ARCHIVE ); g_armor_respawn = trap_Cvar_Get( "g_armor_respawn", "0", CVAR_ARCHIVE ); g_select_empty = trap_Cvar_Get( "g_select_empty", "0", CVAR_DEVELOPER ); g_projectile_touch_owner = trap_Cvar_Get( "g_projectile_touch_owner", "0", CVAR_DEVELOPER ); g_projectile_prestep = trap_Cvar_Get( "g_projectile_prestep", va( "%i", PROJECTILE_PRESTEP ), CVAR_DEVELOPER ); g_self_knockback = trap_Cvar_Get( "g_self_knockback", "1.18", CVAR_DEVELOPER ); g_knockback_scale = trap_Cvar_Get( "g_knockback_scale", "1.0", CVAR_ARCHIVE ); g_allow_stun = trap_Cvar_Get( "g_allow_stun", "1", CVAR_ARCHIVE ); g_armor_degradation = trap_Cvar_Get( "g_armor_degradation", va( "%.2f", ARMOR_DEGRADATION ), CVAR_DEVELOPER ); g_armor_protection = trap_Cvar_Get( "g_armor_protection", va( "%.2f", ARMOR_PROTECTION ), CVAR_DEVELOPER ); g_respawn_delay_min = trap_Cvar_Get( "g_respawn_delay_min", "600", CVAR_DEVELOPER ); g_respawn_delay_max = trap_Cvar_Get( "g_respawn_delay_max", "6000", CVAR_DEVELOPER ); g_numbots = trap_Cvar_Get( "g_numbots", "0", CVAR_ARCHIVE ); g_deadbody_followkiller = trap_Cvar_Get( "g_deadbody_followkiller", "1", CVAR_DEVELOPER ); g_deadbody_autogib_delay = trap_Cvar_Get( "g_deadbody_autogib_delay", "2000", CVAR_DEVELOPER ); g_maxtimeouts = trap_Cvar_Get( "g_maxtimeouts", "2", CVAR_ARCHIVE ); g_antilag = trap_Cvar_Get( "g_antilag", "1", CVAR_SERVERINFO|CVAR_ARCHIVE|CVAR_LATCH ); g_antilag_maxtimedelta = trap_Cvar_Get( "g_antilag_maxtimedelta", "200", CVAR_ARCHIVE ); g_antilag_maxtimedelta->modified = true; g_antilag_timenudge = trap_Cvar_Get( "g_antilag_timenudge", "0", CVAR_ARCHIVE ); g_antilag_timenudge->modified = true; g_allow_spectator_voting = trap_Cvar_Get( "g_allow_spectator_voting", "1", CVAR_ARCHIVE ); if( dedicated->integer ) { g_autorecord = trap_Cvar_Get( "g_autorecord", "1", CVAR_ARCHIVE ); g_autorecord_maxdemos = trap_Cvar_Get( "g_autorecord_maxdemos", "200", CVAR_ARCHIVE ); } else { g_autorecord = trap_Cvar_Get( "g_autorecord", "0", CVAR_ARCHIVE ); g_autorecord_maxdemos = trap_Cvar_Get( "g_autorecord_maxdemos", "0", CVAR_ARCHIVE ); } // flood control g_floodprotection_messages = trap_Cvar_Get( "g_floodprotection_messages", "4", 0 ); g_floodprotection_messages->modified = true; g_floodprotection_team = trap_Cvar_Get( "g_floodprotection_team", "0", 0 ); g_floodprotection_team->modified = true; g_floodprotection_seconds = trap_Cvar_Get( "g_floodprotection_seconds", "4", 0 ); g_floodprotection_seconds->modified = true; g_floodprotection_penalty = trap_Cvar_Get( "g_floodprotection_delay", "10", 0 ); g_floodprotection_penalty->modified = true; g_inactivity_maxtime = trap_Cvar_Get( "g_inactivity_maxtime", "90.0", 0 ); g_inactivity_maxtime->modified = true; // map list g_maplist = trap_Cvar_Get( "g_maplist", "", CVAR_ARCHIVE ); g_maprotation = trap_Cvar_Get( "g_maprotation", "1", CVAR_ARCHIVE ); // map pool g_enforce_map_pool = trap_Cvar_Get( "g_enforce_map_pool", "0", CVAR_ARCHIVE ); g_map_pool = trap_Cvar_Get( "g_map_pool", "", CVAR_ARCHIVE ); //game switches g_instagib = trap_Cvar_Get( "g_instagib", "0", CVAR_SERVERINFO|CVAR_ARCHIVE|CVAR_LATCH ); g_instajump = trap_Cvar_Get( "g_instajump", "1", CVAR_ARCHIVE ); g_instashield = trap_Cvar_Get( "g_instashield", "1", CVAR_ARCHIVE ); // helper cvars to show current status in serverinfo reply trap_Cvar_Get( "g_match_time", "", CVAR_SERVERINFO|CVAR_READONLY ); trap_Cvar_Get( "g_match_score", "", CVAR_SERVERINFO|CVAR_READONLY ); trap_Cvar_Get( "g_needpass", "", CVAR_SERVERINFO|CVAR_READONLY ); trap_Cvar_Get( "g_gametypes_available", "", CVAR_SERVERINFO|CVAR_READONLY ); trap_Cvar_Get( "g_race_gametype", "0", CVAR_SERVERINFO|CVAR_READONLY ); // define this one here so we can see when it's modified g_disable_vote_gametype = trap_Cvar_Get( "g_disable_vote_gametype", "0", CVAR_ARCHIVE ); g_asGC_stats = trap_Cvar_Get( "g_asGC_stats", "0", CVAR_ARCHIVE ); g_asGC_interval = trap_Cvar_Get( "g_asGC_interval", "10", CVAR_ARCHIVE ); g_skillRating = trap_Cvar_Get( "sv_skillRating", va("%.0f", MM_RATING_DEFAULT), CVAR_SERVERINFO|CVAR_READONLY ); // trap_Cvar_ForceSet( "sv_skillRating", va("%d", MM_RATING_DEFAULT) ); // nextmap trap_Cvar_ForceSet( "nextmap", "match \"advance\"" ); // initialize all entities for this game g_maxentities = trap_Cvar_Get( "sv_maxentities", "1024", CVAR_LATCH ); game.maxentities = g_maxentities->integer; game.edicts = ( edict_t * )G_Malloc( game.maxentities * sizeof( game.edicts[0] ) ); // initialize all clients for this game game.clients = ( gclient_t * )G_Malloc( gs.maxclients * sizeof( game.clients[0] ) ); game.quits = NULL; game.numentities = gs.maxclients + 1; trap_LocateEntities( game.edicts, sizeof( game.edicts[0] ), game.numentities, game.maxentities ); // server console commands G_AddServerCommands(); G_LoadFiredefsFromDisk(); // weapon items GS_InitWeapons(); // init AS engine G_asInitGameModuleEngine(); }
/* * G_GS_Malloc - Used only for gameshared linking */ static void *G_GS_Malloc( size_t size ) { return G_Malloc( size ); }
// Argh! - loads id baseq2/player models, "patches" their skin links // for misc_actor (all id skins, and slots for 10 custom // skins), and saves them to the current moddir location // int PatchPlayerModels (char *modelname) { cvar_t *game; int j; int numskins; // number of skin entries char skins[MAX_MD2SKINS][MAX_SKINNAME]; // skin entries char infilename[MAX_OSPATH]; char outfilename[MAX_OSPATH]; FILE *infile; FILE *outfile; dmdl_t model; // model header byte *data; // model data int datasize; // model data size (bytes) int newoffset; // model data offset (after skins) // get game (moddir) name game = gi.cvar("game", "", 0); if (!*game->string) return 0; // we're in baseq2 sprintf (outfilename, "%s/players/%s/tris.md2", game->string, modelname); if ((outfile = fopen (outfilename, "rb"))) { // output file already exists, move along fclose (outfile); // gi.dprintf ("PatchPlayerModels: Could not save %s, file already exists\n", outfilename); return 0; } // clear skin names (just in case) for (j = 0; j < MAX_MD2SKINS; j++) memset (skins[j], 0, MAX_SKINNAME); // set model-specific data if(!Q_strcasecmp(modelname,"male")) { numskins = 15; sprintf (skins[0], "players/male/cipher.pcx"); sprintf (skins[1], "players/male/claymore.pcx"); sprintf (skins[2], "players/male/flak.pcx"); sprintf (skins[3], "players/male/grunt.pcx"); sprintf (skins[4], "players/male/howitzer.pcx"); sprintf (skins[5], "players/male/major.pcx"); sprintf (skins[6], "players/male/nightops.pcx"); sprintf (skins[7], "players/male/pointman.pcx"); sprintf (skins[8], "players/male/psycho.pcx"); sprintf (skins[9], "players/male/rampage.pcx"); sprintf (skins[10], "players/male/razor.pcx"); sprintf (skins[11], "players/male/recon.pcx"); sprintf (skins[12], "players/male/scout.pcx"); sprintf (skins[13], "players/male/sniper.pcx"); sprintf (skins[14], "players/male/viper.pcx"); } else if(!Q_strcasecmp(modelname,"female")) { numskins = 10; sprintf (skins[0], "players/female/athena.pcx"); sprintf (skins[1], "players/female/brianna.pcx"); sprintf (skins[2], "players/female/cobalt.pcx"); sprintf (skins[3], "players/female/ensign.pcx"); sprintf (skins[4], "players/female/jezebel.pcx"); sprintf (skins[5], "players/female/jungle.pcx"); sprintf (skins[6], "players/female/lotus.pcx"); sprintf (skins[7], "players/female/stiletto.pcx"); sprintf (skins[8], "players/female/venus.pcx"); sprintf (skins[9], "players/female/voodoo.pcx"); } else if(!Q_strcasecmp(modelname,"cyborg")) { numskins = 3; sprintf (skins[0], "players/cyborg/oni911.pcx"); sprintf (skins[1], "players/cyborg/ps9000.pcx"); sprintf (skins[2], "players/cyborg/tyr574.pcx"); } else return 0; // fill in 32 slots with "customXX" for(j=numskins; j<32; j++) sprintf( skins[j], "players/%s/custom%d.pcx", modelname, j-numskins+1); numskins = 32; // load original player model sprintf (infilename, "baseq2/players/%s/tris.md2", modelname); if ( !(infile = fopen (infilename, "rb")) ) return 0; // no player model (this shouldn't happen) fread (&model, sizeof (dmdl_t), 1, infile); datasize = model.ofs_end - model.ofs_skins; if ( !(data = (byte*)G_Malloc (datasize)) ) // make sure freed locally { gi.dprintf ("PatchPlayerModels: Could not allocate memory for model\n"); return 0; } fread (data, sizeof (byte), datasize, infile); fclose (infile); // update model info model.num_skins = numskins; newoffset = numskins * MAX_SKINNAME; model.ofs_st += newoffset; model.ofs_tris += newoffset; model.ofs_frames += newoffset; model.ofs_glcmds += newoffset; model.ofs_end += newoffset; // save new player model sprintf (outfilename, "%s/players", game->string); // make some dirs if needed _mkdir (outfilename); sprintf (outfilename, "%s/players/%s", game->string, modelname); _mkdir (outfilename); sprintf (outfilename, "%s/players/%s/tris.md2", game->string, modelname); if ( !(outfile = fopen (outfilename, "wb")) ) { // file couldn't be created for some other reason gi.dprintf ("PatchPlayerModels: Could not save %s\n", outfilename); G_Free(data); return 0; } fwrite (&model, sizeof (dmdl_t), 1, outfile); fwrite (skins, sizeof (char), newoffset, outfile); fwrite (data, sizeof (byte), datasize, outfile); fclose (outfile); gi.dprintf ("PatchPlayerModels: Saved %s\n", outfilename); G_Free(data); return 1; }
/* * G_UpdateMapRotation * * Reads current map rotation into internal list */ static void G_UpdateMapRotation( void ) { int count; qboolean thiswhitespace, lastwhitespace; char *p; static const char *seps = " ,\n\r"; if( g_maplist->modified || !map_rotation_s || !map_rotation_p ) { g_maplist->modified = qfalse; // reread the maplist if( map_rotation_s ) G_Free( map_rotation_s ); if( map_rotation_p ) G_Free( map_rotation_p ); map_rotation_s = G_CopyString( g_maplist->string ); map_rotation_p = NULL; map_rotation_current = 0; // reset the mapcounter too map_rotation_count = 0; // count the number of tokens p = map_rotation_s; count = 0; lastwhitespace = qtrue; while( *p ) { thiswhitespace = ( strchr( seps, *p ) != NULL ) ? qtrue : qfalse; if( lastwhitespace && !thiswhitespace ) count++; lastwhitespace = thiswhitespace; p++; } if( !count ) return; // allocate the array of pointers map_rotation_p = G_Malloc( ( count + 1 ) * sizeof( *map_rotation_p ) ); // now convert the string to tokens by nulling the separators p = map_rotation_s; count = 0; lastwhitespace = qtrue; while( *p ) { thiswhitespace = ( strchr( seps, *p ) != NULL ) ? qtrue : qfalse; if( lastwhitespace && !thiswhitespace ) map_rotation_p[count++] = p; if( thiswhitespace ) *p = 0; lastwhitespace = thiswhitespace; p++; } // final null pointer to mark the end map_rotation_p[count] = NULL; map_rotation_count = count; } }