UFO: Alien Invasion
Loading...
Searching...
No Matches
cl_hud_callbacks.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 "../client.h"
26#include "cl_hud_callbacks.h"
27#include "cl_hud.h"
28#include "cl_actor.h"
29
37{
38 Item* item = actor->getLeftHandItem();
39
40 if (!item) {
41 item = actor->getRightHandItem();
42 if (item == nullptr || !item->isHeldTwoHanded())
43 item = nullptr;
44 else if (container != nullptr)
45 *container = CID_RIGHT;
46 }
47
48 return item;
49}
50
58{
59 if (!actor)
60 return nullptr;
61
62 const Item* weapon = actor->getHandItem(hand);
63 if (!weapon || !weapon->def())
64 return nullptr;
65
66 return weapon->getFiredefs();
67}
68
77static bool HUD_CheckShooting (const le_t* le, Item* weapon)
78{
79 if (!le)
80 return false;
81
82 /* No item in hand. */
83 if (!weapon || !weapon->def()) {
84 HUD_DisplayMessage(_("Can't perform action - no item in hand!"));
85 return false;
86 }
87 /* Cannot shoot because of lack of ammo. */
88 if (weapon->mustReload()) {
89 HUD_DisplayMessage(_("Can't perform action - no ammo!"));
90 return false;
91 }
92 /* Cannot shoot because weapon is fireTwoHanded, yet both hands handle items. */
93 if (weapon->def()->fireTwoHanded && le->getLeftHandItem()) {
94 HUD_DisplayMessage(_("Can't perform action - weapon cannot be fired one handed!"));
95 return false;
96 }
97
98 return true;
99}
100
106static void HUD_FireWeapon_f (void)
107{
108 if (Cmd_Argc() < 3) { /* no argument given */
109 Com_Printf("Usage: %s <l|r> <firemode number>\n", Cmd_Argv(0));
110 return;
111 }
112
113 le_t* actor = selActor;
114 if (actor == nullptr)
115 return;
116
117 const actorHands_t hand = ACTOR_GET_HAND_INDEX(Cmd_Argv(1)[0]);
118 const fireDefIndex_t firemode = atoi(Cmd_Argv(2));
119 if (firemode >= MAX_FIREDEFS_PER_WEAPON || firemode < 0)
120 return;
121
122 const fireDef_t* fd = HUD_GetFireDefinitionForHand(actor, hand);
123 if (fd == nullptr)
124 return;
125
126 const objDef_t* ammo = fd->obj;
127
128 /* Let's check if shooting is possible. */
129 if (!HUD_CheckShooting(actor, actor->getHandItem(hand)))
130 return;
131
132 if (CL_ActorTimeForFireDef(actor, &ammo->fd[fd->weapFdsIdx][firemode]) <= CL_ActorUsableTUs(actor)) {
133 /* Actually start aiming. This is done by changing the current mode of display. */
134 if (hand == ACTOR_HAND_RIGHT)
136 else
138 /* Store firemode. */
139 actor->currentSelectedFiremode = firemode;
140 } else {
141 /* Can not shoot because of not enough TUs - every other
142 * case should be checked previously in this function. */
143 HUD_DisplayMessage(_("Can't perform action - not enough TUs!"));
144 }
145}
146
147static void HUD_SetMoveMode_f (void)
148{
149 le_t* actor = selActor;
150
151 if (actor == nullptr)
152 return;
153
154 CL_ActorSetMode(actor, M_MOVE);
155}
156
161{
162 const le_t* actor = selActor;
163
164 if (!CL_ActorCheckAction(actor))
165 return;
166
168 /* Reset reserved TUs to 0 */
170 HUD_DisplayMessage(_("Disabled crouching/standing up TUs reservation."));
171 } else {
172 /* Reserve the exact amount for crouching/standing up (if we have enough to do so). */
174 HUD_DisplayMessage(va(_("Reserved %i TUs for crouching/standing up."), TU_CROUCH));
175 }
176}
177
181static void HUD_ToggleReaction_f (void)
182{
183 int state = 0;
184 const le_t* actor = selActor;
185
186 if (!CL_ActorCheckAction(actor))
187 return;
188
189 if (!(actor->state & STATE_REACTION)) {
190 if (actor->inv.holdsReactionFireWeapon() && CL_ActorUsableTUs(actor) >= HUD_ReactionFireGetTUs(actor)) {
191 state = STATE_REACTION;
192 HUD_DisplayMessage(_("Reaction fire enabled."));
193 } else {
194 return;
195 }
196 } else {
197 state = ~STATE_REACTION;
198 HUD_DisplayMessage(_("Reaction fire disabled."));
199 }
200
201 /* Send request to update actor's reaction state to the server. */
202 MSG_Write_PA(PA_STATE, actor->entnum, state);
203}
204
217int HUD_CalcReloadTime (const le_t* le, const objDef_t* weapon, containerIndex_t toContainer)
218{
219 if (toContainer == NONE)
220 return -1;
221
222 assert(le);
223 assert(weapon);
224
225 Item* ic;
226 const containerIndex_t container = CL_ActorGetContainerForReload(&ic, &le->inv, weapon);
227 if (container == NONE)
228 return -1;
229
230 /* total TU cost is the sum of 3 numbers:
231 * TU for weapon reload + TU to get ammo out + TU to put ammo in hands */
232 return INVDEF(container)->out + INVDEF(toContainer)->in + weapon->getReloadTime();
233}
234
244static bool HUD_CheckReload (const le_t* le, const Item* weapon, containerIndex_t container)
245{
246 if (!le)
247 return false;
248
249 /* No item in hand. */
250 if (!weapon || !weapon->def()) {
251 HUD_DisplayMessage(_("Can't perform action - no item in hand!"));
252 return false;
253 }
254
255 /* Cannot reload because this item is not reloadable. */
256 if (!weapon->isReloadable()) {
257 HUD_DisplayMessage(_("Can't perform action - this item is not reloadable!"));
258 return false;
259 }
260
261 const int tus = HUD_CalcReloadTime(le, weapon->def(), container);
262 /* Cannot reload because of no ammo in inventory. */
263 if (tus == -1) {
264 HUD_DisplayMessage(_("Can't perform action - no ammo!"));
265 return false;
266 }
267 /* Cannot reload because of not enough TUs. */
268 if (le->TU < tus) {
269 HUD_DisplayMessage(_("Can't perform action - not enough TUs!"));
270 return false;
271 }
272
273 return true;
274}
275
279static void HUD_ReloadLeft_f (void)
280{
281 le_t* actor = selActor;
282
283 if (actor == nullptr)
284 return;
285
286 containerIndex_t container = CID_LEFT;
287 if (!HUD_CheckReload(actor, HUD_GetLeftHandWeapon(actor, &container), container))
288 return;
289 CL_ActorReload(actor, container);
290 HUD_DisplayMessage(_("Left hand weapon reloaded."));
291}
292
296static void HUD_ReloadRight_f (void)
297{
298 le_t* actor = selActor;
299
300 if (!actor || !HUD_CheckReload(actor, actor->getRightHandItem(), CID_RIGHT))
301 return;
303 HUD_DisplayMessage(_("Right hand weapon reloaded."));
304}
305
310static void HUD_ExecuteAction_f (void)
311{
312 if (!selActor)
313 return;
314
315 if (Cmd_Argc() < 2) {
316 Com_Printf("Usage: %s <actionid>\n", Cmd_Argv(0));
317 return;
318 }
319
320 if (Q_streq(Cmd_Argv(1), "reload_handl")) {
322 return;
323 }
324
325 if (Q_streq(Cmd_Argv(1), "reload_handr")) {
327 return;
328 }
329
330 if (char const* const rest = Q_strstart(Cmd_Argv(1), "fire_hand")) {
331 if (strlen(rest) >= 4) {
332 char const hand = rest[0];
333 int const index = atoi(rest + 3);
334 Cmd_ExecuteString("hud_fireweapon %c %i", hand, index);
335 return;
336 }
337 }
338
339 Com_Printf("HUD_ExecuteAction_f: Action \"%s\" unknown.\n", Cmd_Argv(1));
340}
341
343{
344 Cmd_AddCommand("hud_movemode", HUD_SetMoveMode_f, N_("Set selected actor to move mode (it cancels the fire mode)."));
345 Cmd_AddCommand("hud_reloadleft", HUD_ReloadLeft_f, N_("Reload the weapon in the soldiers left hand."));
346 Cmd_AddCommand("hud_reloadright", HUD_ReloadRight_f, N_("Reload the weapon in the soldiers right hand."));
347 Cmd_AddCommand("hud_togglecrouchreserve", HUD_ToggleCrouchReservation_f, N_("Toggle reservation for crouching."));
348 Cmd_AddCommand("hud_togglereaction", HUD_ToggleReaction_f, N_("Toggle reaction fire."));
349 Cmd_AddCommand("hud_fireweapon", HUD_FireWeapon_f, N_("Start aiming the weapon."));
350 Cmd_AddCommand("hud_executeaction", HUD_ExecuteAction_f, N_("Execute an action."));
351}
@ RES_CROUCH
Definition chr_shared.h:210
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
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
void CL_ActorSetMode(le_t *actor, actorModes_t actorMode)
Definition cl_actor.cpp:835
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
void MSG_Write_PA(player_action_t playerAction, int entnum,...)
Writes player action with its data.
Definition cl_actor.cpp:73
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
void CL_ActorReload(le_t *le, containerIndex_t containerID)
Reload weapon with actor.
Definition cl_actor.cpp:948
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
void HUD_DisplayMessage(const char *text)
Displays a message on the hud.
Definition cl_hud.cpp:138
int HUD_ReactionFireGetTUs(const le_t *actor)
Get the weapon firing TUs for reaction fire.
Definition cl_hud.cpp:774
HUD related routines.
#define ACTOR_GET_HAND_INDEX(hand)
Definition cl_hud.h:34
static void HUD_FireWeapon_f(void)
Starts aiming/target mode for selected left/right firemode.
static void HUD_SetMoveMode_f(void)
Item * HUD_GetLeftHandWeapon(const le_t *actor, containerIndex_t *container)
returns the weapon the actor's left hand is touching. In case the actor holds a two handed weapon in ...
int HUD_CalcReloadTime(const le_t *le, const objDef_t *weapon, containerIndex_t toContainer)
Calculate total reload time for selected actor.
static void HUD_ToggleReaction_f(void)
Toggles reaction fire states for the current selected actor.
static void HUD_ToggleCrouchReservation_f(void)
Toggles if the current actor reserves TUs for crouching.
static bool HUD_CheckReload(const le_t *le, const Item *weapon, containerIndex_t container)
Check if reload is possible.
void HUD_InitCallbacks(void)
static void HUD_ExecuteAction_f(void)
static void HUD_ReloadLeft_f(void)
Reload left weapon.
const fireDef_t * HUD_GetFireDefinitionForHand(const le_t *actor, const actorHands_t hand)
Returns the fire definition of the item the actor has in the given hand.
static void HUD_ReloadRight_f(void)
Reload right weapon.
static bool HUD_CheckShooting(const le_t *le, Item *weapon)
Check if shooting is possible. i.e. The weapon has ammo and can be fired with the 'available' hands....
@ M_MOVE
@ M_FIRE_R
@ M_FIRE_L
#define _(String)
Definition cl_shared.h:44
#define N_(String)
Definition cl_shared.h:46
#define INVDEF(containerID)
Definition cl_shared.h:48
bool holdsReactionFireWeapon() const
Checks if there is a weapon in the hands that can be used for reaction fire.
item instance data, with linked list capability
Definition inv_shared.h:402
bool mustReload() const
Definition inv_shared.h:483
const objDef_t * def(void) const
Definition inv_shared.h:469
const fireDef_t * getFiredefs() const
Returns the firedefinitions for a given weapon/ammo.
bool isReloadable() const
Definition inv_shared.h:479
bool isHeldTwoHanded() const
Definition inv_shared.h:476
Primary header for client.
void Cmd_ExecuteString(const char *text,...)
A complete command line has been parsed, so try to execute it.
Definition cmd.cpp:1007
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
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
#define NONE
Definition defines.h:68
#define TU_CROUCH
Definition defines.h:72
int32_t fireDefIndex_t
Definition inv_shared.h:78
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
actorHands_t
Definition inv_shared.h:626
@ ACTOR_HAND_RIGHT
Definition inv_shared.h:628
#define STATE_REACTION
Definition q_shared.h:272
@ PA_STATE
Definition q_shared.h:193
QGL_EXTERN GLuint index
Definition r_gl.h:110
#define Q_streq(a, b)
Definition shared.h:136
char const * Q_strstart(char const *str, char const *start)
Matches the start of a string.
Definition shared.cpp:587
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
this is a fire definition for our weapons/ammo
Definition inv_shared.h:110
const struct objDef_s * obj
Definition inv_shared.h:125
weaponFireDefIndex_t weapFdsIdx
Definition inv_shared.h:126
a local entity
int state
Item * getLeftHandItem() const
fireDefIndex_t currentSelectedFiremode
Item * getRightHandItem() const
int entnum
Item * getHandItem(actorHands_t hand) const
Inventory inv
Defines all attributes of objects used in the inventory.
Definition inv_shared.h:264
int getReloadTime() const
Definition inv_shared.h:349
fireDef_t fd[MAX_WEAPONS_PER_OBJDEF][MAX_FIREDEFS_PER_WEAPON]
Definition inv_shared.h:314
bool fireTwoHanded
Definition inv_shared.h:279