Initial commit.
This commit is contained in:
402
code/game/g_ref.cpp
Normal file
402
code/game/g_ref.cpp
Normal file
@@ -0,0 +1,402 @@
|
||||
// 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 );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user