mirror of
https://github.com/mm201/pkmn-classic-framework.git
synced 2026-08-24 19:24:11 -05:00
Did some cleanup to the pokemon structure.
This commit is contained in:
@@ -65,5 +65,12 @@ namespace PkmnFoundations.Pokedex
|
||||
{
|
||||
get { return m_type_pair.Value; }
|
||||
}
|
||||
|
||||
public static LazyKeyValuePair<int, Move> CreatePair(Pokedex pokedex)
|
||||
{
|
||||
return new LazyKeyValuePair<int, Move>(
|
||||
k => k == 0 ? null : (pokedex == null ? null : pokedex.Moves(k)),
|
||||
v => v == null ? 0 : v.ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +86,9 @@ namespace PkmnFoundations.Pokedex
|
||||
|
||||
public static LazyKeyValuePair<int, Species> CreatePair(Pokedex pokedex)
|
||||
{
|
||||
// xxx: we need to return null when there's a KeyNotFoundException
|
||||
// since we want the Pokemon4/5 ctor to succeed regardless of how
|
||||
// broken the underlying data is.
|
||||
return new LazyKeyValuePair<int, Species>(
|
||||
k => k == 0 ? null : (pokedex == null ? null : pokedex.Species(k)),
|
||||
v => v == null ? 0 : v.NationalDex);
|
||||
|
||||
@@ -219,4 +219,15 @@ namespace PkmnFoundations.Structures
|
||||
Infected,
|
||||
Cured
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ShinyLeaves : byte
|
||||
{
|
||||
LeafA = 1,
|
||||
LeafB = 2,
|
||||
LeafC = 4,
|
||||
LeafD = 8,
|
||||
LeafE = 16,
|
||||
Crown = 32
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,27 +3,43 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using PkmnFoundations.Pokedex;
|
||||
using PkmnFoundations.Support;
|
||||
|
||||
namespace PkmnFoundations.Structures
|
||||
{
|
||||
public struct MoveSlot
|
||||
public class MoveSlot
|
||||
{
|
||||
public MoveSlot(Pokedex.Pokedex pokedex, int moveId, byte ppUps, byte remainingPp) : this()
|
||||
public MoveSlot(Pokedex.Pokedex pokedex, int moveId, byte ppUps, byte remainingPp)
|
||||
{
|
||||
m_pokedex = pokedex;
|
||||
Initialize();
|
||||
|
||||
MoveID = moveId;
|
||||
PPUps = ppUps;
|
||||
RemainingPP = remainingPp;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
m_move_pair = Move.CreatePair(m_pokedex);
|
||||
}
|
||||
|
||||
private Pokedex.Pokedex m_pokedex;
|
||||
|
||||
public int MoveID { get; set; }
|
||||
private LazyKeyValuePair<int, Move> m_move_pair;
|
||||
public int MoveID
|
||||
{
|
||||
get { return m_move_pair.Key; }
|
||||
set { m_move_pair.Key = value; }
|
||||
}
|
||||
public Move Move
|
||||
{
|
||||
get { return m_move_pair.Value; }
|
||||
set { m_move_pair.Value = value; }
|
||||
}
|
||||
|
||||
public byte PPUps { get; set; } // todo: validate range
|
||||
public byte RemainingPP { get; set; } // todo: validate range (against pokedex data and pp ups)
|
||||
|
||||
// todo: should have a MoveID/Move LazyKeyValuePair.
|
||||
public Move Move { get { return MoveID == 0 ? null : m_pokedex.Moves(MoveID); } }
|
||||
public int PP { get { return Move.PP * (5 + PPUps) / 5; } }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace PkmnFoundations.Structures
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
UnknownRibbons = new HashSet<int>();
|
||||
}
|
||||
|
||||
protected override void Load(BinaryReader reader)
|
||||
@@ -116,17 +117,15 @@ namespace PkmnFoundations.Structures
|
||||
|
||||
byte forme = block[24];
|
||||
FatefulEncounter = (forme & 0x01) != 0;
|
||||
Female = (forme & 0x02) != 0;
|
||||
Genderless = (forme & 0x04) != 0;
|
||||
m_female = (forme & 0x02) != 0;
|
||||
m_genderless = (forme & 0x04) != 0;
|
||||
FormID = (byte)(forme >> 3);
|
||||
|
||||
// todo: parse this in a meaningful way.
|
||||
ShinyLeaves = block[25];
|
||||
Unknown1 = BitConverter.ToUInt16(block, 26); // Probably unused?
|
||||
ShinyLeaves = (ShinyLeaves)block[25];
|
||||
Unknown1 = BitConverter.ToUInt16(block, 26);
|
||||
|
||||
// todo: doing trainer memos the right way is a pretty large task
|
||||
// involving new database work.
|
||||
TrainerMemoPlatinum = BitConverter.ToInt32(block, 28);
|
||||
EggLocationID_Plat = BitConverter.ToUInt16(block, 28);
|
||||
LocationID_Plat = BitConverter.ToUInt16(block, 30);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -136,7 +135,7 @@ namespace PkmnFoundations.Structures
|
||||
Unknown2 = block[22];
|
||||
Version = (Versions)block[23];
|
||||
ribbons3 = BitConverter.ToInt32(block, 24);
|
||||
Unknown3 = BitConverter.ToInt32(block, 28);
|
||||
Unknown3 = BitConverter.ToUInt32(block, 28);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -144,13 +143,14 @@ namespace PkmnFoundations.Structures
|
||||
|
||||
TrainerNameEncoded = new EncodedString4(block, 0, 16);
|
||||
|
||||
// todo: parse dates
|
||||
// todo: store as DateTime
|
||||
EggDate = new byte[3];
|
||||
Array.Copy(block, 16, EggDate, 0, 3);
|
||||
Date = new byte[3];
|
||||
Array.Copy(block, 19, Date, 0, 3);
|
||||
|
||||
TrainerMemo = BitConverter.ToInt32(block, 22);
|
||||
EggLocationID = BitConverter.ToUInt16(block, 22);
|
||||
LocationID = BitConverter.ToUInt16(block, 24);
|
||||
byte pokerusStatus = block[26];
|
||||
PokerusDaysLeft = (byte)(pokerusStatus & 0x0f);
|
||||
PokerusStrain = (byte)(pokerusStatus >> 4);
|
||||
@@ -158,7 +158,8 @@ namespace PkmnFoundations.Structures
|
||||
|
||||
byte encounter_level = block[28];
|
||||
EncounterLevel = (byte)(encounter_level & 0x7f);
|
||||
TrainerFemale = (encounter_level & 0x80) != 0;
|
||||
bool trainerFemale = (encounter_level & 0x80) != 0;
|
||||
TrainerGender = trainerFemale ? TrainerGenders.Female : TrainerGenders.Male;
|
||||
|
||||
EncounterType = block[29];
|
||||
PokeBallID_Hgss = block[30];
|
||||
@@ -195,29 +196,19 @@ namespace PkmnFoundations.Structures
|
||||
Array.Copy(block, 76, Seals, 0, 24);
|
||||
}
|
||||
|
||||
Ribbons1 = ribbons1;
|
||||
Ribbons2 = ribbons2;
|
||||
Ribbons3 = ribbons3;
|
||||
|
||||
// todo: Ribbons need to be tracked in the database and stored in a meaningful way.
|
||||
// pkmncf_pokedex_ribbons
|
||||
// id, value3, value4, value5, value6, Name_JA, etc, Description_JA, etc
|
||||
// value >> 3 --> array offset.
|
||||
// value & 0x07 --> bit position.
|
||||
|
||||
byte[] ribbons = new byte[12];
|
||||
Array.Copy(BitConverter.GetBytes(ribbons1), 0, ribbons, 0, 4);
|
||||
Array.Copy(BitConverter.GetBytes(ribbons2), 0, ribbons, 4, 4);
|
||||
Array.Copy(BitConverter.GetBytes(ribbons3), 0, ribbons, 8, 4);
|
||||
|
||||
Ribbons = new HashSet<Ribbon>();
|
||||
UnknownRibbons = new HashSet<int>();
|
||||
Ribbons.Clear();
|
||||
UnknownRibbons.Clear();
|
||||
|
||||
IDictionary<int, Ribbon> allRibbons = m_pokedex.Ribbons(Generations.Generation4);
|
||||
|
||||
for (int x = 0; x < 96; x++)
|
||||
{
|
||||
if (HasRibbon(ribbons, x))
|
||||
if (PokemonPartyBase.HasRibbon(ribbons, x))
|
||||
{
|
||||
if (allRibbons.ContainsKey(x))
|
||||
Ribbons.Add(allRibbons[x]);
|
||||
@@ -227,16 +218,9 @@ namespace PkmnFoundations.Structures
|
||||
}
|
||||
}
|
||||
|
||||
bool HasRibbon(byte[] ribbons, int value)
|
||||
{
|
||||
if (value >= 96 || value < 0) throw new ArgumentOutOfRangeException();
|
||||
int offset = value >> 3;
|
||||
byte mask = (byte)(1 << (value & 0x07));
|
||||
return (ribbons[offset] & mask) != 0;
|
||||
}
|
||||
|
||||
protected override void Save(BinaryWriter writer)
|
||||
{
|
||||
// todo: implement save
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -245,30 +229,27 @@ namespace PkmnFoundations.Structures
|
||||
get { return Generations.Generation4; }
|
||||
}
|
||||
|
||||
public bool Female { get; set; }
|
||||
public bool Genderless { get; set; }
|
||||
private bool m_female;
|
||||
private bool m_genderless;
|
||||
public override Genders Gender
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Genderless) return Genders.None;
|
||||
if (Female) return Genders.Female;
|
||||
if (m_genderless) return Genders.None;
|
||||
if (m_female) return Genders.Female;
|
||||
return Genders.Male;
|
||||
}
|
||||
set
|
||||
{
|
||||
Female = value == Genders.Female;
|
||||
Genderless = value == Genders.None;
|
||||
m_female = value == Genders.Female;
|
||||
m_genderless = value == Genders.None;
|
||||
}
|
||||
}
|
||||
|
||||
// todo: parse shiny leaves data
|
||||
public byte ShinyLeaves { get; set; }
|
||||
public ushort Unknown1 { get; set; }
|
||||
public ShinyLeaves ShinyLeaves { get; set; }
|
||||
public ushort Unknown1 { get; set; } // appears just after a flags region storing gender, forme, shiny leaves, etc.
|
||||
|
||||
// this will require some database work.
|
||||
public int TrainerMemoPlatinum { get; set; } // trainer memo for PtHGSS
|
||||
public EncodedString4 NicknameEncoded { get; set; }
|
||||
public EncodedString4 NicknameEncoded { get; set; } // public so trash bytes can be inspected/manipulated
|
||||
public override string Nickname
|
||||
{
|
||||
get
|
||||
@@ -282,8 +263,9 @@ namespace PkmnFoundations.Structures
|
||||
else NicknameEncoded.Text = value;
|
||||
}
|
||||
}
|
||||
public byte Unknown2 { get; set; }
|
||||
public int Unknown3 { get; set; }
|
||||
|
||||
public byte Unknown2 { get; set; } // appears just before Version
|
||||
public uint Unknown3 { get; set; } // appears just after the last ribbon block
|
||||
public EncodedString4 TrainerNameEncoded { get; set; }
|
||||
public override string TrainerName
|
||||
{
|
||||
@@ -298,40 +280,21 @@ namespace PkmnFoundations.Structures
|
||||
else TrainerNameEncoded.Text = value;
|
||||
}
|
||||
}
|
||||
// fixme: use DateTimes for these
|
||||
|
||||
// todo: Implement trainer memo structure
|
||||
public byte[] EggDate { get; set; } // 3 bytes
|
||||
public byte[] Date { get; set; } // 3 bytes
|
||||
public int TrainerMemo { get; set; }
|
||||
public ushort EggLocationID { get; set; }
|
||||
public ushort LocationID { get; set; }
|
||||
public ushort EggLocationID_Plat { get; set; }
|
||||
public ushort LocationID_Plat { get; set; }
|
||||
public byte EncounterLevel { get; set; }
|
||||
|
||||
private byte m_pokerus_days_left;
|
||||
public override byte PokerusDaysLeft
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_pokerus_days_left;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value > 15) throw new ArgumentOutOfRangeException();
|
||||
m_pokerus_days_left = value;
|
||||
}
|
||||
}
|
||||
// this is the notorious genIV encounter type flag, not used for much besides validation
|
||||
public byte EncounterType { get; set; }
|
||||
public byte Unknown4 { get; set; } // appears just after HGSS pokeball
|
||||
|
||||
private byte m_pokerus_strain;
|
||||
public override byte PokerusStrain
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_pokerus_strain;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value > 15) throw new ArgumentOutOfRangeException();
|
||||
m_pokerus_strain = value;
|
||||
}
|
||||
}
|
||||
|
||||
// todo: need list of values and map them onto items
|
||||
// todo: obtain complete list of Pokeball IDs in HGSS
|
||||
public byte PokeBallID { get; set; }
|
||||
public byte PokeBallID_Hgss { get; set; }
|
||||
|
||||
@@ -348,11 +311,7 @@ namespace PkmnFoundations.Structures
|
||||
set
|
||||
{
|
||||
if (m_pokeball == value) return;
|
||||
if (value == null)
|
||||
{
|
||||
m_pokeball = null;
|
||||
return;
|
||||
}
|
||||
if (value == null) throw new ArgumentNullException();
|
||||
|
||||
if (value.PokeballValue == null) throw new ArgumentException("Item is not a valid Pokeball.");
|
||||
if ((int)value.PokeballValue > 255 || (int)value.PokeballValue < 0)
|
||||
@@ -362,12 +321,15 @@ namespace PkmnFoundations.Structures
|
||||
bool is_hgss = IsHgss();
|
||||
bool is_hgss_pokeball = IsHgssPokeball(pokeballId);
|
||||
if (!is_hgss && is_hgss_pokeball) throw new NotSupportedException("Can't place an HGSS Pokeball on a DPPt Pokémon.");
|
||||
// xxx: we can probably allow an hgss pokeball on a dppt pokemon
|
||||
// although the structure won't be valid
|
||||
// todo: fact check how hgss responds in this situation.
|
||||
|
||||
// todo: fact check these two values:
|
||||
// 1. a pokemon in an HGSS ball has a DPPt value of 1
|
||||
// 1. a pokemon in an HGSS ball has a DPPt value of 4
|
||||
// 2. any pokemon from DPPt has an HGSS value of 0
|
||||
// (investigating pokemon in the system should be enough)
|
||||
PokeBallID = (byte)(is_hgss_pokeball ? 1 : pokeballId);
|
||||
PokeBallID = (byte)(is_hgss_pokeball ? 4 : pokeballId);
|
||||
PokeBallID_Hgss = (byte)(is_hgss ? pokeballId : 0);
|
||||
}
|
||||
}
|
||||
@@ -377,33 +339,14 @@ namespace PkmnFoundations.Structures
|
||||
return (Version == Versions.HeartGold || Version == Versions.SoulSilver);
|
||||
}
|
||||
|
||||
private bool IsHgssPokeball(int pokeballId)
|
||||
private static bool IsHgssPokeball(int pokeballId)
|
||||
{
|
||||
return pokeballId > 16;
|
||||
}
|
||||
|
||||
public byte EncounterLevel { get; set; }
|
||||
public bool TrainerFemale { get; set; }
|
||||
public override TrainerGenders TrainerGender
|
||||
{
|
||||
get
|
||||
{
|
||||
return TrainerFemale ? TrainerGenders.Female : TrainerGenders.Male;
|
||||
}
|
||||
set
|
||||
{
|
||||
TrainerFemale = value == TrainerGenders.Female;
|
||||
}
|
||||
}
|
||||
|
||||
// this is the notorious genIV encounter type flag, not used for much besides validation
|
||||
public byte EncounterType { get; set; }
|
||||
public byte Unknown4 { get; set; }
|
||||
|
||||
public int Ribbons1 { get; set; }
|
||||
public int Ribbons2 { get; set; }
|
||||
public int Ribbons3 { get; set; }
|
||||
public HashSet<Ribbon> Ribbons { get; private set; }
|
||||
/// <summary>
|
||||
/// This allows preservation of unknown ribbon flags when saving.
|
||||
/// </summary>
|
||||
public HashSet<int> UnknownRibbons { get; private set; }
|
||||
|
||||
// party-only stuff. (todo: put in derived class)
|
||||
@@ -414,7 +357,7 @@ namespace PkmnFoundations.Structures
|
||||
public byte CapsuleIndex { get; set; }
|
||||
public ushort HP { get; set; }
|
||||
//public IntStatValues Stats { get; set; } // cached stats (only refreshes per level on gen4)
|
||||
public byte[] Unknown7 { get; set; }
|
||||
public byte[] Unknown7 { get; set; } // 56 bytes
|
||||
public byte[] Seals { get; set; }
|
||||
|
||||
private IntStatValues m_stats;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -60,7 +61,6 @@ namespace PkmnFoundations.Structures
|
||||
{
|
||||
// changing species will cause the looked up Form to be
|
||||
// incorrect so null it out.
|
||||
// xxx: should really observer pattern this.
|
||||
m_species_pair.Key = value;
|
||||
m_form_pair.Invalidate();
|
||||
}
|
||||
@@ -79,12 +79,19 @@ namespace PkmnFoundations.Structures
|
||||
public byte FormID
|
||||
{
|
||||
get { return m_form_pair.Key; }
|
||||
set { m_form_pair.Key = value; }
|
||||
set
|
||||
{
|
||||
m_form_pair.Key = value;
|
||||
}
|
||||
}
|
||||
public Form Form
|
||||
{
|
||||
get { return m_form_pair.Value; }
|
||||
set { m_form_pair.Value = value; }
|
||||
set
|
||||
{
|
||||
SpeciesID = value.SpeciesID;
|
||||
m_form_pair.Value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Generations Generation { get; }
|
||||
@@ -113,16 +120,16 @@ namespace PkmnFoundations.Structures
|
||||
set { m_ability_pair.Value = value; }
|
||||
}
|
||||
|
||||
public MoveSlot[] Moves { get { return m_moves; } }
|
||||
public IList<MoveSlot> Moves { get { return m_moves; } }
|
||||
public uint TrainerID { get; set; }
|
||||
public uint Personality { get; set; }
|
||||
public Natures Nature { get { return (Natures)(Personality % 25u); } }
|
||||
public byte Level { get; set; }
|
||||
public byte Happiness { get; set; }
|
||||
public Languages Language { get; set; }
|
||||
public IvStatValues IVs { get; set; }
|
||||
public ByteStatValues EVs { get; set; }
|
||||
|
||||
public abstract byte Level { get; set; }
|
||||
public abstract Genders Gender { get; set; }
|
||||
public abstract String Nickname { get; set; }
|
||||
|
||||
@@ -131,12 +138,17 @@ namespace PkmnFoundations.Structures
|
||||
get
|
||||
{
|
||||
// Gen3/4/5 formula. Gen6 must override.
|
||||
uint step1 = Personality ^ TrainerID;
|
||||
int step2 = (int)((step1 >> 16) ^ (step1 & 0xffffu));
|
||||
return step2 >> 3 == 0;
|
||||
return ShinyTest(Personality, TrainerID, 3);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ShinyTest(uint personality, uint trainerId, int trimBits)
|
||||
{
|
||||
uint step1 = personality ^ trainerId;
|
||||
int step2 = (int)((step1 >> 16) ^ (step1 & 0xffffu));
|
||||
return step2 >> trimBits == 0;
|
||||
}
|
||||
|
||||
public Characteristic Characteristic
|
||||
{
|
||||
get
|
||||
@@ -200,6 +212,7 @@ namespace PkmnFoundations.Structures
|
||||
return result;
|
||||
}
|
||||
|
||||
#region Experience formulas
|
||||
public static int ExperienceAt(int level, GrowthRates gr)
|
||||
{
|
||||
if (level > 100 || level < 1) throw new ArgumentOutOfRangeException("level");
|
||||
@@ -222,7 +235,7 @@ namespace PkmnFoundations.Structures
|
||||
throw new ArgumentException("gr");
|
||||
}
|
||||
|
||||
public static int LevelAt(int experience, GrowthRates gr)
|
||||
public static byte LevelAt(int experience, GrowthRates gr)
|
||||
{
|
||||
if (experience < 0) throw new ArgumentOutOfRangeException("experience");
|
||||
|
||||
@@ -231,8 +244,8 @@ namespace PkmnFoundations.Structures
|
||||
|
||||
while (1 < 2)
|
||||
{
|
||||
if (maxExp <= experience) return maxLevel;
|
||||
if (minLevel + 1 >= maxLevel) return minLevel;
|
||||
if (maxExp <= experience) return (byte)maxLevel;
|
||||
if (minLevel + 1 >= maxLevel) return (byte)minLevel;
|
||||
|
||||
int midLevel = (minLevel + maxLevel) >> 1;
|
||||
int midExp = ExperienceAt(midLevel, gr);
|
||||
@@ -301,6 +314,7 @@ namespace PkmnFoundations.Structures
|
||||
else
|
||||
return cube * (level / 2 + 32) / 50;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
public struct Characteristic
|
||||
|
||||
@@ -17,15 +17,59 @@ namespace PkmnFoundations.Structures
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
Ribbons = new HashSet<Ribbon>();
|
||||
}
|
||||
|
||||
private int m_experience;
|
||||
public int Experience
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_experience;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (m_experience == value) return;
|
||||
m_experience = value;
|
||||
m_level = null;
|
||||
// xxx: if exp changes but level doesn't, this gets invalidated for no reason.
|
||||
// (really needs observable)
|
||||
m_stats = null;
|
||||
}
|
||||
}
|
||||
|
||||
private byte? m_level;
|
||||
public override byte Level
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_level == null)
|
||||
m_level = LevelAt(m_experience, Species.GrowthRate);
|
||||
return (byte)m_level;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (m_level == value) return;
|
||||
m_experience = ExperienceAt(value, Species.GrowthRate);
|
||||
m_level = value;
|
||||
m_stats = null;
|
||||
}
|
||||
}
|
||||
|
||||
// todo: link experience with level
|
||||
public int Experience { get; set; }
|
||||
public Markings Markings { get; set; }
|
||||
public ConditionValues ContestStats { get; set; }
|
||||
public bool IsEgg { get; set; }
|
||||
public bool HasNickname { get; set; } // this field decides whether or not its name gets reverted when it evolves.
|
||||
public bool FatefulEncounter { get; set; } // aka. obedience flag. A few pokemon, eg. Mew, are disobedient unless this is set.
|
||||
|
||||
/// <summary>
|
||||
/// this field decides whether or not its name gets reverted when it evolves.
|
||||
/// </summary>
|
||||
public bool HasNickname { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// aka. obedience flag. A few pokemon, eg. Mew, are disobedient unless this is set.
|
||||
/// </summary>
|
||||
public bool FatefulEncounter { get; set; }
|
||||
|
||||
public Versions Version { get; set; }
|
||||
|
||||
// todo: create database-driven TrainerMemo class
|
||||
@@ -33,30 +77,72 @@ namespace PkmnFoundations.Structures
|
||||
//public abstract TrainerMemo TrainerMemo { get; }
|
||||
|
||||
public abstract String TrainerName { get; set; }
|
||||
public abstract TrainerGenders TrainerGender { get; set; }
|
||||
|
||||
// todo: Add pokerus status (None, Infected, Cured) and pokerus days remaining
|
||||
//public abstract PokerusStatus PokerusStatus { get; set; }
|
||||
//public abstract int PokerusDaysLeft { get; set; }
|
||||
public TrainerGenders TrainerGender { get; set; }
|
||||
|
||||
public abstract Item Pokeball { get; set; }
|
||||
|
||||
// todo: implement ribbons store (see Pokemon4.Load comment)
|
||||
//public HashSet<Ribbon> Ribbons { get; }
|
||||
public HashSet<Ribbon> Ribbons { get; private set; }
|
||||
|
||||
public abstract IntStatValues Stats { get; }
|
||||
private IntStatValues m_stats = null;
|
||||
public virtual IntStatValues Stats
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_stats == null)
|
||||
{
|
||||
// todo: stat formula
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
return m_stats;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract byte PokerusDaysLeft { get; set; }
|
||||
public abstract byte PokerusStrain { get; set; }
|
||||
private byte m_pokerus_days_left = 0;
|
||||
public virtual byte PokerusDaysLeft
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_pokerus_days_left;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value > 15) throw new ArgumentOutOfRangeException();
|
||||
m_pokerus_days_left = value;
|
||||
}
|
||||
}
|
||||
|
||||
private byte m_pokerus_strain = 0;
|
||||
public virtual byte PokerusStrain
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_pokerus_strain;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value > 15) throw new ArgumentOutOfRangeException();
|
||||
m_pokerus_strain = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Pokerus Pokerus
|
||||
{
|
||||
get
|
||||
{
|
||||
// note: "strain 0" is invalid and will cause the pokemon to
|
||||
// lose pokerus entirely once its days left hits 0.
|
||||
if (PokerusDaysLeft > 0) return Pokerus.Infected;
|
||||
if (PokerusStrain > 0) return Pokerus.Cured;
|
||||
return Pokerus.None;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool HasRibbon(byte[] ribbons, int value)
|
||||
{
|
||||
if (value >= 96 || value < 0) throw new ArgumentOutOfRangeException();
|
||||
int offset = value >> 3;
|
||||
byte mask = (byte)(1 << (value & 0x07));
|
||||
return (ribbons[offset] & mask) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user