+#include "Capsule.h"
+
+#include "../common/Spell.h"
+#include "../common/Stats.h"
+#include "../graphics/Animation.h"
+#include "../graphics/Sprite.h"
+#include "../loader/Interpreter.h"
+#include "../loader/TypeDescription.h"
+
+#include <cassert>
+
+using common::Spell;
+using common::Stats;
+using graphics::Animation;
+using graphics::Sprite;
+using loader::FieldDescription;
+using loader::Interpreter;
+using loader::TypeDescription;
+
+namespace common {
+
+Capsule::Capsule()
+: name("")
+, alignment("")
+
+, maxHealth(0)
+
+, level(1)
+, experience(0)
+
+, levelLadder(0)
+, numLevels(0)
+
+, classes(0)
+, numClasses(0)
+, curClass(0)
+, maxClass(0) {
+
+}
+
+
+Uint16 Capsule::MaxHealth() const {
+ return maxHealth + GetClass().healthBoost;
+}
+
+
+Stats Capsule::GetStats() {
+ return stats + GetClass().statBoost;
+}
+
+int Capsule::NextLevel() const {
+ int levelOffset(Level() - 1);
+ if (levelOffset < numLevels) {
+ return levelLadder[levelOffset] - Experience();
+ } else {
+ return 0;
+ }
+}
+
+
+Sprite *Capsule::BattleSprite() {
+ return GetClass().battleSprite;
+}
+
+const Sprite *Capsule::BattleSprite() const {
+ return GetClass().battleSprite;
+}
+
+Animation *Capsule::MeleeAnimation() {
+ return GetClass().meleeAnimation;
+}
+
+Animation *Capsule::AttackAnimation() {
+ return GetClass().attackAnimation;
+}
+
+Animation *Capsule::SpellAnimation() {
+ return GetClass().spellAnimation;
+}
+
+
+Capsule::Class &Capsule::GetClass() {
+ assert(classes && curClass < numClasses);
+ return classes[curClass];
+}
+
+const Capsule::Class &Capsule::GetClass() const {
+ assert(classes && curClass < numClasses);
+ return classes[curClass];
+}
+
+
+Capsule::Class::Class()
+: name(0)
+, tribe(0)
+, battleSprite(0)
+, meleeAnimation(0)
+, attackAnimation(0)
+, spellAnimation(0)
+
+, healthBoost(0) {
+ attacks[0] = 0;
+ attacks[1] = 0;
+ attacks[2] = 0;
+}
+
+
+void Capsule::CreateTypeDescription() {
+ Capsule c;
+
+ TypeDescription &td(TypeDescription::Create(TYPE_ID, "Capsule"));
+ td.SetConstructor(&Construct);
+ td.SetSize(sizeof(Capsule));
+
+ td.AddField("name", FieldDescription(((char *)&c.name) - ((char *)&c), Interpreter::STRING_ID).SetReferenced());
+ td.AddField("alignment", FieldDescription(((char *)&c.alignment) - ((char *)&c), Interpreter::STRING_ID).SetReferenced());
+
+ td.AddField("maxHealth", FieldDescription(((char *)&c.maxHealth) - ((char *)&c), Interpreter::NUMBER_ID));
+
+ td.AddField("stats", FieldDescription(((char *)&c.stats) - ((char *)&c), Stats::TYPE_ID));
+
+ td.AddField("level", FieldDescription(((char *)&c.level) - ((char *)&c), Interpreter::NUMBER_ID));
+ td.AddField("experience", FieldDescription(((char *)&c.experience) - ((char *)&c), Interpreter::NUMBER_ID));
+
+ td.AddField("ladder", FieldDescription(((char *)&c.levelLadder) - ((char *)&c), Interpreter::NUMBER_ID).SetReferenced().SetAggregate());
+
+ td.AddField("classes", FieldDescription(((char *)&c.classes) - ((char *)&c), Class::TYPE_ID).SetReferenced().SetAggregate());
+ td.AddField("class", FieldDescription(((char *)&c.curClass) - ((char *)&c), Interpreter::NUMBER_ID));
+ td.AddField("maxClass", FieldDescription(((char *)&c.maxClass) - ((char *)&c), Interpreter::NUMBER_ID));
+
+ Class::CreateTypeDescription();
+}
+
+void Capsule::Construct(void *data) {
+ new (data) Capsule;
+}
+
+
+void Capsule::Class::CreateTypeDescription() {
+ Class c;
+
+ TypeDescription &td(TypeDescription::Create(TYPE_ID, "CapsuleClass"));
+ td.SetConstructor(&Construct);
+ td.SetSize(sizeof(Class));
+
+ td.AddField("name", FieldDescription(((char *)&c.name) - ((char *)&c), Interpreter::STRING_ID).SetReferenced());
+ td.AddField("tribe", FieldDescription(((char *)&c.tribe) - ((char *)&c), Interpreter::STRING_ID).SetReferenced());
+
+ td.AddField("attack1", FieldDescription(((char *)&c.attacks[0]) - ((char *)&c), Spell::TYPE_ID).SetReferenced());
+ td.AddField("attack2", FieldDescription(((char *)&c.attacks[1]) - ((char *)&c), Spell::TYPE_ID).SetReferenced());
+ td.AddField("attack3", FieldDescription(((char *)&c.attacks[2]) - ((char *)&c), Spell::TYPE_ID).SetReferenced());
+
+ td.AddField("battleSprite", FieldDescription(((char *)&c.battleSprite) - ((char *)&c), Sprite::TYPE_ID).SetReferenced());
+ td.AddField("meleeAnimation", FieldDescription(((char *)&c.meleeAnimation) - ((char *)&c), Animation::TYPE_ID).SetReferenced());
+ td.AddField("attackAnimation", FieldDescription(((char *)&c.attackAnimation) - ((char *)&c), Animation::TYPE_ID).SetReferenced());
+ td.AddField("spellAnimation", FieldDescription(((char *)&c.spellAnimation) - ((char *)&c), Animation::TYPE_ID).SetReferenced());
+
+ td.AddField("healthBoost", FieldDescription(((char *)&c.healthBoost) - ((char *)&c), Interpreter::NUMBER_ID));
+ td.AddField("statBoost", FieldDescription(((char *)&c.statBoost) - ((char *)&c), Stats::TYPE_ID));
+}
+
+void Capsule::Class::Construct(void *data) {
+ new (data) Capsule::Class;
+}
+
+}