/* ============ G_InitGame ============ */ void G_InitGame( int levelTime, int randomSeed, int restart ) { int i; G_Printf ("------- Game Initialization -------\n"); G_Printf ("gamename: %s\n", GAMEVERSION); G_Printf ("gamedate: %s\n", __DATE__); srand( randomSeed ); G_RegisterCvars(); G_ProcessIPBans(); G_InitMemory(); // set some level globals memset( &level, 0, sizeof( level ) ); level.time = levelTime; level.startTime = levelTime; level.snd_fry = G_SoundIndex("sound/player/fry.wav"); // FIXME standing in lava / slime if ( g_gametype.integer != GT_SINGLE_PLAYER && g_logfile.string[0] ) { if ( g_logfileSync.integer ) { trap_FS_FOpenFile( g_logfile.string, &level.logFile, FS_APPEND_SYNC ); } else { trap_FS_FOpenFile( g_logfile.string, &level.logFile, FS_APPEND ); } if ( !level.logFile ) { G_Printf( "WARNING: Couldn't open logfile: %s\n", g_logfile.string ); } else { char serverinfo[MAX_INFO_STRING]; trap_GetServerinfo( serverinfo, sizeof( serverinfo ) ); G_LogPrintf("------------------------------------------------------------\n" ); G_LogPrintf("InitGame: %s\n", serverinfo ); } } else { G_Printf( "Not logging to disk.\n" ); } G_InitWorldSession(); // initialize all entities for this game memset( g_entities, 0, MAX_GENTITIES * sizeof(g_entities[0]) ); level.gentities = g_entities; // initialize all clients for this game level.maxclients = g_maxclients.integer; memset( g_clients, 0, MAX_CLIENTS * sizeof(g_clients[0]) ); level.clients = g_clients; // set client fields on player ents for ( i=0 ; i<level.maxclients ; i++ ) { g_entities[i].client = level.clients + i; } // always leave room for the max number of clients, // even if they aren't all used, so numbers inside that // range are NEVER anything but clients level.num_entities = MAX_CLIENTS; for ( i=0 ; i<MAX_CLIENTS ; i++ ) { g_entities[i].classname = "clientslot"; } // let the server system know where the entites are trap_LocateGameData( level.gentities, level.num_entities, sizeof( gentity_t ), &level.clients[0].ps, sizeof( level.clients[0] ) ); // reserve some spots for dead player bodies InitBodyQue(); ClearRegisteredItems(); // parse the key/value pairs and spawn gentities G_SpawnEntitiesFromString(); // general initialization G_FindTeams(); // make sure we have flags for CTF, etc if( g_gametype.integer >= GT_TEAM ) { G_CheckTeamItems(); } SaveRegisteredItems(); G_Printf ("-----------------------------------\n"); if( g_gametype.integer == GT_SINGLE_PLAYER || trap_Cvar_VariableIntegerValue( "com_buildScript" ) ) { G_ModelIndex( SP_PODIUM_MODEL ); } if ( trap_Cvar_VariableIntegerValue( "bot_enable" ) ) { BotAISetup( restart ); BotAILoadMap( restart ); G_InitBots( restart ); } G_RemapTeamShaders(); }
/* * Creates a server's entity / program execution context by * parsing textual entity definitions out of an ent file. */ void SpawnEntities(char *mapname, char *entities, char *spawnpoint) { edict_t *ent; int inhibit; char *com_token; int i; float skill_level; skill_level = floor(skill->value); if (skill_level < 0) { skill_level = 0; } if (skill_level > 3) { skill_level = 3; } if (skill->value != skill_level) { gi.cvar_forceset("skill", va("%f", skill_level)); } SaveClientData(); gi.FreeTags(TAG_LEVEL); memset(&level, 0, sizeof(level)); memset(g_edicts, 0, game.maxentities * sizeof(g_edicts[0])); strncpy(level.mapname, mapname, sizeof(level.mapname) - 1); strncpy(game.spawnpoint, spawnpoint, sizeof(game.spawnpoint) - 1); /* set client fields on player ents */ for (i = 0; i < game.maxclients; i++) { g_edicts[i + 1].client = game.clients + i; } ent = NULL; inhibit = 0; /* parse ents */ while (1) { /* parse the opening brace */ com_token = COM_Parse(&entities); if (!entities) { break; } if (com_token[0] != '{') { gi.error("ED_LoadFromFile: found %s when expecting {", com_token); } if (!ent) { ent = g_edicts; } else { ent = G_Spawn(); } entities = ED_ParseEdict(entities, ent); /* yet another map hack */ if (!Q_stricmp(level.mapname, "command") && !Q_stricmp(ent->classname, "trigger_once") && !Q_stricmp(ent->model, "*27")) { ent->spawnflags &= ~SPAWNFLAG_NOT_HARD; } /* remove things (except the world) from different skill levels or deathmatch */ if (ent != g_edicts) { if (deathmatch->value) { if (ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH) { G_FreeEdict(ent); inhibit++; continue; } } else { if (((skill->value == 0) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) || ((skill->value == 1) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) || (((skill->value == 2) || (skill->value == 3)) && (ent->spawnflags & SPAWNFLAG_NOT_HARD)) ) { G_FreeEdict(ent); inhibit++; continue; } } ent->spawnflags &= ~(SPAWNFLAG_NOT_EASY | SPAWNFLAG_NOT_MEDIUM | SPAWNFLAG_NOT_HARD | SPAWNFLAG_NOT_COOP | SPAWNFLAG_NOT_DEATHMATCH); } ED_CallSpawn(ent); } gi.dprintf("%i entities inhibited.\n", inhibit); G_FindTeams(); PlayerTrail_Init(); CTFSpawn(); }
void InitGame( const char *mapname, const char *spawntarget, int checkSum, const char *entities, int levelTime, int randomSeed, int globalTime, SavedGameJustLoaded_e eSavedGameJustLoaded, qboolean qbLoadTransition ) { int i; giMapChecksum = checkSum; g_eSavedGameJustLoaded = eSavedGameJustLoaded; g_qbLoadTransition = qbLoadTransition; gi.Printf ("------- Game Initialization -------\n"); gi.Printf ("gamename: %s\n", GAMEVERSION); gi.Printf ("gamedate: %s\n", __DATE__); srand( randomSeed ); G_InitCvars(); G_InitMemory(); // set some level globals memset( &level, 0, sizeof( level ) ); level.time = levelTime; level.globalTime = globalTime; Q_strncpyz( level.mapname, mapname, sizeof(level.mapname) ); if ( spawntarget != NULL && spawntarget[0] ) { Q_strncpyz( level.spawntarget, spawntarget, sizeof(level.spawntarget) ); } else { level.spawntarget[0] = 0; } G_InitWorldSession(); // initialize all entities for this game memset( g_entities, 0, MAX_GENTITIES * sizeof(g_entities[0]) ); globals.gentities = g_entities; ClearAllInUse(); // initialize all clients for this game level.maxclients = 1; level.clients = (struct gclient_s *) G_Alloc( level.maxclients * sizeof(level.clients[0]) ); // set client fields on player g_entities[0].client = level.clients; // always leave room for the max number of clients, // even if they aren't all used, so numbers inside that // range are NEVER anything but clients globals.num_entities = MAX_CLIENTS; //Set up NPC init data NPC_InitGame(); TIMER_Clear(); // //ICARUS INIT START gi.Printf("------ ICARUS Initialization ------\n"); gi.Printf("ICARUS version : %1.2f\n", ICARUS_VERSION); Interface_Init( &interface_export ); ICARUS_Init(); gi.Printf ("-----------------------------------\n"); //ICARUS INIT END // IT_LoadItemParms (); ClearRegisteredItems(); //FIXME: if this is from a loadgame, it needs to be sure to write this out whenever you do a savegame since the edges and routes are dynamic... navCalculatePaths = ( navigator.Load( mapname, checkSum ) == qfalse ); // parse the key/value pairs and spawn gentities G_SpawnEntitiesFromString( entities ); // general initialization G_FindTeams(); // SaveRegisteredItems(); gi.Printf ("-----------------------------------\n"); //randomize the rand functions byte num_calls = (byte)timeGetTime(); for(i = 0; i < (int)num_calls; i++) { rand(); } if ( navCalculatePaths ) {//not loaded - need to calc paths navCalcPathTime = level.time + START_TIME_NAV_CALC;//make sure all ents are in and linked } else {//loaded //FIXME: if this is from a loadgame, it needs to be sure to write this //out whenever you do a savegame since the edges and routes are dynamic... //OR: always do a navigator.CheckBlockedEdges() on map startup after nav-load/calc-paths navigator.pathsCalculated = qtrue;//just to be safe? Does this get saved out? No... assumed //need to do this, because combatpoint waypoints aren't saved out...? CP_FindCombatPointWaypoints(); navCalcPathTime = 0; if ( g_eSavedGameJustLoaded == eNO ) {//clear all the failed edges unless we just loaded the game (which would include failed edges) navigator.ClearAllFailedEdges(); } } player = &g_entities[0]; //Init dynamic music level.dmState = DM_EXPLORE; level.dmDebounceTime = 0; level.dmBeatTime = 0; level.curAlertID = 1;//0 is default for lastAlertEvent, so... eventClearTime = 0; }
/* ============== 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, char *spawnpoint) { edict_t *ent; int inhibit; char *com_token; int i; float skill_level; skill_level = floor (skill->value); if (skill_level < 0) skill_level = 0; if (skill_level > 3) skill_level = 3; if (skill->value != skill_level) gi.cvar_forceset("skill", va("%f", skill_level)); SaveClientData (); gi.FreeTags (TAG_LEVEL); memset (&level, 0, sizeof(level)); memset (g_edicts, 0, game.maxentities * sizeof (g_edicts[0])); strncpy (level.mapname, mapname, sizeof(level.mapname)-1); strncpy (game.spawnpoint, spawnpoint, sizeof(game.spawnpoint)-1); // set client fields on player ents for (i=0 ; i<game.maxclients ; i++) g_edicts[i+1].client = game.clients + i; ent = NULL; inhibit = 0; // parse ents while (1) { // parse the opening brace com_token = COM_Parse (&entities); if (!entities) break; if (com_token[0] != '{') gi.error ("ED_LoadFromFile: found %s when expecting {",com_token); if (!ent) ent = g_edicts; else ent = G_Spawn (); entities = ED_ParseEdict (entities, ent); // yet another map hack if (!Q_stricmp(level.mapname, "command") && !Q_stricmp(ent->classname, "trigger_once") && !Q_stricmp(ent->model, "*27")) ent->spawnflags &= ~SPAWNFLAG_NOT_HARD; // remove things (except the world) from different skill levels or deathmatch if (ent != g_edicts) { if (deathmatch->value) { if ( ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH ) { G_FreeEdict (ent); inhibit++; continue; } } else { if ( /* ((coop->value) && (ent->spawnflags & SPAWNFLAG_NOT_COOP)) || */ ((skill->value == 0) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) || ((skill->value == 1) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) || (((skill->value == 2) || (skill->value == 3)) && (ent->spawnflags & SPAWNFLAG_NOT_HARD)) ) { G_FreeEdict (ent); inhibit++; continue; } } ent->spawnflags &= ~(SPAWNFLAG_NOT_EASY|SPAWNFLAG_NOT_MEDIUM|SPAWNFLAG_NOT_HARD|SPAWNFLAG_NOT_COOP|SPAWNFLAG_NOT_DEATHMATCH); } ED_CallSpawn (ent); } gi.dprintf ("%i entities inhibited\n", inhibit); #ifdef DEBUG i = 1; ent = EDICT_NUM(i); while (i < globals.num_edicts) { if (ent->inuse != 0 || ent->inuse != 1) Com_DPrintf("Invalid entity %d\n", i); i++, ent++; } #endif G_FindTeams (); PlayerTrail_Init (); }
/* * 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(); }
/* ============== 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, char *spawnpoint) { edict_t *ent = NULL; int inhibit = 0; char *com_token; int i; float skill_level; //AQ2:TNG New Location Code char locfile[MAX_QPATH], line[256]; FILE *f; int readmore, x, y, z, rx, ry, rz, count; char *locationstr, *param; cvar_t *game_cvar; int u; // placedata_t temp; // Reset teamplay stuff for(i = TEAM1; i < TEAM_TOP; i++) { teams[i].score = teams[i].total = 0; teams[i].ready = teams[i].locked = 0; teams[i].pauses_used = teams[i].wantReset = 0; gi.cvar_forceset(teams[i].teamscore->name, "0"); } matchtime = 0; day_cycle_at = 0; team_round_going = team_game_going = team_round_countdown = 0; lights_camera_action = holding_on_tie_check = 0; timewarning = fragwarning = 0; teamCount = 2; if (ctf->value) { // Make sure teamplay is enabled if (!teamplay->value) { gi.dprintf ("CTF Enabled - Forcing teamplay on\n"); gi.cvar_forceset(teamplay->name, "1"); } if (use_3teams->value) { gi.dprintf ("CTF Enabled - Forcing 3Teams off\n"); gi.cvar_forceset(use_3teams->name, "0"); } if(teamdm->value) { gi.dprintf ("CTF Enabled - Forcing Team DM off\n"); gi.cvar_forceset(teamdm->name, "0"); } if (use_tourney->value) { gi.dprintf ("CTF Enabled - Forcing Tourney off\n"); gi.cvar_forceset(use_tourney->name, "0"); } if (!((int) (dmflags->value) & DF_NO_FRIENDLY_FIRE)) { gi.dprintf ("CTF Enabled - Forcing Friendly Fire off\n"); gi.cvar_forceset(dmflags->name, va("%i", (int)dmflags->value | DF_NO_FRIENDLY_FIRE)); } strcpy(teams[TEAM1].name, "RED"); strcpy(teams[TEAM2].name, "BLUE"); strcpy(teams[TEAM1].skin, "male/ctf_r"); strcpy(teams[TEAM2].skin, "male/ctf_b"); strcpy(teams[TEAM1].skin_index, "../players/male/ctf_r_i"); strcpy(teams[TEAM2].skin_index, "../players/male/ctf_b_i"); if(ctf->value == 2) gi.cvar_forceset(ctf->name, "1"); //for now } else if(teamdm->value) { if (!teamplay->value) { gi.dprintf ("Team Deathmatch Enabled - Forcing teamplay on\n"); gi.cvar_forceset(teamplay->name, "1"); } if (use_3teams->value) { gi.dprintf ("Team Deathmatch Enabled - Forcing 3Teams off\n"); gi.cvar_forceset(use_3teams->name, "0"); } if (use_tourney->value) { gi.dprintf ("Team Deathmatch Enabled - Forcing Tourney off\n"); gi.cvar_forceset(use_tourney->name, "0"); } } else if (use_3teams->value) { teamCount = 3; if (!teamplay->value) { gi.dprintf ("3 Teams Enabled - Forcing teamplay on\n"); gi.cvar_forceset(teamplay->name, "1"); } if (use_tourney->value) { gi.dprintf ("3 Teams Enabled - Forcing Tourney off\n"); gi.cvar_forceset(use_tourney->name, "0"); } if (!use_oldspawns->value) { gi.dprintf ("3 Teams Enabled - Forcing use_oldspawns on\n"); gi.cvar_forceset(use_oldspawns->name, "1"); } } else if (matchmode->value) { if (!teamplay->value) { gi.dprintf ("Matchmode Enabled - Forcing teamplay on\n"); gi.cvar_forceset(teamplay->name, "1"); } if (use_tourney->value) { gi.dprintf ("Matchmode Enabled - Forcing Tourney off\n"); gi.cvar_forceset(use_tourney->name, "0"); } } else if (use_tourney->value) { if (!teamplay->value) { gi.dprintf ("Tourney Enabled - Forcing teamplay on\n"); gi.cvar_forceset(teamplay->name, "1"); } } skill_level = floor (skill->value); if (skill_level < 0) skill_level = 0; if (skill_level > 3) skill_level = 3; if (skill->value != skill_level) gi.cvar_forceset ("skill", va("%f", skill_level)); SaveClientData (); gi.FreeTags (TAG_LEVEL); memset (&level, 0, sizeof (level)); memset (g_edicts, 0, game.maxentities * sizeof (g_edicts[0])); 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; i < game.maxclients; i++) g_edicts[i + 1].client = game.clients + i; // parse ents while (1) { // parse the opening brace com_token = COM_Parse (&entities); if (!entities) break; if (com_token[0] != '{') gi.error ("ED_LoadFromFile: found %s when expecting {", com_token); if (!ent) ent = g_edicts; else ent = G_Spawn (); entities = ED_ParseEdict (entities, ent); // yet another map hack if (!Q_stricmp (level.mapname, "command") && !Q_stricmp (ent->classname, "trigger_once") && !Q_stricmp (ent->model, "*27")) ent->spawnflags &= ~SPAWNFLAG_NOT_HARD; // remove things (except the world) from different skill levels or deathmatch if (ent != g_edicts) { if (deathmatch->value) { if (ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH) { G_FreeEdict (ent); inhibit++; continue; } } else { if ( /* ((coop->value) && (ent->spawnflags & SPAWNFLAG_NOT_COOP)) || */ ((skill->value == 0) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) || ((skill->value == 1) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) || (((skill->value == 2) || (skill->value == 3)) && (ent->spawnflags & SPAWNFLAG_NOT_HARD))) { G_FreeEdict (ent); inhibit++; continue; } } ent->spawnflags &= ~(SPAWNFLAG_NOT_EASY | SPAWNFLAG_NOT_MEDIUM | SPAWNFLAG_NOT_HARD | SPAWNFLAG_NOT_COOP | SPAWNFLAG_NOT_DEATHMATCH); } ED_CallSpawn (ent); } gi.dprintf ("%i entities inhibited\n", inhibit); // AQ2:TNG Igor adding .flg files // CTF configuration if(ctf->value) { if(!CTFLoadConfig(level.mapname)) { if ((!G_Find(NULL, FOFS (classname), "item_flag_team1") || !G_Find(NULL, FOFS (classname), "item_flag_team2"))) { gi.dprintf ("No native CTF map, loading flag positions from file\n"); if (LoadFlagsFromFile (level.mapname)) ChangePlayerSpawns (); } } } // AQ2:TNG End adding .flg files G_FindTeams (); PlayerTrail_Init (); // TNG:Freud - Ghosts num_ghost_players = 0; //FIREBLADE if (!teamplay->value || teamdm->value || ctf->value == 2) { //FIREBLADE //zucc for special items SetupSpecSpawn (); } else if (teamplay->value) { GetSpawnPoints (); //TNG:Freud - New spawning system if(!use_oldspawns->value) NS_GetSpawnPoints(); } //AQ2:TNG Slicer - New location code memset (ml_build, 0, sizeof (ml_build)); memset (ml_creator, 0, sizeof (ml_creator)); game_cvar = gi.cvar ("game", "", 0); if (!*game_cvar->string) Com_sprintf(locfile, sizeof(locfile), "%s/tng/%s.aqg", GAMEVERSION, level.mapname); else Com_sprintf(locfile, sizeof(locfile), "%s/tng/%s.aqg", game_cvar->string, level.mapname); f = fopen (locfile, "rt"); if (!f) { ml_count = 0; gi.dprintf ("No location file for %s\n", level.mapname); return; } gi.dprintf ("Location file: %s\n", level.mapname); readmore = 1; count = 0; while (readmore) { readmore = (fgets (line, 256, f) != NULL); param = strtok (line, " :\r\n\0"); if (line[0] == '#' && line[2] == 'C') { u = 0; for (i = 10; line[i] != '\n'; i++) { if (line[i] == '\r') continue; ml_creator[u] = line[i]; u++; } } if (line[0] == '#' && line[2] == 'B') { u = 0; for (i = 8; line[i] != '\n'; i++) { if (line[i] != ' ' && line[i] != '\r') { ml_build[u] = line[i]; u++; } } } ml_build[5] = 0; ml_creator[100] = 0; // TODO: better support for file comments if (!param || param[0] == '#') continue; x = atoi (param); param = strtok (NULL, " :\r\n\0"); if (!param) continue; y = atoi (param); param = strtok (NULL, " :\r\n\0"); if (!param) continue; z = atoi (param); param = strtok (NULL, " :\r\n\0"); if (!param) continue; rx = atoi (param); param = strtok (NULL, " :\r\n\0"); if (!param) continue; ry = atoi (param); param = strtok (NULL, " :\r\n\0"); if (!param) continue; rz = atoi (param); param = strtok (NULL, "\r\n\0"); if (!param) continue; locationstr = param; locationbase[count].x = x; locationbase[count].y = y; locationbase[count].z = z; locationbase[count].rx = rx; locationbase[count].ry = ry; locationbase[count].rz = rz; Q_strncpyz (locationbase[count].desc, locationstr, sizeof(locationbase[count].desc)); count++; if (count >= MAX_LOCATIONS_IN_BASE) { gi.dprintf ("Cannot read more than %d locations.\n", MAX_LOCATIONS_IN_BASE); break; } } ml_count = count; fclose (f); gi.dprintf ("Found %d locations.\n", count); }
/* ============== 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, char *spawnpoint) { edict_t *ent; int inhibit; char *com_token; int i; float skill_level; extern int max_modelindex; extern int max_soundindex; extern int lastgibframe; if (developer->value) gi.dprintf("====== SpawnEntities ========\n"); skill_level = floor (skill->value); if (skill_level < 0) skill_level = 0; if (skill_level > 3) skill_level = 3; if (skill->value != skill_level) gi.cvar_forceset("skill", va("%f", skill_level)); SaveClientData (); gi.FreeTags (TAG_LEVEL); memset (&level, 0, sizeof(level)); memset (g_edicts, 0, game.maxentities * sizeof (g_edicts[0])); // Lazarus: these are used to track model and sound indices // in g_main.c: max_modelindex = 0; max_soundindex = 0; // Lazarus: last frame a gib was spawned in lastgibframe = 0; strncpy (level.mapname, mapname, sizeof(level.mapname)-1); strncpy (game.spawnpoint, spawnpoint, sizeof(game.spawnpoint)-1); // set client fields on player ents for (i=0 ; i<game.maxclients ; i++) g_edicts[i+1].client = game.clients + i; ent = NULL; inhibit = 0; // Knightamre- load the entity alias script file LoadAliasData(); //gi.dprintf ("Size of alias data: %i\n", alias_data_size); // parse ents while (1) { // parse the opening brace com_token = COM_Parse (&entities); if (!entities) break; if (com_token[0] != '{') gi.error ("ED_LoadFromFile: found %s when expecting {",com_token); if (!ent) ent = g_edicts; else ent = G_Spawn (); entities = ED_ParseEdict (entities, ent); // yet another map hack if (!Q_stricmp(level.mapname, "command") && !Q_stricmp(ent->classname, "trigger_once") && !Q_stricmp(ent->model, "*27")) ent->spawnflags &= ~SPAWNFLAG_NOT_HARD; // remove things (except the world) from different skill levels or deathmatch if (ent != g_edicts) { if (deathmatch->value) { if ( ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH ) { G_FreeEdict (ent); inhibit++; continue; } } else if (coop->value) // Knightmare added- not in coop flag support { if ( ent->spawnflags & SPAWNFLAG_NOT_COOP ) { G_FreeEdict (ent); inhibit++; continue; } // NOT_EASY && NOT_MEDIUM && NOT_HARD && NOT_DM == COOP_ONLY if ( (ent->spawnflags & SPAWNFLAG_NOT_EASY) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM) && (ent->spawnflags & SPAWNFLAG_NOT_HARD) && (ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH) ) goto removeflags; if( ((skill->value == 0) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) || ((skill->value == 1) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) || ((skill->value >= 2) && (ent->spawnflags & SPAWNFLAG_NOT_HARD)) ) { G_FreeEdict (ent); inhibit++; continue; } } else // single player { if( ((skill->value == 0) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) || ((skill->value == 1) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) || ((skill->value >= 2) && (ent->spawnflags & SPAWNFLAG_NOT_HARD)) ) { G_FreeEdict (ent); inhibit++; continue; } } removeflags: // Knightmare- remove no coop flag ent->spawnflags &= ~(SPAWNFLAG_NOT_EASY|SPAWNFLAG_NOT_MEDIUM|SPAWNFLAG_NOT_HARD|SPAWNFLAG_NOT_DEATHMATCH|SPAWNFLAG_NOT_COOP); } ED_CallSpawn (ent); ent->s.renderfx |= RF_IR_VISIBLE; // ir goggles flag } // Knightmare- unload the alias script file if (alias_data) { // If no alias file was loaded, don't bother #ifdef KMQUAKE2_ENGINE_MOD // use new engine function instead gi.FreeFile(alias_data); #else if (alias_from_pak) gi.TagFree(alias_data); else free(&alias_data); #endif } // Knightmare- unload the replacement entity data /* if (newents) // If no alias file was loaded, don't bother #ifdef KMQUAKE2_ENGINE_MOD // use new engine function instead gi.FreeFile(newents); #else free(&newents); #endif*/ gi.dprintf ("%i entities inhibited\n", inhibit); #ifdef DEBUG i = 1; ent = EDICT_NUM(i); while (i < globals.num_edicts) { if (ent->inuse != 0 || ent->inuse != 1) Com_DPrintf("Invalid entity %d\n", i); i++, ent++; } #endif G_FindTeams (); // DWH G_FindCraneParts(); // Get origin offsets (mainly for brush models w/o origin brushes) for (i=1, ent=g_edicts+i ; i < globals.num_edicts ; i++,ent++) { VectorAdd(ent->absmin,ent->absmax,ent->origin_offset); VectorScale(ent->origin_offset,0.5,ent->origin_offset); VectorSubtract(ent->origin_offset,ent->s.origin,ent->origin_offset); } // end DWH PlayerTrail_Init (); //ZOID CTFSpawn(); // Knightmare added if (deathmatch->value && !ctf->value) CTFSetupTechSpawn(); //ZOID if (!deathmatch->value) SetupHintPaths(); for(i=1, ent=g_edicts+i; i < globals.num_edicts; i++, ent++) { if(!ent->movewith) continue; if(ent->movewith_ent) continue; ent->movewith_ent = G_Find(NULL,FOFS(targetname),ent->movewith); // Make sure that we can really "movewith" this guy. This check // allows us to have movewith parent with same targetname as // other entities while(ent->movewith_ent && (Q_stricmp(ent->movewith_ent->classname,"func_train") && Q_stricmp(ent->movewith_ent->classname,"model_train") && Q_stricmp(ent->movewith_ent->classname,"func_door") && Q_stricmp(ent->movewith_ent->classname,"func_vehicle") && Q_stricmp(ent->movewith_ent->classname,"func_tracktrain") )) ent->movewith_ent = G_Find(ent->movewith_ent,FOFS(targetname),ent->movewith); if(ent->movewith_ent) movewith_init(ent->movewith_ent); } /* for(i=1, ent=g_edicts+i; i < globals.num_edicts; i++, ent++) { gi.dprintf("%s:%s - movewith=%s, movewith_ent=%s:%s, movewith_next=%s:%s\n====================\n", ent->classname, (ent->targetname ? ent->targetname : "noname"), (ent->movewith ? ent->movewith : "N/A"), (ent->movewith_ent ? ent->movewith_ent->classname : "N/A"), (ent->movewith_ent ? (ent->movewith_ent->targetname ? ent->movewith_ent->targetname : "noname") : "N/A"), (ent->movewith_next ? ent->movewith_next->classname : "N/A"), (ent->movewith_next ? (ent->movewith_next->targetname ? ent->movewith_next->targetname : "noname") : "N/A")); } */ if(game.transition_ents) LoadTransitionEnts(); actor_files(); }
void ParseEntityString (qboolean respawn) { edict_t *ent; int inhibit; const char *com_token; const char *entities; int i; entities = level.entity_string; ent = NULL; inhibit = 0; i = 0; //mark all the spawned_entities as inuse so G_Spawn doesn't try to pick them during //trigger spawning etc for (i = 0; i < num_spawned_entities; i++) spawned_entities[i]->inuse = true; i = 0; // parse ents while (1) { // parse the opening brace com_token = COM_Parse (&entities); if (!entities) break; if (com_token[0] != '{') gi.error ("ED_LoadFromFile: found %s when expecting {",com_token); if (respawn) { ent = spawned_entities[i]; if (ent != world) { //double check we aren't overwriting stuff that we shouldn't be if (ent->enttype == ENT_DOOR_TRIGGER || ent->enttype == ENT_PLAT_TRIGGER) TDM_Error ("ParseEntityString: Trying to reuse an already spawned ent!"); G_FreeEdict (ent); G_InitEdict (ent); } i++; } else { if (!ent) ent = g_edicts; else ent = G_Spawn (); } entities = ED_ParseEdict (entities, ent); // yet another map hack if (!Q_stricmp(level.mapname, "command") && !Q_stricmp(ent->classname, "trigger_once") && !Q_stricmp(ent->model, "*27")) ent->spawnflags &= ~SPAWNFLAG_NOT_HARD; // remove things (except the world) from different skill levels or deathmatch if (ent != g_edicts) { if ( ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH ) { G_FreeEdict (ent); inhibit++; //have to keep num_spawned in sync for respawn if (!respawn) spawned_entities[num_spawned_entities++] = ent; continue; } ent->spawnflags &= ~(SPAWNFLAG_NOT_EASY|SPAWNFLAG_NOT_MEDIUM|SPAWNFLAG_NOT_HARD|SPAWNFLAG_NOT_COOP|SPAWNFLAG_NOT_DEATHMATCH); } else if (respawn) continue; ED_CallSpawn (ent); if (!respawn) { if (num_spawned_entities == MAX_EDICTS * 4) TDM_Error ("Exceeded MAX_EDICTS * 4 entities during entity string parse"); spawned_entities[num_spawned_entities++] = ent; } else { //an elevator or something respawned on top of a player? don't do it for match start, since //players will be respawning anyway. if (tdm_match_status < MM_PLAYING && (ent->solid == SOLID_BBOX || ent->solid == SOLID_BSP)) { edict_t *touch[MAX_EDICTS]; int count; int j; //r1: fix 00000196, can't killbox during map spawn due to risk of killing half-spawned //map entities. do a pseudo-killbox that only whacks players instead. count = gi.BoxEdicts (ent->absmin, ent->absmax, touch, MAX_EDICTS, AREA_SOLID); for (j = 0; j < count; j++) { if (touch[j] == ent) continue; //no point killing anything that won't clip (eg corpses) if (touch[j]->solid == SOLID_NOT || touch[j]->enttype == ENT_BODYQUE) continue; if (!touch[j]->client) continue; if (touch[j]->inuse) T_Damage (touch[j], ent, ent, vec3_origin, ent->s.origin, vec3_origin, 100000, 0, DAMAGE_NO_PROTECTION, MOD_TELEFRAG); } } } } //gi.dprintf ("%i entities inhibited\n", inhibit); #ifdef DEBUG i = 1; ent = EDICT_NUM(i); while (i < globals.num_edicts) { if (ent->inuse != 0 || ent->inuse != 1) Com_DPrintf("Invalid entity %d\n", i); i++, ent++; } #endif G_FindTeams (); }
void G_ResetLevel(void) { gclient_t *client; edict_t *ent; int i; gi.FreeTags(TAG_LEVEL); #if USE_SQLITE G_LogClients(); #endif G_FinishVote(); // clear level level.framenum = 0; level.time = 0; level.intermission_framenum = 0; level.intermission_exit = 0; level.vote.proposal = 0; level.nextmap[0] = 0; level.record = 0; level.players_in = level.players_out = 0; // free all edicts for (i = game.maxclients + 1; i < globals.num_edicts; i++) { ent = &g_edicts[i]; if (ent->inuse) { G_FreeEdict(ent); } } globals.num_edicts = game.maxclients + 1; InitBodyQue(); // respawn all edicts G_ParseString(); G_FindTeams(); //G_UpdateItemBans(); // respawn all clients for (i = 0; i < game.maxclients; i++) { client = &game.clients[i]; if (!client->pers.connected) { continue; } memset(&client->resp, 0, sizeof(client->resp)); memset(&client->level.vote, 0, sizeof(client->level.vote)); if (client->pers.connected == CONN_SPAWNED) { ent = client->edict; G_ScoreChanged(ent); ent->movetype = MOVETYPE_NOCLIP; // do not leave body respawn(ent); } } G_UpdateRanks(); if (timelimit->value > 0) { int remaining = timelimit->value * 60 - level.time; G_WriteTime(remaining); gi.multicast(NULL, MULTICAST_ALL); } // allow everything to settle G_RunFrame(); G_RunFrame(); // make sure movers are not interpolated for (i = game.maxclients + 1; i < globals.num_edicts; i++) { ent = &g_edicts[i]; if (ent->inuse && ent->movetype) { ent->s.event = EV_OTHER_TELEPORT; } } }
/* ============== SpawnEntities Creates a server's entity / program execution context by parsing textual entity definitions out of an ent file. ============== */ void G_SpawnEntities(const char *mapname, const char *entities, const char *spawnpoint) { edict_t *ent; gclient_t *client; int i; client_persistant_t pers; char *token; char playerskin[MAX_QPATH]; #if USE_SQLITE G_OpenDatabase(); G_LogClients(); #endif gi.FreeTags(TAG_LEVEL); memset(&level, 0, sizeof(level)); memset(g_edicts, 0, game.maxentities * sizeof(g_edicts[0])); Q_strlcpy(level.mapname, mapname, sizeof(level.mapname)); G_LoadScores(); // set client fields on player ents for (i = 0; i < game.maxclients; i++) { ent = &g_edicts[i + 1]; client = &game.clients[i]; ent->client = client; ent->inuse = qfalse; if (!client->pers.connected) { continue; } // clear everything but the persistant data pers = client->pers; memset(client, 0, sizeof(*client)); client->pers = pers; client->edict = ent; client->clientNum = i; client->pers.connected = CONN_CONNECTED; // combine name and skin into a configstring Q_concat(playerskin, sizeof(playerskin), client->pers.netname, "\\", client->pers.skin, NULL); gi.configstring(CS_PLAYERSKINS + i, playerskin); gi.configstring(CS_PLAYERNAMES + i, client->pers.netname); } // parse worldspawn token = COM_Parse(&entities); if (!entities) gi.error("%s: empty entity string", __func__); if (token[0] != '{') gi.error("%s: found %s when expecting {", __func__, token); ent = g_edicts; ED_ParseEdict(&entities, ent); ED_CallSpawn(ent); level.entstring = entities; G_ParseString(); G_FindTeams(); //G_UpdateItemBans(); // find spawnpoints ent = NULL; while ((ent = G_Find(ent, FOFS(classname), "info_player_deathmatch")) != NULL) { level.spawns[level.numspawns++] = ent; if (level.numspawns == MAX_SPAWNS) { break; } } gi.dprintf("%d spawn points\n", level.numspawns); }
/* ============ G_InitGame ============ */ void G_InitGame( int levelTime, int randomSeed ) { Com_Printf ("------- Game Initialization -------\n"); Com_Printf ("gamename: %s\n", GAME_IDENTIFIER); Com_Printf ("gamedate: %s\n", __DATE__ ); Com_Printf ("mf version: %s\n", MF_VERSION ); srand( randomSeed ); G_RegisterCvars(); G_ProcessIPBans(); G_InitMemory(); // MFQ3: set the game version into a server var (that can be viewed as server-info) Cvar_Set( "mf_version", MF_VERSION ); // MFQ3: (for now) always set the 'g_synchronousClients' var to 0, as setting to 1 // causes glitching/flickering with the models #pragma message( "g_synchronousClients is always being set to 0 in G_InitGame()" ) Cvar_Set( "g_synchronousClients", "0" ); // set some level globals //memset( &level, 0, sizeof( level ) ); theLevel.resetAll(); theLevel.time_ = levelTime; theLevel.startTime_ = levelTime; //level.snd_fry = G_SoundIndex("sound/player/fry.wav"); // FIXME standing in lava / slime if ( g_gametype.integer != GT_SINGLE_PLAYER && g_gametype.integer != GT_MISSION_EDITOR && g_log.string[0] ) { if ( g_logSync.integer ) FS_FOpenFileByMode( g_log.string, &theLevel.logFile_, FS_APPEND_SYNC ); else FS_FOpenFileByMode( g_log.string, &theLevel.logFile_, FS_APPEND ); if ( !theLevel.logFile_ ) Com_Printf( "WARNING: Couldn't open logfile: %s\n", g_log.string ); else { char serverinfo[MAX_INFO_STRING]; SV_GetServerinfo( serverinfo, sizeof( serverinfo ) ); G_LogPrintf("------------------------------------------------------------\n" ); G_LogPrintf("InitGame: %s\n", serverinfo ); } } else Com_Printf( "Not logging to disk.\n" ); G_InitWorldSession(); // initialize all entities for this game //memset( g_entities, 0, MAX_GENTITIES * sizeof(g_entities[0]) ); //level.gentities = g_entities; // initialize all clients for this game theLevel.maxclients_ = g_maxclients.integer; //memset( g_clients, 0, MAX_CLIENTS * sizeof(g_clients[0]) ); //level.clients = g_clients; // set client fields on player ents #pragma message("cant do this with the new system.... find solution!!") //for( int i=1 ; i <= theLevel.maxclients_ ; i++ ) //{ // //g_entities[i].client = level.clients + i; // reinterpret_cast<GameEntity*>(theLevel.gameEntities_.at(i))->client_ = theLevel.clients_.at(i); //} // always leave room for the max number of clients, // even if they aren't all used, so numbers inside that // range are NEVER anything but clients //theLevel.num_entities_ = 0;//MAX_CLIENTS; // let the server system know where the entites are // SV_LocateGameData( (void*)level.gentities, level.num_entities, sizeof( gentity_t ), // &level.clients[0].ps, sizeof( level.clients[0] ) ); theLevel.setServerGameData();// SV_LocateGameData( &theLevel.gameEntities_, &theLevel.clients_ ); ClearRegisteredItems(); // MFQ3 data MF_LoadAllVehicleData(); //DataManager::getInstance().createAllData(); // parse the key/value pairs and spawn gentities G_SpawnEntitiesFromString(); // general initialization G_FindTeams(); // make sure we have flags for CTF, etc if( g_gametype.integer >= GT_TEAM ) G_CheckTeamItems(); SaveRegisteredItems(); Com_Printf ("-----------------------------------\n"); if( g_gametype.integer == GT_SINGLE_PLAYER || Cvar_VariableIntegerValue( "com_buildScript" ) ) { G_SoundIndex( "sound/player/gurp1.wav" ); G_SoundIndex( "sound/player/gurp2.wav" ); } G_RemapTeamShaders(); if( g_gametype.integer != GT_MISSION_EDITOR ) { // MFQ3 mission scripts //G_LoadMissionScripts(); // init some MFQ3 stuff //DroneInit(); } }
/* ============== SpawnEntities Creates a server's entity / program execution context by parsing textual entity definitions out of an ent file. ============== */ void SpawnEntities (const char *mapname, char *entities, const char *spawnpoint) { edict_t *ent; int inhibit; const char *com_token; int i; float skill_level; int oldmaxent; skill_level = floor (skill->value); if (skill_level < 0) skill_level = 0; if (skill_level > 3) skill_level = 3; if (skill->value != skill_level) gi.cvar_forceset("skill", va("%f", skill_level)); SaveClientData (); gi.FreeTags (TAG_LEVEL); memset (&level, 0, sizeof(level)); memset (g_edicts, 0, game.maxentities * sizeof (g_edicts[0])); strncpy (level.mapname, mapname, sizeof(level.mapname)-1); strncpy (game.spawnpoint, spawnpoint, sizeof(game.spawnpoint)-1); // set client fields on player ents for (i=0 ; i<game.maxclients ; i++) g_edicts[i+1].client = game.clients + i; ent = NULL; inhibit = 0; // parse ents while (1) { // parse the opening brace com_token = COM_Parse (&entities); if (!entities) break; if (com_token[0] != '{') gi.error ("ED_LoadFromFile: found %s when expecting {",com_token); if (!ent) ent = g_edicts; else ent = G_Spawn (); ent->spawnflags2 = 0; entities = ED_ParseEdict (entities, ent); // yet another map hack if (!Q_stricmp(level.mapname, "command") && !Q_stricmp(ent->classname, "trigger_once") && !Q_stricmp(ent->model, "*27")) ent->spawnflags &= ~SPAWNFLAG_NOT_HARD; // remove things (except the world) from different skill levels or deathmatch if (ent != g_edicts) { if (deathmatch->value) { if ( (ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH) || (ent->spawnflags2 & SPAWNFLAG2_NOT_SINGLE) ) { G_FreeEdict (ent); inhibit++; continue; } } #if 0 // FIXME: DG: coop stuff from rogue else if (coop->value) { if (ent->spawnflags & SPAWNFLAG_NOT_COOP) { G_FreeEdict(ent); inhibit++; continue; } /* stuff marked !easy & !med & !hard are coop only, all levels */ if (!((ent->spawnflags & SPAWNFLAG_NOT_EASY) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM) && (ent->spawnflags & SPAWNFLAG_NOT_HARD))) { if (((skill->value == 0) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) || ((skill->value == 1) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) || (((skill->value == 2) || (skill->value == 3)) && (ent->spawnflags & SPAWNFLAG_NOT_HARD))) { G_FreeEdict(ent); inhibit++; continue; } } } #endif // 0 else { if (((!coop->value) && (ent->spawnflags2 & SPAWNFLAG2_NOT_SINGLE)) || ((coop->value) && (ent->spawnflags2 & SPAWNFLAG2_NOT_COOP)) || ((skill->value == 0) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) || ((skill->value == 1) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) || (((skill->value == 2) || (skill->value == 3)) && (ent->spawnflags & SPAWNFLAG_NOT_HARD)) ) { G_FreeEdict (ent); inhibit++; continue; } } ent->spawnflags &= ~(SPAWNFLAG_NOT_EASY|SPAWNFLAG_NOT_MEDIUM|SPAWNFLAG_NOT_HARD|SPAWNFLAG_NOT_COOP|SPAWNFLAG_NOT_DEATHMATCH); } ED_CallSpawn (ent); } oldmaxent = globals.num_edicts; gi.dprintf("%i entities created\n", globals.num_edicts); gi.dprintf ("%i entities inhibited\n", inhibit); G_FindTeams (); PlayerTrail_Init (); Z_SpawnDMItems(); }
/* * Creates a server's entity / program execution context by * parsing textual entity definitions out of an ent file. */ void SpawnEntities(const char *mapname, char *entities, const char *spawnpoint) { edict_t *ent; int inhibit; const char *com_token; int i; float skill_level; static qboolean monster_count_city3 = false; if (!mapname || !entities || !spawnpoint) { return; } skill_level = floor(skill->value); if (skill_level < 0) { skill_level = 0; } if (skill_level > 3) { skill_level = 3; } if (skill->value != skill_level) { gi.cvar_forceset("skill", va("%f", skill_level)); } SaveClientData(); gi.FreeTags(TAG_LEVEL); memset(&level, 0, sizeof(level)); memset(g_edicts, 0, game.maxentities * sizeof(g_edicts[0])); Q_strlcpy(level.mapname, mapname, sizeof(level.mapname)); Q_strlcpy(game.spawnpoint, spawnpoint, sizeof(game.spawnpoint)); /* set client fields on player ents */ for (i = 0; i < game.maxclients; i++) { g_edicts[i + 1].client = game.clients + i; } ent = NULL; inhibit = 0; /* parse ents */ while (1) { /* parse the opening brace */ com_token = COM_Parse(&entities); if (!entities) { break; } if (com_token[0] != '{') { gi.error("ED_LoadFromFile: found %s when expecting {", com_token); } if (!ent) { ent = g_edicts; } else { ent = G_Spawn(); } entities = ED_ParseEdict(entities, ent); /* yet another map hack */ if (!Q_stricmp(level.mapname, "command") && !Q_stricmp(ent->classname, "trigger_once") && !Q_stricmp(ent->model, "*27")) { ent->spawnflags &= ~SPAWNFLAG_NOT_HARD; } /* * The 'monsters' count in city3.bsp is wrong. * There're two monsters triggered in a hidden * and unreachable room next to the security * pass. * * We need to make sure that this hack is only * applied once! */ if(!Q_stricmp(level.mapname, "city3") && !monster_count_city3) { level.total_monsters = level.total_monsters - 2; monster_count_city3 = true; } /* remove things (except the world) from different skill levels or deathmatch */ if (ent != g_edicts) { if (deathmatch->value) { if (ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH) { G_FreeEdict(ent); inhibit++; continue; } } else { if (((skill->value == 0) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) || ((skill->value == 1) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) || (((skill->value == 2) || (skill->value == 3)) && (ent->spawnflags & SPAWNFLAG_NOT_HARD)) ) { G_FreeEdict(ent); inhibit++; continue; } } ent->spawnflags &= ~(SPAWNFLAG_NOT_EASY | SPAWNFLAG_NOT_MEDIUM | SPAWNFLAG_NOT_HARD | SPAWNFLAG_NOT_COOP | SPAWNFLAG_NOT_DEATHMATCH); } ED_CallSpawn(ent); } gi.dprintf("%i entities inhibited.\n", inhibit); G_FindTeams(); PlayerTrail_Init(); }