g_ref.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. // Reference tag utility functions
  2. // leave this line at the top for all g_xxxx.cpp files...
  3. #include "g_headers.h"
  4. #include "g_local.h"
  5. #include "g_functions.h"
  6. #include "g_nav.h"
  7. extern int delayedShutDown;
  8. #define TAG_GENERIC_NAME "__WORLD__" //If a designer chooses this name, cut a finger off as an example to the others
  9. typedef vector < reference_tag_t * > refTag_v;
  10. typedef map < string, reference_tag_t * > refTag_m;
  11. typedef struct tagOwner_s
  12. {
  13. refTag_v tags;
  14. refTag_m tagMap;
  15. } tagOwner_t;
  16. typedef map < string, tagOwner_t * > refTagOwner_m;
  17. refTagOwner_m refTagOwnerMap;
  18. /*
  19. -------------------------
  20. TAG_ShowTags
  21. -------------------------
  22. */
  23. void TAG_ShowTags( int flags )
  24. {
  25. refTagOwner_m::iterator rtoi;
  26. STL_ITERATE( rtoi, refTagOwnerMap )
  27. {
  28. refTag_v::iterator rti;
  29. STL_ITERATE( rti, (((*rtoi).second)->tags) )
  30. {
  31. if ( (*rti)->flags & RTF_NAVGOAL )
  32. {
  33. if ( gi.inPVS( g_entities[0].currentOrigin, (*rti)->origin ) )
  34. CG_DrawNode( (*rti)->origin, NODE_NAVGOAL );
  35. }
  36. }
  37. }
  38. }
  39. /*
  40. -------------------------
  41. TAG_Init
  42. -------------------------
  43. */
  44. void TAG_Init( void )
  45. {
  46. refTagOwner_m::iterator rtoi;
  47. //Delete all owners
  48. for ( rtoi = refTagOwnerMap.begin(); rtoi != refTagOwnerMap.end(); rtoi++ )
  49. {
  50. if ( (*rtoi).second == NULL )
  51. {
  52. assert( 0 ); //FIXME: This is not good
  53. continue;
  54. }
  55. refTag_v::iterator rti;
  56. //Delete all tags within the owner's scope
  57. for ( rti = ((*rtoi).second)->tags.begin(); rti != ((*rtoi).second)->tags.end(); rti++ )
  58. {
  59. if ( (*rti) == NULL )
  60. {
  61. assert( 0 ); //FIXME: Bad bad
  62. continue;
  63. }
  64. //Free it
  65. delete (*rti);
  66. }
  67. //Clear the containers
  68. ((*rtoi).second)->tags.clear();
  69. ((*rtoi).second)->tagMap.clear();
  70. //Delete the owner
  71. delete ((*rtoi).second);
  72. }
  73. //Clear the container
  74. refTagOwnerMap.clear();
  75. }
  76. /*
  77. -------------------------
  78. TAG_FindOwner
  79. -------------------------
  80. */
  81. tagOwner_t *TAG_FindOwner( const char *owner )
  82. {
  83. refTagOwner_m::iterator rtoi;
  84. rtoi = refTagOwnerMap.find( owner );
  85. if ( rtoi == refTagOwnerMap.end() )
  86. return NULL;
  87. return (*rtoi).second;
  88. }
  89. /*
  90. -------------------------
  91. TAG_Find
  92. -------------------------
  93. */
  94. reference_tag_t *TAG_Find( const char *owner, const char *name )
  95. {
  96. tagOwner_t *tagOwner;
  97. tagOwner = VALIDSTRING( owner ) ? TAG_FindOwner( owner ) : TAG_FindOwner( TAG_GENERIC_NAME );
  98. //Not found...
  99. if ( tagOwner == NULL )
  100. {
  101. tagOwner = TAG_FindOwner( TAG_GENERIC_NAME );
  102. if ( tagOwner == NULL )
  103. return NULL;
  104. }
  105. refTag_m::iterator rti;
  106. rti = tagOwner->tagMap.find( name );
  107. if ( rti == tagOwner->tagMap.end() )
  108. {
  109. //Try the generic owner instead
  110. tagOwner = TAG_FindOwner( TAG_GENERIC_NAME );
  111. if ( tagOwner == NULL )
  112. return NULL;
  113. char tempName[ MAX_REFNAME ];
  114. Q_strncpyz( (char *) tempName, name, MAX_REFNAME );
  115. strlwr( (char *) tempName ); //NOTENOTE: For case insensitive searches on a map
  116. rti = tagOwner->tagMap.find( tempName );
  117. if ( rti == tagOwner->tagMap.end() )
  118. return NULL;
  119. }
  120. return (*rti).second;
  121. }
  122. /*
  123. -------------------------
  124. TAG_Add
  125. -------------------------
  126. */
  127. reference_tag_t *TAG_Add( const char *name, const char *owner, vec3_t origin, vec3_t angles, int radius, int flags )
  128. {
  129. reference_tag_t *tag = new reference_tag_t;
  130. VALIDATEP( tag );
  131. //Copy the information
  132. VectorCopy( origin, tag->origin );
  133. VectorCopy( angles, tag->angles );
  134. tag->radius = radius;
  135. tag->flags = flags;
  136. if ( VALIDSTRING( name ) == false )
  137. {
  138. //gi.Error("Nameless ref_tag found at (%i %i %i)", (int)origin[0], (int)origin[1], (int)origin[2]);
  139. gi.Printf(S_COLOR_RED"ERROR: Nameless ref_tag found at (%i %i %i)\n", (int)origin[0], (int)origin[1], (int)origin[2]);
  140. delayedShutDown = level.time + 100;
  141. return NULL;
  142. }
  143. //Copy the name
  144. Q_strncpyz( (char *) tag->name, name, MAX_REFNAME );
  145. strlwr( (char *) tag->name ); //NOTENOTE: For case insensitive searches on a map
  146. //Make sure this tag's name isn't alread in use
  147. if ( TAG_Find( owner, name ) )
  148. {
  149. delayedShutDown = level.time + 100;
  150. gi.Printf(S_COLOR_RED"ERROR: Duplicate tag name \"%s\"\n", name );
  151. return NULL;
  152. }
  153. //Attempt to add this to the owner's list
  154. if ( VALIDSTRING( owner ) == false )
  155. {
  156. //If the owner isn't found, use the generic world name
  157. owner = TAG_GENERIC_NAME;
  158. }
  159. tagOwner_t *tagOwner = TAG_FindOwner( owner );
  160. //If the owner is valid, add this tag to it
  161. if VALID( tagOwner )
  162. {
  163. tagOwner->tags.insert( tagOwner->tags.end(), tag );
  164. tagOwner->tagMap[ (char*) &tag->name ] = tag;
  165. }
  166. else
  167. {
  168. //Create a new owner list
  169. tagOwner_t *tagOwner = new tagOwner_t;
  170. VALIDATEP( tagOwner );
  171. //Insert the information
  172. tagOwner->tags.insert( tagOwner->tags.end(), tag );
  173. tagOwner->tagMap[ (char *) tag->name ] = tag;
  174. //Map it
  175. refTagOwnerMap[ owner ] = tagOwner;
  176. }
  177. return tag;
  178. }
  179. /*
  180. -------------------------
  181. TAG_GetOrigin
  182. -------------------------
  183. */
  184. int TAG_GetOrigin( const char *owner, const char *name, vec3_t origin )
  185. {
  186. reference_tag_t *tag = TAG_Find( owner, name );
  187. if (!tag)
  188. {
  189. VectorClear(origin);
  190. return false;
  191. }
  192. VALIDATEB( tag );
  193. VectorCopy( tag->origin, origin );
  194. return true;
  195. }
  196. /*
  197. -------------------------
  198. TAG_GetOrigin2
  199. Had to get rid of that damn assert for dev
  200. -------------------------
  201. */
  202. int TAG_GetOrigin2( const char *owner, const char *name, vec3_t origin )
  203. {
  204. reference_tag_t *tag = TAG_Find( owner, name );
  205. if( tag == NULL )
  206. {
  207. return qfalse;
  208. }
  209. VectorCopy( tag->origin, origin );
  210. return qtrue;
  211. }
  212. /*
  213. -------------------------
  214. TAG_GetAngles
  215. -------------------------
  216. */
  217. int TAG_GetAngles( const char *owner, const char *name, vec3_t angles )
  218. {
  219. reference_tag_t *tag = TAG_Find( owner, name );
  220. VALIDATEB( tag );
  221. VectorCopy( tag->angles, angles );
  222. return true;
  223. }
  224. /*
  225. -------------------------
  226. TAG_GetRadius
  227. -------------------------
  228. */
  229. int TAG_GetRadius( const char *owner, const char *name )
  230. {
  231. reference_tag_t *tag = TAG_Find( owner, name );
  232. VALIDATEB( tag );
  233. return tag->radius;
  234. }
  235. /*
  236. -------------------------
  237. TAG_GetFlags
  238. -------------------------
  239. */
  240. int TAG_GetFlags( const char *owner, const char *name )
  241. {
  242. reference_tag_t *tag = TAG_Find( owner, name );
  243. VALIDATEB( tag );
  244. return tag->flags;
  245. }
  246. /*
  247. ==============================================================================
  248. Spawn functions
  249. ==============================================================================
  250. */
  251. /*QUAKED ref_tag (0.5 0.5 1) (-8 -8 -8) (8 8 8)
  252. Reference tags which can be positioned throughout the level.
  253. These tags can later be refered to by the scripting system
  254. so that their origins and angles can be referred to.
  255. If you set angles on the tag, these will be retained.
  256. If you target a ref_tag at an entity, that will set the ref_tag's
  257. angles toward that entity.
  258. If you set the ref_tag's ownername to the ownername of an entity,
  259. it makes that entity is the owner of the ref_tag. This means
  260. that the owner, and only the owner, may refer to that tag.
  261. Tags may not have the same name as another tag with the same
  262. owner. However, tags with different owners may have the same
  263. name as one another. In this way, scripts can generically
  264. refer to tags by name, and their owners will automatically
  265. specifiy which tag is being referred to.
  266. targetname - the name of this tag
  267. ownername - the owner of this tag
  268. target - use to point the tag at something for angles
  269. */
  270. void ref_link ( gentity_t *ent )
  271. {
  272. reference_tag_t *tag;
  273. if ( ent->target )
  274. {
  275. //TODO: Find the target and set our angles to that direction
  276. gentity_t *target = G_Find( NULL, FOFS(targetname), ent->target );
  277. vec3_t dir;
  278. if ( target )
  279. {
  280. //Find the direction to the target
  281. VectorSubtract( target->s.origin, ent->s.origin, dir );
  282. VectorNormalize( dir );
  283. vectoangles( dir, ent->s.angles );
  284. //FIXME: Does pitch get flipped?
  285. }
  286. else
  287. {
  288. gi.Printf( S_COLOR_RED"ERROR: ref_tag (%s) has invalid target (%s)", ent->targetname, ent->target );
  289. }
  290. }
  291. //Add the tag
  292. tag = TAG_Add( ent->targetname, ent->ownername, ent->s.origin, ent->s.angles, 16, 0 );
  293. //Delete immediately, cannot be refered to as an entity again
  294. //NOTE: this means if you wanted to link them in a chain for, say, a path, you can't
  295. G_FreeEntity( ent );
  296. }
  297. void SP_reference_tag ( gentity_t *ent )
  298. {
  299. if ( ent->target )
  300. {
  301. //Init cannot occur until all entities have been spawned
  302. ent->e_ThinkFunc = thinkF_ref_link;
  303. ent->nextthink = level.time + START_TIME_LINK_ENTS;
  304. }
  305. else
  306. {
  307. ref_link( ent );
  308. }
  309. }