UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
cp_team_callbacks.cpp
Go to the documentation of this file.
1 
6 /*
7 Copyright (C) 2002-2020 UFO: Alien Invasion.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 */
24 
25 #include "../../cl_shared.h"
26 #include "../../cl_team.h"
27 #include "../../cgame/cl_game_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 
41 static void CP_TEAM_AssignSoldierByUCN_f (void)
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 
80 static void CP_TEAM_SelectActorByUCN_f (void)
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 
115 static 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 
142  CP_CleanTempInventory(base);
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
152 
155 static 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 
180 static void CP_TEAM_FillEmployeeList_f (void)
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 */
301  CP_CleanTempInventory(base);
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 
348 static 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 
367 static 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 };
384 {
385  cgi->Cmd_TableAddList(teamCallbacks);
386 }
387 
392 {
393  cgi->Cmd_TableRemoveList(teamCallbacks);
394 }
static void CP_TEAM_FillEmployeeList_f(void)
Fill the employee list for Soldier/Pilot assignment.
employeeType_t E_GetEmployeeType(const char *type)
Convert string to employeeType_t.
static void CP_TEAM_AssignSoldierByUCN_f(void)
Adds or removes a soldier to/from an aircraft using his/her UCN as reference.
Describes a rank that a recruit can gain.
Definition: cp_rank.h:29
#define E_Foreach(employeeType, var)
Definition: cp_employee.h:122
const aircraft_t * AIR_IsEmployeeInAircraft(const Employee *employee, const aircraft_t *aircraft)
Tells you if an employee is assigned to an aircraft.
#define _(String)
Definition: cl_shared.h:43
int maxTeamSize
Definition: cp_aircraft.h:138
static void CP_TEAM_ChangeSkin_f(void)
Change the skin of a soldier.
bool AIR_RemoveEmployee(Employee *employee, aircraft_t *aircraft)
Removes a soldier from an aircraft.
base_t * B_GetCurrentSelectedBase(void)
returns the currently selected base
Definition: cp_base.cpp:1578
character_t chr
Definition: cp_employee.h:119
aircraft_t * AIR_AircraftGetFromIDX(int aircraftIdx)
Returns aircraft for a given global index.
const char * shortname
Definition: cp_rank.h:32
#define GEO_GetSelectedAircraft()
Definition: cp_geoscape.h:56
char name[MAX_VAR]
Definition: cp_aircraft.h:120
rank_t * CL_GetRankByIdx(const int index)
Returns a rank at an index.
Definition: cp_rank.cpp:50
linkedList_t * acTeam
Definition: cp_aircraft.h:139
equipDef_t storage
Definition: cp_base.h:112
void CP_UpdateActorAircraftVar(aircraft_t *aircraft, employeeType_t employeeType)
Updates data about teams in aircraft.
Definition: cp_team.cpp:296
A base with all it's data.
Definition: cp_base.h:84
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition: shared.cpp:457
aircraft_t * aircraftCurrent
Definition: cp_base.h:100
#define ERR_DROP
Definition: common.h:211
#define MAX_VAR
Definition: shared.h:36
void CP_TEAM_ShutdownCallbacks(void)
Function that unregisters team (UI) callbacks.
Header file for hospital related stuff.
static const cmdList_t teamCallbacks[]
const cgame_import_t * cgi
employeeType_t
The types of employees.
Definition: cp_employee.h:30
Menu related callback functions for the team menu.
character_t * chr
Definition: cgame.h:187
Definition: cmd.h:86
Employee * AIR_GetPilot(const aircraft_t *aircraft)
Get pilot of an aircraft.
Header for Geoscape management.
QGL_EXTERN GLuint count
Definition: r_gl.h:99
struct base_s * homebase
Definition: cp_aircraft.h:149
void CP_TEAM_InitCallbacks(void)
Function that registers team (UI) callbacks.
void CP_CleanupTeam(base_t *base, equipDef_t *ed)
Reloads weapons, removes not assigned and resets defaults.
Definition: cp_team.cpp:185
int AIR_GetTeamSize(const aircraft_t *aircraft)
Counts the number of soldiers in given aircraft.
bool HOS_NeedsHealing(const character_t &chr)
Employee * E_GetEmployeeFromChrUCN(int uniqueCharacterNumber)
Searches all employee for the ucn (character id)
static void CP_TEAM_SelectActorByUCN_f(void)
Selects a soldier by his/her Unique Character Number on team UI.
#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
linkedList_t * next
Definition: list.h:32
Header file for single player campaign control.
static void CP_TEAM_FillBDEFEmployeeList_f(void)
Fill the employee list for Base defence mission.
Inventory inv
Definition: chr_shared.h:392
char name[MAX_VAR]
Definition: chr_shared.h:371
#define lengthof(x)
Definition: shared.h:105
bool isPilot() const
Definition: cp_employee.h:66
bool AIR_SetPilot(aircraft_t *aircraft, Employee *pilot)
Assign a pilot to an aircraft.
void CP_CleanTempInventory(base_t *base)
Clears all containers that are temp containers (see script definition).
Definition: cp_team.cpp:273
Inventory bEquipment
Definition: cp_base.h:114
static void CP_TEAM_FillEquipSoldierList_f(void)
Fill the employee list for the in-base soldier equip screen and initialize the inventory.
An aircraft with all it's data.
Definition: cp_aircraft.h:114
Team management for the campaign gametype headers.
bool AIR_AddToAircraftTeam(aircraft_t *aircraft, Employee *employee)
Adds given employee to given aircraft.
static void CP_TEAM_DeEquipActor_f(void)
Removes every item from a soldier.
const char *IMPORT * Cmd_Argv(int n)
void CP_SetEquipContainer(character_t *chr)
Set up equip (floor) container for soldiers.
Definition: cp_team.cpp:137
Describes a character with all its attributes.
Definition: chr_shared.h:369