1 /**
2  * @file
3  * @brief Header for research related stuff.
4  */
5 
6 /*
7 Copyright (C) 2002-2013 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 
26 #pragma once
27 
28 #define MAX_RESEARCHLIST 32
29 #define MAX_TECHNOLOGIES 256	/**< Maximum number of technologies overall. */
30 #define MAX_TECHLINKS 16	/**< Maximum number of requirements in a technology (i.e in requireAND and requireOR). */
31 #define MAX_DESCRIPTIONS 8	/**< Maximum number of descriptions (per tech and description-type). */
32 
33 #define TECH_INVALID -1	/**< The value for an "undef" tech-index. */
34 
35 #define ANTIMATTER_TECH_ID "antimatter"
36 
37 /** @brief The status of a research (per tech) */
38 typedef enum researchStatus_s {
39 	RS_NONE,
40 	RS_RUNNING,
41 	RS_PAUSED,
42 	RS_FINISH
43 } researchStatus_t;
44 
45 /** @brief Types of research topics */
46 typedef enum researchType_s {
47 	RS_TECH,
48 	RS_WEAPON,
49 	RS_ARMOUR,
50 	RS_CRAFT,
51 	RS_CRAFTITEM,
52 	RS_BUILDING,
53 	RS_ALIEN,
54 	RS_UGV,
55 	RS_NEWS,
56 	RS_LOGIC
57 } researchType_t;
58 
59 typedef enum requirementType_s {
60 	RS_LINK_TECH,
61 	RS_LINK_TECH_NOT,
62 	RS_LINK_ITEM,
63 	RS_LINK_ALIEN,
64 	RS_LINK_ALIEN_DEAD,
65 	RS_LINK_ALIEN_GLOBAL,
66 	RS_LINK_UFO,
67 	RS_LINK_ANTIMATTER,
68 	MAX_RS_LINKTYPES
69 } requirementType_t;
70 
71 typedef struct requirement_s {
72 	requirementType_t type;	/**< What type the requ. is: item (in store/quarantine), event, etc... */
73 	char* id;				/**< Dependency id (text-id) */
74 	union typelink_t {
75 		const struct technology_s* tech;
76 		const struct objDef_s* od;
77 		const struct teamDef_s* td;
78 		const struct aircraft_s* aircraft;
79 	} link;
80 	int amount;				/**< How many items are needed for research ... if any. (fix) */
81 	int collected;			/**< How many items have been collected. (varies) */
82 } requirement_t;
83 
84 typedef struct requirements_s {
85 	int numLinks;			/**< The number of requirements for this tech. */
86 	requirement_t links[MAX_TECHLINKS];
87 } requirements_t;
88 
89 /** @todo MAX_CAMPAIGNS is not defined unless cp_campaign.h is included before */
90 typedef struct markResearched_s {
91 	bool markOnly[MAX_CAMPAIGNS];
92 	char* campaign[MAX_CAMPAIGNS];
93 	int numDefinitions;
94 } markResearched_t;
95 
96 /** @brief Types for tech mail definitions - see tech->mail[] */
97 typedef enum {
98 	TECHMAIL_PRE,			/**< this is a mail_pre (proposal) definition */
99 	TECHMAIL_RESEARCHED,	/**< this is the mail definition (after research was completed) */
100 
101 	TECHMAIL_MAX
102 } techMailType_t;
103 
104 /**
105  * @brief available mails for a tech - mail and mail_pre in script files
106  * @sa eventMail_t
107  */
108 typedef struct techMail_s {
109 	char* from;				/**< sender (_mail_from_paul_navarre, _mail_from_dr_connor) */
110 	const char* to;			/**< recipient (_mail_to_base_commander) */
111 	const char* subject;	/**< mail subject line - if mail and mail_pre are available
112 								 * this will be filled with Proposal: (mail_pre) and Re: (mail)
113 								 * automatically */
114 	const char* date;		/**< date string, if empty use the date of research */
115 	const char* icon;		/**< name of an image file to display in the mail client */
116 	const char* model;		/**< model name of the sender */
117 	bool read;				/**< already read the mail? */
118 } techMail_t;
119 
120 typedef enum {
121 	MAILSENT_NONE,		/**< No mail sent yet. */
122 	MAILSENT_PROPOSAL,	/**< Mail for research proposal already send. */
123 	MAILSENT_FINISHED,	/**< Mail for finished research sent (and maybe the previous as well). */
124 
125 	MAILSENT_MAX
126 } mailSentType_t;
127 
128 typedef struct technologyDescriptions_s {
129 	int numDescriptions;	/**< The number of descriptions. */
130 	int usedDescription;	/**< The index of the first used description, so we do not get a different text each time it should be displayed. undef=-1
131 				 * @todo Check if we should set this in the function that updates the research_proposals? Currently it's only in RS_GetDescription. */
132 	char* text[MAX_DESCRIPTIONS];	/**< A list of descriptions (Short text-id to get the full text via gettext). */
133 	char* tech[MAX_DESCRIPTIONS];	/**< The technology to check (i.e. are its requirements met?) if this description should be displayed. */
134 } technologyDescriptions_t;
135 
136 /** @brief This is the technology parsed from research.ufo */
137 typedef struct technology_s {
138 	char* id;		/**< Short (unique) id/name. */
139 	int idx;		/**< Self-link in the global list */
140 	char* name;		/**< Full name of this technology. */
141 	technologyDescriptions_t description;		/**< Descriptions of researched item.  */
142 	technologyDescriptions_t preDescription;	/**< Descriptions of item before it's researched. */
143 	researchType_t type;			/**< Defines what type this tech-entry is an where to search for other information "tech", "weapon" etc... see research.ufo for more */
144 
145 	struct technology_s* redirect;	/**< Set this to the entry that is supposed to get displayed instead of this one.
146 									 * Mostly used for e.g ammo that doesn't need its own description but rather the one for the weapon. */
147 
148 	requirements_t requireAND;	/**< A list of requirements that ALL need to be met (= AND-related) See struct above. */
149 	requirements_t requireOR;	/**< A list of requirements where ANY need to be met (= OR-related) See struct above. */
150 	bool statusCollected;		/**< Did we loot any items of this tech?
151 								* This is updated from the info stored in the requireOR and requireAND lists.
152 								* @see RS_CheckCollected. */
153 
154 	char* provides;				/**< The item that this technology enables. */
155 
156 	float overallTime, time;	/**< The time that is needed to research this tech. (in days).
157 					 * "overallTime" stays always the same,
158 					 * "time" will be modified when it is under research.*/
159 	int delay;			/**< @todo Number in days the system should wait until the tech is available for research.
160 					 * Starting from the first time all other dependencies have been fulfilled and
161 					 * counting only if a day has passed and they still are met. */
162 
163 	researchStatus_t statusResearch;	/**< Current status of the research. */
164 	char* finishedResearchEvent;		/**< nullptr or string with scriptable commands that are executed after the tech was successfully researched */
165 	bool announce;			/**< if this is true the ufopedia will be opened on finishing the research */
166 
167 	struct base_s	*base;	/**< The base this tech is researched in. */
168 	int scientists;			/**< How many scientists (from "base") are researching this tech. */
169 
170 	char* image;			/**< Image to display in the Ufopedia and other menus for this tech.
171 							 * If not set in the .ufo file this is auto-set in RS_InitTree.
172 							 * @sa cl_research.c: RS_InitTree */
173 	char* mdl;				/**< Same as "image" but it's a 3d model.. */
174 
175 	bool statusResearchable;		/**< Is this item researchable? */
176 
177 	int produceTime;			/**< How many hours the production of this items runs. */
178 	mailSentType_t mailSent;	/**< Store if a Mail has been sent to the commander (player). */
179 	requirements_t requireForProduction;	/**< A list of items that are needed (and used up) on production of _this_ item.
180 						 * Only "item"-type is allowed.
181 						 * All requirements need to be fulfilled in order for _one_ item to be produced.
182 						 * This check is done for each item.*/
183 
184 	date_t preResearchedDate;	/**< Date for UFOpaedia. Research proposal. */
185 	date_t researchedDate;		/**< Date for UFOpaedia. Finished research. */
186 
187 	markResearched_t markResearched;	/**< Mark as researched at parsing state - but i only know the date if we already started a campaign. */
188 
189 	/* Pedia info */
190 	struct pediaChapter_s* upChapter;	/**< UFOpaedia chapter as stored in research.ufo. */
191 	struct technology_s* upPrev;		/**< Previous tech in pedia. */
192 	struct technology_s* upNext;		/**< Next tech in pedia. */
193 
194 	techMail_t mail[TECHMAIL_MAX];		/**< UFOpaedia mails. See techMailType_t for the different array-entries. */
195 	int numTechMails;					/**< Used to store which "mail" entry to display in pedia. if It's equal to TECHMAIL_MAX both mailtypes are available. */
196 
197 	struct technology_s* hashNext;
198 	struct technology_s* hashProvidedNext;
199 } technology_t;
200 
201 #define RS_Collected_(tech) ((tech)->statusCollected)
202 
203 void RS_InitStartup(void);
204 void RS_ResetTechs(void);
205 int RS_ResearchRun(void);
206 void RS_ParseTechnologies(const char* name, const char** text);
207 bool RS_IsResearched_idx(int techIdx);
208 bool RS_IsResearched_ptr(const technology_t* tech);
209 
210 technology_t* RS_GetTechForItem(const objDef_t* item);
211 technology_t* RS_GetTechForTeam(const teamDef_t* team);
212 void RS_AddObjectTechs(void);
213 void RS_RequiredLinksAssign(void);
214 void RS_InitTree(const struct campaign_s* campaign, bool load);
215 const char* RS_GetDescription(technologyDescriptions_t* desc);
216 void RS_MarkCollected(technology_t* tech) __attribute__((nonnull));
217 void RS_MarkResearchable(const struct base_s* base, bool init = false);
218 bool RS_MarkStoryLineEventResearched(const char* techID);
219 void RS_ResearchFinish(technology_t* tech);
220 void RS_StopResearch(technology_t* tech);
221 void RS_MarkOneResearchable(technology_t* tech);
222 
223 void RS_AssignScientist(technology_t* tech, struct base_s* base, Employee* employee = nullptr);
224 void RS_RemoveScientist(technology_t* tech, Employee* employee);
225 void RS_RemoveFiredScientist(struct base_s* base, Employee* employee);
226 void RS_RemoveScientistsExceedingCapacity(struct base_s* base);
227 
228 technology_t* RS_GetTechByID(const char* id);
229 technology_t* RS_GetTechByProvided(const char* idProvided);
230 technology_t* RS_GetTechByIDX(int tech_idx);
231 technology_t* RS_GetTechWithMostScientists(const struct base_s* base);
232 int RS_GetTechIdxByName(const char* name);
233 int RS_CountScientistsInBase(const struct base_s* base);
234 bool RS_ScriptSanityCheck(void);
235 
236 /* UFOpaedia function - but needs technology_t */
237 void UP_AircraftDescription(const technology_t* t);
238 void UP_UGVDescription(const struct ugv_s* ugvType);
239 
240 void RS_CheckRequirements(void);
241 bool RS_RequirementsMet(const technology_t* tech, const struct base_s* base);
242