UFO: Alien Invasion
Loading...
Searching...
No Matches
g_actor.cpp
Go to the documentation of this file.
1
4
5/*
6Copyright (C) 2002-2025 UFO: Alien Invasion.
7
8This program is free software; you can redistribute it and/or
9modify it under the terms of the GNU General Public License
10as published by the Free Software Foundation; either version 2
11of the License, or (at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
17See the GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
21Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23*/
24
25#include "g_actor.h"
26#include "g_client.h"
27#include "g_edicts.h"
28#include "g_health.h"
29#include "g_inventory.h"
30#include "g_reaction.h"
31#include "g_spawn.h"
32#include "g_utils.h"
33#include "g_vis.h"
34
35/* however we manipulate TUs, this value must never be exceeded */
36#define MAX_TU (ROUTING_NOT_REACHABLE - 1)
37
43bool G_IsLivingActor (const Edict* ent)
44{
45 return G_IsActor(ent) && (G_IsStunned(ent) || !G_IsDead(ent));
46}
47
55void G_ActorUseDoor (Actor* actor, Edict* door)
56{
57 /* check whether it's part of an edict group but not the master */
58 if (door->flags & FL_GROUPSLAVE)
59 door = door->groupMaster;
60
61 if (!G_ClientUseEdict(actor->getPlayer(), actor, door))
62 return;
63
64 /* end this loop here, for the AI this is a) not interesting,
65 * and b) could result in endless loops */
66 if (G_IsAI(actor))
67 return;
68
69 Edict* closeActor = nullptr;
70 while ((closeActor = G_FindRadius(closeActor, door->origin, UNIT_SIZE * 3))) {
71 /* check whether the door is still reachable (this might have
72 * changed due to the rotation) or whether an actor can reach it now */
73 G_TouchTriggers(closeActor);
74 }
75}
76
83{
84 if (actor->clientAction == ent)
85 return;
86
87 assert(ent == nullptr || (ent->flags & FL_CLIENTACTION));
88 actor->clientAction = ent;
89 if (ent == nullptr) {
91 } else {
93 }
94}
95
102int G_ActorUsableTUs (const Edict* ent)
103{
104 if (!ent)
105 return 0;
106
107 return ent->getTus() - ent->getReservedTUs();
108}
109
117{
118 const FiremodeSettings* fm = &ent->chr.RFmode;
119
120 const Item* weapon = ent->getHandItem(fm->getHand());
121 assert(weapon);
122 assert(weapon->def());
123
124 const fireDef_t* fd = weapon->getFiredefs();
125 assert(fd);
126 return G_ActorGetModifiedTimeForFiredef(ent, &fd[fm->getFmIdx()], false);
127}
128
136void G_ActorReserveTUs (Edict* ent, int resReaction, int resShot, int resCrouch)
137{
138 if (ent->getTus() >= resReaction + resShot + resCrouch) {
139 ent->chr.reservedTus.reaction = resReaction;
140 ent->chr.reservedTus.shot = resShot;
141 ent->chr.reservedTus.crouch = resCrouch;
142 }
143
145}
146
154int G_ActorDoTurn (Edict* ent, byte dir)
155{
156 assert(ent->dir < CORE_DIRECTIONS);
157 assert(dir < PATHFINDING_DIRECTIONS);
158
159 /*
160 * If dir is at least CORE_DIRECTIONS but less than FLYING_DIRECTIONS,
161 * then the direction is an action.
162 */
166 if (dir >= CORE_DIRECTIONS && dir < FLYING_DIRECTIONS)
167 return 0;
168
169 /* Clamp dir between 0 and CORE_DIRECTIONS - 1. */
170 dir &= (CORE_DIRECTIONS - 1);
171 assert(dir < CORE_DIRECTIONS);
172
173 /* Return if no rotation needs to be done. */
174 if (ent->dir == dir)
175 return 0;
176
177 /* calculate angle difference */
178 float angleDiv = directionAngles[dir] - directionAngles[ent->dir];
179 if (angleDiv > 180.0)
180 angleDiv -= 360.0;
181 if (angleDiv < -180.0)
182 angleDiv += 360.0;
183
184 /* prepare rotation - decide whether the actor turns around the left
185 * shoulder or the right - this is needed the get the rotation vector
186 * that is used below to check in each of the rotation steps
187 * (1/8, 22.5 degree) whether something became visible while turning */
188 const byte* rot;
189 int num;
190 if (angleDiv > 0) {
191 const int angleStep = (360.0 / CORE_DIRECTIONS);
192 rot = dvleft;
193 num = (angleDiv + angleStep / 2) / angleStep;
194 } else {
195 const int angleStep = (360.0 / CORE_DIRECTIONS);
196 rot = dvright;
197 num = (-angleDiv + angleStep / 2) / angleStep;
198 }
199
200 /* do rotation and vis checks */
201 int status = 0;
202
203 /* check every angle (1/8 steps - on the way to the end direction) in the rotation
204 * whether something becomes visible and stop before reaching the final direction
205 * if this happened */
206 for (int i = 0; i < num; i++) {
207 ent->dir = rot[ent->dir];
208 assert(ent->dir < CORE_DIRECTIONS);
209 status |= G_CheckVisTeamAll(ent->getTeam(), 0, ent);
210 }
211
212 if (status & VIS_STOP) {
213 /* send the turn */
214 G_EventActorTurn(*ent);
215 }
216
217 return status;
218}
219
227{
228 switch (actor->type) {
229 case ET_ACTOR:
231 break;
232 case ET_ACTOR2x2:
234 break;
235 default:
236 gi.Error("G_ActorSetMaxs: Unknown actor type: %i (ent %i)", actor->type, actor->getIdNum());
237 }
238 if (actor->isCrouched())
240 else if (actor->isDead() && !CHRSH_IsTeamDefRobot(actor->chr.teamDef))
241 actor->entBox.setMaxZ(PLAYER_DEAD);
242
243 /* Link it. */
244 gi.LinkEdict(actor);
245}
246
248{
249 const int invWeight = ent->chr.inv.getWeight();
250 const int currentMaxTU = GET_TU(ent->chr.score.skills[ABILITY_SPEED], GET_ENCUMBRANCE_PENALTY(invWeight,
252
253 return std::min(currentMaxTU, MAX_TU);
254}
255
261{
262 const int tus = actor->isDazed() ? 0 : G_ActorCalculateMaxTU(actor);
263 G_ActorSetTU(actor, tus);
264 actor->removeDazed();
265}
266
267void G_ActorSetTU (Edict* ent, int tus)
268{
269 if (tus > 0 && tus < ent->getTus()) {
270 if (g_notu != nullptr && g_notu->integer) {
271 ent->setTus(G_ActorCalculateMaxTU(ent));
272 return;
273 }
274 }
275 ent->setTus(std::max(tus, 0));
276}
277
278void G_ActorUseTU (Edict* ent, int tus)
279{
280 G_ActorSetTU(ent, ent->getTus() - tus);
281}
282
283static bool G_ActorStun (Actor* actor, const Edict* attacker)
284{
285 /* already dead or stunned? */
286 if (actor->isDead())
287 return false;
288
289 /* no other state should be set here */
290 actor->state = STATE_STUN;
291 G_ActorSetMaxs(actor);
292 actor->link = attacker;
293
294 G_ActorModifyCounters(attacker, actor, -1, 0, 1);
295
296 return true;
297}
298
299void G_ActorModifyCounters (const Edict* attacker, const Edict* victim, int deltaAlive, int deltaKills, int deltaStuns)
300{
301 const int victimTeam = victim->getTeam();
302 const unsigned spawned = level.num_spawned[victimTeam];
303 const int attackerTeam = (attacker != nullptr ? attacker->getTeam() : MAX_TEAMS);
304 byte* alive = level.num_alive;
305
306 alive[victimTeam] += deltaAlive;
307 if (alive[victimTeam] > spawned)
308 gi.Error("alive counter out of sync");
309
310 if (deltaStuns != 0) {
311 unsigned* stuns = level.num_stuns[attackerTeam];
312 stuns[victimTeam] += deltaStuns;
313 if (stuns[victimTeam] > spawned)
314 gi.Error("stuns counter out of sync");
315 }
316
317 if (deltaKills != 0) {
318 unsigned* kills = level.num_kills[attackerTeam];
319 kills[victimTeam] += deltaKills;
320 if (kills[victimTeam] > spawned)
321 gi.Error("kills counter out of sync");
322 }
323#if 0
324 {
325 Com_Printf("num_spawned: %i\n", spawned);
326
327 if (attacker)
328 for (int i = 0; i < MAX_TEAMS; i++) {
329 if (i == victimTeam) {
330 Com_Printf("^2num_alive (team %i): %i\n", i, level.num_alive[i]);
331 } else {
332 Com_Printf("num_alive (team %i): %i\n", i, level.num_alive[i]);
333 }
334
335 for (int j = 0; j < MAX_TEAMS; j++) {
336 if (j == victimTeam) {
337 Com_Printf("^2num_kills (team %i killed %i): %i\n", i, j, level.num_kills[i][j]);
338 Com_Printf("^2num_stuns (team %i stunned %i): %i\n", i, j, level.num_stuns[i][j]);
339 } else if (i == attacker->team) {
340 Com_Printf("^3num_kills (team %i killed %i): %i\n", i, j, level.num_kills[i][j]);
341 Com_Printf("^3num_stuns (team %i stunned %i): %i\n", i, j, level.num_stuns[i][j]);
342 } else {
343 Com_Printf("num_kills (team %i killed %i): %i\n", i, j, level.num_kills[i][j]);
344 Com_Printf("num_stuns (team %i stunned %i): %i\n", i, j, level.num_stuns[i][j]);
345 }
346 }
347 }
348 }
349#endif
350}
351
357void G_ActorGetEyeVector (const Edict* actor, vec3_t eye)
358{
359 VectorCopy(actor->origin, eye);
360 if (G_IsCrouched(actor) || G_IsPanicked(actor))
361 eye[2] += EYE_CROUCH;
362 else
363 eye[2] += EYE_STAND;
364}
365
366static void G_ActorRevitalise (Actor* actor)
367{
368 if (actor->isStunned()) {
369 actor->removeStunned();
372 G_ActorModifyCounters(actor->link, actor, 1, 0, -1);
373 G_GetFloorItems(actor);
374 }
375 G_ActorSetMaxs(actor);
376
377 /* check if the player appears/perishes, seen from other teams */
378 G_CheckVis(actor);
379
380 /* calc new vis for this player */
381 G_CheckVisTeamAll(actor->getTeam(), 0, actor);
382
383 G_PrintStats("%s is revitalized.", actor->chr.name);
384}
385
387{
388 if (actor->isStunned() && actor->getStun() < actor->HP) {
389 /* check that we could move after we stood up */
390 Edict* otherActor = nullptr;
391 while ((otherActor = G_EdictsGetNextInUse(otherActor))) {
392 if (!VectorCompare(actor->pos, otherActor->pos))
393 continue;
394 if (G_IsBlockingMovementActor(otherActor))
395 return;
396 }
397
398 G_ActorRevitalise(actor);
401 G_SendStats(*actor);
402 }
403}
404
405static bool G_ActorDie (Actor* actor, const Edict* attacker)
406{
407 const bool stunned = actor->isStunned();
408
409 actor->removeStunned();
410
411 if (actor->isDead())
412 return false;
413
414 G_SetState(actor, 1 + rand() % MAX_DEATH);
415 G_ActorSetMaxs(actor);
416
417 if (stunned) {
418 G_ActorModifyCounters(attacker, actor, 0, 1, 0);
419 G_ActorModifyCounters(actor->link, actor, 0, 0, -1);
420 } else {
421 G_ActorModifyCounters(attacker, actor, -1, 1, 0);
422 }
423
424 return true;
425}
426
435bool G_ActorDieOrStun (Actor* actor, Edict* attacker)
436{
437 bool state;
438
439 if (actor->HP == 0)
440 state = G_ActorDie(actor, attacker);
441 else
442 state = G_ActorStun(actor, attacker);
443
444 /* no state change performed? */
445 if (!state) {
446 gi.DPrintf("G_ActorDieOrStun: State wasn't changed\n");
447 return false;
448 }
449
450 if (!actor->isStunned())
451 actor->solid = SOLID_NOT;
452
453 /* send death */
454 G_EventActorDie(*actor, attacker != nullptr);
456
457 /* handle inventory - drop everything but the armour to the floor */
458 G_InventoryToFloor(actor);
459 G_ClientStateChange(actor->getPlayer(), actor, ~STATE_REACTION, false);
460
461 /* check if the player appears/perishes, seen from other teams */
462 G_CheckVis(actor);
463
464 /* check if the attacker appears/perishes, seen from other teams */
465 if (attacker)
466 G_CheckVis(attacker);
467
468 /* calc new vis for this player */
469 G_CheckVisTeamAll(actor->getTeam(), 0, attacker);
470
471 /* unlink the floor container */
472 actor->resetFloor();
473
475 if (!actor->isStunned())
477
478 return true;
479}
480
485{
486 vec3_t pointTrace;
487
488 VectorCopy(origin, pointTrace);
489 pointTrace[2] += PLAYER_MIN;
490
491 return gi.PointContents(pointTrace);
492}
493
506bool G_ActorInvMove (Actor* actor, const invDef_t* fromContType, Item* fItem, const invDef_t* toContType, int tx, int ty, bool checkaction)
507{
508 assert(fItem);
509 assert(fItem->def());
510
511 /* Store the location/item of 'from' BEFORE actually moving items with moveInInventory. */
512 Item fromItemBackup = *fItem;
513
514 /* Store the location of 'to' BEFORE actually moving items with moveInInventory
515 * so in case we swap ammo the client can be updated correctly */
516 Item* tc = actor->chr.inv.getItemAtPos(toContType, tx, ty);
517 Item toItemBackup;
518 if (tc)
519 toItemBackup = *tc;
520 else
521 toItemBackup = *fItem;
522
523 /* Get first used bit in item. */
524 int fx, fy;
525 fItem->getFirstShapePosition(&fx, &fy);
526 fx += fItem->getX();
527 fy += fItem->getY();
528
529 /* Check if action is possible */
530 /* TUs are 1 here - but this is only a dummy - the real TU check is done in the inventory functions below */
531 Player& player = actor->getPlayer();
532 if (checkaction && !G_ActionCheckForCurrentTeam(player, actor, 1))
533 return false;
534
535 if (!actor->chr.inv.canHoldItemWeight(fromContType->id, toContType->id, *fItem, actor->chr.score.skills[ABILITY_POWER])) {
536 G_ClientPrintf(player, PRINT_HUD, _("This soldier can not carry anything else."));
537 return false;
538 }
539
540 /* "get floor ready" - searching for existing floor-edict */
541 Edict* floor = G_GetFloorItems(actor);
542 bool newFloor = false;
543 if (toContType->isFloorDef() && !floor) {
544 /* We are moving to the floor, but no existing edict for this floor-tile found -> create new one */
545 floor = G_SpawnFloor(actor->pos);
546 newFloor = true;
547 } else if (fromContType->isFloorDef() && !floor) {
548 /* We are moving from the floor, but no existing edict for this floor-tile found -> this should never be the case. */
549 gi.DPrintf("G_ClientInvMove: No source-floor found.\n");
550 return false;
551 }
552
553 /* search for space */
554 Item* item2;
555 if (tx == NONE) {
556 item2 = actor->chr.inv.getItemAtPos(fromContType, fItem->getX(), fItem->getY());
557 if (item2)
558 actor->chr.inv.findSpace(toContType, item2, &tx, &ty, fItem);
559 if (tx == NONE)
560 return false;
561 }
562
564 /* Because moveInInventory don't know anything about character_t and it updates actor->TU,
565 * we need to save original actor->TU for the sake of checking TU reservations. */
566 int originalTU = actor->getTus();
567 int reservedTU = actor->getReservedTUs();
568 /* Temporary decrease actor->TU to make moveInInventory do what expected. */
569 G_ActorUseTU(actor, reservedTU);
570 /* Try to actually move the item and check the return value after restoring valid actor->TU. */
572 ia = game.invi.moveInInventory(&actor->chr.inv, fromContType, fItem, toContType, tx, ty, checkaction ? &actor->TU : nullptr, &item2);
573 /* Now restore the original actor->TU and decrease it for TU used for inventory move. */
574 G_ActorSetTU(actor, originalTU - (originalTU - reservedTU - actor->getTus()));
575
576 switch (ia) {
577 case IA_NONE:
578 /* No action possible - abort */
579 return false;
580 case IA_NOTIME:
581 G_ClientPrintf(player, PRINT_HUD, _("Can't perform action - not enough TUs!"));
582 /* New floor was created, inventory move was aborted, delete empty the floor */
583 if (newFloor) {
584 G_FreeEdict(floor);
585 }
586 return false;
587 case IA_NORELOAD:
589 _("Can't perform action - weapon already fully loaded with the same ammunition!"));
590 return false;
591 default:
592 /* Continue below. */
593 break;
594 }
595
596 /* successful inventory change; remove the item in clients */
597 if (fromContType->isFloorDef()) {
598 /* We removed an item from the floor - check how the client
599 * needs to be updated. */
600 assert(!newFloor);
601 if (actor->getFloor()) {
602 /* There is still something on the floor. */
603 floor->setFloor(actor);
604 /* Delay this if swapping ammo, otherwise the le will be removed in the client before we can add back
605 * the current ammo because removeNextFrame is set in LE_PlaceItem() if the floor le has no items */
606 if (ia != IA_RELOAD_SWAP)
607 G_EventInventoryDelete(*floor, G_VisToPM(floor->visflags), fromContType->id, fx, fy);
608 } else {
609 /* Floor is empty, remove the edict (from server + client) if we are
610 * not moving to it. */
611 if (!toContType->isFloorDef()) {
612 G_EventPerish(*floor);
613 G_FreeEdict(floor);
614 } else
615 G_EventInventoryDelete(*floor, G_VisToPM(floor->visflags), fromContType->id, fx, fy);
616 }
617 } else {
618 G_EventInventoryDelete(*actor, G_TeamToPM(actor->getTeam()), fromContType->id, fx, fy);
619 }
620
621 /* send tu's */
622 G_SendStats(*actor);
623
624 assert(item2);
625 Item item = *item2;
626 playermask_t mask;
627
628 if (ia == IA_RELOAD || ia == IA_RELOAD_SWAP) {
629 /* reload */
630 if (toContType->isFloorDef())
631 mask = G_VisToPM(floor->visflags);
632 else
633 mask = G_TeamToPM(actor->getTeam());
634
635 G_EventInventoryReload(toContType->isFloorDef() ? *floor : *actor, mask, &item, toContType, item2);
636
637 if (ia == IA_RELOAD) {
638 return true;
639 } else { /* ia == IA_RELOAD_SWAP */
641 item.setAmmoDef(nullptr);
642 item.setDef(toItemBackup.ammoDef());
643 item.rotated = fromItemBackup.rotated;
644 item.setAmount(toItemBackup.getAmount());
645 toContType = fromContType;
646 if (toContType->isFloorDef()) {
647 /* moveInInventory placed the swapped ammo in an available space, check where it was placed
648 * so we can place it at the same place in the client, otherwise since fItem hasn't been removed
649 * this could end in a different place in the client - will cause an error if trying to use it again */
650 item2 = actor->chr.inv.findInContainer(toContType->id, &item);
651 assert(item2);
652 fromItemBackup = item;
653 fromItemBackup.setX(item2->getX());
654 fromItemBackup.setY(item2->getY());
655 }
656 tx = fromItemBackup.getX();
657 ty = fromItemBackup.getY();
658 }
659 }
660
661 /* We moved an item to the floor - check how the client needs to be updated. */
662 if (toContType->isFloorDef()) {
663 /* we have to link the temp floor container to the new floor edict or add
664 * the item to an already existing floor edict - the floor container that
665 * is already linked might be from a different entity (this might happen
666 * in case of a throw by another actor) */
667 floor->setFloor(actor);
668
669 /* A new container was created for the floor. */
670 if (newFloor) {
671 /* Send item info to the clients */
672 G_CheckVis(floor);
673 } else {
674 /* use the backup item to use the old amount values, because the clients have to use the same actions
675 * on the original amount. Otherwise they would end in a different amount of items as the server (+1) */
676 G_EventInventoryAdd(*floor, G_VisToPM(floor->visflags), 1);
677 G_WriteItem(fromItemBackup, toContType->id, tx, ty);
678 G_EventEnd();
679 /* Couldn't remove it before because that would remove the le from the client and would cause battlescape to crash
680 * when trying to add back the swapped ammo above */
681 if (ia == IA_RELOAD_SWAP)
682 G_EventInventoryDelete(*floor, G_VisToPM(floor->visflags), fromContType->id, fx, fy);
683 }
684 } else {
685 G_EventInventoryAdd(*actor, G_TeamToPM(actor->getTeam()), 1);
686 G_WriteItem(item, toContType->id, tx, ty);
687 G_EventEnd();
688 }
689
691
692 /* Other players receive weapon info only. */
693 mask = G_VisToPM(actor->visflags) & ~G_TeamToPM(actor->getTeam());
694 if (mask) {
695 if (fromContType->isRightDef() || fromContType->isLeftDef()) {
696 G_EventInventoryDelete(*actor, mask, fromContType->id, fx, fy);
697 }
698 if (toContType->isRightDef() || toContType->isLeftDef()) {
699 G_EventInventoryAdd(*actor, mask, 1);
700 G_WriteItem(item, toContType->id, tx, ty);
701 G_EventEnd();
702 }
703 }
704
705 return true;
706}
707
714bool G_ActorReload (Actor* actor, const invDef_t* invDef)
715{
716 const objDef_t* weapon;
717
718 if (actor->getContainer(invDef->id)) {
719 weapon = actor->getContainer(invDef->id)->def();
720 } else if (invDef->isLeftDef() && actor->getRightHandItem()->isHeldTwoHanded()) {
721 /* Check for two-handed weapon */
722 invDef = INVDEF(CID_RIGHT);
723 weapon = actor->getRightHandItem()->def();
724 } else
725 return false;
726
727 assert(weapon);
728
729 /* LordHavoc: Check if item is researched when in singleplayer? I don't think this is really a
730 * cheat issue as in singleplayer there is no way to inject fake client commands in the virtual
731 * network buffer, and in multiplayer everything is researched */
732
733 /* search for clips and select the one that is available easily */
734 /* also try the temp containers */
735 const invDef_t* bestContainer = nullptr;
736 Item* ammoItem = nullptr;
737 int tu = 100;
738 const Container* cont = nullptr;
739 while ((cont = actor->chr.inv.getNextCont(cont, true))) {
740 if (cont->def()->out >= tu)
741 continue;
742 /* Once we've found at least one clip, there's no point
743 * searching other containers if it would take longer
744 * to retrieve the ammo from them than the one
745 * we've already found. */
746 Item* item = nullptr;
747 while ((item = cont->getNextItem(item))) {
748 if (item->def()->isLoadableInWeapon(weapon)) {
749 ammoItem = item;
750 bestContainer = INVDEF(cont->id);
751 tu = bestContainer->out;
752 break;
753 }
754 }
755 }
756
757 /* send request */
758 if (bestContainer)
759 return G_ActorInvMove(actor, bestContainer, ammoItem, invDef, 0, 0, true);
760 /* No ammo found */
761 return false;
762}
763
764int G_ActorGetModifiedTimeForFiredef (const Edict* const ent, const fireDef_t* const fd, const bool reaction)
765{
766 return fd->time * G_ActorGetInjuryPenalty(ent, reaction ? MODIFIER_REACTION : MODIFIER_SHOOTING);
767}
bool CHRSH_IsTeamDefRobot(const teamDef_t *const td)
Check if a team definition is a robot.
@ ABILITY_POWER
Definition chr_shared.h:37
@ ABILITY_SPEED
Definition chr_shared.h:38
@ MODIFIER_REACTION
Definition chr_shared.h:260
@ MODIFIER_TU
Definition chr_shared.h:261
@ MODIFIER_SHOOTING
Definition chr_shared.h:257
#define _(String)
Definition cl_shared.h:44
#define INVDEF(containerID)
Definition cl_shared.h:48
void setMaxs(const vec3_t maxi)
Definition aabb.h:71
void setMaxZ(float zVal)
Definition aabb.h:80
An Edict of type Actor.
Definition g_edict.h:348
bool isDead() const
Definition g_edict.h:362
void removeStunned()
Definition g_edict.h:376
bool isStunned() const
Definition g_edict.h:355
bool isCrouched() const
Definition g_edict.h:361
void removeDazed()
Definition g_edict.h:381
bool isDazed() const
Definition g_edict.h:360
Item * getNextItem(const Item *prev) const
const invDef_t * def() const
teammask_t visflags
Definition g_edict.h:82
int TU
Definition g_edict.h:88
const Edict * link
Definition g_edict.h:80
character_t chr
Definition g_edict.h:116
int flags
Definition g_edict.h:169
int getIdNum() const
Definition g_edict.h:231
void setFloor(const Edict *other)
Definition g_edict.h:207
Item * getRightHandItem() const
Definition g_edict.h:249
vec3_t origin
Definition g_edict.h:53
pos3_t pos
Definition g_edict.h:55
int team
Definition g_edict.h:96
int HP
Definition g_edict.h:89
byte dir
Definition g_edict.h:86
Edict * clientAction
Definition g_edict.h:113
void resetFloor()
Definition g_edict.h:210
int getTeam() const
Definition g_edict.h:269
AABB entBox
Definition g_edict.h:60
Player & getPlayer() const
Definition g_edict.h:265
int getReservedTUs() const
Calculates the amount of all currently reserved TUs.
Definition g_edict.h:336
Item * getHandItem(actorHands_t hand) const
Definition g_edict.h:255
solid_t solid
Definition g_edict.h:58
entity_type_t type
Definition g_edict.h:81
Item * getContainer(const containerIndex_t idx) const
Definition g_edict.h:243
void setTus(int tus)
Definition g_edict.h:315
Item * getFloor() const
Definition g_edict.h:262
Edict * groupMaster
Definition g_edict.h:168
int getStun() const
Definition g_edict.h:308
int getTus() const
Definition g_edict.h:318
int state
Definition g_edict.h:93
actorHands_t getHand() const
Definition chr_shared.h:165
const objDef_t * getWeapon() const
Definition chr_shared.h:161
int getFmIdx() const
Definition chr_shared.h:157
bool canHoldItemWeight(containerIndex_t from, containerIndex_t to, const Item &item, int maxWeight) const
Check that adding an item to the inventory won't exceed the max permitted weight.
void findSpace(const invDef_t *container, const Item *item, int *const px, int *const py, const Item *ignoredItem) const
Finds space for item in inv at container.
int getWeight() const
Get the weight of the items in the given inventory (excluding those in temp containers).
Item * getItemAtPos(const invDef_t *container, const int x, const int y) const
Searches if there is an item at location (x,y) in a container.
const Container * getNextCont(const Container *prev, bool inclTemp=false) const
item instance data, with linked list capability
Definition inv_shared.h:402
const objDef_t * ammoDef(void) const
Definition inv_shared.h:460
int getX() const
Definition inv_shared.h:454
void setAmount(int value)
Definition inv_shared.h:438
void setAmmoDef(const objDef_t *od)
Definition inv_shared.h:435
int rotated
Definition inv_shared.h:412
int getAmount() const
Definition inv_shared.h:463
void setDef(const objDef_t *objDef)
Definition inv_shared.h:444
const objDef_t * def(void) const
Definition inv_shared.h:469
void setY(const int val)
Definition inv_shared.h:432
int getY() const
Definition inv_shared.h:457
void setX(const int val)
Definition inv_shared.h:429
const fireDef_t * getFiredefs() const
Returns the firedefinitions for a given weapon/ammo.
void getFirstShapePosition(int *const x, int *const y) const
Calculates the first "true" bit in the shape and returns its position in the item.
void setAmmoLeft(int value)
Definition inv_shared.h:441
bool isHeldTwoHanded() const
Definition inv_shared.h:476
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
#define PRINT_HUD
Definition defines.h:107
#define MAX_TEAMS
Definition defines.h:98
#define NONE_AMMO
Definition defines.h:69
#define NONE
Definition defines.h:68
#define UNIT_SIZE
Definition defines.h:121
#define MAX_TU
Definition g_actor.cpp:36
void G_ActorReserveTUs(Edict *ent, int resReaction, int resShot, int resCrouch)
Reserves TUs for different actor actions.
Definition g_actor.cpp:136
static bool G_ActorStun(Actor *actor, const Edict *attacker)
Definition g_actor.cpp:283
bool G_ActorDieOrStun(Actor *actor, Edict *attacker)
Reports and handles death or stun of an actor. If the HP of an actor is zero the actor will die,...
Definition g_actor.cpp:435
bool G_ActorReload(Actor *actor, const invDef_t *invDef)
Reload weapon with actor.
Definition g_actor.cpp:714
void G_ActorGiveTimeUnits(Actor *actor)
Set time units for the given edict. Based on speed skills.
Definition g_actor.cpp:260
int G_ActorUsableTUs(const Edict *ent)
Calculates the amount of usable TUs. This is without the reserved TUs.
Definition g_actor.cpp:102
void G_ActorModifyCounters(const Edict *attacker, const Edict *victim, int deltaAlive, int deltaKills, int deltaStuns)
Definition g_actor.cpp:299
void G_ActorCheckRevitalise(Actor *actor)
Definition g_actor.cpp:386
void G_ActorSetClientAction(Edict *actor, Edict *ent)
Handles the client actions (interaction with the world).
Definition g_actor.cpp:82
void G_ActorUseDoor(Actor *actor, Edict *door)
Make the actor use (as in open/close) a door edict.
Definition g_actor.cpp:55
int G_ActorCalculateMaxTU(const Edict *ent)
Definition g_actor.cpp:247
void G_ActorSetTU(Edict *ent, int tus)
Definition g_actor.cpp:267
int G_ActorGetTUForReactionFire(const Edict *ent)
Calculates the amount of TUs that are needed for the current selected reaction fire mode.
Definition g_actor.cpp:116
int G_ActorGetModifiedTimeForFiredef(const Edict *const ent, const fireDef_t *const fd, const bool reaction)
Definition g_actor.cpp:764
static bool G_ActorDie(Actor *actor, const Edict *attacker)
Definition g_actor.cpp:405
static void G_ActorRevitalise(Actor *actor)
Definition g_actor.cpp:366
void G_ActorUseTU(Edict *ent, int tus)
Definition g_actor.cpp:278
int G_ActorDoTurn(Edict *ent, byte dir)
Turns an actor around.
Definition g_actor.cpp:154
bool G_IsLivingActor(const Edict *ent)
Checks whether the given edict is a living actor.
Definition g_actor.cpp:43
void G_ActorSetMaxs(Actor *actor)
Sets correct bounding box for actor (state dependent).
Definition g_actor.cpp:226
bool G_ActorInvMove(Actor *actor, const invDef_t *fromContType, Item *fItem, const invDef_t *toContType, int tx, int ty, bool checkaction)
Moves an item inside an inventory. Floors are handled special.
Definition g_actor.cpp:506
int G_ActorGetContentFlags(const vec3_t origin)
Get the content flags from where the actor is currently standing.
Definition g_actor.cpp:484
void G_ActorGetEyeVector(const Edict *actor, vec3_t eye)
Fills a vector with the eye position of a given actor.
Definition g_actor.cpp:357
#define G_IsStunned(ent)
Definition g_actor.h:30
#define G_IsCrouched(ent)
Definition g_actor.h:32
#define G_SetState(ent, s)
Definition g_actor.h:36
#define G_IsDead(ent)
Definition g_actor.h:34
#define G_IsPanicked(ent)
Definition g_actor.h:31
playermask_t G_TeamToPM(int team)
Generates the player bit mask for a given team.
Definition g_client.cpp:144
bool G_ActionCheckForCurrentTeam(const Player &player, Actor *ent, int TU)
Checks whether the requested action is possible for the current active team.
Definition g_client.cpp:380
bool G_ClientUseEdict(const Player &player, Actor *actor, Edict *edict)
This function 'uses' the edict. E.g. it opens the door when the player wants it to open.
Definition g_client.cpp:614
void G_ClientStateChange(const Player &player, Actor *actor, int reqState, bool checkaction)
Changes the state of a player/soldier.
Definition g_client.cpp:473
void G_ClientPrintf(const Player &player, int printLevel, const char *fmt,...)
Definition g_client.cpp:206
playermask_t G_VisToPM(teammask_t teamMask)
Converts vis mask to player mask.
Definition g_client.cpp:186
Interface for g_client.cpp.
Edict * G_EdictsGetNextInUse(Edict *lastEnt)
Iterate through the entities that are in use.
Definition g_edicts.cpp:166
functions to handle the storage and lifecycle of all edicts in the game module.
void G_EventEnd(void)
Definition g_events.cpp:711
void G_EventInventoryDelete(const Edict &ent, playermask_t playerMask, const containerIndex_t containerId, int x, int y)
Tell the client to remove the item from the container.
Definition g_events.cpp:131
void G_EventActorTurn(const Edict &ent)
Send the turn event for the given entity.
Definition g_events.cpp:77
void G_EventSetClientAction(const Edict &ent)
Informs the client that an interaction with the world is possible.
Definition g_events.cpp:360
void G_EventActorDie(const Edict &ent, bool attacker)
Announce the actor die event for the clients that are seeing the actor.
Definition g_events.cpp:89
void G_EventInventoryAdd(const Edict &ent, playermask_t playerMask, int itemAmount)
Tell the client to add the item from the container.
Definition g_events.cpp:147
void G_EventActorSendReservations(const Edict &ent)
Will inform the player about the real TU reservation.
Definition g_events.cpp:113
void G_EventPerish(const Edict &ent)
Send an event to all clients that are seeing the given edict, that it just has disappeared.
Definition g_events.cpp:158
void G_EventActorRevitalise(const Edict &ent)
Announce the actor revitalize event for the clients that are seeing the actor.
Definition g_events.cpp:102
void G_EventInventoryReload(const Edict &ent, playermask_t playerMask, const Item *item, const invDef_t *invDef, const Item *ic)
Definition g_events.cpp:421
void G_EventResetClientAction(const Edict &ent)
Reset the client actions for the given entity.
Definition g_events.cpp:376
void G_EventActorStateChange(playermask_t playerMask, const Edict &ent)
Definition g_events.cpp:632
unsigned int playermask_t
Definition g_events.h:34
float G_ActorGetInjuryPenalty(const Edict *const ent, const modifier_types_t type)
Returns the penalty to the given stat caused by the actor wounds.
Definition g_health.cpp:177
void G_InventoryToFloor(Edict *ent)
Move items to adjacent locations if the containers on the current floor edict are full.
Edict * G_GetFloorItems(Edict *ent)
Prepares a list of items on the floor at given entity position.
void G_WriteItem(const Item &item, const containerIndex_t contId, int x, int y)
Write an item to the network buffer.
game_locals_t game
Definition g_main.cpp:37
level_locals_t level
Definition g_main.cpp:38
#define G_IsActor(ent)
Definition g_local.h:127
cvar_t * g_notu
Definition g_main.cpp:117
#define G_IsAI(ent)
Definition g_local.h:141
#define FL_GROUPSLAVE
not the first on the team
Definition g_local.h:294
void G_SendStats(Edict &ent)
Send stats to network buffer.
Definition g_stats.cpp:34
game_import_t gi
Definition g_main.cpp:39
#define FL_CLIENTACTION
Edict flag to indicate, that the edict can be used in the context of a client action.
Definition g_local.h:298
#define G_IsBlockingMovementActor(ent)
Definition g_local.h:150
void G_ReactionFireSettingsUpdate(Actor *actor, fireDefIndex_t fmIdx, actorHands_t hand, const objDef_t *od)
Updates the reaction fire settings in case something was moved into a hand or from a hand that would ...
void G_ReactionFireTargetsDestroy(const Edict *shooter)
free function to destroy the table of reaction fire targets for the given edict.
void G_ReactionFireOnDead(const Actor *target)
Removes the given target from the reaction fire lists.
Reaction fire system.
Edict * G_SpawnFloor(const pos3_t pos)
Spawns a new entity at the floor.
Definition g_spawn.cpp:535
Brings new objects into the world.
void G_PrintStats(const char *format,...)
Prints stats to game console and stats log file.
Definition g_utils.cpp:304
void G_FreeEdict(Edict *ent)
Marks the edict as free.
Definition g_utils.cpp:41
int G_TouchTriggers(Edict *ent, const entity_type_t type)
Check the world against triggers for the current entity.
Definition g_utils.cpp:547
Edict * G_FindRadius(Edict *from, const vec3_t org, float rad, entity_type_t type)
Returns entities that have origins within a spherical area.
Definition g_utils.cpp:408
Misc utility functions for game module.
int G_CheckVisTeamAll(const int team, const vischeckflags_t visFlags, const Edict *ent)
Do G_CheckVisTeam for all entities ent is the one that is looking at the others.
Definition g_vis.cpp:376
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
#define VIS_STOP
Definition g_vis.h:40
@ SOLID_NOT
Definition game.h:154
inventory_action_t
Possible inventory actions for moving items between containers.
Definition inv_shared.h:65
@ IA_NONE
Definition inv_shared.h:66
@ IA_NORELOAD
Definition inv_shared.h:74
@ IA_NOTIME
Definition inv_shared.h:73
@ IA_RELOAD
Definition inv_shared.h:70
@ IA_RELOAD_SWAP
Definition inv_shared.h:71
#define CID_RIGHT
Definition inv_shared.h:47
voidpf uLong int origin
Definition ioapi.h:45
const byte dvleft[CORE_DIRECTIONS]
Definition mathlib.cpp:119
const float directionAngles[CORE_DIRECTIONS]
Definition mathlib.cpp:105
const byte dvright[CORE_DIRECTIONS]
Definition mathlib.cpp:116
#define FLYING_DIRECTIONS
Definition mathlib.h:89
#define CORE_DIRECTIONS
Definition mathlib.h:88
#define PATHFINDING_DIRECTIONS
Definition mathlib.h:87
#define GET_TU(ab, md)
Definition q_shared.h:291
#define MAX_DEATH
Definition q_shared.h:257
#define STATE_STUN
Definition q_shared.h:268
@ ET_ACTOR
Definition q_shared.h:148
@ ET_ACTOR2x2
Definition q_shared.h:160
#define GET_ENCUMBRANCE_PENALTY(weight, max)
Definition q_shared.h:287
#define STATE_REACTION
Definition q_shared.h:272
#define PLAYER_DEAD
Definition q_sizes.h:8
#define PLAYER_MIN
Definition q_sizes.h:9
#define PLAYER_CROUCH
Definition q_sizes.h:7
#define PLAYER_STAND
Definition q_sizes.h:6
#define PLAYER_WIDTH
Definition q_sizes.h:10
#define EYE_STAND
Definition q_sizes.h:4
#define EYE_CROUCH
Definition q_sizes.h:5
#define PLAYER2x2_WIDTH
Definition q_sizes.h:23
QGL_EXTERN GLint i
Definition r_gl.h:113
chrReservations_t reservedTus
Definition chr_shared.h:415
const teamDef_t * teamDef
Definition chr_shared.h:413
chrScoreGlobal_t score
Definition chr_shared.h:406
FiremodeSettings RFmode
Definition chr_shared.h:416
char name[MAX_VAR]
Definition chr_shared.h:390
Inventory inv
Definition chr_shared.h:411
int skills[SKILL_NUM_TYPES]
Definition chr_shared.h:122
this is a fire definition for our weapons/ammo
Definition inv_shared.h:110
inventory definition for our menus
Definition inv_shared.h:371
bool isFloorDef() const
Checks whether the inventory definition is the floor.
bool isLeftDef() const
Checks whether a given inventory definition is of special type.
containerIndex_t id
Definition inv_shared.h:373
bool isRightDef() const
Checks whether the inventory definition is the right Hand.
Defines all attributes of objects used in the inventory.
Definition inv_shared.h:264
bool isLoadableInWeapon(const objDef_s *weapon) const
Checks if an item can be used to reload a weapon.
vec_t vec3_t[3]
Definition ufotypes.h:39
#define VectorCopy(src, dest)
Definition vector.h:51
#define VectorCompare(a, b)
Definition vector.h:63