UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
g_spawn.cpp
Go to the documentation of this file.
1 
6 /*
7 All original material Copyright (C) 2002-2020 UFO: Alien Invasion.
8 
9 Original file from Quake 2 v3.21: quake2-2.31/game/g_spawn.c
10 Copyright (C) 1997-2001 Id Software, Inc.
11 
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 as published by the Free Software Foundation; either version 2
15 of the License, or (at your option) any later version.
16 
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 
21 See the GNU General Public License for more details.
22 
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 
27 */
28 
29 #include "g_spawn.h"
30 #include "g_ai.h"
31 #include "g_client.h"
32 #include "g_edicts.h"
33 #include "g_func.h"
34 #include "g_inventory.h"
35 #include "g_mission.h"
36 #include "g_reaction.h"
37 #include "g_trigger.h"
38 #include "g_utils.h"
39 #include "g_vis.h"
40 #include "../shared/parse.h"
41 #include "../shared/keyvaluepair.h"
42 
43 /* fields are needed for spawning from the entity string */
44 #define FFL_SPAWNTEMP 1
45 #define FFL_NOSPAWN 2
46 
47 #define G_ValidDescription(ent) ((ent)->description && ((ent)->description[0] == '_' || strstr((ent)->description, "*msgid:") != nullptr))
48 
53 typedef struct spawn_temp_s {
54  /* world vars */
57 } spawn_temp_t;
58 
60 
61 static void SP_light(Edict* ent);
62 static void SP_dummy(Edict* ent);
63 static void SP_player_start(Edict* ent);
64 static void SP_human_start(Edict* ent);
65 static void SP_alien_start(Edict* ent);
66 static void SP_civilian_start(Edict* ent);
67 static void SP_worldspawn(Edict* ent);
68 static void SP_2x2_start(Edict* ent);
69 static void SP_civilian_target(Edict* ent);
70 static void SP_misc_model(Edict* ent);
71 static void SP_misc_item(Edict* ent);
72 static void SP_misc_mission(Edict* ent);
73 static void SP_misc_message(Edict* ent);
74 static void SP_misc_smoke(Edict* ent);
75 static void SP_misc_fire(Edict* ent);
76 static void SP_misc_camera(Edict* ent);
77 static void SP_misc_smokestun(Edict* ent);
78 
79 typedef struct spawn_s {
80  const char* name;
81  void (*spawn) (Edict* ent);
82 } spawn_t;
83 
84 static const spawn_t spawns[] = {
85  {"worldspawn", SP_worldspawn},
86  {"light", SP_light},
87  {"misc_item", SP_misc_item},
88  {"misc_sound", SP_dummy},
89  {"misc_model", SP_misc_model},
90  {"misc_particle", SP_dummy},
91  {"misc_mission", SP_misc_mission},
92  {"info_player_start", SP_player_start},
93  {"info_human_start", SP_human_start},
94  {"info_alien_start", SP_alien_start},
95  {"info_civilian_start", SP_civilian_start},
96  {"info_civilian_target", SP_civilian_target},
97  {"info_2x2_start", SP_2x2_start},
98  {"info_null", SP_dummy},
99  {"func_breakable", SP_func_breakable},
100  {"func_door", SP_func_door},
101  {"func_door_sliding", SP_func_door_sliding},
102  {"func_rotating", SP_func_rotating},
103  {"trigger_nextmap", SP_trigger_nextmap},
104  {"trigger_hurt", SP_trigger_hurt},
105  {"trigger_touch", SP_trigger_touch},
106  {"trigger_rescue", SP_trigger_rescue},
107  {"misc_message", SP_misc_message},
108  {"misc_smoke", SP_misc_smoke},
109  {"misc_fire", SP_misc_fire},
110  {"misc_smokestun", SP_misc_smokestun},
111  {"misc_camera", SP_misc_camera},
112 
113  {nullptr, nullptr}
114 };
115 
119 static void ED_CallSpawn (Edict* ent)
120 {
121  if (!ent->classname)
122  return;
123 
124  /* check normal spawn functions */
125  for (const spawn_t* s = spawns; s->name; s++) {
126  /* found it */
127  if (Q_streq(s->name, ent->classname)) {
128  s->spawn(ent);
129  return;
130  }
131  }
132 
133  ent->inuse = false;
134 }
135 
141 static char* ED_NewString (const char* string)
142 {
143  const size_t l = strlen(string) + 1;
144  char* newb = (char*)G_TagMalloc(l, TAG_LEVEL);
145  char* new_p = newb;
146 
147  for (int i = 0; i < l; i++) {
148  /* check for special chars and convert them */
149  if (string[i] == '\\' && i < l - 1) {
150  i++;
151  if (string[i] == 'n')
152  *new_p++ = '\n';
153  else
154  *new_p++ = '\\';
155  } else
156  *new_p++ = string[i];
157  }
158 
159  return newb;
160 }
161 
165 static void ED_ParseField (const char* key, const char* value, Edict* ent)
166 {
167  KeyValuePair kvp(key, value);
168 
169  if (kvp.isKey("classname"))
170  ent->classname = ED_NewString(value);
171  else if (kvp.isKey("model"))
172  ent->model = ED_NewString(value);
173  else if (kvp.isKey("spawnflags"))
174  ent->spawnflags = kvp.asInt();
175  else if (kvp.isKey("speed"))
176  ent->speed = kvp.asInt();
177  else if (kvp.isKey("dir"))
178  ent->dir = kvp.asInt();
179  else if (kvp.isKey("active"))
180  ent->active = kvp.asBool();
181  else if (kvp.isKey("target"))
182  ent->target = ED_NewString(value);
183  else if (kvp.isKey("targetname"))
184  ent->targetname = ED_NewString(value);
185  else if (kvp.isKey("item"))
186  ent->item = ED_NewString(value);
187  else if (kvp.isKey("noise"))
188  ent->noise = ED_NewString(value);
189  else if (kvp.isKey("particle"))
190  ent->particle = ED_NewString(value);
191  else if (kvp.isKey("nextmap"))
192  ent->nextmap = ED_NewString(value);
193  else if (kvp.isKey("frame"))
194  ent->frame = kvp.asInt();
195  else if (kvp.isKey("team"))
196  ent->setTeam(kvp.asInt());
197  else if (kvp.isKey("group"))
198  ent->group = ED_NewString(value);
199  else if (kvp.isKey("size"))
200  ent->fieldSize = kvp.asInt();
201  else if (kvp.isKey("count"))
202  ent->count = kvp.asInt();
203  else if (kvp.isKey("time"))
204  ent->time = kvp.asInt();
205  else if (kvp.isKey("health"))
206  ent->HP = kvp.asInt();
207  else if (kvp.isKey("radius"))
208  ent->radius = kvp.asInt();
209  else if (kvp.isKey("sounds"))
210  ent->sounds = kvp.asInt();
211  else if (kvp.isKey("material"))
212  ent->material = static_cast<edictMaterial_t>(kvp.asInt()); // enum !!
213  else if (kvp.isKey("light"))
214  ; // ignore
217  else if (kvp.isKey("maxteams"))
218  ; // ignore
219  else if (kvp.isKey("maxlevel"))
220  ; // ignore
221  else if (kvp.isKey("dmg"))
222  ent->dmg = kvp.asInt();
223  else if (kvp.isKey("origin"))
224  kvp.asVec3(ent->origin);
225  else if (kvp.isKey("angles"))
226  kvp.asVec3(ent->angles);
227  else if (kvp.isKey("angle"))
228  ent->angle = kvp.asFloat();
229  else if (kvp.isKey("message"))
230  ent->message = ED_NewString(value);
231  else if (kvp.isKey("desc"))
232  ent->description = ED_NewString(value);
233 
234  else if (kvp.isKey("norandomspawn"))
235  spawnTemp.noRandomSpawn = kvp.asInt();
236  else if (kvp.isKey("noequipment"))
237  spawnTemp.noEquipment = kvp.asInt();
238 }
239 
245 static const char* ED_ParseEdict (const char* data, Edict* ent)
246 {
247  char keyname[MAX_VAR];
248 
249  bool reset = true;
250  OBJZERO(spawnTemp);
251 
252  /* go through all the dictionary pairs */
253  while (1) {
254  /* parse key */
255  const char* c = Com_Parse(&data);
256  if (c[0] == '}')
257  break;
258  if (!data)
259  gi.Error("ED_ParseEntity: EOF without closing brace");
260 
261  Q_strncpyz(keyname, c, sizeof(keyname));
262 
263  /* parse value */
264  c = Com_Parse(&data);
265  if (!data)
266  gi.Error("ED_ParseEntity: EOF without closing brace");
267 
268  if (c[0] == '}')
269  gi.Error("ED_ParseEntity: closing brace without data");
270 
271  reset = false;
272 
273  /* keynames with a leading underscore are used for utility comments,
274  * and are immediately discarded by ufo */
275  if (keyname[0] == '_')
276  continue;
277 
278  ED_ParseField(keyname, c, ent);
279  }
280 
281  if (reset)
282  ent->nativeReset();
283 
284  return data;
285 }
286 
292 static void G_FindEdictGroups (void)
293 {
294  Edict* ent = G_EdictsGetFirst(); /* the first edict is always a world edict that can be skipped */
295 
296  while ((ent = G_EdictsGetNextInUse(ent))) {
297  /* no group at all */
298  if (!ent->group)
299  continue;
300  /* already marked as slave in another group */
301  if (ent->flags & FL_GROUPSLAVE)
302  continue;
303  Edict* chain = ent;
304  ent->groupMaster = ent;
305  Edict* groupMember = ent;
306  /* search only the remainder of the entities */
307  while ((groupMember = G_EdictsGetNextInUse(groupMember))) {
308  /* no group at all */
309  if (!groupMember->group)
310  continue;
311  /* already marked as slave in another group */
312  if (groupMember->flags & FL_GROUPSLAVE)
313  continue;
314  /* same group as the master? */
315  if (Q_streq(ent->group, groupMember->group)) {
316  chain->groupChain = groupMember;
317  groupMember->groupMaster = ent;
318  chain = groupMember;
319  groupMember->flags |= FL_GROUPSLAVE;
320  }
321  }
322  }
323 }
324 
331 void G_SpawnEntities (const char* mapname, bool day, const char* entities)
332 {
334 
335  OBJZERO(level);
337 
338  G_EdictsInit();
339 
340  /* initialize reactionFire data */
342 
343  Q_strncpyz(level.mapname, mapname, sizeof(level.mapname));
344  level.day = day;
345 
347 
349  level.actualRound = 1;
351 
352  /* parse ents */
353  int entnum = 0;
354  while (1) {
355  /* parse the opening brace */
356  const char* token = Com_Parse(&entities);
357  if (!entities)
358  break;
359  if (token[0] != '{')
360  gi.Error("ED_LoadFromFile: found %s when expecting {", token);
361 
362  Edict* ent = G_Spawn();
363 
364  entities = ED_ParseEdict(entities, ent);
365 
366  ent->mapNum = entnum++;
367 
368  /* Set the position of the entity */
369  VecToPos(ent->origin, ent->pos);
370 
371  /* Call this entity's specific initializer (sets ent->type) */
372  ED_CallSpawn(ent);
373 
374  /* if this entity is an bbox (e.g. actor), then center its origin based on its position */
375  if (ent->solid == SOLID_BBOX)
376  ent->calcOrigin();
377  }
378 
379  /* spawn ai players, if needed */
381  if (AI_CreatePlayer(TEAM_CIVILIAN) == nullptr)
382  gi.DPrintf("Could not create civilian\n");
383  }
384 
386  if (AI_CreatePlayer(TEAM_ALIEN) == nullptr)
387  gi.DPrintf("Could not create alien\n");
388  }
389 
390  Com_Printf("Used inventory slots after ai spawn: %i\n", game.invi.GetUsedSlots());
391 
393 }
394 
403 Edict* G_Spawn (const char* classname)
404 {
405  Edict* ent = G_EdictsGetNewEdict();
406 
407  if (!ent)
408  gi.Error("G_Spawn: no free edicts");
409 
410  ent->inuse = true;
411  ent->number = G_EdictsGetNumber(ent);
412  if (classname)
413  ent->classname = classname;
414  else
415  ent->classname = "noclass";
417  ent->setActive(); /* only used by camera */
418  return ent;
419 }
420 
421 static void Think_SmokeAndFire (Edict* self)
422 {
423  const int endRound = self->time + self->count;
424  const int spawnIndex = (self->getTeam() + level.teamOfs) % MAX_TEAMS;
425  const int currentIndex = (level.activeTeam + level.teamOfs) % MAX_TEAMS;
426  if (endRound < level.actualRound || (endRound == level.actualRound && spawnIndex <= currentIndex)) {
427  const bool checkVis = self->type == ET_SMOKE;
428  G_EventEdictPerish(G_VisToPM(self->particleLink->visflags), *self->particleLink);
429  G_FreeEdict(self->particleLink);
430  G_FreeEdict(self);
431  if (checkVis)
432  G_CheckVis(nullptr);
433  }
434 }
435 
436 static void G_SpawnFieldPart (const entity_type_t fieldtype, const vec3_t vec, const char* particle, int rounds, int damage)
437 {
438  pos3_t pos;
439  VecToPos(vec, pos); /* calculate grid position */
440 
441  Edict* ent = G_GetEdictFromPos(pos, fieldtype);
442  if (ent == nullptr) {
443  pos_t z = gi.GridFall(ACTOR_SIZE_NORMAL, pos);
444  if (std::abs(pos[2] - z) > 1)
445  return;
446 
447  pos[2] = z;
448  ent = G_Spawn();
449  VectorCopy(pos, ent->pos);
450  ent->calcOrigin(); /* although vec is supposed to be the origin, calc origin from pos. That's safer. */
451  ent->dmg = damage;
452  ent->particle = particle;
454  switch (fieldtype) {
455  case ET_SMOKE:
456  SP_misc_smoke(ent);
457  break;
458  case ET_FIRE:
459  SP_misc_fire(ent);
460  break;
461  case ET_SMOKESTUN:
462  SP_misc_smokestun(ent);
463  break;
464  default:
465  break;
466  }
467  }
468 
469  ent->count = rounds;
470 }
471 
482 static void G_SpawnFieldGroup (const entity_type_t fieldtype, const vec3_t vec, const char* particle, int rounds, int damage, vec_t radius)
483 {
484  G_SpawnFieldPart(fieldtype, vec, particle, rounds, damage);
485 
486  /* for all cells in a square of +/- radius */
487  for (vec_t x = vec[0] - radius; x <= vec[0] + radius; x += UNIT_SIZE) {
488  for (vec_t y = vec[1] - radius; y <= vec[1] + radius; y += UNIT_SIZE) {
489  vec3_t end;
490  VectorSet(end, x, y, vec[2]);
491 
492  /* cut off the edges of the square to resemble a circle */
493  if (VectorDist(end, vec) > radius)
494  continue;
495  if (!gi.isOnMap(end))
496  continue;
497  const trace_t tr = G_Trace(Line(vec, end), nullptr, MASK_SMOKE_AND_FIRE);
498  /* trace didn't reach the target - something was hit before */
499  if (tr.fraction < 1.0f || (tr.contentFlags & CONTENTS_WATER)) {
500  continue;
501  }
502  G_SpawnFieldPart(fieldtype, end, particle, rounds, damage);
503  }
504  }
505 }
506 
516 void G_SpawnSmokeField (const vec3_t vec, const char* particle, int rounds, int damage, vec_t radius)
517 {
518  G_SpawnFieldGroup(ET_SMOKE, vec, particle, rounds, damage, radius);
519 }
520 
521 void G_SpawnFireField (const vec3_t vec, const char* particle, int rounds, int damage, vec_t radius)
522 {
523  G_SpawnFieldGroup(ET_FIRE, vec, particle, rounds, damage, radius);
524 }
525 
526 void G_SpawnStunSmokeField (const vec3_t vec, const char* particle, int rounds, int damage, vec_t radius)
527 {
528  G_SpawnFieldGroup(ET_SMOKESTUN, vec, particle, rounds, damage, radius);
529 }
530 
536 {
537  Edict* floorItem = G_Spawn("item");
538  floorItem->type = ET_ITEM;
539  /* make sure that the item is always on a field that even the smallest actor can reach */
540  floorItem->fieldSize = ACTOR_SIZE_NORMAL;
541  VectorCopy(pos, floorItem->pos);
542  floorItem->pos[2] = gi.GridFall(floorItem->fieldSize, floorItem->pos);
543  floorItem->calcOrigin();
544  return floorItem;
545 }
546 
551 Edict* G_SpawnParticle (const vec3_t origin, int spawnflags, const char* particle)
552 {
553  Edict* ent = G_Spawn("particle");
554  ent->type = ET_PARTICLE;
555  VectorCopy(origin, ent->origin);
556 
557  /* Set the position of the entity */
558  VecToPos(ent->origin, ent->pos);
559 
560  ent->particle = particle;
561  ent->spawnflags = spawnflags;
562 
563  G_CheckVis(ent);
564 
565  return ent;
566 }
567 
571 static void G_ActorSpawn (Edict* ent)
572 {
573  /* set properties */
574  level.num_spawnpoints[ent->getTeam()]++;
575  ent->classname = "actor";
576  ent->type = ET_ACTORSPAWN;
578 
579  /* Fall to ground */
580  if (ent->pos[2] >= PATHFINDING_HEIGHT)
581  ent->pos[2] = PATHFINDING_HEIGHT - 1;
582  vec3_t vec;
583  PosToVec(ent->pos, vec);
584  while (ent->pos[2] > 0 && !gi.isOnMap(vec)) {
585  --ent->pos[2];
586  PosToVec(ent->pos, vec);
587  }
588  ent->pos[2] = gi.GridFall(ent->fieldSize, ent->pos);
589  if (ent->pos[2] >= PATHFINDING_HEIGHT)
590  gi.DPrintf("G_ActorSpawn: Warning: z level is out of bounds: %i\n", ent->pos[2]);
591 
592  ent->calcOrigin();
593 
594  /* link it for collision detection */
595  ent->dir = AngleToDir(ent->angle);
596  assert(ent->dir < CORE_DIRECTIONS);
597  ent->solid = SOLID_BBOX;
598 
599  /* Set bounding box. Maybe this is already set in one of the spawn functions? */
600  if (ent->entBox.getMaxX() == 0)
602  if (ent->entBox.getMinX() == 0)
604 }
605 
609 static void G_Actor2x2Spawn (Edict* ent)
610 {
611  /* set properties */
612  level.num_2x2spawnpoints[ent->getTeam()]++;
613  ent->classname = "ugv";
614  ent->type = ET_ACTOR2x2SPAWN;
615  ent->fieldSize = ACTOR_SIZE_2x2;
616 
617  /* Spawning has already calculated the pos from the origin ( = center of the cell). Perfect for normal size actors.
618  * For 2x2 actors, the origin(of the info_ box) is in the middle of the four cells. Using VecToPos on that origin
619  * results in the upper right cell being the pos of the actor. But we want the lower left cell to be the pos of the
620  * 2x2 actor because routing and pathfinding rely on that. So compensate for that. */
621  ent->pos[0]--;
622  ent->pos[1]--;
623 
624  /* Fall to ground */
625  if (ent->pos[2] >= PATHFINDING_HEIGHT)
626  ent->pos[2] = PATHFINDING_HEIGHT - 1;
627  ent->pos[2] = gi.GridFall(ent->fieldSize, ent->pos);
628  if (ent->pos[2] >= PATHFINDING_HEIGHT)
629  gi.DPrintf("G_Actor2x2Spawn: Warning: z level is out of bounds: %i\n", ent->pos[2]);
630  ent->calcOrigin();
631 
632  /* link it for collision detection */
633  ent->dir = AngleToDir(ent->angle);
634  assert(ent->dir < CORE_DIRECTIONS);
635  ent->solid = SOLID_BBOX;
636 
637  /* Set bounding box. Maybe this is already set in one of the spawn functions? */
638  if (ent->entBox.getMaxX() == 0)
640  if (ent->entBox.getMinX() == 0)
642 }
643 
647 static void SP_light (Edict* ent)
648 {
649  /* lights aren't client-server communicated items */
650  /* they are completely client side */
651  G_FreeEdict(ent);
652 }
653 
660 static void SP_player_start (Edict* ent)
661 {
662  /* only used in multi player */
663  if (G_IsSinglePlayer()) {
664  G_FreeEdict(ent);
665  return;
666  }
667 
669  /* maybe there are already the max soldiers allowed per team connected */
671  G_ActorSpawn(ent);
672  } else
673  G_FreeEdict(ent);
674 }
675 
680 static void SP_human_start (Edict* ent)
681 {
682  /* only used in single player */
683  if (G_IsMultiPlayer()) {
684  G_FreeEdict(ent);
685  return;
686  }
687 
688  ent->setTeam(TEAM_PHALANX);
689  G_ActorSpawn(ent);
690 }
691 
692 
697 static void SP_2x2_start (Edict* ent)
698 {
699  /* no 2x2 unit in multiplayer */
700  if (G_IsMultiPlayer()) {
701  G_FreeEdict(ent);
702  return;
703  }
704 
705  if (!ent->getTeam())
706  ent->setTeam(TEAM_PHALANX);
707 
708  /* these units are bigger */
710  ent->entBox.setMins(-(PLAYER_WIDTH * 2), -(PLAYER_WIDTH * 2), PLAYER_MIN);
711 
712  /* spawn singleplayer 2x2 unit */
713  G_Actor2x2Spawn(ent);
714 }
715 
720 static void SP_alien_start (Edict* ent)
721 {
722  /* deactivateable in multiplayer */
724  G_FreeEdict(ent);
725  return;
726  }
727  ent->setTeam(TEAM_ALIEN);
728 
729  G_ActorSpawn(ent);
730 }
731 
732 
737 static void SP_civilian_start (Edict* ent)
738 {
739  /* deactivateable in multiplayer */
741  G_FreeEdict(ent);
742  return;
743  }
744  ent->setTeam(TEAM_CIVILIAN);
745  ent->count = 100; /* current waypoint */
746  G_ActorSpawn(ent);
747 }
748 
756 static void SP_civilian_target (Edict* ent)
757 {
758  /* target point for which team */
759  ent->setTeam(TEAM_CIVILIAN);
760  ent->classname = "civtarget";
761  ent->type = ET_CIVILIANTARGET;
762  ent->fieldSize = ACTOR_SIZE_NORMAL; /* to let the grid fall function work */
763 
764  /* add the edict to the list of known waypoints */
765  G_AddToWayPointList(ent);
766 
767  /* fall to ground */
768  if (ent->pos[2] >= PATHFINDING_HEIGHT)
769  ent->pos[2] = PATHFINDING_HEIGHT - 1;
770  ent->pos[2] = gi.GridFall(ent->fieldSize, ent->pos);
771  ent->calcOrigin();
772 }
773 
777 static void SP_misc_mission (Edict* ent)
778 {
779  ent->classname = "misc_mission";
780  ent->type = ET_MISSION;
781  ent->solid = SOLID_TRIGGER;
782 
783  /* maybe this was set to something else for multiplayer */
784  if (!ent->getTeam())
785  ent->setTeam(TEAM_PHALANX);
786 
787  if (!ent->time && !ent->target && !ent->item) {
788  G_FreeEdict(ent);
789  gi.DPrintf("misc_mission given with no objective\n");
790  return;
791  }
792 
793  /* think function values */
794  ent->think = G_MissionThink;
795  ent->nextthink = 1;
796 
797  if (ent->radius < 1) {
798  ent->radius = UNIT_SIZE * 3;
799  }
800  ent->entBox.setMaxs(ent->radius, ent->radius, PLAYER_STAND);
801  ent->entBox.setMins(-ent->radius, -ent->radius, PLAYER_MIN);
802 
803  if (G_ValidDescription(ent))
805 
806  ent->setTouch(G_MissionTouch);
807  ent->reset = G_MissionReset;
808  if (ent->target) {
809  ent->use = G_MissionUse;
810  /* Bomb/key/etc target will be freed when used - don't group it! */
811  if (ent->item)
812  ent->group = nullptr;
813  }
814 
815  gi.LinkEdict(ent);
816 }
817 
825 {
826  vec3_t center;
827  AABB shiftedBox(ent->absBox);
828  shiftedBox.getCenter(center);
829 
830  pos3_t mins, maxs, origin;
831  VecToPos(shiftedBox.mins, mins);
832  VecToPos(shiftedBox.maxs, maxs);
833  VecToPos(center, origin);
834 
835  const int xDelta = std::max(1, maxs[0] - mins[0]);
836  const int yDelta = std::max(1, maxs[1] - mins[1]);
837 
838  int size = xDelta * yDelta;
839  ent->forbiddenListPos = (pos3_t*)G_TagMalloc(size * sizeof(pos3_t), TAG_LEVEL);
840  ent->forbiddenListSize = size;
841 
842  for (int i = 0; i < xDelta; i++) {
843  for (int j = 0; j < yDelta; j++) {
844  const pos_t x = mins[0] + i;
845  const pos_t y = mins[1] + j;
846  const pos_t z = origin[2];
847  VectorSet(ent->forbiddenListPos[i], x, y, z);
848  }
849  }
850 }
851 
852 #define MISC_MODEL_SOLID (1 << 8)
853 
856 static void SP_misc_model (Edict* ent)
857 {
858  if (ent->spawnflags & MISC_MODEL_SOLID) {
859  if (ent->model && ent->model[0] != '\0') {
860  AABB modelAabb;
861  if (gi.LoadModelAABB(ent->model, ent->frame, modelAabb)) {
862  ent->classname = "model";
863  ent->entBox.set(modelAabb);
864  ent->type = ET_SOLID;
865  ent->solid = SOLID_BBOX;
868  gi.LinkEdict(ent);
870  } else {
871  gi.DPrintf("Could not get mins/maxs for model '%s'\n", ent->model);
872  G_FreeEdict(ent);
873  }
874  } else {
875  gi.DPrintf("server_solid misc_model with no model given\n");
876  G_FreeEdict(ent);
877  }
878  } else {
879  /* handled client side */
880  G_FreeEdict(ent);
881  }
882 }
883 
887 static void SP_misc_item (Edict* ent)
888 {
889  if (!ent->item) {
890  gi.DPrintf("No item defined in misc_item\n");
891  G_FreeEdict(ent);
892  return;
893  }
894 
895  G_AddItemToFloor(ent->pos, ent->item);
896 
897  /* now we can free the original edict */
898  G_FreeEdict(ent);
899 }
900 
901 static bool Message_Use (Edict* self, Edict* activator)
902 {
903  if (!activator || !G_IsActor(activator)) {
904  return false;
905  } else {
906  if (G_ValidMessage(self)) {
907  Player& player = activator->getPlayer();
908  const char* msg = self->message;
909  /* remove gettext marker */
910  if (msg[0] == '_')
911  msg++;
912  G_ClientPrintf(player, PRINT_HUD, "%s", msg);
913  }
914 
915  if (self->spawnflags & 1)
916  G_FreeEdict(self);
917 
918  return false;
919  }
920 }
921 
922 static void G_SpawnField (Edict* ent, const char* classname, entity_type_t type, solid_t solid)
923 {
924  ent->classname = classname;
925  ent->type = type;
927  ent->solid = solid;
928  ent->entBox.setMaxs(UNIT_SIZE / 2, UNIT_SIZE / 2, UNIT_HEIGHT / 2);
929  ent->entBox.setMins(-UNIT_SIZE / 2, -UNIT_SIZE / 2, -UNIT_HEIGHT / 2);
930  ent->calcOrigin();
931  ent->think = Think_SmokeAndFire;
932  ent->nextthink = 1;
933  ent->time = level.actualRound;
934  ent->setTeam(level.activeTeam);
935 
936  gi.LinkEdict(ent);
937 
938  vec3_t particleOrigin;
939  VectorCopy(ent->origin, particleOrigin);
940  particleOrigin[2] -= GROUND_DELTA;
941  ent->particleLink = G_SpawnParticle(particleOrigin, ent->spawnflags, ent->particle);
942 }
943 
944 static void SP_misc_smoke (Edict* ent)
945 {
946  G_SpawnField(ent, "smoke", ET_SMOKE, SOLID_TRIGGER);
947  ent->dmgtype = gi.csi->damStunGas;
949  G_CheckVis(nullptr);
950 }
951 
952 static void SP_misc_fire (Edict* ent)
953 {
954  G_SpawnField(ent, "fire", ET_FIRE, SOLID_TRIGGER);
955  ent->dmgtype = gi.csi->damIncendiary;
957 }
958 
959 static void SP_misc_smokestun (Edict* ent)
960 {
961  G_SpawnField(ent, "stunsmoke", ET_SMOKESTUN, SOLID_TRIGGER);
962  ent->dmgtype = gi.csi->damStunGas;
964 }
965 
966 static void SP_misc_message (Edict* ent)
967 {
968  if (!ent->message) {
969  G_FreeEdict(ent);
970  return;
971  }
972 
973  if (!G_ValidMessage(ent))
974  gi.DPrintf("No translation marker for misc_message set\n");
975  ent->use = Message_Use;
976  ent->classname = "misc_message";
977  ent->type = ET_MESSAGE;
978  ent->solid = SOLID_NOT;
979 }
980 
981 #define CAMERA_ROTATE (1 << 8)
982 
983 static void SP_misc_camera (Edict* ent)
984 {
985  /* only used in single player */
986  if (G_IsMultiPlayer()) {
987  G_FreeEdict(ent);
988  return;
989  }
990 
991  const bool rotate = ent->spawnflags & CAMERA_ROTATE;
992  G_InitCamera(ent, CAMERA_STATIONARY, ent->angle, rotate);
993 }
994 
998 static void SP_dummy (Edict* ent)
999 {
1000  /* particles aren't client-server communicated items
1001  * they are completely client side */
1002  G_FreeEdict(ent);
1003 }
1004 
1013 static void SP_worldspawn (Edict* ent)
1014 {
1015  ent->solid = SOLID_BSP;
1016  /* since the world doesn't use G_Spawn() */
1017  ent->inuse = true;
1018  ent->classname = "worldspawn";
1019 
1020  level.noEquipment = spawnTemp.noEquipment;
1021  level.noRandomSpawn = spawnTemp.noRandomSpawn;
1022 
1023  gi.ConfigString(CS_MAXCLIENTS, "%i", sv_maxclients->integer);
1024 
1025  /* only used in multi player */
1026  if (G_IsMultiPlayer()) {
1027  gi.ConfigString(CS_MAXSOLDIERSPERTEAM, "%i", sv_maxsoldiersperteam->integer);
1029  gi.ConfigString(CS_ENABLEMORALE, "%i", sv_enablemorale->integer);
1030  gi.ConfigString(CS_MAXTEAMS, "%s", sv_maxteams->string);
1031  }
1032 }
int number
Definition: g_edict.h:51
void G_MissionAddVictoryMessage(const char *message)
Definition: g_mission.cpp:38
char * group
Definition: g_edict.h:104
char mapname[MAX_QPATH]
Definition: g_local.h:85
Edict * G_EdictsGetFirst(void)
Returns the first entity.
Definition: g_edicts.cpp:98
Edict * G_SpawnFloor(const pos3_t pos)
Spawns a new entity at the floor.
Definition: g_spawn.cpp:535
float getMaxX() const
Definition: aabb.h:131
void G_ClientPrintf(const Player &player, int printLevel, const char *fmt,...)
Definition: g_client.cpp:206
static const spawn_t spawns[]
Definition: g_spawn.cpp:84
static void SP_misc_item(Edict *ent)
Spawns an item to the ground container.
Definition: g_spawn.cpp:887
Edict * G_EdictsGetNextInUse(Edict *lastEnt)
Iterate through the entities that are in use.
Definition: g_edicts.cpp:166
static void SP_light(Edict *ent)
light (0 1 0) (-8 -8 -8) (8 8 8)
Definition: g_spawn.cpp:647
#define PLAYER_WIDTH
Definition: q_sizes.h:10
Reaction fire system.
#define VectorCopy(src, dest)
Definition: vector.h:51
void SP_func_rotating(Edict *ent)
Spawns a rotating solid inline brush model.
Definition: g_func.cpp:405
void G_AddToWayPointList(Edict *ent)
Definition: g_ai.cpp:1537
this is only used to hold entity field values that can be set from the editor, but aren't actually pr...
Definition: g_spawn.cpp:53
void setActive()
Definition: g_edict.h:198
solid_t solid
Definition: g_edict.h:58
#define ACTOR_SIZE_2x2
Definition: defines.h:303
void asVec3(vec3_t vec) const
Definition: keyvaluepair.h:66
trace_t G_Trace(const Line &trLine, const Edict *passent, int contentmask)
collision detection - this version is more accurate and includes entity tests
Definition: g_utils.cpp:265
const char * targetname
Definition: g_edict.h:126
#define VectorSet(v, x, y, z)
Definition: vector.h:59
void nativeReset()
Definition: g_edict.h:195
cvar_t * sv_maxsoldiersperplayer
Definition: g_main.cpp:54
int noEquipment
Definition: g_spawn.cpp:56
static void SP_misc_model(Edict *ent)
Spawns a misc_model if there is a solid state.
Definition: g_spawn.cpp:856
cvar_t * sv_maxteams
Definition: g_main.cpp:59
QGL_EXTERN GLint GLenum type
Definition: r_gl.h:94
A pair of strings representing a key and a value The value string can be trimmed and rendered in the ...
Definition: keyvaluepair.h:38
float nextthink
Definition: g_edict.h:149
#define TEAM_PHALANX
Definition: q_shared.h:62
static void G_FindEdictGroups(void)
Chain together all entities with a matching team field. All but the first will have the FL_GROUPSLAVE...
Definition: g_spawn.cpp:292
#define MAX_TEAMS
Definition: defines.h:98
void calcOrigin()
Calculate the edict's origin vector from it's grid position.
Definition: g_edict.h:216
int asInt() const
Definition: keyvaluepair.h:57
#define TEAM_ALIEN
Definition: q_shared.h:63
void setTeam(int team_)
Definition: g_edict.h:189
static void G_SpawnField(Edict *ent, const char *classname, entity_type_t type, solid_t solid)
Definition: g_spawn.cpp:922
void G_CheckVis(Edict *check, const vischeckflags_t visFlags)
Check if the edict appears/perishes for the other teams. If they appear for other teams...
Definition: g_vis.cpp:409
bool hurtAliens
Definition: g_local.h:89
byte dmgtype
Definition: g_edict.h:139
int damStunGas
Definition: q_shared.h:533
Edict * G_GetEdictFromPos(const pos3_t pos, const entity_type_t type)
Searches an edict of the given type at the given grid location.
Definition: g_utils.cpp:59
static void G_ActorSpawn(Edict *ent)
Spawn point for a 1x1 unit.
Definition: g_spawn.cpp:571
Artificial Intelligence functions.
cvar_t * sv_maxclients
Definition: g_main.cpp:43
void SP_func_breakable(Edict *ent)
func_breakable (0.3 0.3 0.3) ? Used for breakable objects.
Definition: g_func.cpp:144
Misc utility functions for game module.
static void ED_CallSpawn(Edict *ent)
Finds the spawn function for the entity and calls it.
Definition: g_spawn.cpp:119
int G_EdictsGetNumber(const Edict *ent)
Get an entity's ID number.
Definition: g_edicts.cpp:60
voidpf uLong int origin
Definition: ioapi.h:45
const char * description
Definition: g_edict.h:131
vec3_t angles
Definition: g_edict.h:54
static void SP_civilian_start(Edict *ent)
info_civilian_start (0 1 1) (-16 -16 -24) (16 16 32) Starting point for a civilian.
Definition: g_spawn.cpp:737
const char * message
Definition: g_edict.h:130
#define G_FreeTags(tag)
Definition: g_local.h:63
int activeTeam
Definition: g_local.h:101
Definition: aabb.h:42
static void G_SpawnFieldPart(const entity_type_t fieldtype, const vec3_t vec, const char *particle, int rounds, int damage)
Definition: g_spawn.cpp:436
void SP_trigger_hurt(Edict *ent)
Trigger for grid fields if they are under fire.
Definition: g_trigger.cpp:255
float vec_t
Definition: ufotypes.h:37
bool(* use)(Edict *self, Edict *activator)
Definition: g_edict.h:154
Mission related code - king of the hill and so on.
Trigger functions.
AABB entBox
Definition: g_edict.h:60
bool inuse
Definition: g_edict.h:47
bool active
Definition: g_edict.h:177
static const char * ED_ParseEdict(const char *data, Edict *ent)
Parses an edict out of the given string, returning the new position.
Definition: g_spawn.cpp:245
AABB absBox
Definition: g_edict.h:61
#define VectorDist(a, b)
Definition: vector.h:69
#define UNIT_HEIGHT
Definition: defines.h:122
bool G_MissionUse(Edict *self, Edict *activator)
Mission trigger use function.
Definition: g_mission.cpp:151
int mapNum
Definition: g_edict.h:73
#define CAMERA_ROTATE
Definition: g_spawn.cpp:981
const char * target
Definition: g_edict.h:125
solid_t
edict->solid values
Definition: game.h:153
InventoryInterface invi
Definition: g_local.h:76
static void SP_misc_fire(Edict *ent)
Definition: g_spawn.cpp:952
bool asBool() const
Definition: keyvaluepair.h:60
void set(const AABB &other)
Copies the values from the given aabb.
Definition: aabb.h:60
#define TEAM_CIVILIAN
Definition: q_shared.h:61
int forbiddenListSize
Definition: g_edict.h:175
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
void G_InitCamera(Edict *ent, camera_type_t cameraType, float angle, bool rotate)
Definition: g_camera.cpp:50
static void SP_dummy(Edict *ent)
a dummy to get rid of local entities
Definition: g_spawn.cpp:998
#define CS_MAXSOLDIERSPERTEAM
Definition: q_shared.h:313
vec3_t maxs
Definition: aabb.h:258
byte dir
Definition: g_edict.h:86
entity_t entities[MAX_MAP_ENTITIES]
Definition: bspfile.cpp:395
#define G_IsActor(ent)
Definition: g_local.h:127
int integer
Definition: cvar.h:81
static void SP_2x2_start(Edict *ent)
info_2x2_start (1 1 0) (-32 -32 -24) (32 32 32) Starting point for a 2x2 unit.
Definition: g_spawn.cpp:697
static void SP_misc_message(Edict *ent)
Definition: g_spawn.cpp:966
void setMins(const vec3_t mini)
Definition: aabb.h:68
int actualRound
Definition: g_local.h:104
static void ED_ParseField(const char *key, const char *value, Edict *ent)
Takes a key/value pair and sets the binary values in an edict.
Definition: g_spawn.cpp:165
const csi_t * csi
Definition: game.h:176
void(* spawn)(Edict *ent)
Definition: g_spawn.cpp:81
Player & getPlayer() const
Definition: g_edict.h:265
float asFloat() const
Definition: keyvaluepair.h:54
Edict * G_EdictsGetNewEdict(void)
Find an entity that is not in use.
Definition: g_edicts.cpp:141
int speed
Definition: g_edict.h:124
const char * noise
Definition: g_edict.h:132
int damIncendiary
Definition: q_shared.h:537
#define FL_GROUPSLAVE
not the first on the team
Definition: g_local.h:292
float fraction
Definition: tracing.h:58
int spawnflags
Definition: g_edict.h:118
int AngleToDir(int angle)
Returns the index of array directionAngles[DIRECTIONS] whose value is the closest to angle...
Definition: mathlib.cpp:130
#define CONTENTS_WATER
Definition: defines.h:226
game_locals_t game
Definition: g_main.cpp:37
int getTeam() const
Definition: g_edict.h:269
void setTouch(bool(*touch_)(Edict *self, Edict *activator))
Definition: g_edict.h:321
static bool Message_Use(Edict *self, Edict *activator)
Definition: g_spawn.cpp:901
static void SP_misc_mission(Edict *ent)
Initializes the human/phalanx mission entity.
Definition: g_spawn.cpp:777
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition: shared.cpp:457
#define G_IsMultiPlayer()
Definition: g_local.h:145
unsigned int key
Definition: cl_input.cpp:68
func_* edicts
#define TAG_LEVEL
Definition: g_local.h:59
void SP_trigger_touch(Edict *ent)
Touch trigger to call the use function of the attached target.
Definition: g_trigger.cpp:320
#define PLAYER_MIN
Definition: q_sizes.h:9
GLsizei size
Definition: r_gl.h:152
static spawn_temp_t spawnTemp
Definition: g_spawn.cpp:59
game_import_t gi
Definition: g_main.cpp:39
cvar_t * sv_enablemorale
Definition: g_main.cpp:55
int noRandomSpawn
Definition: g_local.h:108
const char * nextmap
Definition: g_edict.h:129
#define OBJZERO(obj)
Definition: shared.h:178
static char * ED_NewString(const char *string)
Allocated memory for the given string in the level context (TAG_LEVEL)
Definition: g_spawn.cpp:141
cvar_t * sv_maxsoldiersperteam
Definition: g_main.cpp:53
void(* think)(Edict *self)
Definition: g_edict.h:150
#define MAX_VAR
Definition: shared.h:36
int dmg
Definition: g_edict.h:138
static void SP_misc_camera(Edict *ent)
Definition: g_spawn.cpp:983
byte num_spawnpoints[MAX_TEAMS]
Definition: g_local.h:116
int radius
Definition: g_edict.h:123
void G_SpawnFireField(const vec3_t vec, const char *particle, int rounds, int damage, vec_t radius)
Definition: g_spawn.cpp:521
static void G_SpawnFieldGroup(const entity_type_t fieldtype, const vec3_t vec, const char *particle, int rounds, int damage, vec_t radius)
Spawns a field that is available for some rounds.
Definition: g_spawn.cpp:482
cvar_t * ai_multiplayeraliens
Definition: g_main.cpp:74
void SP_trigger_nextmap(Edict *ent)
Definition: g_trigger.cpp:171
Edict * G_Spawn(const char *classname)
Either finds a free edict, or allocates a new one.
Definition: g_spawn.cpp:403
#define VecToPos(v, p)
Map boundary is +/- MAX_WORLD_WIDTH - to get into the positive area we add the possible max negative ...
Definition: mathlib.h:100
void G_EventEdictPerish(playermask_t playerMask, const Edict &ent)
Send disappear event.
Definition: g_events.cpp:624
pos3_t pos
Definition: g_edict.h:55
Edict * groupMaster
Definition: g_edict.h:168
int sounds
Definition: g_edict.h:137
cvar_t * ai_numcivilians
Definition: g_main.cpp:73
float angle
Definition: g_edict.h:120
#define G_TagMalloc(size, tag)
Definition: g_local.h:64
#define PosToVec(p, v)
Pos boundary size is +/- 128 - to get into the positive area we add the possible max negative value a...
Definition: mathlib.h:110
static void SP_alien_start(Edict *ent)
info_alien_start (1 0 0) (-16 -16 -24) (16 16 32) Starting point for a single player alien...
Definition: g_spawn.cpp:720
Edict * G_SpawnParticle(const vec3_t origin, int spawnflags, const char *particle)
Definition: g_spawn.cpp:551
static transfer_t tr
void G_SpawnEntities(const char *mapname, bool day, const char *entities)
Creates a server's entity / program execution context by parsing textual entity definitions out of an...
Definition: g_spawn.cpp:331
int frame
Definition: g_edict.h:102
void SP_trigger_rescue(Edict *ent)
Rescue trigger to mark an actor to be in the rescue zone. Aborting a game would not kill the actors i...
Definition: g_trigger.cpp:375
Definition: line.h:31
playermask_t G_VisToPM(teammask_t teamMask)
Converts vis mask to player mask.
Definition: g_client.cpp:186
void(* reset)(Edict *self, Edict *activator)
Definition: g_edict.h:148
Definition: grid.h:83
void G_MissionReset(Edict *self, Edict *activator)
Definition: g_mission.cpp:124
#define CS_MAXTEAMS
Definition: q_shared.h:316
int time
Definition: g_edict.h:136
pos_t pos3_t[3]
Definition: ufotypes.h:58
bool Touch_HurtTrigger(Edict *self, Edict *activator)
Hurt trigger.
Definition: g_trigger.cpp:212
void getCenter(vec3_t center) const
Calculates the center of the bounding box.
Definition: aabb.h:155
void G_SpawnSmokeField(const vec3_t vec, const char *particle, int rounds, int damage, vec_t radius)
Spawns a smoke field that is available for some rounds.
Definition: g_spawn.cpp:516
void G_ReactionFireTargetsInit(void)
free function to initialize the reaction fire table for all entities.
Definition: g_reaction.cpp:427
int flags
Definition: g_edict.h:169
const GLuint *typedef void(APIENTRY *GenRenderbuffersEXT_t)(GLsizei
Definition: r_gl.h:189
actorSizeEnum_t fieldSize
Definition: g_edict.h:141
#define UNIT_SIZE
Definition: defines.h:121
void SP_func_door_sliding(Edict *ent)
Definition: g_func.cpp:374
#define PLAYER_STAND
Definition: q_sizes.h:6
#define G_ValidDescription(ent)
Definition: g_spawn.cpp:47
int count
Definition: g_edict.h:135
void G_ResetClientData(void)
Called after every player has joined.
Definition: g_client.cpp:1510
int noRandomSpawn
Definition: g_spawn.cpp:55
struct spawn_temp_s spawn_temp_t
this is only used to hold entity field values that can be set from the editor, but aren't actually pr...
#define PATHFINDING_HEIGHT
15 max, adjusting above 8 will require a rewrite to the DV code
Definition: defines.h:294
const char * Com_Parse(const char *data_p[], char *target, size_t size, bool replaceWhitespaces)
Parse a token out of a string.
Definition: parse.cpp:107
#define G_IsSinglePlayer()
Definition: g_local.h:146
#define PLAYER2x2_WIDTH
Definition: q_sizes.h:23
pathing_t * pathingMap
Definition: g_local.h:106
void G_MissionThink(Edict *self)
Definition: g_mission.cpp:188
uint32_t G_GetLevelFlagsFromPos(const pos3_t pos)
Calculates the level flags for a given grid position.
Definition: g_utils.cpp:650
static void SP_civilian_target(Edict *ent)
info_civilian_start (0 1 1) (-16 -16 -24) (16 16 32) Way point for a civilian.
Definition: g_spawn.cpp:756
bool G_AddItemToFloor(const pos3_t pos, const char *itemID)
Adds a new item to an existing or new floor container edict at the given grid location.
#define CS_MAXSOLDIERSPERPLAYER
Definition: q_shared.h:314
cvar_t * sv_hurtaliens
Definition: g_main.cpp:62
QGL_EXTERN GLint i
Definition: r_gl.h:113
char * string
Definition: cvar.h:73
static void SP_misc_smokestun(Edict *ent)
Definition: g_spawn.cpp:959
Brings new objects into the world.
static void SP_player_start(Edict *ent)
info_player_start (1 0 0) (-16 -16 -24) (16 16 32) Starting point for a player. "team" the number of ...
Definition: g_spawn.cpp:660
entity_type_t type
Definition: g_edict.h:81
int noEquipment
Definition: g_local.h:109
#define GROUND_DELTA
Definition: defines.h:115
#define CORE_DIRECTIONS
Definition: mathlib.h:88
#define MISC_MODEL_SOLID
Definition: g_spawn.cpp:852
static void G_Actor2x2Spawn(Edict *ent)
Spawn a singleplayer 2x2 unit.
Definition: g_spawn.cpp:609
functions to handle the storage and lifecycle of all edicts in the game module.
#define CS_ENABLEMORALE
Definition: q_shared.h:315
vec3_t origin
Definition: g_edict.h:53
edictMaterial_t material
Definition: g_edict.h:133
float getMinX() const
Definition: aabb.h:119
bool isKey(const char *name) const
Definition: keyvaluepair.h:51
struct spawn_s spawn_t
vec_t vec3_t[3]
Definition: ufotypes.h:39
static void SP_worldspawn(Edict *ent)
Spawns the world entity.
Definition: g_spawn.cpp:1013
#define CS_MAXCLIENTS
Definition: q_shared.h:311
entity_type_t
Definition: q_shared.h:145
void G_SpawnStunSmokeField(const vec3_t vec, const char *particle, int rounds, int damage, vec_t radius)
Definition: g_spawn.cpp:526
static void SP_misc_smoke(Edict *ent)
Definition: g_spawn.cpp:944
const char * item
Definition: g_edict.h:127
void SP_func_door(Edict *ent)
func_door (0 .5 .8) ? "health" if set, door is destroyable
Definition: g_func.cpp:335
uint32_t contentFlags
Definition: tracing.h:63
void G_EdictsInit(void)
Reset the entity pointers for eg. a new game.
Definition: g_edicts.cpp:48
byte num_2x2spawnpoints[MAX_TEAMS]
Definition: g_local.h:117
vec3_t mins
Definition: aabb.h:257
Player * AI_CreatePlayer(int team)
Spawn civilians and aliens.
Definition: g_ai.cpp:1944
const char * classname
Definition: g_edict.h:67
GLsizei const GLvoid * data
Definition: r_gl.h:152
#define Q_streq(a, b)
Definition: shared.h:136
#define TEAM_NO_ACTIVE
Definition: q_shared.h:60
const char * name
Definition: g_spawn.cpp:80
Definition: g_edict.h:45
void setMaxs(const vec3_t maxi)
Definition: aabb.h:71
#define ACTOR_SIZE_NORMAL
Definition: defines.h:302
const char * name
Definition: cl_spawn.cpp:271
#define G_ValidMessage(ent)
Definition: g_spawn.h:33
static void Think_SmokeAndFire(Edict *self)
Definition: g_spawn.cpp:421
#define MASK_SMOKE_AND_FIRE
Definition: defines.h:276
static void G_BuildForbiddenListForEntity(Edict *ent)
Create a list of the grid positions the edict occupies and store it with the edict.
Definition: g_spawn.cpp:824
void G_FreeEdict(Edict *ent)
Marks the edict as free.
Definition: g_utils.cpp:41
bool G_MissionTouch(Edict *self, Edict *activator)
Mission trigger.
Definition: g_mission.cpp:53
const char * model
Definition: g_edict.h:74
const char * particle
Definition: g_edict.h:128
Edict * groupChain
Definition: g_edict.h:167
Interface for g_client.cpp.
pos3_t * forbiddenListPos
Definition: g_edict.h:173
byte pos_t
Definition: ufotypes.h:57
Edict * particleLink
Definition: g_edict.h:79
level_locals_t level
Definition: g_main.cpp:38
int HP
Definition: g_edict.h:89
#define PRINT_HUD
Definition: defines.h:107
int GetUsedSlots()
Calculate the number of used inventory slots.
Definition: inventory.cpp:966
static void SP_human_start(Edict *ent)
info_human_start (1 0 0) (-16 -16 -24) (16 16 32) Starting point for a single player human...
Definition: g_spawn.cpp:680