/* Copyright (C) 1997-2001 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "g_local.h" #include "g_gametypes.h" typedef struct { char *name; void (*spawn)(edict_t *ent); } spawn_t; void SP_info_player_start (edict_t *ent); void SP_info_player_deathmatch (edict_t *ent); void SP_info_player_intermission (edict_t *ent); void SP_team_CTF_redspawn( edict_t *self ); void SP_team_CTF_bluespawn( edict_t *self ); void SP_team_CTF_redplayer( edict_t *self ); void SP_team_CTF_blueplayer( edict_t *self ); void SP_func_plat (edict_t *ent); void SP_func_rotating (edict_t *ent); void SP_func_button (edict_t *ent); void SP_func_door (edict_t *ent); void SP_func_door_secret (edict_t *ent); void SP_func_door_rotating (edict_t *ent); void SP_func_water (edict_t *ent); void SP_func_train (edict_t *ent); void SP_func_conveyor (edict_t *self); void SP_func_wall (edict_t *self); void SP_func_object (edict_t *self); void SP_func_explosive (edict_t *self); void SP_func_timer (edict_t *self); void SP_func_killbox (edict_t *ent); void SP_func_static (edict_t *ent); void SP_func_bobbing ( edict_t *ent ); void SP_func_pendulum ( edict_t *ent ); void SP_trigger_always (edict_t *ent); void SP_trigger_once (edict_t *ent); void SP_trigger_multiple (edict_t *ent); void SP_trigger_relay (edict_t *ent); void SP_trigger_push (edict_t *ent); void SP_trigger_hurt (edict_t *ent); void SP_trigger_key (edict_t *ent); void SP_trigger_counter (edict_t *ent); void SP_trigger_elevator (edict_t *ent); void SP_trigger_gravity (edict_t *ent); void SP_trigger_monsterjump (edict_t *ent); void SP_target_temp_entity (edict_t *ent); void SP_target_speaker (edict_t *ent); void SP_target_explosion (edict_t *ent); void SP_target_splash (edict_t *ent); void SP_target_spawner (edict_t *ent); void SP_target_blaster (edict_t *ent); void SP_target_crosslevel_trigger (edict_t *ent); void SP_target_crosslevel_target (edict_t *ent); void SP_target_laser (edict_t *self); void SP_target_lightramp (edict_t *self); void SP_target_earthquake (edict_t *ent); void SP_target_character (edict_t *ent); void SP_target_string (edict_t *ent); void SP_target_location (edict_t *self); void SP_target_position (edict_t *self); void SP_target_print (edict_t *self); void SP_target_starttimer (edict_t *self); void SP_target_stoptimer (edict_t *self); void SP_target_checkpoint (edict_t *self); void SP_target_give(edict_t *self); void SP_target_reset_flag_countdown( edict_t *self ); void SP_target_freeze_flag_countdown( edict_t *self ); void SP_worldspawn (edict_t *ent); //void SP_viewthing (edict_t *ent); void SP_light (edict_t *self); void SP_light_mine (edict_t *ent); void SP_info_null (edict_t *self); void SP_info_notnull (edict_t *self); void SP_info_camp (edict_t *self); void SP_path_corner (edict_t *self); void SP_misc_teleporter_dest (edict_t *self); void SP_misc_model (edict_t *ent); void SP_misc_portal_surface (edict_t *ent); void SP_misc_portal_camera (edict_t *ent); void SP_item_botroam (edict_t *self); //MBotGame spawn_t spawns[] = { {"info_player_start", SP_info_player_start}, {"info_player_deathmatch", SP_info_player_deathmatch}, {"info_player_intermission", SP_info_player_intermission}, //ZOID {"team_CTF_redspawn", SP_team_CTF_redspawn}, {"team_CTF_bluespawn", SP_team_CTF_bluespawn}, {"team_CTF_redplayer", SP_team_CTF_redplayer}, {"team_CTF_blueplayer", SP_team_CTF_blueplayer}, //ZOID {"func_plat", SP_func_plat}, {"func_button", SP_func_button}, {"func_door", SP_func_door}, {"func_door_secret", SP_func_door_secret}, {"func_door_rotating", SP_func_door_rotating}, {"func_rotating", SP_func_rotating}, {"func_train", SP_func_train}, {"func_water", SP_func_water}, {"func_conveyor", SP_func_conveyor}, {"func_wall", SP_func_wall}, {"func_object", SP_func_object}, {"func_timer", SP_func_timer}, {"func_explosive", SP_func_explosive}, {"func_killbox", SP_func_killbox}, {"func_static", SP_func_static}, {"func_bobbing", SP_func_bobbing}, {"func_pendulum", SP_func_pendulum}, {"trigger_always", SP_trigger_always}, {"trigger_once", SP_trigger_once}, {"trigger_multiple", SP_trigger_multiple}, {"trigger_relay", SP_trigger_relay}, {"trigger_push", SP_trigger_push}, {"trigger_hurt", SP_trigger_hurt}, {"trigger_counter", SP_trigger_counter}, {"trigger_elevator", SP_trigger_elevator}, {"trigger_gravity", SP_trigger_gravity}, {"trigger_monsterjump", SP_trigger_monsterjump}, {"target_temp_entity", SP_target_temp_entity}, {"target_speaker", SP_target_speaker}, {"target_explosion", SP_target_explosion}, {"target_splash", SP_target_splash}, {"target_spawner", SP_target_spawner}, {"target_blaster", SP_target_blaster}, {"target_crosslevel_trigger", SP_target_crosslevel_trigger}, {"target_crosslevel_target", SP_target_crosslevel_target}, {"target_laser", SP_target_laser}, {"target_lightramp", SP_target_lightramp}, {"target_earthquake", SP_target_earthquake}, {"target_character", SP_target_character}, {"target_string", SP_target_string}, {"target_location", SP_target_location}, {"target_position", SP_target_position}, {"target_print", SP_target_print}, // minimal defrag {"target_starttimer", SP_target_starttimer}, {"target_stoptimer", SP_target_stoptimer}, {"target_checkpoint", SP_target_checkpoint}, {"target_give", SP_target_give}, {"target_reset_flag_countdown", SP_target_reset_flag_countdown}, {"target_freeze_flag_countdown", SP_target_freeze_flag_countdown}, {"worldspawn", SP_worldspawn}, //{"viewthing", SP_viewthing}, {"light", SP_light}, {"light_mine1", SP_light_mine}, {"info_null", SP_info_null}, {"func_group", SP_info_null}, {"info_notnull", SP_info_notnull}, {"info_camp", SP_info_camp}, {"path_corner", SP_path_corner}, {"misc_teleporter_dest", SP_misc_teleporter_dest}, //ZOID {"trigger_teleport", SP_trigger_teleport}, {"info_teleport_destination", SP_info_teleport_destination}, //ZOID {"misc_model", SP_misc_model}, {"misc_portal_surface", SP_misc_portal_surface}, {"misc_portal_camera", SP_misc_portal_camera}, {"item_botroam", SP_item_botroam}, //MBotGame {NULL, NULL} }; gitem_t *G_ItemForEntity( edict_t *ent ) { int i; gitem_t *item; // check item spawn functions for( i = 0; i < game.numItems; i++ ) { item = game.items[i]; if( !item ) continue; if( item->classname && !Q_stricmp(item->classname, ent->classname) ) return item; } // check again using q3 classnames for( i = 0; i < game.numItems; i++ ) { item = game.items[i]; if( !item ) continue; if( item->q3classname && !Q_stricmp(item->q3classname, ent->classname) ) return item; } return NULL; } //============= //G_CanSpawnEntity //============= static qboolean G_CanSpawnEntity( edict_t *ent ) { gitem_t *item; if( ent == world ) return qtrue; if( game.gametype == GAMETYPE_DM && ((ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH)||st.notfree) ) return qfalse; if( game.gametype == GAMETYPE_DUEL && st.notduel ) return qfalse; if( game.gametype == GAMETYPE_TDM && st.notteam ) return qfalse; if( game.gametype == GAMETYPE_CTF && st.notctf ) return qfalse; if( (item = G_ItemForEntity(ent)) != NULL ) { // not pickable items aren't either spawnable if( !(item->flags & ITFLAG_PICKABLE) ) return qfalse; if( !G_Gametype_CanSpawnItem(item) ) { return qfalse; } // some items are disabled by users, by setting up dmflags if( dmflags->integer & DF_NO_ARMOR && (item->flags & IT_ARMOR) ) return qfalse; if( dmflags->integer & DF_NO_ITEMS && (item->flags & IT_POWERUP) ) return qfalse; if( dmflags->integer & DF_NO_HEALTH && (item->flags & IT_HEALTH) ) return qfalse; if( dmflags->integer & DF_INFINITE_AMMO && (item->flags & IT_AMMO) ) return qfalse; if( game.gametype != GAMETYPE_CTF && (item->flags & IT_FLAG) ) return qfalse; } return qtrue; } /* =============== G_CallSpawn Finds the spawn function for the entity and calls it =============== */ void G_CallSpawn( edict_t *ent ) { spawn_t *s; gitem_t *item; if( !ent->classname ) { if( developer->integer ) G_Printf( "G_CallSpawn: NULL classname\n" ); return; } if( (item = G_ItemForEntity(ent)) != NULL ) { ent->classname = item->classname; // for q3 support SpawnItem( ent, item ); return; } // check normal spawn functions for( s = spawns; s->name; s++ ) { if( !Q_stricmp(s->name, ent->classname) ) { // found it s->spawn(ent); return; } } // if( developer->integer ) G_Printf( "%s doesn't have a spawn function\n", ent->classname ); } /* ============= ED_NewString ============= */ char *ED_NewString( char *string ) { char *newb, *new_p; int i,l; l = strlen(string) + 1; newb = G_Malloc(l); new_p = newb; for( i = 0; i < l; i++ ) { if( string[i] == '\\' && i < l-1 ) { i++; if( string[i] == 'n' ) { *new_p++ = '\n'; } else { *new_p++ = '/'; *new_p++ = string[i]; } } else *new_p++ = string[i]; } return newb; } /* =============== ED_ParseField Takes a key/value pair and sets the binary values in an edict =============== */ void ED_ParseField( char *key, char *value, edict_t *ent ) { const field_t *f; qbyte *b; float v; vec3_t vec; for( f=fields; f->name; f++ ) { if( !Q_stricmp(f->name, key) ) { // found it if( f->flags & FFL_SPAWNTEMP ) b = (qbyte *)&st; else b = (qbyte *)ent; switch( f->type ) { case F_LSTRING: *(char **)(b+f->ofs) = ED_NewString(value); break; case F_VECTOR: sscanf (value, "%f %f %f", &vec[0], &vec[1], &vec[2]); ((float *)(b+f->ofs))[0] = vec[0]; ((float *)(b+f->ofs))[1] = vec[1]; ((float *)(b+f->ofs))[2] = vec[2]; break; case F_INT: *(int *)(b+f->ofs) = atoi(value); break; case F_FLOAT: *(float *)(b+f->ofs) = atof(value); break; case F_ANGLEHACK: v = atof(value); ((float *)(b+f->ofs))[0] = 0; ((float *)(b+f->ofs))[1] = v; ((float *)(b+f->ofs))[2] = 0; break; case F_IGNORE: break; default: break; // FIXME: Should this be error? } return; } } if( developer->integer ) G_Printf( "%s is not a field\n", key ); } /* ==================== ED_ParseEdict Parses an edict out of the given string, returning the new position ed should be a properly initialized empty edict. ==================== */ char *ED_ParseEdict( char *data, edict_t *ent ) { qboolean init; char keyname[256]; char *com_token; init = qfalse; memset( &st, 0, sizeof(st) ); // go through all the dictionary pairs while( 1 ) { // parse key com_token = COM_Parse( &data ); if( com_token[0] == '}' ) break; if( !data ) G_Error( "ED_ParseEntity: EOF without closing brace" ); Q_strncpyz( keyname, com_token, sizeof(keyname) ); // parse value com_token = COM_Parse( &data ); if( !data ) G_Error( "ED_ParseEntity: EOF without closing brace" ); if( com_token[0] == '}' ) G_Error( "ED_ParseEntity: closing brace without data" ); init = qtrue; // keynames with a leading underscore are used for utility comments, // and are immediately discarded by quake if( keyname[0] == '_' ) continue; ED_ParseField( keyname, com_token, ent ); } if( !init ) memset( ent, 0, sizeof(*ent) ); return data; } /* ================ G_FindTeams Chain together all entities with a matching team field. All but the first will have the FL_TEAMSLAVE flag set. All but the last will have the teamchain field set to the next one ================ */ void G_FindTeams( void ) { edict_t *e, *e2, *chain; int i, j; int c, c2; c = 0; c2 = 0; for( i=1, e=game.edicts+i; i < game.numentities; i++, e++ ) { if( !e->r.inuse ) continue; if( !e->team ) continue; if( e->flags & FL_TEAMSLAVE ) continue; chain = e; e->teammaster = e; c++; c2++; for( j=i+1, e2=e+1; j < game.numentities; j++,e2++ ) { if( !e2->r.inuse ) continue; if( !e2->team ) continue; if( e2->flags & FL_TEAMSLAVE ) continue; if( !strcmp(e->team, e2->team) ) { c2++; chain->teamchain = e2; e2->teammaster = e; chain = e2; e2->flags |= FL_TEAMSLAVE; } } } if( developer->integer ) G_Printf ("%i teams with %i entities\n", c, c2); } /* ============== SpawnMapEntities Spawns all the entities in the map except the world ============== */ void G_SpawnMapEntities( qboolean worldspawn ) { edict_t *ent = NULL; int i = 0; char *entities, *token; gitem_t *item; // Reset Map Locations Names : wsw : jal level.numLocations = 0; memset( level.locationNames, 0, sizeof(level.locationNames) ); // pb: reset number of checkpoint level.nbcheckpoint=0; // location zero is unknown fallback G_RegisterMapLocationName( "someplace" ); entities = game.map_entities; if( !entities ) return; while( 1 ) { // 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 ) { if( worldspawn != qtrue ) ent = G_Spawn(); else ent = world; } else ent = G_Spawn(); entities = ED_ParseEdict( entities, ent ); if( !Q_stricmp(ent->classname, "worldspawn") && !worldspawn ) { i++; G_FreeEdict(ent); continue; } if( (item = G_ItemForEntity(ent)) != NULL ) PrecacheItem(item); if( !G_CanSpawnEntity(ent) ) { i++; G_FreeEdict(ent); continue; } G_CallSpawn(ent); // wsw : jal : locations names if( !Q_stricmp(ent->classname, "target_location") ) { if( ent->count > 0 && ent->count < 10 ) G_RegisterMapLocationName( va("%c%c%s", Q_COLOR_ESCAPE, ent->count + '0', ent->message) ); else G_RegisterMapLocationName( ent->message ); } } G_FindTeams(); // make sure server got the edicts data trap_LocateEntities( game.edicts, sizeof(game.edicts[0]), game.numentities, game.maxentities ); // update *all* CS_LOCATIONS configstrings for( i = 0; i < MAX_LOCATIONS; i++ ) trap_ConfigString( CS_LOCATIONS + i, level.locationNames[i] ); // check number of checkpoints if(level.nbcheckpoint>MAX_RACE_CHECKPOINT) { G_Printf("Map contains to many target_checkpoint (found %d max %d) \n", level.nbcheckpoint,MAX_RACE_CHECKPOINT); } if(developer->integer) { G_Printf("Found %d target_checkpoint\n",level.nbcheckpoint); } } /* ============== SpawnEntities Creates a server's entity / program execution context by parsing textual entity definitions out of an ent file. ============== */ void SpawnEntities( char *mapname, char *entities, int entstrlen, char *spawnpoint ) { int i; G_EmptyLevelPool(); memset( &level, 0, sizeof(level) ); memset( game.edicts, 0, game.maxentities * sizeof(game.edicts[0]) ); game.map_entities = NULL; Q_strncpyz( level.mapname, mapname, sizeof(level.mapname) ); Q_strncpyz( game.spawnpoint, spawnpoint, sizeof(game.spawnpoint) ); // set client fields on player ents for( i=0 ; ilatched_string ) { game.gametype = GS_Gametype_FindByShortName(g_gametype->latched_string); if( game.gametype < GAMETYPE_DM || game.gametype >= GAMETYPE_TOTAL ) game.gametype = GAMETYPE_DM; } // make a copy of the raw entities string game.map_entities = G_LevelMalloc( entstrlen ); memcpy( game.map_entities, entities, entstrlen ); G_SpawnMapEntities( qtrue ); G_Gametype_Update(); //newgametypes G_Match_NewMap(); //AI_NewMap();//MbotGame } //=================================================================== /*QUAKED worldspawn (0 0 0) ? Only used for the world. "sky" environment map name "skyaxis" vector axis for rotating sky "skyrotate" speed of rotation in degrees/second "sounds" music cd track number "gravity" 800 is default gravity "message" text to print at user logon */ void SP_worldspawn( edict_t *ent ) { ent->movetype = MOVETYPE_PUSH; ent->r.solid = SOLID_BSP; ent->r.inuse = qtrue; // since the world doesn't use G_Spawn() VectorClear( ent->s.origin ); VectorClear( ent->s.angles ); trap_SetBrushModel( ent, "*0" ); // sets mins / maxs and modelindex 1 //--------------- // reserve some spots for dead player bodies for deathmatch InitBodyQue(); // set configstrings for items SetItemNames(); if( st.nextmap ) Q_strncpyz( level.nextmap, st.nextmap, sizeof(level.nextmap) ); // make some data visible to the server if( ent->message && ent->message[0] ) { trap_ConfigString( CS_MESSAGE, ent->message ); Q_strncpyz( level.level_name, ent->message, sizeof(level.level_name) ); } else { trap_ConfigString( CS_MESSAGE, level.mapname ); Q_strncpyz( level.level_name, level.mapname, sizeof(level.level_name) ); } // send music if( st.music ) { trap_ConfigString( CS_AUDIOTRACK, st.music ); } trap_ConfigString( CS_MAPNAME, level.mapname ); trap_ConfigString( CS_MAXCLIENTS, va("%i", game.maxclients ) ); trap_ConfigString( CS_HOSTNAME, trap_Cvar_VariableString("sv_hostname") ); //--------------- if( st.gravity ) trap_Cvar_Set( "g_gravity", st.gravity ); // items that are not in the map, but will still be used PrecacheItem( GS_FindItemByName("Gunblade") ); PrecacheItem( GS_FindItemByName("Ammo Pack") ); //jal[start] splitmodels // viewable weapon models // THIS ORDER MUST MATCH THE DEFINES IN gs_public.h // you can add more, max 255 trap_ModelIndex ( "#gunblade/v_gunblade.md3" ); // WEAP_GUNBLADE trap_ModelIndex ( "#shockwave/v_shockwave.md3" ); // WEAP_SHOCKWAVE trap_ModelIndex ( "#riotgun/v_riotgun.md3" ); // WEAP_RIOTGUN trap_ModelIndex ( "#glauncher/v_glauncher.md3" ); // WEAP_GRENADELAUNCHER trap_ModelIndex ( "#rlauncher/v_rlauncher.md3" ); // WEAP_ROCKETLAUNCHER trap_ModelIndex ( "#plasmagun/v_plasmagun.md3" ); // WEAP_PLASMAGUN trap_ModelIndex ( "#lasergun/v_lasergun.md3" ); // WEAP_LASERGUN trap_ModelIndex ( "#electrobolt/v_electrobolt.md3" ); // WEAP_ELECTROBOLT //------------------- // precache our basic player models, they are just a very few trap_ModelIndex( "$models/players/viciious" ); trap_ModelIndex( "$models/players/monada" ); trap_ModelIndex( "$models/players/silverclaw" ); trap_SkinIndex( "models/players/viciious/default" ); trap_SkinIndex( "models/players/monada/default" ); trap_SkinIndex( "models/players/silverclaw/default" ); //------------------- // jalfixme : most of these sounds can be played from the clients trap_SoundIndex (S_WORLD_WATER_IN); // feet hitting water trap_SoundIndex (S_WORLD_WATER_OUT); // feet leaving water trap_SoundIndex (S_WORLD_UNDERWATER); trap_SoundIndex (S_WORLD_SLIME_IN); trap_SoundIndex (S_WORLD_SLIME_OUT); trap_SoundIndex (S_WORLD_UNDERSLIME); trap_SoundIndex (S_WORLD_LAVA_IN); trap_SoundIndex (S_WORLD_LAVA_OUT); trap_SoundIndex (S_WORLD_UNDERLAVA); trap_SoundIndex (va(S_PLAYER_BURN_1_to_2, 1)); trap_SoundIndex (va(S_PLAYER_BURN_1_to_2, 2)); //wsw: pb disable unreferenced sounds //trap_SoundIndex (S_LAND); // landing thud trap_SoundIndex (S_HIT_WATER); trap_SoundIndex (S_WEAPON_NOAMMO); // announcer // readyup trap_SoundIndex ( S_ANNOUNCER_READY_UP_POLITE ); trap_SoundIndex ( S_ANNOUNCER_READY_UP_PISSEDOFF ); // countdown trap_SoundIndex (va(S_ANNOUNCER_COUNTDOWN_GET_READY_TO_FIGHT_1_to_2, 1)); trap_SoundIndex (va(S_ANNOUNCER_COUNTDOWN_GET_READY_TO_FIGHT_1_to_2, 2)); trap_SoundIndex (va(S_ANNOUNCER_COUNTDOWN_READY_1_to_2, 1)); trap_SoundIndex (va(S_ANNOUNCER_COUNTDOWN_READY_1_to_2, 2)); trap_SoundIndex (va(S_ANNOUNCER_COUNTDOWN_COUNT_1_to_3_SET_1_to_2, 1, 1)); trap_SoundIndex (va(S_ANNOUNCER_COUNTDOWN_COUNT_1_to_3_SET_1_to_2, 2, 1)); trap_SoundIndex (va(S_ANNOUNCER_COUNTDOWN_COUNT_1_to_3_SET_1_to_2, 3, 1)); trap_SoundIndex (va(S_ANNOUNCER_COUNTDOWN_COUNT_1_to_3_SET_1_to_2, 1, 2)); trap_SoundIndex (va(S_ANNOUNCER_COUNTDOWN_COUNT_1_to_3_SET_1_to_2, 2, 2)); trap_SoundIndex (va(S_ANNOUNCER_COUNTDOWN_COUNT_1_to_3_SET_1_to_2, 3, 2)); trap_SoundIndex (va(S_ANNOUNCER_COUNTDOWN_FIGHT_1_to_2, 1)); trap_SoundIndex (va(S_ANNOUNCER_COUNTDOWN_FIGHT_1_to_2, 2)); // postmatch trap_SoundIndex (va(S_ANNOUNCER_POSTMATCH_GAMEOVER_1_to_2, 1)); trap_SoundIndex (va(S_ANNOUNCER_POSTMATCH_GAMEOVER_1_to_2, 2)); // timeout trap_SoundIndex (va(S_ANNOUNCER_TIMEOUT_MATCH_RESUMED_1_to_2, 1)); trap_SoundIndex (va(S_ANNOUNCER_TIMEOUT_MATCH_RESUMED_1_to_2, 2)); trap_SoundIndex (va(S_ANNOUNCER_TIMEOUT_TIMEOUT_1_to_2, 1)); trap_SoundIndex (va(S_ANNOUNCER_TIMEOUT_TIMEOUT_1_to_2, 2)); // callvote trap_SoundIndex (va(S_ANNOUNCER_CALLVOTE_CALLED_1_to_2, 1)); trap_SoundIndex (va(S_ANNOUNCER_CALLVOTE_CALLED_1_to_2, 2)); trap_SoundIndex (va(S_ANNOUNCER_CALLVOTE_FAILED_1_to_2, 2)); trap_SoundIndex (va(S_ANNOUNCER_CALLVOTE_FAILED_1_to_2, 2)); trap_SoundIndex (va(S_ANNOUNCER_CALLVOTE_PASSED_1_to_2, 2)); trap_SoundIndex (va(S_ANNOUNCER_CALLVOTE_PASSED_1_to_2, 2)); trap_SoundIndex (S_ANNOUNCER_CALLVOTE_VOTE_NOW); // overtime trap_SoundIndex (S_ANNOUNCER_OVERTIME_GOING_TO_OVERTIME); trap_SoundIndex (S_ANNOUNCER_OVERTIME_OVERTIME); trap_SoundIndex (va(S_ANNOUNCER_OVERTIME_SUDDENDEATH_1_to_2, 1)); trap_SoundIndex (va(S_ANNOUNCER_OVERTIME_SUDDENDEATH_1_to_2, 2)); // score trap_SoundIndex (va(S_ANNOUNCER_SCORE_TAKEN_LEAD_1_to_2, 1)); trap_SoundIndex (va(S_ANNOUNCER_SCORE_TAKEN_LEAD_1_to_2, 2)); trap_SoundIndex (va(S_ANNOUNCER_SCORE_TEAM_TAKEN_LEAD_1_to_2, 1)); trap_SoundIndex (va(S_ANNOUNCER_SCORE_TEAM_TAKEN_LEAD_1_to_2, 2)); trap_SoundIndex (va(S_ANNOUNCER_SCORE_LOST_LEAD_1_to_2, 1)); trap_SoundIndex (va(S_ANNOUNCER_SCORE_LOST_LEAD_1_to_2, 2)); trap_SoundIndex (va(S_ANNOUNCER_SCORE_TEAM_LOST_LEAD_1_to_2, 1)); trap_SoundIndex (va(S_ANNOUNCER_SCORE_TEAM_LOST_LEAD_1_to_2, 2)); trap_SoundIndex (va(S_ANNOUNCER_SCORE_TIED_LEAD_1_to_2, 1)); trap_SoundIndex (va(S_ANNOUNCER_SCORE_TIED_LEAD_1_to_2, 2)); trap_SoundIndex (va(S_ANNOUNCER_SCORE_TEAM_TIED_LEAD_1_to_2, 1)); trap_SoundIndex (va(S_ANNOUNCER_SCORE_TEAM_TIED_LEAD_1_to_2, 2)); trap_SoundIndex (va(S_ANNOUNCER_SCORE_TEAM_TIED_LEAD_1_to_2, 1)); trap_SoundIndex (va(S_ANNOUNCER_SCORE_TEAM_TIED_LEAD_1_to_2, 2)); trap_SoundIndex (va(S_ANNOUNCER_SCORE_TEAM_1_to_4_TAKEN_LEAD_1_to_2, 1, 1)); trap_SoundIndex (va(S_ANNOUNCER_SCORE_TEAM_1_to_4_TAKEN_LEAD_1_to_2, 1, 2)); trap_SoundIndex (va(S_ANNOUNCER_SCORE_TEAM_1_to_4_TAKEN_LEAD_1_to_2, 2, 1)); trap_SoundIndex (va(S_ANNOUNCER_SCORE_TEAM_1_to_4_TAKEN_LEAD_1_to_2, 2, 2)); trap_SoundIndex (va(S_ANNOUNCER_SCORE_TEAM_1_to_4_TAKEN_LEAD_1_to_2, 3, 1)); trap_SoundIndex (va(S_ANNOUNCER_SCORE_TEAM_1_to_4_TAKEN_LEAD_1_to_2, 3, 2)); trap_SoundIndex (va(S_ANNOUNCER_SCORE_TEAM_1_to_4_TAKEN_LEAD_1_to_2, 4, 1)); trap_SoundIndex (va(S_ANNOUNCER_SCORE_TEAM_1_to_4_TAKEN_LEAD_1_to_2, 4, 2)); // ctf trap_SoundIndex (va(S_ANNOUNCER_CTF_RECOVERY_1_to_2, 1)); trap_SoundIndex (va(S_ANNOUNCER_CTF_RECOVERY_1_to_2, 2)); trap_SoundIndex (S_ANNOUNCER_CTF_RECOVERY_TEAM); trap_SoundIndex (S_ANNOUNCER_CTF_RECOVERY_ENEMY); trap_SoundIndex (S_ANNOUNCER_CTF_FLAG_TAKEN); trap_SoundIndex (va(S_ANNOUNCER_CTF_FLAG_TAKEN_TEAM_1_to_2, 1)); trap_SoundIndex (va(S_ANNOUNCER_CTF_FLAG_TAKEN_TEAM_1_to_2, 2)); trap_SoundIndex (va(S_ANNOUNCER_CTF_FLAG_TAKEN_ENEMY_1_to_2, 1)); trap_SoundIndex (va(S_ANNOUNCER_CTF_FLAG_TAKEN_ENEMY_1_to_2, 2)); trap_SoundIndex (va(S_ANNOUNCER_CTF_SCORE_1_to_2, 1)); trap_SoundIndex (va(S_ANNOUNCER_CTF_SCORE_1_to_2, 2)); trap_SoundIndex (va(S_ANNOUNCER_CTF_SCORE_TEAM_1_to_2, 1)); trap_SoundIndex (va(S_ANNOUNCER_CTF_SCORE_TEAM_1_to_2, 2)); trap_SoundIndex (va(S_ANNOUNCER_CTF_SCORE_ENEMY_1_to_2, 1)); trap_SoundIndex (va(S_ANNOUNCER_CTF_SCORE_ENEMY_1_to_2, 2)); // FIXME: Temporarily use normal gib until the head is fixed trap_ModelIndex ("models/objects/gibs/gib1/gib1.md3"); // // Setup light animation tables. 'a' is total darkness, 'z' is doublebright. // // 0 normal trap_ConfigString( CS_LIGHTS+0, "m" ); // 1 FLICKER (first variety) trap_ConfigString( CS_LIGHTS+1, "mmnmmommommnonmmonqnmmo" ); // 2 SLOW STRONG PULSE trap_ConfigString( CS_LIGHTS+2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba" ); // 3 CANDLE (first variety) trap_ConfigString( CS_LIGHTS+3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg" ); // 4 FAST STROBE trap_ConfigString( CS_LIGHTS+4, "mamamamamama" ); // 5 GENTLE PULSE 1 trap_ConfigString( CS_LIGHTS+5, "jklmnopqrstuvwxyzyxwvutsrqponmlkj" ); // 6 FLICKER (second variety) trap_ConfigString( CS_LIGHTS+6, "nmonqnmomnmomomno" ); // 7 CANDLE (second variety) trap_ConfigString( CS_LIGHTS+7, "mmmaaaabcdefgmmmmaaaammmaamm" ); // 8 CANDLE (third variety) trap_ConfigString( CS_LIGHTS+8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa" ); // 9 SLOW STROBE (fourth variety) trap_ConfigString( CS_LIGHTS+9, "aaaaaaaazzzzzzzz" ); // 10 FLUORESCENT FLICKER trap_ConfigString( CS_LIGHTS+10, "mmamammmmammamamaaamammma" ); // 11 SLOW PULSE NOT FADE TO BLACK trap_ConfigString( CS_LIGHTS+11, "abcdefghijklmnopqrrqponmlkjihgfedcba" ); // styles 32-62 are assigned by the light program for switchable lights // 63 testing trap_ConfigString( CS_LIGHTS+63, "a" ); G_InitGameCommands(); // wsw : jal : gamecommandscompletion }