From 05112fcfdbd0c452c80b6786bf6121d6f63b852a Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Tue, 28 Aug 2012 23:45:32 +0200 Subject: [PATCH] interpretation of Heros and Monsters --- src/loader/Interpreter.cpp | 325 ++++++++++++++++++++++++++++++++++--- src/loader/Interpreter.h | 40 ++++- test-data/test.l2s | 29 ++-- 3 files changed, 357 insertions(+), 37 deletions(-) diff --git a/src/loader/Interpreter.cpp b/src/loader/Interpreter.cpp index 268fab9..9e076c1 100644 --- a/src/loader/Interpreter.cpp +++ b/src/loader/Interpreter.cpp @@ -8,23 +8,41 @@ #include "Interpreter.h" #include "ParsedSource.h" +#include "../battle/Hero.h" #include "../battle/Monster.h" +#include "../graphics/ComplexAnimation.h" +#include "../graphics/SimpleAnimation.h" +#include "../graphics/Sprite.h" +using battle::Hero; using battle::Monster; +using battle::Stats; +using graphics::Animation; +using graphics::ComplexAnimation; +using graphics::SimpleAnimation; +using graphics::Sprite; +using geometry::Vector; using std::map; using std::set; using std::string; +using std::vector; namespace loader { void Interpreter::ReadSource() { for (set::const_iterator i(source.Exports().begin()), end(source.Exports().end()); i != end; ++i) { - const Definition &dfn(source.GetDefinition(*i)); - if (dfn.HasLiteralValue()) { - ReadLiteral(dfn); - } else { - ReadObject(dfn); - } + ReadDefinition(source.GetDefinition(*i)); + } +} + +void Interpreter::ReadDefinition(const Definition &dfn) { + if (parsedDefinitions.find(dfn.Identifier()) != parsedDefinitions.end()) { + return; + } + if (dfn.HasLiteralValue()) { + ReadLiteral(dfn); + } else { + ReadObject(dfn); } } @@ -34,49 +52,312 @@ void Interpreter::ReadLiteral(const Definition &dfn) { throw Error("unhandled literal: array of values"); break; case Literal::ARRAY_PROPS: - throw Error("unhandled literal: array of values"); + throw Error("unhandled literal: array of properties"); break; case Literal::BOOLEAN: - throw Error("unhandled literal: array of values"); + throw Error("unhandled literal: boolean"); break; case Literal::COLOR: - throw Error("unhandled literal: array of values"); + throw Error("unhandled literal: color"); break; case Literal::NUMBER: - throw Error("unhandled literal: array of values"); + numbers[dfn.Identifier()] = dfn.GetLiteral()->GetNumber(); break; case Literal::STRING: - throw Error("unhandled literal: array of values"); + throw Error("unhandled literal: string"); break; case Literal::VECTOR: - throw Error("unhandled literal: array of values"); + throw Error("unhandled literal: vector"); break; case Literal::OBJECT: - throw Error("unhandled literal: array of values"); + throw Error("unhandled literal: object"); break; } } +Animation *Interpreter::GetAnimation(const Value &v) { + if (v.IsLiteral()) { + if (v.GetLiteral().GetTypeName() == "ComplexAnimation") { + ComplexAnimation *a(new ComplexAnimation); + ReadComplexAnimation(*a, *v.GetLiteral().GetProperties()); + return a; + } else { + SimpleAnimation *a(new SimpleAnimation); + ReadSimpleAnimation(*a, *v.GetLiteral().GetProperties()); + return a; + } + } else if (animations.count(v.GetIdentifier())) { + return animations[v.GetIdentifier()]; + } else if (source.IsDefined(v.GetIdentifier())) { + ReadDefinition(source.GetDefinition(v.GetIdentifier())); + if (animations.count(v.GetIdentifier())) { + return animations[v.GetIdentifier()]; + } else { + throw Error("cannot use " + source.GetDefinition(v.GetIdentifier()).Identifier() + " " + v.GetIdentifier() + " as animation"); + } + } else { + throw Error("use of undefined Animation " + v.GetIdentifier()); + } +} + +const vector &Interpreter::GetValueArray(const Value &v) { + if (v.IsLiteral()) { + return v.GetLiteral().GetValues(); + } else { + throw Error("identifier resolution not implemented for arrays of values"); + } +} + +const vector &Interpreter::GetPropertyListArray(const Value &v) { + if (v.IsLiteral()) { + return v.GetLiteral().GetPropertyLists(); + } else { + throw Error("identifier resolution not implemented for arrays of property lists"); + } +} + +bool Interpreter::GetBoolean(const Value &v) { + if (v.IsLiteral()) { + return v.GetLiteral().GetBoolean(); + } else { + throw Error("identifier resolution not implemented for booleans"); + } +} + +SDL_Surface *Interpreter::GetImage(const Value &v) { + if (v.IsLiteral()) { + // TODO: image lookup + return NULL; + } else { + throw Error("identifier resolution not implemented for images"); + } +} + +int Interpreter::GetNumber(const Value &v) { + if (v.IsLiteral()) { + return v.GetLiteral().GetNumber(); + } else if (numbers.count(v.GetIdentifier())) { + return numbers[v.GetIdentifier()]; + } else { + ReadDefinition(source.GetDefinition(v.GetIdentifier())); + if (numbers.count(v.GetIdentifier())) { + return numbers[v.GetIdentifier()]; + } else { + throw Error("use of undefined Number " + v.GetIdentifier()); + } + } +} + +const PropertyList *Interpreter::GetPropertyList(const Value &v) { + if (v.IsLiteral()) { + return v.GetLiteral().GetProperties(); + } else { + throw Error("identifier resolution not implemented for property lists"); + } +} + +Sprite *Interpreter::GetSprite(const Value &v) { + if (v.IsLiteral()) { + Sprite *s(new Sprite); + ReadSprite(*s, *v.GetLiteral().GetProperties()); + return s; + } else if (sprites.count(v.GetIdentifier())) { + return sprites[v.GetIdentifier()]; + } else { + ReadDefinition(source.GetDefinition(v.GetIdentifier())); + if (sprites.count(v.GetIdentifier())) { + return sprites[v.GetIdentifier()]; + } else { + throw Error("use of undefined Sprite " + v.GetIdentifier()); + } + } +} + +const char *Interpreter::GetString(const Value &v) { + if (v.IsLiteral()) { + return v.GetLiteral().GetString().c_str(); + } else { + throw Error("identifier resolution not implemented for strings"); + } +} + +Vector Interpreter::GetVector(const Value &v) { + if (v.IsLiteral()) { + return Vector(v.GetLiteral().GetX(), v.GetLiteral().GetY()); + } else { + throw Error("identifier resolution not implemented for vectors"); + } +} + + void Interpreter::ReadObject(const Definition &dfn) { - if (dfn.TypeName() == "Monster") { - monsters.resize(monsters.size() + 1); - ReadMonster(monsters.back(), *dfn.GetProperties()); + if (dfn.TypeName() == "Hero") { + Hero *h(new Hero); + ReadHero(*h, *dfn.GetProperties()); + heroes[dfn.Identifier()] = h; + } else if (dfn.TypeName() == "Monster") { + Monster *m(new Monster); + ReadMonster(*m, *dfn.GetProperties()); + monsters[dfn.Identifier()] = m; + } else if (dfn.TypeName() == "Sprite") { + Sprite *s(new Sprite); + ReadSprite(*s, *dfn.GetProperties()); + sprites[dfn.Identifier()] = s; } else { throw Error("unhandled object: " + dfn.TypeName()); } } +void Interpreter::ReadComplexAnimation(ComplexAnimation &a, const PropertyList &props) { + for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) { + if (i->first == "sprite") { + a.SetSprite(GetSprite(*i->second)); + } else if (i->first == "frametime") { + a.SetFrameTime(GetNumber(*i->second)); + } else if (i->first == "repeat") { + a.SetRepeat(GetBoolean(*i->second)); + } else if (i->first == "frames") { + const vector &values(GetPropertyListArray(*i->second)); + for (vector::const_iterator i(values.begin()), end(values.end()); i != end; ++i) { + ComplexAnimation::FrameProp frame; + ReadComplexAnimationFrame(frame, **i); + a.AddFrame(frame); + } + } else { + throw Error("unknown ComplexAnimation property: " + i->first); + } + } +} + +void Interpreter::ReadComplexAnimationFrame(ComplexAnimation::FrameProp &f, const PropertyList &props) { + for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) { + if (i->first == "column") { + f.col = GetNumber(*i->second); + } else if (i->first == "row") { + f.row = GetNumber(*i->second); + } else if (i->first == "disposition") { + f.disposition = GetVector(*i->second); + } else { + throw Error("unknown ComplexAnimationFrame property: " + i->first); + } + } +} + +void Interpreter::ReadHero(Hero &h, const PropertyList &props) { + for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) { + if (i->first == "name") { + h.SetName(GetString(*i->second)); + } else if (i->first == "sprite") { + h.SetSprite(GetSprite(*i->second)); + } else if (i->first == "level") { + h.SetLevel(GetNumber(*i->second)); + } else if (i->first == "maxHealth") { + h.SetMaxHealth(GetNumber(*i->second)); + } else if (i->first == "health") { + h.SetHealth(GetNumber(*i->second)); + } else if (i->first == "maxMana") { + h.SetMaxMana(GetNumber(*i->second)); + } else if (i->first == "mana") { + h.SetMana(GetNumber(*i->second)); + } else if (i->first == "ip") { + h.SetIP(GetNumber(*i->second)); + } else if (i->first == "stats") { + battle::Stats stats; + ReadStats(stats, *GetPropertyList(*i->second)); + h.SetStats(stats); + } else if (i->first == "attackAnimation") { + h.SetAttackAnimation(GetAnimation(*i->second)); + } else if (i->first == "spellAnimation") { + h.SetSpellAnimation(GetAnimation(*i->second)); + } else if (i->first == "meleeAnimation") { + h.SetMeleeAnimation(GetAnimation(*i->second)); + } else { + throw Error("unknown Hero property: " + i->first); + } + } +} + void Interpreter::ReadMonster(Monster &m, const PropertyList &props) { for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) { if (i->first == "name") { - if (i->second->IsLiteral()) { - m.SetName(i->second->GetLiteral().GetString().c_str()); - } else { - throw Error("identifier resolution not implemented"); - } + m.SetName(GetString(*i->second)); + } else if (i->first == "sprite") { + m.SetSprite(GetSprite(*i->second)); + } else if (i->first == "level") { + m.SetLevel(GetNumber(*i->second)); + } else if (i->first == "maxHealth") { + m.SetMaxHealth(GetNumber(*i->second)); + } else if (i->first == "health") { + m.SetHealth(GetNumber(*i->second)); + } else if (i->first == "maxMana") { + m.SetMaxMana(GetNumber(*i->second)); + } else if (i->first == "mana") { + m.SetMana(GetNumber(*i->second)); + } else if (i->first == "stats") { + battle::Stats stats; + ReadStats(stats, *GetPropertyList(*i->second)); + m.SetStats(stats); + } else if (i->first == "attackAnimation") { + m.SetAttackAnimation(GetAnimation(*i->second)); + } else { + throw Error("unknown Monster property: " + i->first); + } + } +} + +void Interpreter::ReadSimpleAnimation(SimpleAnimation &a, const PropertyList &props) { + for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) { + if (i->first == "sprite") { + a.SetSprite(GetSprite(*i->second)); + } else if (i->first == "frametime") { + a.SetFrameTime(GetNumber(*i->second)); + } else if (i->first == "repeat") { + a.SetRepeat(GetBoolean(*i->second)); + } else if (i->first == "framecount") { + a.SetNumFrames(GetNumber(*i->second)); + } else if (i->first == "col") { + a.SetCol(GetNumber(*i->second)); + } else if (i->first == "row") { + a.SetRow(GetNumber(*i->second)); + } else { + throw Error("unknown SimpleAnimation property: " + i->first); + } + } +} + +void Interpreter::ReadSprite(Sprite &s, const PropertyList &props) { + for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) { + if (i->first == "image") { + s.SetSurface(GetImage(*i->second)); + } else if (i->first == "size") { + s.SetSize(GetVector(*i->second)); + } else if (i->first == "offset") { + s.SetOffset(GetVector(*i->second)); + } else { + throw Error("unknown Sprite property: " + i->first); + } + } +} + +void Interpreter::ReadStats(Stats &s, const PropertyList &props) { + for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) { + if (i->first == "atp") { + s.SetAttack(GetNumber(*i->second)); + } else if (i->first == "dfp") { + s.SetDefense(GetNumber(*i->second)); + } else if (i->first == "str") { + s.SetStrength(GetNumber(*i->second)); + } else if (i->first == "agl") { + s.SetAgility(GetNumber(*i->second)); + } else if (i->first == "int") { + s.SetIntelligence(GetNumber(*i->second)); + } else if (i->first == "gut") { + s.SetGut(GetNumber(*i->second)); + } else if (i->first == "mgr") { + s.SetMagicResistance(GetNumber(*i->second)); } else { - throw Error("unknown monster property: " + i->first); + throw Error("unknown Stats property: " + i->first); } } } diff --git a/src/loader/Interpreter.h b/src/loader/Interpreter.h index c2fc25f..9ba5924 100644 --- a/src/loader/Interpreter.h +++ b/src/loader/Interpreter.h @@ -8,13 +8,26 @@ #ifndef LOADER_INTERPRETER_H_ #define LOADER_INTERPRETER_H_ +#include "../geometry/Vector.h" +#include "../graphics/ComplexAnimation.h" + #include +#include #include #include #include +#include namespace battle { + class Hero; class Monster; + class Stats; +} + +namespace graphics { + class Animation; + class SimpleAnimation; + class Sprite; } namespace loader { @@ -22,6 +35,7 @@ namespace loader { class Definition; class ParsedSource; class PropertyList; +class Value; class Interpreter { @@ -42,14 +56,38 @@ public: void ReadSource(); private: + void ReadDefinition(const Definition &); void ReadLiteral(const Definition &); void ReadObject(const Definition &); + graphics::Animation *GetAnimation(const Value &); + const std::vector &GetValueArray(const Value &); + const std::vector &GetPropertyListArray(const Value &); + bool GetBoolean(const Value &); + SDL_Surface *GetImage(const Value &); + int GetNumber(const Value &); + const PropertyList *GetPropertyList(const Value &); + graphics::Sprite *GetSprite(const Value &); + const char *GetString(const Value &); + geometry::Vector GetVector(const Value &); + + void ReadComplexAnimation(graphics::ComplexAnimation &, const PropertyList &); + void ReadComplexAnimationFrame(graphics::ComplexAnimation::FrameProp &, const PropertyList &); + void ReadHero(battle::Hero &, const PropertyList &); void ReadMonster(battle::Monster &, const PropertyList &); + void ReadSimpleAnimation(graphics::SimpleAnimation &, const PropertyList &); + void ReadSprite(graphics::Sprite &, const PropertyList &); + void ReadStats(battle::Stats &, const PropertyList &); private: const ParsedSource &source; - std::vector monsters; + std::set parsedDefinitions; + + std::map animations; + std::map heroes; + std::map monsters; + std::map numbers; + std::map sprites; }; diff --git a/test-data/test.l2s b/test-data/test.l2s index ef1cce2..7357381 100644 --- a/test-data/test.l2s +++ b/test-data/test.l2s @@ -10,14 +10,15 @@ export Monster lizard { }, level: 1, maxHealth: 8, + health: 8, stats: Stats { - attack: 14, - defense: 6, - strength: 6, - agility: 6, - intelligence: 6, - gut: 6, - magicResistance: 6 + atp: 14, + dfp: 6, + str: 6, + agl: 6, + int: 6, + gut: 6, + mgr: 6 }, attackAnimation: SimpleAnimation { sprite: Sprite { @@ -43,13 +44,13 @@ export Hero maxim { mana: 20, ip: 0, stats: Stats { - attack: 28, - defense: 22, - strength: 28, - agility: 17, - intelligence: 14, - gut: 100, - magicResistance: 10 + atp: 28, + dfp: 22, + str: 28, + agl: 17, + int: 14, + gut: 100, + mgr: 10 }, attackAnimation: ComplexAnimation { sprite: maximSprite, -- 2.39.2