summaryrefslogtreecommitdiffstats
path: root/pokebattle
diff options
context:
space:
mode:
authorBen Boeckel <MathStuf@gmail.com>2008-08-28 14:52:45 +0000
committerBen Boeckel <MathStuf@gmail.com>2008-08-28 14:52:45 +0000
commitb99ffef4aa68dd5f0af64de9aec0f610e267d8cc (patch)
treed5f9e905c21c47f6a98688d400a99ce8f479e52b /pokebattle
parente4630543dc17d2a42c27d192518fe3f54e7888bc (diff)
downloadsigen-b99ffef4aa68dd5f0af64de9aec0f610e267d8cc.tar.gz
sigen-b99ffef4aa68dd5f0af64de9aec0f610e267d8cc.tar.xz
sigen-b99ffef4aa68dd5f0af64de9aec0f610e267d8cc.zip
[FIX] Changed the providers URL to a better structure
[FIX] Arenas can now count how many players are still active [FIX] long long is now used for experience [FIX] Scripts initialized now git-svn-id: https://pokegen.svn.sourceforge.net/svnroot/pokegen/trunk@248 6ecfd1a5-f3ed-3746-8530-beee90d26b22
Diffstat (limited to 'pokebattle')
-rw-r--r--pokebattle/Arena.cpp8
-rw-r--r--pokebattle/Arena.h1
-rw-r--r--pokebattle/TeamMember.cpp139
-rw-r--r--pokebattle/TeamMember.h42
-rw-r--r--pokebattle/TurnArena.cpp67
-rw-r--r--pokebattle/TurnArena.h12
6 files changed, 219 insertions, 50 deletions
diff --git a/pokebattle/Arena.cpp b/pokebattle/Arena.cpp
index 7a96b71a..84c98dd9 100644
--- a/pokebattle/Arena.cpp
+++ b/pokebattle/Arena.cpp
@@ -66,6 +66,14 @@ QList<Pokebattle::TeamMember*> Pokebattle::Arena::active() const
return active;
}
+int Pokebattle::Arena::numActiveTeams() const
+{
+ int active = 0;
+ foreach (Player* player, m_players)
+ active += !player->active().isEmpty();
+ return active;
+}
+
void Pokebattle::Arena::registerScript(const QString& name, const Pokemod::Script& script)
{
Kross::Action* action = new Kross::Action(m_actions, name);
diff --git a/pokebattle/Arena.h b/pokebattle/Arena.h
index dc13632e..9a3a69e9 100644
--- a/pokebattle/Arena.h
+++ b/pokebattle/Arena.h
@@ -54,6 +54,7 @@ class POKEBATTLE_EXPORT Arena : public Pokescripting::Config
~Arena();
QList<TeamMember*> active() const;
+ int numActiveTeams() const;
Kross::Action* script(const QString& name);
signals:
diff --git a/pokebattle/TeamMember.cpp b/pokebattle/TeamMember.cpp
index c4470e48..84727cb7 100644
--- a/pokebattle/TeamMember.cpp
+++ b/pokebattle/TeamMember.cpp
@@ -19,6 +19,7 @@
#include "TeamMember.h"
// Pokebattle includes
+#include "Arena.h"
#include "Containment.h"
#include "Player.h"
@@ -26,9 +27,11 @@
#include "../pokescripting/AbilityWrapper.h"
#include "../pokescripting/ItemWrapper.h"
#include "../pokescripting/MapTrainerTeamMemberWrapper.h"
+#include "../pokescripting/MoveWrapper.h"
#include "../pokescripting/NatureWrapper.h"
#include "../pokescripting/PokemodWrapper.h"
#include "../pokescripting/RulesWrapper.h"
+#include "../pokescripting/StatusWrapper.h"
#include "../pokescripting/SpeciesWrapper.h"
#include "../pokescripting/SpeciesAbilityWrapper.h"
#include "../pokescripting/SpeciesItemWrapper.h"
@@ -48,6 +51,39 @@
// C includes
#include <cmath>
+// TODO: Current HP
+// TODO: Script cleanup (battle)
+
+int Pokebattle::actionPriority(const TeamMember* teamMember, const TeamMember::Action& action)
+{
+ int priority = INT_MAX;
+ switch (action.first)
+ {
+ case TeamMember::Attack:
+ priority = teamMember->pokemod()->move(action.second.first.toString())->priority();
+ break;
+ case TeamMember::Item:
+ priority = INT_MIN / 3;
+ break;
+ case TeamMember::Switch:
+ priority = INT_MIN / 2;
+ break;
+ case TeamMember::Run:
+ priority = INT_MIN;
+ break;
+ case TeamMember::Skip:
+ priority = INT_MAX - 2;
+ break;
+ case TeamMember::Timeout:
+ priority = INT_MAX;
+ break;
+ case TeamMember::Invalid:
+ priority = INT_MAX - 1;
+ break;
+ }
+ return priority;
+}
+
Pokebattle::TeamMember::TeamMember(const int speciesId, const QString& name, const int level, Containment* containment, const bool suppressItems) :
Pokescripting::Config(containment),
m_containment(containment),
@@ -81,6 +117,7 @@ Pokebattle::TeamMember::TeamMember(const int speciesId, const QString& name, con
evolution->addObject(this, "owner", Kross::ChildrenInterface::AutoConnectSignals);
evolution->trigger();
}
+ m_currentHp = statValue(Pokemod::ST_HP);
}
Pokebattle::TeamMember::TeamMember(Pokescripting::MapTrainerTeamMemberWrapper* teamMember, Containment* containment) :
@@ -93,12 +130,9 @@ Pokebattle::TeamMember::TeamMember(Pokescripting::MapTrainerTeamMemberWrapper* t
setName(m_species->name());
setLevel(teamMember->level());
m_items = teamMember->items();
- m_abilities = teamMember->abilities();
- initAbilities();
- m_moves = teamMember->moves();
- initMoves();
- m_natures = teamMember->natures();
- initNatures();
+ initAbilities(teamMember->abilities());
+ initMoves(teamMember->moves());
+ initNatures(teamMember->natures());
initStats();
if (m_species->genderFactor() <= 1)
m_gender = (m_species->genderFactor().poll() ? Male : Female);
@@ -106,6 +140,7 @@ Pokebattle::TeamMember::TeamMember(Pokescripting::MapTrainerTeamMemberWrapper* t
m_gender = Genderless;
for (int i = 0; i < Pokemod::ST_End_GSC; ++i)
m_statExp[i] = 0;
+ m_currentHp = statValue(Pokemod::ST_HP);
}
QUuid Pokebattle::TeamMember::id() const
@@ -120,6 +155,11 @@ QString Pokebattle::TeamMember::name() const
return m_name;
}
+long long Pokebattle::TeamMember::currentHp() const
+{
+ return m_currentHp;
+}
+
Pokescripting::SpeciesWrapper* Pokebattle::TeamMember::species() const
{
if (value("species").canConvert<Pokescripting::SpeciesWrapper*>())
@@ -139,10 +179,10 @@ Pokebattle::TeamMember::Gender Pokebattle::TeamMember::gender() const
return m_gender;
}
-int Pokebattle::TeamMember::levelExperience() const
+long long Pokebattle::TeamMember::levelExperience() const
{
- if (value("levelExperience").canConvert<int>())
- return value("levelExperience").toInt();
+ if (value("levelExperience").canConvert<long long>())
+ return value("levelExperience").toLongLong();
return m_levelExp;
}
@@ -153,11 +193,11 @@ int Pokebattle::TeamMember::baseStat(const Pokemod::Stat stat) const
return m_species->baseStat(stat);
}
-int Pokebattle::TeamMember::statExperience(const Pokemod::Stat stat) const
+long long Pokebattle::TeamMember::statExperience(const Pokemod::Stat stat) const
{
const QString valueName = QString("statExperience-%1").arg((pokemod()->rules()->specialSplit() ? Pokemod::StatGSCStr : Pokemod::StatRBYStr)[stat]);
- if (value(valueName).canConvert<int>())
- return value(valueName).toInt();
+ if (value(valueName).canConvert<long long>())
+ return value(valueName).toLongLong();
return m_statExp[stat];
}
@@ -173,9 +213,9 @@ int Pokebattle::TeamMember::dv(const Pokemod::Stat stat) const
return m_dv[stat];
}
-int Pokebattle::TeamMember::statValue(const Pokemod::Stat stat, const int exp) const
+long long Pokebattle::TeamMember::statValue(const Pokemod::Stat stat, const long long exp) const
{
- int statValue;
+ long long statValue;
if (exp < 0)
statValue = statExperience(stat);
else
@@ -207,12 +247,12 @@ int Pokebattle::TeamMember::statValue(const Pokemod::Stat stat, const int exp) c
return statValue;
}
-int Pokebattle::TeamMember::calcExp(int level) const
+long long Pokebattle::TeamMember::calcExp(int level) const
{
if (level < 0)
level = m_level;
- const int square = level * level;
- const int cube = square * level;
+ const long long square = level * level;
+ const long long cube = square * level;
switch (m_species->growth())
{
case Pokemod::Species::Fluctuating:
@@ -336,9 +376,10 @@ void Pokebattle::TeamMember::cureStatus(Pokescripting::StatusWrapper* status)
{
if (m_status.contains(status))
{
- m_status.removeAll(status);
-
- // TODO: clean up status script
+ QList<Kross::Action*> actions = m_status.values(status);
+ foreach (Kross::Action* action, actions)
+ delete action;
+ m_status.remove(status);
emit(statusCured(status));
}
}
@@ -348,8 +389,13 @@ void Pokebattle::TeamMember::giveStatus(Pokescripting::StatusWrapper* status)
Q_ASSERT(pokemod()->statusIndex(status) != INT_MAX);
if (!m_status.contains(status))
{
- m_status.append(status);
- // TODO: initialize status script
+ const Pokemod::Script script = status->worldScript();
+ Kross::Action* statusAction = new Kross::Action(Kross::Manager::self().actionCollection()->collection("status"), QString("status-%1").arg(QUuid::createUuid().toString()));
+ statusAction->setInterpreter(script.interpreter());
+ statusAction->setCode(script.script().toUtf8());
+ statusAction->addObject(this, "owner", Kross::ChildrenInterface::AutoConnectSignals);
+ statusAction->trigger();
+ m_status.insert(status, statusAction);
emit(statusInflicted(status));
}
}
@@ -453,8 +499,30 @@ Pokebattle::TeamMember::Action Pokebattle::TeamMember::requestAction() const
void Pokebattle::TeamMember::makeActive(Arena* arena)
{
- // TODO: initialize status scripts
- // TODO: initialize ability scripts
+ QList<Pokescripting::StatusWrapper*> statuses = m_status.uniqueKeys();
+ foreach (Pokescripting::StatusWrapper* status, statuses)
+ {
+ const Pokemod::Script script = status->battleScript();
+ Kross::Action* statusScript = new Kross::Action(Kross::Manager::self().actionCollection()->collection("status"), QString("status-%1").arg(QUuid::createUuid().toString()));
+ statusScript->setInterpreter(script.interpreter());
+ statusScript->setCode(script.script().toUtf8());
+ statusScript->addObject(arena, "arena", Kross::ChildrenInterface::AutoConnectSignals);
+ statusScript->addObject(this, "owner", Kross::ChildrenInterface::AutoConnectSignals);
+ statusScript->trigger();
+ m_statusBattleScripts.append(statusScript);
+ }
+ QList<Pokescripting::AbilityWrapper*> abilities = m_abilities.keys();
+ foreach (Pokescripting::AbilityWrapper* ability, abilities)
+ {
+ const Pokemod::Script script = ability->battleScript();
+ Kross::Action* abilityScript = new Kross::Action(Kross::Manager::self().actionCollection()->collection("ability"), QString("ability-%1").arg(QUuid::createUuid().toString()));
+ abilityScript->setInterpreter(script.interpreter());
+ abilityScript->setCode(script.script().toUtf8());
+ abilityScript->addObject(arena, "arena", Kross::ChildrenInterface::AutoConnectSignals);
+ abilityScript->addObject(this, "owner", Kross::ChildrenInterface::AutoConnectSignals);
+ abilityScript->trigger();
+ m_abilityBattleScripts.append(abilityScript);
+ }
}
void Pokebattle::TeamMember::writeBack()
@@ -496,6 +564,17 @@ void Pokebattle::TeamMember::makeConnections()
// TODO: make connections that are necessary (watching Config changes mainly)
}
+void Pokebattle::TeamMember::initAbility(Pokescripting::AbilityWrapper* ability)
+{
+ const Pokemod::Script script = ability->battleScript();
+ Kross::Action* abilityScript = new Kross::Action(Kross::Manager::self().actionCollection()->collection("ability"), QString("ability-%1").arg(QUuid::createUuid().toString()));
+ abilityScript->setInterpreter(script.interpreter());
+ abilityScript->setCode(script.script().toUtf8());
+ abilityScript->addObject(this, "owner", Kross::ChildrenInterface::AutoConnectSignals);
+ abilityScript->trigger();
+ m_abilities[ability] = abilityScript;
+}
+
void Pokebattle::TeamMember::initItems()
{
Pokemod::Hat<Pokescripting::ItemWrapper*> hat = m_species->itemHat();
@@ -506,19 +585,22 @@ void Pokebattle::TeamMember::initItems()
}
}
-void Pokebattle::TeamMember::initAbilities()
+void Pokebattle::TeamMember::initAbilities(const QList<Pokescripting::AbilityWrapper*>& initial)
{
+ foreach (Pokescripting::AbilityWrapper* ability, initial)
+ initAbility(ability);
Pokemod::Hat<Pokescripting::AbilityWrapper*> hat = m_species->abilityHat();
while (m_abilities.size() < pokemod()->rules()->maxAbilities())
{
Pokescripting::AbilityWrapper* ability = hat.takeAndClear();
if (!m_abilities.contains(ability))
- m_abilities.append(ability);
+ initAbility(ability);
}
}
-void Pokebattle::TeamMember::initMoves()
+void Pokebattle::TeamMember::initMoves(const QList<Pokescripting::MoveWrapper*>& initial)
{
+ m_moves = initial;
for (int i = 0; (i < m_species->moveCount()) && (m_moves.size() < pokemod()->rules()->maxMoves()); ++i)
{
Pokescripting::SpeciesMoveWrapper* move = m_species->move(i);
@@ -527,8 +609,9 @@ void Pokebattle::TeamMember::initMoves()
}
}
-void Pokebattle::TeamMember::initNatures()
+void Pokebattle::TeamMember::initNatures(const QList<Pokescripting::NatureWrapper*>& initial)
{
+ m_natures = initial;
Pokemod::Hat<Pokescripting::NatureWrapper*> hat = pokemod()->natureHat();
while (m_natures.size() < pokemod()->rules()->maxNatures())
{
diff --git a/pokebattle/TeamMember.h b/pokebattle/TeamMember.h
index 3192d876..db61571a 100644
--- a/pokebattle/TeamMember.h
+++ b/pokebattle/TeamMember.h
@@ -30,6 +30,8 @@
// Qt includes
#include <QtCore/QFuture>
#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QMultiMap>
#include <QtCore/QObject>
#include <QtCore/QPair>
#include <QtCore/QString>
@@ -47,6 +49,10 @@ class PokemodWrapper;
class SpeciesWrapper;
class StatusWrapper;
}
+namespace Kross
+{
+class Action;
+}
namespace Pokebattle
{
@@ -87,17 +93,20 @@ class POKEBATTLE_EXPORT TeamMember : public Pokescripting::Config
QUuid id() const;
QString name() const;
+ long long currentHp() const;
Pokescripting::SpeciesWrapper* species() const;
int level() const;
Gender gender() const;
- int levelExperience() const;
+ long long levelExperience() const;
int baseStat(const Pokemod::Stat stat) const;
- int statExperience(const Pokemod::Stat stat) const;
+ long long statExperience(const Pokemod::Stat stat) const;
int dv(const Pokemod::Stat stat) const;
- int statValue(const Pokemod::Stat stat, const int exp = -1) const;
- int calcExp(int level = -1) const;
+ long long statValue(const Pokemod::Stat stat, const long long exp = -1) const;
+ long long calcExp(int level = -1) const;
bool canLearnMove(Pokescripting::MoveWrapper* move) const;
+
+ Pokescripting::PokemodWrapper* pokemod() const;
signals:
void speciesChanged(Pokescripting::SpeciesWrapper* species);
@@ -152,33 +161,40 @@ class POKEBATTLE_EXPORT TeamMember : public Pokescripting::Config
private slots:
void levelGrown();
protected:
- Pokescripting::PokemodWrapper* pokemod() const;
-
Containment* m_containment;
const QUuid m_id;
QString m_name;
+ long long m_currentHp;
Pokescripting::SpeciesWrapper* m_species;
Gender m_gender;
- int m_levelExp;
+ long long m_levelExp;
int m_level;
- int m_statExp[Pokemod::ST_End_GSC];
+ long long m_statExp[Pokemod::ST_End_GSC];
int m_dv[Pokemod::ST_End_GSC];
- QList<Pokescripting::StatusWrapper*> m_status;
- QList<Pokescripting::AbilityWrapper*> m_abilities;
+ QMultiMap<Pokescripting::StatusWrapper*, Kross::Action*> m_status;
+ QMap<Pokescripting::AbilityWrapper*, Kross::Action*> m_abilities;
QList<Pokescripting::ItemWrapper*> m_items;
QList<Pokescripting::MoveWrapper*> m_moves;
QList<Pokescripting::NatureWrapper*> m_natures;
+
+ QList<Kross::Action*> m_abilityBattleScripts;
+ QList<Kross::Action*> m_statusBattleScripts;
private:
void makeConnections();
+ void initAbility(Pokescripting::AbilityWrapper* ability);
+
void initItems();
- void initAbilities();
- void initMoves();
- void initNatures();
+ void initAbilities(const QList<Pokescripting::AbilityWrapper*>& initial = QList<Pokescripting::AbilityWrapper*>());
+ void initMoves(const QList<Pokescripting::MoveWrapper*>& initial = QList<Pokescripting::MoveWrapper*>());
+ void initNatures(const QList<Pokescripting::NatureWrapper*>& initial = QList<Pokescripting::NatureWrapper*>());
void initStats();
};
+
+int actionPriority(const TeamMember* teamMember, const TeamMember::Action& action);
+
}
Q_DECLARE_METATYPE(Pokebattle::TeamMember*)
Q_DECLARE_METATYPE(Pokebattle::TeamMember::Gender)
diff --git a/pokebattle/TurnArena.cpp b/pokebattle/TurnArena.cpp
index 6c279153..bf0bece8 100644
--- a/pokebattle/TurnArena.cpp
+++ b/pokebattle/TurnArena.cpp
@@ -18,30 +18,79 @@
// Header include
#include "TurnArena.h"
+// Pokemod includes
+#include "../pokemod/Fraction.h"
+
// Qt includes
+#include <QtAlgorithms>
#include <QtCore/QtConcurrentMap>
+#include <QtCore/QFuture>
+#include <QtCore/QTimer>
+
+bool Pokebattle::sortActions(const TeamMember::RequestedAction& reqAction1, const TeamMember::RequestedAction& reqAction2)
+{
+ TeamMember::Action action1 = reqAction1.second.isFinished() ? reqAction1.second : TeamMember::Action(TeamMember::Timeout, TeamMember::ActionData());
+ TeamMember::Action action2 = reqAction2.second.isFinished() ? reqAction2.second : TeamMember::Action(TeamMember::Timeout, TeamMember::ActionData());
+ const int priority1 = actionPriority(reqAction1.first, action1);
+ const int priority2 = actionPriority(reqAction1.first, action2);
+ if (priority1 < priority2)
+ return true;
+ else if (priority1 == priority2)
+ {
+ const int speed1 = reqAction1.first->statValue(Pokemod::ST_Speed);
+ const int speed2 = reqAction2.first->statValue(Pokemod::ST_Speed);
+ if (speed1 < speed2)
+ return true;
+ else if (speed1 == speed2)
+ return Pokemod::Fraction(1, 2).poll();
+ }
+ return false;
+}
Pokebattle::TurnArena::TurnArena(QList<Player*> players, QObject* parent) :
- Arena(players, parent)
+ Arena(players, parent),
+ m_watcher(new QFutureWatcher<TeamMember::RequestedAction>(this)),
+ m_timer(new QTimer(this))
{
setupBattle();
+ m_timer->setSingleShot(true);
+ connect(m_timer, SIGNAL(timeout()), m_watcher, SLOT(cancel()));
}
void Pokebattle::TurnArena::processRound()
{
emit(roundAboutToStart());
emit(roundStart());
- QFuture<TeamMember::RequestedAction> actions = QtConcurrent::mapped(active(), &Pokebattle::requestDecision);
- // TODO: timeout here?
- // TODO: wait for all actions (unless timeout)
- // TODO: notify all attacks of what is going on (they can change priorities as needed)
- // TODO: determine the order of attacks
- // TODO: act out actions (ignoring those that affect fainting along the way)
+ QFuture<TeamMember::RequestedAction> reqActions = QtConcurrent::mapped(active(), &Pokebattle::requestDecision);
+ m_watcher->setFuture(reqActions);
+ m_timer->start(120000);
+ reqActions.waitForFinished();
+ m_timer->stop();
+ QList<TeamMember::RequestedAction> actions = reqActions.results();
+ qStableSort(actions.begin(), actions.end(), sortActions);
+ for (int i = 0; i < actions.size(); ++i)
+ {
+ for (int j = 0; j < i; ++j)
+ {
+
+ // TODO: Notify scripts of the moves before it and of its targets
+ }
+ }
+ // TODO: notify all attacks of what is going on in order (they can change priorities as needed)
+ qStableSort(actions.begin(), actions.end(), sortActions);
+ foreach (TeamMember::RequestedAction action, actions)
+ {
+ // TODO: Handle when the target switches or is knocked out
+ if (action.first->currentHp())
+ handleAction(action.first, action.second);
+ }
emit(roundAboutToEnd());
emit(roundEnd());
- // if (teamCount <= 1)
+ if (numActiveTeams() <= 1)
+ {
// TODO: End Round
- // else
+ }
+ else
processRound();
}
diff --git a/pokebattle/TurnArena.h b/pokebattle/TurnArena.h
index 066d762b..636ae501 100644
--- a/pokebattle/TurnArena.h
+++ b/pokebattle/TurnArena.h
@@ -22,6 +22,12 @@
#include "Arena.h"
#include "TeamMember.h"
+// Qt includes
+#include <QtCore/QFutureWatcher>
+
+// Forward declarations
+class QTimer;
+
namespace Pokebattle
{
class POKEBATTLE_EXPORT TurnArena : public Arena
@@ -40,7 +46,13 @@ class POKEBATTLE_EXPORT TurnArena : public Arena
void processRound();
protected:
void setupBattle();
+ private:
+ QFutureWatcher<TeamMember::RequestedAction>* m_watcher;
+ QTimer* m_timer;
};
+
+bool sortActions(const TeamMember::RequestedAction& reqAction1, const TeamMember::RequestedAction& reqAction2);
+
}
Q_DECLARE_METATYPE(Pokebattle::TurnArena*)