UFO: Alien Invasion
cp_employee.cpp
Go to the documentation of this file.
1 
7 /*
8 Copyright (C) 2002-2022 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.
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
Item * getNextItem(const Item *prev) const
Definition: inv_shared.cpp:671
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 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
const employeeType_t _type
Definition: cp_employee.h:42
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
const objDef_t * ammoDef(void) const
Definition: inv_shared.h:460
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.
character_t chr
Definition: cp_employee.h:119
#define B_AtLeastOneExists()
Definition: cp_base.h:55
bool isHired() const
Definition: cp_employee.h:86
void E_HireForBuilding(base_t *base, building_t *building, int num)
Hires some employees of appropriate type for a building.
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
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.
bool isAwayFromBase() const
Tells you if a employee is away from his home base (gone in mission).
Definition: cp_employee.cpp:75
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
#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...
item instance data, with linked list capability
Definition: inv_shared.h:402
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.
#define ngettext(x, y, cnt)
Definition: g_local.h:40
#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
employeeType_t getType() const
Definition: cp_employee.h:99
#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.
const char *IMPORT * XML_GetString(xmlNode_t *parent, const char *name)
bool E_MoveIntoNewBase(Employee *employee, base_t *newBase)
const cgame_import_t * cgi
int salary() const
Calculates the employee&#39;s actual salary.
Definition: cp_employee.cpp:63
Employee * E_GetAssignedEmployee(const base_t *const base, const employeeType_t type)
Gets an unassigned employee of a given type from the given base.
base_t * baseHired
Definition: cp_employee.h:117
int base[MAX_EMPL]
Definition: cp_campaign.h:155
void setAssigned(bool assigned)
Definition: cp_employee.h:62
employeeType_t
The types of employees.
Definition: cp_employee.h:30
bool isSoldier() const
Definition: cp_employee.h:82
ccs_t ccs
Definition: cp_campaign.cpp:63
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.
void E_RemoveInventoryFromStorage(Employee *employee)
Removes the items of an employee (soldier) from the base storage (s)he is hired at.
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.
bool unassign()
Removes the employee from buildings and aircraft.
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
bool isAssigned() const
Definition: cp_employee.h:58
#define SAVE_EMPLOYEE_CHR
Definition: save_employee.h:35
bool isRobot() const
Definition: cp_employee.h:70
bool unhire()
Fires an employee.
chrScoreGlobal_t score
Definition: chr_shared.h:406
Definition: cmd.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
const Container * getNextCont(const Container *prev, bool inclTemp=false) const
Definition: inv_shared.cpp:722
#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
bool isPilot() const
Definition: cp_employee.h:66
const objDef_t * def(void) const
Definition: inv_shared.h:469
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
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
bool transfer
Definition: cp_employee.h:118
void unequip()
Removes the equipment from an employee.
Inventory inv
Definition: chr_shared.h:411