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