OpenXcom  1.0
Open-source clone of the original X-Com
BattleUnitStatistics.h
1 #pragma once
2 /*
3 * Copyright 2010-2016 OpenXcom Developers.
4 *
5 * This file is part of OpenXcom.
6 *
7 * OpenXcom is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * OpenXcom is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with OpenXcom. If not, see <http://www.gnu.org/licenses/>.
19 */
20 #include <string>
21 #include <sstream>
22 #include <yaml-cpp/yaml.h>
23 #include "BattleUnit.h"
24 #include "../Engine/Language.h"
25 
26 namespace OpenXcom
27 {
28 
33 {
34  // Variables
35  std::string name;
36  std::string type, rank, race, weapon, weaponAmmo;
37  UnitFaction faction;
38  UnitStatus status;
39  int mission, turn, id;
40  UnitSide side;
41  UnitBodyPart bodypart;
42 
43  // Functions
46  {
47  return turn += mission * 300; // Maintains divisibility by 3 as well
48  }
49 
51  bool hostileTurn() const
52  {
53  if ((turn - 1) % 3 == 0) return true;
54  return false;
55  }
56 
58  void setTurn(int unitTurn, UnitFaction unitFaction)
59  {
60  turn = unitTurn * 3 + (int)unitFaction;
61  }
62 
64  void load(const YAML::Node &node)
65  {
66  if (const YAML::Node n = node["name"])
67  {
68  name = n.as<std::string>();
69  }
70  type = node["type"].as<std::string>(type);
71  rank = node["rank"].as<std::string>(rank);
72  race = node["race"].as<std::string>(race);
73  weapon = node["weapon"].as<std::string>(weapon);
74  weaponAmmo = node["weaponAmmo"].as<std::string>(weaponAmmo);
75  status = (UnitStatus)node["status"].as<int>();
76  faction = (UnitFaction)node["faction"].as<int>();
77  mission = node["mission"].as<int>(mission);
78  turn = node["turn"].as<int>(turn);
79  side = (UnitSide)node["side"].as<int>();
80  bodypart = (UnitBodyPart)node["bodypart"].as<int>();
81  id = node["id"].as<int>(id);
82  }
83 
85  YAML::Node save() const
86  {
87  YAML::Node node;
88  if (!name.empty())
89  node["name"] = name;
90  if (!type.empty())
91  node["type"] = type;
92  node["rank"] = rank;
93  node["race"] = race;
94  node["weapon"] = weapon;
95  node["weaponAmmo"] = weaponAmmo;
96  node["status"] = (int)status;
97  node["faction"] = (int)faction;
98  node["mission"] = mission;
99  node["turn"] = turn;
100  node["side"] = (int)side;
101  node["bodypart"] = (int)bodypart;
102  node["id"] = id;
103  return node;
104  }
105 
107  std::string getKillStatusString() const
108  {
109  switch (status)
110  {
111  case STATUS_DEAD: return "STR_KILLED";
112  case STATUS_UNCONSCIOUS: return "STR_STUNNED";
113  case STATUS_PANICKING: return "STR_PANICKED";
114  case STATUS_TURNING: return "STR_MINDCONTROLLED";
115  default: return "status error";
116  }
117  }
118 
120  std::string getUnitStatusString() const
121  {
122  switch (status)
123  {
124  case STATUS_DEAD: return "STATUS_DEAD";
125  case STATUS_UNCONSCIOUS: return "STATUS_UNCONSCIOUS";
126  case STATUS_PANICKING: return "STATUS_PANICKING";
127  case STATUS_TURNING: return "STATUS_TURNING";
128  default: return "status error";
129  }
130  }
131 
133  std::string getUnitFactionString() const
134  {
135  switch (faction)
136  {
137  case FACTION_PLAYER: return "FACTION_PLAYER";
138  case FACTION_HOSTILE: return "FACTION_HOSTILE";
139  case FACTION_NEUTRAL: return "FACTION_NEUTRAL";
140  default: return "faction error";
141  }
142  }
143 
145  std::string getUnitSideString() const
146  {
147  switch (side)
148  {
149  case SIDE_FRONT: return "SIDE_FRONT";
150  case SIDE_LEFT: return "SIDE_LEFT";
151  case SIDE_RIGHT: return "SIDE_RIGHT";
152  case SIDE_REAR: return "SIDE_REAR";
153  case SIDE_UNDER: return "SIDE_UNDER";
154  default: return "side error";
155  }
156  }
157 
159  std::string getUnitBodyPartString() const
160  {
161  switch (bodypart)
162  {
163  case BODYPART_HEAD: return "BODYPART_HEAD";
164  case BODYPART_TORSO: return "BODYPART_TORSO";
165  case BODYPART_RIGHTARM: return "BODYPART_RIGHTARM";
166  case BODYPART_LEFTARM: return "BODYPART_LEFTARM";
167  case BODYPART_RIGHTLEG: return "BODYPART_RIGHTLEG";
168  case BODYPART_LEFTLEG: return "BODYPART_LEFTLEG";
169  default: return "body part error";
170  }
171  }
172 
174  std::string getUnitName(Language *lang) const
175  {
176  if (!name.empty())
177  {
178  return name;
179  }
180  else if (!type.empty())
181  {
182  return lang->getString(type);
183  }
184  else
185  {
186  std::ostringstream ss;
187  ss << lang->getString(race) << " " << lang->getString(rank);
188  return ss.str();
189  }
190  }
191 
194  {
195  name = "";
196  type = "";
197  if (unit->getGeoscapeSoldier())
198  {
199  name = unit->getGeoscapeSoldier()->getName();
200  }
201  else
202  {
203  type = unit->getType();
204  }
205 
206  if (unit->getOriginalFaction() == FACTION_PLAYER)
207  {
208  // Soldiers
209  if (unit->getGeoscapeSoldier())
210  {
211  if (!unit->getGeoscapeSoldier()->getRankString().empty())
212  {
213  rank = unit->getGeoscapeSoldier()->getRankString();
214  }
215  else
216  {
217  rank = "STR_SOLDIER";
218  }
219  if (unit->getUnitRules() != 0 && !unit->getUnitRules()->getRace().empty())
220  {
221  race = unit->getUnitRules()->getRace();
222  }
223  else
224  {
225  race = "STR_FRIENDLY";
226  }
227  }
228  // HWPs
229  else
230  {
231  if (unit->getUnitRules() != 0 && !unit->getUnitRules()->getRank().empty())
232  {
233  rank = unit->getUnitRules()->getRank();
234  }
235  else
236  {
237  rank = "STR_HWPS";
238  }
239  if (unit->getUnitRules() != 0 && !unit->getUnitRules()->getRace().empty())
240  {
241  race = unit->getUnitRules()->getRace();
242  }
243  else
244  {
245  race = "STR_FRIENDLY";
246  }
247  }
248  }
249  // Aliens
250  else if (unit->getOriginalFaction() == FACTION_HOSTILE)
251  {
252  if (unit->getUnitRules() != 0 && !unit->getUnitRules()->getRank().empty())
253  {
254  rank = unit->getUnitRules()->getRank();
255  }
256  else
257  {
258  rank = "STR_LIVE_SOLDIER";
259  }
260  if (unit->getUnitRules() != 0 && !unit->getUnitRules()->getRace().empty())
261  {
262  race = unit->getUnitRules()->getRace();
263  }
264  else
265  {
266  race = "STR_HOSTILE";
267  }
268  }
269  // Civilians
270  else if (unit->getOriginalFaction() == FACTION_NEUTRAL)
271  {
272  if (unit->getUnitRules() != 0 && !unit->getUnitRules()->getRank().empty())
273  {
274  rank = unit->getUnitRules()->getRank();
275  }
276  else
277  {
278  rank = "STR_CIVILIAN";
279  }
280  if (unit->getUnitRules() != 0 && !unit->getUnitRules()->getRace().empty())
281  {
282  race = unit->getUnitRules()->getRace();
283  }
284  else
285  {
286  race = "STR_NEUTRAL";
287  }
288  }
289  // Error
290  else
291  {
292  rank = "STR_UNKNOWN";
293  race = "STR_UNKNOWN";
294  }
295  }
296 
297  BattleUnitKills(const YAML::Node& node) { load(node); }
298  BattleUnitKills(): faction(FACTION_HOSTILE), status(STATUS_IGNORE_ME), mission(0), turn(0), id(0), side(SIDE_FRONT), bodypart(BODYPART_HEAD) { }
299  ~BattleUnitKills() { }
300 };
301 
306 {
307  // Variables
314  bool ironMan;
319  std::vector<BattleUnitKills*> kills;
321  bool KIA;
322  bool nikeCross;
323  bool mercyCross;
331  bool MIA;
332  int martyr;
334 
335  // Functions
337  bool duplicateEntry(UnitStatus status, int id) const
338  {
339  for (std::vector<BattleUnitKills*>::const_iterator i = kills.begin(); i != kills.end(); ++i)
340  {
341  if ((*i)->id == id && (*i)->status == status)
342  {
343  return true;
344  }
345  }
346  return false;
347  }
348 
350  bool hasFriendlyFired() const
351  {
352  for (std::vector<BattleUnitKills*>::const_iterator i = kills.begin(); i != kills.end(); ++i)
353  {
354  if ((*i)->faction == FACTION_PLAYER)
355  return true;
356  }
357  return false;
358  }
359 
361  void load(const YAML::Node& node)
362  {
363  wasUnconcious = node["wasUnconcious"].as<bool>(wasUnconcious);
364  if (const YAML::Node &YAMLkills = node["kills"])
365  {
366  for (YAML::const_iterator i = YAMLkills.begin(); i != YAMLkills.end(); ++i)
367  kills.push_back(new BattleUnitKills(*i));
368  }
369  shotAtCounter = node["shotAtCounter"].as<int>(shotAtCounter);
370  hitCounter = node["hitCounter"].as<int>(hitCounter);
371  shotByFriendlyCounter = node["shotByFriendlyCounter"].as<int>(shotByFriendlyCounter);
372  shotFriendlyCounter = node["shotFriendlyCounter"].as<int>(shotFriendlyCounter);
373  loneSurvivor = node["loneSurvivor"].as<bool>(loneSurvivor);
374  ironMan = node["ironMan"].as<bool>(ironMan);
375  longDistanceHitCounter = node["longDistanceHitCounter"].as<int>(longDistanceHitCounter);
376  lowAccuracyHitCounter = node["lowAccuracyHitCounter"].as<int>(lowAccuracyHitCounter);
377  shotsFiredCounter = node["shotsFiredCounter"].as<int>(shotsFiredCounter);
378  shotsLandedCounter = node["shotsLandedCounter"].as<int>(shotsLandedCounter);
379  nikeCross = node["nikeCross"].as<bool>(nikeCross);
380  mercyCross = node["mercyCross"].as<bool>(mercyCross);
381  woundsHealed = node["woundsHealed"].as<int>(woundsHealed);
382  appliedStimulant = node["appliedStimulant"].as<int>(appliedStimulant);
383  appliedPainKill = node["appliedPainKill"].as<int>(appliedPainKill);
384  revivedSoldier = node["revivedSoldier"].as<int>(revivedSoldier);
385  revivedHostile = node["revivedHostile"].as<int>(revivedHostile);
386  revivedNeutral = node["revivedNeutral"].as<int>(revivedNeutral);
387  martyr = node["martyr"].as<int>(martyr);
388  slaveKills = node["slaveKills"].as<int>(slaveKills);
389  }
390 
392  YAML::Node save() const
393  {
394  YAML::Node node;
395  node["wasUnconcious"] = wasUnconcious;
396  if (!kills.empty())
397  {
398  for (std::vector<BattleUnitKills*>::const_iterator i = kills.begin(); i != kills.end(); ++i)
399  node["kills"].push_back((*i)->save());
400  }
401  if (shotAtCounter) node["shotAtCounter"] = shotAtCounter;
402  if (hitCounter) node["hitCounter"] = hitCounter;
403  if (shotByFriendlyCounter) node["shotByFriendlyCounter"] = shotByFriendlyCounter;
404  if (shotFriendlyCounter) node["shotFriendlyCounter"] = shotFriendlyCounter;
405  if (loneSurvivor) node["loneSurvivor"] = loneSurvivor;
406  if (ironMan) node["ironMan"] = ironMan;
407  if (longDistanceHitCounter) node["longDistanceHitCounter"] = longDistanceHitCounter;
408  if (lowAccuracyHitCounter) node["lowAccuracyHitCounter"] = lowAccuracyHitCounter;
409  if (shotsFiredCounter) node["shotsFiredCounter"] = shotsFiredCounter;
410  if (shotsLandedCounter) node["shotsLandedCounter"] = shotsLandedCounter;
411  if (nikeCross) node["nikeCross"] = nikeCross;
412  if (mercyCross) node["mercyCross"] = mercyCross;
413  if (woundsHealed) node["woundsHealed"] = woundsHealed;
414  if (appliedStimulant) node["appliedStimulant"] = appliedStimulant;
415  if (appliedPainKill) node["appliedPainKill"] = appliedPainKill;
416  if (revivedSoldier) node["revivedSoldier"] = revivedSoldier;
417  if (revivedHostile) node["revivedHostile"] = revivedHostile;
418  if (revivedNeutral) node["revivedNeutral"] = revivedNeutral;
419  if (martyr) node["martyr"] = martyr;
420  if (slaveKills) node["slaveKills"] = slaveKills;
421  return node;
422  }
423 
424  BattleUnitStatistics(const YAML::Node& node) { load(node); }
426  ~BattleUnitStatistics() { }
427 };
428 
429 }
std::string getName(bool statstring=false, unsigned int maxLength=20) const
Gets the soldier&#39;s name.
Definition: Soldier.cpp:200
YAML::Node save() const
Save.
Definition: BattleUnitStatistics.h:85
std::string getKillStatusString() const
Convert kill Status to string.
Definition: BattleUnitStatistics.h:107
YAML::Node save() const
Save function.
Definition: BattleUnitStatistics.h:392
std::string getUnitStatusString() const
Convert victim Status to string.
Definition: BattleUnitStatistics.h:120
std::string getRace() const
Gets the alien race type.
Definition: Unit.cpp:160
int longDistanceHitCounter
Tracks how many long distance shots were landed.
Definition: BattleUnitStatistics.h:315
bool hostileTurn() const
Check to see if turn was on HOSTILE side.
Definition: BattleUnitStatistics.h:51
std::vector< BattleUnitKills * > kills
Tracks kills.
Definition: BattleUnitStatistics.h:319
int revivedNeutral
Tracks how many times this soldier revived another civilian.
Definition: BattleUnitStatistics.h:330
int slaveKills
Tracks how many kills the soldier landed thanks to a mind controlled unit.
Definition: BattleUnitStatistics.h:333
void load(const YAML::Node &node)
Load function.
Definition: BattleUnitStatistics.h:361
Soldier * getGeoscapeSoldier() const
Get the geoscape-soldier object.
Definition: BattleUnit.cpp:2617
void setTurn(int unitTurn, UnitFaction unitFaction)
Make turn unique across mission.
Definition: BattleUnitStatistics.h:58
int shotAtCounter
Tracks how many times the unit was shot at.
Definition: BattleUnitStatistics.h:309
int appliedPainKill
Tracks how many times this soldier applied pain killers.
Definition: BattleUnitStatistics.h:327
int lowAccuracyHitCounter
Tracks how many times the unit landed a low probability shot.
Definition: BattleUnitStatistics.h:316
Container for battle unit kills statistics.
Definition: BattleUnitStatistics.h:32
bool MIA
Tracks if the soldier was left behind :(.
Definition: BattleUnitStatistics.h:331
UnitFaction getOriginalFaction() const
Get this unit&#39;s original faction.
Definition: BattleUnit.cpp:2779
bool loneSurvivor
Tracks if the soldier was the only survivor.
Definition: BattleUnitStatistics.h:313
Contains strings used throughout the game for localization.
Definition: Language.h:39
int hitCounter
Tracks how many times the unit was hit.
Definition: BattleUnitStatistics.h:310
bool nikeCross
Tracks if a soldier killed every alien or killed and stunned every alien.
Definition: BattleUnitStatistics.h:322
int martyr
Tracks how many kills the soldier landed on the turn of his death.
Definition: BattleUnitStatistics.h:332
int shotsFiredCounter
Tracks how many times a unit has shot.
Definition: BattleUnitStatistics.h:317
std::string getType() const
Get unit type.
Definition: BattleUnit.cpp:2634
const LocalizedText & getString(const std::string &id) const
Get a localized text.
Definition: Language.cpp:275
int makeTurnUnique()
Make turn unique across all kills.
Definition: BattleUnitStatistics.h:45
std::string getUnitName(Language *lang) const
Get human-readable victim name.
Definition: BattleUnitStatistics.h:174
bool KIA
Tracks if the soldier was killed in battle.
Definition: BattleUnitStatistics.h:321
void setUnitStats(BattleUnit *unit)
Decide victim name, race and rank.
Definition: BattleUnitStatistics.h:193
UnitStats delta
Tracks the increase in unit stats (is not saved, only used during debriefing)
Definition: BattleUnitStatistics.h:325
std::string getUnitSideString() const
Convert victim Side to string.
Definition: BattleUnitStatistics.h:145
bool mercyCross
Tracks if a soldier stunned every alien.
Definition: BattleUnitStatistics.h:323
std::string getRankString() const
Gets a string version of the soldier&#39;s rank.
Definition: Soldier.cpp:276
This struct holds some plain unit attribute data together.
Definition: Unit.h:30
int appliedStimulant
Tracks how many times this soldier applied stimulant.
Definition: BattleUnitStatistics.h:326
int shotByFriendlyCounter
Tracks how many times the unit was hit by a friendly.
Definition: BattleUnitStatistics.h:311
int daysWounded
Tracks how many days the unit was wounded for.
Definition: BattleUnitStatistics.h:320
int shotFriendlyCounter
Tracks how many times the unit was hit a friendly.
Definition: BattleUnitStatistics.h:312
bool wasUnconcious
Tracks if the soldier fell unconcious.
Definition: BattleUnitStatistics.h:308
void load(const YAML::Node &node)
Load.
Definition: BattleUnitStatistics.h:64
std::string getRank() const
Gets the alien rank.
Definition: Unit.cpp:169
Container for battle unit statistics.
Definition: BattleUnitStatistics.h:305
std::string getUnitBodyPartString() const
Convert victim Body part to string.
Definition: BattleUnitStatistics.h:159
bool duplicateEntry(UnitStatus status, int id) const
Duplicate entry check.
Definition: BattleUnitStatistics.h:337
int revivedHostile
Tracks how many times this soldier revived another hostile.
Definition: BattleUnitStatistics.h:329
bool ironMan
Tracks if the soldier was the only soldier on the mission.
Definition: BattleUnitStatistics.h:314
int shotsLandedCounter
Tracks how many times a unit has hit his target.
Definition: BattleUnitStatistics.h:318
Represents a moving unit in the battlescape, player controlled or AI controlled it holds info about i...
Definition: BattleUnit.h:59
Definition: BaseInfoState.cpp:40
int revivedSoldier
Tracks how many times this soldier revived another soldier.
Definition: BattleUnitStatistics.h:328
std::string getUnitFactionString() const
Convert victim Faction to string.
Definition: BattleUnitStatistics.h:133
int woundsHealed
Tracks how many times a fatal wound was healed by this unit.
Definition: BattleUnitStatistics.h:324
bool hasFriendlyFired() const
Friendly fire check.
Definition: BattleUnitStatistics.h:350