Peoplemon  0.1.0
Peoplemon 3 game source documentation
OwnedPeoplemon.cpp
Go to the documentation of this file.
2 
3 #include <BLIB/Util/Random.hpp>
5 #include <Core/Items/Item.hpp>
8 #include <Core/Properties.hpp>
9 #include <cmath>
10 
11 namespace core
12 {
13 namespace pplmn
14 {
15 namespace
16 {
17 float statusBonus(Ailment ail) {
18  switch (ail) {
19  case Ailment::Sleep:
20  case Ailment::Frozen:
21  return 2.f;
22  case Ailment::Annoyed:
24  case Ailment::Sticky:
25  return 1.5f;
26  default:
27  return 1.f;
28  }
29 }
30 } // namespace
31 
33 : _id(Id::Unknown)
34 , level(1)
35 , xp(0)
36 , hp(0)
37 , ailment(Ailment::None)
38 , item(item::Id::None)
39 , pendingEvolve(false) {}
40 
41 OwnedPeoplemon::OwnedPeoplemon(Id ppl, unsigned int l)
42 : OwnedPeoplemon() {
43  _id = ppl;
44  level = l;
45  ivs.randomize();
46  hp = currentStats().hp;
47 }
48 
49 bool OwnedPeoplemon::loadLegacyFile(const std::string& f) {
50  bl::serial::binary::InputFile input(
51  bl::util::FileUtil::joinPath(Properties::LegacyPeoplemonPath(), f));
52  if (!input.good()) return false;
53 
54  if (!input.read(customName)) return false;
55 
56  std::uint16_t u16;
57  if (!input.read<std::uint16_t>(u16)) return false;
58  _id = Peoplemon::cast(u16);
59  if (_id == Id::Unknown) {
60  BL_LOG_ERROR << "Bad peoplemon id " << u16 << " in " << f;
61  return false;
62  }
63 
64  if (!input.read<std::uint16_t>(u16)) return false;
65  level = u16;
66  if (!input.read<std::uint16_t>(u16)) return false;
67  xp = u16;
68  if (!input.read<std::uint16_t>(u16)) return false; // xp for level up, discard
69  if (!input.read<std::uint16_t>(u16)) return false;
70  hp = u16;
71 
72  std::uint8_t u8;
73  if (!input.read<std::uint8_t>(u8)) return false;
74  ailment = static_cast<Ailment>(u8);
75 
76  if (!input.read<std::uint16_t>(u16)) return false;
77  item = item::Item::cast(u16);
78  if (item == item::Id::None) {
79  BL_LOG_ERROR << "Bad item id " << u16 << " in " << f;
80  return false;
81  }
82 
83  for (int i = 0; i < 4; ++i) {
84  if (!input.read<std::uint16_t>(u16)) return false;
85  moves[i] = OwnedMove(Move::cast(u16));
86  if (!input.read<std::uint16_t>(u16)) return false; // pp, discard
87  }
88 
89  if (!input.read<std::uint16_t>(u16)) return false;
90  ivs.hp = u16;
91  if (!input.read<std::uint16_t>(u16)) return false;
92  ivs.atk = u16;
93  if (!input.read<std::uint16_t>(u16)) return false;
94  ivs.def = u16;
95  if (!input.read<std::uint16_t>(u16)) return false;
96  ivs.spatk = u16;
97  if (!input.read<std::uint16_t>(u16)) return false;
98  ivs.spdef = u16;
99  if (!input.read<std::uint16_t>(u16)) return false; // acc
100  if (!input.read<std::uint16_t>(u16)) return false; // evade
101  if (!input.read<std::uint16_t>(u16)) return false;
102  ivs.spd = u16;
103  if (!input.read<std::uint16_t>(u16)) return false; // crit
104 
105  if (!input.read<std::uint16_t>(u16)) return false;
106  evs.hp = u16;
107  if (!input.read<std::uint16_t>(u16)) return false;
108  evs.atk = u16;
109  if (!input.read<std::uint16_t>(u16)) return false;
110  evs.def = u16;
111  if (!input.read<std::uint16_t>(u16)) return false;
112  evs.spatk = u16;
113  if (!input.read<std::uint16_t>(u16)) return false;
114  evs.spdef = u16;
115  if (!input.read<std::uint16_t>(u16)) return false; // acc
116  if (!input.read<std::uint16_t>(u16)) return false; // evade
117  if (!input.read<std::uint16_t>(u16)) return false;
118  evs.spd = u16;
119  if (!input.read<std::uint16_t>(u16)) return false; // crit
120 
121  return true;
122 }
123 
124 Id OwnedPeoplemon::id() const { return _id; }
125 
127  const Id eid = evolvesInto();
128  if (eid != Id::Unknown) { _id = eid; }
129  else { BL_LOG_ERROR << "Tried to evolve " << _id << " but it has no valid evolution!"; }
130 }
131 
132 const std::string& OwnedPeoplemon::name() const {
133  return customName.empty() ? Peoplemon::name(_id) : customName;
134 }
135 
136 Type OwnedPeoplemon::type() const { return Peoplemon::type(_id); }
137 
138 void OwnedPeoplemon::setCustomName(const std::string& n) { customName = n; }
139 
140 unsigned int OwnedPeoplemon::currentLevel() const { return level; }
141 
142 unsigned int OwnedPeoplemon::evolveLevel() const { return Peoplemon::evolveLevel(_id); }
143 
145 
146 bool OwnedPeoplemon::pendingEvolution() const { return pendingEvolve; }
147 
148 bool& OwnedPeoplemon::pendingEvolution() { return pendingEvolve; }
149 
150 unsigned int OwnedPeoplemon::currentXP() const { return xp; }
151 
152 unsigned int OwnedPeoplemon::nextLevelXP() const { return Peoplemon::levelUpXp(_id, level); }
153 
154 unsigned int OwnedPeoplemon::awardXP(unsigned int award) {
155  if (level >= 100) {
156  xp = 0;
157  return 0;
158  }
159 
160  const unsigned int req = Peoplemon::levelUpXp(_id, level);
161  if (xp + award >= req) {
162  const unsigned int aa = req - xp;
163  xp = req;
164  return award - aa;
165  }
166  else {
167  xp += award;
168  return 0;
169  }
170 }
171 
173  return Stats::computeStats(Peoplemon::baseStats(_id), evs, ivs, level);
174 }
175 
176 const Stats& OwnedPeoplemon::currentEVs() const { return evs; }
177 
178 const Stats& OwnedPeoplemon::currentIVs() const { return ivs; }
179 
180 std::uint16_t& OwnedPeoplemon::currentHp() { return hp; }
181 
183  std::uint16_t udmg = dmg;
184  udmg = std::min(udmg, hp);
185  hp -= udmg;
186 }
187 
188 void OwnedPeoplemon::giveHealth(int p) { hp = std::min(hp + p, currentStats().hp); }
189 
190 std::uint16_t OwnedPeoplemon::currentHp() const { return hp; }
191 
192 void OwnedPeoplemon::awardEVs(const Stats& award) { evs.addEVs(award); }
193 
195 
197 
198 Ailment OwnedPeoplemon::currentAilment() const { return ailment; }
199 
200 item::Id OwnedPeoplemon::holdItem() const { return item; }
201 
203 
205  for (unsigned int i = 0; i < 4; ++i) {
206  if (moves[i].id == m) return true;
207  }
208  return false;
209 }
210 
211 const OwnedMove* OwnedPeoplemon::knownMoves() const { return moves; }
212 
214 
215 void OwnedPeoplemon::learnMove(MoveId m, unsigned int i) { moves[i] = OwnedMove(m); }
216 
218  for (int i = 0; i < 4; ++i) {
219  if (moves[i].id == MoveId::Unknown) {
220  moves[i] = OwnedMove(m);
221  return true;
222  }
223  }
224  return false;
225 }
226 
228  ailment = Ailment::None;
229  hp = currentStats().hp;
230 }
231 
233  // TODO - check hold item
234  return false;
235 }
236 
237 unsigned int OwnedPeoplemon::xpYield(bool trainer) const {
238  unsigned int xp = level;
239  if (trainer) { xp = xp * 3 / 2; }
240  xp *= Peoplemon::xpYieldMultiplier(_id);
241  return xp / 7;
242 }
243 
245  if (level < 100) {
246  level += 1;
247  xp = 0;
248  return Peoplemon::moveLearnedAtLevel(_id, level);
249  }
250  return MoveId::Unknown;
251 }
252 
254  for (int i = 0; i < 4; ++i) {
255  if (moves[i].id == id) return &moves[i];
256  }
257  return nullptr;
258 }
259 
260 bool OwnedPeoplemon::shakePasses(item::Id ball, int turnNumber, unsigned int opLevel) {
261  // https://bulbapedia.bulbagarden.net/wiki/Catch_rate#Capture_method_.28Generation_III-IV.29
262 
263 #ifdef PEOPLEMON_DEBUG
264  if (debug::DebugOverrides::get().alwaysCatch) return true;
265 #endif
266 
267  const float chp2 = static_cast<float>(currentHp()) * 2.f;
268  const float mhp3 = static_cast<float>(currentStats().hp) * 3.f;
269  const float levelRatio = static_cast<float>(opLevel) / static_cast<float>(currentLevel());
270  const float br = item::Item::getPeopleballRate(ball, _id, turnNumber, levelRatio);
271  const float ar = statusBonus(currentAilment());
272  const float r = Peoplemon::catchRate(_id);
273 
274  const int a = (mhp3 - chp2) * r * br / mhp3 * ar;
275  const int b = 1048560 / static_cast<int>(std::sqrt(static_cast<int>(std::sqrt(16711680 / a))));
276  const bool passed = a < 255 ? bl::util::Random::get<int>(0, 65535) < b : true;
277  BL_LOG_INFO << "ModifiedCatchRate=" << a << " | ShakeProbability=" << b << " | "
278  << (passed ? "Passed" : "Failed");
279  return passed;
280 }
281 
282 bool OwnedPeoplemon::canClone() const { return Peoplemon::canClone(_id); }
283 
284 } // namespace pplmn
285 } // namespace core
Id
Represents an item in its simplist form.
Definition: Id.hpp:24
Ailment
Represents an ailment that a Peoplemon can have.
Definition: Ailment.hpp:16
Type
Represents a type that a move or Peoplemon can be. Types may be combined.
Definition: Type.hpp:18
MoveId
The id of a move.
Definition: MoveId.hpp:16
SpecialAbility
Represents a special ability that a Peoplemon may have.
Id
The id of a peoplemon.
Definition: Id.hpp:16
Core classes and functionality for both the editor and game.
static float getPeopleballRate(Id ball, pplmn::Id ppl, int turnNumber, float levelRatio)
Returns the catch rate for the given peopleball.
Definition: Item.cpp:426
static Id cast(unsigned int id)
Helper function to cast a raw id to an item Id.
Definition: Item.cpp:31
static MoveId cast(unsigned int id)
Converts the given raw id to a move id, or Unknown if invalid.
Definition: Move.cpp:37
Represents a move owned by a peoplemon.
Definition: OwnedMove.hpp:17
Represents an instance of a peoplemon. Can be a wild peoplemon, trainer, or player peoplemon....
const Stats & currentEVs() const
Returns the current EVs of this peoplemon.
void evolve()
Changes this Peoplemon into it's evolved form if it has one.
Type type() const
Returns the type of the peoplemon.
bool loadLegacyFile(const std::string &file)
Loads the peoplemon from a legacy file.
bool & pendingEvolution()
Flag set by battle controller when this people is able to evolve after battle.
OwnedMove * findMove(MoveId id)
Returns the OwnedMove for the given move.
Ailment & currentAilment()
Access the current ailment of this peoplemon.
unsigned int awardXP(unsigned int xp)
Award XP to this peoplemon. A return of 0 indicates that all XP has been awarded. Non zero indicates ...
SpecialAbility ability() const
Returns the special ability of this peoplemon.
void applyDamage(int dmg)
Applies damage to the peoplemon. Ensures that the hp does not go negative.
unsigned int nextLevelXP() const
Returns the xp required to level up.
void setCustomName(const std::string &name)
Sets a custom name for this peoplemon.
bool canClone() const
Returns whether or not this peoplemon can be cloned.
std::uint16_t & currentHp()
Access the current HP.
MoveId levelUp()
Levels up the peoplemon.
OwnedPeoplemon()
Makes an empty peoplemon with id Unknown.
unsigned int currentLevel() const
Returns the current level of this peoplemon.
const Stats & currentIVs() const
Returns the current IVs of this peoplemon.
bool gainMove(MoveId move)
Attempts to learn the given move if there is an open slot.
void awardEVs(const Stats &evs)
Award EVs to this peoplemon.
Stats currentStats() const
Returns the computed stats for the peoplemon. Does not take into account changes during battle.
Id id() const
Returns the id of this peoplemon.
bool hasExpShare() const
Returns whether or not this peoplemon has an EXP share.
bool knowsMove(MoveId move) const
Returns whether or not this peoplemon knows the given move.
bool shakePasses(item::Id ball, int turnNumber, unsigned int opLevel)
Performs the check that a shake would occur with the given peopleball.
void learnMove(MoveId move, unsigned int i)
Teaches the peoplemon the given move, potentially replacing an existing one.
unsigned int currentXP() const
Returns the current XP of this peoplemon.
unsigned int xpYield(bool isTrainer) const
Returns the XP awarded by defeating this peoplemon.
unsigned int evolveLevel() const
Returns the level that this people can evolve at.
void giveHealth(int hp)
Restores HP and ensures it does not go over max HP.
Id evolvesInto() const
Returns the people that this evolves into. Returns Unknown if no evolution.
const OwnedMove * knownMoves() const
Returns the moves known by this Peoplemon.
item::Id & holdItem()
Access the current hold item of this peoplemon.
void heal()
Restores HP and removes ailments.
const std::string & name() const
Returns the name of this peoplemon, custom or defualt.
static bool canClone(Id id)
Returns whether or not the given Peoplemon may be cloned.
Definition: Peoplemon.cpp:242
static unsigned int evolveLevel(Id id)
Returns the minimum level that the given peoplemon will evolve at.
Definition: Peoplemon.cpp:166
static MoveId moveLearnedAtLevel(Id ppl, unsigned int level)
Returns the move the peoplemon learns at the given level, if any.
Definition: Peoplemon.cpp:157
static float catchRate(Id id)
Returns the base catch rate for the given peoplemon.
Definition: Peoplemon.cpp:237
static SpecialAbility specialAbility(Id id)
Returns the ability of the given peoplemon, if any.
Definition: Peoplemon.cpp:141
static int xpYieldMultiplier(Id id)
Returns the multiplier used when computing the XP award for defeating the given peoplemon.
Definition: Peoplemon.cpp:182
static Id evolvesInto(Id orig)
Returns what the given peoplemon will evolve into.
Definition: Peoplemon.cpp:171
static unsigned int levelUpXp(Id id, unsigned int level)
Returns the XP required to level up the given peoplemon.
Definition: Peoplemon.cpp:187
static const Stats & baseStats(Id id)
Returns the base stats for the given peoplemon.
Definition: Peoplemon.cpp:146
static const std::string & name(Id id)
Returns the name of the given Peoplemon.
Definition: Peoplemon.cpp:126
static Type type(Id id)
Returns the type of the Peoplemon.
Definition: Peoplemon.cpp:136
static Id cast(unsigned int id)
Casts an integer to a validated id. Returns Unknown if the id is invalid.
Definition: Peoplemon.cpp:112
Stats for Peoplemon. This struct is used for base stats, EVs, IVs, battle increases/decreases,...
Definition: Stats.hpp:19
void randomize()
Generates random IV stats.
Definition: Stats.cpp:27
static Stats computeStats(const Stats &base, const Stats &evs, const Stats &ivs, unsigned int level, const Stats &stages={})
Helper method to compute a Peoplemon's current stats.
Definition: Stats.cpp:49
void addEVs(const Stats &evs)
Adds the given EV points to this set of stats while obeying the constraints on EV values and sums.
Definition: Stats.cpp:31
static const std::string & LegacyPeoplemonPath()
Definition: Properties.cpp:551