]> git.localhorst.tv Git - l2e.git/blob - src/common/Capsule.cpp
6667068c3c8299dc11268faa889d4cba9a383a8e
[l2e.git] / src / common / Capsule.cpp
1 #include "Capsule.h"
2
3 #include "../common/Item.h"
4 #include "../common/Spell.h"
5 #include "../common/Stats.h"
6 #include "../graphics/Animation.h"
7 #include "../graphics/Sprite.h"
8 #include "../loader/Interpreter.h"
9 #include "../loader/TypeDescription.h"
10
11 #include <cassert>
12
13 using common::Spell;
14 using common::Stats;
15 using graphics::Animation;
16 using graphics::Sprite;
17 using loader::FieldDescription;
18 using loader::Interpreter;
19 using loader::TypeDescription;
20
21 namespace common {
22
23 Capsule::Capsule()
24 : name("")
25 , alignment("")
26
27 , alignmentSprite(0)
28
29 , maxHealth(0)
30
31 , level(1)
32 , experience(0)
33
34 , levelLadder(0)
35 , numLevels(0)
36
37 , classes(0)
38 , numClasses(0)
39 , curClass(-1)
40 , maxClass(0) {
41
42 }
43
44
45 const char *Capsule::ClassName() const {
46         return GetClass().name;
47 }
48
49 const char *Capsule::Tribe() const {
50         return GetClass().tribe;
51 }
52
53 const Spell *Capsule::Attack1() const {
54         return GetClass().attacks[0];
55 }
56
57 const Spell *Capsule::Attack2() const {
58         return GetClass().attacks[1];
59 }
60
61 const Spell *Capsule::Attack3() const {
62         return GetClass().attacks[2];
63 }
64
65
66 Uint16 Capsule::MaxHealth() const {
67         return maxHealth + GetClass().healthBoost;
68 }
69
70
71 Stats Capsule::GetStats() const {
72         return stats + GetClass().statBoost;
73 }
74
75 int Capsule::NextLevel() const {
76         int levelOffset(Level() - 1);
77         if (levelOffset < numLevels) {
78                 return levelLadder[levelOffset] - Experience();
79         } else {
80                 return 0;
81         }
82 }
83
84 void Capsule::UpgradeClass() {
85         ++maxClass;
86         ++curClass;
87 }
88
89 void Capsule::NextClass() {
90         if (maxClass == numClasses) {
91                 return;
92         }
93         ++curClass;
94         if (curClass >= maxClass) {
95                 curClass = 0;
96         }
97 }
98
99 void Capsule::PreviousClass() {
100         if (maxClass == numClasses) {
101                 return;
102         }
103         --curClass;
104         if (curClass < 0) {
105                 curClass = maxClass - 1;
106         }
107 }
108
109 void Capsule::SetClass(int index) {
110         if (maxClass == numClasses) {
111                 return;
112         }
113         curClass = index;
114         if (curClass < 0 ) {
115                 curClass = 0;
116         }
117         if (curClass >= maxClass) {
118                 curClass = maxClass - 1;
119         }
120 }
121
122
123 Sprite *Capsule::BattleSprite() {
124         return GetClass().battleSprite;
125 }
126
127 const Sprite *Capsule::BattleSprite() const {
128         return GetClass().battleSprite;
129 }
130
131 Animation *Capsule::MeleeAnimation() {
132         return GetClass().meleeAnimation;
133 }
134
135 Animation *Capsule::AttackAnimation() {
136         return GetClass().attackAnimation;
137 }
138
139 Animation *Capsule::SpellAnimation() {
140         return GetClass().spellAnimation;
141 }
142
143
144 Capsule::Class &Capsule::GetClass() {
145         assert(classes && curClass < numClasses);
146         return classes[curClass];
147 }
148
149 const Capsule::Class &Capsule::GetClass() const {
150         assert(classes && curClass < numClasses);
151         return classes[curClass];
152 }
153
154
155 int Capsule::HungerEmpty() const {
156         return HungerTotal() - HungerFull();
157 }
158
159 int Capsule::HungerTotal() const {
160         return GetClass().hunger;
161 }
162
163 int Capsule::HungerFull() const {
164         return GetClass().hungerFull;
165 }
166
167 bool Capsule::IsHungry() const {
168         return HungerEmpty();
169 }
170
171 void Capsule::Feed(const common::Item *item) {
172         // TODO: find out how to calculate an item's feed value
173         // TODO: an item the capsule favors (changes on every feed and after every
174         //       battle) doubles the value
175         int value = 1;
176         GetClass().hungerFull += value;
177         if (GetClass().hungerFull >= GetClass().hunger) {
178                 GetClass().hungerFull = GetClass().hunger;
179                 UpgradeClass();
180         }
181 }
182
183 const common::Item *Capsule::UpgradeItem() const {
184         return GetClass().upgradeItem;
185 }
186
187 void Capsule::UpgradeSpecial() {
188         maxClass = GetClass().upgradeClass + 1;
189         curClass = GetClass().upgradeClass;
190 }
191
192
193 Capsule::Class::Class()
194 : name(0)
195 , tribe(0)
196 , battleSprite(0)
197 , meleeAnimation(0)
198 , attackAnimation(0)
199 , spellAnimation(0)
200
201
202 , upgradeItem(0)
203 , upgradeClass(0)
204 , hunger(32)
205 , hungerFull(0)
206
207 , healthBoost(0) {
208         attacks[0] = 0;
209         attacks[1] = 0;
210         attacks[2] = 0;
211 }
212
213
214 void Capsule::CreateTypeDescription() {
215         Capsule c;
216
217         TypeDescription &td(TypeDescription::Create(TYPE_ID, "Capsule"));
218         td.SetConstructor(&Construct);
219         td.SetSize(sizeof(Capsule));
220
221         td.AddField("name", FieldDescription(((char *)&c.name) - ((char *)&c), Interpreter::STRING_ID).SetReferenced());
222         td.AddField("alignment", FieldDescription(((char *)&c.alignment) - ((char *)&c), Interpreter::STRING_ID).SetReferenced());
223
224         td.AddField("alignmentCursor", FieldDescription(((char *)&c.alignmentCursor) - ((char *)&c), Interpreter::VECTOR_ID));
225         td.AddField("alignmentSprite", FieldDescription(((char *)&c.alignmentSprite) - ((char *)&c), Sprite::TYPE_ID).SetReferenced());
226
227         td.AddField("maxHealth", FieldDescription(((char *)&c.maxHealth) - ((char *)&c), Interpreter::NUMBER_ID));
228
229         td.AddField("stats", FieldDescription(((char *)&c.stats) - ((char *)&c), Stats::TYPE_ID));
230
231         td.AddField("level", FieldDescription(((char *)&c.level) - ((char *)&c), Interpreter::NUMBER_ID));
232         td.AddField("experience", FieldDescription(((char *)&c.experience) - ((char *)&c), Interpreter::NUMBER_ID));
233
234         td.AddField("ladder", FieldDescription(((char *)&c.levelLadder) - ((char *)&c), Interpreter::NUMBER_ID).SetAggregate());
235
236         td.AddField("classes", FieldDescription(((char *)&c.classes) - ((char *)&c), Class::TYPE_ID).SetAggregate());
237         td.AddField("class", FieldDescription(((char *)&c.curClass) - ((char *)&c), Interpreter::NUMBER_ID));
238         td.AddField("maxClass", FieldDescription(((char *)&c.maxClass) - ((char *)&c), Interpreter::NUMBER_ID));
239
240         Class::CreateTypeDescription();
241 }
242
243 void Capsule::Construct(void *data) {
244         new (data) Capsule;
245 }
246
247
248 void Capsule::Class::CreateTypeDescription() {
249         Class c;
250
251         TypeDescription &td(TypeDescription::Create(TYPE_ID, "CapsuleClass"));
252         td.SetConstructor(&Construct);
253         td.SetSize(sizeof(Class));
254
255         td.AddField("name", FieldDescription(((char *)&c.name) - ((char *)&c), Interpreter::STRING_ID).SetReferenced());
256         td.AddField("tribe", FieldDescription(((char *)&c.tribe) - ((char *)&c), Interpreter::STRING_ID).SetReferenced());
257
258         td.AddField("attack1", FieldDescription(((char *)&c.attacks[0]) - ((char *)&c), Spell::TYPE_ID).SetReferenced());
259         td.AddField("attack2", FieldDescription(((char *)&c.attacks[1]) - ((char *)&c), Spell::TYPE_ID).SetReferenced());
260         td.AddField("attack3", FieldDescription(((char *)&c.attacks[2]) - ((char *)&c), Spell::TYPE_ID).SetReferenced());
261
262         td.AddField("battleSprite", FieldDescription(((char *)&c.battleSprite) - ((char *)&c), Sprite::TYPE_ID).SetReferenced());
263         td.AddField("meleeAnimation", FieldDescription(((char *)&c.meleeAnimation) - ((char *)&c), Animation::TYPE_ID).SetReferenced());
264         td.AddField("attackAnimation", FieldDescription(((char *)&c.attackAnimation) - ((char *)&c), Animation::TYPE_ID).SetReferenced());
265         td.AddField("spellAnimation", FieldDescription(((char *)&c.spellAnimation) - ((char *)&c), Animation::TYPE_ID).SetReferenced());
266
267         td.AddField("upgradeItem", FieldDescription(((char *)&c.upgradeItem) - ((char *)&c), common::Item::TYPE_ID).SetReferenced());
268         td.AddField("upgradeClass", FieldDescription(((char *)&c.upgradeClass) - ((char *)&c), Interpreter::NUMBER_ID));
269         td.AddField("hunger", FieldDescription(((char *)&c.hunger) - ((char *)&c), Interpreter::NUMBER_ID));
270
271         td.AddField("healthBoost", FieldDescription(((char *)&c.healthBoost) - ((char *)&c), Interpreter::NUMBER_ID));
272         td.AddField("statBoost", FieldDescription(((char *)&c.statBoost) - ((char *)&c), Stats::TYPE_ID));
273 }
274
275 void Capsule::Class::Construct(void *data) {
276         new (data) Capsule::Class;
277 }
278
279 }