1 /**
2  * @file
3  */
4 
5 /*
6 Copyright (C) 2002-2013 UFO: Alien Invasion.
7 
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 
17 See the GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22 
23 */
24 
25 #pragma once
26 
27 typedef enum {
28 	KILLED_ENEMIES,		/**< Killed enemies */
29 	KILLED_CIVILIANS,	/**< Civilians, animals */
30 	KILLED_TEAM,		/**< Friendly fire, own team, partner-teams. */
31 
32 	KILLED_NUM_TYPES
33 } killtypes_t;
34 
35 /** @note Changing order/entries also changes network-transmission and savegames! */
36 typedef enum {
37 	ABILITY_POWER,
38 	ABILITY_SPEED,
39 	ABILITY_ACCURACY,
40 	ABILITY_MIND,
41 
42 	SKILL_CLOSE,
43 	SKILL_HEAVY,
44 	SKILL_ASSAULT,
45 	SKILL_SNIPER,
46 	SKILL_EXPLOSIVE,
47 	/* Pilot skills */
48 	SKILL_PILOTING,
49 	SKILL_TARGETING,
50 	SKILL_EVADING,
51 	SKILL_NUM_TYPES
52 } abilityskills_t;
53 
54 #define ABILITY_NUM_TYPES SKILL_CLOSE
55 
56 typedef struct chrTemplate_s {
57 	char id[MAX_VAR];					/** short name of the template */
58 	float rate;							/**< rate of this template relative to total */
59 	int skills[SKILL_NUM_TYPES + 1][2];	/** ability and skill min and max */
60 } chrTemplate_t;
61 
62 /**
63  * @brief Structure of all stats collected in a mission.
64  * @note More general Info: http://ufoai.org/wiki/index.php/Proposals/Attribute_Increase
65  * @note Mostly collected in g_client.c and not used anywhere else (at least that's the plan ;)).
66  * The result is parsed into chrScoreGlobal_t which is stored in savegames.
67  * @note BTAxis about "hit" count:
68  * "But yeah, what we want is a counter per skill. This counter should start at 0
69  * every battle, and then be increased by 1 everytime:
70  * - a direct fire weapon hits (or deals damage, same thing) the actor the weapon
71  *   was fired at. If it wasn't fired at an actor, nothing should happen.
72  * - a splash weapon deals damage to any enemy actor. If multiple actors are hit,
73  *   increase the counter multiple times."
74  */
75 typedef struct chrScoreMission_s {
76 	/* Movement counts. */
77 	int movedNormal;
78 	int movedCrouched;
79 
80 	/* Kills & stuns */
81 	/** @todo use existing code */
82 	int kills[KILLED_NUM_TYPES];	/**< Count of kills (aliens, civilians, teammates) */
83 	int stuns[KILLED_NUM_TYPES];	/**< Count of stuns (aliens, civilians, teammates) */
84 
85 	/* Hits/Misses */
86 	int fired[SKILL_NUM_TYPES];					/**< Count of fired "firemodes" (i.e. the count of how many times the soldier started shooting) */
87 	int firedTUs[SKILL_NUM_TYPES];				/**< Count of TUs used for the fired "firemodes". (direct hits only)*/
88 	bool firedHit[KILLED_NUM_TYPES];			/** Temporarily used for shot-stats calculations and status-tracking. Not used in stats.*/
89 	int hits[SKILL_NUM_TYPES][KILLED_NUM_TYPES];	/**< Count of hits (aliens, civilians or, teammates) per skill.
90 													 * It is a sub-count of "fired".
91 													 * It's planned to be increased by 1 for each series of shots that dealt _some_ damage. */
92 	int firedSplash[SKILL_NUM_TYPES];				/**< Count of fired splash "firemodes". */
93 	int firedSplashTUs[SKILL_NUM_TYPES];			/**< Count of TUs used for the fired "firemodes" (splash damage only). */
94 	bool firedSplashHit[KILLED_NUM_TYPES];			/** Same as firedHit but for Splash damage. */
95 	int hitsSplash[SKILL_NUM_TYPES][KILLED_NUM_TYPES];			/**< Count of splash hits. */
96 	int hitsSplashDamage[SKILL_NUM_TYPES][KILLED_NUM_TYPES];	/**< Count of dealt splash damage (aliens, civilians or, teammates).
97 																 * This is counted in overall damage (healthpoint).*/
98 	/** @todo Check HEALING of others. */
99 	int skillKills[SKILL_NUM_TYPES];	/**< Number of kills related to each skill. */
100 
101 	int heal;				/**< How many hitpoints has this soldier received trough healing in battlescape. */
102 	float carriedWeight;	/**< The weight this soldier carried during combat */
103 
chrScoreMission_schrScoreMission_s104 	inline chrScoreMission_s () {
105 		init();
106 	}
initchrScoreMission_s107 	inline void init () {
108 		OBJZERO(*this);
109 	}
110 } chrScoreMission_t;
111 
112 /**
113  * @brief Structure of all stats collected for an actor over time.
114  * @note More general Info: http://ufoai.org/wiki/index.php/Proposals/Attribute_Increase
115  * @note This information is stored in savegames (in contract to chrScoreMission_t).
116  * @note WARNING: if you change something here you'll have to make sure all the network and savegame stuff is updated as well!
117  * Additionally you have to check the size of the network-transfer in G_SendCharacterData and GAME_CP_Results
118  */
119 typedef struct chrScoreGlobal_s {
120 	int experience[SKILL_NUM_TYPES + 1];	/**< Array of experience values for all skills, and health. @todo What are the mins and maxs for these values */
121 
122 	int skills[SKILL_NUM_TYPES];			/**< Array of skills and abilities. This is the total value. */
123 	int initialSkills[SKILL_NUM_TYPES + 1];	/**< Array of initial skills and abilities. This is the value generated at character generation time. */
124 
125 	/* Kills & Stuns */
126 	int kills[KILLED_NUM_TYPES];	/**< Count of kills (aliens, civilians, teammates) */
127 	int stuns[KILLED_NUM_TYPES];	/**< Count of stuns(aliens, civilians, teammates) */
128 
129 	int assignedMissions;			/**< Number of missions this soldier was assigned to. */
130 
131 	int rank;						/**< Index of rank (in ccs.ranks). */
132 
chrScoreGlobal_schrScoreGlobal_s133 	inline chrScoreGlobal_s () {
134 		OBJZERO(*this);
135 	}
136 } chrScoreGlobal_t;
137 
138 class FiremodeSettings {
139 	actorHands_t _hand;		/**< the used hand, an enum */
140 	fireDefIndex_t _fmIdx;	/**< Stores the used firemode index. Max. number is MAX_FIREDEFS_PER_WEAPON -1=undef*/
141 	const objDef_t* _weapon;
142 
143 public:
144 
FiremodeSettings()145 	inline FiremodeSettings () {
146 		OBJZERO(*this);
147 	}
isSaneFiremode()148 	inline bool isSaneFiremode () const {
149 		return _hand > ACTOR_HAND_NOT_SET && _fmIdx >= 0 && _fmIdx < MAX_FIREDEFS_PER_WEAPON && _weapon != nullptr;
150 	}
151 
getFmIdx()152 	inline int getFmIdx () const {
153 		return _fmIdx;
154 	}
155 
getWeapon()156 	inline const objDef_t* getWeapon () const {
157 		return _weapon;
158 	}
159 
getHand()160 	inline actorHands_t getHand () const {
161 		return _hand;
162 	}
163 
setHand(const actorHands_t hand)164 	inline void setHand (const actorHands_t hand) {
165 		_hand = hand;
166 	}
167 
set(const actorHands_t hand,const fireDefIndex_t fmIdx,const objDef_t * weapon)168 	inline void set (const actorHands_t hand, const fireDefIndex_t fmIdx, const objDef_t* weapon) {
169 		_hand = hand;
170 		_fmIdx = fmIdx;
171 		_weapon = weapon;
172 	}
173 };
174 
175 /**
176  * @brief How many TUs (and of what type) did a player reserve for a unit?
177  * @sa CL_ActorUsableTUs
178  * @sa CL_ActorReservedTUs
179  * @sa CL_ActorReserveTUs
180  */
181 typedef struct chrReservations_s {
182 	/* Reaction fire reservation (for current turn and next enemy turn) */
183 	int reaction;	/**< Did the player activate RF with a usable firemode?
184 					 * (And at the same time storing the TU-costs of this firemode) */
185 
186 	/* Crouch reservation (for current turn)	*/
187 	int crouch;	/**< Did the player reserve TUs for crouching (or standing up)? Depends exclusively on TU_CROUCH. */
188 
189 	/* Shot reservation (for current turn) */
190 	int shot;	/**< If non-zero we reserved a shot in this turn. */
191 	FiremodeSettings shotSettings;	/**< Stores what type of firemode & weapon
192 									 * (and hand) was used for "shot" reservation. */
193 
chrReservations_schrReservations_s194 	inline chrReservations_s () {
195 		reaction = crouch = shot = 0;
196 	}
197 } chrReservations_t;
198 
199 typedef enum {
200 	RES_REACTION,
201 	RES_CROUCH,
202 	RES_SHOT,
203 	RES_ALL,
204 	RES_ALL_ACTIVE,
205 	RES_TYPES /**< Max. */
206 } reservation_types_t;
207 
208 /** @brief Types of actor sounds being issued by CL_ActorPlaySound(). */
209 typedef enum {
210 	SND_DEATH,	/**< Sound being played on actor death. */
211 	SND_HURT,	/**< Sound being played when an actor is being hit. */
212 
213 	SND_MAX
214 } actorSound_t;
215 
216 /* team definitions */
217 
218 #define MAX_UGV					8
219 #define MAX_TEAMDEFS			64
220 #define MAX_CHARACTER_TEMPLATES	24
221 #define MAX_TEMPLATES_PER_TEAM	16
222 
223 typedef enum {
224 	NAME_NEUTRAL,
225 	NAME_FEMALE,
226 	NAME_MALE,
227 
228 	NAME_LAST,
229 	NAME_FEMALE_LAST,
230 	NAME_MALE_LAST,
231 
232 	NAME_NUM_TYPES
233 } nametypes_t;
234 
235 /** @brief Defines a type of UGV/Robot */
236 typedef struct ugv_s {
237 	char* id;
238 	int idx;
239 	char weapon[MAX_VAR];
240 	char armour[MAX_VAR];
241 	int tu;
242 	char actors[MAX_VAR];
243 	int price;
244 } ugv_t;
245 
246 enum modifier_types_t {
247 	 MODIFIER_ACCURACY,		/**< Modifier to accuracy */
248 	 MODIFIER_SHOOTING,		/**< Modifier to shooting */
249 	 MODIFIER_MOVEMENT,		/**< Modifier to movement */
250 	 MODIFIER_SIGHT,		/**< Modifier to LoS range */
251 	 MODIFIER_REACTION,		/**< Modifier to reactions */
252 	 MODIFIER_TU,			/**< Modifier to TUs */
253 
254 	 MODIFIER_MAX
255 };
256 
257 #define BODYPART_MAXTYPE 4
258 
259 class BodyPartData {
260 public:
261 	char id[MAX_TEXPATH];
262 	char name[MAX_TEXPATH];
263 	int penalties[MODIFIER_MAX];
264 	vec4_t shape;
265 	int bleedingFactor;
266 	int woundThreshold;
267 };
268 
269 class BodyData {
270 private:
271 	char _id[MAX_TEXPATH];
272 	BodyPartData _bodyParts[BODYPART_MAXTYPE];
273 	float _totalBodyArea;
274 	short _numBodyParts;
275 
276 public:
277 	BodyData(void);
278 	const char* id(void) const;
279 	const char* id(const short bodyPart) const;
280 	const char* name(const short bodyPart) const;
281 	float penalty(const short bodyPart, const modifier_types_t type) const;
282 	float bleedingFactor(const short bodyPart) const;
283 	float woundThreshold(const short bodyPart) const;
284 	short getRandomBodyPart(void) const;
285 	short numBodyParts (void) const;
286 	void setId(const char* id);
287 	void addBodyPart(const BodyPartData &bodyPart);
288 	short getHitBodyPart(const byte direction, const float height) const;
289 	float getArea(const short bodyPart) const;
290 };
291 
292 typedef struct teamNames_s {
293 	char id[MAX_VAR];						/**< id from script file. */
294 	linkedList_t* names[NAME_NUM_TYPES];	/**< Names list per gender. */
295 	int numNames[NAME_NUM_TYPES];			/**< Amount of names in this list for all different genders. */
296 } teamNames_t;
297 
298 typedef struct teamDef_s {
299 	int idx;			/**< The index in the teamDef array. */
300 	char id[MAX_VAR];	/**< id from script file. */
301 	char name[MAX_VAR];	/**< Translatable name. */
302 	char tech[MAX_VAR];	/**< technology_t id from research.ufo */
303 	char footstepSound[MAX_VAR];
304 
305 	linkedList_t* const *names;	/**< Names list per gender. */
306 	const int* numNames;	/**< Amount of names in this list for all different genders. */
307 
308 	struct model_t {
309 		char* path;
310 		char* body;
311 		char* head;
312 		int   bodySkin;
313 		int   headSkin;
314 	};
315 
316 	linkedList_t* models[NAME_LAST];	/**< Models list per gender. */
317 	int numModels[NAME_LAST];	/**< Amount of models in this list for all different genders. */
318 
319 	linkedList_t* sounds[SND_MAX][NAME_LAST];	/**< Sounds list per gender and per sound type. */
320 	int numSounds[SND_MAX][NAME_LAST];	/**< Amount of sounds in this list for all different genders and soundtypes. */
321 
322 	int team;	/**< What is the race of this team? */
323 
324 	bool robot;
325 	bool armour;	/**< Does this team use armour. */
326 	bool weapons;	/**< Does this team use weapons. */
327 	const objDef_t* onlyWeapon;	/**< ods[] index - If this team is not able to use 'normal' weapons, we have to assign a weapon to it
328 							 * The default value is NONE for every 'normal' actor - but e.g. bloodspiders only have
329 							 * the ability to melee attack their victims. They get a weapon assigned with several
330 							 * bloodspider melee attack firedefinitions */
331 
332 	actorSizeEnum_t size;	/**< What size is this unit on the field (1=1x1 or 2=2x2)? */
333 	char hitParticle[MAX_VAR]; /**< Particle id of what particle effect should be spawned if a unit of this type is hit. */
334 	char deathTextureName[MAX_VAR];	/**< texture name for death of any member of this team */
335 
336 	short resistance[MAX_DAMAGETYPES]; /**< Resistance to damage */
337 
338 	const chrTemplate_t* characterTemplates[MAX_TEMPLATES_PER_TEAM];
339 	int numTemplates;
340 
341 	const BodyData* bodyTemplate;
342 
343 //	can't add this simple constructor because in scripts.cpp, teamDefValues 'offsetof' is used on teamdef_t
344 //	inline teamDef_s () {
345 //		OBJZERO(*this);
346 //	}
347 } teamDef_t;
348 
349 /** @brief Info on a wound */
350 typedef struct woundInfo_s {
351 	int woundLevel[BODYPART_MAXTYPE];
352 	int treatmentLevel[BODYPART_MAXTYPE];
353 
woundInfo_swoundInfo_s354 	inline woundInfo_s () {
355 		OBJZERO(*this);
356 	}
357 } woundInfo_t;
358 
359 #define MAX_CHARACTER_IMPLANTS 4
360 typedef struct implant_s {
361 	const implantDef_t* def;	/**< if @c null, the slot is still empty */
362 	int installedTime;	/**< the remaining days until the implant is ready */
363 	int removedTime;	/**< the remaining days until the removal is ready */
364 	int trigger;
365 } implant_t;
366 
367 /** @brief Describes a character with all its attributes */
368 typedef struct character_s {
369 	int ucn;					/**< unique character number */
370 	char name[MAX_VAR];			/**< Character name (as in: soldier name). */
371 	char path[MAX_VAR];
372 	char body[MAX_VAR];
373 	char head[MAX_VAR];
374 	int bodySkin;				/**< Index of skin. */
375 	int headSkin;				/**< Index of skin. */
376 
377 	int HP;						/**< Health points (current ones). */
378 	int minHP;					/**< Minimum hp during combat */
379 	int maxHP;					/**< Maximum health points (as in: 100% == fully healed). */
380 	int STUN;
381 	int morale;
382 	woundInfo_t wounds;			/**< Character wounds */
383 
384 	int state;					/**< a character can request some initial states when the team is spawned (like reaction fire) */
385 
386 	chrScoreGlobal_t score;		/**< Array of scores/stats the soldier/unit collected over time. */
387 	chrScoreMission_t* scoreMission;	/**< Array of scores/stats the soldier/unit collected in a mission - only used in battlescape (server side). Otherwise it's nullptr. */
388 
389 	actorSizeEnum_t fieldSize;
390 
391 	Inventory inv;				/**< the inventory */
392 
393 	const teamDef_t* teamDef;		/**< Pointer to team definition. */
394 	int gender;						/**< Gender index. */
395 	chrReservations_t reservedTus;	/**< Stores the reserved TUs for actions. @sa See chrReserveSettings_t for more. */
396 	FiremodeSettings RFmode;		/**< Stores the firemode to be used for reaction fire (if the fireDef allows that) */
397 
398 	implant_t implants[MAX_CHARACTER_IMPLANTS];
399 
400 	character_s();					/**< ctor */
401 	void init ();
402 } character_t;
403 
404 /* ================================ */
405 /*  CHARACTER GENERATING FUNCTIONS  */
406 /* ================================ */
407 
408 const chrTemplate_t* CHRSH_GetTemplateByID(const teamDef_t* teamDef, const char* templateId);
409 void CHRSH_CharGenAbilitySkills(character_t* chr, bool multiplayer, const char* templateId = "") __attribute__((nonnull));
410 const char* CHRSH_CharGetBody(const character_t* const chr) __attribute__((nonnull));
411 const char* CHRSH_CharGetHead(const character_t* const chr) __attribute__((nonnull));
412 bool CHRSH_IsTeamDefAlien(const teamDef_t* const td) __attribute__((nonnull));
413 bool CHRSH_IsTeamDefRobot(const teamDef_t* const td) __attribute__((nonnull));
414 bool CHRSH_IsArmourUseableForTeam(const objDef_t* od, const teamDef_t* teamDef);
415 const implant_t* CHRSH_ApplyImplant(character_t& chr, const implantDef_t& implant);
416 void CHRSH_UpdateImplants(character_t& chr);
417