* The interface can now be displayed in **German** (thanks [peterpansexuell](http://www.smogon.com/forums/members/peterpansexuell.158307/) !)

* Updates can now be automatically checked for at startup (this is the default)
* **New features**:
 * Ribbon descriptions can now be modified (7 ribbons are concerned)
 * Pokémon can now be imported/exported from/to Base64 strings
 * On Colosseum, you can now change Rui's name
* Minor changes and bugfixes
This commit is contained in:
TuxSH 2015-10-03 22:52:04 +02:00
parent 3173566018
commit 58599addfc
66 changed files with 2931 additions and 648 deletions

View File

@ -1,9 +1,18 @@
###PkmGCToos v1.2:
* The interface can now be displayed in **German** (thanks [peterpansexuell](http://www.smogon.com/forums/members/peterpansexuell.158307/) !)
* Updates can now be automatically checked for at startup (this is the default)
* **New features**:
* Ribbon descriptions can now be modified (7 ribbons are concerned)
* Pokémon can now be imported/exported from/to Base64 strings
* On Colosseum, you can now change Rui's name
* Minor changes and bugfixes
###PkmGCTools v1.1.2:
Fixed a bug in XD: the map+script data was being wiped out.
Some refactoring in LibPkmGC.
###PkmGCTools v1.1.1:
Fixed a lot of critical bugs (affecting IVs, etc...). Money and Pokécoupons are now limited to 9,999,999. Bag items are limited to 99 again in Pokémon Colosseum Fixed a lot of critical bugs (affecting IVs, etc...)
Fixed a lot of critical bugs (affecting IVs, etc...). Pokedollars and PokéCoupons are now limited to 9,999,999. Bag items are limited to 99 again in Pokémon Colosseum Fixed a lot of critical bugs (affecting IVs, etc...)
(use the PC storage system to fix bag entries with more than 99 items).
To users of previous versions:

View File

@ -83,7 +83,7 @@ public:
ItemIndex heldItem;
u8 happiness;
u8 friendship;
u8 locationCaught; // u16 on Colo/XD
ItemIndex ballCaughtWith;
u8 levelMet;
@ -91,7 +91,7 @@ public:
PokemonString* OTName;
PokemonString* name;
u8 contestLuster;
u8 pkrsStatus;
u8 pokerusStatus;
PokemonMarkings markings;
u32 experience;
@ -127,7 +127,7 @@ public:
virtual void setInvalidPokemonFlag(bool flag) = 0;
struct PokemonComputedPartyData {
s8 pkrsDaysRemaining;
s8 pokerusDaysRemaining;
u16 currentHP;
u8 level;
PokemonStatus status;
@ -137,7 +137,7 @@ public:
PokemonComputedPartyData partyData;
void normalizePkrs(void);
void normalizepokerus(void);
void normalizeStatus(void);
void resetPartyData(void);

View File

@ -38,6 +38,7 @@ public:
DaycareData* clone(void) const;
DaycareData* create(void) const;
DaycareData(GC::DaycareData const& other);
DaycareData(XD::DaycareData const& other);
protected:
void loadFields(void);

View File

@ -32,8 +32,10 @@ namespace Colosseum {
0x780: bag
0xa80: u8 trainerGender
0xa84: u32 money
0xa88: u32 pkCoupons + copy
0xa84: u32 pokeDollars
0xa88: u32 pokeCoupons + copy
0xac2: Rui's name
*/
class LIBPKMGC_DECL PlayerData :
@ -43,9 +45,14 @@ public:
static const size_t size = 0xb18;
PlayerData(void);
PlayerData(PlayerData const& other);
PlayerData& operator=(GC::PlayerData const& other);
PlayerData& operator=(PlayerData const& other);
void swap(GC::PlayerData& other);
void swap(PlayerData& other);
PlayerData(const u8* inData);
GC::PokemonString* ruisName;
~PlayerData(void);
PlayerData* clone(void) const;
@ -54,8 +61,10 @@ public:
void save(void);
protected:
void loadFields(void);
void deleteFields(void);
private:
PlayerData(XD::PlayerData const& other);
void _deleteFields_extension(void);
};
}

View File

@ -60,12 +60,12 @@ namespace Colosseum {
0xbc : u8 contestLuster
0xbd : u8 specialRibbons[12]
0xc9 : u8 unimplentedRibbons (max. 15)
0xca : u8 pkrsStatus
0xca : u8 pokerusStatus
0xcb : u8 flags[3] : egg, special ability, invalid pkm
0xce : u8 GCUnk
0xcf : u8 marks
// shadow pkm data ?
0xd0: s8 pkrsRemainingDays
0xd0: s8 pokerusRemainingDays
0xd1--0xd7 : ? ?
0xd2: u16 unk2
0xd4: u16 unk1
@ -95,6 +95,8 @@ public:
void swap(Pokemon& other);
Pokemon& operator=(Pokemon const& other);
Pokemon(GC::Pokemon const& other);
Pokemon(Base::Pokemon const& other);
Pokemon(XD::Pokemon const& other);
Pokemon(GBA::Pokemon const& other);
Pokemon& operator=(GC::Pokemon const& other);

View File

@ -40,6 +40,8 @@ public:
void save(void);
PokemonBox(Base::PokemonBox const& other);
PokemonBox(GC::PokemonBox const& other);
PokemonBox(XD::PokemonBox const& other);
protected:
void loadFields(void);

View File

@ -42,6 +42,7 @@ public:
void save(void);
StrategyMemoData(GC::StrategyMemoData const& other);
StrategyMemoData(XD::StrategyMemoData const& other);
protected:
void loadFields(void);

View File

@ -38,8 +38,8 @@ public:
StrategyMemoEntry* clone(void) const;
StrategyMemoEntry* create(void) const;
bool isInfoPartial(void) const;
void setInfoCompleteness(bool partial);
bool isInfoIncomplete(void) const;
void setInfoCompleteness(bool incomplete);
};
}

View File

@ -38,6 +38,7 @@ public:
TrainerData* clone(void) const;
TrainerData* create(void) const;
TrainerData(GC::TrainerData const& other);
TrainerData(XD::TrainerData const& other);
protected:
void loadFields(void);

View File

@ -22,7 +22,7 @@
#include <boost/config/warning_disable.hpp>
#include <boost/config.hpp>
#define LIBPKMGC_VERSION 1001002
#define LIBPKMGC_VERSION 1002000
#define LIBPKMGC_VERSION_MAJOR ((LIBPKMGC_VERSION / 1000000) % 1000)
#define LIBPKMGC_VERSION_MINOR ((LIBPKMGC_VERSION / 1000) % 1000)
#define LIBPKMGC_VERSION_BUILD (LIBPKMGC_VERSION % 1000)

View File

@ -82,7 +82,7 @@ fromArrayOfIntegers<type*, u8*>(BUFFER_NAME+off, ar##_tmp, ar##_tmp+sz)
#define SV_ARRAY_E(type,ar,sz,off,etype) fromArrayOfEnumIntegers<type,etype*, u8*>(BUFFER_NAME+off, ar, ar+sz)
#define SV_ARRAY_E_MAX(type,ar,sz,off,etype,mx) for(size_t i__ = 0; i__ < sz; ++i__) ar[i__] = ((u32)ar[i__] > (u32)mx) ? (etype)0 : ar[i__];\
fromArrayOfEnumIntegers<type,etype*, u8*>(BUFFER_NAME+off, ar, ar+sz)
#define SV_ARRAY_B(type,ar,sz,off) toArrayOfBoolIntegers<type, bool*, u8*>(BUFFER_NAME+off, ar, ar+sz)
#define SV_ARRAY_B(type,ar,sz,off) fromArrayOfBoolIntegers<type, bool*, u8*>(BUFFER_NAME+off, ar, ar+sz)
#define SV_BIT_ARRAY2(type, ar, sz, off, st) type ar##_tmp; LD_FIELD(type, ar##_tmp, off); ar##_tmp &= ~(((1U << sz) - 1) << (8*sizeof(type) - 1 - st - sz));\
for(int i__ = 0; i__ < sz; ++i__) ar##_tmp |= ((ar[i__]) ? 1U : 0U) << (8*sizeof(type) - 1 - st - i__); SV_FIELD(type, ar##_tmp, off);
#define SV_BIT_ARRAY(type, ar, sz, off) SV_BIT_ARRAY2(type,ar,sz,off,0)
@ -112,25 +112,49 @@ for(int i__ = 0; i__ < sz; ++i__) ar##_tmp |= ((ar[i__]) ? 1U : 0U) << (8*sizeof
#define CL_ARRAY(fld, sz) for(size_t i__1234 = 0; i__1234 < sz; ++i__1234) CL(fld[i__1234]);
#define LIBPKMGC_GEN_CONVERTER_CTOR2(cls, flgs) \
Colosseum::cls::cls(XD::cls const& other) : GC::cls(Colosseum::cls::size){\
namespace Colosseum {\
cls::cls(XD::cls const& other) : GC::cls(cls::size){\
initWithEmptyData(flgs);\
GC::cls::operator=(other);\
}\
XD::cls::cls(Colosseum::cls const& other) : GC::cls(XD::cls::size){\
cls::cls(GC::cls const& other) : GC::cls(cls::size) {\
initWithEmptyData(flgs); \
GC::cls::operator=(other); \
}\
}\
namespace XD {\
cls::cls(Colosseum::cls const& other) : GC::cls(cls::size){\
initWithEmptyData(flgs);\
GC::cls::operator=(other);\
}\
cls::cls(GC::cls const& other) : GC::cls(cls::size) {\
initWithEmptyData(flgs); \
GC::cls::operator=(other); \
}\
}
#define LIBPKMGC_GEN_CONVERTER_CTOR(cls) LIBPKMGC_GEN_CONVERTER_CTOR2(cls, 0)
#define LIBPKMGC_GEN_CONVERTER_CTOR_W_GBA(cls) LIBPKMGC_GEN_CONVERTER_CTOR(cls)\
XD::cls::cls(GBA::cls const& other) : GC::cls(XD::cls::size){\
namespace XD {\
cls::cls(GBA::cls const& other) : GC::cls(cls::size){\
initWithEmptyData(0);\
GC::cls::operator=(other);\
}\
Colosseum::cls::cls(GBA::cls const& other) : GC::cls(XD::cls::size){\
cls::cls(Base::cls const& other) : GC::cls(cls::size) {\
initWithEmptyData(0); \
GC::cls::operator=(other); \
}\
}\
namespace Colosseum {\
cls::cls(GBA::cls const& other) : GC::cls(cls::size){\
initWithEmptyData(0);\
GC::cls::operator=(other);\
}\
cls::cls(Base::cls const& other) : GC::cls(cls::size) {\
initWithEmptyData(0); \
GC::cls::operator=(other); \
}\
}
#define LIBPKMGC_GC_GEN_XD_VTF2(cls, flgs) \
@ -155,6 +179,29 @@ else {cls obj((XD::cls&)other); swap(obj); other.swap(obj);}\
#define LIBPKMGC_GC_GEN_XD_VTF(cls) LIBPKMGC_GC_GEN_XD_VTF2(cls,0)
#define LIBPKMGC_GC_GEN_COL_VTF(cls) LIBPKMGC_GC_GEN_COL_VTF2(cls, 0)
#define LIBPKMGC_GC_GEN_NON_CONVERTIBLE_XD_VTF(cls) \
cls& cls::operator=(GC::cls const& other){\
if(LIBPKMGC_IS_XD(cls,&other)) operator=((cls const&)other);\
else GC::cls::operator=(other);\
return *this;\
}\
void cls::swap(GC::cls & other){\
if(LIBPKMGC_IS_XD(cls,&other)) swap((cls&)other);\
else GC::cls::swap(other);\
}
#define LIBPKMGC_GC_GEN_NON_CONVERTIBLE_COL_VTF(cls) \
cls& cls::operator=(GC::cls const& other){\
if(LIBPKMGC_IS_COLOSSEUM(cls,&other)) operator=((cls const&)other);\
else GC::cls::operator=(other);\
return *this;\
}\
void cls::swap(GC::cls & other){\
if(LIBPKMGC_IS_COLOSSEUM(cls,&other)) swap((cls&)other);\
else GC::cls::swap(other);\
}
#endif
#ifndef BOOST_NO_SFINAE

View File

@ -57,6 +57,7 @@ public:
void swap(Base::Pokemon& other);
Pokemon& operator=(Base::Pokemon const& other);
Pokemon(GC::Pokemon const& other);
Pokemon(Base::Pokemon const& other);
void reload(const u8* data = NULL, u32 inFlags = 0);

View File

@ -40,11 +40,11 @@ public:
virtual ~GroupBattleRule(void);
GroupBattleRule& operator=(GroupBattleRule const& other);
virtual GroupBattleRule& operator=(GroupBattleRule const& other);
virtual GroupBattleRule* clone(void) const = 0;
virtual GroupBattleRule* create(void) const = 0;
void swap(GroupBattleRule& other);
virtual void swap(GroupBattleRule& other);
virtual void save(void);
u16 minLevel, maxLevel;

View File

@ -33,14 +33,14 @@ class LIBPKMGC_DECL PlayerData :
{
public:
PlayerData(size_t inSize, const u8* inData = NULL);
PlayerData& operator=(PlayerData const& other);
virtual PlayerData& operator=(PlayerData const& other);
virtual PlayerData* clone(void) const = 0;
virtual PlayerData* create(void) const = 0;
virtual ~PlayerData(void);
void swap(PlayerData& other);
virtual void swap(PlayerData& other);
virtual void save(void);
@ -48,8 +48,8 @@ public:
BagData* bag;
Gender trainerGender;
u32 money;
u32 pkCoupons;
u32 pokeDollars;
u32 pokeCoupons;
protected:
PlayerData(PlayerData const& other);

View File

@ -53,8 +53,8 @@ public:
bool isEmpty(void) const;
virtual bool isInfoPartial(void) const = 0;
virtual void setInfoCompleteness(bool partial) = 0;
virtual bool isInfoIncomplete(void) const = 0;
virtual void setInfoCompleteness(bool incomplete) = 0;
u16 flags;
PokemonSpeciesIndex species;

View File

@ -45,9 +45,9 @@ public:
virtual ~SaveSlot(void);
void swap(SaveSlot& other);
virtual void swap(SaveSlot& other);
SaveSlot& operator=(SaveSlot const& other);
virtual SaveSlot& operator=(SaveSlot const& other);
virtual SaveSlot* clone(void) const = 0;
virtual SaveSlot* create(void) const = 0;

View File

@ -38,6 +38,7 @@ public:
DaycareData* clone(void) const;
DaycareData* create(void) const;
DaycareData(GC::DaycareData const& other);
DaycareData(Colosseum::DaycareData const& other);
protected:
void loadFields(void);

View File

@ -36,6 +36,10 @@ public:
~GroupBattleRule();
GroupBattleRule& operator=(GC::GroupBattleRule const& other);
GroupBattleRule& operator=(GroupBattleRule const& other);
void swap(GC::GroupBattleRule& other);
void swap(GroupBattleRule& other);
GroupBattleRule* clone(void) const;
GroupBattleRule* create(void) const;

View File

@ -32,8 +32,8 @@ namespace XD {
0x4c8: bag
0x8e0: u8 trainerGender
0x8e4: u32 money
0x8e8: u32 pkCoupons + copy
0x8e4: u32 pokeDollars
0x8e8: u32 pokeCoupons + copy
*/
class LIBPKMGC_DECL PlayerData :

View File

@ -29,7 +29,7 @@ XD::Pokemon
0x00: u16 species (cf PokemonInfo.h)
0x03: u8 itemHeld (ItemInfo.h)
0x04: u16 currentHP
0x06: u16 happiness
0x06: u16 friendship
0x08: u16 locationCaught
// 0x09 -- 0xd :: ??
0x0a: u16 unk1
@ -39,9 +39,9 @@ XD::Pokemon
0x10: u8 OTGender (00 male 01 female 02 genderless=none)
0x11: u8 currentLevel
0x12: u8 Contest Luster
0x13: u8 pkrsStatus
0x13: u8 pokerusStatus
0x14: u8 marks (bitfield)
0x15: s8 pkrsRemainingDays
0x15: s8 pokerusRemainingDays
0x16: u16 status (3 psn, 4 psn (toxic ?), 5 par, 6 brn, 7 frzn, 8 slp)
0x17: s8 turnsOfBadPoison (max 15.)
0x18: s8 turnsOfSleepRemaining (max. 8)
@ -97,6 +97,8 @@ public:
void swap(Pokemon& other);
Pokemon& operator=(Pokemon const& other);
Pokemon(GC::Pokemon const& other);
Pokemon(Base::Pokemon const& other);
Pokemon(Colosseum::Pokemon const& other);
Pokemon(GBA::Pokemon const& other);
Pokemon& operator=(GC::Pokemon const& other);

View File

@ -40,6 +40,8 @@ public:
void save(void);
PokemonBox(Base::PokemonBox const& other);
PokemonBox(GC::PokemonBox const& other);
PokemonBox(Colosseum::PokemonBox const& other);
protected:
void loadFields(void);

View File

@ -44,6 +44,8 @@ public:
void save(void);
StrategyMemoData(Colosseum::StrategyMemoData const& other);
StrategyMemoData(GC::StrategyMemoData const& other);
protected:
void loadFields(void);

View File

@ -38,8 +38,8 @@ public:
StrategyMemoEntry* clone(void) const;
StrategyMemoEntry* create(void) const;
bool isInfoPartial(void) const;
void setInfoCompleteness(bool partial);
bool isInfoIncomplete(void) const;
void setInfoCompleteness(bool incomplete);
};
}

View File

@ -40,6 +40,7 @@ public:
TrainerData* clone(void) const;
TrainerData* create(void) const;
TrainerData(GC::TrainerData const& other);
TrainerData(Colosseum::TrainerData const& other);
protected:
void loadFields(void);

View File

@ -86,6 +86,9 @@ public:
void swap(SaveSlot& other);
SaveSlot& operator=(SaveSlot const& other);
void swap(GC::SaveEditing::SaveSlot& other);
SaveSlot& operator=(GC::SaveEditing::SaveSlot const& other);
void save(void);
bool checkChecksum(bool fix = false);

View File

@ -155,19 +155,19 @@ char Pokemon::getUnownForm(void) const {
return getUnownForm(PID);
}
void Pokemon::normalizePkrs(void) {
u8 st = pkrsStatus & 0xf, dr = pkrsStatus >> 4;
void Pokemon::normalizepokerus(void) {
u8 st = pokerusStatus & 0xf, dr = pokerusStatus >> 4;
if (st == 0) {
dr = 0;
partyData.pkrsDaysRemaining = -1;
partyData.pokerusDaysRemaining = -1;
}
else {
u8 mx = 1 + (st & 0x3);
dr = (dr > mx) ? mx : dr;
partyData.pkrsDaysRemaining = (partyData.pkrsDaysRemaining > mx) ? mx : partyData.pkrsDaysRemaining;
partyData.pokerusDaysRemaining = (partyData.pokerusDaysRemaining > mx) ? mx : partyData.pokerusDaysRemaining;
}
pkrsStatus = (dr << 4) | st;
pokerusStatus = (dr << 4) | st;
}
void Pokemon::normalizeStatus(void) {
@ -183,7 +183,7 @@ void Pokemon::resetPartyData(void) {
updateLevelFromExp();
partyData.status = NoStatus;
partyData.currentHP = partyData.stats[0];
partyData.pkrsDaysRemaining = ((pkrsStatus & 0xf0) != 0) ? pkrsStatus & 0xf : -1;
partyData.pokerusDaysRemaining = ((pokerusStatus & 0xf0) != 0) ? pokerusStatus & 0xf : -1;
}
Pokemon::Pokemon(Pokemon const & other) : Base::DataStruct(other), OTName(NULL), name(NULL){
copyNonVirtual(other);
@ -211,7 +211,7 @@ void Pokemon::swap(Pokemon& other) {
SW(species);
SW(heldItem);
SW(happiness);
SW(friendship);
SW(locationCaught);
SW(ballCaughtWith);
SW(levelMet);
@ -231,7 +231,7 @@ void Pokemon::swap(Pokemon& other) {
other.name->fromUTF8(s1.c_str());
}
SW(contestLuster);
SW(pkrsStatus);
SW(pokerusStatus);
SW(markings);
SW(experience);
@ -273,13 +273,13 @@ void Pokemon::copyNonVirtual(Pokemon const& other) {
CP(species);
CP(heldItem);
CP(happiness);
CP(friendship);
CP(locationCaught);
CP(ballCaughtWith);
CP(levelMet);
CP(OTGender);
CP(contestLuster);
CP(pkrsStatus);
CP(pokerusStatus);
CP(markings);
CP(experience);

View File

@ -17,7 +17,7 @@
*/
#include <LibPkmGC/Base/PokemonBox.h>
#include <string>
namespace LibPkmGC {
namespace Base {
@ -42,7 +42,12 @@ PokemonBox::~PokemonBox(void) {
void PokemonBox::swap(PokemonBox& other) {
DataStruct::swap(other);
SW(name);
if(name->isGBA() == other.name->isGBA()) SW(name);
else {
std::string s(name->toUTF8());
name->fromUTF8(other.name->toUTF8());
other.name->fromUTF8(s.c_str());
}
for (size_t i = 0; i < 30; ++i) pkm[i]->swap(*other.pkm[i]);
}
@ -51,7 +56,7 @@ PokemonBox& PokemonBox::operator=(PokemonBox const& other) {
if (this != &other) {
PokemonBox::deleteFields();
for (size_t i = 0; i < 30; ++i) *pkm[i] = *(other.pkm[i]);
CL(name);
*name = *(other.name);
}
return *this;
}

View File

@ -29,9 +29,36 @@ PlayerData::PlayerData(const u8* inData) : GC::PlayerData(0xb18, inData) {
load();
}
PlayerData::PlayerData(PlayerData const& other) : GC::PlayerData(other) {}
PlayerData::PlayerData(PlayerData const& other) : GC::PlayerData(other) {
CL(ruisName);
}
PlayerData& PlayerData::operator=(PlayerData const& other) {
if (this != &other) {
GC::PlayerData::operator=(other);
CL(ruisName);
}
return *this;
}
void PlayerData::swap(PlayerData & other) {
GC::PlayerData::swap(other);
SW(ruisName);
}
LIBPKMGC_GC_GEN_NON_CONVERTIBLE_COL_VTF(PlayerData)
void PlayerData::_deleteFields_extension(void) {
delete ruisName;
}
void PlayerData::deleteFields(void) {
GC::PlayerData::deleteFields();
_deleteFields_extension();
}
PlayerData::~PlayerData(void){
_deleteFields_extension();
}
PlayerData* PlayerData::clone(void) const {
@ -47,8 +74,10 @@ void PlayerData::loadFields(void) {
LD_FIELD_E(u8, trainerGender, 0xa80, Gender);
if (trainerGender > Female) trainerGender = Male;
LD_FIELD_MAX(u32, money, 0xa84, 9999999);
LD_FIELD_MAX(u32, pkCoupons, 0xa88, 9999999);
LD_FIELD_MAX(u32, pokeDollars, 0xa84, 9999999);
LD_FIELD_MAX(u32, pokeCoupons, 0xa88, 9999999);
ruisName = new GC::PokemonString(data + 0xac2, 10);
LD_SUBSTRUCTURE(BagData, bag, 0x780);
}
@ -57,9 +86,10 @@ void PlayerData::save(void) {
GC::PlayerData::save();
if (trainerGender > Female) trainerGender = Male;
SV_FIELD_E(u8, trainerGender, 0xa80, Gender);
SV_FIELD_MAX(u32, money, 0xa84, 9999999);
SV_FIELD_MAX(u32, pkCoupons, 0xa88, 9999999);
SV_FIELD(u32, pkCoupons, 0xa8c);
SV_FIELD_MAX(u32, pokeDollars, 0xa84, 9999999);
SV_FIELD_MAX(u32, pokeCoupons, 0xa88, 9999999);
SV_FIELD(u32, pokeCoupons, 0xa8c);
ruisName->save(data + 0xac2, 10);
SV_SUBSTRUCTURE(BagData, bag, 0x780);
}

View File

@ -85,7 +85,7 @@ void Pokemon::loadFields(void) {
LD_ARRAY(u16, IVs_tmp, 6, 0xa4);
for (size_t i = 0; i < 6; ++i) IVs[i] = (u8)((IVs_tmp[i] > 31) ? 31 : IVs_tmp[i]);
LD_FIELD_CONV(u16, happiness, 0xb0, u8);
LD_FIELD_CONV(u16, friendship, 0xb0, u8);
LD_ARRAY(u8, contestStats, 5, 0xb2);
LD_ARRAY_E_MAX(u8, contestAchievements, 5, 0xb7, ContestAchievementLevel, MasterContestWon);
@ -94,11 +94,11 @@ void Pokemon::loadFields(void) {
LD_ARRAY_B(u8, specialRibbons, 12, 0xbd);
LD_FIELD_MAX(u8, unimplementedRibbons, 0xc9, 15);
LD_FIELD(u8, pkrsStatus, 0xca);
LD_FIELD(u8, pokerusStatus, 0xca);
LD_ARRAY_B(u8, pkmFlags, 3, 0xcb);
LD_FIELD(u8, GCUnk, 0xce);
LD_FIELD(u8, marksTmp, 0xcf);
LD_FIELD_MAX(s8, partyData.pkrsDaysRemaining, 0xd0, 4);
LD_FIELD_MAX(s8, partyData.pokerusDaysRemaining, 0xd0, 4);
LD_FIELD(u16, unk2, 0xd2);
LD_FIELD(u16, unk1, 0xd4);
LD_FIELD(u16, shadowPkmID, 0xd8);
@ -110,12 +110,12 @@ void Pokemon::loadFields(void) {
moves[i].load(data + 0x78 + 4 * i);
pkmFlags[LIBPKMGC_GC_SECOND_ABILITY_FLAG] = isSecondAbilityDefined() && pkmFlags[LIBPKMGC_GC_SECOND_ABILITY_FLAG];
normalizePkrs();
normalizepokerus();
normalizeStatus();
}
void Pokemon::save(void) {
normalizePkrs();
normalizepokerus();
normalizeStatus();
pkmFlags[LIBPKMGC_GC_SECOND_ABILITY_FLAG] = isSecondAbilityDefined() && pkmFlags[LIBPKMGC_GC_SECOND_ABILITY_FLAG];
@ -154,7 +154,7 @@ void Pokemon::save(void) {
}
SV_ARRAY(u16, IVs_tmp, 6, 0xa4);
SV_FIELD(u16, (u16)happiness, 0xb0);
SV_FIELD(u16, (u16)friendship, 0xb0);
SV_ARRAY(u8, contestStats, 5, 0xb2);
SV_ARRAY_E(u8, contestAchievements, 5, 0xb7, ContestAchievementLevel);
SV_FIELD(u8, contestLuster, 0xbc);
@ -163,11 +163,11 @@ void Pokemon::save(void) {
SV_FIELD_MAX(u8, unimplementedRibbons, 0xc9, 15);
SV_FIELD(u8, pkrsStatus, 0xca);
SV_FIELD(u8, pokerusStatus, 0xca);
SV_ARRAY_B(u8, pkmFlags, 3, 0xcb);
SV_FIELD_MAX(u8, GCUnk, 0xce, 31);
SV_FIELD(u8, markings.save(), 0xcf);
SV_FIELD_MAX(s8, partyData.pkrsDaysRemaining, 0xd0, 4);
SV_FIELD_MAX(s8, partyData.pokerusDaysRemaining, 0xd0, 4);
SV_FIELD(u16, unk2, 0xd2);
SV_FIELD(u16, unk1, 0xd4);
SV_FIELD(u16, shadowPkmID, 0xd8);

View File

@ -45,7 +45,10 @@ PokemonBox* PokemonBox::create(void) const {
return new PokemonBox;
}
PokemonBox::PokemonBox(Base::PokemonBox const& other) : GC::PokemonBox(0x24a4) {
initWithEmptyData();
Base::PokemonBox::operator=(other);
}
void PokemonBox::loadFields(void) {
GC::PokemonBox::loadFields();

View File

@ -44,12 +44,12 @@ StrategyMemoEntry* StrategyMemoEntry::create(void) const {
return new StrategyMemoEntry;
}
bool StrategyMemoEntry::isInfoPartial(void) const {
bool StrategyMemoEntry::isInfoIncomplete(void) const {
return (flags == 2);
}
void StrategyMemoEntry::setInfoCompleteness(bool partial) {
flags = (partial) ? 2 : 0;
void StrategyMemoEntry::setInfoCompleteness(bool incomplete) {
flags = (incomplete) ? 2 : 0;
}

View File

@ -258,10 +258,8 @@ void SaveSlot::loadFields(void) {
LD_IMPLEMENTED_SUBSTRUCTURE(MailboxData, mailbox);
LD_IMPLEMENTED_SUBSTRUCTURE(DaycareData, daycare);
LD_IMPLEMENTED_SUBSTRUCTURE(StrategyMemoData, strategyMemo);
//offset += 0x523c;
offset = 0xe3e8;
LD_IMPLEMENTED_SUBSTRUCTURE(BattleModeData, battleMode);
//offset += 0x1448;
offset = 0x1c45c;
LD_IMPLEMENTED_SUBSTRUCTURE(RibbonDescriptionsData, ribbonDescriptions);
// unknown substructures following
@ -285,17 +283,15 @@ void SaveSlot::save(void) {
SV_IMPLEMENTED_SUBSTRUCTURE(MailboxData, mailbox);
SV_IMPLEMENTED_SUBSTRUCTURE(DaycareData, daycare);
SV_IMPLEMENTED_SUBSTRUCTURE(StrategyMemoData, strategyMemo);
//offset += 0x523c;
offset = 0xe3e8;
SV_IMPLEMENTED_SUBSTRUCTURE(BattleModeData, battleMode);
//offset += 0x1448;
offset = 0x1c45c;
SV_IMPLEMENTED_SUBSTRUCTURE(RibbonDescriptionsData, ribbonDescriptions);
// unknown substructures following
checkBothChecksums(true, true); // update checksums
offset = 8;
offset = 0;
SV_IMPLEMENTED_SUBSTRUCTURE(GameConfigData, gameConfig);
std::copy(randomBytes, randomBytes + 20, data + 0x1dfd8);

View File

@ -212,14 +212,14 @@ void Pokemon::loadFields(void) {
LD_FIELD_E(u16, species, 32, PokemonSpeciesIndex);
LD_FIELD_E(u16, heldItem, 34, ItemIndex);
LD_FIELD_MAX(u32, experience, 36, getSpeciesExpTable(species)[100]);
LD_FIELD(u8, happiness, 41);
LD_FIELD(u8, friendship, 41);
LD_FIELD(u16, unk2, 42);
for (size_t i = 0; i < 6; ++i) EVs[statsOrder[i]] = data[56 + i];
LD_ARRAY(u8, contestStats, 5, 62);
LD_FIELD(u8, contestLuster, 67);
LD_FIELD(u8, pkrsStatus, 68);
LD_FIELD(u8, pokerusStatus, 68);
LD_FIELD(u8, locationCaught, 69);
u16 origins;
@ -275,7 +275,7 @@ void Pokemon::loadFields(void) {
partyData.status = pokemonStatusFromBitField((u16)st, &(partyData.turnsOfBadPoison), &(partyData.turnsOfSleepRemaining));
LD_FIELD_MAX(u8, partyData.level, 84, 100);
LD_FIELD_MAX(s8, partyData.pkrsDaysRemaining, 85, 4);
LD_FIELD_MAX(s8, partyData.pokerusDaysRemaining, 85, 4);
LD_FIELD(u16, partyData.currentHP, 86);
u16 sta[6];
LD_ARRAY(u16, sta, 6, 88);
@ -292,7 +292,7 @@ void Pokemon::loadFields(void) {
name = new PokemonString(data + 8, 10, version.language == Japanese);
OTName = new PokemonString(data + 20, 7, version.language == Japanese);
normalizePkrs();
normalizepokerus();
normalizeStatus();
if (!checkChecksum(false)) setInvalidPokemonFlag(true);
@ -319,7 +319,7 @@ void Pokemon::save(void) {
data[27] = markings.save();
version.save(lg, gm);
normalizePkrs();
normalizepokerus();
name->save(data + 8, 10);
OTName->save(data + 20, 7);
@ -341,14 +341,14 @@ void Pokemon::save(void) {
SV_FIELD_E(u16, species, 32, PokemonSpeciesIndex);
SV_FIELD_E(u16, heldItem, 34, ItemIndex);
SV_FIELD_MAX(u32, experience, 36, getSpeciesExpTable(species)[100]);
SV_FIELD(u8, happiness, 41);
SV_FIELD(u8, friendship, 41);
SV_FIELD(u16, unk2, 42);
for (size_t i = 0; i < 6; ++i) data[56 + i] = EVs[statsOrder[i]];
SV_ARRAY(u8, contestStats, 5, 62);
SV_FIELD(u8, contestLuster, 67);
SV_FIELD(u8, pkrsStatus, 68);
SV_FIELD(u8, pokerusStatus, 68);
SV_FIELD(u8, locationCaught, 69);
u16 origins = 0;
@ -399,8 +399,8 @@ void Pokemon::save(void) {
SV_FIELD(u32, st, 80);
SV_FIELD_MAX(u8, partyData.level, 84, 100);
SV_FIELD_MAX(s8, partyData.pkrsDaysRemaining, 85, 4);
if (partyData.pkrsDaysRemaining < -1) partyData.pkrsDaysRemaining = -1;
SV_FIELD_MAX(s8, partyData.pokerusDaysRemaining, 85, 4);
if (partyData.pokerusDaysRemaining < -1) partyData.pokerusDaysRemaining = -1;
SV_FIELD_MAX(u16, partyData.currentHP, 86, partyData.stats[0]);
u16 sta[6];
for (size_t i = 0; i < 6; ++i) sta[i] = partyData.stats[statsOrder[i]];

View File

@ -61,6 +61,7 @@ GroupBattleRule& GroupBattleRule::operator=(GroupBattleRule const& other) {
if (nbBannableItems != other.nbBannableItems) throw std::invalid_argument("this->nbBannableItems != other.nbBannableItems");
if (this != &other) {
Base::DataStruct::operator=(other);
deleteFields();
CP(minLevel);
CP(maxLevel);
CP(maxLevelSum);

View File

@ -34,7 +34,7 @@ PlayerData::~PlayerData(void) {
PlayerData::deleteFields();
}
PlayerData::PlayerData(PlayerData const& other) : Base::DataStruct(other), money(other.money), pkCoupons(other.pkCoupons),
PlayerData::PlayerData(PlayerData const& other) : Base::DataStruct(other), pokeDollars(other.pokeDollars), pokeCoupons(other.pokeCoupons),
trainerGender(other.trainerGender){
CL(trainer);
CL(bag);
@ -45,7 +45,7 @@ PlayerData& PlayerData::operator=(PlayerData const& other) {
Base::DataStruct::operator=(other);
if (this != &other) {
PlayerData::deleteFields();
CP(money); CP(pkCoupons);
CP(pokeDollars); CP(pokeCoupons);
CL(trainer);
CL(bag);
CP(trainerGender);
@ -56,7 +56,7 @@ PlayerData& PlayerData::operator=(PlayerData const& other) {
void PlayerData::swap(PlayerData& other) {
if (size != other.size) throw std::invalid_argument("Cannot assign because *this and other are of different types");
Base::DataStruct::swap(other);
SW(money); SW(pkCoupons);
SW(pokeDollars); SW(pokeCoupons);
CL(trainer);
SW(bag);
SW(trainerGender);

View File

@ -80,7 +80,7 @@ SaveSlot& SaveSlot::operator=(SaveSlot const& other) {
Base::DataStruct::operator=(other);
if (this != &other) {
SaveSlot::deleteFields();
deleteFields();
randomBytes = new u8[nbRandomBytes];
CP_ARRAY(randomBytes, nbRandomBytes);
CP(magic);

View File

@ -50,6 +50,20 @@ void GroupBattleRule::swap(GroupBattleRule & other) {
SW(customName);
}
GroupBattleRule& GroupBattleRule::operator=(GroupBattleRule const& other) {
if (this != &other) {
GC::GroupBattleRule::operator=(other);
CL(customName);
CP(nbPkm);
CP(isBattleOpen);
CP(revealDeoxysForm);
CP(customName);
}
return *this;
}
LIBPKMGC_GC_GEN_NON_CONVERTIBLE_XD_VTF(GroupBattleRule)
GroupBattleRule* GroupBattleRule::clone(void) const {
return new GroupBattleRule(*this);
}

View File

@ -48,8 +48,8 @@ void PlayerData::loadFields(void) {
LD_FIELD_E(u8, trainerGender, 0x8e0, Gender);
if (trainerGender > Female) trainerGender = Male;
LD_FIELD_MAX(u32, money, 0x8e4, 9999999);
LD_FIELD_MAX(u32, pkCoupons, 0x8e8, 9999999);
LD_FIELD_MAX(u32, pokeDollars, 0x8e4, 9999999);
LD_FIELD_MAX(u32, pokeCoupons, 0x8e8, 9999999);
LD_SUBSTRUCTURE(BagData, bag, 0x4c8);
}
@ -59,9 +59,9 @@ void PlayerData::save(void) {
if (trainerGender > Female) trainerGender = Male;
SV_FIELD_E(u8, trainerGender, 0x8e0, Gender);
SV_FIELD_MAX(u32, money, 0x8e4, 9999999);
SV_FIELD_MAX(u32, pkCoupons, 0x8e8, 9999999);
SV_FIELD(u32, pkCoupons, 0x8ec);
SV_FIELD_MAX(u32, pokeDollars, 0x8e4, 9999999);
SV_FIELD_MAX(u32, pokeCoupons, 0x8e8, 9999999);
SV_FIELD(u32, pokeCoupons, 0x8ec);
SV_SUBSTRUCTURE(BagData, bag, 0x4c8);
//0x94a: total step counter

View File

@ -64,7 +64,7 @@ void Pokemon::loadFields(void) {
LD_FIELD_E(u8, heldItem, 0x03, ItemIndex);
LD_FIELD(u16, partyData.currentHP, 0x04);
LD_FIELD_CONV(u16, happiness, 0x06, u8);
LD_FIELD_CONV(u16, friendship, 0x06, u8);
LD_FIELD_CONV(u16, locationCaught, 0x08, u8);
@ -78,10 +78,10 @@ void Pokemon::loadFields(void) {
if (partyData.level > 100) partyData.level = 100;
LD_FIELD(u8, contestLuster, 0x12);
LD_FIELD(u8, pkrsStatus, 0x13);
LD_FIELD(u8, pokerusStatus, 0x13);
LD_FIELD(u8, marksTmp, 0x14);
LD_FIELD_MAX(s8, partyData.pkrsDaysRemaining, 0x15, 4);
LD_FIELD_MAX(s8, partyData.pokerusDaysRemaining, 0x15, 4);
LD_FIELD_E(u8, partyData.status, 0x16, PokemonStatus);
LD_FIELD(s8, partyData.turnsOfBadPoison, 0x17);
LD_FIELD(s8, partyData.turnsOfSleepRemaining, 0x18);
@ -122,13 +122,13 @@ void Pokemon::loadFields(void) {
if (partyData.currentHP > partyData.stats[0]) partyData.currentHP = partyData.stats[0];
pkmFlags[LIBPKMGC_GC_SECOND_ABILITY_FLAG] = isSecondAbilityDefined() && pkmFlags[LIBPKMGC_GC_SECOND_ABILITY_FLAG];
normalizePkrs();
normalizepokerus();
normalizeStatus();
}
void Pokemon::save(void) {
normalizePkrs();
normalizepokerus();
normalizeStatus();
pkmFlags[LIBPKMGC_GC_SECOND_ABILITY_FLAG] = isSecondAbilityDefined() && pkmFlags[LIBPKMGC_GC_SECOND_ABILITY_FLAG];
@ -138,7 +138,7 @@ void Pokemon::save(void) {
SV_FIELD_E(u16, species, 0x00, PokemonSpeciesIndex);
SV_FIELD_E(u8, heldItem, 0x03, ItemIndex);
SV_FIELD(u16, partyData.currentHP, 0x04);
SV_FIELD_CONV(u16, happiness, 0x06, u8);
SV_FIELD_CONV(u16, friendship, 0x06, u8);
SV_FIELD_CONV(u16, locationCaught, 0x08, u8);
SV_FIELD(u16, unk1, 0xa);
@ -152,10 +152,10 @@ void Pokemon::save(void) {
if (partyData.level > 100) partyData.level = 100;
SV_FIELD(u8, partyData.level, 0x11);
SV_FIELD(u8, contestLuster, 0x12);
SV_FIELD(u8, pkrsStatus, 0x13);
SV_FIELD(u8, pokerusStatus, 0x13);
SV_FIELD(u8, markings.save(), 0x14);
SV_FIELD_MAX(s8, partyData.pkrsDaysRemaining, 0x15, 4);
SV_FIELD_MAX(s8, partyData.pokerusDaysRemaining, 0x15, 4);
SV_FIELD_E(u8, partyData.status, 0x16, PokemonStatus);
SV_FIELD(s8, partyData.turnsOfBadPoison, 0x17);
SV_FIELD(s8, partyData.turnsOfSleepRemaining, 0x18);

View File

@ -44,6 +44,12 @@ PokemonBox* PokemonBox::create(void) const {
return new PokemonBox;
}
PokemonBox::PokemonBox(Base::PokemonBox const& other) : GC::PokemonBox(0x170c) {
initWithEmptyData();
Base::PokemonBox::operator=(other);
}
void PokemonBox::loadFields(void) {
GC::PokemonBox::loadFields();
LD_SUBSTRUCTURE_ARRAY(Pokemon, pkm, 30, 0x14);

View File

@ -44,11 +44,11 @@ StrategyMemoEntry* StrategyMemoEntry::create(void) const {
return new StrategyMemoEntry;
}
bool StrategyMemoEntry::isInfoPartial(void) const{
bool StrategyMemoEntry::isInfoIncomplete(void) const{
return false;
}
void StrategyMemoEntry::setInfoCompleteness(bool partial){
void StrategyMemoEntry::setInfoCompleteness(bool incomplete){
flags = (species == NoSpecies) ? 0 : 2;
}

View File

@ -158,6 +158,21 @@ SaveSlot& SaveSlot::operator=(SaveSlot const & other) {
return *this;
}
void SaveSlot::swap(GC::SaveEditing::SaveSlot& other) {
if (LIBPKMGC_IS_XD(SaveEditing::SaveSlot, &other))
swap((SaveSlot&)other);
else
GC::SaveEditing::SaveSlot::swap(other);
}
SaveSlot& SaveSlot::operator=(GC::SaveEditing::SaveSlot const& other) {
if (LIBPKMGC_IS_XD(SaveEditing::SaveSlot, &other))
operator=((SaveSlot const&)other);
else
GC::SaveEditing::SaveSlot::operator=(other);
return *this;
}
void SaveSlot::loadData(u32 flags) {
bool decrypted = (flags & 1) == 1;

View File

@ -6,6 +6,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5Network REQUIRED)
find_package(Qt5LinguistTools)
file(GLOB_RECURSE source_files src/*)
@ -14,9 +15,9 @@ LIST(APPEND source_files resources/PkmGCSaveEditor.rc)
include_directories(${LIBPKMGC_INCLUDE_DIRS} src/)
add_executable(PkmGCSaveEditor WIN32 ${source_files})
target_link_libraries(PkmGCSaveEditor LibPkmGC Qt5::Widgets)
target_link_libraries(PkmGCSaveEditor LibPkmGC Qt5::Widgets Qt5::Network)
set(PKMGCSAVEEDITOR_SUPPORTED_LANGUAGES en fr CACHE INTERNAL "PkmGCSaveEditor's supported languages" FORCE)
set(PKMGCSAVEEDITOR_SUPPORTED_LANGUAGES en fr de CACHE INTERNAL "PkmGCSaveEditor's supported languages" FORCE)
get_target_property(QT5_QMAKE_EXECUTABLE Qt5::qmake IMPORTED_LOCATION)
execute_process(COMMAND ${QT5_QMAKE_EXECUTABLE} -query QT_INSTALL_BINS OUTPUT_VARIABLE QT5_BINARY_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)

View File

@ -3,6 +3,7 @@ PkmGCSaveEditor is a cross-platform, open source (GPLv3) Pokémon Colosseum and
##Current features:
* You can edit all of your Pokémon, import and export them. You can NOT edit the information specific to Shadow Pokémon, though.
* You can import/export Pokémon from/to Base64 strings
* GBA Pokémon are **fully** supported as well.
* As a consequence conversion between Colosseum, XD and GBA Pokémon is **fully** supported.
* It is done (almost) exactly like it is in Colosseum/XD during a GC<->GBA trade (meaning, for example, that the data specific to shadow Pokémon is lost).
@ -12,6 +13,7 @@ PkmGCSaveEditor is a cross-platform, open source (GPLv3) Pokémon Colosseum and
* You can edit your PC (both Pokémon and items).
* You can edit your Daycare.
* You can edit your Strategy Memo.
* You can edit the description of some ribbons
* On XD, you can edit your Purifier.
###Additional features *partially* supported by the backend library **only**:
@ -22,7 +24,7 @@ Editing your Mailbox and your Battle Mode data.
* Dumped names (thanks [Tiddlywinks](http://projectpokemon.org/forums/showthread.php?46253-Stars-Pokemon-colosseum-and-XD-hacking-tutorial-part-2-Text-editing&p=205271&viewfull=1#post205271)!): English, French, German, Spanish, Italian, Japanese
##Special thanks to:
Ralf (for his "offset tables"), StarsMMD, Tiddlywinks.
peterpansexuall (German translation), Yago (testing), Ralf (for his "offset tables"), StarsMMD, Tiddlywinks.
_Tips_: The most recent versions of Dolphin (e.g. 5.0-rc) can directly read and write to GCI files, making testing your changes much easier.
You can dump/restore your physical memory card contents using Ctr-Gcs-DacoTaco-Edition.

View File

@ -50,4 +50,19 @@ LibPkmGC::LanguageIndex generateDumpedNamesLanguage(void) {
LibPkmGC::LanguageIndex ret = (LibPkmGC::LanguageIndex) languageCodeToIndexMap.value(lg, (size_t)LibPkmGC::English);
if (ret > LibPkmGC::Spanish) ret = LibPkmGC::English;
return ret;
}
void addToolTipTo(QLabel* lbl, QString const& toolTipTxt) {
lbl->setText(lbl->text() + "*");
lbl->setToolTip(toolTipTxt);
}
QString replaceSpecialNameCharsIn(QString inStr) {
// U+2030 -> U+2025
return inStr.replace(QChar(0x2030), QChar(0x2025));
}
QString replaceSpecialNameCharsOut(QString outStr) {
// U+2025 -> U+2030
return outStr.replace(QChar(0x2025), QChar(0x2030));
}

View File

@ -19,7 +19,7 @@
#ifndef _PKMGCSAVEEDITOR_GLOBALS_H
#define _PKMGCSAVEEDITOR_GLOBALS_H
#define PKMGCSAVEEDITOR_VERSION 1001002
#define PKMGCSAVEEDITOR_VERSION 1002000
#define PKMGCSAVEEDITOR_VERSION_MAJOR ((PKMGCSAVEEDITOR_VERSION / 1000000) % 1000)
#define PKMGCSAVEEDITOR_VERSION_MINOR ((PKMGCSAVEEDITOR_VERSION / 1000) % 1000)
#define PKMGCSAVEEDITOR_VERSION_BUILD (PKMGCSAVEEDITOR_VERSION % 1000)
@ -31,6 +31,7 @@
#include <LibPkmGC/GBA/Pokemon.h>
#include <QLocale>
#include <QMap>
#include <QLabel>
const QString appName = QString("PkmGCSaveEditor v%1.%2.%3").arg(PKMGCSAVEEDITOR_VERSION_MAJOR).arg(PKMGCSAVEEDITOR_VERSION_MINOR).arg(PKMGCSAVEEDITOR_VERSION_BUILD);
@ -48,4 +49,9 @@ extern QString lastSaveDirectory;
LibPkmGC::LanguageIndex generateDumpedNamesLanguage(void);
void addToolTipTo(QLabel* lbl, QString const& toolTipTxt);
QString replaceSpecialNameCharsIn(QString inStr);
QString replaceSpecialNameCharsOut(QString outStr);
#endif

View File

@ -62,6 +62,7 @@ void ItemComboBox::resetItemList(void){
}
ItemIndex ItemComboBox::currentItemIndex(void) const{
int index = currentIndex();
return _indices[this->currentIndex()];
}

View File

@ -27,7 +27,6 @@
#include <Core/IDataUI.h>
#include <QPushButton>
#include <QTableWidget>
#include <QLabel>
#include <QHeaderView>
#include <QComboBox>
#include <QShortcut>

View File

@ -47,7 +47,7 @@ QFormLayout(){
}
void TrainerInfoLayout::trainerName(LibPkmGC::Base::PokemonString * outName) {
outName->fromUTF8(nameFld->text().toUtf8().data());
outName->fromUTF8(replaceSpecialNameCharsOut(nameFld->text()).toUtf8().data());
}
u16 TrainerInfoLayout::TID(void) const {
@ -63,7 +63,7 @@ Gender TrainerInfoLayout::trainerGender(void) const {
}
void TrainerInfoLayout::setTrainerName(LibPkmGC::Base::PokemonString* inName) {
if(inName != NULL) nameFld->setText(inName->toUTF8());
if(inName != NULL) nameFld->setText(replaceSpecialNameCharsIn(inName->toUTF8()));
}
void TrainerInfoLayout::setTID(LibPkmGC::u16 inTID) {

View File

@ -24,10 +24,11 @@
#include <QButtonGroup>
#include <QRadioButton>
#include <QLineEdit>
#include <algorithm>
#include <Core/UnsignedSpinbox.h>
#include <LibPkmGC/Core/PokemonInfo.h>
#include <LibPkmGC/Base/PokemonString.h>
#include <Core/Globals.h>
class TrainerInfoLayout : public QFormLayout{
Q_OBJECT
public:

View File

@ -33,16 +33,21 @@ void PlayerUI::initWidget(void){
generalTabLayout = new QVBoxLayout;
trainerInfoBox = new QGroupBox(tr("Trainer information"));
trainerInfoFld = new TrainerInfoLayout;
ruisNameFld = new QLineEdit;
ruisNameFld->setMaxLength(10);
trainerInfoFld->addRow(tr("Rui's name"), ruisNameFld);
trainerInfoBox->setLayout(trainerInfoFld);
currenciesBox = new QGroupBox(tr("Currencies"));
currenciesLayout = new QFormLayout;
moneyFld = new UnsignedSpinbox<32>;
pkCouponsFld = new UnsignedSpinbox<32>;
pokeDollarsFld = new UnsignedSpinbox<32>;
pokeCouponsFld = new UnsignedSpinbox<32>;
currenciesLayout->addRow(tr("Money"), moneyFld);
currenciesLayout->addRow(tr("Pok""\xc3\xa9""coupons"), pkCouponsFld); // Pokécoupons
currenciesLayout->addRow(tr("Pok\xc3\xa9""dollars"), pokeDollarsFld);
currenciesLayout->addRow(tr("Pok""\xc3\xa9""Coupons"), pokeCouponsFld); // Pokécoupons
currenciesBox->setLayout(currenciesLayout);
@ -72,16 +77,22 @@ void PlayerUI::initWidget(void){
}
PlayerUI::~PlayerUI(void){
//for (size_t i = 0; i < 6; ++i) delete partyBackup[i];
}
void PlayerUI::parseData(void){
if (player == NULL) return;
isXD = LIBPKMGC_IS_XD(PlayerData, player);
ruisNameFld->setVisible(!isXD);
trainerInfoFld->labelForField(ruisNameFld)->setVisible(!isXD);
if (!isXD) {
ruisNameFld->setText(replaceSpecialNameCharsIn(static_cast<Colosseum::PlayerData*>(player)->ruisName->toUTF8()));
}
trainerInfoFld->set(player->trainer->trainerName, player->trainer->TID, player->trainer->SID, player->trainerGender);
moneyFld->setValue((int)player->money);
pkCouponsFld->setValue((int)player->pkCoupons);
pokeDollarsFld->setValue((int)player->pokeDollars);
pokeCouponsFld->setValue((int)player->pokeCoupons);
bagTab->bag = player->bag;
bagTab->parseData();
@ -96,12 +107,14 @@ void PlayerUI::parseData(void){
}
void PlayerUI::saveChanges(void) {
if (!isXD)
static_cast<Colosseum::PlayerData*>(player)->ruisName->fromUTF8(replaceSpecialNameCharsOut(ruisNameFld->text()).toUtf8().data());
trainerInfoFld->trainerName(player->trainer->trainerName);
player->trainer->TID = trainerInfoFld->TID();
player->trainer->SID = trainerInfoFld->SID();
player->trainerGender = trainerInfoFld->trainerGender();
player->money = moneyFld->unsignedValue();
player->pkCoupons = pkCouponsFld->unsignedValue();
player->pokeDollars = pokeDollarsFld->unsignedValue();
player->pokeCoupons = pokeCouponsFld->unsignedValue();
for (size_t i = 0; i < 6; ++i) pkmFlds[i]->saveChanges();
bagTab->saveChanges();

View File

@ -51,12 +51,15 @@ private:
QWidget* generalTab;
QVBoxLayout* generalTabLayout;
QGroupBox* trainerInfoBox;
TrainerInfoLayout* trainerInfoFld;
QLineEdit* ruisNameFld;
QGroupBox* currenciesBox;
QFormLayout* currenciesLayout;
UnsignedSpinbox<32> *moneyFld, *pkCouponsFld;
UnsignedSpinbox<32> *pokeDollarsFld, *pokeCouponsFld;
BagEditor* bagTab;

View File

@ -23,11 +23,106 @@
#include <QFileInfo>
#include <QMessageBox>
#include <QMenu>
#include <QAction>
using namespace LibPkmGC;
using namespace Localization;
namespace GCUIs {
QStringList PokemonBase64InputDialog::formats(void) {
return QStringList() << tr("Colosseum") << tr("XD") << tr("GBA (100 bytes)") << tr("GBA (80 bytes)");
}
PokemonBase64InputDialog::PokemonBase64InputDialog(QWidget* parent) : QDialog(parent), mainLayout(new QVBoxLayout), inputLayout(new QFormLayout),
format(new QLabel(tr("N/A"))), contents(new QPlainTextEdit), buttons(new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel)){
this->setWindowTitle(tr("Base64 input"));
contents->setWordWrapMode(QTextOption::WrapAnywhere);
inputLayout->addRow(tr("Format"), format);
inputLayout->addRow(tr("Contents"), contents);
mainLayout->addLayout(inputLayout);
mainLayout->addWidget(buttons);
setLayout(mainLayout);
connect(contents, SIGNAL(textChanged()), this, SLOT(update()));
connect(buttons, SIGNAL(accepted()), this, SLOT(accept()));
connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
}
QByteArray const & PokemonBase64InputDialog::result(void) {
return data;
}
void PokemonBase64InputDialog::accept(void) {
if (!valid) {
QMessageBox::critical(this, tr("Error"), tr("Invalid content size."));
return;
}
QDialog::accept();
}
void PokemonBase64InputDialog::update(void) {
const QStringList fmts = formats();
QString str(contents->toPlainText());
data = QByteArray::fromBase64(str.toLocal8Bit());
valid = true;
switch (data.size()) {
case 0: format->setText(tr("N/A")); break;
case 0x138: format->setText(fmts[0]); break;
case 0xc4: format->setText(fmts[1]); break;
case 100: format->setText(fmts[2]); break;
case 80: format->setText(fmts[3]); break;
default: format->setText(tr("Invalid")); valid = false; break;
}
}
PokemonBase64OutputDialog::PokemonBase64OutputDialog(GC::Pokemon* inPkm, QWidget * parent) : QDialog(parent), pkm(inPkm), mainLayout(new QVBoxLayout),
outputLayout(new QFormLayout), format(new QComboBox), contents(new QPlainTextEdit), buttons(new QDialogButtonBox(QDialogButtonBox::Ok)) {
this->setWindowTitle(tr("Base64 output"));
format->addItems(PokemonBase64InputDialog::formats());
contents->setReadOnly(true);
contents->setWordWrapMode(QTextOption::WrapAnywhere);
outputLayout->addRow(tr("Format"), format);
outputLayout->addRow(tr("Contents"), contents);
mainLayout->addLayout(outputLayout);
mainLayout->addWidget(buttons);
setLayout(mainLayout);
format->setCurrentIndex((LIBPKMGC_IS_XD(Pokemon, pkm)) ? 1 : 0);
connect(format, SIGNAL(currentIndexChanged(int)), this, SLOT(update()));
connect(buttons, SIGNAL(accepted()), this, SLOT(accept()));
connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
update();
}
void PokemonBase64OutputDialog::update(void) {
Base::Pokemon* exportedPkm = NULL;
bool gba80 = false;
switch (format->currentIndex()) {
case 0: exportedPkm = new Colosseum::Pokemon(*pkm); break;
case 1: exportedPkm = new XD::Pokemon(*pkm); break;
case 2: exportedPkm = new GBA::Pokemon(*pkm); break;
case 3: exportedPkm = new GBA::Pokemon(*pkm); gba80 = true; break;
default: break;
}
if (exportedPkm == NULL) return;
exportedPkm->save();
QByteArray data((const char*)exportedPkm->data, (int) ((gba80) ? 80 : exportedPkm->fixedSize));
QByteArray b64 = data.toBase64();
contents->setPlainText(QString(b64.constData()));
}
PokemonDisplayWidget::PokemonDisplayWidget(GC::Pokemon* inPkm, LibPkmGC::PokemonStorageInfo const& inLocation, QWidget* parent) :
QWidget(parent), pkm(inPkm), location(inLocation), pkmBackup(NULL) {
init();
@ -44,9 +139,24 @@ void PokemonDisplayWidget::initWidget(void) {
summary = new QLabel;
editButton = new QPushButton(tr("Edit"));
deleteButton = new QPushButton(tr("Delete"));
importButton = new QPushButton(tr("Import"));
exportButton = new QPushButton(tr("Export"));
importMenu = new QMenu;
importFileAction = new QAction(tr("&File..."), this);
importBase64Action = new QAction(tr("&Base64..."), this);
importMenu->addAction(importFileAction);
importMenu->addAction(importBase64Action);
exportMenu = new QMenu;
exportFileAction = new QAction(tr("&File..."), this);
exportBase64Action = new QAction(tr("&Base64..."), this);
exportMenu->addAction(exportFileAction);
exportMenu->addAction(exportBase64Action);
importButton->setMenu(importMenu);
exportButton->setMenu(exportMenu);
mainLayout->addWidget(nameFld);
mainLayout->addWidget(summary);
buttonsLayout->addWidget(editButton);
@ -58,8 +168,10 @@ void PokemonDisplayWidget::initWidget(void) {
connect(editButton, SIGNAL(clicked()), this, SLOT(openPkmUI()));
connect(deleteButton, SIGNAL(clicked()), this, SLOT(deletePkm()));
connect(importButton, SIGNAL(clicked()), this, SLOT(openImportPkmDialog()));
connect(exportButton, SIGNAL(clicked()), this, SLOT(openExportPkmDialog()));
connect(importFileAction, SIGNAL(triggered()), this, SLOT(openImportPkmFileDialog()));
connect(importBase64Action, SIGNAL(triggered()), this, SLOT(openImportBase64Dialog()));
connect(exportFileAction, SIGNAL(triggered()), this, SLOT(openExportPkmFileDialog()));
connect(exportBase64Action, SIGNAL(triggered()), this, SLOT(openExportBase64Dialog()));
this->setLayout(mainLayout);
}
@ -80,6 +192,7 @@ void PokemonDisplayWidget::cancelChanges(void) {
}
void PokemonDisplayWidget::updatePkmNameAndSummary(void) {
const QStringList invalidStrs = PokemonUI::invalidPkmStrs();
LanguageIndex lg = generateDumpedNamesLanguage();
QString s, tt;
@ -89,25 +202,25 @@ void PokemonDisplayWidget::updatePkmNameAndSummary(void) {
return;
}
nameFld->setText(pkm->name->toUTF8());
nameFld->setText(replaceSpecialNameCharsIn(pkm->name->toUTF8()));
s = "(";
if (!getSpeciesData(pkm->species).isValid || (pkm->species == Bonsly && !LIBPKMGC_IS_XD(Pokemon,pkm))) {
tt = tr("Invalid species");
tt = invalidStrs[1];
}
if (pkm->version.isIncomplete()) {
if (!tt.isEmpty()) tt += "\n";
tt = tr("Invalid version info");
tt = invalidStrs[2];
}
if (pkm->pkmFlags[LIBPKMGC_GC_INVALID_POKEMON_FLAG]) {
if (pkm->isMarkedAsInvalid()) {
if (!tt.isEmpty()) tt += "\n";
tt += tr("\"Invalid Pok\xc3\xa9mon\" flag set");
tt += invalidStrs[3];
}
summary->setToolTip(tt);
if (!tt.isEmpty()) {
s += "<span style='color:red;'>INVALID</span>";
s += "<span style = 'color:red;'>" + invalidStrs[0] + "*</span>";
}
else {
s += tr("Lv. %n ", "", (pkm->partyData.level > 100) ? 100 : pkm->partyData.level);
@ -152,7 +265,7 @@ QString PokemonDisplayWidget::selectFilters(bool op) {
(F[0] + ";;" + F[1] + ";;" + F[2] + ";;" + gbaencfilter);
}
void PokemonDisplayWidget::openImportPkmDialog(void) {
void PokemonDisplayWidget::openImportPkmFileDialog(void) {
QString fileName = QFileDialog::getOpenFileName(this, tr("Open Pok\xc3\xa9mon file"), lastPkmDirectory, selectFilters(true));
if (fileName.isEmpty()) return;
@ -168,7 +281,21 @@ void PokemonDisplayWidget::openImportPkmDialog(void) {
}
void PokemonDisplayWidget::openExportPkmDialog(void) {
void PokemonDisplayWidget::openImportBase64Dialog(void) {
PokemonBase64InputDialog dlg(this);
if(dlg.exec() == QDialog::Rejected) return;
QByteArray const& data = dlg.result();
if (data.isEmpty()) return;
switch (data.size()) {
case 0x138: importPkmFromData<Colosseum::Pokemon>(data); break;
case 0xc4: importPkmFromData<XD::Pokemon>(data); break;
case 100: case 80: importPkmFromData<GBA::Pokemon>(data, data.size()); break;
default: break;
}
}
void PokemonDisplayWidget::openExportPkmFileDialog(void) {
const QString errmsg = tr("Could not write to file.");
const QString errmsg2 = tr("An error occured while writing to the specified Pok\xc3\xa9mon file.");
const QString gbaencfilter = tr("Encrypted GBA Pok\xc3\xa9mon files (*.pkm *.3gpkm)");
@ -221,4 +348,8 @@ void PokemonDisplayWidget::openExportPkmDialog(void) {
}
void PokemonDisplayWidget::openExportBase64Dialog(void) {
PokemonBase64OutputDialog(pkm, this).exec();
}
}

View File

@ -20,9 +20,48 @@
#define _PKMGCSAVEEDITOR_POKEMON_DISPLAY_WIDGET_H
#include <GCUIs/PokemonUI.h>
#include <QPlainTextEdit>
namespace GCUIs {
class PokemonBase64InputDialog : public QDialog {
Q_OBJECT
public:
static QStringList formats(void);
PokemonBase64InputDialog(QWidget* parent = NULL);
QByteArray const& result(void);
private:
bool valid;
QByteArray data;
QFormLayout* inputLayout;
QVBoxLayout* mainLayout;
QLabel* format;
QPlainTextEdit* contents;
QDialogButtonBox* buttons;
public slots:
void accept(void);
void update(void);
};
class PokemonBase64OutputDialog : public QDialog {
Q_OBJECT
public:
PokemonBase64OutputDialog(LibPkmGC::GC::Pokemon* inPkm, QWidget* parent = NULL);
LibPkmGC::GC::Pokemon* pkm;
private:
QFormLayout* outputLayout;
QVBoxLayout* mainLayout;
QComboBox* format;
QPlainTextEdit* contents;
QDialogButtonBox* buttons;
public slots:
void update(void);
};
class PokemonDisplayWidget : public QWidget, IDataUI {
Q_OBJECT
public:
@ -45,8 +84,10 @@ signals:
public slots:
void updatePkmNameAndSummary(void);
void openImportPkmDialog(void);
void openExportPkmDialog(void);
void openImportPkmFileDialog(void);
void openImportBase64Dialog(void);
void openExportPkmFileDialog(void);
void openExportBase64Dialog(void);
void deletePkm(void);
void openPkmUI(void);
@ -60,10 +101,42 @@ private:
QPushButton *importButton;
QPushButton *exportButton;
QMenu* importMenu;
QAction *importFileAction, *importBase64Action;
QMenu* exportMenu;
QAction *exportFileAction, *exportBase64Action;
QString selectFilters(bool op = true);
template<typename P>
void readExpected(QString fileName, size_t sz = P::size) {
void importPkmFromData(QByteArray const& ba, size_t sz = P::size) {
P* importedPkm = NULL;
if (sz != 80)
importedPkm = new P((const u8*)ba.constData());
else {
GBA::Pokemon* pk2 = GBA::Pokemon::load80((const u8*)ba.constData());
importedPkm = new P(*pk2);
delete pk2;
}
if (pkm == NULL) {
if (LIBPKMGC_IS_XD(Pokemon, importedPkm) || (currentSaveSlot != NULL && LIBPKMGC_IS_XD(SaveEditing::SaveSlot, currentSaveSlot)))
pkm = new XD::Pokemon(*importedPkm);
else
pkm = new Colosseum::Pokemon(*importedPkm);
}
else *pkm = *importedPkm;
if (P::size == 100 && currentSaveSlot != NULL)
pkm->version.currentRegion = currentSaveSlot->gameConfig->version.currentRegion;
delete importedPkm;
parseData();
}
template<typename P>
void readExpected(QString const& fileName, size_t sz = P::size) {
const QString errmsg = tr("Could not open file.");
const QString errmsg2 = tr("An error occured while reading the specified Pok\xc3\xa9mon file.");
QFile file(fileName);
@ -78,30 +151,8 @@ private:
return;
}
P* importedPkm = NULL;
if (sz != 80)
importedPkm = new P((const u8*)ba.data());
else {
GBA::Pokemon* pk2 = GBA::Pokemon::load80((const u8*)ba.data());
importedPkm = new P(*pk2);
delete pk2;
}
if (pkm == NULL) {
if (LIBPKMGC_IS_XD(Pokemon, importedPkm) || (currentSaveSlot != NULL && LIBPKMGC_IS_XD(SaveEditing::SaveSlot, currentSaveSlot)))
pkm = new XD::Pokemon(*importedPkm);
else
pkm = new Colosseum::Pokemon(*importedPkm);
}
else *pkm = *importedPkm;
if (P::size == 100 && currentSaveSlot != NULL)
pkm->version.currentRegion = currentSaveSlot->gameConfig->version.currentRegion;
parseData();
importPkmFromData<P>(ba, sz);
lastPkmDirectory = QFileInfo(fileName).canonicalPath();
delete importedPkm;
}

View File

@ -113,6 +113,21 @@ QStringList PokemonUI::statusNames(void) {
tr("Paralyzed") << tr("Burnt") << tr("Frozen") << tr("Asleep");
}
QStringList PokemonUI::ribbonNames(void) {
return QStringList() << tr("Champion") << tr("Winning") << tr("Victory") << tr("Artist") <<
tr("Effort") << tr("Marine") << tr("Land") << tr("Sky") <<
tr("Country") << tr("National") << tr("Earth") << tr("World") <<
tr("Unimplemented 1") << tr("Unimplemented 2") << tr("Unimplemented 3") << tr("Unimplemented 4");
}
QString PokemonUI::ribbonHasNeverBeenMadeAvailableStr(void) {
return tr("This ribbon has never been made available");
}
QStringList PokemonUI::invalidPkmStrs(void) {
return QStringList() << tr("INVALID") << tr("Invalid species") << tr("Invalid version info") << tr("\"Invalid Pok\xc3\xa9mon\" flag set");
}
void PokemonUI::initWidget(void){
const QStringList contestStatNames = QStringList() << tr("Coolness") << tr("Beauty") << tr("Cuteness")
<< tr("Cleverness") << tr("Toughness");
@ -124,9 +139,7 @@ void PokemonUI::initWidget(void){
const QStringList statNames = QStringList() << tr("HP") << tr("Attack") << tr("Defense") <<
tr("S. Attack") << tr("S. Defense") << tr("Speed");
const QStringList srNames = QStringList() << tr("Champion") << tr("Winning") << tr("Victory") << tr("Artist") <<
tr("Effort") << tr("Marine") << tr("Land") << tr("Sky") <<
tr("Country") << tr("National") << tr("Earth") << tr("World");
const QStringList srNames = ribbonNames();
LanguageIndex lg = generateDumpedNamesLanguage();
@ -168,10 +181,10 @@ void PokemonUI::initWidget(void){
syncLevelAndExpFldsCheckBox = new QCheckBox;
heldItemFld = new ItemComboBox;
happinessFld = new UnsignedSpinbox<8>;
pkrsStatusLayout = new QHBoxLayout;
pkrsDaysRemainingFld = new UnsignedSpinbox<3>;
pkrsStrainFld = new UnsignedSpinbox<4>;
friendshipFld = new UnsignedSpinbox<8>;
pokerusStatusLayout = new QHBoxLayout;
pokerusDaysRemainingFld = new UnsignedSpinbox<3>;
pokerusStrainFld = new UnsignedSpinbox<4>;
flagsLayout = new QGridLayout;
flagsButtonGroup = new QButtonGroup;
markingsLayout = new QHBoxLayout;
@ -190,7 +203,7 @@ void PokemonUI::initWidget(void){
levelFld->setRange(1, 100);
syncLevelAndExpFldsCheckBox->setChecked(true);
pkrsDaysRemainingFld->setUnsignedRange(0, 4);
pokerusDaysRemainingFld->setUnsignedRange(0, 4);
experienceLevelAndSyncLayout->addWidget(experienceFld,2);
@ -199,8 +212,8 @@ void PokemonUI::initWidget(void){
levelAndSyncLayout->setAlignment(Qt::AlignRight);
experienceLevelAndSyncLayout->addLayout(levelAndSyncLayout);
pkrsStatusLayout->addWidget(pkrsDaysRemainingFld);
pkrsStatusLayout->addWidget(pkrsStrainFld);
pokerusStatusLayout->addWidget(pokerusDaysRemainingFld);
pokerusStatusLayout->addWidget(pokerusStrainFld);
eggFlagCheckBox = new QCheckBox(tr("Egg")); secondAbilityFlagCheckBox = new QCheckBox(tr("Second ability"));
invalidPokemonCheckBox = new QCheckBox(tr("Invalid Pok\xc3\xa9mon"));
@ -237,8 +250,8 @@ void PokemonUI::initWidget(void){
generalCoreSubTabLayout->addRow(tr("Ability"), abilityFld);
generalCoreSubTabLayout->addRow(tr("Experience and level"), experienceLevelAndSyncLayout);
generalCoreSubTabLayout->addRow(tr("Held item"), heldItemFld);
generalCoreSubTabLayout->addRow(tr("Happiness"), happinessFld);
generalCoreSubTabLayout->addRow(tr("Pok\xc3\xa9rus (days remaing and strain)"), pkrsStatusLayout);
generalCoreSubTabLayout->addRow(tr("Friendship"), friendshipFld);
generalCoreSubTabLayout->addRow(tr("Pok\xc3\xa9rus (days remaing and strain)"), pokerusStatusLayout);
generalCoreSubTabLayout->addRow(tr("Flags"), flagsLayout);
generalCoreSubTabLayout->addRow(tr("Markings"), markingsLayout);
@ -296,8 +309,8 @@ void PokemonUI::initWidget(void){
coreCaptureInfoLayout->addRow(tr("Fateful encounter (obedient)"), obedientFld);
coreCaptureInfoLayout->addRow(tr("Ball caught with"), ballCaughtWithFld);
coreCaptureInfoLayout->labelForField(obedientFld)->setToolTip(tr("Mew and Deoxys need this field to be checked so they can obey.\n"
"Pok\xc3\xa9mon caught in XD always have this field checked."));
addToolTipTo((QLabel*) coreCaptureInfoLayout->labelForField(obedientFld), tr("Mew and Deoxys need this field to be checked so they can obey.\n"
"Pok\xc3\xa9mon caught in XD always have this field checked"));
coreCaptureInfoBox->setLayout(coreCaptureInfoLayout);
OTBox->setLayout(OTField);
versionBox->setLayout(versionFld);
@ -399,8 +412,14 @@ void PokemonUI::initWidget(void){
specialRibbonsFldGroup = new QButtonGroup;
specialRibbonsFldGroup->setExclusive(false);
const QString rna = ribbonHasNeverBeenMadeAvailableStr();
for (size_t i = 0; i < 12; ++i) {
specialRibbonsFlds[i] = new QCheckBox(srNames[i]);
if (i >= 5 && i <= 11 && i != 9 && i != 10) {
specialRibbonsFlds[i] = new QCheckBox(srNames[i] + "*");
specialRibbonsFlds[i]->setToolTip(rna);
}
else
specialRibbonsFlds[i] = new QCheckBox(srNames[i]);
specialRibbonsFldGroup->addButton(specialRibbonsFlds[i], (int)i);
specialRibbonsLayout->addWidget(specialRibbonsFlds[i], (int)(i % 4), (int)(i / 4));
}
@ -435,7 +454,7 @@ void PokemonUI::initWidget(void){
connect(experienceFld, SIGNAL(valueChanged(int)), this, SLOT(updateLevelFromExperience()));
connect(levelFld, SIGNAL(valueChanged(int)), this, SLOT(updateExperienceFromLevel()));
connect(statusFld, SIGNAL(currentIndexChanged(int)), SLOT(statusChangeHandler()));
connect(pkrsStrainFld, SIGNAL(valueChanged(int)), this, SLOT(updatePkrsDaysRemaining()));
connect(pokerusStrainFld, SIGNAL(valueChanged(int)), this, SLOT(updatePokerusDaysRemaining()));
connect(OTField, SIGNAL(TIDorSIDChanged()), this, SLOT(updatePkmAttributes()));
connect(versionFld, SIGNAL(versionChanged()), this, SLOT(versionChangeHandler()));
connect(copyInfoFromSaveButton, SIGNAL(clicked()), this, SLOT(copyInfoFromSave()));
@ -465,7 +484,7 @@ void PokemonUI::parseData(void){
heldItemFld->set(GIVABLE_ITEMS_ALLOWED, isXD);
nameFld->setText(pkm->name->toUTF8());
nameFld->setText(replaceSpecialNameCharsIn(pkm->name->toUTF8()));
speciesFld->setCurrentIndex((int)Localization::pkmSpeciesIndexToNameIndex(pkm->species));
if (pkm->species == Bonsly && !isXD) speciesFld->setCurrentIndex(0);
@ -480,7 +499,7 @@ void PokemonUI::parseData(void){
heldItemFld->setCurrentItemIndex(pkm->heldItem);
happinessFld->setUnsignedValue(pkm->happiness);
friendshipFld->setUnsignedValue(pkm->friendship);
statusFld->disconnect(SIGNAL(currentIndexChanged(int)), this);
@ -491,13 +510,13 @@ void PokemonUI::parseData(void){
connect(statusFld, SIGNAL(currentIndexChanged(int)), SLOT(statusChangeHandler()));
pkrsStrainFld->disconnect(SIGNAL(valueChanged(int)), this);
pkrsStrainFld->setUnsignedValue(pkm->pkrsStatus & 0xf);
pkrsDaysRemainingFld->setUnsignedValue(pkm->pkrsStatus >> 4);
partyPrksDaysRemainingFld->setValue(pkm->pkrsStatus >> 4);
updatePkrsDaysRemaining();
pokerusStrainFld->disconnect(SIGNAL(valueChanged(int)), this);
pokerusStrainFld->setUnsignedValue(pkm->pokerusStatus & 0xf);
pokerusDaysRemainingFld->setUnsignedValue(pkm->pokerusStatus >> 4);
partyPrksDaysRemainingFld->setValue(pkm->pokerusStatus >> 4);
updatePokerusDaysRemaining();
connect(pkrsStrainFld, SIGNAL(valueChanged(int)), this, SLOT(updatePkrsDaysRemaining()));
connect(pokerusStrainFld, SIGNAL(valueChanged(int)), this, SLOT(updatePokerusDaysRemaining()));
@ -555,7 +574,7 @@ void PokemonUI::parseData(void){
void PokemonUI::saveChanges(void){
pkm->species = nameIndexToPkmSpeciesIndex(speciesFld->currentIndex());
pkm->name->fromUTF8(nameFld->text().toUtf8().data());
pkm->name->fromUTF8(replaceSpecialNameCharsOut(nameFld->text()).toUtf8().data());
pkm->PID = PIDFld->unsignedValue();
pkm->setSecondAbilityFlag(abilityFld->currentIndex() != 0);
@ -563,9 +582,9 @@ void PokemonUI::saveChanges(void){
pkm->partyData.level = (u8)levelFld->unsignedValue();
pkm->heldItem = heldItemFld->currentItemIndex();
pkm->happiness = (u8)happinessFld->unsignedValue();
pkm->pkrsStatus = (u8)((pkrsDaysRemainingFld->unsignedValue() << 4) | pkrsStrainFld->unsignedValue());
pkm->partyData.pkrsDaysRemaining = (s8)(partyPrksDaysRemainingFld->value());
pkm->friendship = (u8)friendshipFld->unsignedValue();
pkm->pokerusStatus = (u8)((pokerusDaysRemainingFld->unsignedValue() << 4) | pokerusStrainFld->unsignedValue());
pkm->partyData.pokerusDaysRemaining = (s8)(partyPrksDaysRemainingFld->value());
pkm->partyData.status = (statusFld->currentIndex() == 0) ? NoStatus : (PokemonStatus)(2 + statusFld->currentIndex());
pkm->partyData.turnsOfBadPoison = (s8)turnsOfBadPoisonFld->value();
@ -613,6 +632,8 @@ void PokemonUI::saveChanges(void){
pkm->specialRibbons[i] = specialRibbonsFlds[i]->isChecked();
}
QString PokemonUI::getShortPkmAttributeText(LibPkmGC::PokemonSpeciesIndex species, LibPkmGC::u32 PID, LibPkmGC::u16 TID, LibPkmGC::u16 SID){
QString ret;
@ -658,15 +679,16 @@ QString PokemonUI::getLongPkmAttributeText(LibPkmGC::PokemonSpeciesIndex species
}
QString PokemonUI::getShortPkmAttributeText(void){
const QString invalid = "<span style='color:red;'>INVALID</span>";
const QStringList invalidStrs = invalidPkmStrs();
const QString invalid = "<span style='color:red;'>"+invalidStrs[0]+"*</span>";
QString ret, tt;
if (pkm == NULL || speciesFld->currentIndex() == 0) return "";
if (versionFld->info().isIncomplete())
tt = tr("Invalid version info");
tt = invalidStrs[2];
if (isXD && invalidPokemonCheckBox->isChecked()) {
if (!tt.isEmpty()) tt += "\n";
tt += tr("\"Invalid Pok\xc3\xa9mon\" flag set");
tt += invalidStrs[3];
}
attributesFld->setToolTip(tt);
@ -682,15 +704,16 @@ QString PokemonUI::getShortPkmAttributeText(void){
}
QString PokemonUI::getLongPkmAttributeText(void){
const QString invalid = "<span style='color:red;'>INVALID</span>";
const QStringList invalidStrs = invalidPkmStrs();
const QString invalid = "<span style='color:red;'>" + invalidStrs[0] + "*</span>";
QString ret, tt;
if (pkm == NULL || speciesFld->currentIndex() == 0) return "";
if (versionFld->info().isIncomplete())
tt = tr("Invalid version info");
tt = invalidStrs[2];
if (isXD && invalidPokemonCheckBox->isChecked()) {
if (!tt.isEmpty()) tt += "\n";
tt += tr("\"Invalid Pok\xc3\xa9mon\" flag set");
tt += invalidStrs[3];
}
attributesFld->setToolTip(tt);
@ -798,19 +821,19 @@ void PokemonUI::PIDChangeHandler(void) {
updateMainStats();
}
void PokemonUI::updatePkrsDaysRemaining(void) {
if (pkrsStrainFld->unsignedValue() == 0) {
pkrsDaysRemainingFld->setValue(0);
pkrsDaysRemainingFld->setDisabled(true);
void PokemonUI::updatePokerusDaysRemaining(void) {
if (pokerusStrainFld->unsignedValue() == 0) {
pokerusDaysRemainingFld->setValue(0);
pokerusDaysRemainingFld->setDisabled(true);
partyPrksDaysRemainingFld->setRange(-1, -1);
partyPrksDaysRemainingFld->setValue(-1);
partyPrksDaysRemainingFld->setDisabled(true);
}
else {
pkrsDaysRemainingFld->setDisabled(false);
pokerusDaysRemainingFld->setDisabled(false);
partyPrksDaysRemainingFld->setDisabled(false);
pkrsDaysRemainingFld->setUnsignedRange(0, (pkrsStrainFld->unsignedValue() & 0x3) + 1);
partyPrksDaysRemainingFld->setRange(0, (pkrsStrainFld->unsignedValue() & 0x3) + 1);
pokerusDaysRemainingFld->setUnsignedRange(0, (pokerusStrainFld->unsignedValue() & 0x3) + 1);
partyPrksDaysRemainingFld->setRange(0, (pokerusStrainFld->unsignedValue() & 0x3) + 1);
}
}

View File

@ -26,7 +26,6 @@
#include <QGroupBox>
#include <QTabWidget>
#include <QHBoxLayout>
#include <QLabel>
#include <QCheckBox>
#include <QStackedWidget>
#include <Core/VersionInfoLayout.h>
@ -82,6 +81,9 @@ public:
static QStringList statusNames(void);
static QStringList ribbonNames(void);
static QString ribbonHasNeverBeenMadeAvailableStr(void);
static QStringList invalidPkmStrs(void);
void parseData(void);
void saveChanges(void);
@ -128,10 +130,10 @@ private:
QCheckBox* syncLevelAndExpFldsCheckBox;
ItemComboBox* heldItemFld;
UnsignedSpinbox<8>* happinessFld;
QHBoxLayout* pkrsStatusLayout;
UnsignedSpinbox<3>* pkrsDaysRemainingFld;
UnsignedSpinbox<4>* pkrsStrainFld;
UnsignedSpinbox<8>* friendshipFld;
QHBoxLayout* pokerusStatusLayout;
UnsignedSpinbox<3>* pokerusDaysRemainingFld;
UnsignedSpinbox<4>* pokerusStrainFld;
QComboBox* statusFld;
QSpinBox* turnsOfBadPoisonFld;
@ -210,7 +212,7 @@ public slots:
void updateLevelFromExperience(void);
void speciesChangeHandler(void);
void PIDChangeHandler(void);
void updatePkrsDaysRemaining(void);
void updatePokerusDaysRemaining(void);
void statusChangeHandler(void);
void updateFlags(void);

View File

@ -0,0 +1,70 @@
/*
* Copyright (C) TuxSH 2015
* This file is part of PkmGCSaveEditor.
*
* PkmGCSaveEditor is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PkmGCSaveEditor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PkmGCSaveEditor. If not, see <http://www.gnu.org/licenses/>.
*/
#include <GCUIs/RibbonDescriptionsUI.h>
using namespace LibPkmGC; using namespace Localization; using namespace Base;
namespace GCUIs {
RibbonDescriptionsUI::RibbonDescriptionsUI(GC::RibbonDescriptionsData* inRibbonDescriptions, QWidget *parent, Qt::WindowFlags f) :
DataUI(parent, f), ribbonDescriptions(inRibbonDescriptions) {
init();
}
inline QStringList getRibbonDescriptionTexts(void) {
LanguageIndex lg = generateDumpedNamesLanguage();
QStringList ret;
for (size_t i = 0; i < 65; ++i)
ret.append(Localization::getRibbonDescription(lg, i));
return ret;
}
void RibbonDescriptionsUI::initWidget(void) {
const QStringList srNames = PokemonUI::ribbonNames();
const QString rna = PokemonUI::ribbonHasNeverBeenMadeAvailableStr();
const QStringList descr = getRibbonDescriptionTexts();
descriptionsLayout = new QFormLayout;
for (size_t i = 0; i < 11; ++i) {
descriptionsFld[i] = new QComboBox;
descriptionsFld[i]->addItems(descr);
descriptionsLayout->addRow(srNames[i + 5], descriptionsFld[i]);
if (i >= 0 && i <= 6 && i != 4 && i != 5)
addToolTipTo((QLabel*)descriptionsLayout->labelForField(descriptionsFld[i]), rna);
}
descriptionsLayout->setHorizontalSpacing(20);
mainLayout->addLayout(descriptionsLayout);
DataUI::initWidget();
}
void RibbonDescriptionsUI::parseData(void) {
if (ribbonDescriptions == NULL) return;
isXD = LIBPKMGC_IS_XD(RibbonDescriptionsData, ribbonDescriptions);
for (size_t i = 0; i < 11; ++i)
descriptionsFld[i]->setCurrentIndex(ribbonDescriptions->descriptions[i]);
}
void RibbonDescriptionsUI::saveChanges(void) {
for (size_t i = 0; i < 11; ++i)
ribbonDescriptions->descriptions[i] = (u8)descriptionsFld[i]->currentIndex();
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (C) TuxSH 2015
* This file is part of PkmGCSaveEditor.
*
* PkmGCSaveEditor is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PkmGCSaveEditor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PkmGCSaveEditor. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _PKMGCSAVEEDITOR_RIBBON_DESCRIPTIONS_UI_H
#define _PKMGCSAVEEDITOR_RIBBON_DESCRIPTIONS_UI_H
#include <GCUIs/PokemonUI.h>
namespace GCUIs {
class RibbonDescriptionsUI : public DataUI {
Q_OBJECT
public:
RibbonDescriptionsUI(LibPkmGC::GC::RibbonDescriptionsData* inRibbonDescriptions = NULL, QWidget *parent = NULL, Qt::WindowFlags f = Qt::Window);
void parseData(void);
void saveChanges(void);
LibPkmGC::GC::RibbonDescriptionsData* ribbonDescriptions;
protected:
void initWidget(void);
private:
QFormLayout* descriptionsLayout;
QComboBox* descriptionsFld[11];
};
}
#endif

View File

@ -59,7 +59,7 @@ void StrategyMemoEntryWidget::initWidget(void) {
mainLayout2 = new QFormLayout;
speciesSelector = new QComboBox;
partialInfoCheckBox = new QCheckBox;
incompleteInfoCheckBox = new QCheckBox;
firstTIDFld = new UnsignedSpinbox<16>;
firstSIDFld = new UnsignedSpinbox<16>;
@ -79,7 +79,7 @@ void StrategyMemoEntryWidget::initWidget(void) {
mainLayout2->addRow(tr("First TID"), firstTIDFld);
mainLayout2->addRow(tr("First SID"), firstSIDFld);
mainLayout2->addRow(tr("First PID"), PIDLayout);
mainLayout2->addRow(tr("Partial information"), partialInfoCheckBox);
mainLayout2->addRow(tr("Incomplete information"), incompleteInfoCheckBox);
mainLayout->addLayout(mainLayout2);
mainLayout->addWidget(generateShinyIDsButton);
mainLayout->addWidget(truncateMemoFromHereButton);
@ -104,8 +104,8 @@ void StrategyMemoEntryWidget::parseData(void) {
isXD = LIBPKMGC_IS_XD(StrategyMemoEntry, entry);
generateShinyIDsButton->setVisible(!isXD);
partialInfoCheckBox->setChecked(entry->isInfoPartial());
partialInfoCheckBox->setDisabled(isXD);
incompleteInfoCheckBox->setChecked(entry->isInfoIncomplete());
incompleteInfoCheckBox->setDisabled(isXD);
speciesSelector->setCurrentIndex(pkmSpeciesIndexToNameIndex(entry->species));
@ -116,7 +116,7 @@ void StrategyMemoEntryWidget::parseData(void) {
}
void StrategyMemoEntryWidget::saveChanges(void) {
entry->setInfoCompleteness(partialInfoCheckBox->isChecked());
entry->setInfoCompleteness(incompleteInfoCheckBox->isChecked());
entry->species = nameIndexToPkmSpeciesIndex(speciesSelector->currentIndex());
entry->firstSID = (u16)firstSIDFld->unsignedValue();
entry->firstTID = (u16)firstTIDFld->unsignedValue();

View File

@ -21,7 +21,6 @@
#include <Core/DataUI.h>
#include <Core/UnsignedSpinbox.h>
#include <QLabel>
#include <QFormLayout>
#include <QHBoxLayout>
#include <QButtonGroup>
@ -61,7 +60,7 @@ private:
QFormLayout *mainLayout2;
QComboBox *speciesSelector;
QCheckBox *partialInfoCheckBox;
QCheckBox *incompleteInfoCheckBox;
UnsignedSpinbox<16> *firstTIDFld, *firstSIDFld;
QVBoxLayout* PIDLayout;

View File

@ -28,6 +28,12 @@
#include <QApplication>
#include <QDir>
#include <QNetworkAccessManager>
#include <QEventLoop>
#include <QTimer>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
using namespace GCUIs;
using namespace XDUIs;
using namespace LibPkmGC;
@ -39,12 +45,13 @@ MWCentralWidget::MWCentralWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(p
PCButton = new QPushButton;
daycareButton = new QPushButton;
strategyMemoButton = new QPushButton;
ribbonDescriptionsButton = new QPushButton;
purifierButton = new QPushButton;
updateText();
QPushButton* lst[] = { gameConfigButton, playerButton, PCButton, daycareButton, strategyMemoButton, purifierButton };
QPushButton* lst[] = { gameConfigButton, playerButton, PCButton, daycareButton, strategyMemoButton, ribbonDescriptionsButton, purifierButton };
for (int i = 0; i < 6; ++i)
for (int i = 0; i < 7; ++i)
mainLayout->addWidget(lst[i]);
this->setLayout(mainLayout);
@ -53,6 +60,7 @@ MWCentralWidget::MWCentralWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(p
connect(PCButton, SIGNAL(clicked()), this, SLOT(openPCUI()));
connect(daycareButton, SIGNAL(clicked()), this, SLOT(openDaycareUI()));
connect(strategyMemoButton, SIGNAL(clicked()), this, SLOT(openStrategyMemoUI()));
connect(ribbonDescriptionsButton, SIGNAL(clicked()), this, SLOT(openRibbonDescriptionsUI()));
connect(purifierButton, SIGNAL(clicked()), this, SLOT(openPurifierUI()));
currentSaveSlotChangeHandler();
@ -64,12 +72,13 @@ void MWCentralWidget::updateText(void) {
PCButton->setText(tr("PC"));
daycareButton->setText(tr("Daycare"));
strategyMemoButton->setText(tr("Strategy memo"));
ribbonDescriptionsButton->setText(tr("Ribbon descriptions"));
purifierButton->setText(tr("Purifier"));
}
void MWCentralWidget::currentSaveSlotChangeHandler(void) {
QPushButton* lst[] = { gameConfigButton, playerButton, PCButton, daycareButton, strategyMemoButton, purifierButton };
for (size_t i = 0; i < 6; ++i)
QPushButton* lst[] = { gameConfigButton, playerButton, PCButton, daycareButton, strategyMemoButton, ribbonDescriptionsButton, purifierButton };
for (size_t i = 0; i < 7; ++i)
lst[i]->setDisabled(currentSaveSlot == NULL);
purifierButton->setVisible(currentSaveSlot != NULL && LIBPKMGC_IS_XD(SaveEditing::SaveSlot, currentSaveSlot));
}
@ -86,6 +95,7 @@ GEN_GCUI_SLT(PlayerUI, currentSaveSlot->player)
GEN_GCUI_SLT(PCUI, currentSaveSlot->PC)
GEN_GCUI_SLT(DaycareUI, currentSaveSlot->daycare)
GEN_GCUI_SLT(StrategyMemoUI, currentSaveSlot->strategyMemo)
GEN_GCUI_SLT(RibbonDescriptionsUI, currentSaveSlot->ribbonDescriptions);
void MWCentralWidget::openPurifierUI(void) {
if (!LIBPKMGC_IS_XD(SaveEditing::SaveSlot, currentSaveSlot)) return;
@ -94,6 +104,51 @@ void MWCentralWidget::openPurifierUI(void) {
}
void MainWindow::checkForUpdates(void) {
if (!checkForUpdatesAtStartupAction->isChecked()) return;
QEventLoop loop;
QTimer *timer = new QTimer(this);
timer->setSingleShot(true);
QNetworkAccessManager *networkAccessManager = new QNetworkAccessManager(this);
QUrl url("https://api.github.com/repos/TuxSH/PkmGCTools/releases/latest");
connect(timer, SIGNAL(timeout()), networkAccessManager, SLOT(abort()));
connect(timer, SIGNAL(timeout()), &loop, SLOT(quit()));
connect(networkAccessManager, SIGNAL(finished(QNetworkReply*)), &loop, SLOT(quit()));
timer->start(1500);
QNetworkReply *reply = NULL;
reply = networkAccessManager->get(QNetworkRequest(url));
loop.exec();
if (reply == NULL) return;
QJsonParseError err;
QByteArray result = reply->readAll();
QJsonDocument doc = QJsonDocument::fromJson(result, &err);
if (err.error != QJsonParseError::NoError) return;
if (doc.isObject()) {
QJsonObject obj = doc.object();
QJsonValue html_url = obj.value("html_url"), tag_name = obj.value("tag_name");
if (html_url.isUndefined() || tag_name.isUndefined()) return;
QStringList version_numbers = tag_name.toString().mid(1).split('.');
int ver = 0;
const int powersOfTen[] = { 1000000, 1000, 1 };
for (int i = 0; i < version_numbers.count(); ++i)
ver += powersOfTen[i] * (version_numbers[i].toInt() % 1000);
if (ver > LIBPKMGC_VERSION) {
QMessageBox::information(this, tr("New version available"),
tr("PkmGCTools (PkmGCSaveEditor) %1 is now available!<br/>"
"You can download this new version on <a href='%2'>Github</a>.")
.arg(tag_name.toString()).arg(html_url.toString()));
}
}
}
MainWindow::MainWindow() : QMainWindow(), centralWidget(new MWCentralWidget) {
this->setWindowTitle(appName);
this->setWindowIcon(QIcon(":/PkmGCSaveEditor.ico"));
@ -117,12 +172,16 @@ MainWindow::MainWindow() : QMainWindow(), centralWidget(new MWCentralWidget) {
optionsMenu = menuBar()->addMenu(tr("&Options"));
interfaceLangSubMenu = optionsMenu->addMenu(tr("&Interface language"));
dumpedNamesLangSubMenu = optionsMenu->addMenu(tr("&Dumped names language"));
ignoreDataCorruptionAction = new QAction(this);
ignoreDataCorruptionAction->setCheckable(true);
optionsMenu->addAction(ignoreDataCorruptionAction);
bugFixesSubMenu = optionsMenu->addMenu(tr("&Bug fixes"));
colosseumBugsAffectingPokemonAction = new QAction(this);
bugFixesSubMenu->addAction(colosseumBugsAffectingPokemonAction);
ignoreDataCorruptionAction = new QAction(this);
ignoreDataCorruptionAction->setCheckable(true);
optionsMenu->addAction(ignoreDataCorruptionAction);
checkForUpdatesAtStartupAction = new QAction(this);
checkForUpdatesAtStartupAction->setCheckable(true);
optionsMenu->addAction(checkForUpdatesAtStartupAction);
setCentralWidget(centralWidget);
@ -153,6 +212,8 @@ MainWindow::MainWindow() : QMainWindow(), centralWidget(new MWCentralWidget) {
"(in \"Options\", \"Bug fixes\"). <b>Do it only once and only once</b> (for each concerned save file).</li>"
"<li>If you have imported or exported a Pok\xc3\xa9mon in the GBA format, please check its status alteration, its EVs, and its game of origin.</li></ul>"));
}
checkForUpdates();
}
void MainWindow::createDumpedNamesLanguageMenu(void) {
@ -245,6 +306,7 @@ void MainWindow::updateText(void) {
bugFixesSubMenu->setTitle(tr("&Bug fixes"));
colosseumBugsAffectingPokemonAction->setText(tr("Bugs affecting &Pok\xc3\xa9mon (Colosseum, PkmGCSaveEditor \xe2\x89\xa4 1.1.0)"));
ignoreDataCorruptionAction->setText(tr("&Ignore data corruption"));
checkForUpdatesAtStartupAction->setText(tr("Check for &updates at startup"));
}
@ -493,6 +555,7 @@ void MainWindow::saveSaveFileAs(void) {
void MainWindow::loadSettings(void) {
settings = new QSettings("PkmGCTools", "PkmGCSaveEditor", this);
ignoreDataCorruption = settings->value("IgnoreDataCorruption").toBool();
checkForUpdatesAtStartupAction->setChecked(settings->value("CheckForUpdatesAtStartup", true).toBool());
interfaceLanguage = settings->value("InterfaceLanguage").toString();
dumpedNamesLanguage = (LanguageIndex) settings->value("DumpedNamesLanguage").toInt();
@ -515,6 +578,7 @@ void MainWindow::saveSettings(void) {
settings->setValue("LibPkmGCVersion", LIBPKMGC_VERSION);
settings->setValue("IgnoreDataCorruption", ignoreDataCorruption);
settings->setValue("CheckForUpdatesAtStartup", checkForUpdatesAtStartupAction->isChecked());
settings->setValue("InterfaceLanguage", interfaceLangGroup->checkedAction()->data());
if (dumpedNamesLanguage > Spanish) dumpedNamesLanguage = NoLanguage;
settings->setValue("DumpedNamesLanguage", dumpedNamesLanguage);

View File

@ -24,6 +24,7 @@
#include <GCUIs/PCUI.h>
#include <GCUIs/DaycareUI.h>
#include <GCUIs/StrategyMemoUI.h>
#include <GCUIs/RibbonDescriptionsUI.h>
#include <XDUIs/PurifierUI.h>
#include <QGridLayout>
#include <QMainWindow>
@ -32,7 +33,7 @@
#include <QSettings>
#include <QTranslator>
#include <QActionGroup>
#include <QNetworkReply>
class MWCentralWidget : public QWidget {
Q_OBJECT
public:
@ -47,11 +48,12 @@ public slots:
void openPCUI(void);
void openDaycareUI(void);
void openStrategyMemoUI(void);
void openRibbonDescriptionsUI(void);
void openPurifierUI(void);
private:
QVBoxLayout *mainLayout;
QPushButton *gameConfigButton, *playerButton, *PCButton, *daycareButton, *strategyMemoButton, *purifierButton ;
QPushButton *gameConfigButton, *playerButton, *PCButton, *daycareButton, *strategyMemoButton, *ribbonDescriptionsButton, *purifierButton ;
};
class MainWindow : public QMainWindow {
@ -62,6 +64,8 @@ public:
void updateText(void);
void updateStatusBar(void);
int openSaveChangesPrompt(void);
void checkForUpdates(void);
public slots:
void openSaveFile(void);
bool saveSaveFile(void);
@ -102,6 +106,9 @@ private:
QMenu* bugFixesSubMenu;
QAction* colosseumBugsAffectingPokemonAction;
QAction* ignoreDataCorruptionAction;
QAction* checkForUpdatesAtStartupAction;
QSettings *settings;
QTranslator translator, translatorQt;

View File

@ -19,9 +19,10 @@
#include <QApplication>
#include <MainWindow.h>
using namespace LibPkmGC;
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MainWindow userInterface;
userInterface.show();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff