/* =========================================================================== Wolfenstein: Enemy Territory GPL Source Code Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company. This file is part of the Wolfenstein: Enemy Territory GPL Source Code (“Wolf ET Source Code”). Wolf ET Source Code 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 3 of the License, or (at your option) any later version. Wolf ET Source Code 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 Wolf ET Source Code. If not, see . In addition, the Wolf: ET Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Wolf ET Source Code. If not, please request a copy in writing from id Software at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. =========================================================================== */ /* * name: g_sv_entities.c * * desc: Server sided only map entities */ #include "g_local.h" // TAT 11/13/2002 // The SP uses entities that have no physical manifestation in the game, are are used simply // as locational indicators - seek cover spots, and ai markers, for example // This is an alternate system so those don't clutter up the real game entities // how many of these entities? #define MAX_SERVER_ENTITIES 4096 // for now, statically allocate them g_serverEntity_t g_serverEntities[MAX_SERVER_ENTITIES]; int numServerEntities; // clear out all the sp entities void InitServerEntities( void ) { memset( g_serverEntities, 0, sizeof( g_serverEntities ) ); numServerEntities = 0; } // get the server entity with the passed in number g_serverEntity_t *GetServerEntity( int num ) { // if it's an invalid number, return null if ( ( num < MAX_GENTITIES ) || ( num >= MAX_GENTITIES + numServerEntities ) ) { return NULL; } return &g_serverEntities[num - MAX_GENTITIES]; } g_serverEntity_t *GetFreeServerEntity() { // NOTE: this is simplistic because we can't currently free these entities // if we change this, then we need to be more careful when allocating the entities if ( numServerEntities >= MAX_SERVER_ENTITIES ) { G_Error( "GetFreeServerEntity: Cannot allocate server entity" ); return NULL; } g_serverEntities[numServerEntities].number = MAX_GENTITIES + numServerEntities; g_serverEntities[numServerEntities].inuse = qtrue; return &g_serverEntities[numServerEntities++]; } // Give a gentity_t, create a sp entity, copy all pertinent data, and return it g_serverEntity_t *CreateServerEntity( gentity_t *ent ) { // get the entity out of our pool g_serverEntity_t *newEnt = GetFreeServerEntity(); // if we managed to get one, copy over data if ( newEnt ) { // G_NewString crashes if you pass in NULL, so let's check... if ( ent->classname ) { newEnt->classname = G_NewString( ent->classname ); } if ( ent->targetname ) { newEnt->name = G_NewString( ent->targetname ); } if ( ent->target ) { newEnt->target = G_NewString( ent->target ); } newEnt->spawnflags = ent->spawnflags; newEnt->team = ent->aiTeam; VectorCopy( ent->s.origin, newEnt->origin ); VectorCopy( ent->s.angles, newEnt->angles ); // DON'T set the number - that should have been set when it was spawned // set the areanum to -1, which means we haven't calculated it yet // these don't move, so we should only have to calc it once, the first // time someone asks for it newEnt->areaNum = -1; } return newEnt; } // TAT - create the server entities for the current map void CreateMapServerEntities(); // These server entities don't get to update every frame, but some of them have to set themselves up // after they've all been created // So we want to give each entity the chance to set itself up after it has been created void InitialServerEntitySetup() { int i; g_serverEntity_t *ent; // TAT - create the server entities for the current map // these are read from an additional file CreateMapServerEntities(); for ( i = 0; i < numServerEntities; i++ ) { ent = &g_serverEntities[i]; // if this entity is in use and has a setup function if ( ent->inuse && ent->setup ) { // call it ent->setup( ent ); } } } // Like G_Find, but for server entities g_serverEntity_t *FindServerEntity( g_serverEntity_t *from, int fieldofs, char *match ) { char *s; g_serverEntity_t *max = &g_serverEntities[numServerEntities]; if ( !from ) { from = g_serverEntities; } else { from++; } for ( ; from < max ; from++ ) { if ( !from->inuse ) { continue; } s = *( char ** )( (byte *)from + fieldofs ); if ( !s ) { continue; } if ( !Q_stricmp( s, match ) ) { return from; } } return NULL; } // TAT 11/18/2002 // For the (possibly temporary) system of loading a separate file of these server entities extern void SP_SeekCover_Setup( g_serverEntity_t *ent ); extern void SP_AIMarker_Setup( g_serverEntity_t *ent ); // We have to hardcode the setup functions for these void InitServerEntitySetupFunc( g_serverEntity_t *ent ) { if ( strcmp( ent->classname, "ai_marker" ) == 0 ) { ent->setup = SP_AIMarker_Setup; } else if ( strcmp( ent->classname, "bot_seek_cover_spot" ) == 0 ) { // set the team to allies ent->team = TEAM_ALLIES; // set the setup func ent->setup = SP_SeekCover_Setup; } else if ( strcmp( ent->classname, "bot_axis_seek_cover_spot" ) == 0 ) { // set the team to axis ent->team = TEAM_AXIS; // set the setup func ent->setup = SP_SeekCover_Setup; } } // Create a server entity from some basic data void CreateServerEntityFromData( char* classname, char* targetname, char* target, vec3_t origin, int spawnflags, vec3_t angle ) { // get the entity out of our pool g_serverEntity_t *newEnt = GetFreeServerEntity(); // if we managed to get one, copy over data if ( newEnt ) { // G_NewString crashes if you pass in NULL, so let's check... if ( classname ) { newEnt->classname = G_NewString( classname ); } if ( targetname ) { newEnt->name = G_NewString( targetname ); } if ( target ) { newEnt->target = G_NewString( target ); } newEnt->spawnflags = spawnflags; //newEnt->team = ent->aiTeam; VectorCopy( origin, newEnt->origin ); VectorCopy( angle, newEnt->angles ); // DON'T set the number - that should have been set when it was spawned // set the areanum to -1, which means we haven't calculated it yet // these don't move, so we should only have to calc it once, the first // time someone asks for it newEnt->areaNum = -1; // and do class specific stuff InitServerEntitySetupFunc( newEnt ); } } // TAT - create the server entities for the current map void CreateMapServerEntities() { char info[1024]; char mapname[128]; trap_GetServerinfo( info, sizeof( info ) ); Q_strncpyz( mapname, Info_ValueForKey( info, "mapname" ), sizeof( mapname ) ); }