UFO: Alien Invasion
Loading...
Searching...
No Matches
cp_team_callbacks.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#include "../../cl_shared.h"
26#include "../../cl_team.h"
28#include "../../ui/ui_dataids.h"
29
30#include "cp_campaign.h"
31#include "cp_team.h"
32#include "cp_team_callbacks.h"
33#include "cp_hospital.h" /* HOS_GetInjuryLevel */
34#ifdef DEBUG
35#include "cp_geoscape.h" /* GEO_GetSelectedAircraft */
36#endif
37
42{
43 /* check syntax */
44 if (cgi->Cmd_Argc() < 1 ) {
45 cgi->Com_Printf("Usage: %s <ucn>\n", cgi->Cmd_Argv(0));
46 return;
47 }
48
49 const int ucn = atoi(cgi->Cmd_Argv(1));
50 if (ucn < 0)
51 return;
52
53 const base_t* base = B_GetCurrentSelectedBase();
54 const employeeType_t employeeType = EMPL_SOLDIER;
55 aircraft_t* aircraft = base->aircraftCurrent;
56 if (!aircraft)
57 return;
58
59 Employee* employee = E_GetEmployeeFromChrUCN(ucn);
60 if (!employee)
61 cgi->Com_Error(ERR_DROP, "CP_TEAM_SelectActorByUCN_f: No employee with UCN %i", ucn);
62
63 if (AIR_IsEmployeeInAircraft(employee, aircraft)) {
64 AIR_RemoveEmployee(employee, aircraft);
65 } else {
66 if (employee->isPilot())
67 AIR_SetPilot(aircraft, employee);
68 else
69 AIR_AddToAircraftTeam(aircraft, employee);
70 }
71
72 CP_UpdateActorAircraftVar(aircraft, employeeType);
73 cgi->Cvar_SetValue("cpteam_size", AIR_GetTeamSize(aircraft));
74 cgi->UI_ExecuteConfunc("aircraft_status_change");
75}
76
81{
82 /* check syntax */
83 if (cgi->Cmd_Argc() < 1) {
84 cgi->Com_Printf("Usage: %s <ucn>\n", cgi->Cmd_Argv(0));
85 return;
86 }
87
88 const base_t* base = B_GetCurrentSelectedBase();
89
90 if (!base)
91 return;
92
93 const int ucn = atoi(cgi->Cmd_Argv(1));
94 if (ucn < 0) {
95 cgi->UI_ExecuteConfunc("reset_character_cvars");
96 return;
97 }
98
99 Employee* employee = E_GetEmployeeFromChrUCN(ucn);
100 if (!employee)
101 cgi->Com_Error(ERR_DROP, "CP_TEAM_SelectActorByUCN_f: No employee with UCN %i", ucn);
102
103 character_t* chr = &employee->chr;
104
105 /* update menu inventory */
107
108 /* set info cvars */
109 cgi->CL_UpdateCharacterValues(chr);
110}
111
115static void CP_TEAM_DeEquipActor_f (void)
116{
117 /* check syntax */
118 if (cgi->Cmd_Argc() < 1) {
119 cgi->Com_Printf("Usage: %s <ucn>\n", cgi->Cmd_Argv(0));
120 return;
121 }
122
124
125 if (!base)
126 return;
127
128 const int ucn = atoi(cgi->Cmd_Argv(1));
129 if (ucn < 0) {
130 cgi->UI_ExecuteConfunc("reset_character_cvars");
131 return;
132 }
133
134 Employee* employee = E_GetEmployeeFromChrUCN(ucn);
135 if (!employee)
136 cgi->Com_Error(ERR_DROP, "CP_TEAM_DeEquipActor_f: No employee with UCN %i", ucn);
137
138 character_t* chr = &employee->chr;
139
140 cgi->INV_DestroyInventory(&chr->inv);
141
143 equipDef_t unused = base->storage;
144 CP_CleanupTeam(base, &unused);
145 cgi->UI_ContainerNodeUpdateEquipment(&base->bEquipment, &unused);
146
147 /* set info cvars */
148 cgi->CL_UpdateCharacterValues(chr);
149}
150
151#ifdef DEBUG
155static void CP_TeamListDebug_f (void)
156{
157 const aircraft_t* aircraft = GEO_GetSelectedAircraft();
158 if (!aircraft) {
159 cgi->Com_Printf("Buy/build an aircraft first.\n");
160 return;
161 }
162
163 const base_t* base = aircraft->homebase;
164 if (!base) {
165 cgi->Com_Printf("Build and select a base first\n");
166 return;
167 }
168
169 cgi->Com_Printf("%i members in the current team", AIR_GetTeamSize(aircraft));
170 for (linkedList_t* list = aircraft->acTeam; list != nullptr; list = list->next) {
171 const Employee* employee = (const Employee*)list->data;
172 cgi->Com_Printf("ucn %i - name: %s\n", employee->chr.ucn, employee->chr.name);
173 }
174}
175#endif
176
181{
182 if (cgi->Cmd_Argc() <= 1 ) {
183 cgi->Com_Printf("Usage: %s <soldier|pilot> [aircraftIDX]\n", cgi->Cmd_Argv(0));
184 return;
185 }
186
187 char typeId[MAX_VAR];
188 Q_strncpyz(typeId, cgi->Cmd_Argv(1), lengthof(typeId));
189 const employeeType_t employeeType = E_GetEmployeeType(typeId);
190
191 if (employeeType == MAX_EMPL) {
192 cgi->Com_Printf("Invalid employeeType: %s\n", typeId);
193 return;
194 }
195
196 const base_t* base = B_GetCurrentSelectedBase();
197 const aircraft_t* aircraft = base->aircraftCurrent;
198 if (cgi->Cmd_Argc() > 2 ) {
199 aircraft = AIR_AircraftGetFromIDX(atoi(cgi->Cmd_Argv(2)));
200 if (!aircraft) {
201 cgi->Com_Printf("No aircraft exist with global idx %i\n", atoi(cgi->Cmd_Argv(2)));
202 return;
203 }
204 base = aircraft->homebase;
205 }
206 if (!aircraft)
207 return;
208
209 cgi->UI_ExecuteConfunc("aircraft_soldierlist_clear");
210 const int teamSize = employeeType == EMPL_PILOT ? (AIR_GetPilot(aircraft) != nullptr ? 1 : 0) : AIR_GetTeamSize(aircraft);
211 const int maxTeamSize = employeeType == EMPL_PILOT ? 1 : aircraft->maxTeamSize;
212 E_Foreach(employeeType, employee) {
213 const aircraft_t* assignedCraft;
214 const char* tooltip;
215
216 if (!employee->isHiredInBase(base))
217 continue;
218 if (employee->transfer)
219 continue;
220
221 assignedCraft = AIR_IsEmployeeInAircraft(employee, nullptr);
222 if (assignedCraft == nullptr) {
223 /* employee unassigned */
224 if (teamSize >= maxTeamSize)
225 /* aircraft is full */
226 tooltip = _("No more employees can be assigned to this aircraft");
227 else
228 /* aircraft has free space */
229 tooltip = "";
230 } else {
231 /* employee assigned */
232 if (assignedCraft == aircraft)
233 /* assigned to this aircraft */
234 tooltip = "";
235 else
236 /* assigned to another aircraft */
237 tooltip = _("Employee is assigned to another aircraft");
238 }
239
240 const int needsHealing = HOS_NeedsHealing(employee->chr) ? 1 : 0;
241 cgi->UI_ExecuteConfunc("aircraft_soldierlist_add %d \"%s\" \"%s\" %d %d \"%s\"", employee->chr.ucn, typeId, employee->chr.name, assignedCraft == aircraft, needsHealing, tooltip);
242 }
243}
244
249{
251 if (!base)
252 return;
253
254 const aircraft_t* aircraft = base->aircraftCurrent;
255
256 if (cgi->Cmd_Argc() > 1 ) {
257 int idx = atoi(cgi->Cmd_Argv(1));
258
259 if (idx >= 0) {
260 aircraft = AIR_AircraftGetFromIDX(idx);
261 if (!aircraft) {
262 cgi->Com_Printf("No aircraft exist with global idx %i\n", idx);
263 return;
264 }
265 base = aircraft->homebase;
266 assert(base);
267 } else {
268 aircraft = nullptr;
269 }
270 }
271
272 /* add soldiers to list */
273 int count = 0;
274 cgi->UI_ExecuteConfunc("equipment_soldierlist_clear");
275 if (aircraft) {
276 LIST_Foreach(aircraft->acTeam, Employee, employee) {
277 character_t* chr = &employee->chr;
279 const int needsHealing = HOS_NeedsHealing(*chr) ? 1 : 0;
280 cgi->UI_ExecuteConfunc("equipment_soldierlist_add %d \"%s\" %d \"\"", chr->ucn, chr->name, needsHealing);
281 count++;
282 }
283 } else {
284 E_Foreach(EMPL_SOLDIER, employee) {
285 if (!employee->isHiredInBase(base))
286 continue;
287 if (employee->transfer)
288 continue;
289 if (employee->isAwayFromBase())
290 continue;
291 character_t* chr = &employee->chr;
293 const int needsHealing = HOS_NeedsHealing(*chr) ? 1 : 0;
294 const aircraft_t* assignedCraft = AIR_IsEmployeeInAircraft(employee, nullptr);
295 cgi->UI_ExecuteConfunc("equipment_soldierlist_add %d \"%s\" %d \"%s\"",
296 chr->ucn, chr->name, needsHealing, assignedCraft ? assignedCraft->name : "");
297 count++;
298 }
299 }
300 /* clean up aircraft crew for upcoming mission */
302 equipDef_t unused = base->storage;
303 CP_CleanupTeam(base, &unused);
304 cgi->UI_ContainerNodeUpdateEquipment(&base->bEquipment, &unused);
305 if (count == 0)
306 cgi->UI_PopWindow(false);
307}
308
313{
314 const base_t* base = B_GetCurrentSelectedBase();
315 if (!base)
316 return;
317
318 const aircraft_t* aircraft = base->aircraftCurrent;
319 if (!aircraft)
320 return;
321
322 cgi->UI_ExecuteConfunc("soldierlist_clear");
323 const int teamSize = AIR_GetTeamSize(aircraft);
324 const int maxTeamSize = aircraft->maxTeamSize;
325 E_Foreach(EMPL_SOLDIER, employee) {
326 if (!employee->isHiredInBase(base))
327 continue;
328 if (employee->transfer)
329 continue;
330
331 const char* tooltip;
332 const bool isInTeam = AIR_IsEmployeeInAircraft(employee, aircraft) != nullptr;
333 if (employee->isAwayFromBase())
334 tooltip = _("Employee is away from base");
335 else if (!isInTeam && teamSize >= maxTeamSize)
336 tooltip = _("No more employee can be assigned to this team");
337 else
338 tooltip = "";
339
340 const rank_t* rank = CL_GetRankByIdx(employee->chr.score.rank);
341 cgi->UI_ExecuteConfunc("soldierlist_add %d \"%s %s\" %d \"%s\"", employee->chr.ucn, (rank) ? _(rank->shortname) : "", employee->chr.name, isInTeam, tooltip);
342 }
343}
344
348static void CP_TEAM_ChangeSkin_f (void)
349{
350 if (cgi->Cmd_Argc() < 3 ) {
351 cgi->Com_Printf("Usage: %s <ucn> <bodyskinidx>\n", cgi->Cmd_Argv(0));
352 return;
353 }
354 const int ucn = atoi(cgi->Cmd_Argv(1));
355 const int bodySkinIdx = atoi(cgi->Cmd_Argv(2));
356
357 Employee* soldier = E_GetEmployeeFromChrUCN(ucn);
358 if (soldier == nullptr || !soldier->isSoldier()) {
359 cgi->Com_Printf("Invalid soldier UCN: %i\n", ucn);
360 return;
361 }
362
363 cgi->Cvar_SetValue("mn_body_skin", bodySkinIdx);
364 soldier->chr.bodySkin = bodySkinIdx;
365}
366
367static const cmdList_t teamCallbacks[] = {
368 {"ui_team_select_ucn", CP_TEAM_SelectActorByUCN_f, "Select a soldier in the team menu by his/her UCN"},
369 {"ui_team_assign_ucn", CP_TEAM_AssignSoldierByUCN_f, "Add/remove soldier to the aircraft"},
370 {"ui_team_fill", CP_TEAM_FillEmployeeList_f, "Fill the Team assignment UI with employee"},
371 {"ui_team_fillbdef", CP_TEAM_FillBDEFEmployeeList_f, "Fill the Team assignment UI with employee for base defence"},
372 {"ui_team_fillequip", CP_TEAM_FillEquipSoldierList_f, "Fill the employee list for the in-base soldier equip screen and initialize the inventory"},
373 {"ui_team_deequip", CP_TEAM_DeEquipActor_f, "De-equip soldier"},
374 {"ui_team_changeskin", CP_TEAM_ChangeSkin_f, "Change the skin of a soldier"},
375#ifdef DEBUG
376 {"debug_teamlist", CP_TeamListDebug_f, "Debug function to show all hired and assigned teammembers"},
377#endif
378 {nullptr, nullptr, nullptr}
379};
380
384{
385 cgi->Cmd_TableAddList(teamCallbacks);
386}
387
392{
393 cgi->Cmd_TableRemoveList(teamCallbacks);
394}
cgame team management headers.
Share stuff between the different cgame implementations.
#define _(String)
Definition cl_shared.h:44
character_t chr
bool isSoldier() const
Definition cp_employee.h:82
bool isPilot() const
Definition cp_employee.h:66
#define ERR_DROP
Definition common.h:211
Employee * AIR_GetPilot(const aircraft_t *aircraft)
Get pilot of an aircraft.
bool AIR_SetPilot(aircraft_t *aircraft, Employee *pilot)
Assign a pilot to an aircraft.
bool AIR_AddToAircraftTeam(aircraft_t *aircraft, Employee *employee)
Adds given employee to given aircraft.
bool AIR_RemoveEmployee(Employee *employee, aircraft_t *aircraft)
Removes a soldier from an aircraft.
int AIR_GetTeamSize(const aircraft_t *aircraft)
Counts the number of soldiers in given aircraft.
const aircraft_t * AIR_IsEmployeeInAircraft(const Employee *employee, const aircraft_t *aircraft)
Tells you if an employee is assigned to an aircraft.
aircraft_t * AIR_AircraftGetFromIDX(int aircraftIdx)
Returns aircraft for a given global index.
base_t * B_GetCurrentSelectedBase(void)
returns the currently selected base
Definition cp_base.cpp:1578
Header file for single player campaign control.
const cgame_import_t * cgi
Employee * E_GetEmployeeFromChrUCN(int uniqueCharacterNumber)
Searches all employee for the ucn (character id).
employeeType_t E_GetEmployeeType(const char *type)
Convert string to employeeType_t.
employeeType_t
The types of employees.
Definition cp_employee.h:30
@ EMPL_SOLDIER
Definition cp_employee.h:31
@ MAX_EMPL
Definition cp_employee.h:36
@ EMPL_PILOT
Definition cp_employee.h:34
#define E_Foreach(employeeType, var)
Header for Geoscape management.
#define GEO_GetSelectedAircraft()
Definition cp_geoscape.h:56
bool HOS_NeedsHealing(const character_t &chr)
Header file for hospital related stuff.
rank_t * CL_GetRankByIdx(const int index)
Returns a rank at an index.
Definition cp_rank.cpp:50
void CP_SetEquipContainer(character_t *chr)
Set up equip (floor) container for soldiers.
Definition cp_team.cpp:137
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
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.
static void CP_TEAM_FillEmployeeList_f(void)
Fill the employee list for Soldier/Pilot assignment.
static void CP_TEAM_FillEquipSoldierList_f(void)
Fill the employee list for the in-base soldier equip screen and initialize the inventory.
void CP_TEAM_ShutdownCallbacks(void)
Function that unregisters team (UI) callbacks.
static void CP_TEAM_SelectActorByUCN_f(void)
Selects a soldier by his/her Unique Character Number on team UI.
static void CP_TEAM_FillBDEFEmployeeList_f(void)
Fill the employee list for Base defence mission.
static void CP_TEAM_AssignSoldierByUCN_f(void)
Adds or removes a soldier to/from an aircraft using his/her UCN as reference.
static void CP_TEAM_DeEquipActor_f(void)
Removes every item from a soldier.
static void CP_TEAM_ChangeSkin_f(void)
Change the skin of a soldier.
void CP_TEAM_InitCallbacks(void)
Function that registers team (UI) callbacks.
static const cmdList_t teamCallbacks[]
Menu related callback functions for the team menu.
#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 GLuint count
Definition r_gl.h:99
#define MAX_VAR
Definition shared.h:36
#define lengthof(x)
Definition shared.h:105
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition shared.cpp:457
An aircraft with all it's data.
struct base_s * homebase
linkedList_t * acTeam
char name[MAX_VAR]
A base with all it's data.
Definition cp_base.h:84
aircraft_t * aircraftCurrent
Definition cp_base.h:100
Inventory bEquipment
Definition cp_base.h:114
equipDef_t storage
Definition cp_base.h:112
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
linkedList_t * next
Definition list.h:32
Describes a rank that a recruit can gain.
Definition cp_rank.h:29
const char * shortname
Definition cp_rank.h:32