UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
cp_research_callbacks.cpp
Go to the documentation of this file.
1 
7 /*
8 Copyright (C) 2002-2020 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 "cp_campaign.h"
28 #include "cp_research_callbacks.h"
29 #include "cp_base.h"
30 
34 static void RS_Max_f (void)
35 {
36  /* The base the tech is researched in. */
38 
39  if (!base)
40  return;
41 
42  if (cgi->Cmd_Argc() < 2) {
43  cgi->Com_Printf("Usage: %s <tech_id>\n", cgi->Cmd_Argv(0));
44  return;
45  }
46  /* The technology you want to max out. */
48  if (!tech) {
49  cgi->Com_Printf("RS_Max_f: Invalid tech '%s'\n", cgi->Cmd_Argv(1));
50  return;
51  }
52  if (tech->base && tech->base != base) {
53  cgi->Com_Printf("RS_Max_f: Tech '%s' is not researched in this base\n", cgi->Cmd_Argv(1));
54  return;
55  }
56 
57  /* Add as many scientists as possible to this tech. */
58  while (CAP_GetFreeCapacity(base, CAP_LABSPACE) > 0) {
60  if (!employee)
61  break;
62  RS_AssignScientist(tech, base, employee);
63  if (!employee->isAssigned())
64  break;
65  }
66 
67  cgi->UI_ExecuteConfunc("ui_research_update_topic %s %d", tech->id, tech->scientists);
68  cgi->UI_ExecuteConfunc("ui_research_update_caps %d %d %d %d", E_CountUnassigned(base, EMPL_SCIENTIST),
70 }
71 
75 static void RS_Change_f (void)
76 {
78 
79  if (cgi->Cmd_Argc() < 2) {
80  cgi->Com_Printf("Usage: %s <tech_id>\n", cgi->Cmd_Argv(0));
81  return;
82  }
84  if (!tech) {
85  cgi->Com_Printf("RS_ChangeScientist_f: Invalid tech '%s'\n", cgi->Cmd_Argv(1));
86  return;
87  }
88  if (tech->base && tech->base != base) {
89  cgi->Com_Printf("RS_ChangeScientist_f: Tech '%s' is not researched in this base\n", cgi->Cmd_Argv(1));
90  return;
91  }
92  const int diff = atoi(cgi->Cmd_Argv(2));
93  if (diff == 0)
94  return;
95 
96  if (diff > 0) {
97  RS_AssignScientist(tech, base);
98  } else if (tech->base) {
99  RS_RemoveScientist(tech, nullptr);
100  }
101 
102  cgi->UI_ExecuteConfunc("ui_research_update_topic %s %d", tech->id, tech->scientists);
103  cgi->UI_ExecuteConfunc("ui_research_update_caps %d %d %d %d", E_CountUnassigned(base, EMPL_SCIENTIST),
105 }
106 
110 static void RS_Stop_f (void)
111 {
113 
114  if (cgi->Cmd_Argc() < 2) {
115  cgi->Com_Printf("Usage: %s <tech_id>\n", cgi->Cmd_Argv(0));
116  return;
117  }
119  if (!tech) {
120  cgi->Com_Printf("RS_Stop_f: Invalid tech '%s'\n", cgi->Cmd_Argv(1));
121  return;
122  }
123  if (!tech->base) {
124  return;
125  }
126  if (tech->base != base) {
127  cgi->Com_Printf("RS_Stop_f: Tech '%s' is not researched in this base\n", cgi->Cmd_Argv(1));
128  return;
129  }
130 
131  RS_StopResearch(tech);
132 
133  cgi->UI_ExecuteConfunc("ui_research_update_topic %s %d", tech->id, tech->scientists);
134  cgi->UI_ExecuteConfunc("ui_research_update_caps %d %d %d %d", E_CountUnassigned(base, EMPL_SCIENTIST),
136 }
137 
141 static void RS_GetDetails_f (void)
142 {
143  if (cgi->Cmd_Argc() < 2) {
144  cgi->Com_Printf("Usage: %s <tech_id>\n", cgi->Cmd_Argv(0));
145  return;
146  }
147  const technology_t* tech = RS_GetTechByID(cgi->Cmd_Argv(1));
148  if (!tech) {
149  cgi->Com_Printf("RS_GetDetails_f: Invalid tech '%s'\n", cgi->Cmd_Argv(1));
150  return;
151  }
152  cgi->UI_ExecuteConfunc("ui_research_details \"%s\" \"%s\" \"%s\"", _(tech->name), tech->image ? tech->image : "", tech->mdl ? tech->mdl : "");
153 }
154 
158 static void RS_FillTechnologyList_f (void)
159 {
161 
162  if (!base)
163  return;
164 
165  RS_MarkResearchable(base);
166 
167  cgi->UI_ExecuteConfunc("ui_research_update_caps %d %d %d %d", E_CountUnassigned(base, EMPL_SCIENTIST),
169  cgi->UI_ExecuteConfunc("ui_techlist_clear");
170  for (int i = 0; i < ccs.numTechnologies; i++) {
171  technology_t* tech = RS_GetTechByIDX(i);
172  /* Don't show technologies with time == 0 - those are NOT separate research topics. */
173  if (tech->time == 0)
174  continue;
175  /* hide finished research */
176  if (tech->statusResearch == RS_FINISH)
177  continue;
178 
179  int percentage = 0;
180  if (tech->overallTime > 0.0) {
181  percentage = std::min(100, std::max(0, 100 - int(round(tech->time * 100.0 / tech->overallTime))));
182  }
183 
184  /* show researches that are running */
185  if (tech->base && tech->scientists > 0) {
186  if (tech->base == base) {
187  cgi->UI_ExecuteConfunc("ui_techlist_add %s \"%s\" %d %d %s %d \"%s\"",
188  tech->id, _(tech->name), tech->scientists, percentage, "", 0, "");
189  } else {
190  cgi->UI_ExecuteConfunc("ui_techlist_add %s \"%s\" %d %d base %d \"%s\"",
191  tech->id, _(tech->name), tech->scientists, percentage,
192  tech->base->idx, tech->base->name);
193  }
194  continue;
195  }
196  /* show topics that are researchable on this base */
197  const bool req = RS_RequirementsMet(tech, base);
198  if (tech->statusResearchable && req) {
199  cgi->UI_ExecuteConfunc("ui_techlist_add %s \"%s\" %d %d %s %d \"%s\"",
200  tech->id, _(tech->name), tech->scientists, percentage, "", 0, "");
201  continue;
202  }
203  if (tech->statusCollected && !req) {
204  cgi->UI_ExecuteConfunc("ui_techlist_add %s \"%s\" %d %d %s %d \"%s\"",
205  tech->id, _(tech->name), tech->scientists, percentage, "missing", 0, "");
206  continue;
207  }
208  }
209 }
210 
214 static void RS_ShowActiveResearch_f (void)
215 {
216  if (cgi->Cmd_Argc() < 2) {
217  cgi->Com_Printf("Usage: %s <base_idx>\n", cgi->Cmd_Argv(0));
218  return;
219  }
220  const base_t* const base = B_GetFoundedBaseByIDX(atoi(cgi->Cmd_Argv(1)));
221  if (base == nullptr) {
222  cgi->Com_Printf("PR_ShowActiveResearch_f: Invalid base_idx!\n");
223  return;
224  }
225  /* Get the production item closest to completion in the base if it exists */
226  if (!RS_ResearchAllowed(base))
227  return;
228 
229  for (int i = 0; i < ccs.numTechnologies; i++) {
230  const technology_t* tech = RS_GetTechByIDX(i);
231  if (!tech)
232  continue;
233  if (tech->base != base)
234  continue;
235  if (tech->statusResearch != RS_RUNNING)
236  continue;
237  if (tech->scientists <= 0)
238  continue;
239  const double completition = (1 - tech->time / tech->overallTime) * 100;
240  cgi->UI_ExecuteConfunc("show_research %s \"%s\" %i %3.0f", tech->id, tech->name, tech->scientists, completition);
241  }
242 }
243 
244 static const cmdList_t research_commands[] = {
245  {"ui_research_fill", RS_FillTechnologyList_f, "Fill research screen with list of researchable technologies"},
246  {"ui_research_getdetails", RS_GetDetails_f, "Show technology image/model in reseach screen"},
247  {"ui_research_stop", RS_Stop_f, "Stops the research"},
248  {"ui_research_change", RS_Change_f, "Change number of scientists working on the research"},
249  {"ui_research_max", RS_Max_f, "Allocates as many scientists on the research as possible"},
250  {"ui_research_show_active", RS_ShowActiveResearch_f, "Show the active research topics and their status"},
251  {nullptr, nullptr, nullptr}
252 };
253 
254 void RS_InitCallbacks (void)
255 {
256  cgi->Cmd_TableAddList(research_commands);
257 }
258 
260 {
261  cgi->Cmd_TableRemoveList(research_commands);
262 }
static void RS_Stop_f(void)
Removes all scientists from the selected research-list entry.
static void RS_FillTechnologyList_f(void)
Fills technology list on research UI.
technology_t * RS_GetTechByIDX(int techIdx)
Returns the technology pointer for a tech index. You can use this instead of "&ccs.technologies[techIdx]" to avoid having to check valid indices.
bool statusResearchable
Definition: cp_research.h:175
#define _(String)
Definition: cl_shared.h:43
Header for menu related research stuff.
researchStatus_t statusResearch
Definition: cp_research.h:163
char name[MAX_VAR]
Definition: cp_base.h:86
void RS_MarkResearchable(const base_t *base, bool init)
Marks all the techs that can be researched. Automatically researches 'free' techs such as ammo for a ...
static void RS_Change_f(void)
Script function to add and remove a scientist to the technology entry in the research-list.
base_t * B_GetCurrentSelectedBase(void)
returns the currently selected base
Definition: cp_base.cpp:1578
struct base_s * base
Definition: cp_research.h:167
bool RS_RequirementsMet(const technology_t *tech, const base_t *base)
Checks if all requirements of a tech have been met so that it becomes researchable.
static void RS_ShowActiveResearch_f(void)
Show active research topics in Base sections.
bool isAssigned() const
Definition: cp_employee.h:58
int E_CountHired(const base_t *const base, employeeType_t type)
Counts hired employees of a given type in a given base.
A base with all it's data.
Definition: cp_base.h:84
base_t * B_GetFoundedBaseByIDX(int baseIdx)
Array bound check for the base index.
Definition: cp_base.cpp:325
int CAP_GetFreeCapacity(const base_t *base, baseCapacities_t capacityType)
Returns the free capacity of a type.
static const cmdList_t research_commands[]
const cgame_import_t * cgi
int idx
Definition: cp_base.h:85
This is the technology parsed from research.ufo.
Definition: cp_research.h:137
int numTechnologies
Definition: cp_campaign.h:277
ccs_t ccs
Definition: cp_campaign.cpp:62
Definition: cmd.h:86
bool RS_ResearchAllowed(const base_t *base)
Returns true if the current base is able to handle research.
technology_t * RS_GetTechByID(const char *id)
return a pointer to the technology identified by given id string
#define CAP_GetMax(base, capacity)
Definition: cp_capacity.h:51
static void RS_Max_f(void)
Assign as many scientists to the research project as possible.
QGL_EXTERN GLint i
Definition: r_gl.h:113
void RS_InitCallbacks(void)
char * image
Definition: cp_research.h:170
void RS_StopResearch(technology_t *tech)
Stops a research (Removes scientists from it)
Definition: cp_research.cpp:93
bool statusCollected
Definition: cp_research.h:150
int E_CountUnassigned(const base_t *const base, employeeType_t type)
Counts unassigned employees of a given type in a given base.
Header file for single player campaign control.
Employee * E_GetUnassignedEmployee(const base_t *const base, const employeeType_t type)
Gets an assigned employee of a given type from the given base.
float overallTime
Definition: cp_research.h:156
void RS_AssignScientist(technology_t *tech, base_t *base, Employee *employee)
Assigns scientist to the selected research-project.
Header for base management related stuff.
const char *IMPORT * Cmd_Argv(int n)
static void RS_GetDetails_f(void)
Shows research image/model and title on the research screen.
void RS_RemoveScientist(technology_t *tech, Employee *employee)
Remove a scientist from a technology.
void RS_ShutdownCallbacks(void)