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