UFO: Alien Invasion
Loading...
Searching...
No Matches
g_edicts.cpp
Go to the documentation of this file.
1
5
6/*
7All original material Copyright (C) 2002-2025 UFO: Alien Invasion.
8
9Original file from Quake 2 v3.21: quake2-2.31/game/g_utils.c
10Copyright (C) 1997-2001 Id Software, Inc.
11
12This program is free software; you can redistribute it and/or
13modify it under the terms of the GNU General Public License
14as published by the Free Software Foundation; either version 2
15of the License, or (at your option) any later version.
16
17This program is distributed in the hope that it will be useful,
18but WITHOUT ANY WARRANTY; without even the implied warranty of
19MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20
21See the GNU General Public License for more details.
22
23You should have received a copy of the GNU General Public License
24along with this program; if not, write to the Free Software
25Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
27*/
28
29#include "g_edicts.h"
30#include "g_actor.h"
31
34
40{
41 g_edicts = static_cast<Edict*>(G_TagMalloc(game.sv_maxentities * sizeof(g_edicts[0]), TAG_GAME));
42 return g_edicts;
43}
44
48void G_EdictsInit (void)
49{
50 for (int i = 0; i < game.sv_maxentities; i++)
51 g_edicts[i].init(i);
52}
53
60int G_EdictsGetNumber (const Edict* ent)
61{
62 const int idx = ent - g_edicts;
63 assert(idx >= 0 && idx < globals.num_edicts);
64 return idx;
65}
66
72bool G_EdictsIsValidNum (const int num)
73{
74 if (num >= 0 && num < globals.num_edicts)
75 return true;
76 return false;
77}
78
83Edict* G_EdictsGetByNum (const int num)
84{
85 if (!G_EdictsIsValidNum(num)) {
86 gi.DPrintf("Invalid edict num %i\n", num);
87 return nullptr;
88 }
89
90 return g_edicts + num;
91}
92
99{
100 return &g_edicts[0];
101}
102
108{
109 if (!globals.num_edicts)
110 return nullptr;
111
112 if (!lastEnt)
113 return g_edicts;
114
115 const Edict* endOfEnts = &g_edicts[globals.num_edicts];
116 assert(lastEnt >= g_edicts);
117 assert(lastEnt < endOfEnts);
118
119 Edict* ent = lastEnt;
120
121 ent++;
122 if (ent >= endOfEnts)
123 return nullptr;
124
125 return ent;
126}
127
129{
130 Edict* duplicate = G_EdictsGetNewEdict();
131 if (duplicate == nullptr)
132 return nullptr;
133 *duplicate = *edict;
134 duplicate->number = G_EdictsGetNumber(duplicate);
135 return duplicate;
136}
137
142{
143 Edict* ent = nullptr;
144
145 /* try to recycle an edict */
146 while ((ent = G_EdictsGetNext(ent))) {
147 if (!ent->inuse)
148 return ent;
149 }
150
151 /* no unused edict found, create a new one */
152 ent = &g_edicts[globals.num_edicts];
153 globals.num_edicts++;
154 if (globals.num_edicts > game.sv_maxentities)
155 return nullptr;
156
157 return ent;
158}
159
167{
168 Edict* ent = lastEnt;
169
170 while ((ent = G_EdictsGetNext(ent))) {
171 if (ent->inuse)
172 break;
173 }
174 return ent;
175}
176
182{
183 Edict* ent = lastEnt;
184
185 while ((ent = G_EdictsGetNextInUse(ent))) {
186 if (G_IsTriggerNextMap(ent))
187 break;
188 }
189 return ent;
190}
191
197{
198 Edict* ent = lastEnt;
199
200 while ((ent = G_EdictsGetNextInUse(ent))) {
201 if (G_IsLivingActor(ent)) {
202 Actor* actor = static_cast<Actor*>(ent);
203 if (actor)
204 return actor;
205 Sys_Error("dynamic_cast to Actor failed.");
206 }
207 }
208 return nullptr;
209}
210
217{
218 Actor* actor = lastEnt;
219
220 while ((actor = G_EdictsGetNextLivingActor(actor))) {
221 if (actor->getTeam() == team)
222 break;
223 }
224 return actor;
225}
226
232{
233 Edict* ent = lastEnt;
234
235 assert(lastEnt < &g_edicts[globals.num_edicts]);
236
237 while ((ent = G_EdictsGetNextInUse(ent))) {
238 if (G_IsActor(ent)) {
239 Actor* actor = static_cast<Actor*>(ent);
240 if (actor)
241 return actor;
242 Sys_Error("dynamic_cast to Actor failed.");
243 }
244 }
245 return nullptr;
246}
247
254Actor* G_EdictsGetActorByUCN (const int ucn, const int team)
255{
256 Actor* actor = nullptr;
257
258 while ((actor = G_EdictsGetNextActor(actor)))
259 if (team == actor->getTeam() && actor->chr.ucn == ucn)
260 return actor;
261
262 return nullptr;
263}
264
271{
272 Actor* actor = nullptr;
273
274 while ((actor = G_EdictsGetNextLivingActor(actor))) {
275 if (!VectorCompare(pos, actor->pos))
276 continue;
277
278 return actor;
279 }
280 /* nothing found at this pos */
281 return nullptr;
282}
283
290Edict* G_EdictsFindTargetEntity (const char* target)
291{
292 Edict* ent = nullptr;
293
294 while ((ent = G_EdictsGetNextInUse(ent))) {
295 const char* n = ent->targetname;
296 if (n && Q_streq(n, target))
297 return ent;
298 }
299
300 return nullptr;
301}
302
306void G_EdictsThink (void)
307{
308 /* treat each object in turn */
309 /* even the world gets a chance to think */
310 Edict* ent = nullptr;
311 while ((ent = G_EdictsGetNextInUse(ent))) {
312 if (!ent->think)
313 continue;
314 if (ent->nextthink <= 0)
315 continue;
316 if (ent->nextthink > level.time + 0.001f)
317 continue;
318
320 ent->think(ent);
321 }
322}
323
328{
329 if (G_IsActor(ent)) {
330 /* should be a dynamic_cast one fine day */
331 Actor* actor = static_cast<Actor*>(ent);
332 if (actor)
333 return actor;
334 }
335 Sys_Error("Unexpected non-Actor Edict found.");
336 return nullptr;
337}
338
339void Edict::init (int idx)
340{
341 inuse = inRescueZone = hiding = active = false;
344 body = head = 0;
345 visflags = 0;
346 dir = dmgtype = 0;
347 angle = nextthink = 0.0f;
349 type = ET_NULL;
354 link = nullptr;
356 group = nullptr;
357 _touch = nullptr;
358 reset = nullptr;
359 think = nullptr;
360 use = nullptr;
361 destroy = nullptr;
362 touchedList = nullptr;
363 forbiddenListPos = nullptr;
364
371 AI = AI_t();
372
373 number = idx;
374 chr.init();
375}
376
383bool Edict::isOpponent (const Actor* actor) const
384{
385 const bool actControlled = actor->isState(STATE_XVI);
386 const bool selfControlled = G_IsState(this, STATE_XVI);
387 if (actor->isSameTeamAs(this))
388 return selfControlled ? !actControlled : actControlled;
389
390 bool opponent = true;
391 switch (this->getTeam()) {
392 /* Aliens: hostile to everyone */
393 case TEAM_ALIEN:
394 opponent = !actControlled;
395 break;
396 /* Civilians: Only hostile to aliens */
397 case TEAM_CIVILIAN:
398 opponent = G_IsAlien(actor) || actControlled;
399 break;
400 /* PHALANX and MP teams: Hostile to aliens and rival teams
401 * (under AI control while under panic/rage or when g_aihumans is non-zero) */
402 default:
403 opponent = !G_IsCivilian(actor) || actControlled;
404 break;
405 }
406
407 return selfControlled ? !opponent : opponent;
408}
static const AABB EMPTY
Definition aabb.h:44
An Edict of type Actor.
Definition g_edict.h:348
bool isState(int flag) const
Definition g_edict.h:353
teammask_t visflags
Definition g_edict.h:82
int linkcount
Definition g_edict.h:48
Edict * _child
Definition g_edict.h:64
int TU
Definition g_edict.h:88
Edict * particleLink
Definition g_edict.h:79
bool isSameTeamAs(const Edict *other) const
Definition g_edict.h:278
const Edict * link
Definition g_edict.h:80
bool hiding
Definition g_edict.h:142
unsigned int body
Definition g_edict.h:99
character_t chr
Definition g_edict.h:116
int flags
Definition g_edict.h:169
camera_edict_data_t camera
Definition g_edict.h:134
bool(* _touch)(Edict *self, Edict *activator)
Definition g_edict.h:146
byte dmgtype
Definition g_edict.h:139
const char * classname
Definition g_edict.h:67
bool active
Definition g_edict.h:177
vec3_t origin
Definition g_edict.h:53
const char * particle
Definition g_edict.h:128
pos3_t pos
Definition g_edict.h:55
moveinfo_t moveinfo
Definition g_edict.h:160
float angle
Definition g_edict.h:120
actorSizeEnum_t fieldSize
Definition g_edict.h:141
int _STUN
Definition g_edict.h:90
int team
Definition g_edict.h:96
void(* think)(Edict *self)
Definition g_edict.h:150
const char * target
Definition g_edict.h:125
int HP
Definition g_edict.h:89
int doorState
Definition g_edict.h:158
const char * noise
Definition g_edict.h:132
byte dir
Definition g_edict.h:86
void init(int idx)
Definition g_edicts.cpp:339
AI_t AI
Definition g_edict.h:171
Edict * groupChain
Definition g_edict.h:167
vec3_t angles
Definition g_edict.h:54
vec3_t size
Definition g_edict.h:62
pos3_t * forbiddenListPos
Definition g_edict.h:173
int contentFlags
Definition g_edict.h:84
Edict * clientAction
Definition g_edict.h:113
bool(* use)(Edict *self, Edict *activator)
Definition g_edict.h:154
bool inuse
Definition g_edict.h:47
int getTeam() const
Definition g_edict.h:269
AABB entBox
Definition g_edict.h:60
Edict * _owner
Definition g_edict.h:65
int modelindex
Definition g_edict.h:66
float nextthink
Definition g_edict.h:149
int mapNum
Definition g_edict.h:73
bool(* destroy)(Edict *self)
Definition g_edict.h:155
bool isOpponent(const Actor *actor) const
Check if given actor is an enemy.
Definition g_edicts.cpp:383
void(* reset)(Edict *self, Edict *activator)
Definition g_edict.h:148
AABB absBox
Definition g_edict.h:61
int dmg
Definition g_edict.h:138
int sounds
Definition g_edict.h:137
int spawnflags
Definition g_edict.h:118
const char * targetname
Definition g_edict.h:126
int time
Definition g_edict.h:136
int count
Definition g_edict.h:135
linkedList_t * touchedList
Definition g_edict.h:157
solid_t solid
Definition g_edict.h:58
int radius
Definition g_edict.h:123
char * group
Definition g_edict.h:104
entity_type_t type
Definition g_edict.h:81
const char * message
Definition g_edict.h:130
bool inRescueZone
Definition g_edict.h:109
int number
Definition g_edict.h:51
unsigned int head
Definition g_edict.h:100
const char * item
Definition g_edict.h:127
Edict * groupMaster
Definition g_edict.h:168
int pnum
Definition g_edict.h:97
int speed
Definition g_edict.h:124
edictMaterial_t material
Definition g_edict.h:133
int forbiddenListSize
Definition g_edict.h:175
int morale
Definition g_edict.h:91
int frame
Definition g_edict.h:102
int state
Definition g_edict.h:93
const char * description
Definition g_edict.h:131
const char * model
Definition g_edict.h:74
const char * nextmap
Definition g_edict.h:129
#define ACTOR_SIZE_INVALID
Definition defines.h:301
bool G_IsLivingActor(const Edict *ent)
Checks whether the given edict is a living actor.
Definition g_actor.cpp:43
#define G_IsState(ent, s)
Definition g_actor.h:29
Edict * G_EdictsFindTargetEntity(const char *target)
Searches the edict that has the given target as targetname set.
Definition g_edicts.cpp:290
Edict * G_EdictsGetFirst(void)
Returns the first entity.
Definition g_edicts.cpp:98
Edict * G_EdictsConstruct(void)
Allocate space for the entity pointers.
Definition g_edicts.cpp:39
Actor * G_EdictsGetNextLivingActorOfTeam(Actor *lastEnt, const int team)
Iterate through the living actor entities of the given team.
Definition g_edicts.cpp:216
Edict * G_EdictsGetTriggerNextMaps(Edict *lastEnt)
Iterator through all the trigger_nextmap edicts.
Definition g_edicts.cpp:181
Actor * G_EdictsGetActorByUCN(const int ucn, const int team)
Searches an actor by a unique character number.
Definition g_edicts.cpp:254
Actor * G_EdictsGetNextActor(Actor *lastEnt)
Iterate through the actor entities (even the dead!).
Definition g_edicts.cpp:231
Actor * makeActor(Edict *ent)
Convert an Edict pointer into an Actor pointer.
Definition g_edicts.cpp:327
Edict * G_EdictsGetNewEdict(void)
Find an entity that is not in use.
Definition g_edicts.cpp:141
Actor * G_EdictsGetNextLivingActor(Actor *lastEnt)
Iterate through the living actor entities.
Definition g_edicts.cpp:196
bool G_EdictsIsValidNum(const int num)
Check if the given number could point to an existing entity.
Definition g_edicts.cpp:72
Edict * G_EdictsGetNext(Edict *lastEnt)
Iterate through the list of entities.
Definition g_edicts.cpp:107
Edict * G_EdictDuplicate(const Edict *edict)
Definition g_edicts.cpp:128
int G_EdictsGetNumber(const Edict *ent)
Get an entity's ID number.
Definition g_edicts.cpp:60
Edict * G_EdictsGetNextInUse(Edict *lastEnt)
Iterate through the entities that are in use.
Definition g_edicts.cpp:166
static Edict * g_edicts
Definition g_edicts.cpp:33
void G_EdictsThink(void)
Called every frame to let the edicts tick.
Definition g_edicts.cpp:306
Actor * G_EdictsGetLivingActorFromPos(const pos3_t pos)
Searches an actor at the given grid location.
Definition g_edicts.cpp:270
Edict * G_EdictsGetByNum(const int num)
Get an entity by it's number.
Definition g_edicts.cpp:83
void G_EdictsInit(void)
Reset the entity pointers for eg. a new game.
Definition g_edicts.cpp:48
functions to handle the storage and lifecycle of all edicts in the game module.
game_locals_t game
Definition g_main.cpp:37
level_locals_t level
Definition g_main.cpp:38
#define SERVER_FRAME_SECONDS
Definition g_local.h:55
#define G_IsActor(ent)
Definition g_local.h:127
#define TAG_GAME
Definition g_local.h:58
game_import_t gi
Definition g_main.cpp:39
#define G_IsTriggerNextMap(ent)
Definition g_local.h:133
#define G_TagMalloc(size, tag)
Definition g_local.h:64
#define G_IsCivilian(ent)
Definition g_local.h:148
#define G_IsAlien(ent)
Definition g_local.h:149
game_export_t globals
Definition g_main.cpp:40
@ MAT_GLASS
Definition g_local.h:268
void Sys_Error(const char *error,...)
Definition g_main.cpp:421
@ SOLID_NOT
Definition game.h:154
#define TEAM_ALIEN
Definition q_shared.h:63
#define STATE_XVI
Definition q_shared.h:274
@ ET_NULL
Definition q_shared.h:146
#define TEAM_CIVILIAN
Definition q_shared.h:61
QGL_EXTERN GLint i
Definition r_gl.h:113
#define Q_streq(a, b)
Definition shared.h:136
Artificial intelligence of a character.
Definition g_local.h:305
actor movement
Definition g_local.h:277
pos_t pos3_t[3]
Definition ufotypes.h:58
#define VectorClear(a)
Definition vector.h:55
#define VectorCompare(a, b)
Definition vector.h:63