UFO: Alien Invasion
Loading...
Searching...
No Matches
cp_team.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.m
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 "../../cl_shared.h"
27#include "../../cl_team.h"
28#include "cp_campaign.h"
29#include "cp_team.h"
30
39{
40 const objDef_t* type = item->def();
41
42 assert(ed->numItems[type->idx] > 0);
43 --ed->numItems[type->idx];
44 if (type->isArmour())
45 return;
46
47 if (type->weapons[0]) {
48 /* The given item is ammo or self-contained weapon (i.e. It has firedefinitions. */
49 if (!type->isAmmo()) {
50 /* "Recharge" the oneshot weapon. */
51 item->setAmmoLeft(type->ammo);
52 item->setAmmoDef(item->def()); /* Just in case this hasn't been done yet. */
53 cgi->Com_DPrintf(DEBUG_CLIENT, "CL_AddWeaponAmmo: oneshot weapon '%s'.\n", type->id);
54 return;
55 } else {
56 /* No change, nothing needs to be done to this item. */
57 return;
58 }
59 } else if (item->getAmmoLeft()) {
60 assert(item->ammoDef());
61 /* The item is a weapon and it was reloaded one time. */
62 if (item->getAmmoLeft() == type->ammo) {
63 /* Fully loaded, no need to reload, but mark the ammo as used. */
64 if (ed->numItems[item->ammoDef()->idx] > 0) {
65 --ed->numItems[item->ammoDef()->idx];
66 } else {
67 /* Your clip has been sold; give it back. */
69 }
70 return;
71 }
72 }
73
74 /* Check for complete clips of the same kind */
75 if (item->ammoDef() && ed->numItems[item->ammoDef()->idx] > 0) {
76 --ed->numItems[item->ammoDef()->idx];
77 item->setAmmoLeft(type->ammo);
78 return;
79 }
80
81 /* Search for any complete clips. */
83 for (int i = 0; i < cgi->csi->numODs; i++) {
84 const objDef_t* od = INVSH_GetItemByIDX(i);
85 if (od->isLoadableInWeapon(type)) {
86 if (ed->numItems[i] > 0) {
87 --ed->numItems[i];
88 item->setAmmoLeft(type->ammo);
89 item->setAmmoDef(od);
90 return;
91 }
92 }
93 }
94
100
101 /* Failed to find a complete clip - see if there's any loose ammo
102 * of the same kind; if so, gather it all in this weapon. */
103 if (item->ammoDef() && ed->numItemsLoose[item->ammoDef()->idx] > 0) {
104 item->setAmmoLeft(ed->numItemsLoose[item->ammoDef()->idx]);
105 ed->numItemsLoose[item->ammoDef()->idx] = 0;
106 return;
107 }
108
109 /* See if there's any loose ammo */
111 item->setAmmoLeft(NONE_AMMO);
112 for (int i = 0; i < cgi->csi->numODs; i++) {
113 const objDef_t* od = INVSH_GetItemByIDX(i);
114 if (od->isLoadableInWeapon(type) && ed->numItemsLoose[i] > item->getAmmoLeft()) {
115 if (item->getAmmoLeft() > 0) {
116 /* We previously found some ammo, but we've now found other
117 * loose ammo of a different (but appropriate) type with
118 * more bullets. Put the previously found ammo back, so
119 * we'll take the new type. */
120 assert(item->ammoDef());
121 ed->numItemsLoose[item->ammoDef()->idx] = item->getAmmoLeft();
122 /* We don't have to accumulate loose ammo into clips
123 * because we did it previously and we create no new ammo */
124 }
125 /* Found some loose ammo to load the weapon with */
126 item->setAmmoLeft(ed->numItemsLoose[i]);
127 ed->numItemsLoose[i] = 0;
128 item->setAmmoDef(od);
129 }
130 }
131}
132
138{
139 /* get the inventory the UI uses for all the work */
140 Inventory* uiInv = *cgi->ui_inventory;
141 /* if it was not already set to our character's inventory ... */
142 if (uiInv && uiInv != &chr->inv) {
143 /* ...use the UI equip cont for our character's equipment container */
145 /* set 'old' CID_EQUIP to nullptr */
147 }
148 /* set the UI inventory to our char's (including the equip container we preserved.) */
149 *cgi->ui_inventory = &chr->inv;
150}
151
156{
157 Item* ic, *next;
158
159 for (ic = chr->inv.getContainer2(container); ic; ic = next) {
160 next = ic->getNext();
161 if (ed->numItems[ic->def()->idx] > 0) {
162 CP_AddWeaponAmmo(ed, ic);
163 } else {
164 /* Drop ammo used for reloading and sold carried weapons. */
165 if (!cgi->INV_RemoveFromInventory(&chr->inv, chr->inv.getContainer(container).def(), ic))
166 cgi->Com_Error(ERR_DROP, "Could not remove item from inventory");
167 }
168 }
169}
170
186{
187 assert(base);
188
189 /* Auto-assign weapons to UGVs/Robots if they have no weapon yet. */
190 E_Foreach(EMPL_ROBOT, employee) {
191 if (!employee->isHiredInBase(base))
192 continue;
193 if (employee->transfer)
194 continue;
195
196 character_t* chr = &employee->chr;
197
198 /* This is an UGV */
199 if (employee->getUGV()) {
200 /* Check if there is a weapon and add it if there isn't. */
201 Item* rightH = chr->inv.getRightHandContainer();
202 if (!rightH || !rightH->def())
203 cgi->INV_EquipActor(chr, nullptr, INVSH_GetItemByID(employee->getUGV()->weapon),
204 cgi->GAME_GetChrMaxLoad(chr));
205 }
206 }
207
208 for (containerIndex_t container = 0; container < CID_MAX; container++) {
209 E_Foreach(EMPL_SOLDIER, employee) {
210 if (!employee->isHiredInBase(base))
211 continue;
212 if (employee->transfer)
213 continue;
214
215 character_t* chr = &employee->chr;
216#if 0
217 /* ignore items linked from any temp container */
218 if (INVDEF(container)->temp)
219 continue;
220#endif
221 CP_CleanupContainerWeapons(ed, container, chr);
222 }
223 }
224}
225
241{
242 assert(aircraft);
243
244 for (containerIndex_t container = 0; container < CID_MAX; container++) {
245 LIST_Foreach(aircraft->acTeam, Employee, employee) {
246 character_t* chr = &employee->chr;
247
248 /* Auto-assign weapons to UGVs/Robots if they have no weapon yet. */
249 if (employee->getUGV()) {
250 /* Check if there is a weapon and add it if there isn't. */
251 Item* rightH = chr->inv.getRightHandContainer();
252 if (!rightH || !rightH->def())
253 cgi->INV_EquipActor(chr, nullptr, INVSH_GetItemByID(employee->getUGV()->weapon),
254 cgi->GAME_GetChrMaxLoad(chr));
255 continue;
256 }
257
258#if 0
259 /* ignore items linked from any temp container */
260 if (INVDEF(container)->temp)
261 continue;
262#endif
263 CP_CleanupContainerWeapons(ed, container, chr);
264 }
265 }
266}
267
274{
275 E_Foreach(EMPL_SOLDIER, employee) {
276 employee->chr.inv.resetTempContainers();
277 }
278
279 E_Foreach(EMPL_ROBOT, employee) {
280 employee->chr.inv.resetTempContainers();
281 }
282
283 if (!base)
284 return;
285
286 cgi->INV_DestroyInventory(&base->bEquipment);
287}
288
297{
298 int numOnAircraft;
299 const Employee* pilot = AIR_GetPilot(aircraft);
300
301 assert(aircraft);
302
303 numOnAircraft = AIR_GetTeamSize(aircraft);
304 cgi->Cvar_Set("mn_hired", _("%i of %i"), numOnAircraft, aircraft->maxTeamSize);
305 cgi->Cvar_Set("mn_hirable_count", "%i", aircraft->maxTeamSize - numOnAircraft);
306 cgi->Cvar_Set("mn_hired_count", "%i", numOnAircraft);
307
308 if (pilot) {
309 cgi->Cvar_Set("mn_pilotassigned", "1");
310 cgi->Cvar_Set("mn_pilot_name", "%s", pilot->chr.name);
311 cgi->Cvar_Set("mn_pilot_body", "%s", CHRSH_CharGetBody(&pilot->chr));
312 cgi->Cvar_Set("mn_pilot_head", "%s", CHRSH_CharGetHead(&pilot->chr));
313 cgi->Cvar_Set("mn_pilot_body_skin", "%i", pilot->chr.bodySkin);
314 cgi->Cvar_Set("mn_pilot_head_skin", "%i", pilot->chr.headSkin);
315 } else {
316 cgi->Cvar_Set("mn_pilotassigned", "0");
317 cgi->Cvar_Set("mn_pilot_name", "");
318 cgi->Cvar_Set("mn_pilot_body", "");
319 cgi->Cvar_Set("mn_pilot_head", "");
320 cgi->Cvar_Set("mn_pilot_body_skin", "");
321 cgi->Cvar_Set("mn_pilot_head_skin", "");
322 }
323}
const char * CHRSH_CharGetBody(const character_t *const chr)
Returns the body model for the soldiers for armoured and non armoured soldiers.
const char * CHRSH_CharGetHead(const character_t *const chr)
Returns the head model for the soldiers for armoured and non armoured soldiers.
Share stuff between the different cgame implementations.
#define _(String)
Definition cl_shared.h:44
#define INVDEF(containerID)
Definition cl_shared.h:48
const invDef_t * def() const
character_t chr
inventory definition with all its containers
Definition inv_shared.h:525
Item * getRightHandContainer() const
void setContainer(const containerIndex_t idx, Item *cont)
Definition inv_shared.h:550
void resetContainer(const containerIndex_t idx)
Definition inv_shared.h:554
const Container & getContainer(const containerIndex_t idx) const
Definition inv_shared.h:537
Item * getContainer2(const containerIndex_t idx) const
Definition inv_shared.h:546
item instance data, with linked list capability
Definition inv_shared.h:402
const objDef_t * ammoDef(void) const
Definition inv_shared.h:460
int getAmmoLeft() const
Definition inv_shared.h:466
void setAmmoDef(const objDef_t *od)
Definition inv_shared.h:435
const objDef_t * def(void) const
Definition inv_shared.h:469
void setAmmoLeft(int value)
Definition inv_shared.h:441
Item * getNext() const
Definition inv_shared.h:451
#define ERR_DROP
Definition common.h:211
Employee * AIR_GetPilot(const aircraft_t *aircraft)
Get pilot of an aircraft.
int AIR_GetTeamSize(const aircraft_t *aircraft)
Counts the number of soldiers in given aircraft.
Header file for single player campaign control.
const cgame_import_t * cgi
employeeType_t
The types of employees.
Definition cp_employee.h:30
@ EMPL_SOLDIER
Definition cp_employee.h:31
@ EMPL_ROBOT
Definition cp_employee.h:35
#define E_Foreach(employeeType, var)
void CP_SetEquipContainer(character_t *chr)
Set up equip (floor) container for soldiers.
Definition cp_team.cpp:137
void CP_CleanupAircraftTeam(aircraft_t *aircraft, equipDef_t *ed)
Reloads weapons, removes not assigned and resets defaults.
Definition cp_team.cpp:240
void CP_CleanupTeam(base_t *base, equipDef_t *ed)
Reloads weapons, removes not assigned and resets defaults.
Definition cp_team.cpp:185
void CP_UpdateActorAircraftVar(aircraft_t *aircraft, employeeType_t employeeType)
Updates data about teams in aircraft.
Definition cp_team.cpp:296
static void CP_CleanupContainerWeapons(equipDef_t *ed, containerIndex_t container, character_t *chr)
Reload or remove weapons in container.
Definition cp_team.cpp:155
void CP_AddWeaponAmmo(equipDef_t *ed, Item *item)
Updates status of weapon (sets pointers, reloads, etc).
Definition cp_team.cpp:38
void CP_CleanTempInventory(base_t *base)
Clears all containers that are temp containers (see script definition).
Definition cp_team.cpp:273
Team management for the campaign gametype headers.
#define DEBUG_CLIENT
Definition defines.h:59
#define NONE_AMMO
Definition defines.h:69
const objDef_t * INVSH_GetItemByIDX(int index)
Returns the item that belongs to the given index or nullptr if the index is invalid.
const objDef_t * INVSH_GetItemByID(const char *id)
Returns the item that belongs to the given id or nullptr if it wasn't found.
#define CID_MAX
Definition inv_shared.h:57
int32_t containerIndex_t
Definition inv_shared.h:46
#define CID_EQUIP
Definition inv_shared.h:56
#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
QGL_EXTERN GLint i
Definition r_gl.h:113
QGL_EXTERN GLint GLenum type
Definition r_gl.h:94
An aircraft with all it's data.
linkedList_t * acTeam
A base with all it's data.
Definition cp_base.h:84
Inventory bEquipment
Definition cp_base.h:114
Describes a character with all its attributes.
Definition chr_shared.h:388
char name[MAX_VAR]
Definition chr_shared.h:390
Inventory inv
Definition chr_shared.h:411
int numItems[MAX_OBJDEFS]
Definition inv_shared.h:608
byte numItemsLoose[MAX_OBJDEFS]
Definition inv_shared.h:609
Defines all attributes of objects used in the inventory.
Definition inv_shared.h:264
bool isLoadableInWeapon(const objDef_s *weapon) const
Checks if an item can be used to reload a weapon.