123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402 |
- // Reference tag utility functions
- // leave this line at the top for all g_xxxx.cpp files...
- #include "g_headers.h"
- #include "g_local.h"
- #include "g_functions.h"
- #include "g_nav.h"
- extern int delayedShutDown;
- #define TAG_GENERIC_NAME "__WORLD__" //If a designer chooses this name, cut a finger off as an example to the others
- typedef vector < reference_tag_t * > refTag_v;
- typedef map < string, reference_tag_t * > refTag_m;
- typedef struct tagOwner_s
- {
- refTag_v tags;
- refTag_m tagMap;
- } tagOwner_t;
- typedef map < string, tagOwner_t * > refTagOwner_m;
- refTagOwner_m refTagOwnerMap;
- /*
- -------------------------
- TAG_ShowTags
- -------------------------
- */
- void TAG_ShowTags( int flags )
- {
- refTagOwner_m::iterator rtoi;
- STL_ITERATE( rtoi, refTagOwnerMap )
- {
- refTag_v::iterator rti;
- STL_ITERATE( rti, (((*rtoi).second)->tags) )
- {
- if ( (*rti)->flags & RTF_NAVGOAL )
- {
- if ( gi.inPVS( g_entities[0].currentOrigin, (*rti)->origin ) )
- CG_DrawNode( (*rti)->origin, NODE_NAVGOAL );
- }
- }
- }
- }
- /*
- -------------------------
- TAG_Init
- -------------------------
- */
- void TAG_Init( void )
- {
- refTagOwner_m::iterator rtoi;
- //Delete all owners
- for ( rtoi = refTagOwnerMap.begin(); rtoi != refTagOwnerMap.end(); rtoi++ )
- {
- if ( (*rtoi).second == NULL )
- {
- assert( 0 ); //FIXME: This is not good
- continue;
- }
- refTag_v::iterator rti;
-
- //Delete all tags within the owner's scope
- for ( rti = ((*rtoi).second)->tags.begin(); rti != ((*rtoi).second)->tags.end(); rti++ )
- {
- if ( (*rti) == NULL )
- {
- assert( 0 ); //FIXME: Bad bad
- continue;
- }
- //Free it
- delete (*rti);
- }
- //Clear the containers
- ((*rtoi).second)->tags.clear();
- ((*rtoi).second)->tagMap.clear();
- //Delete the owner
- delete ((*rtoi).second);
- }
- //Clear the container
- refTagOwnerMap.clear();
- }
- /*
- -------------------------
- TAG_FindOwner
- -------------------------
- */
- tagOwner_t *TAG_FindOwner( const char *owner )
- {
- refTagOwner_m::iterator rtoi;
- rtoi = refTagOwnerMap.find( owner );
- if ( rtoi == refTagOwnerMap.end() )
- return NULL;
- return (*rtoi).second;
- }
- /*
- -------------------------
- TAG_Find
- -------------------------
- */
- reference_tag_t *TAG_Find( const char *owner, const char *name )
- {
- tagOwner_t *tagOwner;
- tagOwner = VALIDSTRING( owner ) ? TAG_FindOwner( owner ) : TAG_FindOwner( TAG_GENERIC_NAME );
- //Not found...
- if ( tagOwner == NULL )
- {
- tagOwner = TAG_FindOwner( TAG_GENERIC_NAME );
- if ( tagOwner == NULL )
- return NULL;
- }
- refTag_m::iterator rti;
- rti = tagOwner->tagMap.find( name );
- if ( rti == tagOwner->tagMap.end() )
- {
- //Try the generic owner instead
- tagOwner = TAG_FindOwner( TAG_GENERIC_NAME );
- if ( tagOwner == NULL )
- return NULL;
- char tempName[ MAX_REFNAME ];
- Q_strncpyz( (char *) tempName, name, MAX_REFNAME );
- strlwr( (char *) tempName ); //NOTENOTE: For case insensitive searches on a map
- rti = tagOwner->tagMap.find( tempName );
-
- if ( rti == tagOwner->tagMap.end() )
- return NULL;
- }
- return (*rti).second;
- }
- /*
- -------------------------
- TAG_Add
- -------------------------
- */
- reference_tag_t *TAG_Add( const char *name, const char *owner, vec3_t origin, vec3_t angles, int radius, int flags )
- {
- reference_tag_t *tag = new reference_tag_t;
- VALIDATEP( tag );
-
- //Copy the information
- VectorCopy( origin, tag->origin );
- VectorCopy( angles, tag->angles );
- tag->radius = radius;
- tag->flags = flags;
- if ( VALIDSTRING( name ) == false )
- {
- //gi.Error("Nameless ref_tag found at (%i %i %i)", (int)origin[0], (int)origin[1], (int)origin[2]);
- gi.Printf(S_COLOR_RED"ERROR: Nameless ref_tag found at (%i %i %i)\n", (int)origin[0], (int)origin[1], (int)origin[2]);
- delayedShutDown = level.time + 100;
- return NULL;
- }
- //Copy the name
- Q_strncpyz( (char *) tag->name, name, MAX_REFNAME );
- strlwr( (char *) tag->name ); //NOTENOTE: For case insensitive searches on a map
- //Make sure this tag's name isn't alread in use
- if ( TAG_Find( owner, name ) )
- {
- delayedShutDown = level.time + 100;
- gi.Printf(S_COLOR_RED"ERROR: Duplicate tag name \"%s\"\n", name );
- return NULL;
- }
- //Attempt to add this to the owner's list
- if ( VALIDSTRING( owner ) == false )
- {
- //If the owner isn't found, use the generic world name
- owner = TAG_GENERIC_NAME;
- }
- tagOwner_t *tagOwner = TAG_FindOwner( owner );
-
- //If the owner is valid, add this tag to it
- if VALID( tagOwner )
- {
- tagOwner->tags.insert( tagOwner->tags.end(), tag );
- tagOwner->tagMap[ (char*) &tag->name ] = tag;
- }
- else
- {
- //Create a new owner list
- tagOwner_t *tagOwner = new tagOwner_t;
- VALIDATEP( tagOwner );
- //Insert the information
- tagOwner->tags.insert( tagOwner->tags.end(), tag );
- tagOwner->tagMap[ (char *) tag->name ] = tag;
- //Map it
- refTagOwnerMap[ owner ] = tagOwner;
- }
- return tag;
- }
- /*
- -------------------------
- TAG_GetOrigin
- -------------------------
- */
- int TAG_GetOrigin( const char *owner, const char *name, vec3_t origin )
- {
- reference_tag_t *tag = TAG_Find( owner, name );
- if (!tag)
- {
- VectorClear(origin);
- return false;
- }
- VALIDATEB( tag );
- VectorCopy( tag->origin, origin );
- return true;
- }
- /*
- -------------------------
- TAG_GetOrigin2
- Had to get rid of that damn assert for dev
- -------------------------
- */
- int TAG_GetOrigin2( const char *owner, const char *name, vec3_t origin )
- {
- reference_tag_t *tag = TAG_Find( owner, name );
- if( tag == NULL )
- {
- return qfalse;
- }
- VectorCopy( tag->origin, origin );
- return qtrue;
- }
- /*
- -------------------------
- TAG_GetAngles
- -------------------------
- */
- int TAG_GetAngles( const char *owner, const char *name, vec3_t angles )
- {
- reference_tag_t *tag = TAG_Find( owner, name );
- VALIDATEB( tag );
- VectorCopy( tag->angles, angles );
-
- return true;
- }
- /*
- -------------------------
- TAG_GetRadius
- -------------------------
- */
- int TAG_GetRadius( const char *owner, const char *name )
- {
- reference_tag_t *tag = TAG_Find( owner, name );
- VALIDATEB( tag );
- return tag->radius;
- }
- /*
- -------------------------
- TAG_GetFlags
- -------------------------
- */
- int TAG_GetFlags( const char *owner, const char *name )
- {
- reference_tag_t *tag = TAG_Find( owner, name );
- VALIDATEB( tag );
- return tag->flags;
- }
- /*
- ==============================================================================
- Spawn functions
- ==============================================================================
- */
- /*QUAKED ref_tag (0.5 0.5 1) (-8 -8 -8) (8 8 8)
- Reference tags which can be positioned throughout the level.
- These tags can later be refered to by the scripting system
- so that their origins and angles can be referred to.
- If you set angles on the tag, these will be retained.
- If you target a ref_tag at an entity, that will set the ref_tag's
- angles toward that entity.
- If you set the ref_tag's ownername to the ownername of an entity,
- it makes that entity is the owner of the ref_tag. This means
- that the owner, and only the owner, may refer to that tag.
- Tags may not have the same name as another tag with the same
- owner. However, tags with different owners may have the same
- name as one another. In this way, scripts can generically
- refer to tags by name, and their owners will automatically
- specifiy which tag is being referred to.
- targetname - the name of this tag
- ownername - the owner of this tag
- target - use to point the tag at something for angles
- */
- void ref_link ( gentity_t *ent )
- {
- reference_tag_t *tag;
- if ( ent->target )
- {
- //TODO: Find the target and set our angles to that direction
- gentity_t *target = G_Find( NULL, FOFS(targetname), ent->target );
- vec3_t dir;
- if ( target )
- {
- //Find the direction to the target
- VectorSubtract( target->s.origin, ent->s.origin, dir );
- VectorNormalize( dir );
- vectoangles( dir, ent->s.angles );
-
- //FIXME: Does pitch get flipped?
- }
- else
- {
- gi.Printf( S_COLOR_RED"ERROR: ref_tag (%s) has invalid target (%s)", ent->targetname, ent->target );
- }
- }
-
- //Add the tag
- tag = TAG_Add( ent->targetname, ent->ownername, ent->s.origin, ent->s.angles, 16, 0 );
- //Delete immediately, cannot be refered to as an entity again
- //NOTE: this means if you wanted to link them in a chain for, say, a path, you can't
- G_FreeEntity( ent );
- }
- void SP_reference_tag ( gentity_t *ent )
- {
- if ( ent->target )
- {
- //Init cannot occur until all entities have been spawned
- ent->e_ThinkFunc = thinkF_ref_link;
- ent->nextthink = level.time + START_TIME_LINK_ENTS;
- }
- else
- {
- ref_link( ent );
- }
- }
|