summaryrefslogtreecommitdiffstats
path: root/pokebattle/TeamMember.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'pokebattle/TeamMember.cpp')
-rw-r--r--pokebattle/TeamMember.cpp286
1 files changed, 199 insertions, 87 deletions
diff --git a/pokebattle/TeamMember.cpp b/pokebattle/TeamMember.cpp
index 8b2d59c9..aed42f05 100644
--- a/pokebattle/TeamMember.cpp
+++ b/pokebattle/TeamMember.cpp
@@ -19,7 +19,7 @@
#include "TeamMember.h"
// Pokebattle includes
-#include "Team.h"
+#include "Containment.h"
// Pokemod includes
#include "../pokemod/Hat.h"
@@ -31,64 +31,51 @@
#include "../pokemod/SpeciesItem.h"
#include "../pokemod/SpeciesMove.h"
-Pokebattle::TeamMember::TeamMember(const int speciesId, const int level, const Team* team, const bool suppressItems) :
- m_team(team)
+// Qt includes
+#include <QtCore/QUuid>
+
+// KDE includes
+#include <kross/core/action.h>
+#include <kross/core/actioncollection.h>
+#include <kross/core/manager.h>
+
+// C includes
+#include <cmath>
+
+Pokebattle::TeamMember::TeamMember(const int speciesId, const QString& name, const int level, Containment* containment, const bool suppressItems) :
+ m_containment(containment)
{
- const Pokemod::Species* species = pokemod()->speciesById(speciesId);
setSpecies(speciesId);
+ const Pokemod::Species* species = pokemod()->speciesById(m_species);
+ if (name.isEmpty())
+ setName(species->name());
+ else
+ setName(name);
setLevel(level);
if (!suppressItems)
- {
- const Pokemod::Fraction itemChance = species->itemChance();
- Pokemod::Hat<int> itemHat;
- for (int i = 0; i < species->itemCount(); ++i)
- {
- const Pokemod::SpeciesItem* item = species->item(i);
- itemHat.add(item->item(), item->weight());
- }
- for (int i = 0; i < pokemod()->rules()->maxHeldItems(); ++i)
- {
- if (itemChance.poll())
- m_items.append(itemHat.pick());
- }
- }
- // TODO: choose moves
- Pokemod::Hat<int> abilityHat;
- for (int i = 0; i < species->abilityCount(); ++i)
- {
- const Pokemod::SpeciesAbility* ability = species->ability(i);
- abilityHat.add(ability->ability(), ability->weight());
- }
- for (int i = 0; i < pokemod()->rules()->maxAbilities(); ++i)
- {
- const int ability = abilityHat.pick();
- m_abilities.append(ability);
- abilityHat.setCount(ability, 0);
- }
- if (pokemod()->rules()->specialDVSplit())
- {
- for (int i = 0; i < Pokemod::ST_End_GSC; ++i)
- m_dv[i] = qrand() & 31;
- }
- else
- {
- for (int i = Pokemod::ST_No_HP_Start; i < Pokemod::ST_End_RBY; ++i)
- m_dv[i] = qrand() & 15;
- m_dv[Pokemod::ST_HP] = (m_dv[Pokemod::ST_Attack] << 3) + (m_dv[Pokemod::ST_Defense] << 2) + (m_dv[Pokemod::ST_Speed] << 1) + m_dv[Pokemod::ST_Special];
- }
+ initItems();
+ initAbilities();
+ initMoves();
+ initStats();
if (species->genderFactor() <= 1)
- setGender(species->genderFactor().poll());
+ m_gender = species->genderFactor().poll();
else
- setGender(-1);
+ m_gender = -1;
for (int i = 0; i < Pokemod::ST_End_GSC; ++i)
- {
m_statExp[i] = 0;
- m_effortValues[i] = 0;
+ if (m_containment->isMutable())
+ {
+ const Pokemod::Script script = species->evolution();
+ Kross::Action* evolution = new Kross::Action(Kross::Manager::self().actionCollection()->collection("evolutions"), QString("evolution-%1").arg(QUuid::createUuid().toString()));
+ evolution->setInterpreter(script.interpreter());
+ evolution->setCode(script.script().toUtf8());
+ evolution->addObject(this, "owner", Kross::ChildrenInterface::AutoConnectSignals);
+ evolution->trigger();
}
}
-Pokebattle::TeamMember::TeamMember(const Pokemod::MapTrainerTeamMember& teamMember, const Team* team) :
- m_team(team)
+Pokebattle::TeamMember::TeamMember(const Pokemod::MapTrainerTeamMember& teamMember, Containment* containment) :
+ m_containment(containment)
{
// TODO: grab information from the class
// TODO: fill in anything else
@@ -109,15 +96,38 @@ int Pokebattle::TeamMember::level() const
return m_level;
}
-int Pokebattle::TeamMember::stat(const int stat) const
+int Pokebattle::TeamMember::statValue(const int stat, const int exp) const
{
- return calcStat(stat);
-}
-
-int Pokebattle::TeamMember::effortValue(const int stat) const
-{
- Q_ASSERT(stat < (pokemod()->rules()->specialSplit() ? Pokemod::ST_End_RBY : Pokemod::ST_End_GSC));
- return m_effortValues[stat];
+ Q_ASSERT(stat < (pokemod()->rules()->specialSplit() ? Pokemod::ST_End_GSC : Pokemod::ST_End_RBY));
+ int statValue;
+ if (exp < 0)
+ statValue = m_statExp[stat];
+ else
+ statValue = exp;
+ if (!pokemod()->rules()->effortValuesAllowed() && statValue)
+ statValue = sqrt(statValue - 1) + 1;
+ statValue >>= 2;
+ statValue += pokemod()->speciesById(m_species)->baseStat(stat) << 1;
+ if (pokemod()->rules()->specialDVSplit())
+ {
+ if (stat == Pokemod::ST_SpecialDefense)
+ statValue += m_dv[Pokemod::ST_Special] << 1;
+ else
+ statValue += m_dv[stat] << 1;
+ }
+ else
+ statValue += m_dv[stat];
+ statValue *= m_level;
+ statValue /= 100;
+ if (stat == Pokemod::ST_HP)
+ statValue += 10 + m_level;
+ else
+ {
+ statValue += 5;
+ foreach (int natureId, m_natures)
+ statValue *= pokemod()->natureById(natureId)->stat(stat);
+ }
+ return statValue;
}
int Pokebattle::TeamMember::calcExp(int level) const
@@ -136,6 +146,7 @@ int Pokebattle::TeamMember::calcExp(int level) const
return cube * ((14 + level) / 50.0);
else if (level <= 100)
return cube * ((32 + (level / 2)) / 50.0);
+ // TODO: better way for further growth?
else if (level <= 102)
return cube * (23 + level) / 75;
else
@@ -157,16 +168,25 @@ int Pokebattle::TeamMember::calcExp(int level) const
return cube * (1.274 - (level / 3) / 50.0 - p[level % 3]);
else if (level <= 100)
return cube * ((160 - level) / 100.0);
+ // TODO: better way for further growth?
else
return 3 * cube / 5;
+ default:
+ break;
}
+ Q_ASSERT(false);
+ return -1;
}
-int Pokebattle::TeamMember::calcStat(const int stat, int exp) const
+bool Pokebattle::TeamMember::canLearnMove(const int move)
{
- // TODO: calculate stat
- // TODO: extra factor for HP
- // TODO: factor in natures
+ const Pokemod::Species* species = pokemod()->speciesById(m_species);
+ for (int i = 0; i < species->moveCount(); ++i)
+ {
+ if (move == species->move(i)->move())
+ return true;
+ }
+ return false;
}
void Pokebattle::TeamMember::boostLevels(const int levels)
@@ -178,6 +198,11 @@ void Pokebattle::TeamMember::boostLevels(const int levels)
}
}
+void Pokebattle::TeamMember::evolveInto(const int newSpecies)
+{
+ setSpecies(newSpecies);
+}
+
void Pokebattle::TeamMember::setName(const QString& name)
{
if (m_name != name)
@@ -228,18 +253,32 @@ void Pokebattle::TeamMember::giveLevelExp(const int exp)
void Pokebattle::TeamMember::giveStatExp(const int stat, const int exp)
{
- // TODO: ensure that the stat is valid
- const int currentStat = calcStat(stat);
- // TODO: make sure the new exp doesn't overflow the total exp
- // TODO: emit a signal if the stat was changed
-}
-
-void Pokebattle::TeamMember::giveEffort(const int stat, const int exp)
-{
- // TODO: ensure that the stat is valid
- const int currentEffort = m_effortValues[stat];
- // TODO: Make sure both the stat and total EV is not overflowed
- // TODO: emit a signal if it updated the stat
+ Q_ASSERT(stat < (pokemod()->rules()->specialSplit() ? Pokemod::ST_End_GSC : Pokemod::ST_End_RBY));
+ const int oldStat = statValue(stat);
+ int expToGive = exp;
+ if (pokemod()->rules()->effortValuesAllowed())
+ {
+ int totalEV = 0;
+ for (int i = 0; i < Pokemod::ST_End_GSC; ++i)
+ totalEV += m_statExp[i];
+ while (expToGive && (totalEV < pokemod()->rules()->maxTotalEV()) && (m_statExp[stat] < pokemod()->rules()->maxEVPerStat()))
+ {
+ --expToGive;
+ ++totalEV;
+ ++m_statExp[stat];
+ }
+ }
+ else
+ {
+ while (expToGive && (m_statExp[stat] < INT_MAX))
+ {
+ --expToGive;
+ ++m_statExp[stat];
+ }
+ }
+ const int newStat = statValue(stat);
+ if (oldStat != newStat)
+ emit(statChanged(stat, newStat));
}
void Pokebattle::TeamMember::takeItem(const int itemIndex)
@@ -254,10 +293,12 @@ void Pokebattle::TeamMember::takeItem(const int itemIndex)
void Pokebattle::TeamMember::giveItem(const int item)
{
- // TODO: make sure that more items can be carried
- // TODO: make sure its a valid item
- m_items.append(item);
- emit(itemGiven(item));
+ Q_ASSERT(pokemod()->itemIndex(item) != INT_MAX);
+ if (m_items.size() < pokemod()->rules()->maxHeldItems())
+ {
+ m_items.append(item);
+ emit(itemGiven(item));
+ }
}
void Pokebattle::TeamMember::forgetMove(const int moveIndex)
@@ -272,11 +313,12 @@ void Pokebattle::TeamMember::forgetMove(const int moveIndex)
void Pokebattle::TeamMember::teachMove(const int move)
{
- // TODO: make sure that more moves can be learned
- // TODO: make sure its a valid move
- // TODO: make sure the move can be learned
- m_moves.append(move);
- emit(moveLearned(move));
+ Q_ASSERT(pokemod()->moveIndex(move) != INT_MAX);
+ if ((m_moves.size() < pokemod()->rules()->maxMoves()) && canLearnMove(move))
+ {
+ m_moves.append(move);
+ emit(moveLearned(move));
+ }
}
const Pokemod::Pokemod* Pokebattle::TeamMember::pokemod() const
@@ -289,12 +331,7 @@ void Pokebattle::TeamMember::setSpecies(const int species)
{
Q_ASSERT(pokemod()->speciesIndex(species) != INT_MAX);
m_species = species;
-}
-
-void Pokebattle::TeamMember::setGender(const int gender)
-{
- Q_ASSERT((-1 <= gender) && (gender <= 1));
- m_gender = gender;
+ emit(speciesChanged(m_species));
}
void Pokebattle::TeamMember::setLevel(const int level)
@@ -303,3 +340,78 @@ void Pokebattle::TeamMember::setLevel(const int level)
m_level = level;
m_levelExp = calcExp();
}
+
+void Pokebattle::TeamMember::levelGrown()
+{
+ const Pokemod::Species* species = pokemod()->speciesById(m_species);
+ for (int i = 0; i < species->moveCount(); ++i)
+ {
+ const Pokemod::SpeciesMove* move = species->move(i);
+ if (move->level() == m_level)
+ teachMove(move->move());
+ }
+}
+
+void Pokebattle::TeamMember::initItems()
+{
+ const Pokemod::Species* species = pokemod()->speciesById(m_species);
+ Pokemod::Hat<int> itemHat;
+ m_items.clear();
+ for (int i = 0; i < species->itemCount(); ++i)
+ {
+ const Pokemod::SpeciesItem* item = species->item(i);
+ itemHat.add(item->item(), item->weight());
+ }
+ for (int i = 0; i < pokemod()->rules()->maxHeldItems(); ++i)
+ {
+ if (species->itemChance().poll())
+ m_items.append(itemHat.pick());
+ }
+}
+
+void Pokebattle::TeamMember::initAbilities()
+{
+ m_abilities.clear();
+ while (m_abilities.size())
+ m_abilities.append(newAbility());
+}
+
+void Pokebattle::TeamMember::initMoves()
+{
+ const Pokemod::Species* species = pokemod()->speciesById(m_species);
+ m_moves.clear();
+ for (int i = 0; (i < species->moveCount()) && (m_moves.size() < pokemod()->rules()->maxMoves()); ++i)
+ {
+ if ((species->move(i)->level() < m_level) && (0 <= species->move(i)->level()))
+ m_moves.append(species->move(i)->move());
+ }
+ Q_ASSERT(m_moves.size());
+}
+
+void Pokebattle::TeamMember::initStats()
+{
+ if (pokemod()->rules()->specialDVSplit())
+ {
+ for (int i = 0; i < Pokemod::ST_End_GSC; ++i)
+ m_dv[i] = qrand() & 31;
+ }
+ else
+ {
+ for (int i = Pokemod::ST_No_HP_Start; i < Pokemod::ST_End_RBY; ++i)
+ m_dv[i] = qrand() & 15;
+ m_dv[Pokemod::ST_HP] = (m_dv[Pokemod::ST_Attack] << 3) + (m_dv[Pokemod::ST_Defense] << 2) + (m_dv[Pokemod::ST_Speed] << 1) + m_dv[Pokemod::ST_Special];
+ }
+}
+
+int Pokebattle::TeamMember::newAbility()
+{
+ const Pokemod::Species* species = pokemod()->speciesById(m_species);
+ Pokemod::Hat<int> abilityHat;
+ for (int i = 0; i < species->abilityCount(); ++i)
+ {
+ const Pokemod::SpeciesAbility* ability = species->ability(i);
+ if (!m_abilities.contains(ability->ability()))
+ abilityHat.add(ability->ability(), ability->weight());
+ }
+ return abilityHat.pick();
+}