-/*
- * BattleState.cpp
- *
- * Created on: Aug 5, 2012
- * Author: holy
- */
-
#include "BattleState.h"
#include "PartyLayout.h"
#include "../common/Spell.h"
#include "../graphics/Frame.h"
#include "../graphics/Sprite.h"
+#include "../math/Vector.h"
#include <algorithm>
#include <cassert>
using common::Item;
using common::Spell;
using common::Stats;
-using geometry::Vector;
+using math::Vector;
using graphics::Menu;
using std::rand;
++numHeroes;
}
+void BattleState::SetCapsule(const Capsule &c) {
+ capsule = c;
+}
+
void BattleState::NextHero() {
++activeHero;
while (activeHero < numHeroes && heroes[activeHero].Health() == 0) {
smallHeroTags[i] = SmallHeroTag(this, i);
}
+ capsule.Position() = heroesLayout->CalculatePosition(4, background->w, background->h);
+
for (int i(0); i < int(monsters.size()); ++i) {
monsters[i].Position() = monstersLayout->CalculatePosition(i, background->w, background->h);
}
public:
OrderCompare(BattleState *battle) : battle(battle) { }
bool operator ()(const BattleState::Order &lhs, const BattleState::Order &rhs) {
- int lagl(lhs.isMonster ? battle->MonsterAt(lhs.index).GetStats().Agility() : battle->HeroAt(lhs.index).GetStats().Agility());
- int ragl(rhs.isMonster ? battle->MonsterAt(rhs.index).GetStats().Agility() : battle->HeroAt(rhs.index).GetStats().Agility());
- return lagl > ragl;
+ return lhs.GetStats(*battle).Agility() > rhs.GetStats(*battle).Agility();
}
private:
BattleState *battle;
void BattleState::CalculateAttackOrder() {
attackOrder.reserve(monsters.size() + NumHeroes());
for (int i(0); i < NumHeroes(); ++i) {
- attackOrder.push_back(Order(i, false));
+ attackOrder.push_back(Order(Order::HERO, i));
}
for (vector<Monster>::size_type i(0), end(monsters.size()); i < end; ++i) {
- attackOrder.push_back(Order(i, true));
+ attackOrder.push_back(Order(Order::MONSTER, i));
MonsterAt(i).GetAttackChoice() = AttackChoice(this);
}
+ if (capsule.Active() && capsule.Health() > 0) {
+ attackOrder.push_back(Order(Order::CAPSULE));
+ }
std::sort(attackOrder.begin(), attackOrder.end(), OrderCompare(this));
}
}
++attackCursor;
while (attackCursor < int(attackOrder.size())) {
- if (attackOrder[attackCursor].isMonster) {
+ if (attackOrder[attackCursor].IsMonster()) {
if (MonsterAt(attackOrder[attackCursor].index).Health() > 0) break;
- } else {
+ } else if (attackOrder[attackCursor].IsHero()) {
if (HeroAt(attackOrder[attackCursor].index).Health() > 0) break;
+ } else {
+ if (capsule.Active() && capsule.Health() > 0) break;
}
++attackCursor;
}
}
void BattleState::CalculateDamage() {
- if (CurrentAttack().isMonster) {
+ if (CurrentAttack().IsMonster()) {
DecideMonsterAttack(MonsterAt(CurrentAttack().index));
+ } else if (CurrentAttack().IsCapsule()) {
+ DecideCapsuleAttack();
}
- AttackChoice &ac(CurrentAttack().isMonster ? MonsterAt(CurrentAttack().index).GetAttackChoice() : HeroAt(CurrentAttack().index).GetAttackChoice());
+ AttackChoice &ac = CurrentAttack().GetAttackChoice(*this);
if (ac.GetType() == AttackChoice::DEFEND) return;
TargetSelection &ts(ac.Selection());
- if (CurrentAttack().isMonster) {
- const Stats &attackerStats(MonsterAt(CurrentAttack().index).GetStats());
- CalculateDamage(attackerStats, ts);
- } else {
- const Stats &attackerStats(HeroAt(CurrentAttack().index).GetStats());
- CalculateDamage(attackerStats, ts);
- }
+ const Stats &attackerStats = CurrentAttack().GetStats(*this);
+ CalculateDamage(attackerStats, ts);
}
-void BattleState::DecideMonsterAttack(Monster &m) const {
+void BattleState::DecideMonsterAttack(Monster &m) {
AttackChoice &ac(m.GetAttackChoice());
TargetSelection &ts(ac.Selection());
ac.Reset();
ts.Select(target);
}
+void BattleState::DecideCapsuleAttack() {
+ AttackChoice &ac(capsule.GetAttackChoice());
+ TargetSelection &ts(ac.Selection());
+ ac.Reset();
+ int target(rand() % monsters.size());
+ while (!MonsterPositionOccupied(target)) {
+ target = rand() % monsters.size();
+ }
+ ac.SetType(AttackChoice::SWORD);
+ ts.SelectMonsters();
+ ts.SetSingle();
+ ts.Select(target);
+}
+
+AttackChoice &BattleState::Order::GetAttackChoice(BattleState &b) const {
+ switch (by) {
+ case HERO:
+ return b.HeroAt(index).GetAttackChoice();
+ case CAPSULE:
+ return b.GetCapsule().GetAttackChoice();
+ case MONSTER:
+ return b.MonsterAt(index).GetAttackChoice();
+ default:
+ throw std::runtime_error("invalid case in BttleStats::Order::GetAttackChoice()");
+ }
+}
+
+Stats &BattleState::Order::GetStats(BattleState &b) const {
+ switch (by) {
+ case HERO:
+ return b.HeroAt(index).GetStats();
+ case CAPSULE:
+ return b.GetCapsule().GetStats();
+ case MONSTER:
+ return b.MonsterAt(index).GetStats();
+ default:
+ throw std::runtime_error("invalid case in BttleStats::Order::GetAttackChoice()");
+ }
+}
+
void BattleState::CalculateDamage(const Stats &attackerStats, TargetSelection &ts) const {
bool hitSome(false);
if (ts.TargetsMonsters()) {
void BattleState::ApplyDamage() {
if (attackCursor < 0) return;
- AttackChoice &ac(CurrentAttack().isMonster ? MonsterAt(CurrentAttack().index).GetAttackChoice() : HeroAt(CurrentAttack().index).GetAttackChoice());
+ AttackChoice &ac = CurrentAttack().GetAttackChoice(*this);
TargetSelection &ts(ac.Selection());
if (ts.TargetsMonsters()) {
for (int i(0); i < MaxMonsters(); ++i) {
}
AttackChoice &BattleState::CurrentAttackAttackChoice() {
- if (CurrentAttack().isMonster) {
- return MonsterAt(CurrentAttack().index).GetAttackChoice();
- } else {
- return HeroAt(CurrentAttack().index).GetAttackChoice();
- }
+ return CurrentAttack().GetAttackChoice(*this);
}
void BattleState::ClearAllAttacks() {
for (int i(0); i < MaxMonsters(); ++i) {
MonsterAt(i).GetAttackChoice() = AttackChoice(this);
}
+ capsule.GetAttackChoice() = AttackChoice(this);
attackOrder.clear();
}
}
-void BattleState::UpdateWorld(float deltaT) {
+void BattleState::UpdateWorld(Uint32 deltaT) {
}
}
}
+void BattleState::RenderCapsule(SDL_Surface *screen, const Vector<int> &offset) {
+ if (!capsule.Active() || capsule.Health() <= 0) return;
+ if (capsule.GetAnimation().Running()) {
+ capsule.GetAnimation().DrawCenter(screen, capsule.Position() + offset);
+ } else {
+ capsule.Sprite()->DrawCenter(screen, capsule.Position() + offset);
+ }
+}
+
void BattleState::RenderHeroTags(SDL_Surface *screen, const Vector<int> &offset) {
assert(screen);
int tagHeight(attackTypeMenu.Height());