]> git.localhorst.tv Git - l2e.git/blob - src/loader/Interpreter.cpp
interpretation of Heros and Monsters
[l2e.git] / src / loader / Interpreter.cpp
1 /*
2  * Interpreter.cpp
3  *
4  *  Created on: Aug 26, 2012
5  *      Author: holy
6  */
7
8 #include "Interpreter.h"
9
10 #include "ParsedSource.h"
11 #include "../battle/Hero.h"
12 #include "../battle/Monster.h"
13 #include "../graphics/ComplexAnimation.h"
14 #include "../graphics/SimpleAnimation.h"
15 #include "../graphics/Sprite.h"
16
17 using battle::Hero;
18 using battle::Monster;
19 using battle::Stats;
20 using graphics::Animation;
21 using graphics::ComplexAnimation;
22 using graphics::SimpleAnimation;
23 using graphics::Sprite;
24 using geometry::Vector;
25 using std::map;
26 using std::set;
27 using std::string;
28 using std::vector;
29
30 namespace loader {
31
32 void Interpreter::ReadSource() {
33         for (set<string>::const_iterator i(source.Exports().begin()), end(source.Exports().end()); i != end; ++i) {
34                 ReadDefinition(source.GetDefinition(*i));
35         }
36 }
37
38 void Interpreter::ReadDefinition(const Definition &dfn) {
39         if (parsedDefinitions.find(dfn.Identifier()) != parsedDefinitions.end()) {
40                 return;
41         }
42         if (dfn.HasLiteralValue()) {
43                 ReadLiteral(dfn);
44         } else {
45                 ReadObject(dfn);
46         }
47 }
48
49 void Interpreter::ReadLiteral(const Definition &dfn) {
50         switch (dfn.GetLiteral()->GetType()) {
51                 case Literal::ARRAY_VALUES:
52                         throw Error("unhandled literal: array of values");
53                         break;
54                 case Literal::ARRAY_PROPS:
55                         throw Error("unhandled literal: array of properties");
56                         break;
57                 case Literal::BOOLEAN:
58                         throw Error("unhandled literal: boolean");
59                         break;
60                 case Literal::COLOR:
61                         throw Error("unhandled literal: color");
62                         break;
63                 case Literal::NUMBER:
64                         numbers[dfn.Identifier()] = dfn.GetLiteral()->GetNumber();
65                         break;
66                 case Literal::STRING:
67                         throw Error("unhandled literal: string");
68                         break;
69                 case Literal::VECTOR:
70                         throw Error("unhandled literal: vector");
71                         break;
72                 case Literal::OBJECT:
73                         throw Error("unhandled literal: object");
74                         break;
75         }
76 }
77
78 Animation *Interpreter::GetAnimation(const Value &v) {
79         if (v.IsLiteral()) {
80                 if (v.GetLiteral().GetTypeName() == "ComplexAnimation") {
81                         ComplexAnimation *a(new ComplexAnimation);
82                         ReadComplexAnimation(*a, *v.GetLiteral().GetProperties());
83                         return a;
84                 } else {
85                         SimpleAnimation *a(new SimpleAnimation);
86                         ReadSimpleAnimation(*a, *v.GetLiteral().GetProperties());
87                         return a;
88                 }
89         } else if (animations.count(v.GetIdentifier())) {
90                 return animations[v.GetIdentifier()];
91         } else if (source.IsDefined(v.GetIdentifier())) {
92                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
93                 if (animations.count(v.GetIdentifier())) {
94                         return animations[v.GetIdentifier()];
95                 } else {
96                         throw Error("cannot use " + source.GetDefinition(v.GetIdentifier()).Identifier() + " " + v.GetIdentifier() + " as animation");
97                 }
98         } else {
99                 throw Error("use of undefined Animation " + v.GetIdentifier());
100         }
101 }
102
103 const vector<Value *> &Interpreter::GetValueArray(const Value &v) {
104         if (v.IsLiteral()) {
105                 return v.GetLiteral().GetValues();
106         } else {
107                 throw Error("identifier resolution not implemented for arrays of values");
108         }
109 }
110
111 const vector<PropertyList *> &Interpreter::GetPropertyListArray(const Value &v) {
112         if (v.IsLiteral()) {
113                 return v.GetLiteral().GetPropertyLists();
114         } else {
115                 throw Error("identifier resolution not implemented for arrays of property lists");
116         }
117 }
118
119 bool Interpreter::GetBoolean(const Value &v) {
120         if (v.IsLiteral()) {
121                 return v.GetLiteral().GetBoolean();
122         } else {
123                 throw Error("identifier resolution not implemented for booleans");
124         }
125 }
126
127 SDL_Surface *Interpreter::GetImage(const Value &v) {
128         if (v.IsLiteral()) {
129                 // TODO: image lookup
130                 return NULL;
131         } else {
132                 throw Error("identifier resolution not implemented for images");
133         }
134 }
135
136 int Interpreter::GetNumber(const Value &v) {
137         if (v.IsLiteral()) {
138                 return v.GetLiteral().GetNumber();
139         } else if (numbers.count(v.GetIdentifier())) {
140                 return numbers[v.GetIdentifier()];
141         } else {
142                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
143                 if (numbers.count(v.GetIdentifier())) {
144                         return numbers[v.GetIdentifier()];
145                 } else {
146                         throw Error("use of undefined Number " + v.GetIdentifier());
147                 }
148         }
149 }
150
151 const PropertyList *Interpreter::GetPropertyList(const Value &v) {
152         if (v.IsLiteral()) {
153                 return v.GetLiteral().GetProperties();
154         } else {
155                 throw Error("identifier resolution not implemented for property lists");
156         }
157 }
158
159 Sprite *Interpreter::GetSprite(const Value &v) {
160         if (v.IsLiteral()) {
161                 Sprite *s(new Sprite);
162                 ReadSprite(*s, *v.GetLiteral().GetProperties());
163                 return s;
164         } else if (sprites.count(v.GetIdentifier())) {
165                 return sprites[v.GetIdentifier()];
166         } else {
167                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
168                 if (sprites.count(v.GetIdentifier())) {
169                         return sprites[v.GetIdentifier()];
170                 } else {
171                         throw Error("use of undefined Sprite " + v.GetIdentifier());
172                 }
173         }
174 }
175
176 const char *Interpreter::GetString(const Value &v) {
177         if (v.IsLiteral()) {
178                 return v.GetLiteral().GetString().c_str();
179         } else {
180                 throw Error("identifier resolution not implemented for strings");
181         }
182 }
183
184 Vector<int> Interpreter::GetVector(const Value &v) {
185         if (v.IsLiteral()) {
186                 return Vector<int>(v.GetLiteral().GetX(), v.GetLiteral().GetY());
187         } else {
188                 throw Error("identifier resolution not implemented for vectors");
189         }
190 }
191
192
193 void Interpreter::ReadObject(const Definition &dfn) {
194         if (dfn.TypeName() == "Hero") {
195                 Hero *h(new Hero);
196                 ReadHero(*h, *dfn.GetProperties());
197                 heroes[dfn.Identifier()] = h;
198         } else if (dfn.TypeName() == "Monster") {
199                 Monster *m(new Monster);
200                 ReadMonster(*m, *dfn.GetProperties());
201                 monsters[dfn.Identifier()] = m;
202         } else if (dfn.TypeName() == "Sprite") {
203                 Sprite *s(new Sprite);
204                 ReadSprite(*s, *dfn.GetProperties());
205                 sprites[dfn.Identifier()] = s;
206         } else {
207                 throw Error("unhandled object: " + dfn.TypeName());
208         }
209 }
210
211
212 void Interpreter::ReadComplexAnimation(ComplexAnimation &a, const PropertyList &props) {
213         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
214                 if (i->first == "sprite") {
215                         a.SetSprite(GetSprite(*i->second));
216                 } else if (i->first == "frametime") {
217                         a.SetFrameTime(GetNumber(*i->second));
218                 } else if (i->first == "repeat") {
219                         a.SetRepeat(GetBoolean(*i->second));
220                 } else if (i->first == "frames") {
221                         const vector<PropertyList *> &values(GetPropertyListArray(*i->second));
222                         for (vector<PropertyList *>::const_iterator i(values.begin()), end(values.end()); i != end; ++i) {
223                                 ComplexAnimation::FrameProp frame;
224                                 ReadComplexAnimationFrame(frame, **i);
225                                 a.AddFrame(frame);
226                         }
227                 } else {
228                         throw Error("unknown ComplexAnimation property: " + i->first);
229                 }
230         }
231 }
232
233 void Interpreter::ReadComplexAnimationFrame(ComplexAnimation::FrameProp &f, const PropertyList &props) {
234         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
235                 if (i->first == "column") {
236                         f.col = GetNumber(*i->second);
237                 } else if (i->first == "row") {
238                         f.row = GetNumber(*i->second);
239                 } else if (i->first == "disposition") {
240                         f.disposition = GetVector(*i->second);
241                 } else {
242                         throw Error("unknown ComplexAnimationFrame property: " + i->first);
243                 }
244         }
245 }
246
247 void Interpreter::ReadHero(Hero &h, const PropertyList &props) {
248         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
249                 if (i->first == "name") {
250                         h.SetName(GetString(*i->second));
251                 } else if (i->first == "sprite") {
252                         h.SetSprite(GetSprite(*i->second));
253                 } else if (i->first == "level") {
254                         h.SetLevel(GetNumber(*i->second));
255                 } else if (i->first == "maxHealth") {
256                         h.SetMaxHealth(GetNumber(*i->second));
257                 } else if (i->first == "health") {
258                         h.SetHealth(GetNumber(*i->second));
259                 } else if (i->first == "maxMana") {
260                         h.SetMaxMana(GetNumber(*i->second));
261                 } else if (i->first == "mana") {
262                         h.SetMana(GetNumber(*i->second));
263                 } else if (i->first == "ip") {
264                         h.SetIP(GetNumber(*i->second));
265                 } else if (i->first == "stats") {
266                         battle::Stats stats;
267                         ReadStats(stats, *GetPropertyList(*i->second));
268                         h.SetStats(stats);
269                 } else if (i->first == "attackAnimation") {
270                         h.SetAttackAnimation(GetAnimation(*i->second));
271                 } else if (i->first == "spellAnimation") {
272                         h.SetSpellAnimation(GetAnimation(*i->second));
273                 } else if (i->first == "meleeAnimation") {
274                         h.SetMeleeAnimation(GetAnimation(*i->second));
275                 } else {
276                         throw Error("unknown Hero property: " + i->first);
277                 }
278         }
279 }
280
281 void Interpreter::ReadMonster(Monster &m, const PropertyList &props) {
282         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
283                 if (i->first == "name") {
284                         m.SetName(GetString(*i->second));
285                 } else if (i->first == "sprite") {
286                         m.SetSprite(GetSprite(*i->second));
287                 } else if (i->first == "level") {
288                         m.SetLevel(GetNumber(*i->second));
289                 } else if (i->first == "maxHealth") {
290                         m.SetMaxHealth(GetNumber(*i->second));
291                 } else if (i->first == "health") {
292                         m.SetHealth(GetNumber(*i->second));
293                 } else if (i->first == "maxMana") {
294                         m.SetMaxMana(GetNumber(*i->second));
295                 } else if (i->first == "mana") {
296                         m.SetMana(GetNumber(*i->second));
297                 } else if (i->first == "stats") {
298                         battle::Stats stats;
299                         ReadStats(stats, *GetPropertyList(*i->second));
300                         m.SetStats(stats);
301                 } else if (i->first == "attackAnimation") {
302                         m.SetAttackAnimation(GetAnimation(*i->second));
303                 } else {
304                         throw Error("unknown Monster property: " + i->first);
305                 }
306         }
307 }
308
309 void Interpreter::ReadSimpleAnimation(SimpleAnimation &a, const PropertyList &props) {
310         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
311                 if (i->first == "sprite") {
312                         a.SetSprite(GetSprite(*i->second));
313                 } else if (i->first == "frametime") {
314                         a.SetFrameTime(GetNumber(*i->second));
315                 } else if (i->first == "repeat") {
316                         a.SetRepeat(GetBoolean(*i->second));
317                 } else if (i->first == "framecount") {
318                         a.SetNumFrames(GetNumber(*i->second));
319                 } else if (i->first == "col") {
320                         a.SetCol(GetNumber(*i->second));
321                 } else if (i->first == "row") {
322                         a.SetRow(GetNumber(*i->second));
323                 } else {
324                         throw Error("unknown SimpleAnimation property: " + i->first);
325                 }
326         }
327 }
328
329 void Interpreter::ReadSprite(Sprite &s, const PropertyList &props) {
330         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
331                 if (i->first == "image") {
332                         s.SetSurface(GetImage(*i->second));
333                 } else if (i->first == "size") {
334                         s.SetSize(GetVector(*i->second));
335                 } else if (i->first == "offset") {
336                         s.SetOffset(GetVector(*i->second));
337                 } else {
338                         throw Error("unknown Sprite property: " + i->first);
339                 }
340         }
341 }
342
343 void Interpreter::ReadStats(Stats &s, const PropertyList &props) {
344         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
345                 if (i->first == "atp") {
346                         s.SetAttack(GetNumber(*i->second));
347                 } else if (i->first == "dfp") {
348                         s.SetDefense(GetNumber(*i->second));
349                 } else if (i->first == "str") {
350                         s.SetStrength(GetNumber(*i->second));
351                 } else if (i->first == "agl") {
352                         s.SetAgility(GetNumber(*i->second));
353                 } else if (i->first == "int") {
354                         s.SetIntelligence(GetNumber(*i->second));
355                 } else if (i->first == "gut") {
356                         s.SetGut(GetNumber(*i->second));
357                 } else if (i->first == "mgr") {
358                         s.SetMagicResistance(GetNumber(*i->second));
359                 } else {
360                         throw Error("unknown Stats property: " + i->first);
361                 }
362         }
363 }
364
365 }