UFO: Alien Invasion
Loading...
Searching...
No Matches
cp_research_callbacks.cpp
Go to the documentation of this file.
1
6
7/*
8Copyright (C) 2002-2025 UFO: Alien Invasion.
9
10This program is free software; you can redistribute it and/or
11modify it under the terms of the GNU General Public License
12as published by the Free Software Foundation; either version 2
13of the License, or (at your option) any later version.
14
15This program is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18
19See the GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License
22along with this program; if not, write to the Free Software
23Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24*/
25
26#include "../../cl_shared.h"
27#include "cp_campaign.h"
29#include "cp_base.h"
30
34static 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. */
47 technology_t* tech = RS_GetTechByID(cgi->Cmd_Argv(1));
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
75static 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 }
83 technology_t* tech = RS_GetTechByID(cgi->Cmd_Argv(1));
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
110static void RS_Stop_f (void)
111{
112 const base_t* base = B_GetCurrentSelectedBase();
113
114 if (cgi->Cmd_Argc() < 2) {
115 cgi->Com_Printf("Usage: %s <tech_id>\n", cgi->Cmd_Argv(0));
116 return;
117 }
118 technology_t* tech = RS_GetTechByID(cgi->Cmd_Argv(1));
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
141static 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
158static void RS_FillTechnologyList_f (void)
159{
161
162 if (!base)
163 return;
164
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++) {
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
214static 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
244static 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
255{
256 cgi->Cmd_TableAddList(research_commands);
257}
258
260{
261 cgi->Cmd_TableRemoveList(research_commands);
262}
Share stuff between the different cgame implementations.
#define _(String)
Definition cl_shared.h:44
bool isAssigned() const
Definition cp_employee.h:58
base_t * B_GetFoundedBaseByIDX(int baseIdx)
Array bound check for the base index.
Definition cp_base.cpp:326
base_t * B_GetCurrentSelectedBase(void)
returns the currently selected base
Definition cp_base.cpp:1578
Header for base management related stuff.
bool RS_ResearchAllowed(const base_t *base)
Returns true if the current base is able to handle research.
ccs_t ccs
Header file for single player campaign control.
const cgame_import_t * cgi
int CAP_GetFreeCapacity(const base_t *base, baseCapacities_t capacityType)
Returns the free capacity of a type.
@ CAP_LABSPACE
Definition cp_capacity.h:33
#define CAP_GetMax(base, capacity)
Definition cp_capacity.h:51
Employee * E_GetUnassignedEmployee(const base_t *const base, const employeeType_t type)
Gets an assigned employee of a given type from the given base.
int E_CountHired(const base_t *const base, employeeType_t type)
Counts hired employees of a given type in a given base.
int E_CountUnassigned(const base_t *const base, employeeType_t type)
Counts unassigned employees of a given type in a given base.
@ EMPL_SCIENTIST
Definition cp_employee.h:32
void RS_RemoveScientist(technology_t *tech, Employee *employee)
Remove a scientist from a technology.
technology_t * RS_GetTechByID(const char *id)
return a pointer to the technology identified by given id string
void RS_StopResearch(technology_t *tech)
Stops a research (Removes scientists from it).
void RS_AssignScientist(technology_t *tech, base_t *base, Employee *employee)
Assigns scientist to the selected research-project.
technology_t * RS_GetTechByIDX(int techIdx)
Returns the technology pointer for a tech index. You can use this instead of "&ccs....
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.
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 ...
@ RS_FINISH
Definition cp_research.h:44
@ RS_RUNNING
Definition cp_research.h:42
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.
void RS_ShutdownCallbacks(void)
static void RS_Change_f(void)
Script function to add and remove a scientist to the technology entry in the research-list.
static const cmdList_t research_commands[]
static void RS_ShowActiveResearch_f(void)
Show active research topics in Base sections.
static void RS_Max_f(void)
Assign as many scientists to the research project as possible.
void RS_InitCallbacks(void)
static void RS_GetDetails_f(void)
Shows research image/model and title on the research screen.
Header for menu related research stuff.
QGL_EXTERN GLint i
Definition r_gl.h:113
A base with all it's data.
Definition cp_base.h:84
This is the technology parsed from research.ufo.
researchStatus_t statusResearch
float overallTime
struct base_s * base
bool statusResearchable
bool statusCollected