UFO: Alien Invasion
Loading...
Searching...
No Matches
cl_actor.cpp
Go to the documentation of this file.
1
5
6/*
7Copyright (C) 2002-2025 UFO: Alien Invasion.
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18See the GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24*/
25
26#include "../client.h"
27#include "cl_actor.h"
28#include "../cgame/cl_game.h"
29#include "cl_hud.h"
30#include "cl_parse.h"
31#include "cl_particle.h"
32#include "cl_view.h"
33#include "../cl_screen.h"
34#include "../ui/ui_main.h"
35#include "../ui/ui_popup.h"
38#include "../renderer/r_mesh.h"
40#include "../../common/grid.h"
41
47
48/* public */
53
63
67
73void MSG_Write_PA (player_action_t playerAction, int entnum, ...)
74{
75 va_list ap;
76 dbuffer msg;
77
78 va_start(ap, entnum);
79 NET_WriteFormat(&msg, "bbs", clc_action, playerAction, entnum);
80 NET_vWriteFormat(&msg, pa_format[playerAction], ap);
81 va_end(ap);
82 NET_WriteMsg(cls.netStream, msg);
83}
84
85/*
86==============================================================
87ACTOR MENU UPDATING
88==============================================================
89*/
90
91void CL_ActorSetFireDef (le_t* actor, const fireDef_t* fd)
92{
93 if (actor->fd != fd)
95 actor->fd = fd;
96}
97
102int CL_ActorMoveMode (const le_t* le)
103{
104 assert(le);
105 if (!LE_IsCrouched(le))
106 return WALKTYPE_WALKING;
107
108 /* Is the player using autostand? */
109 if (!cl_autostand->integer)
111
112 /* ...and if this is a long walk... */
113 if (RT_CanActorStandHere(cl.mapData->routing, le->fieldSize, le->pos)
114 && Grid_ShouldUseAutostand(&cl.pathMap, mousePos))
116
118}
119
125int CL_ActorGetNumber (const le_t* le)
126{
127 assert(le);
128
129 for (int actorIdx = 0; actorIdx < cl.numTeamList; actorIdx++) {
130 if (cl.teamList[actorIdx] == le)
131 return actorIdx;
132 }
133 return -1;
134}
135
142{
143 for (int i = 0; i < cl.numTeamList; ++i) {
144 if (cl.teamList[i] && cl.teamList[i]->ucn == chr->ucn)
145 return cl.teamList[i];
146 }
147 return nullptr;
148}
149
156{
157 const linkedList_t* chrList = cl.chrList;
158
159 LIST_Foreach(chrList, character_t, chr) {
160 if (chr->ucn == le->ucn)
161 return chr;
162 }
163
164 return nullptr;
165}
166
172{
173 const character_t* chr = CL_ActorGetChr(shooter);
174 if (chr == nullptr)
175 return nullptr;
176
177 const FiremodeSettings& fmSetting = chr->RFmode;
178 const Item* weapon = shooter->getHandItem(fmSetting.getHand());
179 if (weapon == nullptr)
180 return nullptr;
181
182 const fireDef_t* fdArray = weapon->getFiredefs();
183 if (fdArray == nullptr)
184 return nullptr;
185
186 const int fmIdx = fmSetting.getFmIdx();
187 if (fmIdx < 0 || fmIdx >= MAX_FIREDEFS_PER_WEAPON)
188 return nullptr;
189
190 const fireDef_t* fd = &fdArray[fmIdx];
191 return fd;
192}
193
199bool CL_ActorIsReactionFireOutOfRange (const le_t* shooter, const le_t* target)
200{
201 const float distance = VectorDist(shooter->origin, target->origin);
202 const fireDef_t* fd = CL_ActorGetReactionFireFireDef(shooter);
203 const bool outOfRange = fd->range < distance;
204 return outOfRange;
205}
206
215{
216 if (!le)
217 return -1;
218
219 const character_t* chr = CL_ActorGetChr(le);
220 if (!chr) {
221 Com_DPrintf(DEBUG_CLIENT, "CL_ActorReservedTUs: No character found for le.\n");
222 return -1;
223 }
224
225 const int reservedReaction = std::max(0, chr->reservedTus.reaction);
226 const int reservedCrouch = std::max(0, chr->reservedTus.crouch);
227 const int reservedShot = std::max(0, chr->reservedTus.shot);
228
229 switch (type) {
230 case RES_ALL:
231 /* A summary of ALL TUs that are reserved. */
232 return reservedReaction + reservedCrouch + reservedShot;
233 case RES_ALL_ACTIVE: {
234 /* A summary of ALL TUs that are reserved depending on their "status". */
235 /* Only use reaction-value if we have RF activated. */
236 if ((le->state & STATE_REACTION))
237 return reservedReaction + reservedShot + reservedCrouch;
238 else
239 return reservedShot + reservedCrouch;
240 }
241 case RES_REACTION:
242 return reservedReaction;
243 case RES_CROUCH:
244 return reservedCrouch;
245 case RES_SHOT:
246 return reservedShot;
247 default:
248 Com_DPrintf(DEBUG_CLIENT, "CL_ActorReservedTUs: Bad type given: %i\n", type);
249 return -1;
250 }
251}
252
259int CL_ActorUsableTUs (const le_t* le)
260{
261 if (!le)
262 return -1;
263
264 return le->TU - CL_ActorReservedTUs(le, RES_ALL_ACTIVE);
265}
266
273void CL_ActorReserveTUs (const le_t* le, const reservation_types_t type, const int tus)
274{
275 assert(type != RES_REACTION);
276
277 if (!le || tus < 0)
278 return;
279
280 character_t* chr = CL_ActorGetChr(le);
281 if (chr) {
283
284 if (type == RES_CROUCH)
285 res.crouch = tus;
286 else if (type == RES_SHOT)
287 res.shot = tus;
288
290 }
291}
292
300{
301 float mod = 0;
302
303 if (le) {
304 const character_t* chr = CL_ActorGetChr(le);
305 if (!chr)
306 return 0;
307 const BodyData* bodyTemplate = chr->teamDef->bodyTemplate;
308 for (int bodyPart = 0; bodyPart < bodyTemplate->numBodyParts(); ++bodyPart) {
309 const int threshold = le->maxHP * bodyTemplate->woundThreshold(bodyPart);
310 const int injury = (le->wounds.woundLevel[bodyPart] + le->wounds.treatmentLevel[bodyPart] * 0.5);
311 if (injury > threshold)
312 mod += 2 * bodyTemplate->penalty(bodyPart, type) * injury / le->maxHP;
313 }
314
315 switch (type) {
318 break;
321 ++mod;
322 break;
324 mod = ceil(mod);
325 break;
326 default:
327 Com_Printf("CL_ActorInjuryPenalty: Unused modifier type %i\n", type);
328 mod = 0;
329 break;
330 }
331 }
332 return mod;
333}
334
342int CL_ActorTimeForFireDef (const le_t* le, const fireDef_t* fd, bool reaction)
343{
344 if (!fd)
345 return -1;
346
347 return fd->time * CL_ActorInjuryModifier(le, reaction ? MODIFIER_REACTION : MODIFIER_SHOOTING);
348}
349
350/*
351==============================================================
352ACTOR SELECTION AND TEAM LIST
353==============================================================
354*/
355
363{
364 /* test team */
365 if (!le || le->team != cls.team || le->pnum != cl.pnum || LE_IsDead(le))
366 return;
367
368 /* check list for that actor */
369 int actorIdx = CL_ActorGetNumber(le);
370
371 /* add it */
372 if (actorIdx == -1) {
373 /* check list length */
374 const size_t size = lengthof(cl.teamList);
375 if (cl.numTeamList >= size) {
376 Com_Printf("Too many actors on the teamlist!\n");
377 return;
378 }
379 cl.teamList[cl.numTeamList] = le;
380 UI_ExecuteConfunc("hudenable %i", cl.numTeamList);
381 cl.numTeamList++;
382 if (cl.numTeamList == 1)
384 } else {
385 UI_ExecuteConfunc("hudenable %i", actorIdx);
386 }
387}
388
390{
391 cls.i.destroyInventory(&le->inv);
392}
393
401{
402 if (!le)
403 return;
404
405 for (int i = 0; i < cl.numTeamList; i++) {
406 if (cl.teamList[i] == le) {
407 if (!LE_IsStunned(le)) {
408 CL_ActorCleanup(le);
409 /* remove from list */
410 cl.teamList[i] = nullptr;
411 }
412
413 /* disable hud button */
414 UI_ExecuteConfunc("huddisable %i", i);
415
416 break;
417 }
418 }
419
420 /* check selection */
421 if (LE_IsSelected(le)) {
422 int i;
423 for (i = 0; i < cl.numTeamList; i++) {
424 le_t* tl = cl.teamList[i];
425 if (tl && CL_ActorSelect(tl))
426 break;
427 }
428
429 if (i == cl.numTeamList)
430 CL_ActorSelect(nullptr);
431 }
432}
433
441{
442 /* test team */
443 if (!le) {
444 if (selActor)
445 selActor->flags &= ~LE_SELECTED;
446 selActor = nullptr;
447 ui_inventory = nullptr;
448 return false;
449 }
450
451 if (le->pnum != cl.pnum || LE_IsDead(le) || !le->inuse)
452 return false;
453
454 if (LE_IsSelected(le)) {
456 return true;
457 }
458
459 if (selActor)
460 selActor->flags &= ~LE_SELECTED;
461
463 selActor = le;
464 selActor->flags |= LE_SELECTED;
465 ui_inventory = &selActor->inv;
466
467 if (le->state & RF_IRGOGGLESSHOT)
468 refdef.rendererFlags |= RDF_IRGOGGLES;
469 else
470 refdef.rendererFlags &= ~RDF_IRGOGGLES;
471
472 if (le->clientAction != nullptr)
473 UI_ExecuteConfunc("enable_clientaction");
474 else
475 UI_ExecuteConfunc("disable_clientaction");
476
477 const int actorIdx = CL_ActorGetNumber(le);
478 if (actorIdx == -1)
479 return false;
480
481 /* console commands, update cvars */
482 Cvar_ForceSet("cl_selected", va("%i", actorIdx));
483
484 const character_t* chr = CL_ActorGetChr(le);
485 if (!chr)
486 Com_Error(ERR_DROP, "No character given for local entity!");
487
489
491
492 return true;
493}
494
506bool CL_ActorSelectList (int num)
507{
508 /* check if actor exists */
509 if (num >= cl.numTeamList || num < 0)
510 return false;
511
512 /* select actor */
513 le_t* le = cl.teamList[num];
514 if (!le || !CL_ActorSelect(le))
515 return false;
516
517 /* center view (if wanted) */
518 LE_CenterView(le);
519 Cvar_SetValue("cl_worldlevel", le->pos[2]);
520
521 return true;
522}
523
528{
529 int selIndex = -1;
530 const int num = cl.numTeamList;
531
532 /* find index of currently selected actor */
533 for (int i = 0; i < num; i++) {
534 const le_t* le = cl.teamList[i];
535 if (le && le->inuse && LE_IsSelected(le) && !LE_IsDead(le)) {
536 selIndex = i;
537 break;
538 }
539 }
540 if (selIndex < 0)
541 return false; /* no one selected? */
542
543 /* cycle round */
544 int i = selIndex;
545 while (true) {
546 i = (i + 1) % num;
547 if (i == selIndex)
548 break;
550 return true;
551 }
552 return false;
553}
554
559{
560 int selIndex = -1;
561 const int num = cl.numTeamList;
562
563 /* find index of currently selected actor */
564 for (int i = 0; i < num; i++) {
565 const le_t* le = cl.teamList[i];
566 if (le && le->inuse && LE_IsSelected(le) && !LE_IsDead(le)) {
567 selIndex = i;
568 break;
569 }
570 }
571 if (selIndex < 0)
572 return false; /* no one selected? */
573
574 /* cycle round */
575 int i = selIndex;
576 while (true) {
577 /* i = (i - 1) % num; */
578 i--;
579 if (i < 0)
580 i = num - 1;
581
582 if (i == selIndex)
583 break;
585 return true;
586 }
587 return false;
588}
589
590
591/*
592==============================================================
593ACTOR MOVEMENT AND SHOOTING
594==============================================================
595*/
596
603
612static void CL_BuildForbiddenList (void)
613{
614 le_t* le = nullptr;
615
616 forbiddenList.reset();
617
618 while ((le = LE_GetNextInUse(le))) {
619 if (LE_IsInvisible(le))
620 continue;
621 /* Dead ugv will stop walking, too. */
622 if (le->type == ET_ACTOR2x2 || (!LE_IsStunned(le) && LE_IsLivingAndVisibleActor(le))) {
623 forbiddenList.add(le->pos, (byte*)&le->fieldSize);
624 }
625 }
626}
627
628#ifdef DEBUG
635static void CL_DisplayBlockedPaths_f (void)
636{
637 le_t* le = nullptr;
638
639 while ((le = LE_GetNextInUse(le))) {
640 vec3_t s;
641 switch (le->type) {
642 case ET_ACTOR:
643 case ET_ACTOR2x2:
644 /* draw blocking cursor at le->pos */
645 if (!LE_IsDead(le))
646 Grid_PosToVec(cl.mapData->routing, le->fieldSize, le->pos, s);
647 break;
648 case ET_DOOR:
649 case ET_BREAKABLE:
650 case ET_ROTATING:
651 VectorCopy(le->origin, s);
652 break;
653 default:
654 continue;
655 }
656
657 ptl_t* ptl = CL_ParticleSpawn("blocked_field", 0, s, nullptr, nullptr);
658 ptl->rounds = 2;
659 ptl->roundsCnt = 2;
660 ptl->life = 10000;
661 ptl->t = 0;
662 if (le->fieldSize == ACTOR_SIZE_2x2) {
663 /* If this actor blocks 4 fields draw them as well. */
664 for (int j = 0; j < 3; j++) {
665 ptl_t* ptl2 = CL_ParticleSpawn("blocked_field", 0, s, nullptr, nullptr);
666 ptl2->rounds = ptl->rounds;
667 ptl2->roundsCnt = ptl->roundsCnt;
668 ptl2->life = ptl->life;
669 ptl2->t = ptl->t;
670 }
671 }
672 }
673}
674#endif
675
683{
685 if (le && LE_IsSelected(le)) {
686 Grid_CalcPathing(cl.mapData->routing, le->fieldSize, &cl.pathMap, le->pos, MAX_ROUTE_TUS, &forbiddenList);
688 }
689}
690
695{
696 le_t* closest = nullptr;
697 le_t* le = nullptr;
698 while ((le = LE_GetNextInUse(le))) {
699 if (le->team != team || !LE_IsLivingAndVisibleActor(le))
700 continue;
701
702 if (closest == nullptr || VectorDist(le->origin, origin) < VectorDist(closest->origin, origin))
703 closest = le;
704 }
705 return closest;
706}
707
714{
715 if (!le)
716 return false;
717
718 if (le->isMoving())
719 return false;
720
721 if (!cls.isOurRound()) {
722 HUD_DisplayMessage(_("It is not your turn!"));
723 return false;
724 }
725
726 return true;
727}
728
737static byte CL_ActorMoveLength (const le_t* le, const pos3_t to)
738{
739 const bool useAutostand = LE_IsCrouched(le) && cl_autostand->integer
740 && Grid_ShouldUseAutostand(&cl.pathMap, to);
741 const int autostandTU = useAutostand ? 2 * TU_CROUCH : 0;
742 byte crouchingState = LE_IsCrouched(le) && !useAutostand ? 1 : 0;
743 const int length = Grid_MoveLength(&cl.pathMap, to, crouchingState, false);
744
746 return length;
747
748 pos3_t pos;
749 VectorCopy(to, pos);
750 int dvec, numSteps = 0;
751 while ((dvec = Grid_MoveNext(&cl.pathMap, pos, crouchingState)) != ROUTING_UNREACHABLE) {
752 ++numSteps;
753 PosSubDV(pos, crouchingState, dvec); /* We are going backwards to the origin. */
754 }
755
756 return std::min(ROUTING_NOT_REACHABLE, length + static_cast<int>(numSteps
757 * CL_ActorInjuryModifier(le, MODIFIER_MOVEMENT)) + autostandTU);
758}
759
768
776static bool CL_ActorTraceMove (const pos3_t to)
777{
778 if (!selActor)
779 return false;
780
783 return false;
784
785
786 vec3_t oldVec;
787 Grid_PosToVec(cl.mapData->routing, selActor->fieldSize, to, oldVec);
788 pos3_t pos;
789 VectorCopy(to, pos);
790
791 int dvec;
792 byte crouchingState = LE_IsCrouched(selActor) ? 1 : 0;
793 while ((dvec = Grid_MoveNext(&cl.pathMap, pos, crouchingState)) != ROUTING_UNREACHABLE) {
795 PosSubDV(pos, crouchingState, dvec); /* We are going backwards to the origin. */
796 vec3_t vec;
797 Grid_PosToVec(cl.mapData->routing, selActor->fieldSize, pos, vec);
799 CL_ParticleSpawn("longRangeTracer", 0, vec, oldVec);
800 else if (crouchingState)
801 CL_ParticleSpawn("crawlTracer", 0, vec, oldVec);
802 else
803 CL_ParticleSpawn("moveTracer", 0, vec, oldVec);
804 VectorCopy(vec, oldVec);
805 }
806 return true;
807}
808
816static void CL_ActorMaximumMove (const pos3_t to, const le_t* le, pos3_t pos)
817{
818 const byte length = CL_ActorMoveLength(le, to);
820 return;
821
822 VectorCopy(to, pos);
823
824 int dvec;
825 byte crouchingState = le && LE_IsCrouched(le) ? 1 : 0;
826 const int tus = CL_ActorUsableTUs(le);
827 while ((dvec = Grid_MoveNext(&cl.pathMap, pos, crouchingState)) != ROUTING_UNREACHABLE) {
828 const byte length2 = CL_ActorMoveLength(le, pos);
829 if (length2 <= tus)
830 return;
831 PosSubDV(pos, crouchingState, dvec); /* We are going backwards to the origin. */
832 }
833}
834
835void CL_ActorSetMode (le_t* actor, actorModes_t actorMode)
836{
837 actor->actorMode = actorMode;
838}
839
847void CL_ActorStartMove (le_t* le, const pos3_t to)
848{
849 if (IN_GetMouseSpace() != MS_WORLD)
850 return;
851
852 if (!CL_ActorCheckAction(le))
853 return;
854
855 byte length = CL_ActorMoveLength(le, to);
856
858 /* move not valid, don't even care to send */
859 return;
860 }
861
862 /* Get the last position we can walk to with the usable TUs. */
863 pos3_t toReal;
864 CL_ActorMaximumMove(to, le, toReal);
865
866 /* Get the cost of the new position just in case. */
867 length = CL_ActorMoveLength(le, toReal);
868
869 if (CL_ActorUsableTUs(le) < length) {
870 /* We do not have enough _usable_ TUs to move so don't even try to send. */
871 /* This includes a check for reserved TUs (which isn't done on the server!) */
872 return;
873 }
874
875 /* change mode to move now */
877
878 /* move seems to be possible; send request to server */
879 MSG_Write_PA(PA_MOVE, le->entnum, toReal);
880}
881
882
888void CL_ActorShoot (const le_t* le, const pos3_t at)
889{
890 if (IN_GetMouseSpace() != MS_WORLD)
891 return;
892
893 if (!CL_ActorCheckAction(le))
894 return;
895
896 int type;
897 if (IS_MODE_FIRE_RIGHT(le->actorMode)) {
898 type = ST_RIGHT;
899 } else if (IS_MODE_FIRE_LEFT(le->actorMode)) {
900 type = ST_LEFT;
901 } else if (IS_MODE_FIRE_HEADGEAR(le->actorMode)) {
903 } else
904 return;
905
907}
908
916int CL_ActorGetContainerForReload (Item** ammoItem, const Inventory* inv, const objDef_t* weapon)
917{
918 int tu = 100;
919 containerIndex_t bestContainer = NONE;
920
921 /* also search the linked ground floor tile (temp container) */
922 for (containerIndex_t container = 0; container < CID_MAX; container++) {
923 if (INVDEF(container)->out >= tu)
924 continue;
925 /* Once we've found at least one clip, there's no point
926 * searching other containers if it would take longer
927 * to retrieve the ammo from them than the one
928 * we've already found. */
929 for (Item* item = inv->getContainer2(container); item; item = item->getNext()) {
930 const objDef_t* od = item->def();
931 if (!od->isLoadableInWeapon(weapon) || !GAME_ItemIsUseable(od))
932 continue;
933 tu = INVDEF(container)->out;
934 bestContainer = container;
935 *ammoItem = item;
936 break;
937 }
938 }
939 return bestContainer;
940}
941
948void CL_ActorReload (le_t* le, containerIndex_t containerID)
949{
950 if (!CL_ActorCheckAction(le))
951 return;
952
953 /* check weapon */
954 Inventory* inv = &le->inv;
955
956 const objDef_t* weapon;
957 if (inv->getContainer2(containerID)) {
958 weapon = inv->getContainer2(containerID)->def();
959 } else if (containerID == CID_LEFT && inv->getContainer2(CID_RIGHT)->isHeldTwoHanded()) {
960 /* Check for two-handed weapon */
961 containerID = CID_RIGHT;
962 weapon = inv->getContainer2(containerID)->def();
963 } else {
964 /* no weapon in the reloadable containers found */
965 return;
966 }
967
968 if (!weapon)
969 return;
970
971 /* return if the weapon is not reloadable */
972 if (!weapon->isReloadable())
973 return;
974
975 if (!GAME_ItemIsUseable(weapon)) {
976 HUD_DisplayMessage(_("You cannot reload this unknown item."));
977 return;
978 }
979
980 Item* ic;
981 const containerIndex_t bestContainer = CL_ActorGetContainerForReload(&ic, inv, weapon);
982 /* send request */
983 if (bestContainer != NONE) {
984 int x, y;
985
986 ic->getFirstShapePosition(&x, &y);
987 x += ic->getX();
988 y += ic->getY();
989
990 CL_ActorInvMove(le, bestContainer, x, y, containerID, 0, 0);
991 }
992}
993
1004void CL_ActorInvMove (const le_t* le, containerIndex_t fromContainer, int fromX, int fromY, containerIndex_t toContainer, int toX, int toY)
1005{
1006 assert(CL_BattlescapeRunning());
1007 assert(le);
1008 assert(LE_IsActor(le));
1009
1010 const invDef_t* fromPtr = INVDEF(fromContainer);
1011 const Item* item = le->inv.getItemAtPos(fromPtr, fromX, fromY);
1012
1013 if (item != nullptr) {
1014 const character_t* chr = CL_ActorGetChr(le);
1015 if (!le->inv.canHoldItemWeight(fromContainer, toContainer, *item, GAME_GetChrMaxLoad(chr))) {
1016 UI_Popup(_("Warning"), _("This soldier can not carry anything else."));
1017 return;
1018 }
1019 MSG_Write_PA(PA_INVMOVE, le->entnum, fromContainer, fromX, fromY, toContainer, toX, toY);
1020 }
1021}
1022
1027static void CL_ActorUse (const le_t* le)
1028{
1029 if (!CL_ActorCheckAction(le))
1030 return;
1031
1032 assert(le->clientAction);
1033
1034 MSG_Write_PA(PA_USE, le->entnum, le->clientAction->entnum);
1035 Com_DPrintf(DEBUG_CLIENT, "CL_ActorUse: Use door number: %i (actor %i).\n", le->clientAction->entnum, le->entnum);
1036}
1037
1041static void CL_ActorUse_f (void)
1042{
1043 le_t* actor = selActor;
1044
1045 if (!CL_ActorCheckAction(actor))
1046 return;
1047
1048 /* no client action */
1049 if (actor->clientAction == nullptr) {
1050 Com_DPrintf(DEBUG_CLIENT, "CL_ActorUse_f: No client_action set for actor with entnum %i.\n", actor->entnum);
1051 return;
1052 }
1053
1054 if (LE_IsDoor(actor->clientAction)) {
1055 /* Check if we should even try to send this command (no TUs left or). */
1056 if (CL_ActorUsableTUs(actor) >= TU_DOOR_ACTION)
1057 CL_ActorUse(actor);
1058 }
1059}
1060
1070
1075{
1076 if (IN_GetMouseSpace() != MS_WORLD)
1077 return;
1078
1080 return;
1081
1083 /* Cannot turn because of not enough usable TUs. */
1084 return;
1085 }
1086
1087 /* check for fire-modes, and cancel them */
1088 if (CL_ActorFireModeActivated(selActor->actorMode)) {
1090 return; /* and return without turning */
1091 }
1092
1093 /* calculate dvec */
1094 vec3_t directionVector;
1095 VectorSubtract(mousePos, selActor->pos, directionVector);
1096 const dvec_t dvec = AngleToDV((int) (atan2(directionVector[1], directionVector[0]) * todeg));
1097
1098 /* send message to server */
1099 MSG_Write_PA(PA_TURN, selActor->entnum, dvec);
1100}
1101
1105static void CL_ActorStandCrouch_f (void)
1106{
1108 return;
1109
1110 /* In case of standing up also check the headroom */
1111 if (LE_IsCrouched(selActor) && !RT_CanActorStandHere(cl.mapData->routing, selActor->fieldSize, selActor->pos))
1112 return;
1113
1114 /* Check if we should even try to send this command (no TUs left or). */
1116 /* send a request to toggle crouch to the server */
1118 }
1119}
1120
1124static void CL_ActorUseHeadgear_f (void)
1125{
1126 const mouseSpace_t tmpMouseSpace = IN_GetMouseSpace();
1127
1128 /* this can be executed by a click on a hud button
1129 * but we need MS_WORLD mouse space to let the shooting
1130 * function work */
1132
1134 return;
1135
1136 Item* headgear = selActor->inv.getHeadgear();
1137 if (!headgear)
1138 return;
1139
1142 selActor->currentSelectedFiremode = 0;
1145
1146 /* restore old mouse space */
1147 IN_SetMouseSpace(tmpMouseSpace);
1148}
1149
1150/*
1151==============================================================
1152MOUSE INPUT
1153==============================================================
1154*/
1155
1161static void CL_ActorMoveMouse (void)
1162{
1163 /* Don't display the cursor if it's above the currently selected level.
1164 * The 2nd part of the if is an attempt to display it anyway when we eg. climb a hill.
1165 * But there are too many situations inside buildings that match the criteria (eg. actorclip around chair).
1166 * So disabled for now.*/
1167 if (mousePos[2] > cl_worldlevel->integer/* && !RT_AllCellsBelowAreFilled(cl.mapData->map, fieldSize, pos)*/)
1168 return;
1169
1170 if (selActor->actorMode == M_PEND_MOVE) {
1171 if (VectorCompare(mousePos, selActor->mousePendPos)) {
1172 /* Pending move and clicked the same spot (i.e. 2 clicks on the same place) */
1174 } else {
1175 /* Clicked different spot. */
1176 VectorCopy(mousePos, selActor->mousePendPos);
1177 }
1178 } else {
1179 /* either we want to confirm every move, or it's not our round and we prepare the
1180 * movement for the next round */
1181 if (confirm_actions->integer || !cls.isOurRound()) {
1182 /* Set our mode to pending move. */
1183 VectorCopy(mousePos, selActor->mousePendPos);
1184
1186 } else {
1187 /* Just move there */
1189 }
1190 }
1191}
1192
1198{
1199 if (IN_GetMouseSpace() != MS_WORLD || !selActor)
1200 return;
1201
1202 switch (selActor->actorMode) {
1203 case M_MOVE:
1204 case M_PEND_MOVE:
1205 /* Try and select another team member */
1207 /* Succeeded so go back into move mode. */
1209 } else if (interactEntity) {
1211 } else {
1213 }
1214 break;
1215 case M_PEND_FIRE_R:
1216 case M_PEND_FIRE_L:
1217 if (VectorCompare(mousePos, selActor->mousePendPos)) {
1218 /* Pending shot and clicked the same spot (i.e. 2 clicks on the same place) */
1220
1221 /* We switch back to aiming mode. */
1222 if (selActor->actorMode == M_PEND_FIRE_R)
1224 else
1226 } else {
1227 /* Clicked different spot. */
1228 VectorCopy(mousePos, selActor->mousePendPos);
1229 }
1230 break;
1231 case M_FIRE_R:
1233 break;
1234
1235 /* We either switch to "pending" fire-mode or fire the gun. */
1236 if (confirm_actions->integer == 1) {
1238 VectorCopy(mousePos, selActor->mousePendPos);
1239 } else {
1241 }
1242 break;
1243 case M_FIRE_L:
1245 break;
1246
1247 /* We either switch to "pending" fire-mode or fire the gun. */
1248 if (confirm_actions->integer == 1) {
1250 VectorCopy(mousePos, selActor->mousePendPos);
1251 } else {
1253 }
1254 break;
1255 default:
1256 break;
1257 }
1258}
1259
1260
1267{
1268 if (!selActor || IN_GetMouseSpace() != MS_WORLD)
1269 return;
1270
1271 if (CL_ActorFireModeActivated(selActor->actorMode)) {
1273 }
1274}
1275
1276/*
1277==============================================================
1278MOUSE SCANNING
1279==============================================================
1280*/
1281
1290void CL_GetWorldCoordsUnderMouse (vec3_t groundIntersection, vec3_t upperTracePoint, vec3_t lowerTracePoint)
1291{
1292 /* TODO: Move this to cl_battlescape.cpp? This function is not directly related to actors. */
1293
1294 /* get cursor position as a -1 to +1 range for projection */
1295 float cur[2];
1296 cur[0] = (mousePosX * viddef.rx - viddef.viewWidth * 0.5 - viddef.x) / (viddef.viewWidth * 0.5);
1297 cur[1] = (mousePosY * viddef.ry - viddef.viewHeight * 0.5 - viddef.y) / (viddef.viewHeight * 0.5);
1298
1299 /* get trace vectors */
1300 vec3_t from, forward, right, up;
1301 VectorCopy(cl.cam.camorg, from);
1302 VectorCopy(cl.cam.axis[0], forward);
1303 VectorCopy(cl.cam.axis[1], right);
1304 VectorCopy(cl.cam.axis[2], up);
1305
1306 float frustumSlope[2];
1307 const float projectionDistance = 2048.0f;
1308 if (cl_isometric->integer)
1309 frustumSlope[0] = 10.0 * refdef.fieldOfViewX;
1310 else
1311 frustumSlope[0] = tan(refdef.fieldOfViewX * (M_PI / 360.0)) * projectionDistance;
1312 frustumSlope[1] = frustumSlope[0] * ((float)viddef.viewHeight / (float)viddef.viewWidth);
1313
1314 /* transform cursor position into perspective space */
1315 vec3_t stop;
1316 VectorMA(from, projectionDistance, forward, stop);
1317 VectorMA(stop, cur[0] * frustumSlope[0], right, stop);
1318 VectorMA(stop, cur[1] * -frustumSlope[1], up, stop);
1319
1320 /* in isometric mode the camera position has to be calculated from the cursor position so that the trace goes in the right direction */
1321 if (cl_isometric->integer)
1322 VectorMA(stop, -projectionDistance * 2, forward, from);
1323
1324 /* set stop point to the intersection of the trace line with the desired plane */
1325 /* description of maths used:
1326 * The equation for the plane can be written:
1327 * mapNormal dot (end - P3) = 0
1328 * where mapNormal is the vector normal to the plane,
1329 * P3 is any point on the plane and
1330 * end is the point where the line intersects the plane
1331 * All points on the line can be calculated using:
1332 * P1 + u*(P2 - P1)
1333 * where P1 and P2 are points that define the line and
1334 * u is some scalar
1335 * The intersection of the line and plane occurs when:
1336 * mapNormal dot (P1 + u*(P2 - P1)) == mapNormal dot P3
1337 * The intersection therefore occurs when:
1338 * u = (mapNormal dot (P3 - P1))/(mapNormal dot (P2 - P1))
1339 * Note: in the code below from & stop represent P1 and P2 respectively
1340 */
1341 vec3_t mapNormal, P3, P2minusP1;
1342 VectorSet(P3, 0., 0., cl_worldlevel->integer * UNIT_HEIGHT + CURSOR_OFFSET);
1343 VectorSet(mapNormal, 0., 0., 1.);
1344 VectorSubtract(stop, from, P2minusP1);
1345 const float nDotP2minusP1 = DotProduct(mapNormal, P2minusP1);
1346
1347 /* calculate intersection directly if angle is not parallel to the map plane */
1348 vec3_t end;
1349 if (nDotP2minusP1 > 0.01 || nDotP2minusP1 < -0.01) {
1350 vec3_t dir, P3minusP1;
1351
1352 VectorSubtract(P3, from, P3minusP1);
1353 const float u = DotProduct(mapNormal, P3minusP1) / nDotP2minusP1;
1354 VectorScale(P2minusP1, (vec_t)u, dir);
1355 VectorAdd(from, dir, end);
1356 } else { /* otherwise do a full trace */
1357 CM_EntTestLineDM(cl.mapTiles, Line(from, stop), end, TL_FLAG_ACTORCLIP, cl.leInlineModelList);
1358 }
1359
1360 if (groundIntersection)
1361 VectorCopy(end, groundIntersection);
1362 if (upperTracePoint)
1363 VectorCopy(from, upperTracePoint);
1364 if (lowerTracePoint)
1365 VectorCopy(stop, lowerTracePoint);
1366}
1367
1374{
1375 vec3_t from, stop, end;
1376 CL_GetWorldCoordsUnderMouse(end, from, stop);
1377 pos3_t testPos;
1378 VecToPos(end, testPos);
1379 /* hack to prevent cursor from getting stuck on the top of an invisible
1380 * playerclip surface (in most cases anyway) */
1381 vec3_t pA;
1382 PosToVec(testPos, pA);
1383 /* ensure that the cursor is in the world, if this is not done, the tracer box is
1384 * drawn in the void on the first level and the menu key bindings might get executed
1385 * this could result in different problems like the zooming issue (where you can't zoom
1386 * in again, because in_zoomout->state is not reseted). */
1388 return false;
1389
1390 vec3_t pB;
1391 VectorCopy(pA, pB);
1392 pA[2] += UNIT_HEIGHT;
1393 pB[2] -= UNIT_HEIGHT;
1397 pos_t restingLevel = Grid_Fall(cl.mapData->routing, ACTOR_GET_FIELDSIZE(selActor), testPos);
1398 vec3_t pC;
1399 CM_EntTestLineDM(cl.mapTiles, Line(pA, pB), pC, TL_FLAG_ACTORCLIP, cl.leInlineModelList);
1400 VecToPos(pC, testPos);
1401 /* VecToPos strictly rounds the values down, while routing will round floors up to the next QUANT.
1402 * This makes a huge diffence when calculating the z-level:
1403 * without compensation, z of 61-63 will belong to the level below. */
1404 testPos[2] = ModelFloorToQuant(pC[2] / CELL_HEIGHT);
1405
1406 restingLevel = std::min(restingLevel, Grid_Fall(cl.mapData->routing, ACTOR_GET_FIELDSIZE(selActor), testPos));
1407
1408 /* if grid below intersection level, start a trace from the intersection */
1409 if (restingLevel < cl_worldlevel->integer) {
1410 VectorCopy(end, from);
1411 from[2] -= CURSOR_OFFSET;
1412 CM_EntTestLineDM(cl.mapTiles, Line(from, stop), end, TL_FLAG_ACTORCLIP, cl.leInlineModelList);
1413 VecToPos(end, testPos);
1414 restingLevel = Grid_Fall(cl.mapData->routing, ACTOR_GET_FIELDSIZE(selActor), testPos);
1415 }
1416
1417 /* test if the selected grid is out of the world */
1418 if (restingLevel >= PATHFINDING_HEIGHT)
1419 return false;
1420
1421 /* Set truePos- test pos is under the cursor. */
1422 VectorCopy(testPos, truePos);
1423 truePos[2] = cl_worldlevel->integer;
1424
1425 /* Set mousePos to the position that the actor will move to. */
1426 testPos[2] = restingLevel;
1427 VectorCopy(testPos, mousePos);
1428
1429 le_t* interactLe = CL_BattlescapeSearchAtGridPos(mousePos, false, selActor);
1430 if (interactLe != nullptr && LE_IsActor(interactLe)) {
1431 mouseActor = interactLe;
1432 interactEntity = nullptr;
1433 } else if (selActor != nullptr && selActor->clientAction == interactLe) {
1434 interactEntity = interactLe;
1435 mouseActor = nullptr;
1436 } else {
1437 interactEntity = nullptr;
1438 mouseActor = nullptr;
1439 }
1440
1441 if (interactEntity != nullptr) {
1443 } else {
1445 }
1446
1447 /* calculate move length */
1451 }
1452
1453 return true;
1454}
1455
1463
1468{
1469 /* TODO: the movement is snapping to the cell center, and is clunky - make it smooth */
1470 /* Difference between last and currently selected cell, we'll move camera by that difference */
1471 vec3_t currentMousePos;
1472
1473 CL_GetWorldCoordsUnderMouse(currentMousePos, nullptr, nullptr);
1474 if (fabs(currentMousePos[0] - mouseDraggingPos[0]) + fabs(currentMousePos[1] - mouseDraggingPos[1]) < 0.5f)
1475 return;
1476
1477 vec3_t mousePosDiff;
1478 VectorSubtract(mouseDraggingPos, currentMousePos, mousePosDiff);
1479 VectorMA(cl.cam.origin, 0.2f, mousePosDiff, cl.cam.origin); /* Move camera slowly to the dest point, to prevent shaking */
1480 Cvar_SetValue("cl_worldlevel", truePos[2]); /* Do not change world level */
1481}
1482
1483/*
1484==============================================================
1485ACTOR GRAPHICS
1486==============================================================
1487*/
1488
1495static inline bool CL_AddActorWeapon (int objID)
1496{
1497 if (objID != NONE) {
1498 const objDef_t* od = INVSH_GetItemByIDX(objID);
1499 if (od->isVirtual)
1500 return false;
1501 return true;
1502 }
1503 return false;
1504}
1505
1515bool CL_AddActor (le_t* le, entity_t* ent)
1516{
1517 if (!cl_showactors->integer)
1518 return false;
1519
1520 const bool hasTagHead = R_GetTagIndexByName(le->model1, "tag_head") != -1;
1521
1522 if (LE_IsStunned(le)) {
1523 if (!le->ptl) {
1524 int levelflags = 0;
1525 for (int i = le->pos[2]; i < PATHFINDING_HEIGHT; ++i)
1526 levelflags |= (1 << i);
1527 le->ptl = CL_ParticleSpawn("stunnedactor", levelflags, le->origin);
1528 }
1529 } else if (!LE_IsDead(le)) {
1530 /* add the weapons to the actor's hands */
1531 const bool addLeftHandWeapon = CL_AddActorWeapon(le->left);
1532 const bool addRightHandWeapon = CL_AddActorWeapon(le->right);
1533 const int delta = hasTagHead ? 2 : 1;
1534 /* add left hand weapon */
1535 if (addLeftHandWeapon) {
1536 entity_t leftHand(RF_NONE);
1537
1538 leftHand.model = cls.modelPool[le->left];
1539 if (!leftHand.model)
1540 Com_Error(ERR_DROP, "Actor model for left hand weapon wasn't found!");
1541
1542 /* point to the body ent which will be added last */
1543 leftHand.tagent = R_GetFreeEntity() + delta + addRightHandWeapon;
1544 leftHand.tagname = "tag_lweapon";
1545
1546 R_AddEntity(&leftHand);
1547 }
1548
1549 /* add right hand weapon */
1550 if (addRightHandWeapon) {
1551 entity_t rightHand(RF_NONE);
1552
1553 rightHand.alpha = le->alpha;
1554 rightHand.model = cls.modelPool[le->right];
1555 if (!rightHand.model)
1556 Com_Error(ERR_DROP, "Actor model for right hand weapon wasn't found!");
1557
1558 /* point to the body ent which will be added last */
1559 rightHand.tagent = R_GetFreeEntity() + delta;
1560 rightHand.tagname = "tag_rweapon";
1561
1562 R_AddEntity(&rightHand);
1563 }
1564 }
1565
1566 if (hasTagHead) {
1567 /* add head */
1568 entity_t head(RF_NONE);
1569
1570 head.alpha = le->alpha;
1571 head.model = le->model2;
1572 if (!head.model)
1573 Com_Error(ERR_DROP, "Actor model wasn't found!");
1574 head.skinnum = le->headSkin;
1575
1576 /* point to the body ent which will be added last */
1577 head.tagent = R_GetFreeEntity() + 1;
1578 head.tagname = "tag_head";
1579
1580 if (le->team != cls.team)
1581 head.flags |= RF_IRGOGGLES;
1582
1583 R_AddEntity(&head);
1584 }
1585
1589 if (LE_IsStunned(le) && le->HP <= le->maxHP / 2)
1590 ent->flags |= RF_BLOOD;
1591 else if (LE_IsDead(le))
1592 ent->flags |= RF_BLOOD;
1593 else
1594 ent->flags |= RF_SHADOW;
1595
1596 ent->flags |= RF_ACTOR;
1597 /* actors are highlighted if some other actor uses ir goggles */
1598 if (le->team != cls.team)
1599 ent->flags |= RF_IRGOGGLES;
1600
1601 if (!LE_IsDead(le) && !LE_IsStunned(le)) {
1602 if (LE_IsSelected(le))
1603 ent->flags |= RF_SELECTED;
1604 if (le->team == cls.team) {
1605 if (le->pnum == cl.pnum)
1606 ent->flags |= RF_MEMBER;
1607 if (le->pnum != cl.pnum)
1608 ent->flags |= RF_ALLIED;
1609 } else {
1610 ent->flags |= RF_OPPONENT;
1611 }
1612 if (le->team == TEAM_CIVILIAN)
1613 ent->flags |= RF_NEUTRAL;
1614 }
1615
1616 if (ent->flags & RF_BLOOD) {
1617 const char* deathTextureName;
1618 assert(le->teamDef != nullptr);
1619 deathTextureName = le->teamDef->deathTextureName;
1620 ent->texture = R_FindImage(deathTextureName, it_effect);
1621 }
1622
1623 return true;
1624}
1625
1626/*
1627==============================================================
1628TARGETING GRAPHICS
1629==============================================================
1630*/
1631
1637static void CL_TargetingRadius (const vec3_t center, const float radius)
1638{
1639 ptl_t* particle = CL_ParticleSpawn("circle", 0, center);
1640 if (particle != nullptr)
1641 particle->size[0] = radius;
1642}
1643
1654static void CL_TargetingStraight (const pos3_t fromPos, actorSizeEnum_t fromActorSize, const pos3_t toPos)
1655{
1656 if (!selActor || !selActor->fd)
1657 return;
1658
1659 /* search for an actor at target */
1660 le_t* target = CL_BattlescapeSearchAtGridPos(toPos, true, nullptr);
1661
1662 /* Determine the target's size. */
1663 const actorSizeEnum_t toActorSize = target
1664 ? target->fieldSize
1666
1667 vec3_t start, end;
1668 Grid_PosToVec(cl.mapData->routing, fromActorSize, fromPos, start);
1669 Grid_PosToVec(cl.mapData->routing, toActorSize, toPos, end);
1671 end[2] -= mousePosTargettingAlign;
1672
1673 /* calculate direction */
1674 vec3_t dir;
1675 VectorSubtract(end, start, dir);
1676
1677 /* Calculate shot origin */
1678 selActor->fd->getShotOrigin(start, dir, LE_IsCrouched(selActor), start);
1679 VectorSubtract(end, start, dir);
1680 VectorNormalize(dir);
1681
1682 /* calculate 'out of range point' if there is one */
1683 bool crossNo;
1684 vec3_t mid;
1685 if (VectorDistSqr(start, end) > selActor->fd->range * selActor->fd->range) {
1686 VectorMA(start, selActor->fd->range, dir, mid);
1687 crossNo = true;
1688 } else {
1689 VectorCopy(end, mid);
1690 crossNo = false;
1691 }
1692
1693 vec3_t temp;
1694 VectorMA(start, UNIT_SIZE * 1.4, dir, temp);
1695 /* switch up to top level, this is needed to make sure our trace doesn't go through ceilings ... */
1698 trace_t tr = CL_Trace(Line(start, temp), AABB::EMPTY, selActor, nullptr, MASK_SHOT, cl.mapMaxLevel - 1);
1699 if (tr.le && (tr.le->team == cls.team || LE_IsCivilian(tr.le)) && LE_IsCrouched(tr.le))
1700 VectorMA(start, UNIT_SIZE * 1.4, dir, temp);
1701 else
1702 VectorCopy(start, temp);
1703
1706 tr = CL_Trace(Line(temp, mid), AABB::EMPTY, selActor, target, MASK_SHOT, cl.mapMaxLevel - 1);
1707
1708 if (tr.fraction < 1.0 && (!tr.le || (!LE_IsInvisible(tr.le) && !VectorCompare(tr.le->pos, toPos)))) {
1709 const float d = VectorDist(temp, mid);
1710 VectorMA(start, tr.fraction * d, dir, mid);
1711 crossNo = true;
1712 }
1713
1714 /* spawn particles */
1715 CL_ParticleSpawn("inRangeTracer", 0, start, mid);
1716 if (crossNo) {
1717 CL_ParticleSpawn("longRangeTracer", 0, mid, end);
1718 CL_ParticleSpawn("cross_no", 0, end);
1719 } else {
1720 CL_ParticleSpawn("cross", 0, end);
1721 }
1722
1723 if (selActor->fd->splrad > 0.0) {
1724 Grid_PosToVec(cl.mapData->routing, toActorSize, toPos, end);
1725 CL_TargetingRadius(end, selActor->fd->splrad);
1726 }
1727}
1728
1729#define GRENADE_PARTITIONS 20
1730
1738static void CL_TargetingGrenade (const pos3_t fromPos, actorSizeEnum_t fromActorSize, const pos3_t toPos)
1739{
1740 if (!selActor || !selActor->fd || Vector2Compare(fromPos, toPos))
1741 return;
1742
1743 /* search for an actor at target */
1744 le_t* target = CL_BattlescapeSearchAtGridPos(toPos, true, nullptr);
1745
1746 /* Determine the target's size. */
1747 actorSizeEnum_t toActorSize = target
1748 ? target->fieldSize
1750
1751 /* get vectors, paint cross */
1752 vec3_t from, at, cross;
1753 Grid_PosToVec(cl.mapData->routing, fromActorSize, fromPos, from);
1754 Grid_PosToVec(cl.mapData->routing, toActorSize, toPos, at);
1755
1756 /* prefer to aim grenades at the ground */
1757 at[2] -= GROUND_DELTA;
1759 at[2] -= mousePosTargettingAlign;
1760 VectorCopy(at, cross);
1761
1762 /* Calculate shot origin */
1763 vec3_t ds;
1764 VectorSubtract(at, from, ds);
1765 selActor->fd->getShotOrigin(from, ds, LE_IsCrouched(selActor), from);
1766
1767 /* calculate parabola */
1768 vec3_t v0;
1769 float dt = Com_GrenadeTarget(from, at, selActor->fd->range, selActor->fd->launched, selActor->fd->rolled, v0);
1770 if (!dt) {
1771 CL_ParticleSpawn("cross_no", 0, cross);
1772 return;
1773 }
1774
1775 dt /= GRENADE_PARTITIONS;
1776 VectorSubtract(at, from, ds);
1777 VectorScale(ds, 1.0 / GRENADE_PARTITIONS, ds);
1778 ds[2] = 0;
1779
1780 /* paint */
1781 float vz = v0[2];
1782
1783 bool obstructed = false;
1784 for (int i = 0; i < GRENADE_PARTITIONS; i++) {
1785 vec3_t next;
1786 VectorAdd(from, ds, next);
1787 next[2] += dt * (vz - 0.5 * GRAVITY * dt);
1788 vz -= GRAVITY * dt;
1789 VectorScale(ds, i + 1.0, at);
1790
1791 /* trace for obstacles. Switch up to top level, to make sure our trace
1792 * doesn't go through ceilings ... */
1793 const trace_t tr = CL_Trace(Line(from, next), AABB::EMPTY, selActor, target, MASK_SHOT, cl.mapMaxLevel - 1);
1794
1795 /* something was hit */
1796 if (tr.fraction < 1.0 && (!tr.le || (!LE_IsInvisible(tr.le) && !VectorCompare(tr.le->pos, toPos)))) {
1797 obstructed = true;
1798 }
1799
1800 /* draw particles */
1803 if (obstructed || VectorLength(at) > selActor->fd->range)
1804 CL_ParticleSpawn("longRangeTracer", 0, from, next);
1805 else
1806 CL_ParticleSpawn("inRangeTracer", 0, from, next);
1807 VectorCopy(next, from);
1808 }
1809 /* draw targeting cross */
1810 if (obstructed || VectorLength(at) > selActor->fd->range)
1811 CL_ParticleSpawn("cross_no", 0, cross);
1812 else
1813 CL_ParticleSpawn("cross", 0, cross);
1814
1815 if (selActor->fd->splrad > 0.0) {
1816 Grid_PosToVec(cl.mapData->routing, toActorSize, toPos, at);
1817 CL_TargetingRadius(at, selActor->fd->splrad);
1818 }
1819}
1820
1826#define BoxOffset(aSize, target) (target[0]=(aSize-1)*(UNIT_SIZE+BOX_DELTA_WIDTH), target[1]=(aSize-1)*(UNIT_SIZE+BOX_DELTA_LENGTH), target[2]=0)
1827
1833static void CL_AddTargetingBox (pos3_t pos, bool pendBox)
1834{
1835 if (!cl_showactors->integer)
1836 return;
1837
1838 entity_t cursor(RF_BOX);
1839
1840 /* Paint the green box if move is possible ...
1841 * OR paint a dark blue one if move is impossible or the
1842 * soldier does not have enough TimeUnits left. */
1843 if (selActor && selActor->actorMoveLength < ROUTING_NOT_REACHABLE
1844 && selActor->actorMoveLength <= CL_ActorUsableTUs(selActor))
1845 VectorSet(cursor.color, 0, 1, 0); /* Green */
1846 else
1847 VectorSet(cursor.color, 0.6, 0.68, 1); /* Light Blue */
1848
1849 /* color */
1850 /* if the mouse is over an actor, but not the selected one */
1853 actorSize = mouseActor->fieldSize;
1854 cursor.alpha = 0.6 + 0.2 * sin((float) cl.time / 80);
1855 /* Paint the box red if the soldiers under the cursor is
1856 * not in our team and no civilian either. */
1857 if (mouseActor->team != cls.team) {
1858 switch (mouseActor->team) {
1859 case TEAM_CIVILIAN:
1860 /* Civilians are yellow */
1861 VectorSet(cursor.color, 1, 1, 0); /* Yellow */
1862 break;
1863 default:
1864 if (LE_IsAlien(mouseActor)) {
1865 if (GAME_TeamIsKnown(mouseActor->teamDef))
1867 else
1868 UI_RegisterText(TEXT_MOUSECURSOR_PLAYERNAMES, _("Unknown alien race"));
1869 } else {
1870 /* multiplayer names */
1871 /* see CL_ParseClientinfo */
1873 }
1874 /* Aliens (and players not in our team [multiplayer]) are red */
1875 VectorSet(cursor.color, 1, 0, 0); /* Red */
1876 break;
1877 }
1878 } else {
1879 /* coop multiplayer games */
1880 if (mouseActor->pnum != cl.pnum) {
1882 } else {
1883 /* we know the names of our own actors */
1885 assert(chr);
1887 }
1888 /* Paint a light blue box if on our team */
1889 VectorSet(cursor.color, 0.2, 0.3, 1); /* Light Blue */
1890 }
1891 } else {
1892 /* either no actor under the cursor or the selected one */
1893 cursor.alpha = 0.3;
1894 if (selActor) { /* there should always be an actor selected, but who knows */
1895 actorSize = selActor->fieldSize;
1896 }
1897 }
1898
1899 /* Now calculate the size of the cursor box, depending on the actor. */
1900 /* For some strange reason we use origin and oldorigin instead of the ent's min/max, respectively */
1901 Grid_PosToVec(cl.mapData->routing, ACTOR_SIZE_NORMAL, pos, cursor.origin); /* center of the (lower left) cell */
1902 VectorAdd(cursor.origin, halfBoxSize, cursor.oldorigin);
1903 VectorSubtract(cursor.origin, halfBoxSize, cursor.origin);
1904 if (actorSize > ACTOR_SIZE_NORMAL) {
1905 vec_t inc = UNIT_SIZE * (actorSize - 1);
1906 vec3_t increase = { inc, inc, 0};
1907 VectorAdd(cursor.oldorigin, increase, cursor.oldorigin);
1908 }
1909
1910 /* if pendBox is true then ignore all the previous color considerations and use cyan */
1911 if (pendBox) {
1912 VectorSet(cursor.color, 0, 1, 1); /* Cyan */
1913 cursor.alpha = 0.15;
1914 }
1915
1916 /* add it */
1917 R_AddEntity(&cursor);
1918}
1919
1925{
1926 /* no firedef selected */
1927 if (!selActor || !selActor->fd)
1928 return;
1929 if (!CL_ActorFireModeActivated(selActor->actorMode))
1930 return;
1931
1932 /* user defined height align */
1933 int align = GROUND_DELTA;
1934 if (Cmd_Argc() == 2) {
1935 align = atoi(Cmd_Argv(1));
1936 } else {
1937 static int currentPos = 0;
1938 switch (currentPos) {
1939 case 0:
1940 if (selActor->fd->gravity)
1941 align = -align;
1942 currentPos = 1; /* next level */
1943 break;
1944 case 1:
1945 /* only allow to align to lower z level if the actor is
1946 * standing at a higher z-level */
1947 if (selActor->fd->gravity)
1948 align = -(2 * align);
1949 else
1950 align = -align;
1951 currentPos = 2;
1952 break;
1953 case 2:
1954 /* the static var is not reseted on weaponswitch or actorswitch */
1955 if (selActor->fd->gravity) {
1956 align = 0;
1957 currentPos = 0; /* next level */
1958 } else {
1959 align = -(2 * align);
1960 currentPos = 3; /* next level */
1961 }
1962 break;
1963 case 3:
1964 align = 0;
1965 currentPos = 0; /* back to start */
1966 break;
1967 }
1968 }
1970}
1971
1982{
1983 if (IN_GetMouseSpace() != MS_WORLD || !selActor)
1984 return;
1985
1986 switch (selActor->actorMode) {
1987 case M_MOVE:
1988 case M_PEND_MOVE:
1989 /* Don't display the cursor if it's above the currently selected level.
1990 * The 2nd part of the if is an attempt to display it anyway when we eg. climb a hill.
1991 * But there are too many situations inside buildings that match the criteria (eg. actorclip around chair).
1992 * So disabled for now.*/
1993 if (mousePos[2] > cl_worldlevel->integer/* && !RT_AllCellsBelowAreFilled(cl.mapData->map, fieldSize, pos)*/)
1994 return;
1995
1996 /* Display Move-cursor. */
1998
1999 if (selActor->actorMode == M_PEND_MOVE) {
2000 /* Also display a box for the pending move if we have one. */
2001 CL_AddTargetingBox(selActor->mousePendPos, true);
2002 if (!CL_ActorTraceMove(selActor->mousePendPos))
2004 }
2005 break;
2006 case M_FIRE_R:
2007 case M_FIRE_L:
2008 if (!selActor->fd)
2009 return;
2010
2011 if (!selActor->fd->gravity)
2013 else
2014 CL_TargetingGrenade(selActor->pos, selActor->fieldSize, mousePos);
2015 break;
2016 case M_PEND_FIRE_R:
2017 case M_PEND_FIRE_L:
2018 if (!selActor->fd)
2019 return;
2020
2021 /* Draw cursor at mousepointer */
2023
2024 /* Draw (pending) Cursor at target */
2025 CL_AddTargetingBox(selActor->mousePendPos, true);
2026
2027 if (!selActor->fd->gravity)
2028 CL_TargetingStraight(selActor->pos, selActor->fieldSize, selActor->mousePendPos);
2029 else
2030 CL_TargetingGrenade(selActor->pos, selActor->fieldSize, selActor->mousePendPos);
2031 break;
2032 default:
2033 break;
2034 }
2035}
2036
2038
2043static bool CL_AddPathingBox (pos3_t pos, bool addUnreachableCells)
2044{
2045 const int TUneed = CL_ActorMoveLength(selActor, pos);
2046 const int TUhave = CL_ActorUsableTUs(selActor);
2047 if (!addUnreachableCells && TUhave < TUneed)
2048 return false;
2049
2050 entity_t ent(RF_PATH);
2051
2052 Grid_PosToVec(cl.mapData->routing, ACTOR_GET_FIELDSIZE(selActor), pos, ent.origin);
2054
2055 /* The floor relative to this cell */
2056 const int base = Grid_Floor(cl.mapData->routing, ACTOR_GET_FIELDSIZE(selActor), pos);
2057
2058 /* Paint the box green if it is reachable,
2059 * yellow if it can be entered but is too far,
2060 * or red if it cannot be entered ever. */
2061 if (base < -QuantToModel(PATHFINDING_MAX_FALL)) {
2062 VectorSet(ent.color, 0.0, 0.0, 0.0); /* Can't enter - black */
2063 } else {
2064 /* Can reach - green
2065 * Passable but unreachable - yellow
2066 * Not passable - red */
2067 VectorSet(ent.color, (TUneed > TUhave), (TUneed != ROUTING_NOT_REACHABLE), 0);
2068 }
2069
2070 /* Set the box height to the ceiling value of the cell. */
2071 /* The total opening size */
2072 const int height = 2 + std::min(TUneed * (UNIT_HEIGHT - 2) / ROUTING_NOT_REACHABLE, 16);
2073 ent.oldorigin[2] = height;
2074 ent.oldorigin[0] = TUneed;
2075 ent.oldorigin[1] = TUhave;
2076
2077 ent.alpha = 0.25;
2078
2079 /* add it */
2080 R_AddEntity(&ent);
2081 return true;
2082}
2083
2089void CL_AddPathing (void)
2090{
2091 if (selActor == nullptr) {
2092 return;
2093 }
2094
2095 pos3_t pos;
2096 pos[2] = cl_worldlevel->integer;
2097 for (pos[1] = std::max(mousePos[1] - 8, 0); pos[1] <= std::min(mousePos[1] + 8, PATHFINDING_WIDTH - 1); pos[1]++) {
2098 for (pos[0] = std::max(mousePos[0] - 8, 0); pos[0] <= std::min(mousePos[0] + 8, PATHFINDING_WIDTH - 1); pos[0]++) {
2099 CL_AddPathingBox(pos, true);
2100 }
2101 }
2102}
2103
2110{
2111 if (selActor == nullptr) {
2112 return;
2113 }
2114
2115 pos3_t pos;
2116 pos[2] = cl_worldlevel->integer;
2117 int i = 0;
2118 for (int y = 0; y <= PATHFINDING_WIDTH; y++) {
2119 for (int x = 0; x <= PATHFINDING_WIDTH; x++) {
2120 pos[0] = (pos_t)x;
2121 pos[1] = (pos_t)y;
2122 i += CL_AddPathingBox(pos, false);
2123 if (i > 1024)
2124 return;
2125 }
2126 }
2127}
2128
2134void CL_ActorPlaySound (const le_t* le, actorSound_t soundType)
2135{
2136 const char* actorSound = le->teamDef->getActorSound(le->gender, soundType);
2137 if (actorSound) {
2139 Com_DPrintf(DEBUG_SOUND|DEBUG_CLIENT, "CL_PlayActorSound: ActorSound: '%s'\n", actorSound);
2140 }
2141 }
2142}
2143
2147static void CL_AddArrow (vec3_t from, vec3_t to, float red, float green, float blue)
2148{
2149 /* Com_Printf("Adding arrow (%f, %f, %f) to (%f, %f, %f).\n", from[0], from[1], from[2], to[0], to[1], to[2]); */
2150
2151 entity_t ent(RF_ARROW);
2152
2153 VectorCopy(from, ent.origin);
2154 VectorCopy(to, ent.oldorigin);
2155 VectorSet(ent.color, red, green, blue);
2156
2157 ent.alpha = 0.25;
2158
2159 /* add it */
2160 R_AddEntity(&ent);
2161}
2162
2167{
2168 vec3_t base, start;
2169
2170 Grid_PosToVec(cl.mapData->routing, ACTOR_GET_FIELDSIZE(selActor), truePos, base);
2171 VectorCopy(base, start);
2172 base[2] -= QUANT;
2173 start[2] += QUANT;
2174 CL_AddArrow(base, start, 0.0, 0.0, 0.0);
2175}
2176
2181{
2182 vec3_t base, start;
2183
2184 Grid_PosToVec(cl.mapData->routing, ACTOR_GET_FIELDSIZE(selActor), truePos, base);
2185 VectorCopy(base, start);
2186 CL_AddArrow(base, start, 0.0, 0.0, 0.0);
2187}
2188
2189#ifdef DEBUG
2193static void CL_DumpMoveMark_f (void)
2194{
2195 const int temp = developer->integer;
2196
2197 if (!selActor)
2198 return;
2199
2202
2204 developer->integer = temp;
2205}
2206
2211static void CL_DumpTUs_f (void)
2212{
2213 if (!selActor)
2214 return;
2215
2216 const int crouchingState = LE_IsCrouched(selActor) ? 1 : 0;
2217 pos3_t pos;
2218 VectorCopy(selActor->pos, pos);
2219
2220 Com_Printf("TUs around (%i, %i, %i).\n", pos[0], pos[1], pos[2]);
2221
2222 for (int y = std::max(0, pos[1] - 8); y <= std::min(PATHFINDING_WIDTH, pos[1] + 8); y++) {
2223 for (int x = std::max(0, pos[0] - 8); x <= std::min(PATHFINDING_WIDTH, pos[0] + 8); x++) {
2224 pos3_t loc;
2225 VectorSet(loc, x, y, pos[2]);
2226 Com_Printf("%3i ", Grid_MoveLength(&cl.pathMap, loc, crouchingState, false));
2227 }
2228 Com_Printf("\n");
2229 }
2230 Com_Printf("TUs at (%i, %i, %i) = %i\n", pos[0], pos[1], pos[2], Grid_MoveLength(&cl.pathMap, pos, crouchingState, false));
2231}
2232
2233static void CL_DebugPath_f (void)
2234{
2235 if (IN_GetMouseSpace() != MS_WORLD)
2236 return;
2237
2238 const actorSizeEnum_t actorSize = ACTOR_SIZE_NORMAL;
2239 const pos_t x = mousePos[0];
2240 const pos_t y = mousePos[1];
2241 const pos_t z = mousePos[2];
2242
2243#if 0
2244 int dir = 3;
2245 RT_DebugSpecial(cl.mapTiles, cl.mapData->routing, actorSize, x, y, dir, cl.leInlineModelList);
2246
2247 bool found = Grid_FindPath(cl.mapData->routing, actorSize, &cl.pathMap, selActor->pos, mousePos, 0, 600, nullptr);
2248 if (found)
2249 Com_Printf("found the path !\n");
2250 {
2251// pos3_t boxmin = {134,128,0};
2252// pos3_t boxmax = {136,130,1};
2253// GridBox myBox(boxmin, boxmax);
2254// Grid_RecalcBoxRouting(cl.mapTiles, cl.mapData->routing, myBox, cl.leInlineModelList);
2255 }
2256 int dir = 0;
2257 long time = Sys_Milliseconds();
2258 RT_UpdateConnectionColumn(cl.mapTiles, cl.mapData->routing, actorSize, x, y, dir, cl.leInlineModelList);
2259 time = (Sys_Milliseconds() - time);
2260 Com_Printf("RT_UpdateConnectionColumn needed %i milliseconds\n", (int)time);
2261#endif
2262
2263 RT_DebugPathDisplay(cl.mapData->routing, actorSize, x, y, z);
2264 cl.mapTiles->printTilesAt(x, y);
2265
2266 GridBox mbox;
2267 mbox.setFromMapBounds(cl.mapData->mapBox.mins, cl.mapData->mapBox.maxs);
2268 const int xW = mbox.getMaxX() - mbox.getMinX();
2269 const int yW = mbox.getMaxY() - mbox.getMinY();
2270 const int zW = mbox.getMaxZ() - mbox.getMinZ();
2271 Com_Printf("Statistics:\nWorldsize(x/y/z) %i/%i/%i\n", xW, yW, zW);
2272 int numCells = xW * yW * zW;
2273 Com_Printf("number of Cells: %i\n", numCells);
2274 Com_Printf("Base Coords (x/y/z) %i/%i/%i\n", mbox.getMinX(), mbox.getMinY(), mbox.getMinZ());
2275}
2276#endif
2277
2278
2282static void CL_ActorNext_f (void)
2283{
2284 if (CL_BattlescapeRunning()) {
2286 }
2287}
2288
2292static void CL_ActorPrev_f (void)
2293{
2294 if (CL_BattlescapeRunning()) {
2296 }
2297}
2298
2302static void CL_ActorSelect_f (void)
2303{
2304 /* check syntax */
2305 if (Cmd_Argc() < 2) {
2306 Com_Printf("Usage: %s <num>\n", Cmd_Argv(0));
2307 return;
2308 }
2309
2310 /* check whether we are connected (tactical mission) */
2311 if (CL_BattlescapeRunning()) {
2312 const int num = atoi(Cmd_Argv(1));
2313 CL_ActorSelectList(num);
2314 }
2315}
2316
2320static void CL_ActorUpdate_f (void)
2321{
2322 const int num = cl_selected->integer;
2323
2324 /* We are in the base or multiplayer inventory */
2325 int i = 0;
2327 if (i++ != num)
2328 continue;
2330 }
2331}
2332
2339static bool CL_ActorVis (const le_t* le, const le_t* check)
2340{
2341 vec3_t from;
2342
2343 VectorCopy(le->origin, from);
2344
2345 /* start on eye height */
2346 vec3_t test;
2347 VectorCopy(check->origin, test);
2348 float delta;
2349 if (LE_IsDead(check)) {
2350 test[2] += PLAYER_DEAD;
2351 delta = 0;
2352 } else if (LE_IsCrouched(check)) {
2353 test[2] += PLAYER_CROUCH - 2;
2354 delta = (PLAYER_CROUCH - PLAYER_MIN) / 2 - 2;
2355 } else {
2356 test[2] += PLAYER_STAND;
2357 delta = (PLAYER_STAND - PLAYER_MIN) / 2 - 2;
2358 }
2359
2360 /* side shifting -> better checks */
2361 vec3_t dir;
2362 dir[0] = from[1] - check->origin[1];
2363 dir[1] = check->origin[0] - from[0];
2364 dir[2] = 0;
2365 VectorNormalize(dir);
2366 VectorMA(test, -7, dir, test);
2367
2368 /* do 3 tests */
2369 for (int i = 0; i < 3; i++) {
2370 const trace_t tr = CL_Trace(Line(from, test), AABB::EMPTY, le, nullptr, MASK_SOLID, cl_worldlevel->integer);
2371 /* trace didn't reach the target - something was hit before */
2372 if (tr.fraction < 1.0) {
2373 /* look further down or stop */
2374 if (!delta)
2375 return false;
2376 VectorMA(test, 7, dir, test);
2377 test[2] -= delta;
2378 continue;
2379 }
2380
2381 return true;
2382 }
2383
2384 return false;
2385}
2386
2392{
2393 static int lastAlien = 0;
2394
2395 if (!selActor)
2396 return;
2397
2398 if (lastAlien >= cl.numLEs)
2399 lastAlien = 0;
2400
2401 int i = lastAlien;
2402 do {
2403 if (++i >= cl.numLEs)
2404 i = 0;
2405 const le_t* le = &cl.LEs[i];
2406 if (le->inuse && LE_IsLivingAndVisibleActor(le) && le->team != cls.team
2407 && !LE_IsCivilian(le)) {
2408 if (CL_ActorVis(selActor, le)) {
2409 lastAlien = i;
2411 CL_ParticleSpawn("fadeTracer", 0, selActor->origin, le->origin);
2412 return;
2413 }
2414 }
2415 } while (i != lastAlien);
2416}
2417
2422static void CL_NextAlien_f (void)
2423{
2424 if (cl.numLEs <= 0)
2425 return;
2426
2427 int lastAlien = Cvar_GetInteger("ui_lastalien");
2428 lastAlien = std::max(0, std::min(cl.numLEs - 1, lastAlien));
2429
2430 int i = lastAlien;
2431 do {
2432 if (++i >= cl.numLEs)
2433 i = 0;
2434 const le_t* le = &cl.LEs[i];
2435 if (le->inuse && LE_IsLivingAndVisibleActor(le) && le->team != cls.team
2436 && le->team != TEAM_CIVILIAN) {
2437 lastAlien = i;
2439 Cvar_SetValue("ui_lastalien", lastAlien);
2440 return;
2441 }
2442 } while (i != lastAlien);
2443}
2444
2449static void CL_PrevAlien_f (void)
2450{
2451 if (cl.numLEs <= 0)
2452 return;
2453
2454 int lastAlien = Cvar_GetInteger("ui_lastalien");
2455 lastAlien = std::max(0, std::min(cl.numLEs - 1, lastAlien));
2456
2457 int i = lastAlien;
2458 do {
2459 if (--i < 0)
2460 i = cl.numLEs - 1;
2461 const le_t* le = &cl.LEs[i];
2462 if (le->inuse && LE_IsLivingAndVisibleActor(le) && le->team != cls.team
2463 && le->team != TEAM_CIVILIAN) {
2464 lastAlien = i;
2466 Cvar_SetValue("ui_lastalien", lastAlien);
2467 return;
2468 }
2469 } while (i != lastAlien);
2470}
2471
2477{
2478 if (le->team != cl.actTeam)
2479 return;
2480
2481 /* might be a friendly player controlled actor */
2482 if (le->pnum != cl.pnum)
2483 return;
2484
2485 switch (le->actorMode) {
2486 case M_PEND_MOVE:
2488 break;
2489 case M_PEND_FIRE_R:
2490 case M_PEND_FIRE_L:
2491 CL_ActorShoot(le, le->mousePendPos);
2492 break;
2493 default:
2494 break;
2495 }
2496}
2497
2504static void CL_ActorConfirmAction_f (void)
2505{
2506 static int time = 0;
2507
2508 if (time - cl.time < 1000) {
2509 le_t* le = nullptr;
2510 while ((le = LE_GetNextInUse(le))) {
2511 if (LE_IsLivingActor(le) && !LE_IsStunned(le) && le->team == cls.team)
2513 }
2514 } else {
2515 time = cl.time;
2516 if (!selActor)
2517 return;
2519 }
2520}
2521
2523{
2524 cl_autostand = Cvar_Get("cl_autostand","1", CVAR_USERINFO | CVAR_ARCHIVE, "Prevent accidental wasting of TUs by allowing the actor to automatically stand up before starting long walks.");
2525 confirm_actions = Cvar_Get("confirm_actions", "0", CVAR_ARCHIVE, "Confirm all actions in tactical mode");
2526 cl_showactors = Cvar_Get("cl_showactors", "1", 0, "Show actors on the battlefield");
2527 Cmd_AddCommand("actor_next", CL_ActorNext_f, N_("Toggle to next living actor"));
2528 Cmd_AddCommand("actor_prev", CL_ActorPrev_f, N_("Toggle to previous living actor"));
2529 Cmd_AddCommand("actor_select", CL_ActorSelect_f, N_("Select an actor from list"));
2530 Cmd_AddCommand("actor_updatecurrent", CL_ActorUpdate_f, N_("Update an actor"));
2531 Cmd_AddCommand("actor_standcrouch", CL_ActorStandCrouch_f, N_("Toggle stand/crouch."));
2532 Cmd_AddCommand("actor_useheadgear", CL_ActorUseHeadgear_f, N_("Toggle the headgear"));
2533 Cmd_AddCommand("actor_use", CL_ActorUse_f, N_("Use"));
2534 Cmd_AddCommand("actor_confirmaction", CL_ActorConfirmAction_f, N_("Confirm the current action"));
2535 Cmd_AddCommand("actor_nextalien", CL_NextAlienVisibleFromActor_f, N_("Toggle to the next alien in sight of the selected actor."));
2536
2537 Cmd_AddCommand("nextalien", CL_NextAlien_f, N_("Toggle camera to the next visible alien."));
2538 Cmd_AddCommand("prevalien", CL_PrevAlien_f, N_("Toggle camera to the previous visible alien."));
2539
2540#ifdef DEBUG
2541 Cmd_AddCommand("debug_path", CL_DebugPath_f, "Display routing data for current mouse position.");
2542 Cmd_AddCommand("debug_drawblocked", CL_DisplayBlockedPaths_f, "Draw a marker for all blocked map-positions.");
2543 Cmd_AddCommand("debug_movemark", CL_DumpMoveMark_f, "Trigger Step::isPossible in every direction at the current truePos.");
2544 Cmd_AddCommand("debug_tus", CL_DumpTUs_f, "Show a table of the TUs that would be used by the current actor to move relative to his current location.");
2545 Cmd_AddCommand("debug_actorinvlist", nullptr, "Show the inventory list of all actors.");
2546#endif /* DEBUG */
2547}
reservation_types_t
Definition chr_shared.h:208
@ RES_ALL
Definition chr_shared.h:212
@ RES_REACTION
Definition chr_shared.h:209
@ RES_ALL_ACTIVE
Definition chr_shared.h:213
@ RES_CROUCH
Definition chr_shared.h:210
@ RES_SHOT
Definition chr_shared.h:211
actorSound_t
Types of actor sounds being issued by CL_ActorPlaySound().
Definition chr_shared.h:218
modifier_types_t
Definition chr_shared.h:255
@ MODIFIER_REACTION
Definition chr_shared.h:260
@ MODIFIER_ACCURACY
Definition chr_shared.h:256
@ MODIFIER_MOVEMENT
Definition chr_shared.h:258
@ MODIFIER_SHOOTING
Definition chr_shared.h:257
static cvar_t * cl_showactors
Definition cl_actor.cpp:46
static const vec3_t boxShift
void CL_ActorStartMove(le_t *le, const pos3_t to)
Starts moving actor.
Definition cl_actor.cpp:847
static void CL_AddTargetingBox(pos3_t pos, bool pendBox)
create a targeting box at the given position
void ACTOR_InitStartup(void)
static bool CL_AddActorWeapon(int objID)
Checks whether a weapon should be added to the entity's hand.
void CL_ActorReserveTUs(const le_t *le, const reservation_types_t type, const int tus)
Replace the reserved TUs for a certain type.
Definition cl_actor.cpp:273
static void CL_ActorConfirmAction(le_t *le)
pos3_t mousePos
Definition cl_actor.cpp:51
static const vec3_t halfBoxSize
field marker box
le_t * CL_ActorGetFromCharacter(const character_t *chr)
Returns the local entity information for a character in the team list.
Definition cl_actor.cpp:141
void CL_ActorRemoveFromTeamList(le_t *le)
Removes an actor (from your team) from the team list.
Definition cl_actor.cpp:400
static void CL_ActorMoveMouse(void)
handle select or action clicking in either move mode
static int mousePosTargettingAlign
If you want to change the z level of targeting and shooting, use this value. Negative and positive of...
Definition cl_actor.cpp:62
static bool CL_ActorVis(const le_t *le, const le_t *check)
static void CL_ActorUseHeadgear_f(void)
Toggles the headgear for the current selected player.
int CL_ActorGetNumber(const le_t *le)
Returns the number of the actor in the teamlist.
Definition cl_actor.cpp:125
void CL_ActorSelectMouse(void)
Selects an actor using the mouse.
static void CL_ActorNext_f(void)
Switch to the next living soldier.
static void CL_TargetingRadius(const vec3_t center, const float radius)
Show weapon radius.
int CL_ActorCheckAction(const le_t *le)
Checks that an action is valid.
Definition cl_actor.cpp:713
int CL_ActorUsableTUs(const le_t *le)
Returns the amount of usable (overall-reserved) TUs for an actor.
Definition cl_actor.cpp:259
static byte CL_ActorMoveLength(const le_t *le, const pos3_t to)
Get the real move length (depends on crouch-state of the current actor).
Definition cl_actor.cpp:737
le_t * CL_ActorGetClosest(const vec3_t origin, int team)
Returns the actor that is closest to the given origin.
Definition cl_actor.cpp:694
void CL_ActorTurnMouse(void)
Turns the actor around without moving.
void CL_ActorSetMode(le_t *actor, actorModes_t actorMode)
Definition cl_actor.cpp:835
static void CL_TargetingStraight(const pos3_t fromPos, actorSizeEnum_t fromActorSize, const pos3_t toPos)
Draws line to target.
static bool CL_ActorTraceMove(const pos3_t to)
Draws the way to walk when confirm actions is activated.
Definition cl_actor.cpp:776
void CL_BattlescapeMouseDragging(void)
Scroll battlescape touchscreen-style, by clicking and dragging away.
bool CL_ActorMouseTrace(void)
Battlescape cursor positioning.
int CL_ActorReservedTUs(const le_t *le, const reservation_types_t type)
Returns the amount of reserved TUs for a certain type.
Definition cl_actor.cpp:214
static cvar_t * confirm_actions
Confirm actions in tactical mode - valid values are 0, 1 and 2.
Definition cl_actor.cpp:43
static void CL_ActorUse_f(void)
Hud callback to use the current selected entity.
static void CL_PrevAlien_f(void)
Cycles between visible aliens in reverse direction.
void CL_ActorSetFireDef(le_t *actor, const fireDef_t *fd)
Definition cl_actor.cpp:91
void CL_DisplayObstructionArrows(void)
Useful for debugging pathfinding.
static void CL_ActorConfirmAction_f(void)
Executes "pending" actions such as walking and firing.
static void CL_ActorUse(const le_t *le)
Uses the current selected entity in the battlescape. Can e.g. open the selected door.
void CL_AddTargeting(void)
Adds a target cursor when we render the world.
static void CL_ActorStandCrouch_f(void)
Stands or crouches actor.
static void CL_ActorUpdate_f(void)
Update the skin of the current soldier.
void MSG_Write_PA(player_action_t playerAction, int entnum,...)
Writes player action with its data.
Definition cl_actor.cpp:73
void CL_ActorTargetAlign_f(void)
Targets to the ground when holding the assigned button.
bool CL_ActorSelectPrev(void)
selects the previous actor
Definition cl_actor.cpp:558
static bool CL_AddPathingBox(pos3_t pos, bool addUnreachableCells)
create a targeting box at the given position
int CL_ActorGetContainerForReload(Item **ammoItem, const Inventory *inv, const objDef_t *weapon)
Searches the clip with the least TU usage to put it into the weapon.
Definition cl_actor.cpp:916
static void CL_TargetingGrenade(const pos3_t fromPos, actorSizeEnum_t fromActorSize, const pos3_t toPos)
Shows targeting for a grenade.
void CL_InitBattlescapeMouseDragging(void)
Scroll battlescape touchscreen-style, by clicking and dragging away.
void CL_ActorReload(le_t *le, containerIndex_t containerID)
Reload weapon with actor.
Definition cl_actor.cpp:948
void CL_ActorAddToTeamList(le_t *le)
Adds the actor to the team list.
Definition cl_actor.cpp:362
pos3_t truePos
Definition cl_actor.cpp:50
int CL_ActorMoveMode(const le_t *le)
Decide how the actor will walk, taking into account autostanding.
Definition cl_actor.cpp:102
bool CL_AddActor(le_t *le, entity_t *ent)
Adds an actor to the render entities with all it's models and items.
void CL_ActorPlaySound(const le_t *le, actorSound_t soundType)
Plays various sounds on actor action.
bool CL_ActorFireModeActivated(const actorModes_t mode)
Checks whether we are in fire mode or node.
void CL_AddActorPathing(void)
Adds an actor pathing marker to the current floor when we render the world.
void CL_GetWorldCoordsUnderMouse(vec3_t groundIntersection, vec3_t upperTracePoint, vec3_t lowerTracePoint)
Get battlescape cell position under mouse cursor.
void CL_ActorConditionalMoveCalc(le_t *le)
Recalculate forbidden list, available moves and actor's move length for the current selected actor.
Definition cl_actor.cpp:682
const fireDef_t * CL_ActorGetReactionFireFireDef(const le_t *shooter)
Definition cl_actor.cpp:171
void CL_ActorResetMoveLength(le_t *le)
Recalculates the currently selected Actor's move length.
Definition cl_actor.cpp:764
void CL_ActorShoot(const le_t *le, const pos3_t at)
Shoot with actor.
Definition cl_actor.cpp:888
static void CL_ActorPrev_f(void)
Switch to the previous living soldier.
le_t * selActor
Definition cl_actor.cpp:49
int CL_ActorTimeForFireDef(const le_t *le, const fireDef_t *fd, bool reaction)
Find the TUs needed for the given fireDef taking into account the actor wound penalties.
Definition cl_actor.cpp:342
static le_t * mouseActor
Definition cl_actor.cpp:64
void CL_ActorActionMouse(void)
initiates action with mouse.
static cvar_t * cl_autostand
Player preference: should the server make guys stand for long walks, to save TU.
Definition cl_actor.cpp:45
static void CL_ActorSelect_f(void)
Selects a soldier while we are on battlescape.
bool CL_ActorSelect(le_t *le)
Selects an actor.
Definition cl_actor.cpp:440
void CL_ActorCleanup(le_t *le)
Definition cl_actor.cpp:389
static forbiddenList_t forbiddenList
A list of locations that cannot be moved to.
Definition cl_actor.cpp:602
static void CL_NextAlienVisibleFromActor_f(void)
Cycles between visible (to selected actor) aliens.
static vec3_t mouseDraggingPos
Definition cl_actor.cpp:52
#define GRENADE_PARTITIONS
static void CL_AddArrow(vec3_t from, vec3_t to, float red, float green, float blue)
create an arrow between from and to with the specified color ratios
bool CL_ActorIsReactionFireOutOfRange(const le_t *shooter, const le_t *target)
Definition cl_actor.cpp:199
static void CL_NextAlien_f(void)
Cycles between visible aliens.
bool CL_ActorSelectList(int num)
Selects an actor from a list.
Definition cl_actor.cpp:506
void CL_AddPathing(void)
Adds a pathing marker to the current floor when we render the world.
static le_t * interactEntity
Definition cl_actor.cpp:65
static void CL_BuildForbiddenList(void)
Builds a list of locations that cannot be moved to (client side).
Definition cl_actor.cpp:612
bool CL_ActorSelectNext(void)
selects the next actor
Definition cl_actor.cpp:527
void CL_ActorInvMove(const le_t *le, containerIndex_t fromContainer, int fromX, int fromY, containerIndex_t toContainer, int toX, int toY)
Sends an inventory move event to the server.
character_t * CL_ActorGetChr(const le_t *le)
Returns the character information for an actor in the teamlist.
Definition cl_actor.cpp:155
float CL_ActorInjuryModifier(const le_t *le, const modifier_types_t type)
Returns the actor injury modifier of the specified type.
Definition cl_actor.cpp:299
void CL_DisplayFloorArrows(void)
Useful for debugging pathfinding.
static void CL_ActorMaximumMove(const pos3_t to, const le_t *le, pos3_t pos)
Return the last position we can walk to with a defined amount of TUs.
Definition cl_actor.cpp:816
static pos3_t mouseLastPos
Definition cl_actor.cpp:66
#define CURSOR_OFFSET
Definition cl_actor.h:28
#define ACTOR_GET_FIELDSIZE(actor)
Definition cl_actor.h:48
@ WALKTYPE_AUTOSTAND_BUT_NOT_FAR_ENOUGH
Definition cl_actor.h:36
@ WALKTYPE_WALKING
Definition cl_actor.h:38
@ WALKTYPE_AUTOSTAND_BEING_USED
Definition cl_actor.h:37
@ WALKTYPE_CROUCH_WALKING
Definition cl_actor.h:39
bool CL_OutsideMap(const vec3_t position, const float delta)
Checks whether give position is still inside the map borders.
le_t * CL_BattlescapeSearchAtGridPos(const pos3_t pos, bool includingStunned, const le_t *actor)
Searches a local entity at the given position.
clientBattleScape_t cl
bool CL_BattlescapeRunning(void)
Check whether we already have actors spawned on the battlefield.
bool GAME_ItemIsUseable(const objDef_t *od)
Definition cl_game.cpp:1104
int GAME_GetChrMaxLoad(const character_t *chr)
Returns the max weight the given character can carry.
Definition cl_game.cpp:1577
bool GAME_TeamIsKnown(const teamDef_t *teamDef)
Definition cl_game.cpp:1439
Shared game type headers.
void HUD_DisplayMessage(const char *text)
Displays a message on the hud.
Definition cl_hud.cpp:138
cvar_t * cl_worldlevel
Definition cl_hud.cpp:46
HUD related routines.
int mousePosY
Definition cl_input.cpp:76
int mousePosX
Definition cl_input.cpp:76
void IN_SetMouseSpace(mouseSpace_t mspace)
#define IN_GetMouseSpace()
Definition cl_input.h:48
mouseSpace_t
Definition cl_input.h:31
@ MS_WORLD
Definition cl_input.h:34
le_t * LE_GetNextInUse(le_t *lastLE)
Iterate through the entities that are in use.
void LE_CenterView(const le_t *le)
Center the camera on the local entity's origin.
trace_t CL_Trace(const Line &traceLine, const AABB &box, const le_t *passle, le_t *passle2, int contentmask, int worldLevel)
Moves the given mins/maxs volume through the world from start to end.
bool LE_IsLivingAndVisibleActor(const le_t *le)
Checks whether the given le is a living and visible actor.
bool LE_IsLivingActor(const le_t *le)
Checks whether the given le is a living actor (but might be hidden).
bool LE_IsActor(const le_t *le)
Checks whether the given le is a living actor.
#define LE_IsDead(le)
#define LE_SELECTED
#define IS_MODE_FIRE_RIGHT(x)
#define IS_MODE_FIRE_HEADGEAR(x)
#define IS_MODE_FIRE_LEFT(x)
#define LE_IsCrouched(le)
#define LE_IsDoor(le)
#define LE_IsInvisible(le)
#define LE_IsSelected(le)
actorModes_t
Actor actions.
@ M_PEND_FIRE_L
@ M_MOVE
@ M_FIRE_R
@ M_FIRE_HEADGEAR
@ M_PEND_FIRE_R
@ M_FIRE_L
@ M_PEND_MOVE
#define LE_IsCivilian(le)
#define LE_IsAlien(le)
#define LE_IsStunned(le)
client_static_t cls
Definition cl_main.cpp:83
cvar_t * cl_selected
Definition cl_main.cpp:73
const char * CL_PlayerGetName(unsigned int player)
Get the player name.
Definition cl_parse.cpp:113
ptl_t * CL_ParticleSpawn(const char *name, int levelFlags, const vec3_t s, const vec3_t v, const vec3_t a)
Spawn a new particle to the map.
#define RDF_IRGOGGLES
Definition cl_renderer.h:35
rendererData_t refdef
Definition r_main.cpp:45
void SCR_ChangeCursor(int cursor)
Header for certain screen operations.
#define _(String)
Definition cl_shared.h:44
#define N_(String)
Definition cl_shared.h:46
#define INVDEF(containerID)
Definition cl_shared.h:48
void CL_UpdateCharacterValues(const character_t *chr)
Definition cl_team.cpp:218
linkedList_t * chrDisplayList
List of currently displayed or equipable characters.
Definition cl_team.cpp:38
viddef_t viddef
Definition cl_video.cpp:34
void CL_ViewCenterAtGridPosition(const pos3_t pos)
Centers the camera on a given grid field.
Definition cl_view.cpp:289
cvar_t * cl_isometric
Definition cl_input.cpp:73
static const AABB EMPTY
Definition aabb.h:44
float woundThreshold(const short bodyPart) const
short numBodyParts(void) const
float penalty(const short bodyPart, const modifier_types_t type) const
actorHands_t getHand() const
Definition chr_shared.h:165
int getFmIdx() const
Definition chr_shared.h:157
pos_t getMinY() const
Definition mathlib.h:177
pos_t getMinZ() const
Definition mathlib.h:180
pos_t getMaxY() const
Definition mathlib.h:186
pos_t getMinX() const
Definition mathlib.h:174
pos_t getMaxX() const
Definition mathlib.h:183
pos_t getMaxZ() const
Definition mathlib.h:189
void setFromMapBounds(const vec3_t mini, const vec3_t maxi)
Set the box correctly if the maxs value is the upper corner of a cell. VecToPos considers the upper b...
Definition mathlib.h:163
inventory definition with all its containers
Definition inv_shared.h:525
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.
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.
Item * getContainer2(const containerIndex_t idx) const
Definition inv_shared.h:546
item instance data, with linked list capability
Definition inv_shared.h:402
int getX() const
Definition inv_shared.h:454
const objDef_t * def(void) const
Definition inv_shared.h:469
int getY() const
Definition inv_shared.h:457
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.
bool isHeldTwoHanded() const
Definition inv_shared.h:476
Item * getNext() const
Definition inv_shared.h:451
Definition line.h:31
Primary header for client.
const char * Cmd_Argv(int arg)
Returns a given argument.
Definition cmd.cpp:516
int Cmd_Argc(void)
Return the number of arguments of the current command. "command parameter" will result in a argc of 2...
Definition cmd.cpp:505
void Cmd_AddCommand(const char *cmdName, xcommand_t function, const char *desc)
Add a new command to the script interface.
Definition cmd.cpp:744
bool CM_EntTestLineDM(mapTiles_t *mapTiles, const Line &trLine, vec3_t hit, const int levelmask, const char **entlist)
Checks traces against the world and all inline models, gives the hit position back.
Definition cmodel.cpp:230
bool RT_CanActorStandHere(const Routing &routing, const int actorSize, const pos3_t pos)
Check if an actor can stand(up) in the cell given by pos.
Definition routing.cpp:237
void RT_UpdateConnectionColumn(mapTiles_t *mapTiles, Routing &routing, const int actorSize, const int x, const int y, const int dir, const char **list, const int minZ, const int maxZ)
Routing Function to update the connection between two fields.
Definition routing.cpp:1292
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
Definition common.cpp:440
float Com_GrenadeTarget(const vec3_t from, const vec3_t at, float speed, bool launched, bool rolled, vec3_t v0)
Calculates parabola-type shot.
Definition common.cpp:273
void Com_Error(int code, const char *fmt,...)
Definition common.cpp:459
cvar_t * developer
Definition common.cpp:46
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
@ clc_action
Definition common.h:179
#define SOUND_ATTN_IDLE
Definition common.h:187
#define ERR_DROP
Definition common.h:211
static const vec4_t red
static const vec4_t green
static transfer_t tr
cvar_t * Cvar_ForceSet(const char *varName, const char *value)
Will set the variable even if NOSET or LATCH.
Definition cvar.cpp:604
void Cvar_SetValue(const char *varName, float value)
Expands value to a string and calls Cvar_Set.
Definition cvar.cpp:671
int Cvar_GetInteger(const char *varName)
Returns the int value of a cvar.
Definition cvar.cpp:194
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags, const char *desc)
Init or return a cvar.
Definition cvar.cpp:342
#define CVAR_USERINFO
Definition cvar.h:41
#define CVAR_ARCHIVE
Definition cvar.h:40
#define TL_FLAG_ACTORCLIP
Definition defines.h:359
#define QUANT
Definition defines.h:126
#define MAX_ROUTE_TUS
Definition defines.h:83
#define MASK_SHOT
Definition defines.h:275
#define PATHFINDING_MAX_FALL
Definition defines.h:309
#define ROUTING_NOT_REACHABLE
Definition defines.h:283
#define DEBUG_CLIENT
Definition defines.h:59
#define NONE
Definition defines.h:68
#define MAP_SIZE_OFFSET
Definition defines.h:388
#define PATHFINDING_WIDTH
absolute max
Definition defines.h:292
#define DEBUG_SOUND
Definition defines.h:63
#define DIST_EPSILON
Definition defines.h:377
#define UNIT_HEIGHT
Definition defines.h:122
#define CELL_HEIGHT
A cell's height in QUANT sized units.
Definition defines.h:296
#define TU_TURN
Definition defines.h:73
#define UNIT_SIZE
Definition defines.h:121
#define ROUTING_UNREACHABLE
Definition defines.h:284
#define TU_DOOR_ACTION
Definition defines.h:78
#define ACTOR_SIZE_2x2
Definition defines.h:303
#define ACTOR_SIZE_NORMAL
Definition defines.h:302
#define TU_CROUCH
Definition defines.h:72
#define PATHFINDING_HEIGHT
15 max, adjusting above 8 will require a rewrite to the DV code
Definition defines.h:294
#define GROUND_DELTA
Definition defines.h:115
#define MASK_SOLID
Definition defines.h:272
void Grid_CalcPathing(const Routing &routing, const actorSizeEnum_t actorSize, pathing_t *path, const pos3_t from, int maxTUs, forbiddenList_t *fb_list)
Recalculate the pathing table for the given actor(-position).
Definition grid.cpp:497
pos_t Grid_MoveLength(const pathing_t *path, const pos3_t to, byte crouchingState, bool stored)
Return the needed TUs to walk to a given position.
Definition grid.cpp:698
pos_t Grid_Fall(const Routing &routing, const actorSizeEnum_t actorSize, const pos3_t pos)
Calculated the new height level when something falls down from a certain position.
Definition grid.cpp:783
void Grid_PosToVec(const Routing &routing, const actorSizeEnum_t actorSize, const pos3_t pos, vec3_t vec)
Converts a grid position to world coordinates.
Definition grid.cpp:832
bool Grid_ShouldUseAutostand(const pathing_t *path, const pos3_t toPos)
Checks if a crouched actor could save TUs by standing up, walking and crouching again.
Definition grid.cpp:818
int Grid_MoveNext(const pathing_t *path, const pos3_t toPos, byte crouchingState)
Get the direction to use to move to a position (used to reconstruct the path).
Definition grid.cpp:719
bool Grid_FindPath(const Routing &routing, const actorSizeEnum_t actorSize, pathing_t *path, const pos3_t from, const pos3_t targetPos, byte crouchingState, int maxTUs, forbiddenList_t *forbiddenList)
Tries to find a path from the given actor(-position) to a given target position.
Definition grid.cpp:590
int Grid_Floor(const Routing &routing, const actorSizeEnum_t actorSize, const pos3_t pos)
Returns the height of the floor in a cell.
Definition grid.cpp:754
Battlescape grid functions.
const objDef_t * INVSH_GetItemByIDX(int index)
Returns the item that belongs to the given index or nullptr if the index is invalid.
#define CID_MAX
Definition inv_shared.h:57
int32_t containerIndex_t
Definition inv_shared.h:46
#define MAX_FIREDEFS_PER_WEAPON
Definition inv_shared.h:42
#define CID_LEFT
Definition inv_shared.h:48
#define CID_RIGHT
Definition inv_shared.h:47
voidpf void uLong size
Definition ioapi.h:42
voidpf uLong int origin
Definition ioapi.h:45
const char int mode
Definition ioapi.h:41
#define LIST_Foreach(list, type, var)
Iterates over a linked list, it's safe to delete the returned entry from the list while looping over ...
Definition list.h:41
vec_t VectorNormalize(vec3_t v)
Calculate unit vector for a given vec3_t.
Definition mathlib.cpp:745
vec_t VectorLength(const vec3_t v)
Calculate the length of a vector.
Definition mathlib.cpp:434
void VectorMA(const vec3_t veca, const float scale, const vec3_t vecb, vec3_t outVector)
Sets vector_out (vc) to vevtor1 (va) + scale * vector2 (vb).
Definition mathlib.cpp:261
#define PosSubDV(p, crouch, dv)
Definition mathlib.h:254
#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
#define AngleToDV(x)
Definition mathlib.h:257
short dvec_t
The direction vector tells us where the actor came from (in his previous step). The pathing table hol...
Definition mathlib.h:236
#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
#define todeg
Definition mathlib.h:51
#define M_PI
Definition mathlib.h:34
void NET_vWriteFormat(dbuffer *buf, const char *format, va_list ap)
Writes to buffer according to format; version without syntactic sugar for variable arguments,...
Definition netpack.cpp:149
void NET_WriteMsg(struct net_stream *s, dbuffer &buf)
Enqueue the buffer in the net stream for ONE client.
Definition netpack.cpp:569
void NET_WriteFormat(dbuffer *buf, const char *format,...)
The user-friendly version of NET_WriteFormat that writes variable arguments to buffer according to fo...
Definition netpack.cpp:207
const char * pa_format[]
Player action format strings for netchannel transfer.
Definition q_shared.cpp:34
#define GRAVITY
Definition q_shared.h:276
@ ET_ACTOR
Definition q_shared.h:148
@ ET_ACTOR2x2
Definition q_shared.h:160
@ ET_ROTATING
Definition q_shared.h:158
@ ET_BREAKABLE
Definition q_shared.h:150
@ ET_DOOR
Definition q_shared.h:156
#define STATE_CROUCHED
Definition q_shared.h:263
#define STATE_REACTION
Definition q_shared.h:272
#define ST_HEADGEAR
The headgear slot item should be used when shooting/using the item in the slot.
Definition q_shared.h:231
player_action_t
Definition q_shared.h:189
@ PA_SHOOT
Definition q_shared.h:194
@ PA_INVMOVE
Definition q_shared.h:196
@ PA_USE
Definition q_shared.h:195
@ PA_STATE
Definition q_shared.h:193
@ PA_RESERVE_STATE
Definition q_shared.h:198
@ PA_TURN
Definition q_shared.h:191
@ PA_MOVE
Definition q_shared.h:192
#define ST_RIGHT
The right hand should be used for shooting.
Definition q_shared.h:211
#define TEAM_CIVILIAN
Definition q_shared.h:61
#define ST_LEFT
The left hand should be used for shooting.
Definition q_shared.h:221
#define PLAYER_DEAD
Definition q_sizes.h:8
#define BOX_DELTA_HEIGHT
Definition q_sizes.h:28
#define PLAYER_MIN
Definition q_sizes.h:9
#define BOX_DELTA_LENGTH
Definition q_sizes.h:27
#define PLAYER_CROUCH
Definition q_sizes.h:7
#define BOX_DELTA_WIDTH
Definition q_sizes.h:26
#define PLAYER_STAND
Definition q_sizes.h:6
#define PLAYER_WIDTH
Definition q_sizes.h:10
int R_AddEntity(const entity_t *ent)
Adds a copy of the specified entity to the list of all known render entities.
Definition r_entity.cpp:706
entity_t * R_GetFreeEntity(void)
Get the next free entry in the entity list (the last one).
Definition r_entity.cpp:684
#define RF_IRGOGGLESSHOT
Definition r_entity.h:52
#define RF_SHADOW
Definition r_entity.h:50
#define RF_PATH
Definition r_entity.h:37
#define RF_ACTOR
Definition r_entity.h:46
#define RF_MEMBER
Definition r_entity.h:44
#define RF_SELECTED
Definition r_entity.h:43
#define RF_IRGOGGLES
Definition r_entity.h:48
#define RF_BOX
Definition r_entity.h:36
#define RF_BLOOD
Definition r_entity.h:42
#define RF_ARROW
Definition r_entity.h:38
#define RF_OPPONENT
Definition r_entity.h:51
#define RF_ALLIED
Definition r_entity.h:45
#define RF_NONE
Definition r_entity.h:34
#define RF_NEUTRAL
Definition r_entity.h:49
QGL_EXTERN GLuint GLsizei GLsizei * length
Definition r_gl.h:110
QGL_EXTERN GLint i
Definition r_gl.h:113
QGL_EXTERN GLint GLenum type
Definition r_gl.h:94
image_t * R_FindImage(const char *pname, imagetype_t type)
Finds or loads the given image.
Definition r_image.cpp:603
@ it_effect
Definition r_image.h:43
int R_GetTagIndexByName(const model_t *mod, const char *tagName)
Searches the tag data for the given name.
Definition r_mesh.cpp:247
grid pathfinding and routing
#define ModelFloorToQuant(x)
These macros are meant to correctly convert from model units to QUANT units and back.
Definition routing.h:75
#define QuantToModel(x)
Definition routing.h:79
bool S_LoadAndPlaySample(const char *s, const vec3_t origin, float attenuation, float volume)
does what the name implies in just one function to avoid exposing s_sample_t
Definition s_main.cpp:307
#define SND_VOLUME_DEFAULT
Definition s_main.h:42
#define lengthof(x)
Definition shared.h:105
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
Definition shared.cpp:410
Describes a character with all its attributes.
Definition chr_shared.h:388
chrReservations_t reservedTus
Definition chr_shared.h:415
const teamDef_t * teamDef
Definition chr_shared.h:413
FiremodeSettings RFmode
Definition chr_shared.h:416
char name[MAX_VAR]
Definition chr_shared.h:390
How many TUs (and of what type) did a player reserve for a unit?
Definition chr_shared.h:186
This is a cvar definition. Cvars can be user modified and used in our menus e.g.
Definition cvar.h:71
float alpha
Definition r_entity.h:111
int flags
Definition r_entity.h:112
struct model_s * model
Definition r_entity.h:97
const char * tagname
Definition r_entity.h:107
vec3_t origin
Definition r_entity.h:101
vec3_t color
Definition r_entity.h:100
int skinnum
Definition r_entity.h:110
const image_t * texture
Definition r_entity.h:123
struct entity_s * tagent
Definition r_entity.h:106
vec3_t oldorigin
Definition r_entity.h:102
this is a fire definition for our weapons/ammo
Definition inv_shared.h:110
float range
Definition inv_shared.h:152
A list of locations that cannot be moved to.
Definition grid.h:35
inventory definition for our menus
Definition inv_shared.h:371
a local entity
int state
fireDefIndex_t currentSelectedFiremode
ptl_t * ptl
actorModes_t actorMode
vec3_t origin
actorSizeEnum_t fieldSize
float alpha
pos3_t pos
const fireDef_t * fd
model_t * model1
byte actorMoveLength
The TUs that the current selected actor needs to walk to the current grid position marked by the mous...
unsigned int headSkin
teamDef_t * teamDef
pos3_t mousePendPos
struct le_s * clientAction
int entnum
model_t * model2
int maxHP
Item * getHandItem(actorHands_t hand) const
bool inuse
entity_type_t type
Inventory inv
woundInfo_t wounds
bool isMoving() const
Defines all attributes of objects used in the inventory.
Definition inv_shared.h:264
bool isVirtual
Definition inv_shared.h:284
bool isLoadableInWeapon(const objDef_s *weapon) const
Checks if an item can be used to reload a weapon.
bool isReloadable() const
Definition inv_shared.h:352
vec2_t size
float t
int rounds
int roundsCnt
float life
const char * getActorSound(int gender, actorSound_t soundType) const
char deathTextureName[MAX_VAR]
Definition chr_shared.h:343
const BodyData * bodyTemplate
Definition chr_shared.h:350
int woundLevel[BODYPART_MAXTYPE]
Definition chr_shared.h:362
int treatmentLevel[BODYPART_MAXTYPE]
Definition chr_shared.h:363
int Sys_Milliseconds(void)
pos_t pos3_t[3]
Definition ufotypes.h:58
byte pos_t
Definition ufotypes.h:57
float vec_t
Definition ufotypes.h:37
vec_t vec3_t[3]
Definition ufotypes.h:39
int32_t actorSizeEnum_t
Definition ufotypes.h:77
void UI_RegisterText(int dataId, const char *text)
share a text with a data id
Definition ui_data.cpp:115
@ TEXT_MOUSECURSOR_PLAYERNAMES
Definition ui_dataids.h:48
void UI_ExecuteConfunc(const char *fmt,...)
Executes confunc - just to identify those confuncs in the code - in this frame.
Definition ui_main.cpp:110
Inventory * ui_inventory
void UI_Popup(const char *title, const char *text)
Popup on geoscape.
Definition ui_popup.cpp:47
#define VectorDist(a, b)
Definition vector.h:69
#define VectorSubtract(a, b, dest)
Definition vector.h:45
#define VectorCopy(src, dest)
Definition vector.h:51
#define VectorCompare(a, b)
Definition vector.h:63
#define Vector2Compare(a, b)
Definition vector.h:66
#define VectorDistSqr(a, b)
Definition vector.h:68
#define VectorAdd(a, b, dest)
Definition vector.h:47
#define DotProduct(x, y)
Returns the distance between two 3-dimensional vectors.
Definition vector.h:44
#define VectorSet(v, x, y, z)
Definition vector.h:59
#define VectorScale(in, scale, out)
Definition vector.h:79