diff options
author | Ben Boeckel <MathStuf@gmail.com> | 2008-08-28 14:52:45 +0000 |
---|---|---|
committer | Ben Boeckel <MathStuf@gmail.com> | 2008-08-28 14:52:45 +0000 |
commit | b99ffef4aa68dd5f0af64de9aec0f610e267d8cc (patch) | |
tree | d5f9e905c21c47f6a98688d400a99ce8f479e52b /pokebattle | |
parent | e4630543dc17d2a42c27d192518fe3f54e7888bc (diff) | |
download | sigen-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.cpp | 8 | ||||
-rw-r--r-- | pokebattle/Arena.h | 1 | ||||
-rw-r--r-- | pokebattle/TeamMember.cpp | 139 | ||||
-rw-r--r-- | pokebattle/TeamMember.h | 42 | ||||
-rw-r--r-- | pokebattle/TurnArena.cpp | 67 | ||||
-rw-r--r-- | pokebattle/TurnArena.h | 12 |
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*) |