UFO: Alien Invasion
Doxygen documentation generating
cp_employee.cpp
Go to the documentation of this file.
1 
7 /*
8 Copyright (C) 2002-2023 UFO: Alien Invasion.
9 
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14 
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 
19 See the GNU General Public License for more details.
20 
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 */
25 
26 #include "../../cl_shared.h"
27 #include "../cl_game.h" /* GAME_GetTeamDef */
28 #include "../cl_game_team.h" /* character xml loading */
29 #include "cp_campaign.h"
30 #include "cp_employee_callbacks.h"
31 #include "cp_rank.h"
32 #include "cp_popup.h"
33 #include "save/save_employee.h"
34 
40 {
41  return cgi->LIST_Count(ccs.employees[type]);
42 }
43 
50 {
51  E_Foreach(type, employee) {
52  if (!employee->isHired())
53  return employee;
54  }
55 
56  return nullptr;
57 }
58 
63 int Employee::salary() const
64 {
65  const campaign_t* campaign = ccs.curCampaign;
66  const salary_t* salary = &campaign->salaries;
67  const rank_t* rank = CL_GetRankByIdx(this->chr.score.rank);
68  return salary->base[getType()] + rank->level * salary->rankBonus[getType()];
69 }
70 
76 {
77  /* Check that employee is hired */
78  if (!isHired())
79  return false;
80 
81  /* Check if employee is currently transferred. */
82  if (transfer)
83  return true;
84 
85  /* for now only soldiers, ugvs and pilots can be assigned to an aircraft */
86  if (!isSoldier() && !isRobot() && !isPilot())
87  return false;
88 
89  /* Crashed aircraft no longer belongs to any base but poor pilot/soldiers assigned
90  * to it are definitely away from the base so we need to iterate through all aircraft */
91  AIR_Foreach(aircraft) {
92  if (aircraft->homebase != baseHired)
93  continue;
94  if (!AIR_IsAircraftInBase(aircraft) && AIR_IsEmployeeInAircraft(this, aircraft))
95  return true;
96  }
97  return false;
98 }
99 
107 void E_HireForBuilding (base_t* base, building_t* building, int num)
108 {
109  if (num < 0)
110  num = building->maxEmployees;
111 
112  if (num) {
113  employeeType_t employeeType;
114  switch (building->buildingType) {
115  case B_WORKSHOP:
116  employeeType = EMPL_WORKER;
117  break;
118  case B_LAB:
119  employeeType = EMPL_SCIENTIST;
120  break;
121  case B_HANGAR: /* the Dropship Hangar */
122  employeeType = EMPL_SOLDIER;
123  break;
124  case B_MISC:
125  cgi->Com_DPrintf(DEBUG_CLIENT, "E_HireForBuilding: Misc building type: %i with employees: %i.\n", building->buildingType, num);
126  return;
127  default:
128  cgi->Com_DPrintf(DEBUG_CLIENT, "E_HireForBuilding: Unknown building type: %i.\n", building->buildingType);
129  return;
130  }
131  /* don't try to hire more that available - see E_CreateEmployee */
132  num = std::min(num, E_CountByType(employeeType));
133  for (;num--;) {
134  assert(base);
135  if (!E_HireEmployeeByType(base, employeeType)) {
136  cgi->Com_DPrintf(DEBUG_CLIENT, "E_HireForBuilding: Hiring %i employee(s) of type %i failed.\n", num, employeeType);
137  return;
138  }
139  }
140  }
141 }
142 
151 bool E_MoveIntoNewBase (Employee* employee, base_t* newBase)
152 {
153  if (employee) {
154  base_t* oldBase = employee->baseHired;
155  employee->baseHired = newBase;
156  /* Remove employee from corresponding capacity */
157  switch (employee->getType()) {
158  case EMPL_WORKER:
159  if (oldBase != nullptr)
160  PR_UpdateProductionCap(oldBase, 0);
161  /* fall through */
162  case EMPL_PILOT:
163  case EMPL_SCIENTIST:
164  case EMPL_SOLDIER:
165  if (oldBase != nullptr)
166  CAP_AddCurrent(oldBase, CAP_EMPLOYEES, -1);
167  CAP_AddCurrent(newBase, CAP_EMPLOYEES, 1);
168  break;
169  case EMPL_ROBOT:
170  if (oldBase != nullptr)
171  CAP_AddCurrent(oldBase, CAP_ITEMS, -UGV_SIZE);
172  CAP_AddCurrent(newBase, CAP_ITEMS, UGV_SIZE);
173  break;
174  case MAX_EMPL:
175  break;
176  }
177  return true;
178  }
179 
180  return false;
181 }
182 
190 {
191  switch (type) {
192  case EMPL_SOLDIER:
193  return ngettext("Soldier", "Soldiers", n);
194  case EMPL_SCIENTIST:
195  return ngettext("Scientist", "Scientists", n);
196  case EMPL_WORKER:
197  return ngettext("Worker", "Workers", n);
198  case EMPL_PILOT:
199  return ngettext("Pilot", "Pilots", n);
200  case EMPL_ROBOT:
201  return ngettext("UGV", "UGVs", n);
202  default:
203  cgi->Com_Error(ERR_DROP, "Unknown employee type '%i'\n", type);
204  }
205 }
206 
214 {
215  if (!type)
216  return MAX_EMPL;
217 
218  /* employee types as string */
219  if (Q_streq(type, "EMPL_SCIENTIST"))
220  return EMPL_SCIENTIST;
221  else if (Q_streq(type, "EMPL_SOLDIER"))
222  return EMPL_SOLDIER;
223  else if (Q_streq(type, "EMPL_WORKER"))
224  return EMPL_WORKER;
225  else if (Q_streq(type, "EMPL_PILOT"))
226  return EMPL_PILOT;
227  else if (Q_streq(type, "EMPL_ROBOT"))
228  return EMPL_ROBOT;
229 
230  /* human readable employee type strings */
231  if (Q_streq(type, "scientist"))
232  return EMPL_SCIENTIST;
233  else if (Q_streq(type, "soldier"))
234  return EMPL_SOLDIER;
235  else if (Q_streq(type, "worker"))
236  return EMPL_WORKER;
237  else if (Q_streq(type, "pilot"))
238  return EMPL_PILOT;
239  else if (Q_streq(type, "robot"))
240  return EMPL_ROBOT;
241  else if (Q_streq(type, "ugv"))
242  return EMPL_ROBOT;
243 
244  return MAX_EMPL;
245 }
246 
254 {
255  E_Foreach(EMPL_ROBOT, employee) {
256  if (!employee->isHired()) {
257  /* If no type was given we return the first ugv we find. */
258  if (!ugvType || employee->getUGV() == ugvType)
259  return employee;
260  }
261  }
262 
263  return nullptr;
264 }
265 
273 int E_GetHiredEmployees (const base_t* const base, employeeType_t type, linkedList_t** hiredEmployees)
274 {
275  if (type >= MAX_EMPL) {
276  cgi->Com_Printf("E_GetHiredEmployees: Unknown EmployeeType: %i\n", type);
277  *hiredEmployees = nullptr;
278  return -1;
279  }
280 
281  cgi->LIST_Delete(hiredEmployees);
282 
283  E_Foreach(type, employee) {
284  if (!employee->isHired())
285  continue;
286  if (!employee->transfer && (!base || employee->isHiredInBase(base))) {
287  cgi->LIST_AddPointer(hiredEmployees, employee);
288  }
289  }
290 
291  return cgi->LIST_Count(*hiredEmployees);
292 }
293 
301 Employee* E_GetHiredRobot (const base_t* const base, const ugv_t* ugvType)
302 {
303  linkedList_t* hiredEmployees = nullptr;
304  Employee* employee;
305 
306  E_GetHiredEmployees(base, EMPL_ROBOT, &hiredEmployees);
307 
308  employee = nullptr;
309  LIST_Foreach(hiredEmployees, Employee, e) {
310  if ((e->getUGV() == ugvType || !ugvType) /* If no type was given we return the first ugv we find. */
311  && e->isHiredInBase(base)) { /* It has to be in the defined base. */
312  assert(e->isHired());
313  employee = e;
314  break;
315  }
316  }
317 
318  cgi->LIST_Delete(&hiredEmployees);
319 
320  if (!employee)
321  cgi->Com_DPrintf(DEBUG_CLIENT, "Could not get unhired ugv/robot.\n");
322 
323  return employee;
324 }
325 
335 {
336  E_Foreach(type, employee) {
337  if (!employee->isHiredInBase(base))
338  continue;
339  if (employee->isAssigned())
340  return employee;
341  }
342  return nullptr;
343 }
344 
354 {
355  E_Foreach(type, employee) {
356  if (!employee->isHiredInBase(base))
357  continue;
358  if (employee->transfer)
359  continue;
360  if (!employee->isAssigned())
361  return employee;
362  }
363  return nullptr;
364 }
365 
373 bool E_HireEmployee (base_t* base, Employee* employee)
374 {
375  if (CAP_GetFreeCapacity(base, CAP_EMPLOYEES) <= 0) {
376  CP_Popup(_("Not enough quarters"), _("You don't have enough quarters for your employees.\nBuild more quarters."));
377  return false;
378  }
379 
380  if (employee) {
381  /* Now uses quarter space. */
382  employee->baseHired = base;
383  /* Update other capacities */
384  switch (employee->getType()) {
385  case EMPL_WORKER:
386  CAP_AddCurrent(base, CAP_EMPLOYEES, 1);
388  break;
389  case EMPL_PILOT:
390  AIR_AutoAddPilotToAircraft(base, employee);
391  /* fall through */
392  case EMPL_SCIENTIST:
393  case EMPL_SOLDIER:
394  CAP_AddCurrent(base, CAP_EMPLOYEES, 1);
396  break;
397  case EMPL_ROBOT:
399  break;
400  case MAX_EMPL:
401  break;
402  }
403  return true;
404  }
405  return false;
406 }
407 
415 {
416  Employee* employee = E_GetUnhired(type);
417  return employee ? E_HireEmployee(base, employee) : false;
418 }
419 
426 bool E_HireRobot (base_t* base, const ugv_t* ugvType)
427 {
428  Employee* employee = E_GetUnhiredRobot(ugvType);
429  return employee ? E_HireEmployee(base, employee) : false;
430 }
431 
436 {
437  if (!baseHired)
438  return false;
439 
440  /* Remove employee from building/tech/production/aircraft). */
441  switch (_type) {
442  case EMPL_SCIENTIST:
443  if (isAssigned())
445  break;
446  case EMPL_ROBOT:
447  case EMPL_SOLDIER:
448  /* Remove soldier from aircraft/team if he was assigned to one. */
449  if (AIR_IsEmployeeInAircraft(this, nullptr))
450  AIR_RemoveEmployee(this, nullptr);
451  break;
452  case EMPL_PILOT:
454  break;
455  case EMPL_WORKER:
456  default:
457  break;
458  }
459 
460  return true;
461 }
462 
467 {
468  /* Destroy the inventory of the employee (carried items will remain in base->storage) */
469  cgi->INV_DestroyInventory(&chr.inv);
470 }
471 
481 {
482  if (!isHired() || transfer) {
483  cgi->Com_DPrintf(DEBUG_CLIENT, "Could not fire employee\n");
484  return false;
485  }
486 
487  unassign();
488  unequip();
489 
490  /* Remove employee from corresponding capacity */
491  switch (_type) {
492  case EMPL_WORKER:
494  /* fall through */
495  case EMPL_PILOT:
496  case EMPL_SCIENTIST:
497  case EMPL_SOLDIER:
499  break;
500  case EMPL_ROBOT:
502  break;
503  case MAX_EMPL:
504  break;
505  }
506 
507  /* Set all employee-tags to 'unhired'. */
508  baseHired = nullptr;
509 
510  return true;
511 }
512 
519 {
520  if (!base)
521  return;
522 
523  assert(type < MAX_EMPL);
524 
525  E_Foreach(type, employee) {
526  if (!employee->isHiredInBase(base))
527  continue;
528  employee->unhire();
529  }
530 }
531 
540 Employee* E_CreateEmployee (employeeType_t type, const nation_t* nation, const ugv_t* ugvType)
541 {
542  const char* teamID;
543  char teamDefName[MAX_VAR];
544  const char* rank;
545 
546  if (type >= MAX_EMPL)
547  return nullptr;
548 
549  Employee employee(type, nation, ugvType);
550 
551  teamID = GAME_CP_GetTeamDef();
552 
553  /* Generate character stats, models & names. */
554  switch (type) {
555  case EMPL_SOLDIER:
556  rank = "rifleman";
557  Q_strncpyz(teamDefName, teamID, sizeof(teamDefName));
558  break;
559  case EMPL_SCIENTIST:
560  rank = "scientist";
561  Com_sprintf(teamDefName, sizeof(teamDefName), "%s_scientist", teamID);
562  break;
563  case EMPL_PILOT:
564  rank = "pilot";
565  Com_sprintf(teamDefName, sizeof(teamDefName), "%s_pilot", teamID);
566  break;
567  case EMPL_WORKER:
568  rank = "worker";
569  Com_sprintf(teamDefName, sizeof(teamDefName), "%s_worker", teamID);
570  break;
571  case EMPL_ROBOT:
572  if (ugvType == nullptr)
573  cgi->Com_Error(ERR_DROP, "E_CreateEmployee: no type given for generation of EMPL_ROBOT employee.");
574 
575  rank = "ugv";
576 
577  Com_sprintf(teamDefName, sizeof(teamDefName), "%s%s", teamID, ugvType->actors);
578  break;
579  default:
580  cgi->Com_Error(ERR_DROP, "E_CreateEmployee: Unknown employee type\n");
581  }
582 
583  cgi->CL_GenerateCharacter(&employee.chr, teamDefName);
584  employee.chr.score.rank = CL_GetRankIdx(rank);
585 
586  cgi->Com_DPrintf(DEBUG_CLIENT, "Generate character for type: %i\n", type);
587 
588  return &LIST_Add(&ccs.employees[type], employee);
589 }
590 
602 bool E_DeleteEmployee (Employee* employee)
603 {
605 
606  if (!employee)
607  return false;
608 
609  type = employee->getType();
610 
611  /* Fire the employee. This will also:
612  * 1) remove him from buildings&work
613  * 2) remove his inventory */
614 
615  if (employee->baseHired) {
616  /* make sure that this employee is really unhired */
617  employee->transfer = false;
618  employee->unhire();
619  }
620 
621  /* Remove the employee from the global list. */
622  return cgi->LIST_Remove(&ccs.employees[type], (void*) employee);
623 }
624 
631 {
632  int i;
633 
634  for (i = EMPL_SOLDIER; i < MAX_EMPL; i++) {
636  E_Foreach(type, employee) {
637  if (base == nullptr || employee->isHiredInBase(base))
638  E_DeleteEmployee(employee);
639  }
640  }
641 }
642 
649 int E_CountHired (const base_t* const base, employeeType_t type)
650 {
651  int count = 0;
652 
653  E_Foreach(type, employee) {
654  if (!employee->isHired())
655  continue;
656  if (!base || employee->isHiredInBase(base))
657  count++;
658  }
659  return count;
660 }
661 
668 int E_CountHiredRobotByType (const base_t* const base, const ugv_t* ugvType)
669 {
670  int count = 0;
671 
672  E_Foreach(EMPL_ROBOT, employee) {
673  if (!employee->isHired())
674  continue;
675  if (employee->getUGV() == ugvType && (!base || employee->isHiredInBase(base)))
676  count++;
677  }
678  return count;
679 }
680 
681 
688 int E_CountAllHired (const base_t* const base, const bool peopleOnly)
689 {
690  if (!base)
691  return 0;
692 
693  int count = 0;
694  for (int i = 0; i < MAX_EMPL; i++) {
696  if (peopleOnly && i == EMPL_ROBOT)
697  continue;
698  count += E_CountHired(base, type);
699  }
700 
701  return count;
702 }
703 
710 {
711  int count = 0;
712 
713  E_Foreach(type, employee) {
714  if (!employee->isHired())
715  count++;
716  }
717  return count;
718 }
719 
725 int E_CountUnhiredRobotsByType (const ugv_t* ugvType)
726 {
727  int count = 0;
728 
729  E_Foreach(EMPL_ROBOT, employee) {
730  if (!employee->isHired() && employee->getUGV() == ugvType)
731  count++;
732  }
733  return count;
734 }
735 
741 int E_CountUnassigned (const base_t* const base, employeeType_t type)
742 {
743  if (!base)
744  return 0;
745 
746  int count = 0;
747  E_Foreach(type, employee) {
748  if (!employee->isHiredInBase(base))
749  continue;
750  if (!employee->isAssigned())
751  count++;
752  }
753  return count;
754 }
755 
759 void E_InitialEmployees (const campaign_t* campaign)
760 {
761  int i;
762 
763  /* setup initial employee count */
764  for (i = 0; i < campaign->soldiers; i++)
766  for (i = 0; i < campaign->scientists; i++)
768  for (i = 0; i < campaign->workers; i++)
770  for (i = 0; i < campaign->pilots; i++)
772  for (i = 0; i < campaign->ugvs; i++) {
774  if (frand() > 0.5)
776  else
778  }
779 }
780 
781 #ifdef DEBUG
782 
785 static void E_ListHired_f (void)
786 {
787  int i;
788 
789  for (i = 0; i < MAX_EMPL; i++) {
790  const employeeType_t emplType = (employeeType_t)i;
791  E_Foreach(emplType, employee) {
792  cgi->Com_Printf("Employee: %s (ucn: %i) %s at %s\n", E_GetEmployeeString(employee->getType(), 1), employee->chr.ucn,
793  employee->chr.name, employee->baseHired->name);
794  if (employee->getType() != emplType)
795  cgi->Com_Printf("Warning: EmployeeType mismatch: %i != %i\n", emplType, employee->getType());
796  }
797  }
798 }
799 
804 static void CL_DebugNewEmployees_f (void)
805 {
806  nation_t* nation = NAT_GetRandom();
807 
808  int j;
809  for (j = 0; j < 5; j++)
810  /* Create a scientist */
811  E_CreateEmployee(EMPL_SCIENTIST, nation, nullptr);
812 
813  for (j = 0; j < 5; j++)
814  /* Create a pilot. */
815  E_CreateEmployee(EMPL_PILOT, nation, nullptr);
816 
817  for (j = 0; j < 5; j++)
818  /* Create a soldier. */
819  E_CreateEmployee(EMPL_SOLDIER, nation, nullptr);
820 
821  for (j = 0; j < 5; j++)
822  /* Create a worker. */
823  E_CreateEmployee(EMPL_WORKER, nation, nullptr);
824 }
825 #endif
826 
833 {
834  E_Foreach(type, employee) {
835  if (employee->chr.ucn == uniqueCharacterNumber)
836  return employee;
837  }
838 
839  return nullptr;
840 }
841 
846 Employee* E_GetEmployeeFromChrUCN (int uniqueCharacterNumber)
847 {
848  int i;
849 
850  for (i = EMPL_SOLDIER; i < MAX_EMPL; i++) {
851  const employeeType_t emplType = (employeeType_t)i;
852  Employee* employee = E_GetEmployeeByTypeFromChrUCN(emplType, uniqueCharacterNumber);
853  if (employee)
854  return employee;
855  }
856 
857  return nullptr;
858 }
859 
860 
871 {
872  int i;
873 
874  cgi->Com_RegisterConstList(saveEmployeeConstants);
875  for (i = 0; i < MAX_EMPL; i++) {
876  const employeeType_t emplType = (employeeType_t)i;
878 
879  cgi->XML_AddString(snode, SAVE_EMPLOYEE_TYPE, cgi->Com_GetConstVariable(SAVE_EMPLOYEETYPE_NAMESPACE, emplType));
880  E_Foreach(emplType, employee) {
881  xmlNode_t* chrNode;
882  xmlNode_t* ssnode = cgi->XML_AddNode(snode, SAVE_EMPLOYEE_EMPLOYEE);
883 
885  if (employee->baseHired)
886  cgi->XML_AddInt(ssnode, SAVE_EMPLOYEE_BASEHIRED, employee->baseHired->idx);
887  if (employee->isAssigned())
888  cgi->XML_AddBool(ssnode, SAVE_EMPLOYEE_ASSIGNED, employee->isAssigned());
889  /* Store the nations identifier string. */
890  assert(employee->getNation());
891  cgi->XML_AddString(ssnode, SAVE_EMPLOYEE_NATION, employee->getNation()->id);
892  /* Store the ugv-type identifier string. (Only exists for EMPL_ROBOT). */
893  if (employee->getUGV())
894  cgi->XML_AddString(ssnode, SAVE_EMPLOYEE_UGV, employee->getUGV()->id);
895  /* Character Data */
896  chrNode = cgi->XML_AddNode(ssnode, SAVE_EMPLOYEE_CHR);
897  cgi->GAME_SaveCharacter(chrNode, &employee->chr);
898  }
899  }
900  cgi->Com_UnregisterConstList(saveEmployeeConstants);
901 
902  return true;
903 }
904 
910 {
911  xmlNode_t* snode;
912  bool success = true;
913  linkedList_t* lastEmployee[MAX_EMPL];
914 
915  OBJZERO(lastEmployee);
916  cgi->Com_RegisterConstList(saveEmployeeConstants);
917  for (snode = cgi->XML_GetNode(p, SAVE_EMPLOYEE_EMPLOYEES); snode;
918  snode = cgi->XML_GetNextNode(snode, p, SAVE_EMPLOYEE_EMPLOYEES)) {
919  xmlNode_t* ssnode;
920  employeeType_t emplType;
921  const char* type = cgi->XML_GetString(snode, SAVE_EMPLOYEE_TYPE);
922 
923  if (!cgi->Com_GetConstIntFromNamespace(SAVE_EMPLOYEETYPE_NAMESPACE, type, (int*) &emplType)) {
924  cgi->Com_Printf("Invalid employee type '%s'\n", type);
925  success = false;
926  break;
927  }
928 
929  for (ssnode = cgi->XML_GetNode(snode, SAVE_EMPLOYEE_EMPLOYEE); ssnode;
930  ssnode = cgi->XML_GetNextNode(ssnode, snode, SAVE_EMPLOYEE_EMPLOYEE)) {
931  int baseIDX;
932  xmlNode_t* chrNode;
933 
934  /* nation */
936  if (!nation) {
937  cgi->Com_Printf("No nation defined for employee\n");
938  success = false;
939  break;
940  }
941  /* UGV-Type */
943  Employee e(emplType, nation, ugv);
945  /* base */
946  assert(B_AtLeastOneExists()); /* Just in case the order is ever changed. */
947  baseIDX = cgi->XML_GetInt(ssnode, SAVE_EMPLOYEE_BASEHIRED, -1);
948  e.baseHired = B_GetBaseByIDX(baseIDX);
949  /* assigned to a building? */
950  e.setAssigned(cgi->XML_GetBool(ssnode, SAVE_EMPLOYEE_ASSIGNED, false));
951  /* Character Data */
952  chrNode = cgi->XML_GetNode(ssnode, SAVE_EMPLOYEE_CHR);
953  if (!chrNode) {
954  cgi->Com_Printf("No character definition found for employee\n");
955  success = false;
956  break;
957  }
958  if (!cgi->GAME_LoadCharacter(chrNode, &e.chr)) {
959  cgi->Com_Printf("Error loading character definition for employee\n");
960  success = false;
961  break;
962  }
963  if (lastEmployee[emplType] == nullptr)
964  lastEmployee[emplType] = LIST_Add(&ccs.employees[emplType], (void*) &e, sizeof(e));
965  else
966  lastEmployee[emplType] = LIST_Add(&lastEmployee[emplType], (void*) &e, sizeof(e));
967  if (lastEmployee[emplType] == nullptr) {
968  cgi->Com_Printf("Could not add employee to the game\n");
969  success = false;
970  break;
971  }
972  }
973  if (!success)
974  break;
975  }
976  cgi->Com_UnregisterConstList(saveEmployeeConstants);
977 
978  return success;
979 }
980 
985 bool E_HireAllowed (const base_t* base)
986 {
987  if (!B_IsUnderAttack(base) && B_GetBuildingStatus(base, B_QUARTERS))
988  return true;
989  return false;
990 }
991 
997 {
998  const character_t* chr = &employee->chr;
999 
1000  assert(employee->baseHired);
1001 
1002  const Container* cont = nullptr;
1003  while ((cont = chr->inv.getNextCont(cont))) {
1004  Item* item = nullptr;
1005  while ((item = cont->getNextItem(item))) {
1006  /* Remove ammo */
1007  if (item->ammoDef() && item->ammoDef() != item->def())
1008  B_AddToStorage(employee->baseHired, item->ammoDef(), -1);
1009  /* Remove Item */
1010  if (item->def())
1011  B_AddToStorage(employee->baseHired, item->def(), -1);
1012  }
1013  }
1014 }
1015 
1016 static const cmdList_t debugEmployeeCmds[] = {
1017 #ifdef DEBUG
1018  {"debug_listhired", E_ListHired_f, "Debug command to list all hired employee"},
1019  {"debug_addemployees", CL_DebugNewEmployees_f, "Debug function to add 5 new unhired employees of each type"},
1020 #endif
1021  {nullptr, nullptr, nullptr}
1022 };
1027 void E_InitStartup (void)
1028 {
1029  E_InitCallbacks();
1030  cgi->Cmd_TableAddList(debugEmployeeCmds);
1031 }
1032 
1036 void E_Shutdown (void)
1037 {
1038  for (int i = EMPL_SOLDIER; i < MAX_EMPL; i++) {
1039  const employeeType_t emplType = (employeeType_t)i;
1040  cgi->LIST_Delete(&ccs.employees[emplType]);
1041  }
1042 
1044  cgi->Cmd_TableRemoveList(debugEmployeeCmds);
1045 }
bool E_SaveXML(xmlNode_t *p)
Save callback for savegames in XML Format.
const objDef_t * def(void) const
Definition: inv_shared.h:469
xmlNode_t *IMPORT * XML_GetNode(xmlNode_t *parent, const char *name)
nation_t * NAT_GetNationByID(const char *nationID)
Return a nation-pointer by the nations id.
Definition: cp_nation.cpp:64
bool AIR_IsAircraftInBase(const aircraft_t *aircraft)
Checks whether given aircraft is in its homebase.
QGL_EXTERN GLint GLenum type
Definition: r_gl.h:94
bool B_GetBuildingStatus(const base_t *const base, const buildingType_t buildingType)
Get the status associated to a building.
Definition: cp_base.cpp:478
employeeType_t E_GetEmployeeType(const char *type)
Convert string to employeeType_t.
#define SAVE_EMPLOYEE_UGV
Definition: save_employee.h:34
nation_t * NAT_GetRandom(void)
Return a pointer to a random nation.
Definition: cp_nation.cpp:46
void setAssigned(bool assigned)
Definition: cp_employee.h:62
void E_ShutdownCallbacks(void)
Unregister UI callbacks.
bool E_HireEmployeeByType(base_t *base, employeeType_t type)
Hires the first free employee of that type.
A base with all it&#39;s data.
Definition: cp_base.h:84
int CL_GetRankIdx(const char *rankID)
Get the index of the given rankID in ccs.ranks array.
Definition: cp_rank.cpp:34
void CAP_AddCurrent(base_t *base, baseCapacities_t capacity, int value)
Changes the current (used) capacity on a base.
#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.
Employee * E_GetUnhired(employeeType_t type)
Iterates through unhired employees.
Definition: cp_employee.cpp:49
Header file for menu callback functions used for hire/fire employee menu.
#define _(String)
Definition: cl_shared.h:44
int E_CountAllHired(const base_t *const base, const bool peopleOnly)
Counts all hired employees of a given base.
const ugv_t *IMPORT * Com_GetUGVByID(const char *ugvID)
bool E_HireAllowed(const base_t *base)
Returns true if the current base is able to handle employees.
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition: shared.cpp:494
int B_AddToStorage(base_t *base, const objDef_t *obj, int amount)
Add/remove items to/from the storage.
Definition: cp_base.cpp:2576
#define B_IsUnderAttack(base)
Definition: cp_base.h:53
bool E_LoadXML(xmlNode_t *p)
Load callback for savegames in XML Format.
void E_InitCallbacks(void)
Register UI callbacks.
Describes a character with all its attributes.
Definition: chr_shared.h:388
bool AIR_RemoveEmployee(Employee *employee, aircraft_t *aircraft)
Removes a soldier from an aircraft.
Item * getNextItem(const Item *prev) const
Definition: inv_shared.cpp:671
#define B_AtLeastOneExists()
Definition: cp_base.h:55
void E_HireForBuilding(base_t *base, building_t *building, int num)
Hires some employees of appropriate type for a building.
employeeType_t getType() const
Definition: cp_employee.h:99
const objDef_t * ammoDef(void) const
Definition: inv_shared.h:460
rank_t * CL_GetRankByIdx(const int index)
Returns a rank at an index.
Definition: cp_rank.cpp:50
void E_Shutdown(void)
Closing actions for employee-subsystem.
Nation definition.
Definition: cp_nation.h:46
#define SAVE_EMPLOYEE_NATION
Definition: save_employee.h:33
bool isSoldier() const
Definition: cp_employee.h:82
int E_CountHired(const base_t *const base, employeeType_t type)
Counts hired employees of a given type in a given base.
bool E_HireRobot(base_t *base, const ugv_t *ugvType)
Hires the first free employee of that type.
int E_GetHiredEmployees(const base_t *const base, employeeType_t type, linkedList_t **hiredEmployees)
Return a list of hired employees in the given base of a given type.
int CAP_GetFreeCapacity(const base_t *base, baseCapacities_t capacityType)
Returns the free capacity of a type.
bool E_HireEmployee(base_t *base, Employee *employee)
Hires the employee in a base.
static const cmdList_t debugEmployeeCmds[]
#define SAVE_EMPLOYEE_EMPLOYEES
Definition: save_employee.h:27
bool isAssigned() const
Definition: cp_employee.h:58
#define xmlNode_t
Definition: xml.h:24
void AIR_RemovePilotFromAssignedAircraft(const base_t *base, const Employee *pilot)
Checks to see if the pilot is in any aircraft at this base. If he is then he is removed from that air...
bool E_DeleteEmployee(Employee *employee)
Removes the employee completely from the game (buildings + global list).
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition: shared.cpp:457
static const constListEntry_t saveEmployeeConstants[]
Definition: save_employee.h:38
void AIR_AutoAddPilotToAircraft(const base_t *base, Employee *pilot)
Adds the pilot to the first available aircraft at the specified base.
void unequip()
Removes the equipment from an employee.
#define ngettext(x, y, cnt)
Definition: g_local.h:40
const employeeType_t _type
Definition: cp_employee.h:42
#define ERR_DROP
Definition: common.h:211
#define DEBUG_CLIENT
Definition: defines.h:59
void RS_RemoveFiredScientist(base_t *base, Employee *employee)
Remove one scientist from research project if needed.
#define OBJZERO(obj)
Definition: shared.h:178
bool transfer
Definition: cp_employee.h:118
#define MAX_VAR
Definition: shared.h:36
int E_CountUnhiredRobotsByType(const ugv_t *ugvType)
Counts all available Robots/UGVs that are for sale.
#define SAVE_EMPLOYEE_ASSIGNED
Definition: save_employee.h:32
int E_CountByType(employeeType_t type)
Returns number of employees of a type.
Definition: cp_employee.cpp:39
void CP_Popup(const char *title, const char *text,...)
Wrapper around UI_Popup.
Definition: cp_popup.cpp:474
#define SAVE_EMPLOYEE_EMPLOYEE
Definition: save_employee.h:29
Employee * E_CreateEmployee(employeeType_t type, const nation_t *nation, const ugv_t *ugvType)
Creates an entry of a new employee in the global list and assignes it to no building/base.
bool unhire()
Fires an employee.
const char *IMPORT * XML_GetString(xmlNode_t *parent, const char *name)
bool E_MoveIntoNewBase(Employee *employee, base_t *newBase)
const cgame_import_t * cgi
Employee * E_GetAssignedEmployee(const base_t *const base, const employeeType_t type)
Gets an unassigned employee of a given type from the given base.
int base[MAX_EMPL]
Definition: cp_campaign.h:155
employeeType_t
The types of employees.
Definition: cp_employee.h:30
bool unassign()
Removes the employee from buildings and aircraft.
ccs_t ccs
Definition: cp_campaign.cpp:63
item instance data, with linked list capability
Definition: inv_shared.h:402
salary_t salaries
Definition: cp_campaign.h:196
base_t * B_GetBaseByIDX(int baseIdx)
Array bound check for the base index. Will also return unfounded bases as long as the index is in the...
Definition: cp_base.cpp:313
int scientists
Definition: cp_campaign.h:180
xmlNode_t *IMPORT * XML_GetNextNode(xmlNode_t *current, xmlNode_t *parent, const char *name)
const char * GAME_CP_GetTeamDef(void)
XML tag constants for savegame.
const Container * getNextCont(const Container *prev, bool inclTemp=false) const
Definition: inv_shared.cpp:722
void E_RemoveInventoryFromStorage(Employee *employee)
Removes the items of an employee (soldier) from the base storage (s)he is hired at.
bool isRobot() const
Definition: cp_employee.h:70
QGL_EXTERN GLuint count
Definition: r_gl.h:99
#define SAVE_EMPLOYEE_TYPE
Definition: save_employee.h:28
Employee * E_GetUnhiredRobot(const ugv_t *ugvType)
Return a "not hired" ugv-employee pointer of a given ugv-type.
CGAME_HARD_LINKED_FUNCTIONS linkedList_t * LIST_Add(linkedList_t **listDest, void const *data, size_t length)
void E_InitStartup(void)
This is more or less the initial Bind some of the functions in this file to console-commands that you...
Employee * E_GetHiredRobot(const base_t *const base, const ugv_t *ugvType)
Return a "hired" ugv-employee pointer of a given ugv-type in a given base.
int E_CountUnhired(employeeType_t type)
Counts unhired employees of a given type in a given base.
void E_UnhireAllEmployees(base_t *base, employeeType_t type)
Reset the hired flag for all employees of a given type in a given base.
campaign_t * curCampaign
Definition: cp_campaign.h:378
float frand(void)
Return random values between 0 and 1.
Definition: mathlib.cpp:506
QGL_EXTERN GLint i
Definition: r_gl.h:113
base_t * baseHired
Definition: cp_employee.h:117
#define SAVE_EMPLOYEE_CHR
Definition: save_employee.h:35
character_t chr
Definition: cp_employee.h:119
chrScoreGlobal_t score
Definition: chr_shared.h:406
bool isHired() const
Definition: cp_employee.h:86
Employee * E_GetEmployeeFromChrUCN(int uniqueCharacterNumber)
Searches all employee for the ucn (character id)
const char * E_GetEmployeeString(employeeType_t type, int n)
Convert employeeType_t to translated string.
#define SAVE_EMPLOYEE_BASEHIRED
Definition: save_employee.h:31
int level
Definition: cp_rank.h:40
int E_CountUnassigned(const base_t *const base, employeeType_t type)
Counts unassigned employees of a given type in a given base.
#define LIST_Foreach(list, type, var)
Iterates over a linked list, it&#39;s safe to delete the returned entry from the list while looping over ...
Definition: list.h:41
void E_InitialEmployees(const campaign_t *campaign)
Create initial hireable employees.
int maxEmployees
Definition: cp_building.h:108
buildingType_t buildingType
Definition: cp_building.h:110
Header file for single player campaign control.
void E_DeleteAllEmployees(base_t *base)
Removes all employees completely from the game (buildings + global list) from a given base...
const ugv_t *IMPORT * Com_GetUGVByIDSilent(const char *ugvID)
Employee * E_GetUnassignedEmployee(const base_t *const base, const employeeType_t type)
Gets an assigned employee of a given type from the given base.
xmlNode_t *IMPORT * XML_AddNode(xmlNode_t *parent, const char *name)
A building with all it&#39;s data.
Definition: cp_building.h:73
#define UGV_SIZE
Definition: cp_produce.h:33
#define Q_streq(a, b)
Definition: shared.h:136
#define SAVE_EMPLOYEETYPE_NAMESPACE
Definition: save_employee.h:37
#define AIR_Foreach(var)
iterates trough all aircraft
Definition: cp_aircraft.h:193
void PR_UpdateProductionCap(base_t *base, int workerChange)
Update the current capacity of Workshop.
Definition: cp_produce.cpp:607
Describes a rank that a recruit can gain.
Definition: cp_rank.h:29
const char *IMPORT * Com_GetConstVariable(const char *space, int value)
char actors[MAX_VAR]
Definition: chr_shared.h:251
bool isAwayFromBase() const
Tells you if a employee is away from his home base (gone in mission).
Definition: cp_employee.cpp:75
int E_CountHiredRobotByType(const base_t *const base, const ugv_t *ugvType)
Counts &#39;hired&#39; (i.e. bought or produced UGVs and other robots of a given ugv-type in a given base...
linkedList_t * employees[MAX_EMPL]
Definition: cp_campaign.h:273
Employee * E_GetEmployeeByTypeFromChrUCN(employeeType_t type, int uniqueCharacterNumber)
Searches employee from a type for the ucn (character id)
Defines a type of UGV/Robot.
Definition: chr_shared.h:245
int salary() const
Calculates the employee&#39;s actual salary.
Definition: cp_employee.cpp:63
bool isPilot() const
Definition: cp_employee.h:66
Definition: cmd.h:86
Inventory inv
Definition: chr_shared.h:411