This introduces the capability of loading l2 formatted source files.
The syntax for those is described here:
http://luke.redirectme.net/redmine/projects/l2e/wiki/LoaderSource
Please note that this method of loading data is very inefficient, but
convenient. Efficiency issues will be adressed by a binary file format
which mentioned source files can be compiled to.
Also, some representations have been adapted to a more link-friendly
structure and most of the configuration code in main has been moved to
their respective l2s files residing in /test-data/ .
# All of the sources participating in the build are defined here
-include sources.mk
-include src/sdl/subdir.mk
+-include src/loader/subdir.mk
-include src/graphics/subdir.mk
-include src/common/subdir.mk
-include src/battle/states/subdir.mk
SUBDIRS := \
src/sdl \
src \
+src/loader \
src/graphics \
src/common \
src/battle/states \
--- /dev/null
+################################################################################
+# Automatically-generated file. Do not edit!
+################################################################################
+
+# Add inputs and outputs from these tool invocations to the build variables
+CPP_SRCS += \
+../src/loader/Interpreter.cpp \
+../src/loader/ParsedSource.cpp \
+../src/loader/Parser.cpp \
+../src/loader/Tokenizer.cpp \
+../src/loader/utility.cpp
+
+OBJS += \
+./src/loader/Interpreter.o \
+./src/loader/ParsedSource.o \
+./src/loader/Parser.o \
+./src/loader/Tokenizer.o \
+./src/loader/utility.o
+
+CPP_DEPS += \
+./src/loader/Interpreter.d \
+./src/loader/ParsedSource.d \
+./src/loader/Parser.d \
+./src/loader/Tokenizer.d \
+./src/loader/utility.d
+
+
+# Each subdirectory must supply rules for building sources it contributes
+src/loader/%.o: ../src/loader/%.cpp
+ @echo 'Building file: $<'
+ @echo 'Invoking: GCC C++ Compiler'
+ g++ -I/usr/include/SDL -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<"
+ @echo 'Finished building: $<'
+ @echo ' '
+
+
# All of the sources participating in the build are defined here
-include sources.mk
-include src/sdl/subdir.mk
+-include src/loader/subdir.mk
-include src/graphics/subdir.mk
-include src/common/subdir.mk
-include src/battle/states/subdir.mk
SUBDIRS := \
src/sdl \
src \
+src/loader \
src/graphics \
src/common \
src/battle/states \
--- /dev/null
+################################################################################
+# Automatically-generated file. Do not edit!
+################################################################################
+
+# Add inputs and outputs from these tool invocations to the build variables
+CPP_SRCS += \
+../src/loader/Interpreter.cpp \
+../src/loader/ParsedSource.cpp \
+../src/loader/Parser.cpp \
+../src/loader/Tokenizer.cpp \
+../src/loader/utility.cpp
+
+OBJS += \
+./src/loader/Interpreter.o \
+./src/loader/ParsedSource.o \
+./src/loader/Parser.o \
+./src/loader/Tokenizer.o \
+./src/loader/utility.o
+
+CPP_DEPS += \
+./src/loader/Interpreter.d \
+./src/loader/ParsedSource.d \
+./src/loader/Parser.d \
+./src/loader/Tokenizer.d \
+./src/loader/utility.d
+
+
+# Each subdirectory must supply rules for building sources it contributes
+src/loader/%.o: ../src/loader/%.cpp
+ @echo 'Building file: $<'
+ @echo 'Invoking: GCC C++ Compiler'
+ g++ -I/usr/include/SDL -O3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<"
+ @echo 'Finished building: $<'
+ @echo ' '
+
+
void BattleState::EnterState(Application &ctrl, SDL_Surface *screen) {
for (int i(0); i < 4; ++i) {
heroes[i].Position() = heroesLayout->CalculatePosition(i, background->w, background->h);
- heroes[i].SpellMenu() = res->spellMenuPrototype;
+ heroes[i].SpellMenu() = *res->spellMenuProperties;
heroes[i].UpdateSpellMenu();
- heroes[i].IkariMenu() = res->ikariMenuPrototype;
+ heroes[i].IkariMenu() = *res->ikariMenuProperties;
heroes[i].UpdateIkariMenu(res);
heroTags[i] = HeroTag(this, i);
smallHeroTags[i] = SmallHeroTag(this, i);
smallHeroTagPositions[2] = Vector<int>(xOffset + tagWidth, yOffset);
smallHeroTagPositions[3] = Vector<int>(xOffset + 3 * tagWidth, yOffset);
- itemMenu = res->itemMenuPrototype;
+ itemMenu = *res->itemMenuProperties;
LoadInventory();
}
SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, 0, 0, 0));
rect.y += res->normalFont->CharHeight() / 8;
rect.h -= res->normalFont->CharHeight() / 4;
- SDL_FillRect(screen, &rect, res->heroesBgColor);
+ SDL_FillRect(screen, &rect, res->heroesBgColor.MapRGB(screen->format));
for (int i(0); i < numHeroes; ++i) {
smallHeroTags[i].Render(screen, tagWidth, tagHeight, smallHeroTagPositions[i] + offset);
#ifndef BATTLE_RESOURCES_H_
#define BATTLE_RESOURCES_H_
-#include "../graphics/Menu.h"
+#include "../graphics/Color.h"
#include <SDL.h>
graphics::Sprite *itemTargetCursor;
const char *spellMenuHeadline;
- graphics::Menu<const common::Spell *> spellMenuPrototype;
+ graphics::MenuProperties *spellMenuProperties;
common::Inventory *inventory;
const char *itemMenuHeadline;
- graphics::Menu<const common::Item *> itemMenuPrototype;
+ graphics::MenuProperties *itemMenuProperties;
const char *ikariMenuHeadline;
- graphics::Menu<const common::Item *> ikariMenuPrototype;
+ graphics::MenuProperties *ikariMenuProperties;
const char *noEquipmentText;
const char *escapeText;
int ikariLabelCol;
int ikariLabelRow;
- Uint32 heroesBgColor;
+ graphics::Color heroesBgColor;
Resources()
, itemTargetCursor(0)
, spellMenuHeadline("")
+ , spellMenuProperties(0)
, inventory(0)
, itemMenuHeadline("")
+ , itemMenuProperties(0)
, ikariMenuHeadline("")
+ , ikariMenuProperties(0)
, noEquipmentText("")
, escapeText("")
, ikariLabelCol(0)
, ikariLabelRow(0)
- , heroesBgColor(0)
{ }
};
Uint8 Gut() const { return gut; }
Uint16 MagicResistance() const { return magicResistance; }
+ void SetAttack(Uint16 a) { attack = a; }
+ void SetDefense(Uint16 d) { defense = d; }
+ void SetStrength(Uint16 s) { strength = s; }
+ void SetAgility(Uint16 a) { agility = a; }
+ void SetIntelligence(Uint16 i) { intelligence = i; }
+ void SetGut(Uint8 g) { gut = g; }
+ void SetMagicResistance(Uint16 m) { magicResistance = m; }
+
private:
Uint16 attack;
Uint16 defense;
bool TargetsMultiple() const { return (mode & COUNT_MASK) == MULTIPLE; }
bool TargetsSingle() const { return (mode & COUNT_MASK) == SINGLE; }
+ void TargetAll() { mode = (mode & FACTION_MASK) | ALL; }
+ void TargetMultiple() { mode = (mode & FACTION_MASK) | MULTIPLE; }
+ void TargetSingle() { mode = (mode & FACTION_MASK) | SINGLE; }
+ void TargetAlly() { mode = ALLY | (mode & COUNT_MASK); }
+ void TargetEnemy() { mode = ENEMY | (mode & COUNT_MASK); }
+
void TargetAllEnemies() { mode = ENEMY | ALL; }
void TargetMultipleEnemies() { mode = ENEMY | MULTIPLE; }
void TargetSingleEnemy() { mode = ENEMY | SINGLE; }
virtual ~Animation() { };
public:
-
const Sprite *GetSprite() const { return sprite; }
int FrameTime() const { return frameTime; }
bool Repeat() const { return repeat; }
+public:
+ void SetSprite(const Sprite *s) { sprite = s; }
+ void SetFrameTime(int t) { frameTime = t; }
+ void SetRepeat(bool r) { repeat = r; }
+
public:
virtual int NumFrames() const = 0;
virtual int Col(int frame) const = 0;
--- /dev/null
+/*
+ * Color.h
+ *
+ * Created on: Sep 1, 2012
+ * Author: holy
+ */
+
+#ifndef GRAPHICS_COLOR_H_
+#define GRAPHICS_COLOR_H_
+
+#include <SDL.h>
+
+namespace graphics {
+
+class Color {
+
+public:
+ Color() :r(0), g(0), b(0), a(255) { }
+ Color(Uint8 r, Uint8 g, Uint8 b, Uint8 a = 255) : r(r), g(g), b(b), a(a) { }
+
+public:
+ Uint8 RedChannel() const { return r; }
+ Uint8 GreenChannel() const { return g; }
+ Uint8 BlueChannel() const { return b; }
+ Uint8 AlphaChannel() const { return a; }
+
+ Uint32 MapRGB(SDL_PixelFormat *f) const { return SDL_MapRGB(f, r, g, b); }
+ Uint32 MapRGBA(SDL_PixelFormat *f) const { return SDL_MapRGBA(f, r, g, b, a); }
+
+ void SetRedChannel(Uint8 i) { r = i; }
+ void SetGreenChannel(Uint8 i) { g = i; }
+ void SetBlueChannel(Uint8 i) { b = i; }
+ void SetAlphaChannel(Uint8 i) { a = i; }
+
+private:
+ Uint8 r, g, b, a;
+
+};
+
+}
+
+#endif /* GRAPHICS_COLOR_H_ */
}
}
-protected:
- virtual int NumFrames() const { return frames.size(); };
- virtual int Col(int frame) const { return frames[frame].col; }
- virtual int Row(int frame) const { return frames[frame].row; }
- virtual geometry::Vector<int> Offset(int frame) const { return frames[frame].disposition; }
-
-private:
+public:
struct FrameProp {
+ FrameProp() : col(0), row(0) { }
FrameProp(int col, int row, const geometry::Vector<int> &disposition)
: col(col), row(row), disposition(disposition) {}
int col;
int row;
geometry::Vector<int> disposition;
};
+ void AddFrame(const FrameProp &f) { frames.push_back(f); }
+
+protected:
+ virtual int NumFrames() const { return frames.size(); };
+ virtual int Col(int frame) const { return frames[frame].col; }
+ virtual int Row(int frame) const { return frames[frame].row; }
+ virtual geometry::Vector<int> Offset(int frame) const { return frames[frame].disposition; }
+
+private:
std::vector<FrameProp> frames;
};
#include "Font.h"
#include <cmath>
+#include <iostream>
using geometry::Vector;
using std::pow;
namespace graphics {
void Font::DrawChar(char c, SDL_Surface *dest, const Vector<int> &position) const {
+ if (!sprite) return;
+
int col(colOffset + (c % 0x10));
int row(rowOffset + (c / 0x10));
sprite->Draw(dest, position, col, row);
}
void Font::DrawString(const char *s, SDL_Surface *dest, const Vector<int> &positionIn, int maxChars) const {
+ if (!sprite) return;
+
Vector<int> position(positionIn);
Vector<int> step(CharWidth(), 0);
for (int i(0); s[i] && (maxChars <= 0 || i < maxChars); ++i, position += step) {
}
void Font::DrawDigit(int digit, SDL_Surface *dest, const Vector<int> &position) const {
+ if (!sprite) return;
+
DrawChar(digit + 0x30, dest, position);
}
void Font::DrawNumber(int numberIn, SDL_Surface *dest, const Vector<int> &positionIn, int digits) const {
+ if (!sprite) return;
+
int number(numberIn);
if (digits > 0 && numberIn >= pow(10.0, digits)) {
numberIn = pow(10.0, digits) - 1;
class Font {
public:
- explicit Font(const Sprite *sprite, int colOffset = 0, int rowOffset = 0)
+ explicit Font(const Sprite *sprite = 0, int colOffset = 0, int rowOffset = 0)
: sprite(sprite), colOffset(colOffset), rowOffset(rowOffset) {
}
void DrawDigit(int d, SDL_Surface *dest, const geometry::Vector<int> &position) const;
void DrawNumber(int n, SDL_Surface *dest, const geometry::Vector<int> &position, int digits = 0) const;
+public:
+ void SetSprite(const Sprite *s) { sprite = s; }
+ void SetColOffset(int n) { colOffset = n; }
+ void SetRowOffset(int n) { rowOffset = n; }
+
private:
const Sprite *sprite;
int colOffset;
// TODO: maybe create a cache for frames?
void Frame::Draw(SDL_Surface *dest, const Vector<int> &position, int width, int height) const {
+ if (!surface) {
+ SDL_Rect rect;
+ rect.x = position.X();
+ rect.y = position.Y();
+ rect.w = width;
+ rect.h = height;
+ SDL_FillRect(dest, &rect, SDL_MapRGB(dest->format, 0xFF, 0x00, 0x00));
+ return;
+ }
// top-left corner
SDL_Rect srcRect;
srcRect.x = offset.X();
class Frame {
public:
- Frame(SDL_Surface *s, int borderWidth, int borderHeight, int repeatWidth = 1, int repeatHeight = 1, int xOffset = 0, int yOffset = 0)
+ explicit Frame(SDL_Surface *s = 0, int borderWidth = 1, int borderHeight = 1, int repeatWidth = 1, int repeatHeight = 1, int xOffset = 0, int yOffset = 0)
: surface(s), borderSize(borderWidth, borderHeight), repeatSize(repeatWidth, repeatHeight), offset(xOffset, yOffset) { }
public:
const geometry::Vector<int> RepeatSize() const { return repeatSize; }
void Draw(SDL_Surface *dest, const geometry::Vector<int> &position, int width, int height) const;
+public:
+ void SetSurface(SDL_Surface *s) { surface = s; }
+ void SetBorderSize(const geometry::Vector<int> &s) { borderSize = s; }
+ void SetRepeatSize(const geometry::Vector<int> &s) { repeatSize = s; }
+ void SetOffset(const geometry::Vector<int> &o) { offset = o; }
+
private:
SDL_Surface *surface;
geometry::Vector<int> borderSize;
int filledWidth = fill * (width - startWidth - endWidth) / 255;
int emptyWidth = (255 - fill) * (width - startWidth - endWidth) / 255;
+ if (!surface) {
+ destRect.x = position.X();
+ destRect.y = position.Y();
+ destRect.w = filledWidth + startWidth;
+ destRect.h = height;
+ SDL_FillRect(dest, &destRect, SDL_MapRGB(dest->format, 0x00, 0xFF, 0x00));
+ destRect.x += destRect.w;
+ destRect.w = emptyWidth + endWidth;
+ SDL_FillRect(dest, &destRect, SDL_MapRGB(dest->format, 0xFF, 0x00, 0x00));
+ return;
+ }
+
// start
srcRect.w = startWidth;
srcRect.h = height;
destRect.y = position.Y();
// full part
if (fill == 0) {
- srcRect.x = emptyX;
- srcRect.y = emptyY;
+ srcRect.x = emptyOffset.X();
+ srcRect.y = emptyOffset.Y();
SDL_BlitSurface(surface, &srcRect, dest, &destRect);
} else {
- srcRect.x = fullX;
- srcRect.y = fullY;
+ srcRect.x = fullOffset.X();
+ srcRect.y = fullOffset.Y();
SDL_BlitSurface(surface, &srcRect, dest, &destRect);
}
destRect.x = position.X() + startWidth;
// fill
- srcRect.x = fullX + startWidth;
- srcRect.y = fullY;
+ srcRect.x = fullOffset.X() + startWidth;
+ srcRect.y = fullOffset.Y();
srcRect.w = repeatWidth;
while (filledWidth > repeatWidth) {
SDL_BlitSurface(surface, &srcRect, dest, &destRect);
destRect.x += repeatWidth;
filledWidth -= repeatWidth;
}
- srcRect.x = emptyX + startWidth;
- srcRect.y = emptyY;
+ srcRect.x = emptyOffset.X() + startWidth;
+ srcRect.y = emptyOffset.Y();
while (emptyWidth > repeatWidth) {
SDL_BlitSurface(surface, &srcRect, dest, &destRect);
destRect.x += repeatWidth;
// end
srcRect.w = endWidth;
if (fill == 255) {
- srcRect.x = fullX + startWidth + repeatWidth;
- srcRect.y = fullY;
+ srcRect.x = fullOffset.X() + startWidth + repeatWidth;
+ srcRect.y = fullOffset.Y();
SDL_BlitSurface(surface, &srcRect, dest, &destRect);
} else {
- srcRect.x = emptyX + startWidth + repeatWidth;
- srcRect.y = emptyY;
+ srcRect.x = emptyOffset.X() + startWidth + repeatWidth;
+ srcRect.y = emptyOffset.Y();
SDL_BlitSurface(surface, &srcRect, dest, &destRect);
}
class Gauge {
public:
- Gauge(SDL_Surface *s, int fullX, int fullY, int emptyX, int emptyY, int height, int startWidth, int repeatWidth, int endWidth)
- : surface(s), fullX(fullX), fullY(fullY), emptyX(emptyX), emptyY(emptyY), height(height), startWidth(startWidth), repeatWidth(repeatWidth), endWidth(endWidth) { }
+ explicit Gauge(SDL_Surface *s = 0, int fullX = 0, int fullY = 0, int emptyX = 0, int emptyY = 0, int height = 1, int startWidth = 0, int repeatWidth = 1, int endWidth = 0)
+ : surface(s), fullOffset(fullX, fullY), emptyOffset(emptyX, emptyY), height(height), startWidth(startWidth), repeatWidth(repeatWidth), endWidth(endWidth) { }
public:
int MinWidth() const { return startWidth + endWidth; }
int Height() const { return height; }
void Draw(SDL_Surface *dest, const geometry::Vector<int> &position, int width, Uint8 fill) const;
+public:
+ void SetSurface(SDL_Surface *s) { surface = s; }
+ void SetFullOffset(const geometry::Vector<int> &o) { fullOffset = o; }
+ void SetEmptyOffset(const geometry::Vector<int> &o) { emptyOffset = o; }
+ void SetHeight(int h) { height = h; }
+ void SetStartWidth(int w) { startWidth = w; }
+ void SetRepeatWidth(int w) { repeatWidth = w; }
+ void SetEndWidth(int w) { endWidth = w; }
+
private:
SDL_Surface *surface;
- int fullX;
- int fullY;
- int emptyX;
- int emptyY;
+ geometry::Vector<int> fullOffset;
+ geometry::Vector<int> emptyOffset;
int height;
int startWidth;
int repeatWidth;
class Sprite;
+struct MenuProperties {
+ const Font *font;
+ const Font *disabledFont;
+ const Sprite *cursor;
+ int charsPerEntry;
+ int rows;
+ int rowGap;
+ int iconSpace;
+ int cols;
+ int colGap;
+ int charsPerNumber;
+ int charsPerAdditionalText;
+ int additionalTextGap;
+ char delimiter;
+
+ MenuProperties()
+ : font(0), disabledFont(0), cursor(0)
+ , charsPerEntry(0), rows(0), rowGap(0)
+ , iconSpace(0), cols(0), colGap(0)
+ , charsPerNumber(0), charsPerAdditionalText(0)
+ , additionalTextGap(0), delimiter(':') { }
+
+ MenuProperties(const Font *font, const Font *disabledFont, const Sprite *cursor, int charsPerEntry, int rows, int rowGap, int iconSpace, int cols, int colGap, int charsPerNumber, char delimiter, int charsPerAdditionalText, int additionalTextGap)
+ : font(font), disabledFont(disabledFont), cursor(cursor), charsPerEntry(charsPerEntry), rows(rows), rowGap(rowGap), iconSpace(iconSpace), cols(cols), colGap(colGap), charsPerNumber(charsPerNumber), charsPerAdditionalText(charsPerAdditionalText), additionalTextGap(additionalTextGap), delimiter(delimiter) { }
+};
+
template<class T>
-class Menu {
+class Menu
+: private MenuProperties {
public:
Menu();
+ Menu(const MenuProperties &);
Menu(const Font *font, const Font *disabledFont, const Sprite *cursor, int charsPerEntry, int rows, int rowGap = 0, int iconSpace = 0, int cols = 1, int colGap = 0, int charsPerNumber = 0, char delimiter = ':', int charsPerAdditionalText = 0, int additionalTextGap = 0);
public:
T value;
bool enabled;
};
- const Font *font;
- const Font *disabledFont;
- const Sprite *cursor;
std::vector<Entry> entries;
- int charsPerEntry;
- int rows;
- int rowGap;
- int iconSpace;
- int cols;
- int colGap;
int selected;
int topRow;
- int charsPerNumber;
- int charsPerAdditionalText;
- int additionalTextGap;
- char delimiter;
};
template<class T>
Menu<T>::Menu()
-: font(0)
-, disabledFont(0)
-, cursor(0)
-, charsPerEntry(0)
-, rows(0)
-, rowGap(0)
-, iconSpace(0)
-, cols(0)
-, colGap(0)
+: MenuProperties()
+, selected(0)
+, topRow(0) {
+
+}
+
+template<class T>
+Menu<T>::Menu(const MenuProperties &p)
+: MenuProperties(p)
, selected(0)
-, topRow(0)
-, charsPerNumber(0)
-, charsPerAdditionalText(0)
-, additionalTextGap(0)
-, delimiter(':') {
+, topRow(0) {
}
template<class T>
Menu<T>::Menu(const Font *font, const Font *disabledFont, const Sprite *cursor, int charsPerEntry, int rows, int rowGap, int iconSpace, int cols, int colGap, int charsPerNumber, char delimiter, int charsPerAdditionalText, int additionalTextGap)
-: font(font)
-, disabledFont(disabledFont ? disabledFont : font)
-, cursor(cursor)
-, charsPerEntry(charsPerEntry)
-, rows(rows)
-, rowGap(rowGap)
-, iconSpace(iconSpace)
-, cols(cols)
-, colGap(colGap)
+: MenuProperties(
+ font, disabledFont ? disabledFont : font,
+ cursor, charsPerEntry,
+ rows, rowGap, iconSpace,
+ cols, colGap, charsPerNumber,
+ delimiter,
+ charsPerAdditionalText,
+ additionalTextGap)
, selected(0)
-, topRow(0)
-, charsPerNumber(charsPerNumber)
-, charsPerAdditionalText(charsPerAdditionalText)
-, additionalTextGap(additionalTextGap)
-, delimiter(delimiter) {
+, topRow(0) {
}
SimpleAnimation(const Sprite *sprite, int frameTime, int numFrames, int col = 0, int row = 0, bool repeat = false)
: Animation(sprite, frameTime, repeat), numFrames(numFrames), col(col), row(row) { }
+public:
+ void SetNumFrames(int n) { numFrames = n; }
+ void SetCol(int c) { col = c; }
+ void SetRow(int r) { row = r; }
+
protected:
virtual int NumFrames() const { return numFrames; };
virtual int Col(int frame) const { return col; }
class Sprite {
public:
+ Sprite() : surface(0), size(64, 64), offset() { }
Sprite(SDL_Surface *s, int width, int height, int xOffset = 0, int yOffset = 0)
: surface(s), size(width, height), offset(xOffset, yOffset) { }
Draw(dest, position + offset, col, row);
}
+public:
+ void SetSurface(SDL_Surface *s) { surface = s; }
+ void SetSize(const geometry::Vector<int> &s) { size = s; }
+ void SetOffset(const geometry::Vector<int> &o) { offset = o; }
+
private:
SDL_Surface *surface;
geometry::Vector<int> size;
--- /dev/null
+/*
+ * Interpreter.cpp
+ *
+ * Created on: Aug 26, 2012
+ * Author: holy
+ */
+
+#include "Interpreter.h"
+
+#include "ParsedSource.h"
+#include "../battle/Hero.h"
+#include "../battle/Monster.h"
+#include "../battle/PartyLayout.h"
+#include "../battle/Resources.h"
+#include "../common/Ikari.h"
+#include "../common/Item.h"
+#include "../common/Spell.h"
+#include "../common/TargetingMode.h"
+#include "../graphics/ComplexAnimation.h"
+#include "../graphics/Font.h"
+#include "../graphics/Frame.h"
+#include "../graphics/Gauge.h"
+#include "../graphics/Menu.h"
+#include "../graphics/SimpleAnimation.h"
+#include "../graphics/Sprite.h"
+
+#include <algorithm>
+#include <cstring>
+#include <SDL_image.h>
+
+using battle::Hero;
+using battle::Monster;
+using battle::PartyLayout;
+using battle::Stats;
+using common::Ikari;
+using common::Item;
+using common::Spell;
+using common::TargetingMode;
+using graphics::Animation;
+using graphics::Color;
+using graphics::Font;
+using graphics::Frame;
+using graphics::Gauge;
+using graphics::ComplexAnimation;
+using graphics::SimpleAnimation;
+using graphics::Sprite;
+using geometry::Vector;
+using std::make_pair;
+using std::map;
+using std::set;
+using std::string;
+using std::vector;
+
+namespace loader {
+
+Interpreter::~Interpreter() {
+ for (vector<battle::Resources *>::const_iterator i(battleResources.begin()), end(battleResources.end()); i != end; ++i) {
+ delete *i;
+ }
+ for (vector<ComplexAnimation *>::const_iterator i(complexAnimations.begin()), end(complexAnimations.end()); i != end; ++i) {
+ delete *i;
+ }
+ for (vector<Font *>::const_iterator i(fonts.begin()), end(fonts.end()); i != end; ++i) {
+ delete *i;
+ }
+ for (vector<Frame *>::const_iterator i(frames.begin()), end(frames.end()); i != end; ++i) {
+ delete *i;
+ }
+ for (vector<Gauge *>::const_iterator i(gauges.begin()), end(gauges.end()); i != end; ++i) {
+ delete *i;
+ }
+ for (vector<Hero *>::const_iterator i(heroes.begin()), end(heroes.end()); i != end; ++i) {
+ delete *i;
+ }
+ for (vector<Ikari *>::const_iterator i(ikaris.begin()), end(ikaris.end()); i != end; ++i) {
+ delete *i;
+ }
+ for (vector<SDL_Surface *>::const_iterator i(images.begin()), end(images.end()); i != end; ++i) {
+ SDL_FreeSurface(*i);
+ }
+ for (vector<Item *>::const_iterator i(items.begin()), end(items.end()); i != end; ++i) {
+ delete *i;
+ }
+ for (vector<graphics::MenuProperties *>::const_iterator i(menuProperties.begin()), end(menuProperties.end()); i != end; ++i) {
+ delete *i;
+ }
+ for (vector<Monster *>::const_iterator i(monsters.begin()), end(monsters.end()); i != end; ++i) {
+ delete *i;
+ }
+ for (vector<PartyLayout *>::const_iterator i(partyLayouts.begin()), end(partyLayouts.end()); i != end; ++i) {
+ delete *i;
+ }
+ for (vector<SimpleAnimation *>::const_iterator i(simpleAnimations.begin()), end(simpleAnimations.end()); i != end; ++i) {
+ delete *i;
+ }
+ for (vector<Spell *>::const_iterator i(spells.begin()), end(spells.end()); i != end; ++i) {
+ delete *i;
+ }
+ for (vector<Sprite *>::const_iterator i(sprites.begin()), end(sprites.end()); i != end; ++i) {
+ delete *i;
+ }
+ for (vector<const char *>::const_iterator i(strings.begin()), end(strings.end()); i != end; ++i) {
+ delete *i;
+ }
+ for (vector<TargetingMode *>::const_iterator i(targetingModes.begin()), end(targetingModes.end()); i != end; ++i) {
+ delete *i;
+ }
+}
+
+
+Animation *Interpreter::GetAnimation(const std::string &name) {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == COMPLEX_ANIMATION) {
+ return complexAnimations[i->second.index];
+ } else if (i->second.type == SIMPLE_ANIMATION) {
+ return simpleAnimations[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Animation");
+ }
+ } else {
+ throw Error("access to undefined Animation " + name);
+ }
+}
+
+battle::Resources *Interpreter::GetBattleResources(const std::string &name) {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == BATTLE_RESOURCES) {
+ return battleResources[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to BattleResources");
+ }
+ } else {
+ throw Error("access to undefined BattleResources " + name);
+ }
+}
+
+bool Interpreter::GetBoolean(const std::string &name) const {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == BOOLEAN) {
+ return booleans[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Boolean");
+ }
+ } else {
+ throw Error("access to undefined Boolean " + name);
+ }
+}
+
+const Color &Interpreter::GetColor(const std::string &name) const {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == COLOR) {
+ return colors[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Color");
+ }
+ } else {
+ throw Error("access to undefined Color " + name);
+ }
+}
+
+Font *Interpreter::GetFont(const std::string &name) {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == FONT) {
+ return fonts[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Font");
+ }
+ } else {
+ throw Error("access to undefined Font " + name);
+ }
+}
+
+Frame *Interpreter::GetFrame(const std::string &name) {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == FRAME) {
+ return frames[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Frame");
+ }
+ } else {
+ throw Error("access to undefined Frame " + name);
+ }
+}
+
+Gauge *Interpreter::GetGauge(const std::string &name) {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == GAUGE) {
+ return gauges[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Gauge");
+ }
+ } else {
+ throw Error("access to undefined Gauge " + name);
+ }
+}
+
+Hero *Interpreter::GetHero(const std::string &name) {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == HERO) {
+ return heroes[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Hero");
+ }
+ } else {
+ throw Error("access to undefined Hero " + name);
+ }
+}
+
+Ikari *Interpreter::GetIkari(const std::string &name) {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == IKARI) {
+ return ikaris[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Ikari");
+ }
+ } else {
+ throw Error("access to undefined Ikari " + name);
+ }
+}
+
+Item *Interpreter::GetItem(const std::string &name) {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == ITEM) {
+ return items[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Item");
+ }
+ } else {
+ throw Error("access to undefined Item " + name);
+ }
+}
+
+graphics::MenuProperties *Interpreter::GetMenuProperties(const std::string &name) {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == MENU_PROPERTIES) {
+ return menuProperties[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to MenuProperties");
+ }
+ } else {
+ throw Error("access to undefined MenuProperties " + name);
+ }
+}
+
+Monster *Interpreter::GetMonster(const std::string &name) {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == MONSTER) {
+ return monsters[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Monster");
+ }
+ } else {
+ throw Error("access to undefined Monster " + name);
+ }
+}
+
+int Interpreter::GetNumber(const std::string &name) const {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == NUMBER) {
+ return numbers[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Number");
+ }
+ } else {
+ throw Error("access to undefined Number " + name);
+ }
+}
+
+PartyLayout *Interpreter::GetPartyLayout(const std::string &name) {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == PARTY_LAYOUT) {
+ return partyLayouts[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to PartyLayout");
+ }
+ } else {
+ throw Error("access to undefined PartyLayout " + name);
+ }
+}
+
+const char *Interpreter::GetPath(const std::string &name) const {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == PATH) {
+ return strings[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Path");
+ }
+ } else {
+ throw Error("access to undefined Path " + name);
+ }
+}
+
+Spell *Interpreter::GetSpell(const std::string &name) {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == SPELL) {
+ return spells[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Spell");
+ }
+ } else {
+ throw Error("access to undefined Spell " + name);
+ }
+}
+
+Sprite *Interpreter::GetSprite(const std::string &name) {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == SPRITE) {
+ return sprites[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Sprite");
+ }
+ } else {
+ throw Error("access to undefined Sprite " + name);
+ }
+}
+
+const char *Interpreter::GetString(const std::string &name) const {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ // TODO: enable path to string casting some time
+ if (i->second.type == STRING /* || i->second.type == PATH */) {
+ return strings[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to String");
+ }
+ } else {
+ throw Error("access to undefined String " + name);
+ }
+}
+
+TargetingMode *Interpreter::GetTargetingMode(const std::string &name) {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == TARGETING_MODE) {
+ return targetingModes[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to TargetingMode");
+ }
+ } else {
+ throw Error("access to undefined TargetingMode " + name);
+ }
+}
+
+Vector<int> Interpreter::GetVector(const std::string &name) const {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == VECTOR) {
+ return vectors[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Vector");
+ }
+ } else {
+ throw Error("access to undefined Vector " + name);
+ }
+}
+
+
+void Interpreter::ReadSource() {
+ for (set<string>::const_iterator i(source.Exports().begin()), end(source.Exports().end()); i != end; ++i) {
+ 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);
+ }
+}
+
+void Interpreter::ReadLiteral(const Definition &dfn) {
+ switch (dfn.GetLiteral()->GetType()) {
+ case Literal::ARRAY_VALUES:
+ valueArrays.push_back(dfn.GetLiteral()->GetValues());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, VALUE_ARRAY, valueArrays.size() - 1)));
+ break;
+ case Literal::ARRAY_PROPS:
+ propertyListArrays.push_back(dfn.GetLiteral()->GetPropertyLists());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, PROPERTY_LIST_ARRAY, propertyListArrays.size() - 1)));
+ break;
+ case Literal::BOOLEAN:
+ booleans.push_back(dfn.GetLiteral()->GetBoolean());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, BOOLEAN, booleans.size() - 1)));
+ break;
+ case Literal::COLOR:
+ colors.push_back(Color(dfn.GetLiteral()->GetRed(), dfn.GetLiteral()->GetGreen(), dfn.GetLiteral()->GetBlue(), dfn.GetLiteral()->GetAlpha()));
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, COLOR, colors.size() - 1)));
+ break;
+ case Literal::NUMBER:
+ numbers.push_back(dfn.GetLiteral()->GetNumber());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, NUMBER, numbers.size() - 1)));
+ break;
+ case Literal::PATH:
+ {
+ char *str(new char[dfn.GetLiteral()->GetString().size() + 1]);
+ std::memcpy(str, dfn.GetLiteral()->GetString().c_str(), dfn.GetLiteral()->GetString().size());
+ str[dfn.GetLiteral()->GetString().size()] = '\0';
+ strings.push_back(str);
+ }
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, PATH, strings.size() - 1)));
+ break;
+ case Literal::STRING:
+ {
+ char *str(new char[dfn.GetLiteral()->GetString().size() + 1]);
+ std::memcpy(str, dfn.GetLiteral()->GetString().c_str(), dfn.GetLiteral()->GetString().size());
+ str[dfn.GetLiteral()->GetString().size()] = '\0';
+ strings.push_back(str);
+ }
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, STRING, strings.size() - 1)));
+ break;
+ case Literal::VECTOR:
+ vectors.push_back(Vector<int>(dfn.GetLiteral()->GetX(), dfn.GetLiteral()->GetY()));
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, VECTOR, vectors.size() - 1)));
+ break;
+ case Literal::OBJECT:
+ ReadObject(dfn);
+ break;
+ }
+}
+
+Animation *Interpreter::GetAnimation(const Value &v) {
+ if (v.IsLiteral()) {
+ if (v.GetLiteral().GetTypeName() == "ComplexAnimation") {
+ ComplexAnimation *a(new ComplexAnimation);
+ ReadComplexAnimation(*a, *v.GetLiteral().GetProperties());
+ complexAnimations.push_back(a);
+ return a;
+ } else {
+ SimpleAnimation *a(new SimpleAnimation);
+ ReadSimpleAnimation(*a, *v.GetLiteral().GetProperties());
+ simpleAnimations.push_back(a);
+ return a;
+ }
+ } else {
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetAnimation(v.GetIdentifier());
+ }
+}
+
+battle::Resources *Interpreter::GetBattleResources(const Value &v) {
+ if (v.IsLiteral()) {
+ battle::Resources *r(new battle::Resources);
+ ReadBattleResources(*r, *v.GetLiteral().GetProperties());
+ return r;
+ } else {
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetBattleResources(v.GetIdentifier());
+ }
+}
+
+bool Interpreter::GetBoolean(const Value &v) {
+ if (v.IsLiteral()) {
+ return v.GetLiteral().GetBoolean();
+ } else {
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetBoolean(v.GetIdentifier());
+ }
+}
+
+Color Interpreter::GetColor(const Value &v) {
+ if (v.IsLiteral()) {
+ return Color(v.GetLiteral().GetRed(), v.GetLiteral().GetGreen(), v.GetLiteral().GetBlue(), v.GetLiteral().GetAlpha());
+ } else {
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetColor(v.GetIdentifier());
+ }
+}
+
+Font *Interpreter::GetFont(const Value &v) {
+ if (v.IsLiteral()) {
+ Font *f(new Font);
+ ReadFont(*f, *v.GetLiteral().GetProperties());
+ return f;
+ } else {
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetFont(v.GetIdentifier());
+ }
+}
+
+Frame *Interpreter::GetFrame(const Value &v) {
+ if (v.IsLiteral()) {
+ Frame *f(new Frame);
+ ReadFrame(*f, *v.GetLiteral().GetProperties());
+ return f;
+ } else {
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetFrame(v.GetIdentifier());
+ }
+}
+
+Gauge *Interpreter::GetGauge(const Value &v) {
+ if (v.IsLiteral()) {
+ Gauge *g(new Gauge);
+ ReadGauge(*g, *v.GetLiteral().GetProperties());
+ return g;
+ } else {
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetGauge(v.GetIdentifier());
+ }
+}
+
+Hero *Interpreter::GetHero(const Value &v) {
+ if (v.IsLiteral()) {
+ Hero *h(new Hero);
+ ReadHero(*h, *v.GetLiteral().GetProperties());
+ return h;
+ } else {
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetHero(v.GetIdentifier());
+ }
+}
+
+Ikari *Interpreter::GetIkari(const Value &v) {
+ if (v.IsLiteral()) {
+ Ikari *i(new Ikari);
+ ReadIkari(*i, *v.GetLiteral().GetProperties());
+ return i;
+ } else {
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetIkari(v.GetIdentifier());
+ }
+}
+
+SDL_Surface *Interpreter::GetImage(const Value &v) {
+ string path(GetPath(v));
+ map<string, SDL_Surface *>::const_iterator i(imageCache.find(path));
+ if (i == imageCache.end()) {
+ SDL_Surface *image(IMG_Load(path.c_str()));
+ images.push_back(image);
+ imageCache.insert(make_pair(path, image));
+ return image;
+ } else {
+ return i->second;
+ }
+}
+
+Item *Interpreter::GetItem(const Value &v) {
+ if (v.IsLiteral()) {
+ Item *i(new Item);
+ ReadItem(*i, *v.GetLiteral().GetProperties());
+ return i;
+ } else {
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetItem(v.GetIdentifier());
+ }
+}
+
+graphics::MenuProperties *Interpreter::GetMenuProperties(const Value &v) {
+ if (v.IsLiteral()) {
+ graphics::MenuProperties *m(new graphics::MenuProperties);
+ ReadMenuProperties(*m, *v.GetLiteral().GetProperties());
+ return m;
+ } else {
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetMenuProperties(v.GetIdentifier());
+ }
+}
+
+Monster *Interpreter::GetMonster(const Value &v) {
+ if (v.IsLiteral()) {
+ Monster *m(new Monster);
+ ReadMonster(*m, *v.GetLiteral().GetProperties());
+ return m;
+ } else {
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetMonster(v.GetIdentifier());
+ }
+}
+
+int Interpreter::GetNumber(const Value &v) {
+ if (v.IsLiteral()) {
+ return v.GetLiteral().GetNumber();
+ } else {
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetNumber(v.GetIdentifier());
+ }
+}
+
+PartyLayout *Interpreter::GetPartyLayout(const Value &v) {
+ if (v.IsLiteral()) {
+ PartyLayout *l(new PartyLayout);
+ ReadPartyLayout(*l, *v.GetLiteral().GetProperties());
+ return l;
+ } else {
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetPartyLayout(v.GetIdentifier());
+ }
+}
+
+const char *Interpreter::GetPath(const Value &v) {
+ if (v.IsLiteral()) {
+ return v.GetLiteral().GetString().c_str();
+ } else {
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetPath(v.GetIdentifier());
+ }
+}
+
+const PropertyList *Interpreter::GetPropertyList(const Value &v) {
+ if (v.IsLiteral()) {
+ return v.GetLiteral().GetProperties();
+ } else {
+ throw Error("cannot reference property lists");
+ }
+}
+
+const vector<PropertyList *> &Interpreter::GetPropertyListArray(const Value &v) {
+ if (v.IsLiteral()) {
+ return v.GetLiteral().GetPropertyLists();
+ } else {
+ throw Error("cannot reference property list arrays");
+ }
+}
+
+Spell *Interpreter::GetSpell(const Value &v) {
+ if (v.IsLiteral()) {
+ Spell *s(new Spell);
+ ReadSpell(*s, *v.GetLiteral().GetProperties());
+ return s;
+ } else {
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetSpell(v.GetIdentifier());
+ }
+}
+
+Sprite *Interpreter::GetSprite(const Value &v) {
+ if (v.IsLiteral()) {
+ Sprite *s(new Sprite);
+ ReadSprite(*s, *v.GetLiteral().GetProperties());
+ return s;
+ } else {
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetSprite(v.GetIdentifier());
+ }
+}
+
+const char *Interpreter::GetString(const Value &v) {
+ if (v.IsLiteral()) {
+ return v.GetLiteral().GetString().c_str();
+ } else {
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetString(v.GetIdentifier());
+ }
+}
+
+TargetingMode *Interpreter::GetTargetingMode(const Value &v) {
+ if (v.IsLiteral()) {
+ TargetingMode *t(new TargetingMode);
+ ReadTargetingMode(*t, *v.GetLiteral().GetProperties());
+ return t;
+ } else {
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetTargetingMode(v.GetIdentifier());
+ }
+}
+
+Vector<int> Interpreter::GetVector(const Value &v) {
+ if (v.IsLiteral()) {
+ return Vector<int>(v.GetLiteral().GetX(), v.GetLiteral().GetY());
+ } else {
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetVector(v.GetIdentifier());
+ }
+}
+
+const vector<Value *> &Interpreter::GetValueArray(const Value &v) {
+ if (v.IsLiteral()) {
+ return v.GetLiteral().GetValues();
+ } else {
+ throw Error("cannot reference value arrays");
+ }
+}
+
+
+void Interpreter::ReadObject(const Definition &dfn) {
+ if (dfn.TypeName() == "BattleResources") {
+ battle::Resources *res(new battle::Resources);
+ int index(battleResources.size());
+ battleResources.push_back(res);
+ ReadBattleResources(*res, *dfn.GetProperties());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, BATTLE_RESOURCES, index)));
+ } else if (dfn.TypeName() == "ComplexAnimation") {
+ ComplexAnimation *animation(new ComplexAnimation);
+ int index(complexAnimations.size());
+ complexAnimations.push_back(animation);
+ ReadComplexAnimation(*animation, *dfn.GetProperties());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, COMPLEX_ANIMATION, index)));
+ } else if (dfn.TypeName() == "Font") {
+ Font *font(new Font);
+ int index(fonts.size());
+ fonts.push_back(font);
+ ReadFont(*font, *dfn.GetProperties());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, FONT, index)));
+ } else if (dfn.TypeName() == "Frame") {
+ Frame *frame(new Frame);
+ int index(frames.size());
+ frames.push_back(frame);
+ ReadFrame(*frame, *dfn.GetProperties());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, FRAME, index)));
+ } else if (dfn.TypeName() == "Gauge") {
+ Gauge *gauge(new Gauge);
+ int index(gauges.size());
+ gauges.push_back(gauge);
+ ReadGauge(*gauge, *dfn.GetProperties());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, GAUGE, index)));
+ } else if (dfn.TypeName() == "Hero") {
+ Hero *hero(new Hero);
+ int index(heroes.size());
+ heroes.push_back(hero);
+ ReadHero(*hero, *dfn.GetProperties());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, HERO, index)));
+ } else if (dfn.TypeName() == "Ikari") {
+ Ikari *ikari(new Ikari);
+ int index(ikaris.size());
+ ikaris.push_back(ikari);
+ ReadIkari(*ikari, *dfn.GetProperties());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, IKARI, index)));
+ } else if (dfn.TypeName() == "Item") {
+ Item *item(new Item);
+ int index(items.size());
+ items.push_back(item);
+ ReadItem(*item, *dfn.GetProperties());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, ITEM, index)));
+ } else if (dfn.TypeName() == "MenuProperties") {
+ graphics::MenuProperties *mprops(new graphics::MenuProperties);
+ int index(menuProperties.size());
+ menuProperties.push_back(mprops);
+ ReadMenuProperties(*mprops, *dfn.GetProperties());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, MENU_PROPERTIES, index)));
+ } else if (dfn.TypeName() == "Monster") {
+ Monster *monster(new Monster);
+ int index(monsters.size());
+ monsters.push_back(monster);
+ ReadMonster(*monster, *dfn.GetProperties());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, MONSTER, index)));
+ } else if (dfn.TypeName() == "PartyLayout") {
+ PartyLayout *layout(new PartyLayout);
+ int index(partyLayouts.size());
+ partyLayouts.push_back(layout);
+ ReadPartyLayout(*layout, *dfn.GetProperties());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, PARTY_LAYOUT, index)));
+ } else if (dfn.TypeName() == "SimpleAnimation") {
+ SimpleAnimation *animation(new SimpleAnimation);
+ int index(simpleAnimations.size());
+ simpleAnimations.push_back(animation);
+ ReadSimpleAnimation(*animation, *dfn.GetProperties());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, SIMPLE_ANIMATION, index)));
+ } else if (dfn.TypeName() == "Spell") {
+ Spell *spell(new Spell);
+ int index(spells.size());
+ spells.push_back(spell);
+ ReadSpell(*spell, *dfn.GetProperties());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, SPELL, index)));
+ } else if (dfn.TypeName() == "Sprite") {
+ Sprite *sprite(new Sprite);
+ int index(sprites.size());
+ sprites.push_back(sprite);
+ ReadSprite(*sprite, *dfn.GetProperties());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, SPRITE, index)));
+ } else if (dfn.TypeName() == "TargetingMode") {
+ TargetingMode *mode(new TargetingMode);
+ int index(targetingModes.size());
+ targetingModes.push_back(mode);
+ ReadTargetingMode(*mode, *dfn.GetProperties());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, TARGETING_MODE, index)));
+ } else {
+ throw Error("unhandled object type: " + dfn.TypeName());
+ }
+}
+
+
+void Interpreter::ReadBattleResources(battle::Resources &res, const PropertyList &props) {
+ for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
+ if (i->first == "swapCursor") {
+ res.swapCursor = GetSprite(*i->second);
+ } else if (i->first == "moveIcons") {
+ res.moveIcons = GetSprite(*i->second);
+ } else if (i->first == "attackIcons") {
+ res.attackIcons = GetSprite(*i->second);
+ } else if (i->first == "attackChoiceIcons") {
+ res.attackChoiceIcons = GetSprite(*i->second);
+ } else if (i->first == "titleFrame") {
+ res.titleFrame = GetFrame(*i->second);
+ } else if (i->first == "titleFont") {
+ res.titleFont = GetFont(*i->second);
+ } else if (i->first == "heroTagFrame") {
+ res.heroTagFrame = GetFrame(*i->second);
+ } else if (i->first == "activeHeroTagFrame") {
+ res.activeHeroTagFrame = GetFrame(*i->second);
+ } else if (i->first == "smallHeroTagFrame") {
+ res.smallHeroTagFrame = GetFrame(*i->second);
+ } else if (i->first == "lastSmallHeroTagFrame") {
+ res.lastSmallHeroTagFrame = GetFrame(*i->second);
+ } else if (i->first == "heroTagFont") {
+ res.heroTagFont = GetFont(*i->second);
+ } else if (i->first == "heroTagLabels") {
+ res.heroTagLabels = GetSprite(*i->second);
+ } else if (i->first == "healthGauge") {
+ res.healthGauge = GetGauge(*i->second);
+ } else if (i->first == "manaGauge") {
+ res.manaGauge = GetGauge(*i->second);
+ } else if (i->first == "ikariGauge") {
+ res.ikariGauge = GetGauge(*i->second);
+ } else if (i->first == "selectFrame") {
+ res.selectFrame = GetFrame(*i->second);
+ } else if (i->first == "normalFont") {
+ res.normalFont = GetFont(*i->second);
+ } else if (i->first == "disabledFont") {
+ res.disabledFont = GetFont(*i->second);
+ } else if (i->first == "menuCursor") {
+ res.menuCursor = GetSprite(*i->second);
+ } else if (i->first == "weaponTargetCursor") {
+ res.weaponTargetCursor = GetSprite(*i->second);
+ } else if (i->first == "magicTargetCursor") {
+ res.magicTargetCursor = GetSprite(*i->second);
+ } else if (i->first == "itemTargetCursor") {
+ res.itemTargetCursor = GetSprite(*i->second);
+ } else if (i->first == "spellMenuHeadline") {
+ res.spellMenuHeadline = GetString(*i->second);
+ } else if (i->first == "spellMenuProperties") {
+ res.spellMenuProperties = GetMenuProperties(*i->second);
+ } else if (i->first == "itemMenuHeadline") {
+ res.itemMenuHeadline = GetString(*i->second);
+ } else if (i->first == "itemMenuProperties") {
+ res.itemMenuProperties = GetMenuProperties(*i->second);
+ } else if (i->first == "ikariMenuHeadline") {
+ res.ikariMenuHeadline = GetString(*i->second);
+ } else if (i->first == "ikariMenuProperties") {
+ res.ikariMenuProperties = GetMenuProperties(*i->second);
+ } else if (i->first == "noEquipmentText") {
+ res.noEquipmentText = GetString(*i->second);
+ } else if (i->first == "escapeText") {
+ res.escapeText = GetString(*i->second);
+ } else if (i->first == "numberAnimationPrototype") {
+ res.numberAnimationPrototype = GetAnimation(*i->second);
+ } else if (i->first == "bigNumberSprite") {
+ res.bigNumberSprite = GetSprite(*i->second);
+ } else if (i->first == "greenNumberSprite") {
+ res.greenNumberSprite = GetSprite(*i->second);
+ } else if (i->first == "weaponMenuIcon") {
+ res.weaponMenuIcon = GetSprite(*i->second);
+ } else if (i->first == "armorMenuIcon") {
+ res.armorMenuIcon = GetSprite(*i->second);
+ } else if (i->first == "shieldMenuIcon") {
+ res.shieldMenuIcon = GetSprite(*i->second);
+ } else if (i->first == "helmetMenuIcon") {
+ res.helmetMenuIcon = GetSprite(*i->second);
+ } else if (i->first == "ringMenuIcon") {
+ res.ringMenuIcon = GetSprite(*i->second);
+ } else if (i->first == "jewelMenuIcon") {
+ res.jewelMenuIcon = GetSprite(*i->second);
+ } else if (i->first == "levelLabelCol") {
+ res.levelLabelCol = GetNumber(*i->second);
+ } else if (i->first == "levelLabelRow") {
+ res.levelLabelRow = GetNumber(*i->second);
+ } else if (i->first == "healthLabelCol") {
+ res.healthLabelCol = GetNumber(*i->second);
+ } else if (i->first == "healthLabelRow") {
+ res.healthLabelRow = GetNumber(*i->second);
+ } else if (i->first == "manaLabelCol") {
+ res.manaLabelCol = GetNumber(*i->second);
+ } else if (i->first == "manaLabelRow") {
+ res.manaLabelRow = GetNumber(*i->second);
+ } else if (i->first == "moveLabelCol") {
+ res.moveLabelCol = GetNumber(*i->second);
+ } else if (i->first == "moveLabelRow") {
+ res.moveLabelRow = GetNumber(*i->second);
+ } else if (i->first == "ikariLabelCol") {
+ res.ikariLabelCol = GetNumber(*i->second);
+ } else if (i->first == "ikariLabelRow") {
+ res.ikariLabelRow = GetNumber(*i->second);
+ } else if (i->first == "heroesBgColor") {
+ res.heroesBgColor = GetColor(*i->second);
+ } else {
+ throw Error("unknown BattleResources property: " + i->first);
+ }
+ }
+}
+
+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<PropertyList *> &values(GetPropertyListArray(*i->second));
+ for (vector<PropertyList *>::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::ReadFont(Font &f, const PropertyList &props) {
+ for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
+ if (i->first == "sprite") {
+ f.SetSprite(GetSprite(*i->second));
+ } else if (i->first == "columnoffset") {
+ f.SetColOffset(GetNumber(*i->second));
+ } else if (i->first == "rowoffset") {
+ f.SetRowOffset(GetNumber(*i->second));
+ } else {
+ throw Error("unknown Font property: " + i->first);
+ }
+ }
+}
+
+void Interpreter::ReadFrame(Frame &f, const PropertyList &props) {
+ for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
+ if (i->first == "image") {
+ f.SetSurface(GetImage(*i->second));
+ } else if (i->first == "border") {
+ f.SetBorderSize(GetVector(*i->second));
+ } else if (i->first == "repeat") {
+ f.SetRepeatSize(GetVector(*i->second));
+ } else if (i->first == "offset") {
+ f.SetOffset(GetVector(*i->second));
+ } else {
+ throw Error("unknown Frame property: " + i->first);
+ }
+ }
+}
+
+void Interpreter::ReadGauge(Gauge &g, const PropertyList &props) {
+ for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
+ if (i->first == "image") {
+ g.SetSurface(GetImage(*i->second));
+ } else if (i->first == "full") {
+ g.SetFullOffset(GetVector(*i->second));
+ } else if (i->first == "empty") {
+ g.SetEmptyOffset(GetVector(*i->second));
+ } else if (i->first == "height") {
+ g.SetHeight(GetNumber(*i->second));
+ } else if (i->first == "start") {
+ g.SetStartWidth(GetNumber(*i->second));
+ } else if (i->first == "repeat") {
+ g.SetRepeatWidth(GetNumber(*i->second));
+ } else if (i->first == "end") {
+ g.SetEndWidth(GetNumber(*i->second));
+ } else {
+ throw Error("unknown Gauge property: " + i->first);
+ }
+ }
+}
+
+void Interpreter::ReadIkari(Ikari &ikari, const PropertyList &props) {
+ for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
+ if (i->first == "name") {
+ ikari.SetName(GetString(*i->second));
+ } else if (i->first == "cost") {
+ ikari.SetCost(GetNumber(*i->second));
+ } else if (i->first == "targets") {
+ ikari.GetTargetingMode() = *GetTargetingMode(*i->second);
+ } else if (i->first == "magical") {
+ if (GetBoolean(*i->second)) {
+ ikari.SetMagical();
+ }
+ } else if (i->first == "physical") {
+ if (GetBoolean(*i->second)) {
+ ikari.SetPhysical();
+ }
+ } else {
+ throw Error("unknown Ikari property: " + i->first);
+ }
+ }
+}
+
+void Interpreter::ReadItem(Item &item, const PropertyList &props) {
+ for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
+ if (i->first == "name") {
+ item.SetName(GetString(*i->second));
+ } else if (i->first == "menuicon") {
+ item.SetMenuIcon(GetSprite(*i->second));
+ } else if (i->first == "battle") {
+ if (GetBoolean(*i->second)) {
+ item.SetUsableInBattle();
+ }
+ } else if (i->first == "targets") {
+ item.GetTargetingMode() = *GetTargetingMode(*i->second);
+ } else if (i->first == "ikari") {
+ item.SetIkari(GetIkari(*i->second));
+ } else if (i->first == "attackanimation") {
+ item.SetAttackAnimation(GetAnimation(*i->second));
+ } else {
+ throw Error("unknown Item 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::ReadMenuProperties(graphics::MenuProperties &mprops, const PropertyList &props) {
+ for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
+ if (i->first == "font") {
+ mprops.font = GetFont(*i->second);
+ } else if (i->first == "disabledFont") {
+ mprops.disabledFont = GetFont(*i->second);
+ } else if (i->first == "cursor") {
+ mprops.cursor = GetSprite(*i->second);
+ } else if (i->first == "charsPerEntry") {
+ mprops.charsPerEntry = GetNumber(*i->second);
+ } else if (i->first == "rows") {
+ mprops.rows = GetNumber(*i->second);
+ } else if (i->first == "rowGap") {
+ mprops.rowGap = GetNumber(*i->second);
+ } else if (i->first == "iconSpace") {
+ mprops.iconSpace = GetNumber(*i->second);
+ } else if (i->first == "cols") {
+ mprops.cols = GetNumber(*i->second);
+ } else if (i->first == "colGap") {
+ mprops.colGap = GetNumber(*i->second);
+ } else if (i->first == "delimiter") {
+ mprops.delimiter = *GetString(*i->second);
+ } else if (i->first == "charsPerNumber") {
+ mprops.charsPerNumber = GetNumber(*i->second);
+ } else if (i->first == "charsPerAdditionalText") {
+ mprops.charsPerAdditionalText = GetNumber(*i->second);
+ } else if (i->first == "additionalTextGap") {
+ mprops.additionalTextGap = GetNumber(*i->second);
+ } else {
+ throw Error("unknown MenuProperties 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") {
+ 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 if (i->first == "meleeAnimation") {
+ m.SetMeleeAnimation(GetAnimation(*i->second));
+ } else {
+ throw Error("unknown Monster property: " + i->first);
+ }
+ }
+}
+
+void Interpreter::ReadPartyLayout(PartyLayout &p, const PropertyList &props) {
+ for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
+ if (i->first == "positions") {
+ const vector<Value *> &positions(GetValueArray(*i->second));
+ for (vector<Value *>::const_iterator j(positions.begin()), end(positions.end()); j != end; ++j) {
+ p.AddPosition(GetVector(**j));
+ }
+ } else {
+ throw Error("unknown PartyLayout 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::ReadSpell(Spell &s, const PropertyList &props) {
+ for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
+ if (i->first == "name") {
+ s.SetName(GetString(*i->second));
+ } else if (i->first == "cost") {
+ s.SetCost(GetNumber(*i->second));
+ } else if (i->first == "battle") {
+ if (GetBoolean(*i->second)) {
+ s.SetUsableInBattle();
+ }
+ } else if (i->first == "targets") {
+ s.GetTargetingMode() = *GetTargetingMode(*i->second);
+ } else {
+ throw Error("unknown Spell 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 Stats property: " + i->first);
+ }
+ }
+}
+
+void Interpreter::ReadTargetingMode(TargetingMode &t, const PropertyList &props) {
+ for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
+ if (i->first == "ally") {
+ if (GetBoolean(*i->second)) {
+ t.TargetAlly();
+ } else {
+ t.TargetEnemy();
+ }
+ } else if (i->first == "enemy") {
+ if (GetBoolean(*i->second)) {
+ t.TargetEnemy();
+ } else {
+ t.TargetAlly();
+ }
+ } else if (i->first == "all") {
+ if (GetBoolean(*i->second)) {
+ t.TargetAll();
+ }
+ } else if (i->first == "multiple") {
+ if (GetBoolean(*i->second)) {
+ t.TargetMultiple();
+ }
+ } else if (i->first == "single") {
+ if (GetBoolean(*i->second)) {
+ t.TargetSingle();
+ }
+ } else {
+ throw Error("unknown TargetingMode property: " + i->first);
+ }
+ }
+}
+
+}
--- /dev/null
+/*
+ * Interpreter.h
+ *
+ * Created on: Aug 26, 2012
+ * Author: holy
+ */
+
+#ifndef LOADER_INTERPRETER_H_
+#define LOADER_INTERPRETER_H_
+
+#include "../geometry/Vector.h"
+#include "../graphics/Color.h"
+#include "../graphics/ComplexAnimation.h"
+
+#include <map>
+#include <stdexcept>
+#include <string>
+#include <vector>
+#include <SDL.h>
+
+namespace battle {
+ class Hero;
+ class Monster;
+ class PartyLayout;
+ struct Resources;
+ class Stats;
+}
+
+namespace common {
+ class Ikari;
+ class Item;
+ class Spell;
+ class TargetingMode;
+}
+
+namespace graphics {
+ class Animation;
+ class Font;
+ class Frame;
+ class Gauge;
+ struct MenuProperties;
+ class SimpleAnimation;
+ class Sprite;
+}
+
+namespace loader {
+
+class Definition;
+class ParsedSource;
+class PropertyList;
+class Value;
+
+class Interpreter {
+
+public:
+ class Error: public std::runtime_error {
+ public:
+ Error(const std::string &msg) : std::runtime_error("interpreter error: " + msg) { }
+ };
+
+public:
+ Interpreter(const ParsedSource &source) : source(source) { }
+ ~Interpreter();
+private:
+ Interpreter(const Interpreter &);
+ Interpreter &operator =(const Interpreter &);
+
+public:
+ void ReadSource();
+
+public:
+ graphics::Animation *GetAnimation(const std::string &name);
+ battle::Resources *GetBattleResources(const std::string &name);
+ bool GetBoolean(const std::string &name) const;
+ const graphics::Color &GetColor(const std::string &name) const;
+ graphics::Font *GetFont(const std::string &name);
+ graphics::Frame *GetFrame(const std::string &name);
+ graphics::Gauge *GetGauge(const std::string &name);
+ battle::Hero *GetHero(const std::string &name);
+ common::Ikari *GetIkari(const std::string &name);
+ common::Item *GetItem(const std::string &name);
+ graphics::MenuProperties *GetMenuProperties(const std::string &name);
+ battle::Monster *GetMonster(const std::string &name);
+ int GetNumber(const std::string &name) const;
+ battle::PartyLayout *GetPartyLayout(const std::string &name);
+ const char *GetPath(const std::string &name) const;
+ common::Spell *GetSpell(const std::string &name);
+ graphics::Sprite *GetSprite(const std::string &name);
+ const char *GetString(const std::string &name) const;
+ common::TargetingMode *GetTargetingMode(const std::string &name);
+ geometry::Vector<int> GetVector(const std::string &name) const;
+
+public:
+ const std::vector<battle::Resources *> &BattleResources() const { return battleResources; }
+ const std::vector<bool> &Booleans() const { return booleans; }
+ const std::vector<graphics::Color> &Colors() const { return colors; }
+ const std::vector<graphics::ComplexAnimation *> &ComplexAnimations() const { return complexAnimations; }
+ const std::vector<graphics::Font *> &Fonts() const { return fonts; }
+ const std::vector<graphics::Frame *> &Frames() const { return frames; }
+ const std::vector<graphics::Gauge *> &Gauges() const { return gauges; }
+ const std::vector<battle::Hero *> &Heroes() const { return heroes; }
+ const std::vector<common::Ikari *> &Ikaris() const { return ikaris; }
+ const std::vector<SDL_Surface *> &Images() const { return images; }
+ const std::vector<common::Item *> &Items() const { return items; }
+ const std::vector<graphics::MenuProperties *> &MenuProperties() const { return menuProperties; }
+ const std::vector<battle::Monster *> &Monsters() const { return monsters; }
+ const std::vector<int> &Numbers() const { return numbers; }
+ const std::vector<battle::PartyLayout *> &PartyLayouts() const { return partyLayouts; }
+ const std::vector<graphics::SimpleAnimation *> &SimpleAnimations() const { return simpleAnimations; }
+ const std::vector<common::Spell *> &Spells() const { return spells; }
+ const std::vector<graphics::Sprite *> &Sprites() const { return sprites; }
+ const std::vector<const char *> &Strings() const { return strings; }
+ const std::vector<common::TargetingMode *> &TargetingModes() const { return targetingModes; }
+ const std::vector<geometry::Vector<int> > &Vectors() const { return vectors; }
+
+private:
+ void ReadDefinition(const Definition &);
+ void ReadLiteral(const Definition &);
+ void ReadObject(const Definition &);
+
+ graphics::Animation *GetAnimation(const Value &);
+ battle::Resources *GetBattleResources(const Value &);
+ graphics::Color GetColor(const Value &);
+ bool GetBoolean(const Value &);
+ graphics::Font *GetFont(const Value &);
+ graphics::Frame *GetFrame(const Value &);
+ graphics::Gauge *GetGauge(const Value &);
+ battle::Hero *GetHero(const Value &);
+ common::Ikari *GetIkari(const Value &);
+ SDL_Surface *GetImage(const Value &);
+ common::Item *GetItem(const Value &);
+ graphics::MenuProperties *GetMenuProperties(const Value &);
+ battle::Monster *GetMonster(const Value &);
+ int GetNumber(const Value &);
+ battle::PartyLayout *GetPartyLayout(const Value &);
+ const PropertyList *GetPropertyList(const Value &);
+ const std::vector<PropertyList *> &GetPropertyListArray(const Value &);
+ const char *GetPath(const Value &);
+ common::Spell *GetSpell(const Value &);
+ graphics::Sprite *GetSprite(const Value &);
+ const char *GetString(const Value &);
+ common::TargetingMode *GetTargetingMode(const Value &);
+ const std::vector<Value *> &GetValueArray(const Value &);
+ geometry::Vector<int> GetVector(const Value &);
+
+ void ReadBattleResources(battle::Resources &, const PropertyList &);
+ void ReadComplexAnimation(graphics::ComplexAnimation &, const PropertyList &);
+ void ReadComplexAnimationFrame(graphics::ComplexAnimation::FrameProp &, const PropertyList &);
+ void ReadFont(graphics::Font &, const PropertyList &);
+ void ReadFrame(graphics::Frame &, const PropertyList &);
+ void ReadGauge(graphics::Gauge &, const PropertyList &);
+ void ReadHero(battle::Hero &, const PropertyList &);
+ void ReadIkari(common::Ikari &, const PropertyList &);
+ void ReadItem(common::Item &, const PropertyList &);
+ void ReadMenuProperties(graphics::MenuProperties &, const PropertyList &);
+ void ReadMonster(battle::Monster &, const PropertyList &);
+ void ReadPartyLayout(battle::PartyLayout &, const PropertyList &);
+ void ReadSimpleAnimation(graphics::SimpleAnimation &, const PropertyList &);
+ void ReadSpell(common::Spell &, const PropertyList &);
+ void ReadSprite(graphics::Sprite &, const PropertyList &);
+ void ReadStats(battle::Stats &, const PropertyList &);
+ void ReadTargetingMode(common::TargetingMode &, const PropertyList &);
+
+private:
+ const ParsedSource &source;
+ enum Type {
+ BATTLE_RESOURCES,
+ BOOLEAN,
+ COLOR,
+ COMPLEX_ANIMATION,
+ FONT,
+ FRAME,
+ GAUGE,
+ HERO,
+ IKARI,
+ IMAGE,
+ ITEM,
+ MENU_PROPERTIES,
+ MONSTER,
+ NUMBER,
+ PARTY_LAYOUT,
+ PATH,
+ PROPERTY_LIST_ARRAY,
+ SIMPLE_ANIMATION,
+ SPELL,
+ SPRITE,
+ STRING,
+ TARGETING_MODE,
+ VECTOR,
+ VALUE_ARRAY,
+ };
+ struct ParsedDefinition {
+ ParsedDefinition(const Definition *dfn, Type type, int index)
+ : dfn(dfn), type(type), index(index) { }
+ const Definition *dfn;
+ Type type;
+ int index;
+ };
+ std::map<std::string, ParsedDefinition> parsedDefinitions;
+
+ std::map<std::string, SDL_Surface *> imageCache;
+
+ std::vector<battle::Resources *> battleResources;
+ std::vector<bool> booleans;
+ std::vector<graphics::Color> colors;
+ std::vector<graphics::ComplexAnimation *> complexAnimations;
+ std::vector<graphics::Font *> fonts;
+ std::vector<graphics::Frame *> frames;
+ std::vector<graphics::Gauge *> gauges;
+ std::vector<battle::Hero *> heroes;
+ std::vector<common::Ikari *> ikaris;
+ std::vector<SDL_Surface *> images;
+ std::vector<common::Item *> items;
+ std::vector<graphics::MenuProperties *> menuProperties;
+ std::vector<battle::Monster *> monsters;
+ std::vector<int> numbers;
+ std::vector<battle::PartyLayout *> partyLayouts;
+ std::vector<PropertyList *> propertyLists;
+ std::vector<std::vector<PropertyList *> > propertyListArrays;
+ std::vector<graphics::SimpleAnimation *> simpleAnimations;
+ std::vector<common::Spell *> spells;
+ std::vector<graphics::Sprite *> sprites;
+ std::vector<const char *> strings;
+ std::vector<common::TargetingMode *> targetingModes;
+ std::vector<std::vector<Value *> > valueArrays;
+ std::vector<geometry::Vector<int> > vectors;
+
+};
+
+}
+
+#endif /* LOADER_INTERPRETER_H_ */
--- /dev/null
+/*
+ * ParsedSource.cpp
+ *
+ * Created on: Aug 26, 2012
+ * Author: holy
+ */
+
+#include "ParsedSource.h"
+
+#include "utility.h"
+
+#include <ostream>
+#include <stdexcept>
+
+using std::map;
+using std::runtime_error;
+using std::string;
+using std::vector;
+
+namespace loader {
+
+ParsedSource::~ParsedSource() {
+ for (map<string, Declaration *>::const_iterator i(declarations.begin()), end(declarations.end()); i != end; ++i) {
+ delete i->second;
+ }
+}
+
+void ParsedSource::AddDeclaration(Declaration *d) {
+ map<string, Declaration *>::iterator i(declarations.find(d->Identifier()));
+ if (i != declarations.end()) {
+ if (d->TypeName() != i->second->TypeName()) {
+ throw runtime_error("invalid redeclaration of " + i->second->TypeName() + " " + d->Identifier());
+ }
+ } else {
+ declarations.insert(std::make_pair(d->Identifier(), d));
+ }
+}
+
+void ParsedSource::AddDefinition(Definition *d) {
+ map<string, Definition *>::iterator i(definitions.find(d->Identifier()));
+ if (i != definitions.end()) {
+ throw runtime_error("redefinition of " + i->second->TypeName() + " " + d->Identifier());
+ } else {
+ definitions.insert(std::make_pair(d->Identifier(), d));
+ }
+}
+
+void ParsedSource::ExportDeclaration(Declaration *d) {
+ AddDeclaration(d);
+ exports.insert(d->Identifier());
+}
+
+void ParsedSource::ExportIdentifier(const std::string &i) {
+ if (declarations.count(i)) {
+ exports.insert(i);
+ } else {
+ throw runtime_error("cannot export undeclared identifier " + i);
+ }
+}
+
+
+bool ParsedSource::IsDeclared(const std::string &name) const {
+ return declarations.count(name);
+}
+
+Declaration &ParsedSource::GetDeclaration(const std::string &name) {
+ map<string, Declaration *>::const_iterator i(declarations.find(name));
+ if (i != declarations.end()) {
+ return *i->second;
+ } else {
+ throw runtime_error("undeclared identifier " + name);
+ }
+}
+
+const Declaration &ParsedSource::GetDeclaration(const std::string &name) const {
+ map<string, Declaration *>::const_iterator i(declarations.find(name));
+ if (i != declarations.end()) {
+ return *i->second;
+ } else {
+ throw runtime_error("undeclared identifier " + name);
+ }
+}
+
+bool ParsedSource::IsDefined(const std::string &name) const {
+ return definitions.count(name);
+}
+
+Definition &ParsedSource::GetDefinition(const std::string &name) {
+ map<string, Definition *>::const_iterator i(definitions.find(name));
+ if (i != definitions.end()) {
+ return *i->second;
+ } else {
+ string msg("undefined identifier " + name);
+ map<string, Declaration *>::const_iterator i(declarations.find(name));
+ if (i != declarations.end()) {
+ msg += ", declared as " + i->second->TypeName();
+ } else {
+ msg += ", not declared";
+ }
+ throw runtime_error(msg);
+ }
+}
+
+const Definition &ParsedSource::GetDefinition(const std::string &name) const {
+ map<string, Definition *>::const_iterator i(definitions.find(name));
+ if (i != definitions.end()) {
+ return *i->second;
+ } else {
+ string msg("undefined identifier " + name);
+ map<string, Declaration *>::const_iterator i(declarations.find(name));
+ if (i != declarations.end()) {
+ msg += ", declared as " + i->second->TypeName();
+ } else {
+ msg += ", not declared";
+ }
+ throw runtime_error(msg);
+ }
+}
+
+void ParsedSource::WriteHeader(std::ostream &out) const {
+ for (std::set<string>::const_iterator i(exports.begin()), end(exports.end()); i != end; ++i) {
+ out << GetDeclaration(*i).TypeName() << ' ' << *i << std::endl;
+ }
+}
+
+
+Definition::~Definition() {
+ if (isLiteral) {
+ delete reinterpret_cast<Literal *>(value);
+ } else {
+ delete reinterpret_cast<PropertyList *>(value);
+ }
+}
+
+void Definition::SetValue(Literal *v) {
+ value = v;
+ isLiteral = true;
+}
+
+void Definition::SetValue(PropertyList *v) {
+ value = v;
+ isLiteral = false;
+}
+
+Literal *Definition::GetLiteral() {
+ if (isLiteral) {
+ return reinterpret_cast<Literal *>(value);
+ } else {
+ throw runtime_error("tried to access properties as literal");
+ }
+}
+
+const Literal *Definition::GetLiteral() const {
+ if (isLiteral) {
+ return reinterpret_cast<Literal *>(value);
+ } else {
+ throw runtime_error("tried to access properties as literal");
+ }
+}
+
+PropertyList *Definition::GetProperties() {
+ if (!isLiteral) {
+ return reinterpret_cast<PropertyList *>(value);
+ } else {
+ throw runtime_error("tried to access literal value as property list");
+ }
+}
+
+const PropertyList *Definition::GetProperties() const {
+ if (!isLiteral) {
+ return reinterpret_cast<PropertyList *>(value);
+ } else if (GetLiteral()->GetType() == Literal::OBJECT) {
+ return GetLiteral()->GetProperties();
+ } else {
+ throw runtime_error("tried to access literal value as property list");
+ }
+}
+
+
+PropertyList::~PropertyList() {
+ for (map<string, Value *>::iterator i(props.begin()), end(props.end()); i != end; ++i) {
+ delete i->second;
+ }
+}
+
+
+Literal::Literal(const vector<Value *> &v)
+: props(0)
+, values(v)
+, i1(0), i2(0)
+, i3(0), i4(0)
+, b(false)
+, type(ARRAY_VALUES) {
+
+}
+
+Literal::Literal(const std::vector<PropertyList *> &pls)
+: props(0)
+, propertyLists(pls)
+, i1(0), i2(0)
+, i3(0), i4(0)
+, b(false)
+, type(ARRAY_PROPS) {
+
+}
+
+Literal::Literal(bool b)
+: props(0)
+, i1(0), i2(0)
+, i3(0), i4(0)
+, b(b)
+, type(BOOLEAN) {
+
+}
+
+Literal::Literal(int r, int g, int b, int a)
+: props(0)
+, i1(r), i2(g)
+, i3(b), i4(a)
+, b(false)
+, type(COLOR) {
+
+}
+
+Literal::Literal(int number)
+: props(0)
+, i1(number), i2(0)
+, i3(0), i4(0)
+, b(false)
+, type(NUMBER) {
+
+}
+
+Literal::Literal(const string &dir, const string &path)
+: props(0)
+, str(CatPath(dir, path))
+, i1(0), i2(0)
+, i3(0), i4(0)
+, b(false)
+, type(STRING) {
+
+}
+
+Literal::Literal(const string &str)
+: props(0)
+, str(str)
+, i1(0), i2(0)
+, i3(0), i4(0)
+, b(false)
+, type(STRING) {
+
+}
+
+Literal::Literal(int x, int y)
+: props(0)
+, i1(x), i2(y)
+, i3(0), i4(0)
+, b(false)
+, type(VECTOR) {
+
+}
+
+Literal::Literal(const string &typeName, PropertyList *properties)
+: props(properties)
+, str(typeName)
+, i1(0), i2(0)
+, i3(0), i4(0)
+, b(false)
+, type(OBJECT) {
+
+}
+
+Literal::~Literal() {
+ switch (type) {
+ case ARRAY_VALUES:
+ for (vector<Value *>::const_iterator i(values.begin()), end(values.end()); i != end; ++i) {
+ delete *i;
+ }
+ break;
+ case ARRAY_PROPS:
+ for (vector<PropertyList *>::const_iterator i(propertyLists.begin()), end(propertyLists.end()); i != end; ++i) {
+ delete *i;
+ }
+ break;
+ case OBJECT:
+ delete props;
+ break;
+ default:
+ break;
+ }
+}
+
+
+const vector<Value *> &Literal::GetValues() const {
+ if (type == ARRAY_VALUES) {
+ return values;
+ } else {
+ throw runtime_error("tried to access values of non-array literal");
+ }
+}
+
+const vector<PropertyList *> &Literal::GetPropertyLists() const {
+ if (type == ARRAY_PROPS) {
+ return propertyLists;
+ } else {
+ throw runtime_error("tried to access property lists of non-array literal");
+ }
+}
+
+bool Literal::GetBoolean() const {
+ if (type == BOOLEAN) {
+ return b;
+ } else {
+ throw runtime_error("tried to access boolean value of non-boolean literal");
+ }
+}
+
+int Literal::GetRed() const {
+ if (type == COLOR) {
+ return i1;
+ } else {
+ throw runtime_error("tried to access red component of non-color literal");
+ }
+}
+
+int Literal::GetGreen() const {
+ if (type == COLOR) {
+ return i2;
+ } else {
+ throw runtime_error("tried to access green component of non-color literal");
+ }
+}
+
+int Literal::GetBlue() const {
+ if (type == COLOR) {
+ return i3;
+ } else {
+ throw runtime_error("tried to access blue component of non-color literal");
+ }
+}
+
+int Literal::GetAlpha() const {
+ if (type == COLOR) {
+ return i4;
+ } else {
+ throw runtime_error("tried to access alpha component of non-color literal");
+ }
+}
+
+int Literal::GetNumber() const {
+ if (type == NUMBER) {
+ return i1;
+ } else {
+ throw runtime_error("tried to access numerical value of non-number literal");
+ }
+}
+
+const string &Literal::GetString() const {
+ if (type == STRING) {
+ return str;
+ } else {
+ throw runtime_error("tried to access string value of non-color literal");
+ }
+}
+
+int Literal::GetX() const {
+ if (type == VECTOR) {
+ return i1;
+ } else {
+ throw runtime_error("tried to access x component of non-vector literal");
+ }
+}
+
+int Literal::GetY() const {
+ if (type == VECTOR) {
+ return i2;
+ } else {
+ throw runtime_error("tried to access y component of non-vector literal");
+ }
+}
+
+const string &Literal::GetTypeName() const {
+ if (type == OBJECT) {
+ return str;
+ } else {
+ throw runtime_error("tried to access type name of non-object literal");
+ }
+}
+
+const PropertyList *Literal::GetProperties() const {
+ if (type == OBJECT) {
+ return props;
+ } else {
+ throw runtime_error("tried to access properties of non-object literal");
+ }
+}
+
+
+Value::~Value() {
+ if (isLiteral) {
+ delete literal;
+ }
+}
+
+const Literal &Value::GetLiteral() const {
+ if (isLiteral) {
+ return *literal;
+ } else {
+ throw runtime_error("tried to access literal of identifier value");
+ }
+}
+
+const std::string &Value::GetIdentifier() const {
+ if (!isLiteral) {
+ return identifier;
+ } else {
+ throw runtime_error("tried to access identifier of literal value");
+ }
+}
+
+}
+
+
+namespace std {
+
+ostream &operator <<(ostream &out, const loader::ParsedSource &source) {
+ out << "parsed source file" << endl;
+ out << "declared objects: " << endl;
+ for (map<string, loader::Declaration *>::const_iterator i(source.Declarations().begin()), end(source.Declarations().end()); i != end; ++i) {
+ out << " - " << i->first << " of type " << i->second->TypeName() << endl;
+ }
+ out << "defined objects: " << endl;
+ for (map<string, loader::Definition *>::const_iterator i(source.Definitions().begin()), end(source.Definitions().end()); i != end; ++i) {
+ out << " - " << i->first << " of type " << i->second->TypeName() << endl;
+ if (i->second->HasLiteralValue()) {
+ out << " literal value: " << *i->second->GetLiteral() << endl;
+ }
+ }
+ out << "exported objects: " << endl;
+ for (set<string>::const_iterator i(source.Exports().begin()), end(source.Exports().end()); i != end; ++i) {
+ out << " - " << *i << endl;
+ }
+ return out;
+}
+
+ostream &operator <<(ostream &out, const loader::Literal &l) {
+ switch (l.GetType()) {
+ case loader::Literal::ARRAY_VALUES:
+ out << "array of values";
+ break;
+ case loader::Literal::ARRAY_PROPS:
+ out << "array of property lists";
+ break;
+ case loader::Literal::BOOLEAN:
+ out << "boolean, " << (l.GetBoolean() ? "true" : "false");
+ break;
+ case loader::Literal::COLOR:
+ out << "color, (" << l.GetRed() << ',' << l.GetGreen() << ',' << l.GetBlue() << ',' << l.GetAlpha() << ')';
+ break;
+ case loader::Literal::NUMBER:
+ out << "number, " << l.GetNumber();
+ break;
+ case loader::Literal::PATH:
+ out << "path, \"" << l.GetString() << '"';
+ break;
+ case loader::Literal::STRING:
+ out << "string, \"" << l.GetString() << '"';
+ break;
+ case loader::Literal::VECTOR:
+ out << "vector, <" << l.GetX() << ',' << l.GetY() << '>';
+ break;
+ case loader::Literal::OBJECT:
+ out << "object of type " << l.GetTypeName();
+ break;
+ }
+ return out;
+}
+
+}
--- /dev/null
+/*
+ * ParsedSource.h
+ *
+ * Created on: Aug 26, 2012
+ * Author: holy
+ */
+
+#ifndef LOADER_PARSEDSOURCE_H_
+#define LOADER_PARSEDSOURCE_H_
+
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+namespace loader {
+
+class PropertyList;
+class Value;
+
+class Literal {
+
+public:
+ enum Type {
+ ARRAY_VALUES,
+ ARRAY_PROPS,
+ BOOLEAN,
+ COLOR,
+ NUMBER,
+ PATH,
+ STRING,
+ VECTOR,
+ OBJECT
+ };
+
+public:
+ explicit Literal(const std::vector<Value *> &);
+ explicit Literal(const std::vector<PropertyList *> &);
+ explicit Literal(bool);
+ Literal(int r, int g, int b, int a = 255);
+ explicit Literal(int number);
+ Literal(const std::string &dir, const std::string &path);
+ Literal(const std::string &);
+ Literal(int x, int y);
+ Literal(const std::string &typeName, PropertyList *properties);
+ ~Literal();
+private:
+ Literal(const Literal &);
+ Literal &operator =(const Literal &);
+
+public:
+ Type GetType() const { return type; }
+
+ const std::vector<Value *> &GetValues() const;
+ const std::vector<PropertyList *> &GetPropertyLists() const;
+ bool GetBoolean() const;
+ int GetRed() const;
+ int GetGreen() const;
+ int GetBlue() const;
+ int GetAlpha() const;
+ int GetNumber() const;
+ const std::string &GetString() const;
+ int GetX() const;
+ int GetY() const;
+ const std::string &GetTypeName() const;
+ const PropertyList *GetProperties() const;
+
+private:
+ PropertyList *props;
+ std::string str;
+ std::vector<Value *> values;
+ std::vector<PropertyList *> propertyLists;
+ int i1, i2, i3, i4;
+ bool b;
+ Type type;
+
+};
+
+
+class Value {
+
+public:
+ explicit Value(const std::string &identifier)
+ : literal(0), identifier(identifier), isLiteral(false) { }
+ explicit Value(Literal *literal)
+ : literal(literal), isLiteral(true) { }
+ ~Value();
+private:
+ Value(const Value &);
+ Value &operator =(const Value &);
+
+public:
+ bool IsLiteral() const { return isLiteral; }
+ const Literal &GetLiteral() const;
+ const std::string &GetIdentifier() const;
+
+private:
+ Literal *literal;
+ std::string identifier;
+ bool isLiteral;
+
+};
+
+
+class PropertyList {
+
+public:
+ PropertyList() { }
+ ~PropertyList();
+private:
+ PropertyList(const PropertyList &);
+ PropertyList &operator =(const PropertyList &);
+
+public:
+ void SetProperty(const std::string &name, Value *value) {
+ props[name] = value;
+ }
+
+ typedef std::map<std::string, Value *>::iterator Iterator;
+ typedef std::map<std::string, Value *>::const_iterator ConstIterator;
+ Iterator Begin() { return props.begin(); }
+ ConstIterator Begin() const { return props.begin(); }
+ Iterator End() { return props.end(); }
+ ConstIterator End() const { return props.end(); }
+
+private:
+ std::map<std::string, Value *> props;
+
+};
+
+
+class Declaration {
+
+public:
+ Declaration(const std::string &typeName, const std::string &identifier)
+ : typeName(typeName), identifier(identifier) { }
+ virtual ~Declaration() { }
+private:
+ Declaration(const Declaration &);
+ Declaration &operator =(const Declaration &);
+
+public:
+ const std::string &TypeName() const { return typeName; }
+ const std::string &Identifier() const { return identifier; }
+
+private:
+ std::string typeName;
+ std::string identifier;
+
+};
+
+
+class Definition
+: public Declaration {
+
+public:
+ Definition(const std::string &typeName, const std::string &identifier)
+ : Declaration(typeName, identifier), value(0), isLiteral(false) { }
+ virtual ~Definition();
+private:
+ Definition(const Definition &);
+ Definition &operator =(const Definition &);
+
+public:
+ void SetValue(Literal *);
+ void SetValue(PropertyList *);
+
+ bool HasLiteralValue() const { return isLiteral && value; }
+ bool HasProperties() const { return !isLiteral && value; }
+ Literal *GetLiteral();
+ const Literal *GetLiteral() const;
+ PropertyList *GetProperties();
+ const PropertyList *GetProperties() const;
+
+private:
+ void *value;
+ bool isLiteral;
+
+};
+
+
+class ParsedSource {
+
+public:
+ ParsedSource() { }
+ ~ParsedSource();
+private:
+ ParsedSource(const ParsedSource &);
+ ParsedSource &operator =(const ParsedSource &);
+
+public:
+ void AddDeclaration(Declaration *);
+ void AddDefinition(Definition *);
+ void ExportDeclaration(Declaration *);
+ void ExportIdentifier(const std::string &);
+
+ bool IsDeclared(const std::string &) const;
+ Declaration &GetDeclaration(const std::string &);
+ const Declaration &GetDeclaration(const std::string &) const;
+ bool IsDefined(const std::string &) const;
+ Definition &GetDefinition(const std::string &);
+ const Definition &GetDefinition(const std::string &) const;
+
+ const std::map<std::string, Declaration *> &Declarations() const { return declarations; }
+ const std::map<std::string, Definition *> &Definitions() const { return definitions; }
+ const std::set<std::string> &Exports() const { return exports; }
+
+public:
+ void WriteHeader(std::ostream &) const;
+
+private:
+ std::map<std::string, Declaration *> declarations;
+ std::map<std::string, Definition *> definitions;
+ std::set<std::string> exports;
+
+};
+
+}
+
+
+namespace std {
+
+ostream &operator <<(ostream &, const loader::ParsedSource &);
+ostream &operator <<(ostream &, const loader::Literal &);
+
+}
+
+#endif /* LOADER_PARSEDSOURCE_H_ */
--- /dev/null
+/*
+ * Parser.cpp
+ *
+ * Created on: Aug 26, 2012
+ * Author: holy
+ */
+
+#include "Parser.h"
+
+#include "utility.h"
+
+#include <auto_ptr.h>
+#include <fstream>
+
+using std::auto_ptr;
+using std::ifstream;
+using std::string;
+using std::vector;
+
+namespace loader {
+
+Parser::Parser(const string &file, ParsedSource &product)
+: file(file)
+, dirname(Dirname(file))
+, in(this->file.c_str())
+, tok(in)
+, product(product) {
+ if (!in) {
+ throw Error(file, 0, "unable to read file");
+ }
+}
+
+void Parser::Parse() {
+ while (tok.HasMore()) {
+ ParseStatement();
+ }
+}
+
+void Parser::ParseStatement() {
+ Tokenizer::Token t(GetToken());
+ switch (t.type) {
+ case Tokenizer::Token::KEYWORD_EXPORT:
+ ParseExportDirective();
+ break;
+ case Tokenizer::Token::KEYWORD_INCLUDE:
+ ParseIncludeDirective();
+ break;
+ case Tokenizer::Token::TYPE_NAME:
+ tok.Putback(t);
+ {
+ Declaration *decl(ProbeDefinition());
+ product.AddDeclaration(decl);
+ }
+ break;
+ default:
+ throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type));
+ }
+}
+
+Tokenizer::Token Parser::GetToken() try {
+ return tok.GetNext();
+} catch (Tokenizer::LexerError &e) {
+ throw Error(file, e.Line(), e.what());
+}
+
+void Parser::ParseExportDirective() {
+ Tokenizer::Token t(GetToken());
+ if (t.type != Tokenizer::Token::IDENTIFIER) {
+ tok.Putback(t);
+ Declaration *decl(ProbeDefinition());
+ product.ExportDeclaration(decl);
+ } else {
+ product.ExportIdentifier(t.str);
+ }
+}
+
+void Parser::ParseIncludeDirective() {
+ Tokenizer::Token t(GetToken());
+ AssertTokenType(t.type, Tokenizer::Token::STRING);
+ Parser sub(CatPath(dirname, t.str), product);
+ sub.Parse();
+}
+
+Declaration *Parser::ProbeDefinition() {
+ string typeName(ParseTypeName());
+ string identifier(ParseIdentifier());
+
+ if (tok.HasMore()) {
+ Tokenizer::Token t(GetToken());
+ tok.Putback(t);
+ if (BeginOfPropertyList(t)) {
+ auto_ptr<PropertyList> propertyList(ParsePropertyList());
+ auto_ptr<Definition> dfn(new Definition(typeName, identifier));
+ dfn->SetValue(propertyList.release());
+ product.AddDefinition(dfn.get());
+ return dfn.release();
+ } else if (BeginningOfPrimitiveLiteral(t)) {
+ auto_ptr<Literal> literal(ParseLiteral());
+ auto_ptr<Definition> dfn(new Definition(typeName, identifier));
+ dfn->SetValue(literal.release());
+ product.AddDefinition(dfn.get());
+ return dfn.release();
+ }
+ }
+ return new Declaration(typeName, identifier);
+}
+
+bool Parser::BeginningOfLiteral(const Tokenizer::Token &t) const {
+ switch (t.type) {
+ case Tokenizer::Token::CHEVRON_OPEN:
+ case Tokenizer::Token::COLON:
+ case Tokenizer::Token::BRACKET_OPEN:
+ case Tokenizer::Token::PARENTHESIS_OPEN:
+ case Tokenizer::Token::NUMBER:
+ case Tokenizer::Token::STRING:
+ case Tokenizer::Token::KEYWORD_FALSE:
+ case Tokenizer::Token::KEYWORD_TRUE:
+ case Tokenizer::Token::TYPE_NAME:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool Parser::BeginningOfPrimitiveLiteral(const Tokenizer::Token &t) const {
+ switch (t.type) {
+ case Tokenizer::Token::CHEVRON_OPEN:
+ case Tokenizer::Token::COLON:
+ case Tokenizer::Token::BRACKET_OPEN:
+ case Tokenizer::Token::PARENTHESIS_OPEN:
+ case Tokenizer::Token::NUMBER:
+ case Tokenizer::Token::STRING:
+ case Tokenizer::Token::KEYWORD_FALSE:
+ case Tokenizer::Token::KEYWORD_TRUE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool Parser::BeginOfPropertyList(const Tokenizer::Token &t) const {
+ return t.type == Tokenizer::Token::ANGLE_BRACKET_OPEN;
+}
+
+Definition *Parser::ParseDefinition() {
+ string typeName(ParseTypeName());
+ string identifier(ParseIdentifier());
+
+ Tokenizer::Token t(GetToken());
+ tok.Putback(t);
+ if (BeginOfPropertyList(t)) {
+ PropertyList *propertyList(ParsePropertyList());
+ Definition *dfn(new Definition(typeName, identifier));
+ dfn->SetValue(propertyList);
+ return dfn;
+ } else if (BeginningOfLiteral(t)) {
+ Literal *literal(ParseLiteral());
+ Definition *dfn(new Definition(typeName, identifier));
+ dfn->SetValue(literal);
+ return dfn;
+ } else {
+ throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected property-list or literal");
+ }
+}
+
+string Parser::ParseIdentifier() {
+ Tokenizer::Token t(GetToken());
+ AssertTokenType(t.type, Tokenizer::Token::IDENTIFIER);
+ return t.str;
+}
+
+string Parser::ParseTypeName() {
+ Tokenizer::Token t(GetToken());
+ AssertTokenType(t.type, Tokenizer::Token::TYPE_NAME);
+ return t.str;
+}
+
+PropertyList *Parser::ParsePropertyList() {
+ Tokenizer::Token t(GetToken());
+ AssertTokenType(t.type, Tokenizer::Token::ANGLE_BRACKET_OPEN);
+
+ auto_ptr<PropertyList> props(new PropertyList);
+
+ while (t.type != Tokenizer::Token::ANGLE_BRACKET_CLOSE) {
+ Tokenizer::Token name(GetToken());
+ AssertTokenType(name.type, Tokenizer::Token::IDENTIFIER);
+
+ t = GetToken();
+ AssertTokenType(t.type, Tokenizer::Token::COLON);
+
+ Value *value(ParseValue());
+ props->SetProperty(name.str, value);
+
+ t = GetToken();
+ if (t.type != Tokenizer::Token::ANGLE_BRACKET_CLOSE && t.type != Tokenizer::Token::COMMA) {
+ throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or }");
+ }
+ }
+
+ return props.release();
+}
+
+Value *Parser::ParseValue() {
+ Tokenizer::Token t(GetToken());
+ if (t.type == Tokenizer::Token::IDENTIFIER) {
+ return new Value(t.str);
+ } else if (BeginningOfLiteral(t)) {
+ tok.Putback(t);
+ Literal *literal(ParseLiteral());
+ return new Value(literal);
+ } else {
+ throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected literal or identifier");
+ }
+}
+
+Literal *Parser::ParseLiteral() {
+ Tokenizer::Token t(GetToken());
+ if (t.type == Tokenizer::Token::TYPE_NAME) {
+ PropertyList *props(ParsePropertyList());
+ return new Literal(t.str, props);
+ } else if (BeginningOfLiteral(t)) {
+ switch (t.type) {
+ case Tokenizer::Token::CHEVRON_OPEN:
+ tok.Putback(t);
+ return ParseVector();
+ case Tokenizer::Token::COLON:
+ t = GetToken();
+ AssertTokenType(t.type, Tokenizer::Token::STRING);
+ return new Literal(dirname, t.str);
+ case Tokenizer::Token::BRACKET_OPEN:
+ tok.Putback(t);
+ return ParseArray();
+ case Tokenizer::Token::PARENTHESIS_OPEN:
+ tok.Putback(t);
+ return ParseColor();
+ case Tokenizer::Token::NUMBER:
+ return new Literal(t.number);
+ case Tokenizer::Token::STRING:
+ return new Literal(t.str);
+ case Tokenizer::Token::KEYWORD_FALSE:
+ return new Literal(false);
+ case Tokenizer::Token::KEYWORD_TRUE:
+ return new Literal(true);
+ default:
+ throw std::logic_error("literal switch reached impossible default branch oO");
+ }
+ } else {
+ throw new Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected type-name or primitive");
+ }
+}
+
+Literal *Parser::ParseArray() {
+ Tokenizer::Token t(GetToken());
+ AssertTokenType(t.type, Tokenizer::Token::BRACKET_OPEN);
+
+ Tokenizer::Token probe(GetToken());
+ tok.Putback(probe);
+
+ if (probe.type == Tokenizer::Token::ANGLE_BRACKET_OPEN) {
+ vector<PropertyList *> values;
+ while (t.type != Tokenizer::Token::BRACKET_CLOSE) {
+ PropertyList *value(ParsePropertyList());
+ values.push_back(value);
+
+ t = GetToken();
+ if (t.type != Tokenizer::Token::BRACKET_CLOSE && t.type != Tokenizer::Token::COMMA) {
+ throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]");
+ }
+ }
+ return new Literal(values);
+ } else {
+ vector<Value *> values;
+ while (t.type != Tokenizer::Token::BRACKET_CLOSE) {
+ Value *value(ParseValue());
+ values.push_back(value);
+
+ t = GetToken();
+ if (t.type != Tokenizer::Token::BRACKET_CLOSE && t.type != Tokenizer::Token::COMMA) {
+ throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]");
+ }
+ }
+ return new Literal(values);
+ }
+}
+
+Literal *Parser::ParseColor() {
+ string msg("error parsing color");
+ Tokenizer::Token t(GetToken());
+ AssertTokenType(t.type, Tokenizer::Token::PARENTHESIS_OPEN, msg);
+
+ Tokenizer::Token red(GetToken());
+ AssertTokenType(red.type, Tokenizer::Token::NUMBER, "error parsing red component of color");
+
+ t = GetToken();
+ AssertTokenType(t.type, Tokenizer::Token::COMMA, msg);
+
+ Tokenizer::Token green(GetToken());
+ AssertTokenType(green.type, Tokenizer::Token::NUMBER, "error parsing green component of color");
+
+ t = GetToken();
+ AssertTokenType(t.type, Tokenizer::Token::COMMA, msg);
+
+ Tokenizer::Token blue(GetToken());
+ AssertTokenType(blue.type, Tokenizer::Token::NUMBER, "error parsing blue component of color");
+
+ t = GetToken();
+ if (t.type == Tokenizer::Token::PARENTHESIS_CLOSE) {
+ return new Literal(red.number, green.number, blue.number);
+ } else if (t.type != Tokenizer::Token::COMMA) {
+ Tokenizer::Token alpha(GetToken());
+ AssertTokenType(alpha.type, Tokenizer::Token::NUMBER, "error parsing alpha component of color");
+
+ t = GetToken();
+ AssertTokenType(t.type, Tokenizer::Token::PARENTHESIS_CLOSE, msg);
+
+ return new Literal(red.number, green.number, blue.number, alpha.number);
+ } else {
+ throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]");
+ }
+}
+
+Literal *Parser::ParseVector() {
+ std::string msg("error parsing vector");
+ Tokenizer::Token t(GetToken());
+ AssertTokenType(t.type, Tokenizer::Token::CHEVRON_OPEN, msg);
+
+ Tokenizer::Token x(GetToken());
+ AssertTokenType(x.type, Tokenizer::Token::NUMBER, "error parsing x component of vector");
+
+ t = GetToken();
+ AssertTokenType(t.type, Tokenizer::Token::COMMA, msg);
+
+ Tokenizer::Token y(GetToken());
+ AssertTokenType(y.type, Tokenizer::Token::NUMBER, "error parsing y component of vector");
+
+ t = GetToken();
+ AssertTokenType(t.type, Tokenizer::Token::CHEVRON_CLOSE, msg);
+
+ return new Literal(x.number, y.number);
+}
+
+void Parser::AssertTokenType(Tokenizer::Token::Type actual, Tokenizer::Token::Type expected) {
+ if (expected != actual) {
+ throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(actual) + ", expected " + TokenTypeToString(expected));
+ }
+}
+
+void Parser::AssertTokenType(Tokenizer::Token::Type actual, Tokenizer::Token::Type expected, const string &msg) {
+ if (expected != actual) {
+ throw Error(file, tok.Line(), msg + ": unexpected token " + TokenTypeToString(actual) + ", expected " + TokenTypeToString(expected));
+ }
+}
+
+}
--- /dev/null
+/*
+ * Parser.h
+ *
+ * Created on: Aug 26, 2012
+ * Author: holy
+ */
+
+#ifndef LOADER_PARSER_H_
+#define LOADER_PARSER_H_
+
+#include "ParsedSource.h"
+#include "Tokenizer.h"
+
+#include <fstream>
+#include <iosfwd>
+#include <stdexcept>
+#include <string>
+
+namespace loader {
+
+class Declaration;
+class Definition;
+class Literal;
+class PropertyList;
+
+class Parser {
+
+public:
+ Parser(const std::string &file, ParsedSource &product);
+ ~Parser() { }
+private:
+ Parser(const Parser &);
+ Parser &operator =(const Parser &);
+
+public:
+ void Parse();
+
+public:
+ class Error: public std::runtime_error {
+ public:
+ Error(const std::string &file, int line, const std::string &msg)
+ : std::runtime_error(msg), file(file), line(line) { };
+ ~Error() throw() { }
+ const std::string &File() const { return file; }
+ int Line() const { return line; }
+ private:
+ std::string file;
+ int line;
+ };
+
+private:
+ Tokenizer::Token GetToken();
+ void ParseStatement();
+ void ParseExportDirective();
+ void ParseIncludeDirective();
+
+ Declaration *ProbeDefinition();
+ Definition *ParseDefinition();
+
+ std::string ParseIdentifier();
+ std::string ParseTypeName();
+
+ Value *ParseValue();
+ PropertyList *ParsePropertyList();
+ Literal *ParseLiteral();
+ Literal *ParseArray();
+ Literal *ParseColor();
+ Literal *ParseVector();
+
+private:
+ void AssertTokenType(Tokenizer::Token::Type actual, Tokenizer::Token::Type expected);
+ void AssertTokenType(Tokenizer::Token::Type actual, Tokenizer::Token::Type expected, const std::string &msg);
+ bool BeginningOfLiteral(const Tokenizer::Token &) const;
+ bool BeginningOfPrimitiveLiteral(const Tokenizer::Token &) const;
+ bool BeginOfPropertyList(const Tokenizer::Token &) const;
+
+private:
+ std::string file;
+ std::string dirname;
+ std::ifstream in;
+ Tokenizer tok;
+ ParsedSource &product;
+
+};
+
+}
+
+#endif /* LOADER_PARSER_H_ */
--- /dev/null
+/*
+ * Tokenizer.cpp
+ *
+ * Created on: Aug 26, 2012
+ * Author: holy
+ */
+
+#include "Tokenizer.h"
+
+#include <istream>
+
+namespace loader {
+
+bool Tokenizer::HasMore() {
+ if (isPutback) return true;
+ ScanSpace();
+ if (!in) return false;
+
+ putback = ReadToken();
+ isPutback = true;
+ if (!skipComments || putback.type != Token::COMMENT) return true;
+
+ while (in && putback.type == Token::COMMENT) {
+ putback = ReadToken();
+ ScanSpace();
+ }
+ return putback.type != Token::COMMENT;
+}
+
+void Tokenizer::ScanSpace() {
+ std::istream::char_type c;
+ in.get(c);
+ while (in && std::isspace(c)) {
+ if (c == '\n') {
+ ++line;
+ }
+ in.get(c);
+ }
+ if (in) {
+ in.putback(c);
+ }
+}
+
+void Tokenizer::Putback(const Token &t) {
+ if (isPutback) {
+ throw LexerError(line, "Tokenizer: double putback not supported");
+ } else {
+ putback = t;
+ isPutback = true;
+ }
+}
+
+const Tokenizer::Token &Tokenizer::Peek() {
+ if (!isPutback) {
+ putback = GetNext();
+ isPutback = true;
+ }
+ return putback;
+}
+
+Tokenizer::Token Tokenizer::GetNext() {
+ if (!HasMore()) {
+ throw LexerError(line, "read beyond last token");
+ }
+ if (isPutback) {
+ isPutback = false;
+ return putback;
+ } else {
+ return ReadToken();
+ }
+}
+
+Tokenizer::Token Tokenizer::ReadToken() {
+ ScanSpace();
+ std::istream::char_type c;
+ in.get(c);
+ switch (c) {
+ case Token::ANGLE_BRACKET_OPEN:
+ case Token::ANGLE_BRACKET_CLOSE:
+ case Token::CHEVRON_OPEN:
+ case Token::CHEVRON_CLOSE:
+ case Token::COLON:
+ case Token::COMMA:
+ case Token::BRACKET_OPEN:
+ case Token::BRACKET_CLOSE:
+ case Token::PARENTHESIS_OPEN:
+ case Token::PARENTHESIS_CLOSE:
+ return Token ((Token::Type) c);
+ case '+': case '-':
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ in.putback(c);
+ return ReadNumber();
+ case '"':
+ in.putback(c);
+ return ReadString();
+ case '/':
+ {
+ std::istream::char_type c2;
+ in.get(c2);
+ if (c2 == '/') {
+ return ReadComment();
+ } else if (c2 == '*') {
+ return ReadMultilineComment();
+ } else {
+ throw LexerError(line, std::string("Tokenizer: cannot parse token: ") + c + c2 + ": expected / or *");
+ }
+ }
+ break;
+ default:
+ in.putback(c);
+ {
+ Token t(ReadIdentifier());
+ if (std::isupper(c)) {
+ t.type = Token::TYPE_NAME;
+ } else if (std::islower(c)) {
+ CheckKeyword(t);
+ } else {
+ throw LexerError(line, std::string("Tokenizer: cannot parse token: ") + c);
+ }
+ return t;
+ }
+ }
+}
+
+Tokenizer::Token Tokenizer::ReadNumber() {
+ Token t(Token::NUMBER);
+ bool isNegative(false);
+
+ std::istream::char_type c;
+ in.get(c);
+ if (c == '-') {
+ isNegative = true;
+ } else if (c != '+') {
+ in.putback(c);
+ }
+
+ while (in.get(c)) {
+ if (!std::isdigit(c)) {
+ in.putback(c);
+ break;
+ }
+ t.number *= 10;
+ t.number += c - '0';
+ }
+
+ if (isNegative) t.number *= -1;
+
+ return t;
+}
+
+Tokenizer::Token Tokenizer::ReadString() {
+ Token t(Token::STRING);
+ bool escape(false);
+
+ std::istream::char_type c;
+ in.get(c);
+ if (c != '"') {
+ throw LexerError(line, "Tokenizer: strings must begin with '\"'");
+ }
+
+ while (in.get(c)) {
+ if (escape) {
+ escape = false;
+ switch (c) {
+ case 'n':
+ t.str.push_back('\n');
+ break;
+ case 'r':
+ t.str.push_back('\r');
+ break;
+ case 't':
+ t.str.push_back('\t');
+ break;
+ default:
+ t.str.push_back(c);
+ break;
+ }
+ } else if (c == '"') {
+ break;
+ } else if (c == '\\') {
+ escape = true;
+ } else {
+ t.str.push_back(c);
+ }
+ }
+
+ return t;
+}
+
+Tokenizer::Token Tokenizer::ReadIdentifier() {
+ Token t(Token::IDENTIFIER);
+
+ std::istream::char_type c;
+ while (in.get(c)) {
+ if (std::isalnum(c) || c == '_') {
+ t.str.push_back(c);
+ } else {
+ in.putback(c);
+ break;
+ }
+ }
+
+ return t;
+}
+
+Tokenizer::Token Tokenizer::ReadComment() {
+ std::istream::char_type c;
+ while (in.get(c) && c != '\n');
+ ++line;
+ return Token(Token::COMMENT);
+}
+
+Tokenizer::Token Tokenizer::ReadMultilineComment() {
+ std::istream::char_type c;
+ while (in.get(c)) {
+ if (c == '*') {
+ std::istream::char_type c2;
+ if (in.get(c2) && c2 == '/') {
+ break;
+ }
+ } else if (c == '\n') {
+ ++line;
+ }
+ }
+ return Token(Token::COMMENT);
+}
+
+bool Tokenizer::CheckKeyword(Token &t) {
+ if (t.str == "export") {
+ t.type = Token::KEYWORD_EXPORT;
+ return true;
+ } else if (t.str == "false") {
+ t.type = Token::KEYWORD_FALSE;
+ return true;
+ } else if (t.str == "include") {
+ t.type = Token::KEYWORD_INCLUDE;
+ return true;
+ } else if (t.str == "true") {
+ t.type = Token::KEYWORD_TRUE;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+}
--- /dev/null
+/*
+ * Tokenizer.h
+ *
+ * Created on: Aug 26, 2012
+ * Author: holy
+ */
+
+#ifndef LOADER_TOKENIZER_H_
+#define LOADER_TOKENIZER_H_
+
+#include <iosfwd>
+#include <ostream>
+#include <stdexcept>
+#include <string>
+
+namespace loader {
+
+class Tokenizer {
+
+public:
+ explicit Tokenizer(std::istream &in)
+ : in(in), line(1), isPutback(false), skipComments(true) { }
+ ~Tokenizer() { }
+private:
+ Tokenizer(const Tokenizer &);
+ Tokenizer &operator =(const Tokenizer &);
+
+public:
+ struct Token {
+
+ enum Type {
+ UNKNOWN = 0,
+ ANGLE_BRACKET_OPEN = '{',
+ ANGLE_BRACKET_CLOSE = '}',
+ CHEVRON_OPEN = '<',
+ CHEVRON_CLOSE = '>',
+ COLON = ':',
+ COMMA = ',',
+ BRACKET_OPEN = '[',
+ BRACKET_CLOSE = ']',
+ PARENTHESIS_OPEN = '(',
+ PARENTHESIS_CLOSE = ')',
+ NUMBER = '0',
+ STRING = '"',
+ KEYWORD_EXPORT = 'e',
+ KEYWORD_FALSE = 'f',
+ KEYWORD_INCLUDE = 'i',
+ KEYWORD_TRUE = 't',
+ IDENTIFIER = 'x',
+ TYPE_NAME = 'n',
+ COMMENT = 'c'
+ };
+
+ Token() : type(UNKNOWN), number(0) { }
+ explicit Token(Type t) : type(t), number(0) { }
+
+ Type type;
+ std::string str;
+ int number;
+
+ };
+
+ class LexerError: public std::runtime_error {
+ public:
+ LexerError(int line, const std::string &msg)
+ : std::runtime_error(msg), line(line) { }
+ int Line() const { return line; }
+ private:
+ int line;
+ };
+
+ bool HasMore();
+ Token GetNext();
+ const Token &Peek();
+ void Putback(const Token &);
+ int Line() const { return line; }
+
+private:
+ void ScanSpace();
+ Token ReadToken();
+
+ Token ReadNumber();
+ Token ReadString();
+ Token ReadIdentifier();
+
+ Token ReadComment();
+ Token ReadMultilineComment();
+
+ bool CheckKeyword(Token &);
+
+private:
+ std::istream ∈
+ Token putback;
+ int line;
+ bool isPutback;
+ bool skipComments;
+
+};
+
+inline const char *TokenTypeToString(Tokenizer::Token::Type t) {
+ switch (t) {
+ case Tokenizer::Token::ANGLE_BRACKET_OPEN:
+ return "ANGLE_BRACKET_OPEN";
+ case Tokenizer::Token::ANGLE_BRACKET_CLOSE:
+ return "ANGLE_BRACKET_CLOSE";
+ case Tokenizer::Token::CHEVRON_OPEN:
+ return "CHEVRON_OPEN";
+ case Tokenizer::Token::CHEVRON_CLOSE:
+ return "CHEVRON_CLOSE";
+ case Tokenizer::Token::COLON:
+ return "COLON";
+ case Tokenizer::Token::COMMA:
+ return "COMMA";
+ case Tokenizer::Token::BRACKET_OPEN:
+ return "BRACKET_OPEN";
+ case Tokenizer::Token::BRACKET_CLOSE:
+ return "BRACKET_CLOSE";
+ case Tokenizer::Token::PARENTHESIS_OPEN:
+ return "PARENTHESIS_OPEN";
+ case Tokenizer::Token::PARENTHESIS_CLOSE:
+ return "PARENTHESIS_CLOSE";
+ case Tokenizer::Token::NUMBER:
+ return "NUMBER";
+ case Tokenizer::Token::STRING:
+ return "STRING";
+ case Tokenizer::Token::KEYWORD_EXPORT:
+ return "KEYWORD_EXPORT";
+ case Tokenizer::Token::KEYWORD_FALSE:
+ return "KEYWORD_FALSE";
+ case Tokenizer::Token::KEYWORD_INCLUDE:
+ return "KEYWORD_INCLUDE";
+ case Tokenizer::Token::KEYWORD_TRUE:
+ return "KEYWORD_TRUE";
+ case Tokenizer::Token::IDENTIFIER:
+ return "IDENTIFIER";
+ case Tokenizer::Token::TYPE_NAME:
+ return "TYPE_NAME";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+inline std::ostream &operator <<(std::ostream &out, Tokenizer::Token::Type t) {
+ out << TokenTypeToString(t);
+ return out;
+}
+
+}
+
+#endif /* LOADER_TOKENIZER_H_ */
--- /dev/null
+/*
+ * utility.cpp
+ *
+ * Created on: Sep 1, 2012
+ * Author: holy
+ */
+
+#include "utility.h"
+
+#include <cstring>
+#include <libgen.h>
+
+using std::string;
+
+namespace loader {
+
+string Dirname(const string &path) {
+ // unix version
+ char *str(new char[path.size() + 1]);
+ std::memcpy(str, path.c_str(), path.size());
+ str[path.size()] = '\0';
+ string dn(dirname(str));
+ delete str;
+ return dn;
+}
+
+string CatPath(const string &lhs, const string &rhs) {
+ // unix version
+ string path(lhs);
+ if (!path.empty() && path[path.size() - 1] != '/') {
+ path += '/';
+ }
+ if (!rhs.empty() && rhs[0] == '/') {
+ path.append(rhs, 1, string::npos);
+ } else {
+ path += rhs;
+ }
+ return path;
+}
+
+}
--- /dev/null
+/*
+ * utility.h
+ *
+ * Created on: Sep 1, 2012
+ * Author: holy
+ */
+
+#ifndef LOADER_UTILITY_H_
+#define LOADER_UTILITY_H_
+
+#include <string>
+
+namespace loader {
+
+std::string Dirname(const std::string &path);
+
+std::string CatPath(const std::string &lhs, const std::string &rhs);
+
+}
+
+#endif /* LOADER_UTILITY_H_ */
#include "graphics/Menu.h"
#include "graphics/SimpleAnimation.h"
#include "graphics/Sprite.h"
+#include "loader/Interpreter.h"
+#include "loader/ParsedSource.h"
+#include "loader/Parser.h"
#include "sdl/InitImage.h"
#include "sdl/InitScreen.h"
#include "sdl/InitSDL.h"
using graphics::Menu;
using graphics::SimpleAnimation;
using graphics::Sprite;
+using loader::Interpreter;
+using loader::ParsedSource;
+using loader::Parser;
using sdl::InitImage;
using sdl::InitScreen;
using sdl::InitSDL;
const int width = 800;
const int height = 480;
- const int framerate = 33;
-
// std::srand(std::time(0));
try {
InitSDL sdl;
InitImage image(IMG_INIT_PNG);
+
+ ParsedSource source;
+ Parser("test-data/test.l2s", source).Parse();
+ Parser("test-data/ikaris.l2s", source).Parse();
+ Parser("test-data/items.l2s", source).Parse();
+ Parser("test-data/spells.l2s", source).Parse();
+ Interpreter intp(source);
+ intp.ReadSource();
+
InitScreen screen(width, height);
// temporary test data
SDL_Surface *bg(IMG_Load("test-data/battle-bg.png"));
- PartyLayout monstersLayout;
- monstersLayout.AddPosition(Vector<Uint8>(88, 88));
- monstersLayout.AddPosition(Vector<Uint8>(128, 88));
- monstersLayout.AddPosition(Vector<Uint8>(168, 88));
- monstersLayout.AddPosition(Vector<Uint8>(208, 88));
- PartyLayout heroesLayout;
- heroesLayout.AddPosition(Vector<Uint8>(48, 136));
- heroesLayout.AddPosition(Vector<Uint8>(128, 136));
- heroesLayout.AddPosition(Vector<Uint8>(80, 152));
- heroesLayout.AddPosition(Vector<Uint8>(160, 152));
-
- SDL_Surface *monsterImg(IMG_Load("test-data/monster.png"));
- Sprite monsterSprite(monsterImg, 64, 64);
- Monster monster;
- monster.SetName("Lizard");
- monster.SetSprite(&monsterSprite);
- monster.SetLevel(1);
- monster.SetMaxHealth(8);
- monster.SetHealth(8);
- monster.SetStats(Stats(14, 6, 6, 6, 6, 6, 6));
- monster.SetReward(3, 5);
- ComplexAnimation monsterAttackAnimation(&monsterSprite, 4 * framerate);
- monsterAttackAnimation.AddFrame(0, 1, Vector<int>(0, 16));
- monsterAttackAnimation.AddFrame(0, 0, Vector<int>(0, 16));
- monsterAttackAnimation.AddFrame(0, 1, Vector<int>(0, 16));
- monster.SetAttackAnimation(&monsterAttackAnimation);
- SDL_Surface *monsterMeleeImg(IMG_Load("test-data/attack-monster.png"));
- Sprite monsterMeleeSprite(monsterMeleeImg, 96, 64);
- SimpleAnimation monsterMeleeAnimation(&monsterMeleeSprite, framerate, 14);
- monster.SetMeleeAnimation(&monsterMeleeAnimation);
-
- SDL_Surface *maximImg(IMG_Load("test-data/maxim.png"));
- Sprite maximSprite(maximImg, 64, 64);
- Hero maxim;
- maxim.SetName("Maxim");
- maxim.SetLevel(1);
- maxim.SetSprite(&maximSprite);
- maxim.SetMaxHealth(33);
- maxim.SetHealth(33);
- maxim.SetMaxMana(20);
- maxim.SetMana(20);
- maxim.SetIP(0);
- maxim.SetStats(Stats(28, 22, 28, 17, 14, 100, 10));
- ComplexAnimation maximAttackAnimation(&maximSprite, framerate);
- maximAttackAnimation.AddFrames(1, 0, Vector<int>(0, 0), 7);
- maximAttackAnimation.AddFrames(1, 0, Vector<int>(4, -1), 2);
- maximAttackAnimation.AddFrames(2, 0, Vector<int>(4, -2), 2);
- maximAttackAnimation.AddFrames(2, 0, Vector<int>(6, -2), 2);
- maximAttackAnimation.AddFrames(2, 1, Vector<int>(6, -1), 1);
- maximAttackAnimation.AddFrames(2, 1, Vector<int>(3, -1), 2);
- maximAttackAnimation.AddFrames(2, 1, Vector<int>(0, 0), 1);
- maximAttackAnimation.AddFrames(2, 2, Vector<int>(0, 0), 2);
- maximAttackAnimation.AddFrames(2, 2, Vector<int>(2, 0), 1);
- maximAttackAnimation.AddFrames(1, 0, Vector<int>(0, 0), 7);
- maxim.SetAttackAnimation(&maximAttackAnimation);
- ComplexAnimation maximSpellAnimation(&maximSprite, 5 * framerate);
- maximSpellAnimation.AddFrames(3, 0, Vector<int>(), 2);
- maximSpellAnimation.AddFrame(3, 1);
- maxim.SetSpellAnimation(&maximSpellAnimation);
- SDL_Surface *maximMeleeImg(IMG_Load("test-data/melee-maxim.png"));
- Sprite maximMeleeSprite(maximMeleeImg, 96, 96);
- SimpleAnimation maximMeleeAnimation(&maximMeleeSprite, 2 * framerate, 4);
- maxim.SetMeleeAnimation(&maximMeleeAnimation);
-
- SDL_Surface *selanImg(IMG_Load("test-data/selan.png"));
- Sprite selanSprite(selanImg, 64, 64);
- Hero selan;
- selan.SetName("Selan");
- selan.SetLevel(1);
- selan.SetSprite(&selanSprite);
- selan.SetMaxHealth(28);
- selan.SetHealth(28);
- selan.SetMaxMana(23);
- selan.SetMana(23);
- selan.SetIP(0);
- selan.SetStats(Stats(23, 21, 23, 19, 22, 80, 13));
- ComplexAnimation selanAttackAnimation(&selanSprite, framerate);
- selanAttackAnimation.AddFrames(1, 0, Vector<int>(4, 0), 2);
- selanAttackAnimation.AddFrame(1, 0, Vector<int>(8, 2));
- selanAttackAnimation.AddFrame(2, 0, Vector<int>(10, 4));
- selanAttackAnimation.AddFrame(2, 0, Vector<int>(14, 4));
- selanAttackAnimation.AddFrames(2, 0, Vector<int>(12, 2), 3);
- selanAttackAnimation.AddFrames(2, 1, Vector<int>(14, 2), 2);
- selanAttackAnimation.AddFrame(2, 1, Vector<int>(2, 0));
- selanAttackAnimation.AddFrame(2, 2, Vector<int>(-2, -4));
- selanAttackAnimation.AddFrame(2, 2, Vector<int>(-8, -8));
- selanAttackAnimation.AddFrame(2, 2);
- selan.SetAttackAnimation(&selanAttackAnimation);
- ComplexAnimation selanSpellAnimation(&selanSprite, framerate);
- selanSpellAnimation.AddFrames(2, 0, Vector<int>(), 3);
- selanSpellAnimation.AddFrames(2, 1, Vector<int>(), 2);
- selanSpellAnimation.AddFrames(2, 2, Vector<int>(), 3);
- selanSpellAnimation.AddFrames(2, 3, Vector<int>(), 2);
- selan.SetSpellAnimation(&selanSpellAnimation);
- SDL_Surface *selanMeleeImg(IMG_Load("test-data/melee-selan.png"));
- Sprite selanMeleeSprite(selanMeleeImg, 96, 96);
- SimpleAnimation selanMeleeAnimation(&selanMeleeSprite, 2 * framerate, 4);
- selan.SetMeleeAnimation(&selanMeleeAnimation);
-
- SDL_Surface *guyImg(IMG_Load("test-data/guy.png"));
- Sprite guySprite(guyImg, 64, 64);
- Hero guy;
- guy.SetName("Guy");
- guy.SetLevel(1);
- guy.SetSprite(&guySprite);
- guy.SetMaxHealth(38);
- guy.SetHealth(38);
- guy.SetMaxMana(0);
- guy.SetMana(0);
- guy.SetIP(0);
- guy.SetStats(Stats(38, 25, 38, 13, 8, 90, 8));
- ComplexAnimation guyAttackAnimation(&guySprite, framerate);
- guyAttackAnimation.AddFrames(1, 0, Vector<int>(-4, 0), 2);
- guyAttackAnimation.AddFrames(1, 0, Vector<int>(-8, 0), 2);
- guyAttackAnimation.AddFrames(2, 0, Vector<int>(-8, 0), 2);
- guyAttackAnimation.AddFrame(2, 0, Vector<int>(-4, 0));
- guyAttackAnimation.AddFrames(2, 0, Vector<int>(), 2);
- guyAttackAnimation.AddFrame(2, 1);
- guyAttackAnimation.AddFrame(2, 1, Vector<int>(4, 0));
- guyAttackAnimation.AddFrame(2, 1, Vector<int>(10, 0));
- guyAttackAnimation.AddFrame(2, 2, Vector<int>(10, 0));
- guyAttackAnimation.AddFrame(2, 2);
- guy.SetAttackAnimation(&guyAttackAnimation);
- SDL_Surface *guyMeleeImg(IMG_Load("test-data/melee-guy.png"));
- Sprite guyMeleeSprite(guyMeleeImg, 96, 96);
- SimpleAnimation guyMeleeAnimation(&guyMeleeSprite, 2 * framerate, 4);
- guy.SetMeleeAnimation(&guyMeleeAnimation);
-
- SDL_Surface *dekarImg(IMG_Load("test-data/dekar.png"));
- Sprite dekarSprite(dekarImg, 64, 64);
- Hero dekar;
- dekar.SetName("Dekar");
- dekar.SetLevel(1);
- dekar.SetSprite(&dekarSprite);
- dekar.SetMaxHealth(38);
- dekar.SetHealth(38);
- dekar.SetMaxMana(0);
- dekar.SetMana(0);
- dekar.SetIP(0);
- dekar.SetStats(Stats(46, 29, 46, 13, 7, 100, 5));
- ComplexAnimation dekarAttackAnimation(&dekarSprite, framerate);
- dekarAttackAnimation.AddFrame(1, 0, Vector<int>(4, 0));
- dekarAttackAnimation.AddFrame(1, 0, Vector<int>(8, 2));
- dekarAttackAnimation.AddFrame(2, 0, Vector<int>(12, 4));
- dekarAttackAnimation.AddFrame(2, 0, Vector<int>(16, 4));
- dekarAttackAnimation.AddFrames(2, 0, Vector<int>(10, 2), 4);
- dekarAttackAnimation.AddFrame(2, 1, Vector<int>(6, 2));
- dekarAttackAnimation.AddFrame(2, 1, Vector<int>());
- dekarAttackAnimation.AddFrame(2, 2, Vector<int>(-2, 0));
- dekarAttackAnimation.AddFrames(2, 2, Vector<int>(0, 0), 3);
- dekar.SetAttackAnimation(&dekarAttackAnimation);
- ComplexAnimation dekarSpellAnimation(&dekarSprite, framerate);
- dekarSpellAnimation.AddFrames(2, 0, Vector<int>(), 6);
- dekarSpellAnimation.AddFrames(2, 1, Vector<int>(), 2);
- dekarSpellAnimation.AddFrames(2, 2, Vector<int>(), 3);
- dekar.SetSpellAnimation(&dekarSpellAnimation);
- SDL_Surface *dekarMeleeImg(IMG_Load("test-data/melee-dekar.png"));
- Sprite dekarMeleeSprite(dekarMeleeImg, 96, 96);
- SimpleAnimation dekarMeleeAnimation(&dekarMeleeSprite, 2 * framerate, 4);
- dekar.SetMeleeAnimation(&dekarMeleeAnimation);
-
- battle::Resources battleRes;
-
- SDL_Surface *swapCursorImg(IMG_Load("test-data/swap-cursor.png"));
- Sprite swapCursorSprite(swapCursorImg, 32, 32);
- battleRes.swapCursor = &swapCursorSprite;
- SDL_Surface *attackIconsImg(IMG_Load("test-data/attack-type-icons.png"));
- Sprite attackIconsSprite(attackIconsImg, 32, 32);
- battleRes.attackIcons = &attackIconsSprite;
- SDL_Surface *attackChoiceIconsImg(IMG_Load("test-data/attack-choice-icons.png"));
- Sprite attackChoiceIconsSprite(attackChoiceIconsImg, 16, 16);
- battleRes.attackChoiceIcons = &attackChoiceIconsSprite;
- SDL_Surface *moveIconsImg(IMG_Load("test-data/move-icons.png"));
- Sprite moveIconsSprite(moveIconsImg, 32, 32);
- battleRes.moveIcons = &moveIconsSprite;
-
- SDL_Surface *titleFrameImg(IMG_Load("test-data/title-frame.png"));
- Frame titleFrame(titleFrameImg, 16, 16);
- battleRes.titleFrame = &titleFrame;
-
- SDL_Surface *largeFontImg(IMG_Load("test-data/large-font.png"));
- Sprite largeFontSprite(largeFontImg, 16, 32);
- Font largeFont(&largeFontSprite, 0, -2);
- battleRes.titleFont = &largeFont;
-
- ComplexAnimation numberAnimationPrototype(0, framerate);
- numberAnimationPrototype.AddFrame(0, 0);
- numberAnimationPrototype.AddFrame(0, 0, Vector<int>(0, -26));
- numberAnimationPrototype.AddFrame(0, 0, Vector<int>(0, -42));
- numberAnimationPrototype.AddFrame(0, 0, Vector<int>(0, -48));
- numberAnimationPrototype.AddFrame(0, 0, Vector<int>(0, -42));
- numberAnimationPrototype.AddFrame(0, 0, Vector<int>(0, -26));
- numberAnimationPrototype.AddFrame(0, 0);
- numberAnimationPrototype.AddFrame(0, 0, Vector<int>(0, -12));
- numberAnimationPrototype.AddFrame(0, 0, Vector<int>(0, -20));
- numberAnimationPrototype.AddFrame(0, 0, Vector<int>(0, -24));
- numberAnimationPrototype.AddFrame(0, 0, Vector<int>(0, -20));
- numberAnimationPrototype.AddFrame(0, 0, Vector<int>(0, -12));
- numberAnimationPrototype.AddFrame(0, 0);
- numberAnimationPrototype.AddFrame(0, 0, Vector<int>(0, -6));
- numberAnimationPrototype.AddFrame(0, 0, Vector<int>(0, -10));
- numberAnimationPrototype.AddFrame(0, 0, Vector<int>(0, -12));
- numberAnimationPrototype.AddFrame(0, 0, Vector<int>(0, -10));
- numberAnimationPrototype.AddFrame(0, 0, Vector<int>(0, -6));
- numberAnimationPrototype.AddFrames(0, 0, Vector<int>(), 14);
- numberAnimationPrototype.AddFrame(0, 0, Vector<int>(0, -36));
- numberAnimationPrototype.AddFrame(0, 0, Vector<int>(0, -32));
- numberAnimationPrototype.AddFrame(0, 0, Vector<int>(0, -18));
- battleRes.numberAnimationPrototype = &numberAnimationPrototype;
-
- SDL_Surface *bigNumbersImg(IMG_Load("test-data/big-numbers.png"));
- Sprite bigNumbersSprite(bigNumbersImg, 16, 32);
- battleRes.bigNumberSprite = &bigNumbersSprite;
- SDL_Surface *bigGreenNumbersImg(IMG_Load("test-data/big-green-numbers.png"));
- Sprite bigGreenNumbersSprite(bigGreenNumbersImg, 16, 32);
- battleRes.greenNumberSprite = &bigGreenNumbersSprite;
-
- SDL_Surface *heroTagImg(IMG_Load("test-data/hero-tag-sprites.png"));
- Sprite heroTagSprite(heroTagImg, 32, 16);
- battleRes.heroTagLabels = &heroTagSprite;
- battleRes.levelLabelCol = 0;
- battleRes.levelLabelRow = 0;
- battleRes.healthLabelCol = 0;
- battleRes.healthLabelRow = 1;
- battleRes.manaLabelCol = 0;
- battleRes.manaLabelRow = 2;
- battleRes.moveLabelCol = 0;
- battleRes.moveLabelRow = 3;
- battleRes.ikariLabelCol = 0;
- battleRes.ikariLabelRow = 4;
-
- SDL_Surface *numbersImg(IMG_Load("test-data/numbers.png"));
- Sprite numbersSprite(numbersImg, 16, 16);
- Font heroTagFont(&numbersSprite, 0, -3);
- battleRes.heroTagFont = &heroTagFont;
- SDL_Surface *tagFramesImg(IMG_Load("test-data/tag-frames.png"));
- Frame heroTagFrame(tagFramesImg, 16, 16, 1, 1, 0, 33);
- battleRes.heroTagFrame = &heroTagFrame;
- Frame activeHeroTagFrame(tagFramesImg, 16, 16);
- battleRes.activeHeroTagFrame = &activeHeroTagFrame;
- SDL_Surface *smallTagFrameImg(IMG_Load("test-data/small-tag-frame.png"));
- Frame smallTagFrame(smallTagFrameImg, 8, 16);
- battleRes.smallHeroTagFrame = &smallTagFrame;
- Frame lastSmallTagFrame(smallTagFrameImg, 8, 16, 1, 1, 0, 33);
- battleRes.lastSmallHeroTagFrame = &lastSmallTagFrame;
- battleRes.heroesBgColor = SDL_MapRGB(screen.Screen()->format, 0x18, 0x28, 0x31);
-
- SDL_Surface *gauges(IMG_Load("test-data/gauges.png"));
- Gauge healthGauge(gauges, 0, 16, 0, 0, 16, 6, 1, 6);
- battleRes.healthGauge = &healthGauge;
- Gauge manaGauge(gauges, 0, 32, 0, 0, 16, 6, 1, 6);
- battleRes.manaGauge = &manaGauge;
- Gauge ikariGauge(gauges, 0, 48, 0, 0, 16, 6, 1, 6);
- battleRes.ikariGauge = &ikariGauge;
-
- SDL_Surface *selectFrameImg(IMG_Load("test-data/select-frame.png"));
- Frame selectFrame(selectFrameImg, 16, 16);
- battleRes.selectFrame = &selectFrame;
-
- SDL_Surface *normalFontImg(IMG_Load("test-data/normal-font.png"));
- Sprite normalFontSprite(normalFontImg, 16, 16);
- Font normalFont(&normalFontSprite, 0, -2);
- battleRes.normalFont = &normalFont;
-
- SDL_Surface *disabledFontImg(IMG_Load("test-data/disabled-font.png"));
- Sprite disabledFontSprite(disabledFontImg, 16, 16);
- Font disabledFont(&disabledFontSprite, 0, -2);
- battleRes.disabledFont = &disabledFont;
-
- SDL_Surface *handCursorImg(IMG_Load("test-data/cursor-hand.png"));
- Sprite handCursorSprite(handCursorImg, 32, 32);
- battleRes.menuCursor = &handCursorSprite;
-
- SDL_Surface *targetingIconsImg(IMG_Load("test-data/targeting-icons.png"));
- Sprite weaponTargetCursor(targetingIconsImg, 32, 32);
- Sprite magicTargetCursor(targetingIconsImg, 32, 32, 0, 32);
- Sprite itemTargetCursor(targetingIconsImg, 32, 32, 0, 64);
- battleRes.weaponTargetCursor = &weaponTargetCursor;
- battleRes.magicTargetCursor = &magicTargetCursor;
- battleRes.itemTargetCursor = &itemTargetCursor;
-
- Spell resetSpell;
- resetSpell.SetName("Reset");
- maxim.AddSpell(&resetSpell);
- Spell strongSpell;
- strongSpell.SetName("Strong");
- strongSpell.SetCost(3);
- strongSpell.SetUsableInBattle();
- strongSpell.GetTargetingMode().TargetMultipleAllies();
- maxim.AddSpell(&strongSpell);
- selan.AddSpell(&strongSpell);
- Spell strongerSpell;
- strongerSpell.SetName("Stronger");
- strongerSpell.SetCost(8);
- strongerSpell.SetUsableInBattle();
- strongerSpell.GetTargetingMode().TargetMultipleAllies();
- maxim.AddSpell(&strongerSpell);
- selan.AddSpell(&strongerSpell);
- Spell championSpell;
- championSpell.SetName("Champion");
- championSpell.SetCost(16);
- championSpell.SetUsableInBattle();
- championSpell.GetTargetingMode().TargetMultipleAllies();
- maxim.AddSpell(&championSpell);
- selan.AddSpell(&championSpell);
- Spell rallySpell;
- rallySpell.SetName("Rally");
- rallySpell.SetCost(10);
- rallySpell.SetUsableInBattle();
- rallySpell.GetTargetingMode().TargetMultipleAllies();
- maxim.AddSpell(&rallySpell);
- selan.AddSpell(&rallySpell);
- Spell escapeSpell;
- escapeSpell.SetName("Escape");
- escapeSpell.SetCost(8);
- selan.AddSpell(&escapeSpell);
- Spell valorSpell;
- valorSpell.SetName("Valor");
- valorSpell.SetCost(30);
- valorSpell.SetUsableInBattle();
- valorSpell.GetTargetingMode().TargetMultipleAllies();
- maxim.AddSpell(&valorSpell);
- selan.AddSpell(&valorSpell);
-
- battleRes.spellMenuHeadline = "Please choose a spell.";
- battleRes.spellMenuPrototype = Menu<const Spell *>(&normalFont, &disabledFont, &handCursorSprite, 9, 6, 8, 0, 2, 32, 2, ':');
-
- SDL_Surface *itemIcons(IMG_Load("test-data/item-icons.png"));
- Sprite potionIcon(itemIcons, 16, 16);
- Sprite ballIcon(itemIcons, 16, 16, 0, 16);
- Sprite crankIcon(itemIcons, 16, 16, 0, 32);
- Sprite spearIcon(itemIcons, 16, 16, 0, 48);
- Sprite swordIcon(itemIcons, 16, 16, 0, 64);
- Sprite axIcon(itemIcons, 16, 16, 0, 80);
- Sprite rodIcon(itemIcons, 16, 16, 0, 96);
- Sprite armorIcon(itemIcons, 16, 16, 0, 112);
- Sprite shieldIcon(itemIcons, 16, 16, 0, 128);
- Sprite helmetIcon(itemIcons, 16, 16, 0, 144);
- Sprite ringIcon(itemIcons, 16, 16, 0, 160);
- Sprite jewelIcon(itemIcons, 16, 16, 0, 176);
-
- battleRes.weaponMenuIcon = &swordIcon;
- battleRes.armorMenuIcon = &armorIcon;
- battleRes.shieldMenuIcon = &shieldIcon;
- battleRes.helmetMenuIcon = &helmetIcon;
- battleRes.ringMenuIcon = &ringIcon;
- battleRes.jewelMenuIcon = &jewelIcon;
+ PartyLayout monstersLayout(*intp.GetPartyLayout("monstersLayout"));
+ PartyLayout heroesLayout(*intp.GetPartyLayout("heroesLayout"));
+
+ Monster monster(*intp.GetMonster("lizard"));
+ Hero maxim(*intp.GetHero("maxim"));
+ Hero selan(*intp.GetHero("selan"));
+ Hero guy(*intp.GetHero("guy"));
+ Hero dekar(*intp.GetHero("dekar"));
+
+ battle::Resources *battleRes(intp.GetBattleResources("battleResources"));
+
+ maxim.AddSpell(intp.GetSpell("resetSpell"));
+ Spell *strongSpell(intp.GetSpell("strongSpell"));
+ maxim.AddSpell(strongSpell);
+ selan.AddSpell(strongSpell);
+ Spell *strongerSpell(intp.GetSpell("strongerSpell"));
+ maxim.AddSpell(strongerSpell);
+ selan.AddSpell(strongerSpell);
+ Spell *championSpell(intp.GetSpell("championSpell"));
+ maxim.AddSpell(championSpell);
+ selan.AddSpell(championSpell);
+ Spell *rallySpell(intp.GetSpell("rallySpell"));
+ maxim.AddSpell(rallySpell);
+ selan.AddSpell(rallySpell);
+ selan.AddSpell(intp.GetSpell("escapeSpell"));
+ Spell *valorSpell(intp.GetSpell("valorSpell"));
+ maxim.AddSpell(valorSpell);
+ selan.AddSpell(valorSpell);
Inventory inventory;
- Item antidote;
- antidote.SetName("Antidote");
- antidote.SetMenuIcon(&potionIcon);
- antidote.SetUsableInBattle();
- antidote.GetTargetingMode().TargetSingleAlly();
- inventory.Add(&antidote, 9);
- Item magicJar;
- magicJar.SetName("Magic jar");
- magicJar.SetMenuIcon(&potionIcon);
- magicJar.SetUsableInBattle();
- magicJar.GetTargetingMode().TargetSingleAlly();
- inventory.Add(&magicJar, 4);
- Item hiPotion;
- hiPotion.SetName("Hi-Potion");
- hiPotion.SetMenuIcon(&potionIcon);
- hiPotion.SetUsableInBattle();
- hiPotion.GetTargetingMode().TargetSingleAlly();
- inventory.Add(&hiPotion, 4);
- Item powerPotion;
- powerPotion.SetName("Power potion");
- powerPotion.SetMenuIcon(&potionIcon);
- inventory.Add(&powerPotion, 4);
- Item escape;
- escape.SetName("Escape");
- inventory.Add(&escape, 2);
- Item sleepBall;
- sleepBall.SetName("Sleep ball");
- sleepBall.SetMenuIcon(&ballIcon);
- sleepBall.SetUsableInBattle();
- sleepBall.GetTargetingMode().TargetSingleEnemy();
- inventory.Add(&sleepBall, 1);
- Item multiBall;
- multiBall.SetName("Multi-ball!");
- multiBall.SetMenuIcon(&ballIcon);
- multiBall.SetUsableInBattle();
- multiBall.GetTargetingMode().TargetMultipleEnemies();
- inventory.Add(&multiBall, 1);
- Item figgoru;
- figgoru.SetName("Figgoru");
- figgoru.SetMenuIcon(&crankIcon);
- figgoru.GetTargetingMode().TargetAllEnemies();
- inventory.Add(&figgoru, 1);
- battleRes.inventory = &inventory;
-
- battleRes.itemMenuHeadline = "Please choose an item.";
- battleRes.itemMenuPrototype = Menu<const common::Item *>(&normalFont, &disabledFont, &handCursorSprite, 15, 6, 8, 16, 1, 32, 2, ':');
-
- SDL_Surface *swordAttackImg(IMG_Load("test-data/attack-sword.png"));
- Sprite swordAttackSprite(swordAttackImg, 96, 96);
- SimpleAnimation swordAttackAnimation(&swordAttackSprite, 2 * framerate, 4);
-
- Item zircoSword;
- zircoSword.SetName("Zirco sword");
- zircoSword.SetMenuIcon(&swordIcon);
- zircoSword.GetTargetingMode().TargetSingleEnemy();
- Ikari firestorm;
- firestorm.SetName("Firestorm");
- firestorm.SetCost(224);
- firestorm.GetTargetingMode().TargetAllEnemies();
- firestorm.SetPhysical();
- zircoSword.SetIkari(&firestorm);
- zircoSword.SetAttackAnimation(&swordAttackAnimation);
- maxim.SetWeapon(&zircoSword);
- Item zirconArmor;
- zirconArmor.SetName("Zircon armor");
- zirconArmor.SetMenuIcon(&armorIcon);
- Ikari magicCure;
- magicCure.SetName("Magic cure");
- magicCure.SetCost(128);
- magicCure.GetTargetingMode().TargetSingleAlly();
- magicCure.SetMagical();
- zirconArmor.SetIkari(&magicCure);
- maxim.SetArmor(&zirconArmor);
- Item holyShield;
- holyShield.SetName("Holy shield");
- holyShield.SetMenuIcon(&shieldIcon);
- Ikari lightGuard;
- lightGuard.SetName("Light guard");
- lightGuard.SetCost(128);
- lightGuard.GetTargetingMode().TargetAllAllies(); // actually only targets self
- lightGuard.SetMagical();
- holyShield.SetIkari(&lightGuard);
- maxim.SetShield(&holyShield);
- Item legendHelm;
- legendHelm.SetName("Legend helm");
- legendHelm.SetMenuIcon(&helmetIcon);
- Ikari boomerang;
- boomerang.SetName("Boomerang");
- boomerang.SetCost(164);
- boomerang.GetTargetingMode().TargetAllAllies(); // actually only targets self
- boomerang.SetMagical();
- legendHelm.SetIkari(&boomerang);
- maxim.SetHelmet(&legendHelm);
- Item sProRing;
- sProRing.SetName("S-pro ring");
- sProRing.SetMenuIcon(&ringIcon);
- Ikari courage;
- courage.SetName("Courage");
- courage.SetCost(64);
- courage.GetTargetingMode().TargetMultipleAllies();
- courage.SetMagical();
- sProRing.SetIkari(&courage);
- maxim.SetRing(&sProRing);
- Item evilJewel;
- evilJewel.SetName("Evil jewel");
- evilJewel.SetMenuIcon(&jewelIcon);
- Ikari gloomy;
- gloomy.SetName("Gloomy");
- gloomy.SetCost(164);
- gloomy.GetTargetingMode().TargetAllEnemies();
- gloomy.SetMagical();
- evilJewel.SetIkari(&gloomy);
- maxim.SetJewel(&evilJewel);
-
- Item zircoWhip;
- zircoWhip.SetName("Zirco whip");
- zircoWhip.SetMenuIcon(&rodIcon);
- zircoWhip.GetTargetingMode().TargetSingleEnemy();
- Ikari thundershriek;
- thundershriek.SetName("Thundershriek");
- thundershriek.SetCost(224);
- thundershriek.GetTargetingMode().TargetAllEnemies();
- thundershriek.SetPhysical();
- zircoWhip.SetIkari(&thundershriek);
-// selan.SetWeapon(&zircoWhip);
- Item zirconPlate;
- zirconPlate.SetName("Zircon plate");
- zirconPlate.SetMenuIcon(&armorIcon);
- Ikari suddenCure;
- suddenCure.SetName("Sudden cure");
- suddenCure.SetCost(96);
- suddenCure.GetTargetingMode().TargetAllAllies();
- suddenCure.SetMagical();
- zirconPlate.SetIkari(&suddenCure);
- selan.SetArmor(&zirconPlate);
- Item zircoGloves;
- zircoGloves.SetName("Zirco gloves");
- zircoGloves.SetMenuIcon(&shieldIcon);
- Ikari forcefield;
- forcefield.SetName("Forcefield");
- forcefield.SetCost(64);
- forcefield.GetTargetingMode().TargetAllAllies();
- forcefield.SetMagical();
- zircoGloves.SetIkari(&forcefield);
- selan.SetShield(&zircoGloves);
- Item holyCap;
- holyCap.SetName("Holy cap");
- holyCap.SetMenuIcon(&helmetIcon);
- Ikari vulnerable;
- vulnerable.SetName("Vulnerable");
- vulnerable.SetCost(196);
- vulnerable.GetTargetingMode().TargetAllEnemies();
- vulnerable.SetPhysical();
- holyCap.SetIkari(&vulnerable);
- selan.SetHelmet(&holyCap);
- Item ghostRing;
- ghostRing.SetName("Ghost ring");
- ghostRing.SetMenuIcon(&ringIcon);
- Ikari destroy;
- destroy.SetName("Destroy");
- destroy.SetCost(128);
- destroy.GetTargetingMode().TargetMultipleEnemies();
- destroy.SetMagical();
- ghostRing.SetIkari(&destroy);
- selan.SetRing(&ghostRing);
- Item eagleRock;
- eagleRock.SetName("Eagle rock");
- eagleRock.SetMenuIcon(&jewelIcon);
- Ikari dive;
- dive.SetName("Dive");
- dive.SetCost(128);
- dive.GetTargetingMode().TargetSingleEnemy();
- dive.SetPhysical();
- eagleRock.SetIkari(&dive);
- selan.SetJewel(&eagleRock);
-
- Item zircoAx;
- zircoAx.SetName("Zirco ax");
- zircoAx.SetMenuIcon(&axIcon);
- zircoAx.GetTargetingMode().TargetSingleEnemy();
- Ikari torrent;
- torrent.SetName("Torrent");
- torrent.SetCost(224);
- torrent.GetTargetingMode().TargetAllEnemies();
- torrent.SetPhysical();
- zircoAx.SetIkari(&torrent);
-// guy.SetWeapon(&zircoAx);
- guy.SetArmor(&zirconArmor);
- Item megaShield;
- megaShield.SetName("Mega shield");
- megaShield.SetMenuIcon(&shieldIcon);
- Ikari ironBarrier;
- ironBarrier.SetName("Iron barrier");
- ironBarrier.SetCost(255);
- ironBarrier.GetTargetingMode().TargetAllAllies(); // actually only targets self
- ironBarrier.SetMagical();
- megaShield.SetIkari(&ironBarrier);
- guy.SetShield(&megaShield);
- Item zircoHelmet;
- zircoHelmet.SetName("Zirco helmet");
- zircoHelmet.SetMenuIcon(&helmetIcon);
- Ikari slow;
- slow.SetName("Slow");
- slow.SetCost(196);
- slow.GetTargetingMode().TargetAllEnemies();
- slow.SetPhysical();
- zircoHelmet.SetIkari(&slow);
- guy.SetHelmet(&zircoHelmet);
- Item powerRing;
- powerRing.SetName("Power ring");
- powerRing.SetMenuIcon(&ringIcon);
- Ikari trick;
- trick.SetName("Trick");
- trick.SetCost(32);
- trick.GetTargetingMode().TargetAllEnemies();
- trick.SetMagical();
- zircoHelmet.SetIkari(&trick);
- guy.SetRing(&powerRing);
- guy.SetJewel(&evilJewel);
+ inventory.Add(intp.GetItem("antidoteItem"), 9);
+ inventory.Add(intp.GetItem("magicJarItem"), 4);
+ inventory.Add(intp.GetItem("hiPotionItem"), 4);
+ inventory.Add(intp.GetItem("powerPotionItem"), 4);
+ inventory.Add(intp.GetItem("escapeItem"), 2);
+ inventory.Add(intp.GetItem("sleepBallItem"), 1);
+ battleRes->inventory = &inventory;
+
+ maxim.SetWeapon(intp.GetItem("zircoSwordItem"));
+ maxim.SetArmor(intp.GetItem("zirconArmorItem"));
+ maxim.SetShield(intp.GetItem("holyShieldItem"));
+ maxim.SetHelmet(intp.GetItem("legendHelmItem"));
+ maxim.SetRing(intp.GetItem("sProRingItem"));
+ maxim.SetJewel(intp.GetItem("evilJewelItem"));
+
+// selan.SetWeapon(intp.GetItem("zircoWhipItem"));
+ selan.SetArmor(intp.GetItem("zirconPlateItem"));
+ selan.SetShield(intp.GetItem("zircoGlovesItem"));
+ selan.SetHelmet(intp.GetItem("holyCapItem"));
+ selan.SetRing(intp.GetItem("ghostRingItem"));
+ selan.SetJewel(intp.GetItem("eagleRockItem"));
+
+// guy.SetWeapon(intp.GetItem("zircoAxItem"));
+ guy.SetArmor(intp.GetItem("zirconArmorItem"));
+ guy.SetShield(intp.GetItem("megaShieldItem"));
+ guy.SetHelmet(intp.GetItem("zircoHelmetItem"));
+ guy.SetRing(intp.GetItem("powerRingItem"));
+ guy.SetJewel(intp.GetItem("evilJewelItem"));
// NOTE: this is actually Artea equipment
- Item lizardBlow;
- lizardBlow.SetName("Lizard blow");
- lizardBlow.SetMenuIcon(&swordIcon);
- lizardBlow.GetTargetingMode().TargetSingleEnemy();
- Ikari dragonRush;
- dragonRush.SetName("Dragon rush");
- dragonRush.SetCost(164);
- dragonRush.GetTargetingMode().TargetSingleEnemy();
- dragonRush.SetPhysical();
- lizardBlow.SetIkari(&dragonRush);
-// dekar.SetWeapon(&lizardBlow);
- Item holyRobe;
- holyRobe.SetName("Holy robe");
- holyRobe.SetMenuIcon(&armorIcon);
- Ikari crisisCure;
- crisisCure.SetName("Crisis cure");
- crisisCure.SetCost(164);
- crisisCure.GetTargetingMode().TargetAllAllies();
- crisisCure.SetMagical();
- holyRobe.SetIkari(&crisisCure);
- dekar.SetArmor(&holyRobe);
- dekar.SetShield(&zircoGloves);
- dekar.SetHelmet(&holyCap);
- Item rocketRing;
- rocketRing.SetName("Rocket ring");
- rocketRing.SetMenuIcon(&ringIcon);
- Ikari fake;
- fake.SetName("Fake");
- fake.SetCost(32);
- fake.GetTargetingMode().TargetSingleAlly();
- fake.SetMagical();
- rocketRing.SetIkari(&fake);
- dekar.SetRing(&rocketRing);
- Item krakenRock;
- krakenRock.SetName("Kraken rock");
- krakenRock.SetMenuIcon(&jewelIcon);
- Ikari tenLegger;
- tenLegger.SetName("Ten-legger");
- tenLegger.SetCost(164);
- tenLegger.GetTargetingMode().TargetAllEnemies();
- tenLegger.SetPhysical();
- rocketRing.SetIkari(&tenLegger);
- dekar.SetJewel(&krakenRock);
-
- battleRes.ikariMenuHeadline = "Please choose equipment.";
- battleRes.noEquipmentText = "No equip";
- battleRes.ikariMenuPrototype = Menu<const Item *>(&normalFont, &disabledFont, &handCursorSprite, 12, 6, normalFont.CharHeight() / 2, normalFont.CharWidth(), 1, normalFont.CharWidth() * 2, 0, ':', 12, normalFont.CharWidth());
-
- battleRes.escapeText = "Escapes.";
-
- BattleState *battleState(new BattleState(bg, monstersLayout, heroesLayout, &battleRes));
+// dekar.SetWeapon(intp.GetItem("lizardBlowItem"));
+ dekar.SetArmor(intp.GetItem("holyRobeItem"));
+ dekar.SetShield(intp.GetItem("zircoGlovesItem"));
+ dekar.SetHelmet(intp.GetItem("holyCapItem"));
+ dekar.SetRing(intp.GetItem("rocketRingItem"));
+ dekar.SetJewel(intp.GetItem("krakenRockItem"));
+
+ BattleState *battleState(new BattleState(bg, monstersLayout, heroesLayout, battleRes));
battleState->AddMonster(monster);
battleState->AddMonster(monster);
battleState->AddMonster(monster);
app.Run();
return 0;
+ } catch (Parser::Error &e) {
+ cerr << "parsing exception in file " << e.File() << " on line " << e.Line() << ": " << e.what() << endl;
+ return 1;
} catch (exception &e) {
cerr << "exception in main(): " << e.what() << endl;
return 1;
--- /dev/null
+Ikari boomerangIkari
+Ikari courageIkari
+Ikari crisisCureIkari
+Ikari destroyIkari
+Ikari diveIkari
+Ikari dragonRushIkari
+Ikari fakeIkari
+Ikari firestormIkari
+Ikari forcefieldIkari
+Ikari gloomyIkari
+Ikari ironBarrierIkari
+Ikari lightGuardIkari
+Ikari magicCureIkari
+Ikari slowIkari
+Ikari suddenCureIkari
+Ikari tenLeggerIkari
+Ikari thundershriekIkari
+Ikari torrentIkari
+Ikari trickIkari
+Ikari vulnerableIkari
--- /dev/null
+export Ikari boomerangIkari {
+ name: "Boomerang",
+ cost: 164,
+ targets: TargetingMode {
+ ally: true,
+ all: true
+ },
+ magical: true
+}
+export Ikari courageIkari {
+ name: "Courage",
+ cost: 64,
+ targets: TargetingMode {
+ ally: true,
+ multiple: true
+ },
+ magical: true
+}
+export Ikari crisisCureIkari {
+ name: "Crisis cure",
+ cost: 164,
+ targets: TargetingMode {
+ ally: true,
+ all: true
+ },
+ magical: true
+}
+export Ikari destroyIkari {
+ name: "Destroy",
+ cost: 128,
+ targets: TargetingMode {
+ enemy: true,
+ multiple: true
+ },
+ magical: true
+}
+export Ikari diveIkari {
+ name: "Dive",
+ cost: 128,
+ targets: TargetingMode {
+ enemy: true,
+ single: true
+ },
+ physical: true
+}
+export Ikari dragonRushIkari {
+ name: "Dragon rush",
+ cost: 164,
+ targets: TargetingMode {
+ enemy: true,
+ single: true
+ },
+ physical: true
+}
+export Ikari fakeIkari {
+ name: "Fake",
+ cost: 32,
+ targets: TargetingMode {
+ ally: true,
+ single: true
+ },
+ magical: true
+}
+export Ikari firestormIkari {
+ name: "Firestorm",
+ cost: 224,
+ targets: TargetingMode {
+ enemy: true,
+ all: true
+ },
+ physical: true
+}
+export Ikari forcefieldIkari {
+ name: "Forcefield",
+ cost: 64,
+ targets: TargetingMode {
+ ally: true,
+ all: true
+ },
+ magical: true
+}
+export Ikari gloomyIkari {
+ name: "Gloomy",
+ cost: 164,
+ targets: TargetingMode {
+ enemy: true,
+ all: true
+ },
+ magical: true
+}
+export Ikari ironBarrierIkari {
+ name: "Iron barrier",
+ cost: 255,
+ targets: TargetingMode {
+ ally: true,
+ all: true
+ },
+ magical: true
+}
+export Ikari lightGuardIkari {
+ name: "Light guard",
+ cost: 128,
+ targets: TargetingMode {
+ ally: true,
+ all: true
+ },
+ magical: true
+}
+export Ikari magicCureIkari {
+ name: "Magic cure",
+ cost: 128,
+ targets: TargetingMode {
+ ally: true,
+ single: true
+ },
+ magical: true
+}
+export Ikari slowIkari {
+ name: "Slow",
+ cost: 196,
+ targets: TargetingMode {
+ enemy: true,
+ all: true
+ },
+ physical: true
+}
+export Ikari suddenCureIkari {
+ name: "Sudden cure",
+ cost: 96,
+ targets: TargetingMode {
+ ally: true,
+ all: true
+ },
+ magical: true
+}
+export Ikari tenLeggerIkari {
+ name: "Ten-legger",
+ cost: 164,
+ targets: TargetingMode {
+ enemy: true,
+ all: true
+ },
+ physical: true
+}
+export Ikari thundershriekIkari {
+ name: "Thundershriek",
+ cost: 224,
+ targets: TargetingMode {
+ enemy: true,
+ all: true
+ },
+ physical: true
+}
+export Ikari torrentIkari {
+ name: "Torrent",
+ cost: 224,
+ targets: TargetingMode {
+ enemy: true,
+ all: true
+ },
+ physical: true
+}
+export Ikari trickIkari {
+ name: "Trick",
+ cost: 32,
+ targets: TargetingMode {
+ enemy: true,
+ all: true
+ },
+ magical: true
+}
+export Ikari vulnerableIkari {
+ name: "Vulnerable",
+ cost: 196,
+ targets: TargetingMode {
+ enemy: true,
+ all: true
+ },
+ physical: true
+}
--- /dev/null
+Item antidoteItem
+Sprite armorIcon
+Sprite axIcon
+Sprite ballIcon
+Sprite crankIcon
+Item eagleRockItem
+Item escapeItem
+Item evilJewelItem
+Item ghostRingItem
+Sprite helmetIcon
+Item hiPotionItem
+Item holyCapItem
+Item holyRobeItem
+Item holyShieldItem
+Sprite jewelIcon
+Item krakenRockItem
+Item legendHelmItem
+Item lizardBlowItem
+Item magicJarItem
+Item megaShieldItem
+Sprite potionIcon
+Item powerPotionItem
+Item powerRingItem
+Sprite ringIcon
+Item rocketRingItem
+Sprite rodIcon
+Item sProRingItem
+Sprite shieldIcon
+Item sleepBallItem
+Sprite spearIcon
+SimpleAnimation swordAttackAnimation
+Sprite swordIcon
+Item zircoAxItem
+Item zircoGlovesItem
+Item zircoHelmetItem
+Item zircoSwordItem
+Item zircoWhipItem
+Item zirconArmorItem
+Item zirconPlateItem
--- /dev/null
+include "ikaris.l2h"
+
+export Sprite potionIcon {
+ image: :"item-icons.png",
+ size: <16,16>
+}
+export Sprite ballIcon {
+ image: :"item-icons.png",
+ size: <16,16>,
+ offset: <0,16>
+}
+export Sprite crankIcon {
+ image: :"item-icons.png",
+ size: <16,16>,
+ offset: <0,32>
+}
+export Sprite spearIcon {
+ image: :"item-icons.png",
+ size: <16,16>,
+ offset: <0,48>
+}
+export Sprite swordIcon {
+ image: :"item-icons.png",
+ size: <16,16>,
+ offset: <0,64>
+}
+export Sprite axIcon {
+ image: :"item-icons.png",
+ size: <16,16>,
+ offset: <0,80>
+}
+export Sprite rodIcon {
+ image: :"item-icons.png",
+ size: <16,16>,
+ offset: <0,96>
+}
+export Sprite armorIcon {
+ image: :"item-icons.png",
+ size: <16,16>,
+ offset: <0,112>
+}
+export Sprite shieldIcon {
+ image: :"item-icons.png",
+ size: <16,16>,
+ offset: <0,128>
+}
+export Sprite helmetIcon {
+ image: :"item-icons.png",
+ size: <16,16>,
+ offset: <0,144>
+}
+export Sprite ringIcon {
+ image: :"item-icons.png",
+ size: <16,16>,
+ offset: <0,160>
+}
+export Sprite jewelIcon {
+ image: :"item-icons.png",
+ size: <16,16>,
+ offset: <0,176>
+}
+
+export SimpleAnimation swordAttackAnimation {
+ sprite: Sprite {
+ image: :"attack-sword.png",
+ size: <96,96>
+ },
+ frametime: twoFramesTime,
+ repeat: false,
+ framecount: 4
+}
+
+export Item antidoteItem {
+ name: "Antidote",
+ menuicon: potionIcon,
+ battle: true,
+ targets: TargetingMode {
+ ally: true,
+ single: true
+ }
+}
+export Item eagleRockItem {
+ name: "Eagle rock",
+ menuicon: jewelIcon,
+ ikari: diveIkari
+}
+export Item escapeItem {
+ name: "Escape",
+ battle: false
+}
+export Item evilJewelItem {
+ name: "Evil jewel",
+ menuicon: jewelIcon,
+ ikari: gloomyIkari
+}
+export Item ghostRingItem {
+ name: "Ghost ring",
+ menuicon: ringIcon,
+ ikari: destroyIkari
+}
+export Item hiPotionItem {
+ name: "Hi-Potion",
+ menuicon: potionIcon,
+ battle: true,
+ targets: TargetingMode {
+ ally: true,
+ single: true
+ }
+}
+export Item holyCapItem {
+ name: "Holy cap",
+ menuicon: helmetIcon,
+ ikari: vulnerableIkari
+}
+export Item holyRobeItem {
+ name: "Holy robe",
+ menuicon: armorIcon,
+ ikari: crisisCureIkari
+}
+export Item holyShieldItem {
+ name: "Holy shield",
+ menuicon: shieldIcon,
+ ikari: lightGuardIkari
+}
+export Item krakenRockItem {
+ name: "Kraken rock",
+ menuicon: jewelIcon,
+ ikari: tenLeggerIkari
+}
+export Item legendHelmItem {
+ name: "Legend helm",
+ menuicon: helmetIcon,
+ ikari: boomerangIkari
+}
+export Item lizardBlowItem {
+ name: "Lizard blow",
+ menuicon: swordIcon,
+ ikari: dragonRushIkari,
+ targets: TargetingMode {
+ enemy: true,
+ single: true
+ }
+}
+export Item magicJarItem {
+ name: "Magic jar",
+ menuicon: potionIcon,
+ battle: true,
+ targets: TargetingMode {
+ ally: true,
+ single: true
+ }
+}
+export Item megaShieldItem {
+ name: "Mega shield",
+ menuicon: shieldIcon,
+ ikari: ironBarrierIkari
+}
+export Item powerPotionItem {
+ name: "Power potion",
+ menuicon: potionIcon,
+ battle: false
+}
+export Item powerRingItem {
+ name: "Power ring",
+ menuicon: ringIcon,
+ ikari: trickIkari
+}
+export Item rocketRingItem {
+ name: "Rocket ring",
+ menuicon: ringIcon,
+ ikari: fakeIkari
+}
+export Item sleepBallItem {
+ name: "Sleep ball",
+ menuicon: ballIcon,
+ battle: true,
+ targets: TargetingMode {
+ enemy: true,
+ single: true
+ }
+}
+export Item sProRingItem {
+ name: "S-pro ring",
+ menuicon: ringIcon,
+ ikari: courageIkari
+}
+export Item zircoAxItem {
+ name: "Zirco ax",
+ menuicon: axIcon,
+ ikari: torrentIkari,
+ targets: TargetingMode {
+ enemy: true,
+ single: true
+ }
+}
+export Item zircoGlovesItem {
+ name: "Zirco gloves",
+ menuicon: shieldIcon,
+ ikari: forcefieldIkari
+}
+export Item zircoHelmetItem {
+ name: "Zirco helmet",
+ menuicon: helmetIcon,
+ ikari: slowIkari
+}
+export Item zirconArmorItem {
+ name: "Zircon armor",
+ menuicon: armorIcon,
+ battle: false,
+ ikari: magicCureIkari
+}
+export Item zirconPlateItem {
+ name: "Zircon plate",
+ menuicon: armorIcon,
+ ikari: suddenCureIkari
+}
+export Item zircoSwordItem {
+ name: "Zirco sword",
+ menuicon: swordIcon,
+ battle: false,
+ targets: TargetingMode {
+ enemy: true,
+ single: true
+ },
+ ikari: firestormIkari,
+ attackanimation: swordAttackAnimation
+}
+export Item zircoWhipItem {
+ name: "Zirco whip",
+ menuicon: rodIcon,
+ targets: TargetingMode {
+ enemy: true,
+ single: true
+ },
+ ikari: thundershriekIkari
+}
--- /dev/null
+Spell championSpell
+Spell escapeSpell
+Spell rallySpell
+Spell resetSpell
+Spell strongSpell
+Spell strongerSpell
+Spell valorSpell
--- /dev/null
+export Spell championSpell {
+ name: "Champion",
+ cost: 16,
+ battle: true,
+ targets: TargetingMode {
+ ally: true,
+ multiple: true
+ }
+}
+
+export Spell escapeSpell {
+ name: "Escape",
+ cost: 8,
+ battle: false
+}
+
+export Spell rallySpell {
+ name: "Rally",
+ cost: 10,
+ battle: true,
+ targets: TargetingMode {
+ ally: true,
+ multiple: true
+ }
+}
+
+export Spell resetSpell {
+ name: "Reset",
+ cost: 0,
+ battle: false
+}
+
+export Spell strongSpell {
+ name: "Strong",
+ cost: 3,
+ battle: true,
+ targets: TargetingMode {
+ ally: true,
+ multiple: true
+ }
+}
+
+export Spell strongerSpell {
+ name: "Stronger",
+ cost: 8,
+ battle: true,
+ targets: TargetingMode {
+ ally: true,
+ multiple: true
+ }
+}
+
+export Spell valorSpell {
+ name: "Valor",
+ cost: 30,
+ battle: true,
+ targets: TargetingMode {
+ ally: true,
+ multiple: true
+ }
+}
--- /dev/null
+include "ikaris.l2h"
+include "items.l2h"
+include "spells.l2h"
+
+Number frameTime 33
+Number twoFramesTime 66
+Number fourFramesTime 132
+Number fiveFramesTime 165 // darn, i really need to implement expressions
+
+export PartyLayout monstersLayout {
+ positions: [
+ < 88, 88>,
+ <128, 88>,
+ <168, 88>,
+ <208, 88>
+ ]
+}
+export PartyLayout heroesLayout {
+ positions: [
+ < 48,136>,
+ <128,136>,
+ < 80,152>,
+ <160,152>
+ ]
+}
+
+Sprite lizardSprite {
+ image: :"monster.png",
+ size: <64,64>
+}
+
+export Monster lizard {
+ name: "Lizard",
+ sprite: lizardSprite,
+ level: 1,
+ maxHealth: 8,
+ health: 8,
+ stats: Stats {
+ atp: 14,
+ dfp: 6,
+ str: 6,
+ agl: 6,
+ int: 6,
+ gut: 6,
+ mgr: 6
+ },
+ attackAnimation: ComplexAnimation {
+ sprite: lizardSprite,
+ frametime: fourFramesTime,
+ repeat: false,
+ frames: [
+ { column: 0, row: 1, disposition: < 0, 16> },
+ { column: 0, row: 0, disposition: < 0, 16> },
+ { column: 0, row: 1, disposition: < 0, 16> },
+ { column: 0, row: 0, disposition: < 0, 16> }
+ ]
+ },
+ meleeAnimation: SimpleAnimation {
+ sprite: Sprite {
+ image: :"attack-monster.png",
+ size: <96,64>
+ },
+ frametime: frameTime,
+ framecount: 14
+ }
+}
+
+Sprite maximSprite {
+ image: :"maxim.png",
+ size: <64,64>
+}
+export Hero maxim {
+ name: "Maxim",
+ level: 1,
+ sprite: maximSprite,
+ maxHealth: 33,
+ health: 33,
+ maxMana: 20,
+ mana: 20,
+ ip: 0,
+ stats: Stats {
+ atp: 28,
+ dfp: 22,
+ str: 28,
+ agl: 17,
+ int: 14,
+ gut: 100,
+ mgr: 10
+ },
+ attackAnimation: ComplexAnimation {
+ sprite: maximSprite,
+ frametime: frameTime,
+ repeat: false,
+ frames: [
+ { column: 1, row: 0, disposition: < 0, 0> },
+ { column: 1, row: 0, disposition: < 0, 0> },
+ { column: 1, row: 0, disposition: < 0, 0> },
+ { column: 1, row: 0, disposition: < 0, 0> },
+ { column: 1, row: 0, disposition: < 0, 0> },
+ { column: 1, row: 0, disposition: < 0, 0> },
+ { column: 1, row: 0, disposition: < 0, 0> },
+ { column: 1, row: 0, disposition: < 4,-1> },
+ { column: 1, row: 0, disposition: < 4,-1> },
+ { column: 2, row: 0, disposition: < 4,-2> },
+ { column: 2, row: 0, disposition: < 4,-2> },
+ { column: 2, row: 0, disposition: < 6,-2> },
+ { column: 2, row: 0, disposition: < 6,-2> },
+ { column: 2, row: 1, disposition: < 6,-1> },
+ { column: 2, row: 1, disposition: < 3,-1> },
+ { column: 2, row: 1, disposition: < 3,-1> },
+ { column: 2, row: 1, disposition: < 0, 0> },
+ { column: 2, row: 2, disposition: < 0, 0> },
+ { column: 2, row: 2, disposition: < 0, 0> },
+ { column: 2, row: 2, disposition: < 2, 0> },
+ { column: 1, row: 0, disposition: < 0, 0> },
+ { column: 1, row: 0, disposition: < 0, 0> },
+ { column: 1, row: 0, disposition: < 0, 0> },
+ { column: 1, row: 0, disposition: < 0, 0> },
+ { column: 1, row: 0, disposition: < 0, 0> },
+ { column: 1, row: 0, disposition: < 0, 0> },
+ { column: 1, row: 0, disposition: < 0, 0> }
+ ]
+ },
+ spellAnimation: ComplexAnimation {
+ sprite: maximSprite,
+ frametime: fiveFramesTime,
+ repeat: false,
+ frames: [
+ { column: 3, row: 0, disposition: < 0, 0> },
+ { column: 3, row: 0, disposition: < 0, 0> },
+ { column: 3, row: 1, disposition: < 0, 0> }
+ ]
+ },
+ meleeAnimation: SimpleAnimation {
+ sprite: Sprite {
+ image: :"melee-maxim.png",
+ size: <96,96>
+ },
+ frametime: twoFramesTime,
+ framecount: 4
+ }
+}
+
+Sprite selanSprite {
+ image: :"selan.png",
+ size: <64,64>
+}
+export Hero selan {
+ name: "Selan",
+ level: 1,
+ sprite: selanSprite,
+ maxHealth: 28,
+ health: 28,
+ maxMana: 23,
+ mana: 23,
+ ip: 0,
+ stats: Stats {
+ atp: 23,
+ dfp: 21,
+ str: 23,
+ agl: 19,
+ int: 22,
+ gut: 80,
+ mgr: 13
+ },
+ attackAnimation: ComplexAnimation {
+ sprite: selanSprite,
+ frametime: frameTime,
+ repeat: false,
+ frames: [
+ { column: 1, row: 0, disposition: < 4, 0> },
+ { column: 1, row: 0, disposition: < 4, 0> },
+ { column: 1, row: 0, disposition: < 8, 2> },
+ { column: 2, row: 0, disposition: <10, 4> },
+ { column: 2, row: 0, disposition: <14, 4> },
+ { column: 2, row: 0, disposition: <12, 2> },
+ { column: 2, row: 0, disposition: <12, 2> },
+ { column: 2, row: 0, disposition: <12, 2> },
+ { column: 2, row: 1, disposition: <14, 2> },
+ { column: 2, row: 1, disposition: <14, 2> },
+ { column: 2, row: 1, disposition: < 2, 0> },
+ { column: 2, row: 2, disposition: <-2,-4> },
+ { column: 2, row: 2, disposition: <-8,-8> },
+ { column: 2, row: 2, disposition: < 0, 0> }
+ ]
+ },
+ spellAnimation: ComplexAnimation {
+ sprite: selanSprite,
+ frametime: frameTime,
+ repeat: false,
+ frames: [
+ { column: 3, row: 0, disposition: < 0, 0> },
+ { column: 3, row: 0, disposition: < 0, 0> },
+ { column: 3, row: 0, disposition: < 0, 0> },
+ { column: 3, row: 1, disposition: < 0, 0> },
+ { column: 3, row: 1, disposition: < 0, 0> },
+ { column: 3, row: 2, disposition: < 0, 0> },
+ { column: 3, row: 2, disposition: < 0, 0> },
+ { column: 3, row: 2, disposition: < 0, 0> },
+ { column: 3, row: 3, disposition: < 0, 0> },
+ { column: 3, row: 3, disposition: < 0, 0> }
+ ]
+ },
+ meleeAnimation: SimpleAnimation {
+ sprite: Sprite {
+ image: :"melee-selan.png",
+ size: <96,96>
+ },
+ frametime: twoFramesTime,
+ framecount: 4
+ }
+}
+
+Sprite guySprite {
+ image: :"guy.png",
+ size: <64,64>
+}
+export Hero guy {
+ name: "Guy",
+ level: 1,
+ sprite: guySprite,
+ maxHealth: 38,
+ health: 38,
+ maxMana: 0,
+ mana: 0,
+ ip: 0,
+ stats: Stats {
+ atp: 38,
+ dfp: 25,
+ str: 38,
+ agl: 13,
+ int: 8,
+ gut: 90,
+ mgr: 8
+ },
+ attackAnimation: ComplexAnimation {
+ sprite: guySprite,
+ frametime: frameTime,
+ repeat: false,
+ frames: [
+ { column: 1, row: 0, disposition: <-4, 0> },
+ { column: 1, row: 0, disposition: <-4, 0> },
+ { column: 1, row: 0, disposition: <-8, 0> },
+ { column: 1, row: 0, disposition: <-8, 0> },
+ { column: 2, row: 0, disposition: <-8, 0> },
+ { column: 2, row: 0, disposition: <-8, 0> },
+ { column: 2, row: 0, disposition: <-4, 0> },
+ { column: 2, row: 0, disposition: < 0, 0> },
+ { column: 2, row: 0, disposition: < 0, 0> },
+ { column: 2, row: 1, disposition: < 0, 0> },
+ { column: 2, row: 1, disposition: < 4, 0> },
+ { column: 2, row: 1, disposition: <10, 0> },
+ { column: 2, row: 2, disposition: <10, 0> },
+ { column: 2, row: 2, disposition: < 0, 0> }
+ ]
+ },
+ meleeAnimation: SimpleAnimation {
+ sprite: Sprite {
+ image: :"melee-guy.png",
+ size: <96,96>
+ },
+ frametime: fourFramesTime,
+ framecount: 4
+ }
+}
+
+Sprite dekarSprite {
+ image: :"dekar.png",
+ size: <64,64>
+}
+export Hero dekar {
+ name: "Dekar",
+ level: 1,
+ sprite: dekarSprite,
+ maxHealth: 38,
+ health: 38,
+ maxMana: 0,
+ mana: 0,
+ ip: 0,
+ stats: Stats {
+ atp: 46,
+ dfp: 29,
+ str: 46,
+ agl: 13,
+ int: 7,
+ gut: 100,
+ mgr: 5
+ },
+ attackAnimation: ComplexAnimation {
+ sprite: dekarSprite,
+ frametime: frameTime,
+ repeat: false,
+ frames: [
+ { column: 1, row: 0, disposition: < 4, 0> },
+ { column: 1, row: 0, disposition: < 8, 2> },
+ { column: 2, row: 0, disposition: <12, 4> },
+ { column: 2, row: 0, disposition: <16, 4> },
+ { column: 2, row: 0, disposition: <10, 2> },
+ { column: 2, row: 0, disposition: <10, 2> },
+ { column: 2, row: 0, disposition: <10, 2> },
+ { column: 2, row: 0, disposition: <10, 2> },
+ { column: 2, row: 1, disposition: < 6, 2> },
+ { column: 2, row: 1, disposition: < 0, 0> },
+ { column: 2, row: 2, disposition: <-2, 0> },
+ { column: 2, row: 2, disposition: < 0, 0> },
+ { column: 2, row: 2, disposition: < 0, 0> },
+ { column: 2, row: 2, disposition: < 0, 0> }
+ ]
+ },
+ spellAnimation: ComplexAnimation {
+ sprite: dekarSprite,
+ frametime: twoFramesTime,
+ repeat: false,
+ frames: [
+ { column: 3, row: 0, disposition: < 0, 0> },
+ { column: 3, row: 0, disposition: < 0, 0> },
+ { column: 3, row: 0, disposition: < 0, 0> },
+ { column: 3, row: 0, disposition: < 0, 0> },
+ { column: 3, row: 0, disposition: < 0, 0> },
+ { column: 3, row: 0, disposition: < 0, 0> },
+ { column: 3, row: 1, disposition: < 0, 0> },
+ { column: 3, row: 1, disposition: < 0, 0> },
+ { column: 3, row: 2, disposition: < 0, 0> },
+ { column: 3, row: 2, disposition: < 0, 0> },
+ { column: 3, row: 2, disposition: < 0, 0> }
+ ]
+ },
+ meleeAnimation: SimpleAnimation {
+ sprite: Sprite {
+ image: :"melee-dekar.png",
+ size: <96,96>
+ },
+ frametime: twoFramesTime,
+ framecount: 4
+ }
+}
+
+Sprite handCursor {
+ image: :"cursor-hand.png",
+ size: <32,32>
+}
+
+Font normalFont {
+ sprite: Sprite {
+ image: :"normal-font.png",
+ size: <16,16>
+ },
+ rowoffset: -2
+}
+
+Font disabledFont {
+ sprite: Sprite {
+ image: :"disabled-font.png",
+ size: <16,16>
+ },
+ rowoffset: -2
+}
+
+export BattleResources battleResources {
+ swapCursor: Sprite {
+ image: :"swap-cursor.png",
+ size: <32,32>
+ },
+ attackIcons: Sprite {
+ image: :"attack-type-icons.png",
+ size: <32,32>
+ },
+ attackChoiceIcons: Sprite {
+ image: :"attack-choice-icons.png",
+ size: <16,16>
+ },
+ moveIcons: Sprite {
+ image: :"move-icons.png",
+ size: <32,32>
+ },
+
+ titleFrame: Frame {
+ image: :"title-frame.png",
+ border: <16,16>
+ },
+ titleFont: Font {
+ sprite: Sprite {
+ image: :"large-font.png",
+ size: <16,32>
+ },
+ rowoffset: -2
+ },
+
+ numberAnimationPrototype: ComplexAnimation {
+ frametime: frameTime,
+ repeat: false,
+ frames: [
+ { column: 0, row: 0, disposition: < 0, 0> },
+ { column: 0, row: 0, disposition: < 0,-26> },
+ { column: 0, row: 0, disposition: < 0,-42> },
+ { column: 0, row: 0, disposition: < 0,-48> },
+ { column: 0, row: 0, disposition: < 0,-42> },
+ { column: 0, row: 0, disposition: < 0,-26> },
+ { column: 0, row: 0, disposition: < 0, 0> },
+ { column: 0, row: 0, disposition: < 0,-12> },
+ { column: 0, row: 0, disposition: < 0,-20> },
+ { column: 0, row: 0, disposition: < 0,-24> },
+ { column: 0, row: 0, disposition: < 0,-20> },
+ { column: 0, row: 0, disposition: < 0,-12> },
+ { column: 0, row: 0, disposition: < 0, 0> },
+ { column: 0, row: 0, disposition: < 0, -6> },
+ { column: 0, row: 0, disposition: < 0,-10> },
+ { column: 0, row: 0, disposition: < 0,-12> },
+ { column: 0, row: 0, disposition: < 0,-10> },
+ { column: 0, row: 0, disposition: < 0, -6> },
+ { column: 0, row: 0, disposition: < 0, 0> },
+ { column: 0, row: 0, disposition: < 0, 0> },
+ { column: 0, row: 0, disposition: < 0, 0> },
+ { column: 0, row: 0, disposition: < 0, 0> },
+ { column: 0, row: 0, disposition: < 0, 0> },
+ { column: 0, row: 0, disposition: < 0, 0> },
+ { column: 0, row: 0, disposition: < 0, 0> },
+ { column: 0, row: 0, disposition: < 0, 0> },
+ { column: 0, row: 0, disposition: < 0, 0> },
+ { column: 0, row: 0, disposition: < 0, 0> },
+ { column: 0, row: 0, disposition: < 0, 0> },
+ { column: 0, row: 0, disposition: < 0, 0> },
+ { column: 0, row: 0, disposition: < 0, 0> },
+ { column: 0, row: 0, disposition: < 0, 0> },
+ { column: 0, row: 0, disposition: < 0,-36> },
+ { column: 0, row: 0, disposition: < 0,-32> },
+ { column: 0, row: 0, disposition: < 0,-18> }
+ ]
+ },
+ bigNumberSprite: Sprite {
+ image: :"big-numbers.png",
+ size: <16,32>
+ },
+ greenNumberSprite: Sprite {
+ image: :"big-green-numbers.png",
+ size: <16,32>
+ },
+
+ heroTagLabels: Sprite {
+ image: :"hero-tag-sprites.png",
+ size: <32,16>
+ },
+ levelLabelCol: 0,
+ levelLabelRow: 0,
+ healthLabelCol: 0,
+ healthLabelRow: 1,
+ manaLabelCol: 0,
+ manaLabelRow: 2,
+ moveLabelCol: 0,
+ moveLabelRow: 3,
+ ikariLabelCol: 0,
+ ikariLabelRow: 4,
+ heroTagFont: Font {
+ sprite: Sprite {
+ image: :"numbers.png",
+ size: <16,16>
+ },
+ rowoffset: -3
+ },
+
+ activeHeroTagFrame: Frame {
+ image: :"tag-frames.png",
+ border: <16,16>
+ },
+ heroTagFrame: Frame {
+ image: :"tag-frames.png",
+ border: <16,16>,
+ offset: < 0,33>
+ },
+
+ smallHeroTagFrame: Frame {
+ image: :"small-tag-frame.png",
+ border: <8,16>
+ },
+ lastSmallHeroTagFrame: Frame {
+ image: :"small-tag-frame.png",
+ border: <8,16>,
+ offset: <0,33>
+ },
+ heroesBgColor: (24, 40, 49),
+
+ healthGauge: Gauge {
+ image: :"gauges.png",
+ full: <0,16>,
+ empty: <0, 0>,
+ height: 16,
+ start: 6,
+ repeat: 1,
+ end: 6
+ },
+ manaGauge: Gauge {
+ image: :"gauges.png",
+ full: <0,32>,
+ empty: <0, 0>,
+ height: 16,
+ start: 6,
+ repeat: 1,
+ end: 6
+ },
+ ikariGauge: Gauge {
+ image: :"gauges.png",
+ full: <0,48>,
+ empty: <0, 0>,
+ height: 16,
+ start: 6,
+ repeat: 1,
+ end: 6
+ },
+
+ selectFrame: Frame {
+ image: :"select-frame.png",
+ border: <16,16>
+ },
+ normalFont: normalFont,
+ disabledFont: disabledFont,
+ menuCursor: Sprite {
+ image: :"cursor-hand.png",
+ size: <32,32>
+ },
+
+ weaponTargetCursor: Sprite {
+ image: :"targeting-icons.png",
+ size: <32,32>
+ },
+ magicTargetCursor: Sprite {
+ image: :"targeting-icons.png",
+ size: <32,32>,
+ offset: <0,32>
+ },
+ itemTargetCursor: Sprite {
+ image: :"targeting-icons.png",
+ size: <32,32>,
+ offset: <0,64>
+ },
+
+ weaponMenuIcon: swordIcon,
+ armorMenuIcon: armorIcon,
+ shieldMenuIcon: shieldIcon,
+ helmetMenuIcon: helmetIcon,
+ ringMenuIcon: ringIcon,
+ jewelMenuIcon: jewelIcon,
+
+ spellMenuHeadline: "Please choose a spell.",
+ spellMenuProperties: MenuProperties {
+ font: normalFont,
+ disabledFont: disabledFont,
+ cursor: handCursor,
+ charsPerEntry: 9,
+ rows: 6,
+ rowGap: 8,
+ iconSpace: 0,
+ cols: 2,
+ colGap: 32,
+ charsPerNumber: 2,
+ delimiter: ":"
+ },
+
+ itemMenuHeadline: "Please choose an item.",
+ itemMenuProperties: MenuProperties {
+ font: normalFont,
+ disabledFont: disabledFont,
+ cursor: handCursor,
+ charsPerEntry: 15,
+ rows: 6,
+ rowGap: 8,
+ iconSpace: 16,
+ cols: 1,
+ colGap: 32,
+ charsPerNumber: 2,
+ delimiter: ":"
+ },
+
+ ikariMenuHeadline: "Please choose equipment.",
+ ikariMenuProperties: MenuProperties {
+ font: normalFont,
+ disabledFont: disabledFont,
+ cursor: handCursor,
+ charsPerEntry: 12,
+ rows: 6,
+ rowGap: 8,
+ iconSpace: 16,
+ cols: 1,
+ colGap: 32,
+ charsPerAdditionalText: 12,
+ additionalTextGap: 16
+ },
+ noEquipmentText: "No equip",
+
+ escapeText: "Escapes."
+}
\ No newline at end of file