]> git.localhorst.tv Git - l2e.git/blob - src/loader/Interpreter.cpp
added Spell and TargetingMode interpretation
[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 "../battle/PartyLayout.h"
14 #include "../common/Spell.h"
15 #include "../common/TargetingMode.h"
16 #include "../graphics/ComplexAnimation.h"
17 #include "../graphics/Font.h"
18 #include "../graphics/Frame.h"
19 #include "../graphics/Gauge.h"
20 #include "../graphics/SimpleAnimation.h"
21 #include "../graphics/Sprite.h"
22
23 #include <algorithm>
24 #include <cstring>
25 #include <SDL_image.h>
26
27 using battle::Hero;
28 using battle::Monster;
29 using battle::PartyLayout;
30 using battle::Stats;
31 using common::Spell;
32 using common::TargetingMode;
33 using graphics::Animation;
34 using graphics::Font;
35 using graphics::Frame;
36 using graphics::Gauge;
37 using graphics::ComplexAnimation;
38 using graphics::SimpleAnimation;
39 using graphics::Sprite;
40 using geometry::Vector;
41 using std::make_pair;
42 using std::map;
43 using std::set;
44 using std::string;
45 using std::vector;
46
47 namespace loader {
48
49 Interpreter::~Interpreter() {
50         for (vector<ComplexAnimation *>::const_iterator i(complexAnimations.begin()), end(complexAnimations.end()); i != end; ++i) {
51                 delete *i;
52         }
53         for (vector<Hero *>::const_iterator i(heroes.begin()), end(heroes.end()); i != end; ++i) {
54                 delete *i;
55         }
56         for (vector<Font *>::const_iterator i(fonts.begin()), end(fonts.end()); i != end; ++i) {
57                 delete *i;
58         }
59         for (vector<Frame *>::const_iterator i(frames.begin()), end(frames.end()); i != end; ++i) {
60                 delete *i;
61         }
62         for (vector<Gauge *>::const_iterator i(gauges.begin()), end(gauges.end()); i != end; ++i) {
63                 delete *i;
64         }
65         for (vector<SDL_Surface *>::const_iterator i(images.begin()), end(images.end()); i != end; ++i) {
66                 SDL_FreeSurface(*i);
67         }
68         for (vector<Monster *>::const_iterator i(monsters.begin()), end(monsters.end()); i != end; ++i) {
69                 delete *i;
70         }
71         for (vector<PartyLayout *>::const_iterator i(partyLayouts.begin()), end(partyLayouts.end()); i != end; ++i) {
72                 delete *i;
73         }
74         for (vector<SimpleAnimation *>::const_iterator i(simpleAnimations.begin()), end(simpleAnimations.end()); i != end; ++i) {
75                 delete *i;
76         }
77         for (vector<Spell *>::const_iterator i(spells.begin()), end(spells.end()); i != end; ++i) {
78                 delete *i;
79         }
80         for (vector<Sprite *>::const_iterator i(sprites.begin()), end(sprites.end()); i != end; ++i) {
81                 delete *i;
82         }
83         for (vector<const char *>::const_iterator i(strings.begin()), end(strings.end()); i != end; ++i) {
84                 delete *i;
85         }
86         for (vector<TargetingMode *>::const_iterator i(targetingModes.begin()), end(targetingModes.end()); i != end; ++i) {
87                 delete *i;
88         }
89 }
90
91
92 Animation *Interpreter::GetAnimation(const std::string &name) {
93         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
94         if (i != parsedDefinitions.end()) {
95                 if (i->second.type == COMPLEX_ANIMATION) {
96                         return complexAnimations[i->second.index];
97                 } else if (i->second.type == SIMPLE_ANIMATION) {
98                         return simpleAnimations[i->second.index];
99                 } else {
100                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Animation");
101                 }
102         } else {
103                 throw Error("access to undefined Animation " + name);
104         }
105 }
106
107 bool Interpreter::GetBoolean(const std::string &name) const {
108         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
109         if (i != parsedDefinitions.end()) {
110                 if (i->second.type == BOOLEAN) {
111                         return booleans[i->second.index];
112                 } else {
113                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Boolean");
114                 }
115         } else {
116                 throw Error("access to undefined Boolean " + name);
117         }
118 }
119
120 Font *Interpreter::GetFont(const std::string &name) {
121         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
122         if (i != parsedDefinitions.end()) {
123                 if (i->second.type == FONT) {
124                         return fonts[i->second.index];
125                 } else {
126                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Font");
127                 }
128         } else {
129                 throw Error("access to undefined Font " + name);
130         }
131 }
132
133 Frame *Interpreter::GetFrame(const std::string &name) {
134         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
135         if (i != parsedDefinitions.end()) {
136                 if (i->second.type == FRAME) {
137                         return frames[i->second.index];
138                 } else {
139                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Frame");
140                 }
141         } else {
142                 throw Error("access to undefined Frame " + name);
143         }
144 }
145
146 Gauge *Interpreter::GetGauge(const std::string &name) {
147         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
148         if (i != parsedDefinitions.end()) {
149                 if (i->second.type == GAUGE) {
150                         return gauges[i->second.index];
151                 } else {
152                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Gauge");
153                 }
154         } else {
155                 throw Error("access to undefined Gauge " + name);
156         }
157 }
158
159 Hero *Interpreter::GetHero(const std::string &name) {
160         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
161         if (i != parsedDefinitions.end()) {
162                 if (i->second.type == HERO) {
163                         return heroes[i->second.index];
164                 } else {
165                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Hero");
166                 }
167         } else {
168                 throw Error("access to undefined Hero " + name);
169         }
170 }
171
172 Monster *Interpreter::GetMonster(const std::string &name) {
173         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
174         if (i != parsedDefinitions.end()) {
175                 if (i->second.type == MONSTER) {
176                         return monsters[i->second.index];
177                 } else {
178                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Monster");
179                 }
180         } else {
181                 throw Error("access to undefined Monster " + name);
182         }
183 }
184
185 int Interpreter::GetNumber(const std::string &name) const {
186         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
187         if (i != parsedDefinitions.end()) {
188                 if (i->second.type == NUMBER) {
189                         return numbers[i->second.index];
190                 } else {
191                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Number");
192                 }
193         } else {
194                 throw Error("access to undefined Number " + name);
195         }
196 }
197
198 PartyLayout *Interpreter::GetPartyLayout(const std::string &name) {
199         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
200         if (i != parsedDefinitions.end()) {
201                 if (i->second.type == PARTY_LAYOUT) {
202                         return partyLayouts[i->second.index];
203                 } else {
204                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to PartyLayout");
205                 }
206         } else {
207                 throw Error("access to undefined PartyLayout " + name);
208         }
209 }
210
211 Spell *Interpreter::GetSpell(const std::string &name) {
212         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
213         if (i != parsedDefinitions.end()) {
214                 if (i->second.type == SPELL) {
215                         return spells[i->second.index];
216                 } else {
217                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Spell");
218                 }
219         } else {
220                 throw Error("access to undefined Spell " + name);
221         }
222 }
223
224 Sprite *Interpreter::GetSprite(const std::string &name) {
225         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
226         if (i != parsedDefinitions.end()) {
227                 if (i->second.type == SPRITE) {
228                         return sprites[i->second.index];
229                 } else {
230                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Sprite");
231                 }
232         } else {
233                 throw Error("access to undefined Sprite " + name);
234         }
235 }
236
237 const char *Interpreter::GetString(const std::string &name) const {
238         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
239         if (i != parsedDefinitions.end()) {
240                 if (i->second.type == STRING) {
241                         return strings[i->second.index];
242                 } else {
243                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to String");
244                 }
245         } else {
246                 throw Error("access to undefined String " + name);
247         }
248 }
249
250 TargetingMode *Interpreter::GetTargetingMode(const std::string &name) {
251         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
252         if (i != parsedDefinitions.end()) {
253                 if (i->second.type == TARGETING_MODE) {
254                         return targetingModes[i->second.index];
255                 } else {
256                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to TargetingMode");
257                 }
258         } else {
259                 throw Error("access to undefined TargetingMode " + name);
260         }
261 }
262
263 Vector<int> Interpreter::GetVector(const std::string &name) const {
264         map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
265         if (i != parsedDefinitions.end()) {
266                 if (i->second.type == VECTOR) {
267                         return vectors[i->second.index];
268                 } else {
269                         throw Error("cannot cast " + i->second.dfn->TypeName() + " to Vector");
270                 }
271         } else {
272                 throw Error("access to undefined Vector " + name);
273         }
274 }
275
276
277 void Interpreter::ReadSource() {
278         for (set<string>::const_iterator i(source.Exports().begin()), end(source.Exports().end()); i != end; ++i) {
279                 ReadDefinition(source.GetDefinition(*i));
280         }
281 }
282
283 void Interpreter::ReadDefinition(const Definition &dfn) {
284         if (parsedDefinitions.find(dfn.Identifier()) != parsedDefinitions.end()) {
285                 return;
286         }
287         if (dfn.HasLiteralValue()) {
288                 ReadLiteral(dfn);
289         } else {
290                 ReadObject(dfn);
291         }
292 }
293
294 void Interpreter::ReadLiteral(const Definition &dfn) {
295         switch (dfn.GetLiteral()->GetType()) {
296                 case Literal::ARRAY_VALUES:
297                         valueArrays.push_back(dfn.GetLiteral()->GetValues());
298                         parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, VALUE_ARRAY, valueArrays.size() - 1)));
299                         break;
300                 case Literal::ARRAY_PROPS:
301                         propertyListArrays.push_back(dfn.GetLiteral()->GetPropertyLists());
302                         parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, PROPERTY_LIST_ARRAY, propertyListArrays.size() - 1)));
303                         break;
304                 case Literal::BOOLEAN:
305                         booleans.push_back(dfn.GetLiteral()->GetBoolean());
306                         parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, BOOLEAN, booleans.size() - 1)));
307                         break;
308                 case Literal::COLOR:
309                         throw Error("unhandled literal: color");
310                         break;
311                 case Literal::NUMBER:
312                         numbers.push_back(dfn.GetLiteral()->GetNumber());
313                         parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, NUMBER, numbers.size() - 1)));
314                         break;
315                 case Literal::STRING:
316                         {
317                                 char *str(new char[dfn.GetLiteral()->GetString().size() + 1]);
318                                 std::memcpy(str, dfn.GetLiteral()->GetString().c_str(), dfn.GetLiteral()->GetString().size());
319                                 str[dfn.GetLiteral()->GetString().size()] = '\0';
320                                 strings.push_back(str);
321                         }
322                         parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, STRING, strings.size() - 1)));
323                         break;
324                 case Literal::VECTOR:
325                         vectors.push_back(Vector<int>(dfn.GetLiteral()->GetX(), dfn.GetLiteral()->GetY()));
326                         parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, VECTOR, vectors.size() - 1)));
327                         break;
328                 case Literal::OBJECT:
329                         ReadObject(dfn);
330                         break;
331         }
332 }
333
334 Animation *Interpreter::GetAnimation(const Value &v) {
335         if (v.IsLiteral()) {
336                 if (v.GetLiteral().GetTypeName() == "ComplexAnimation") {
337                         ComplexAnimation *a(new ComplexAnimation);
338                         ReadComplexAnimation(*a, *v.GetLiteral().GetProperties());
339                         complexAnimations.push_back(a);
340                         return a;
341                 } else {
342                         SimpleAnimation *a(new SimpleAnimation);
343                         ReadSimpleAnimation(*a, *v.GetLiteral().GetProperties());
344                         simpleAnimations.push_back(a);
345                         return a;
346                 }
347         } else {
348                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
349                 return GetAnimation(v.GetIdentifier());
350         }
351 }
352
353 bool Interpreter::GetBoolean(const Value &v) {
354         if (v.IsLiteral()) {
355                 return v.GetLiteral().GetBoolean();
356         } else {
357                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
358                 return GetBoolean(v.GetIdentifier());
359         }
360 }
361
362 Font *Interpreter::GetFont(const Value &v) {
363         if (v.IsLiteral()) {
364                 Font *f(new Font);
365                 ReadFont(*f, *v.GetLiteral().GetProperties());
366                 return f;
367         } else {
368                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
369                 return GetFont(v.GetIdentifier());
370         }
371 }
372
373 Frame *Interpreter::GetFrame(const Value &v) {
374         if (v.IsLiteral()) {
375                 Frame *f(new Frame);
376                 ReadFrame(*f, *v.GetLiteral().GetProperties());
377                 return f;
378         } else {
379                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
380                 return GetFrame(v.GetIdentifier());
381         }
382 }
383
384 Gauge *Interpreter::GetGauge(const Value &v) {
385         if (v.IsLiteral()) {
386                 Gauge *g(new Gauge);
387                 ReadGauge(*g, *v.GetLiteral().GetProperties());
388                 return g;
389         } else {
390                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
391                 return GetGauge(v.GetIdentifier());
392         }
393 }
394
395 SDL_Surface *Interpreter::GetImage(const Value &v) {
396         const char *file(GetString(v));
397         SDL_Surface *image(IMG_Load(file));
398         images.push_back(image);
399         return image;
400 }
401
402 int Interpreter::GetNumber(const Value &v) {
403         if (v.IsLiteral()) {
404                 return v.GetLiteral().GetNumber();
405         } else {
406                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
407                 return GetNumber(v.GetIdentifier());
408         }
409 }
410
411 PartyLayout *Interpreter::GetPartyLayout(const Value &v) {
412         if (v.IsLiteral()) {
413                 PartyLayout *l(new PartyLayout);
414                 ReadPartyLayout(*l, *v.GetLiteral().GetProperties());
415                 return l;
416         } else {
417                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
418                 return GetPartyLayout(v.GetIdentifier());
419         }
420 }
421
422 const PropertyList *Interpreter::GetPropertyList(const Value &v) {
423         if (v.IsLiteral()) {
424                 return v.GetLiteral().GetProperties();
425         } else {
426                 throw Error("cannot reference property lists");
427         }
428 }
429
430 const vector<PropertyList *> &Interpreter::GetPropertyListArray(const Value &v) {
431         if (v.IsLiteral()) {
432                 return v.GetLiteral().GetPropertyLists();
433         } else {
434                 throw Error("cannot reference property list arrays");
435         }
436 }
437
438 Spell *Interpreter::GetSpell(const Value &v) {
439         if (v.IsLiteral()) {
440                 Spell *s(new Spell);
441                 ReadSpell(*s, *v.GetLiteral().GetProperties());
442                 return s;
443         } else {
444                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
445                 return GetSpell(v.GetIdentifier());
446         }
447 }
448
449 Sprite *Interpreter::GetSprite(const Value &v) {
450         if (v.IsLiteral()) {
451                 Sprite *s(new Sprite);
452                 ReadSprite(*s, *v.GetLiteral().GetProperties());
453                 return s;
454         } else {
455                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
456                 return GetSprite(v.GetIdentifier());
457         }
458 }
459
460 const char *Interpreter::GetString(const Value &v) {
461         if (v.IsLiteral()) {
462                 return v.GetLiteral().GetString().c_str();
463         } else {
464                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
465                 return GetString(v.GetIdentifier());
466         }
467 }
468
469 TargetingMode *Interpreter::GetTargetingMode(const Value &v) {
470         if (v.IsLiteral()) {
471                 TargetingMode *t(new TargetingMode);
472                 ReadTargetingMode(*t, *v.GetLiteral().GetProperties());
473                 return t;
474         } else {
475                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
476                 return GetTargetingMode(v.GetIdentifier());
477         }
478 }
479
480 Vector<int> Interpreter::GetVector(const Value &v) {
481         if (v.IsLiteral()) {
482                 return Vector<int>(v.GetLiteral().GetX(), v.GetLiteral().GetY());
483         } else {
484                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
485                 return GetVector(v.GetIdentifier());
486         }
487 }
488
489 const vector<Value *> &Interpreter::GetValueArray(const Value &v) {
490         if (v.IsLiteral()) {
491                 return v.GetLiteral().GetValues();
492         } else {
493                 throw Error("cannot reference value arrays");
494         }
495 }
496
497
498 void Interpreter::ReadObject(const Definition &dfn) {
499         if (dfn.TypeName() == "ComplexAnimation") {
500                 ComplexAnimation *animation(new ComplexAnimation);
501                 int index(complexAnimations.size());
502                 complexAnimations.push_back(animation);
503                 ReadComplexAnimation(*animation, *dfn.GetProperties());
504                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, COMPLEX_ANIMATION, index)));
505         } else if (dfn.TypeName() == "Font") {
506                 Font *font(new Font);
507                 int index(fonts.size());
508                 fonts.push_back(font);
509                 ReadFont(*font, *dfn.GetProperties());
510                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, FONT, index)));
511         } else if (dfn.TypeName() == "Frame") {
512                 Frame *frame(new Frame);
513                 int index(frames.size());
514                 frames.push_back(frame);
515                 ReadFrame(*frame, *dfn.GetProperties());
516                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, FRAME, index)));
517         } else if (dfn.TypeName() == "Gauge") {
518                 Gauge *gauge(new Gauge);
519                 int index(gauges.size());
520                 gauges.push_back(gauge);
521                 ReadGauge(*gauge, *dfn.GetProperties());
522                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, GAUGE, index)));
523         } else if (dfn.TypeName() == "Hero") {
524                 Hero *hero(new Hero);
525                 int index(heroes.size());
526                 heroes.push_back(hero);
527                 ReadHero(*hero, *dfn.GetProperties());
528                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, HERO, index)));
529         } else if (dfn.TypeName() == "Monster") {
530                 Monster *monster(new Monster);
531                 int index(monsters.size());
532                 monsters.push_back(monster);
533                 ReadMonster(*monster, *dfn.GetProperties());
534                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, MONSTER, index)));
535         } else if (dfn.TypeName() == "PartyLayout") {
536                 PartyLayout *layout(new PartyLayout);
537                 int index(partyLayouts.size());
538                 partyLayouts.push_back(layout);
539                 ReadPartyLayout(*layout, *dfn.GetProperties());
540                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, PARTY_LAYOUT, index)));
541         } else if (dfn.TypeName() == "SimpleAnimation") {
542                 SimpleAnimation *animation(new SimpleAnimation);
543                 int index(simpleAnimations.size());
544                 simpleAnimations.push_back(animation);
545                 ReadSimpleAnimation(*animation, *dfn.GetProperties());
546                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, SIMPLE_ANIMATION, index)));
547         } else if (dfn.TypeName() == "Spell") {
548                 Spell *spell(new Spell);
549                 int index(spells.size());
550                 spells.push_back(spell);
551                 ReadSpell(*spell, *dfn.GetProperties());
552                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, SPELL, index)));
553         } else if (dfn.TypeName() == "Sprite") {
554                 Sprite *sprite(new Sprite);
555                 int index(sprites.size());
556                 sprites.push_back(sprite);
557                 ReadSprite(*sprite, *dfn.GetProperties());
558                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, SPRITE, index)));
559         } else if (dfn.TypeName() == "TargetingMode") {
560                 TargetingMode *mode(new TargetingMode);
561                 int index(targetingModes.size());
562                 targetingModes.push_back(mode);
563                 ReadTargetingMode(*mode, *dfn.GetProperties());
564                 parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, TARGETING_MODE, index)));
565         } else {
566                 throw Error("unhandled object type: " + dfn.TypeName());
567         }
568 }
569
570
571 void Interpreter::ReadComplexAnimation(ComplexAnimation &a, const PropertyList &props) {
572         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
573                 if (i->first == "sprite") {
574                         a.SetSprite(GetSprite(*i->second));
575                 } else if (i->first == "frametime") {
576                         a.SetFrameTime(GetNumber(*i->second));
577                 } else if (i->first == "repeat") {
578                         a.SetRepeat(GetBoolean(*i->second));
579                 } else if (i->first == "frames") {
580                         const vector<PropertyList *> &values(GetPropertyListArray(*i->second));
581                         for (vector<PropertyList *>::const_iterator i(values.begin()), end(values.end()); i != end; ++i) {
582                                 ComplexAnimation::FrameProp frame;
583                                 ReadComplexAnimationFrame(frame, **i);
584                                 a.AddFrame(frame);
585                         }
586                 } else {
587                         throw Error("unknown ComplexAnimation property: " + i->first);
588                 }
589         }
590 }
591
592 void Interpreter::ReadComplexAnimationFrame(ComplexAnimation::FrameProp &f, const PropertyList &props) {
593         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
594                 if (i->first == "column") {
595                         f.col = GetNumber(*i->second);
596                 } else if (i->first == "row") {
597                         f.row = GetNumber(*i->second);
598                 } else if (i->first == "disposition") {
599                         f.disposition = GetVector(*i->second);
600                 } else {
601                         throw Error("unknown ComplexAnimationFrame property: " + i->first);
602                 }
603         }
604 }
605
606 void Interpreter::ReadFont(Font &f, const PropertyList &props) {
607         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
608                 if (i->first == "sprite") {
609                         f.SetSprite(GetSprite(*i->second));
610                 } else if (i->first == "columnoffset") {
611                         f.SetColOffset(GetNumber(*i->second));
612                 } else if (i->first == "rowoffset") {
613                         f.SetRowOffset(GetNumber(*i->second));
614                 } else {
615                         throw Error("unknown Font property: " + i->first);
616                 }
617         }
618 }
619
620 void Interpreter::ReadFrame(Frame &f, const PropertyList &props) {
621         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
622                 if (i->first == "image") {
623                         f.SetSurface(GetImage(*i->second));
624                 } else if (i->first == "border") {
625                         f.SetBorderSize(GetVector(*i->second));
626                 } else if (i->first == "repeat") {
627                         f.SetRepeatSize(GetVector(*i->second));
628                 } else if (i->first == "offset") {
629                         f.SetOffset(GetVector(*i->second));
630                 } else {
631                         throw Error("unknown Frame property: " + i->first);
632                 }
633         }
634 }
635
636 void Interpreter::ReadGauge(Gauge &g, const PropertyList &props) {
637         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
638                 if (i->first == "image") {
639                         g.SetSurface(GetImage(*i->second));
640                 } else if (i->first == "full") {
641                         g.SetFullOffset(GetVector(*i->second));
642                 } else if (i->first == "empty") {
643                         g.SetEmptyOffset(GetVector(*i->second));
644                 } else if (i->first == "height") {
645                         g.SetHeight(GetNumber(*i->second));
646                 } else if (i->first == "start") {
647                         g.SetStartWidth(GetNumber(*i->second));
648                 } else if (i->first == "repeat") {
649                         g.SetRepeatWidth(GetNumber(*i->second));
650                 } else if (i->first == "end") {
651                         g.SetEndWidth(GetNumber(*i->second));
652                 } else {
653                         throw Error("unknown Gauge property: " + i->first);
654                 }
655         }
656 }
657
658 void Interpreter::ReadHero(Hero &h, const PropertyList &props) {
659         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
660                 if (i->first == "name") {
661                         h.SetName(GetString(*i->second));
662                 } else if (i->first == "sprite") {
663                         h.SetSprite(GetSprite(*i->second));
664                 } else if (i->first == "level") {
665                         h.SetLevel(GetNumber(*i->second));
666                 } else if (i->first == "maxHealth") {
667                         h.SetMaxHealth(GetNumber(*i->second));
668                 } else if (i->first == "health") {
669                         h.SetHealth(GetNumber(*i->second));
670                 } else if (i->first == "maxMana") {
671                         h.SetMaxMana(GetNumber(*i->second));
672                 } else if (i->first == "mana") {
673                         h.SetMana(GetNumber(*i->second));
674                 } else if (i->first == "ip") {
675                         h.SetIP(GetNumber(*i->second));
676                 } else if (i->first == "stats") {
677                         battle::Stats stats;
678                         ReadStats(stats, *GetPropertyList(*i->second));
679                         h.SetStats(stats);
680                 } else if (i->first == "attackAnimation") {
681                         h.SetAttackAnimation(GetAnimation(*i->second));
682                 } else if (i->first == "spellAnimation") {
683                         h.SetSpellAnimation(GetAnimation(*i->second));
684                 } else if (i->first == "meleeAnimation") {
685                         h.SetMeleeAnimation(GetAnimation(*i->second));
686                 } else {
687                         throw Error("unknown Hero property: " + i->first);
688                 }
689         }
690 }
691
692 void Interpreter::ReadMonster(Monster &m, const PropertyList &props) {
693         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
694                 if (i->first == "name") {
695                         m.SetName(GetString(*i->second));
696                 } else if (i->first == "sprite") {
697                         m.SetSprite(GetSprite(*i->second));
698                 } else if (i->first == "level") {
699                         m.SetLevel(GetNumber(*i->second));
700                 } else if (i->first == "maxHealth") {
701                         m.SetMaxHealth(GetNumber(*i->second));
702                 } else if (i->first == "health") {
703                         m.SetHealth(GetNumber(*i->second));
704                 } else if (i->first == "maxMana") {
705                         m.SetMaxMana(GetNumber(*i->second));
706                 } else if (i->first == "mana") {
707                         m.SetMana(GetNumber(*i->second));
708                 } else if (i->first == "stats") {
709                         battle::Stats stats;
710                         ReadStats(stats, *GetPropertyList(*i->second));
711                         m.SetStats(stats);
712                 } else if (i->first == "attackAnimation") {
713                         m.SetAttackAnimation(GetAnimation(*i->second));
714                 } else if (i->first == "meleeAnimation") {
715                         m.SetMeleeAnimation(GetAnimation(*i->second));
716                 } else {
717                         throw Error("unknown Monster property: " + i->first);
718                 }
719         }
720 }
721
722 void Interpreter::ReadPartyLayout(PartyLayout &p, const PropertyList &props) {
723         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
724                 if (i->first == "positions") {
725                         const vector<Value *> &positions(GetValueArray(*i->second));
726                         for (vector<Value *>::const_iterator j(positions.begin()), end(positions.end()); j != end; ++j) {
727                                 p.AddPosition(GetVector(**j));
728                         }
729                 } else {
730                         throw Error("unknown PartyLayout property: " + i->first);
731                 }
732         }
733 }
734
735 void Interpreter::ReadSimpleAnimation(SimpleAnimation &a, const PropertyList &props) {
736         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
737                 if (i->first == "sprite") {
738                         a.SetSprite(GetSprite(*i->second));
739                 } else if (i->first == "frametime") {
740                         a.SetFrameTime(GetNumber(*i->second));
741                 } else if (i->first == "repeat") {
742                         a.SetRepeat(GetBoolean(*i->second));
743                 } else if (i->first == "framecount") {
744                         a.SetNumFrames(GetNumber(*i->second));
745                 } else if (i->first == "col") {
746                         a.SetCol(GetNumber(*i->second));
747                 } else if (i->first == "row") {
748                         a.SetRow(GetNumber(*i->second));
749                 } else {
750                         throw Error("unknown SimpleAnimation property: " + i->first);
751                 }
752         }
753 }
754
755 void Interpreter::ReadSpell(Spell &s, const PropertyList &props) {
756         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
757                 if (i->first == "name") {
758                         s.SetName(GetString(*i->second));
759                 } else if (i->first == "cost") {
760                         s.SetCost(GetNumber(*i->second));
761                 } else if (i->first == "battle") {
762                         if (GetBoolean(*i->second)) {
763                                 s.SetUsableInBattle();
764                         }
765                 } else if (i->first == "targets") {
766                         s.GetTargetingMode() = *GetTargetingMode(*i->second);
767                 } else {
768                         throw Error("unknown Spell property: " + i->first);
769                 }
770         }
771 }
772
773 void Interpreter::ReadSprite(Sprite &s, const PropertyList &props) {
774         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
775                 if (i->first == "image") {
776                         s.SetSurface(GetImage(*i->second));
777                 } else if (i->first == "size") {
778                         s.SetSize(GetVector(*i->second));
779                 } else if (i->first == "offset") {
780                         s.SetOffset(GetVector(*i->second));
781                 } else {
782                         throw Error("unknown Sprite property: " + i->first);
783                 }
784         }
785 }
786
787 void Interpreter::ReadStats(Stats &s, const PropertyList &props) {
788         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
789                 if (i->first == "atp") {
790                         s.SetAttack(GetNumber(*i->second));
791                 } else if (i->first == "dfp") {
792                         s.SetDefense(GetNumber(*i->second));
793                 } else if (i->first == "str") {
794                         s.SetStrength(GetNumber(*i->second));
795                 } else if (i->first == "agl") {
796                         s.SetAgility(GetNumber(*i->second));
797                 } else if (i->first == "int") {
798                         s.SetIntelligence(GetNumber(*i->second));
799                 } else if (i->first == "gut") {
800                         s.SetGut(GetNumber(*i->second));
801                 } else if (i->first == "mgr") {
802                         s.SetMagicResistance(GetNumber(*i->second));
803                 } else {
804                         throw Error("unknown Stats property: " + i->first);
805                 }
806         }
807 }
808
809 void Interpreter::ReadTargetingMode(TargetingMode &t, const PropertyList &props) {
810         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
811                 if (i->first == "ally") {
812                         if (GetBoolean(*i->second)) {
813                                 t.TargetAlly();
814                         } else {
815                                 t.TargetEnemy();
816                         }
817                 } else if (i->first == "enemy") {
818                         if (GetBoolean(*i->second)) {
819                                 t.TargetEnemy();
820                         } else {
821                                 t.TargetAlly();
822                         }
823                 } else if (i->first == "all") {
824                         if (GetBoolean(*i->second)) {
825                                 t.TargetAll();
826                         }
827                 } else if (i->first == "multiple") {
828                         if (GetBoolean(*i->second)) {
829                                 t.TargetMultiple();
830                         }
831                 } else if (i->first == "single") {
832                         if (GetBoolean(*i->second)) {
833                                 t.TargetSingle();
834                         }
835                 } else {
836                         throw Error("unknown TargetingMode property: " + i->first);
837                 }
838         }
839 }
840
841 }