1 #pragma once
2 
3 #include "util.h"
4 #include "unique_entity.h"
5 #include "position.h"
6 #include "sound.h"
7 
8 #undef HUGE
9 
10 RICH_ENUM(BodyPart,
11   HEAD,
12   TORSO,
13   ARM,
14   WING,
15   LEG,
16   BACK
17 );
18 
19 extern const char* getName(BodyPart);
20 
21 class Attack;
22 struct AdjectiveInfo;
23 
24 class Body {
25   public:
26 
27   enum class Material {
28     FLESH,
29     SPIRIT,
30     FIRE,
31     WATER,
32     UNDEAD_FLESH,
33     BONE,
34     ROCK,
35     CLAY,
36     WOOD,
37     IRON,
38     LAVA,
39   };
40 
41   enum class Size {
42     SMALL,
43     MEDIUM,
44     LARGE,
45     HUGE
46   };
47 
48   static Body humanoid(Material, Size);
49   static Body humanoid(Size);
50   static Body nonHumanoid(Material, Size);
51   static Body nonHumanoid(Size);
52   static Body humanoidSpirit(Size);
53   static Body nonHumanoidSpirit(Size);
54   Body(bool humanoid, Material, Size);
55 
56   Body& addWings();
57   Body& setWeight(double);
58   Body& setBodyParts(const EnumMap<BodyPart, int>&);
59   Body& setHumanoidBodyParts();
60   Body& setHorseBodyParts();
61   Body& setBirdBodyParts();
62   Body& setMinionFood();
63   Body& setDeathSound(optional<SoundId>);
64   Body& setNoCarryLimit();
65   Body& setDoesntEat();
66 
67   void affectPosition(Position);
68 
69   bool takeDamage(const Attack&, WCreature, double damage);
70 
71   bool tick(WConstCreature);
72   bool heal(WCreature, double amount);
73   bool affectByFire(WCreature, double amount);
74   bool isIntrinsicallyAffected(LastingEffect) const;
75   bool affectByPoisonGas(WCreature, double amount);
76   void affectByTorture(WCreature);
77   bool affectBySilver(WCreature);
78   bool affectByAcid(WCreature);
79   bool isKilledByBoulder() const;
80   bool canWade() const;
81   bool isMinionFood() const;
82   bool canCopulateWith() const;
83   bool canConsume() const;
84   bool isWounded() const;
85   bool isSeriouslyWounded() const;
86   double getHealth() const;
87   bool hasBrain() const;
88   bool needsToEat() const;
89   vector<PItem> getCorpseItem(const string& name, UniqueEntity<Creature>::Id);
90 
91   vector<AttackLevel> getAttackLevels() const;
92   double modifyAttr(AttrType, double) const;
93 
94   bool isCollapsed(WConstCreature) const;
95   int numGood(BodyPart) const;
96   int numLost(BodyPart) const;
97   int numBodyParts(BodyPart) const;
98   void getBadAdjectives(vector<AdjectiveInfo>&) const;
99   optional<Sound> getDeathSound() const;
100   void injureBodyPart(WCreature, BodyPart, bool drop);
101 
102   void healBodyParts(WCreature, bool regrow);
103   int lostOrInjuredBodyParts() const;
104   bool canHeal() const;
105   bool isImmuneTo(LastingEffect effect) const;
106   bool hasHealth() const;
107 
108   void consumeBodyParts(WCreature, const Body& other, vector<string>& adjectives);
109 
110   bool isHumanoid() const;
111   string getDescription() const;
112   void updateViewObject(ViewObject&) const;
113   const optional<double>& getCarryLimit() const;
114   void bleed(WCreature, double amount);
115 
116   bool isUndead() const;
117   double getBoulderDamage() const;
118 
119   SERIALIZATION_DECL(Body);
120 
121   private:
122   friend class Test;
123   BodyPart getBodyPart(AttackLevel attack, bool flying, bool collapsed) const;
124   BodyPart armOrWing() const;
125   int numInjured(BodyPart) const;
126   void clearInjured(BodyPart);
127   void clearLost(BodyPart);
128   void looseBodyPart(BodyPart);
129   void injureBodyPart(BodyPart);
130   void decreaseHealth(double amount);
131   bool isPartDamaged(BodyPart, double damage) const;
132   bool isCritical(BodyPart) const;
133   PItem getBodyPartItem(const string& creatureName, BodyPart);
134   string getMaterialAndSizeAdjectives() const;
135   bool fallsApartFromDamage() const;
136   bool SERIAL(xhumanoid);
137   Size SERIAL(size);
138   double SERIAL(weight);
139   EnumMap<BodyPart, int> SERIAL(bodyParts) = {{BodyPart::TORSO, 1}, {BodyPart::BACK, 1}};
140   EnumMap<BodyPart, int> SERIAL(injuredBodyParts);
141   EnumMap<BodyPart, int> SERIAL(lostBodyParts);
142   Material SERIAL(material);
143   double SERIAL(health) = 1;
144   bool SERIAL(minionFood) = false;
145   optional<SoundId> SERIAL(deathSound);
146   optional<double> SERIAL(carryLimit);
147   bool SERIAL(doesntEat) = false;
148 };
149 
150