From 06b8ce60171ac841a4797fe32d7c2512a969de50 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 24 Jan 2015 23:43:00 -0600 Subject: [PATCH] Cleanup database.h header and add database_conversions.cpp file --- common/database.cpp | 34 - common/database.h | 195 ++- common/database_conversions.cpp | 1973 +++++++++++++++++++++++++++++++ 3 files changed, 2070 insertions(+), 132 deletions(-) create mode 100644 common/database_conversions.cpp diff --git a/common/database.cpp b/common/database.cpp index af6771e4a..b864b30ca 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -849,40 +849,6 @@ void Database::GetCharName(uint32 char_id, char* name) { } } -bool Database::CheckDatabaseConversions() { - CheckDatabaseConvertPPDeblob(); - CheckDatabaseConvertBotsPostPPDeblob(); - CheckDatabaseConvertCorpseDeblob(); - - /* Fetch Automatic Database Upgrade Script */ - // if (!std::ifstream("db_update.pl")){ - std::cout << "Pulling down automatic database upgrade script...\n" << std::endl; -#ifdef _WIN32 - system("perl -MLWP::UserAgent -e \"require LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get('https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/db_update.pl'); if ($response->is_success){ open(FILE, '> db_update.pl'); print FILE $response->decoded_content; close(FILE); }\""); -#else - system("wget -O db_update.pl https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/db_update.pl"); -#endif - // } - - /* - Automatic Database Upgrade Script - Script: db_update.pl V 1 - the number that world passes to the script will - force the script to check for a newer version to update itself with - db_update.pl ran_from_world - won't bring up a menu if your database versions match - db_update.pl - ran standalone will bring up a menu prompt - */ - - /* Check for a new version of this script, the arg passed - would have to be higher than the copy they have downloaded - locally and they will re fetch */ - system("perl db_update.pl V 1"); - - /* Run Automatic Database Upgrade Script */ - system("perl db_update.pl ran_from_world"); - - return true; -} - bool Database::LoadVariables() { char *query = nullptr; diff --git a/common/database.h b/common/database.h index d7ad51604..9815248d1 100644 --- a/common/database.h +++ b/common/database.h @@ -90,164 +90,163 @@ public: bool Connect(const char* host, const char* user, const char* passwd, const char* database,uint32 port); ~Database(); - - /* - * General Character Related Stuff - */ - /* Character Creation */ - bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp); + bool AddToNameFilter(const char* name); + bool CreateCharacter(uint32 account_id, char* name, uint16 gender, uint16 race, uint16 class_, uint8 str, uint8 sta, uint8 cha, uint8 dex, uint8 int_, uint8 agi, uint8 wis, uint8 face); + bool DeleteCharacter(char* name); bool MoveCharacterToZone(const char* charname, const char* zonename); bool MoveCharacterToZone(const char* charname, const char* zonename,uint32 zoneid); bool MoveCharacterToZone(uint32 iCharID, const char* iZonename); - bool UpdateName(const char* oldname, const char* newname); + bool ReserveName(uint32 account_id, char* name); + bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp); bool SetHackerFlag(const char* accountname, const char* charactername, const char* hacked); bool SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone); - bool AddToNameFilter(const char* name); - bool ReserveName(uint32 account_id, char* name); - bool CreateCharacter(uint32 account_id, char* name, uint16 gender, uint16 race, uint16 class_, uint8 str, uint8 sta, uint8 cha, uint8 dex, uint8 int_, uint8 agi, uint8 wis, uint8 face); bool StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv); - bool DeleteCharacter(char* name); + bool UpdateName(const char* oldname, const char* newname); - /* - * General Information Getting Queries - */ + /* General Information Queries */ + + bool AddBannedIP(char* bannedIP, const char* notes); //Lieka Edit: Add IP address to the Banned_IPs table. + bool AddGMIP(char* ip_address, char* name); + bool CheckBannedIPs(const char* loginIP); //Lieka Edit: Check incomming connection against banned IP table. + bool CheckGMIPs(const char* loginIP, uint32 account_id); bool CheckNameFilter(const char* name, bool surname = false); bool CheckUsedName(const char* name); + uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0); uint32 GetAccountIDByChar(uint32 char_id); uint32 GetAccountIDByName(const char* accname, int16* status = 0, uint32* lsid = 0); + uint32 GetCharacterID(const char *name); + uint32 GetCharacterInfo(const char* iName, uint32* oAccID = 0, uint32* oZoneID = 0, uint32* oInstanceID = 0,float* oX = 0, float* oY = 0, float* oZ = 0); uint32 GetGuildIDByCharID(uint32 char_id); + void GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID = 0); void GetCharName(uint32 char_id, char* name); - uint32 GetCharacterInfo(const char* iName, uint32* oAccID = 0, uint32* oZoneID = 0, uint32* oInstanceID = 0,float* oX = 0, float* oY = 0, float* oZ = 0); - uint32 GetCharacterID(const char *name); - bool CheckBannedIPs(const char* loginIP); //Lieka Edit: Check incomming connection against banned IP table. - bool AddBannedIP(char* bannedIP, const char* notes); //Lieka Edit: Add IP address to the Banned_IPs table. - bool CheckGMIPs(const char* loginIP, uint32 account_id); - bool AddGMIP(char* ip_address, char* name); void LoginIP(uint32 AccountID, const char* LoginIP); - /* - * Instancing Stuff - */ - bool VerifyZoneInstance(uint32 zone_id, uint16 instance_id); - bool VerifyInstanceAlive(uint16 instance_id, uint32 char_id); - bool CharacterInInstanceGroup(uint16 instance_id, uint32 char_id); - void DeleteInstance(uint16 instance_id); - bool CheckInstanceExpired(uint16 instance_id); - uint32 ZoneIDFromInstanceID(uint16 instance_id); - uint32 VersionFromInstanceID(uint16 instance_id); - uint32 GetTimeRemainingInstance(uint16 instance_id, bool &is_perma); - bool GetUnusedInstanceID(uint16 &instance_id); - bool CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration); - void PurgeExpiredInstances(); + /* Instancing */ + bool AddClientToInstance(uint16 instance_id, uint32 char_id); + bool CharacterInInstanceGroup(uint16 instance_id, uint32 char_id); + bool CheckInstanceExists(uint16 instance_id); + bool CheckInstanceExpired(uint16 instance_id); + bool CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration); + bool GetUnusedInstanceID(uint16 &instance_id); + bool GlobalInstance(uint16 instance_id); bool RemoveClientFromInstance(uint16 instance_id, uint32 char_id); bool RemoveClientsFromInstance(uint16 instance_id); - bool CheckInstanceExists(uint16 instance_id); - void BuryCorpsesInInstance(uint16 instance_id); - uint16 GetInstanceVersion(uint16 instance_id); + bool VerifyInstanceAlive(uint16 instance_id, uint32 char_id); + bool VerifyZoneInstance(uint32 zone_id, uint16 instance_id); + uint16 GetInstanceID(const char* zone, uint32 charid, int16 version); uint16 GetInstanceID(uint32 zone, uint32 charid, int16 version); - void GetCharactersInInstance(uint16 instance_id, std::list &charid_list); + uint16 GetInstanceVersion(uint16 instance_id); + uint32 GetTimeRemainingInstance(uint16 instance_id, bool &is_perma); + uint32 VersionFromInstanceID(uint16 instance_id); + uint32 ZoneIDFromInstanceID(uint16 instance_id); + void AssignGroupToInstance(uint32 gid, uint32 instance_id); void AssignRaidToInstance(uint32 rid, uint32 instance_id); + void BuryCorpsesInInstance(uint16 instance_id); + void DeleteInstance(uint16 instance_id); void FlagInstanceByGroupLeader(uint32 zone, int16 version, uint32 charid, uint32 gid); void FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 charid, uint32 rid); + void GetCharactersInInstance(uint16 instance_id, std::list &charid_list); + void PurgeExpiredInstances(); void SetInstanceDuration(uint16 instance_id, uint32 new_duration); - bool GlobalInstance(uint16 instance_id); - /* - * Adventure related. - */ + /* Adventure related. */ + void UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win); bool GetAdventureStats(uint32 char_id, AdventureStats_Struct *as); - /* - * Account Related - */ - uint32 GetMiniLoginAccount(char* ip); - void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus); - uint32 CheckLogin(const char* name, const char* password, int16* oStatus = 0); - int16 CheckStatus(uint32 account_id); - uint32 CreateAccount(const char* name, const char* password, int16 status, uint32 lsaccount_id = 0); + /* Account Related */ + bool DeleteAccount(const char* name); + bool GetLiveChar(uint32 account_id, char* cname); bool SetAccountStatus(const char* name, int16 status); bool SetLocalPassword(uint32 accid, const char* password); + bool UpdateLiveChar(char* charname, uint32 lsaccount_id); + + int16 CheckStatus(uint32 account_id); + + uint32 CheckLogin(const char* name, const char* password, int16* oStatus = 0); + uint32 CreateAccount(const char* name, const char* password, int16 status, uint32 lsaccount_id = 0); uint32 GetAccountIDFromLSID(uint32 iLSID, char* oAccountName = 0, int16* oStatus = 0); - bool UpdateLiveChar(char* charname,uint32 lsaccount_id); - bool GetLiveChar(uint32 account_id, char* cname); + uint32 GetMiniLoginAccount(char* ip); uint8 GetAgreementFlag(uint32 acctid); + + void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus); void SetAgreementFlag(uint32 acctid); - /* - * Groups - */ - uint32 GetGroupID(const char* name); - void SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ismerc = false); - void ClearGroup(uint32 gid = 0); - char* GetGroupLeaderForLogin(const char* name,char* leaderbuf); - void SetGroupLeaderName(uint32 gid, const char* name); - char* GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, - char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr); - void ClearGroupLeader(uint32 gid = 0); + /* Groups */ + char* GetGroupLeaderForLogin(const char* name,char* leaderbuf); + char* GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr); + + uint32 GetGroupID(const char* name); + + void ClearGroup(uint32 gid = 0); + void ClearGroupLeader(uint32 gid = 0); + void SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ismerc = false); + void SetGroupLeaderName(uint32 gid, const char* name); + + /* Raids */ + + const char *GetRaidLeaderName(uint32 rid); + + uint32 GetRaidID(const char* name); - /* - * Raids - */ void ClearRaid(uint32 rid = 0); void ClearRaidDetails(uint32 rid = 0); - uint32 GetRaidID(const char* name); - const char *GetRaidLeaderName(uint32 rid); - void GetGroupLeadershipInfo(uint32 gid, uint32 rid, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, - char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr); - void GetRaidLeadershipInfo(uint32 rid, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, - RaidLeadershipAA_Struct* RLAA = nullptr); - void SetRaidGroupLeaderInfo(uint32 gid, uint32 rid); void ClearRaidLeader(uint32 gid = 0xFFFFFFFF, uint32 rid = 0); + void GetGroupLeadershipInfo(uint32 gid, uint32 rid, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr); + void GetRaidLeadershipInfo(uint32 rid, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, RaidLeadershipAA_Struct* RLAA = nullptr); + void SetRaidGroupLeaderInfo(uint32 gid, uint32 rid); + + /* Database Conversions 'database_conversions.cpp' */ - /* Database Conversions*/ bool CheckDatabaseConversions(); - bool CheckDatabaseConvertPPDeblob(); - bool CheckDatabaseConvertCorpseDeblob(); bool CheckDatabaseConvertBotsPostPPDeblob(); + bool CheckDatabaseConvertCorpseDeblob(); + bool CheckDatabaseConvertPPDeblob(); + + /* Database Variables */ - /* - * Database Variables - */ bool GetVariable(const char* varname, char* varvalue, uint16 varvalue_len); bool SetVariable(const char* varname, const char* varvalue); bool LoadVariables(); uint32 LoadVariables_MQ(char** query); bool LoadVariables_result(MySQLRequestResult results); - /* - * General Queries - */ - bool LoadZoneNames(); - bool GetZoneLongName(const char* short_name, char** long_name, char* file_name = 0, float* safe_x = 0, float* safe_y = 0, float* safe_z = 0, uint32* graveyard_id = 0, uint32* maxclients = 0); - bool GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid = 0, float* graveyard_x = 0, float* graveyard_y = 0, float* graveyard_z = 0, float* graveyard_heading = 0); - uint32 GetZoneGraveyardID(uint32 zone_id, uint32 version); - uint32 GetZoneID(const char* zonename); - uint8 GetPEQZone(uint32 zoneID, uint32 version); - const char* GetZoneName(uint32 zoneID, bool ErrorUnknown = false); - uint8 GetServerType(); + /* General Queries */ + bool GetSafePoints(const char* short_name, uint32 version, float* safe_x = 0, float* safe_y = 0, float* safe_z = 0, int16* minstatus = 0, uint8* minlevel = 0, char *flag_needed = nullptr); bool GetSafePoints(uint32 zoneID, uint32 version, float* safe_x = 0, float* safe_y = 0, float* safe_z = 0, int16* minstatus = 0, uint8* minlevel = 0, char *flag_needed = nullptr) { return GetSafePoints(GetZoneName(zoneID), version, safe_x, safe_y, safe_z, minstatus, minlevel, flag_needed); } - uint8 GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level); - uint8 GetRaceSkill(uint8 skillid, uint8 in_race); + bool GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid = 0, float* graveyard_x = 0, float* graveyard_y = 0, float* graveyard_z = 0, float* graveyard_heading = 0); + bool GetZoneLongName(const char* short_name, char** long_name, char* file_name = 0, float* safe_x = 0, float* safe_y = 0, float* safe_z = 0, uint32* graveyard_id = 0, uint32* maxclients = 0); bool LoadPTimers(uint32 charid, PTimerList &into); - void ClearPTimers(uint32 charid); - void ClearMerchantTemp(); - void SetLFP(uint32 CharID, bool LFP); - void SetLFG(uint32 CharID, bool LFG); - void SetFirstLogon(uint32 CharID, uint8 firstlogon); - void SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon); + bool LoadZoneNames(); + + const char* GetZoneName(uint32 zoneID, bool ErrorUnknown = false); + + uint32 GetZoneGraveyardID(uint32 zone_id, uint32 version); + uint32 GetZoneID(const char* zonename); + + uint8 GetPEQZone(uint32 zoneID, uint32 version); + uint8 GetRaceSkill(uint8 skillid, uint8 in_race); + uint8 GetServerType(); + uint8 GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level); + void AddReport(std::string who, std::string against, std::string lines); + void ClearMerchantTemp(); + void ClearPTimers(uint32 charid); + void SetFirstLogon(uint32 CharID, uint8 firstlogon); + void SetLFG(uint32 CharID, bool LFG); + void SetLFP(uint32 CharID, bool LFP); + void SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon); /* EQEmuLogSys */ void LoadLogSettings(EQEmuLogSys::LogSettings* log_settings); diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp new file mode 100644 index 000000000..b802f0579 --- /dev/null +++ b/common/database_conversions.cpp @@ -0,0 +1,1973 @@ +/* EQEMu: Everquest Server Emulator +Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) + +This program 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; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY except by those people which sell it, which +are required to give you total support for your newly bought product; +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 this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "../common/string_util.h" + +#include "database.h" +#include "extprofile.h" + +#include +#include + +#pragma pack(1) + +/* Conversion Structs */ + +namespace Convert { + struct BindStruct { + /*000*/ uint32 zoneId; + /*004*/ float x; + /*008*/ float y; + /*012*/ float z; + /*016*/ float heading; + }; + struct Color_Struct + { + union + { + struct + { + uint8 blue; + uint8 green; + uint8 red; + uint8 use_tint; // if there's a tint this is FF + } rgb; + uint32 color; + }; + }; + struct AA_Array + { + uint32 AA; + uint32 value; + }; + struct SpellBuff_Struct + { + /*000*/ uint8 slotid; //badly named... seems to be 2 for a real buff, 0 otherwise + /*001*/ uint8 level; + /*002*/ uint8 bard_modifier; + /*003*/ uint8 effect; //not real + /*004*/ uint32 spellid; + /*008*/ uint32 duration; + /*012*/ uint32 counters; + /*016*/ uint32 player_id; //'global' ID of the caster, for wearoff messages + /*020*/ + }; + struct Tribute_Struct { + uint32 tribute; + uint32 tier; + }; + struct Disciplines_Struct { + uint32 values[MAX_PP_DISCIPLINES]; + }; + struct GroupLeadershipAA_Struct { + union { + struct { + uint32 groupAAMarkNPC; + uint32 groupAANPCHealth; + uint32 groupAADelegateMainAssist; + uint32 groupAADelegateMarkNPC; + uint32 groupAA4; + uint32 groupAA5; + uint32 groupAAInspectBuffs; + uint32 groupAA7; + uint32 groupAASpellAwareness; + uint32 groupAAOffenseEnhancement; + uint32 groupAAManaEnhancement; + uint32 groupAAHealthEnhancement; + uint32 groupAAHealthRegeneration; + uint32 groupAAFindPathToPC; + uint32 groupAAHealthOfTargetsTarget; + uint32 groupAA15; + }; + uint32 ranks[MAX_GROUP_LEADERSHIP_AA_ARRAY]; + }; + }; + + struct RaidLeadershipAA_Struct { + union { + struct { + uint32 raidAAMarkNPC; + uint32 raidAANPCHealth; + uint32 raidAADelegateMainAssist; + uint32 raidAADelegateMarkNPC; + uint32 raidAA4; + uint32 raidAA5; + uint32 raidAA6; + uint32 raidAASpellAwareness; + uint32 raidAAOffenseEnhancement; + uint32 raidAAManaEnhancement; + uint32 raidAAHealthEnhancement; + uint32 raidAAHealthRegeneration; + uint32 raidAAFindPathToPC; + uint32 raidAAHealthOfTargetsTarget; + uint32 raidAA14; + uint32 raidAA15; + }; + uint32 ranks[MAX_RAID_LEADERSHIP_AA_ARRAY]; + }; + }; + + struct LeadershipAA_Struct { + union { + struct { + Convert::GroupLeadershipAA_Struct group; + Convert::RaidLeadershipAA_Struct raid; + }; + uint32 ranks[MAX_LEADERSHIP_AA_ARRAY]; + }; + }; + typedef struct + { + /*00*/ char Name[64]; + /*64*/ uint32 Level; + /*68*/ uint32 Race; + /*72*/ uint32 Class; + /*76*/ uint32 Zone; + /*80*/ uint32 Time; + /*84*/ uint32 Points; + /*88*/ + } PVPStatsEntry_Struct; + struct BandolierItem_Struct { + uint32 item_id; + uint32 icon; + char item_name[64]; + }; + struct Bandolier_Struct { + char name[32]; + Convert::BandolierItem_Struct items[EmuConstants::BANDOLIER_SIZE]; + }; + struct PotionBelt_Struct { + Convert::BandolierItem_Struct items[EmuConstants::POTION_BELT_SIZE]; + }; + struct SuspendedMinion_Struct + { + /*000*/ uint16 SpellID; + /*002*/ uint32 HP; + /*006*/ uint32 Mana; + /*010*/ Convert::SpellBuff_Struct Buffs[BUFF_COUNT]; + /*510*/ uint32 Items[_MaterialCount]; + /*546*/ char Name[64]; + /*610*/ + }; + + struct PlayerProfile_Struct { + /*0000*/ uint32 checksum; // Checksum from CRC32::SetEQChecksum + /*0004*/ char name[64]; // Name of player sizes not right + /*0068*/ char last_name[32]; // Last name of player sizes not right + /*0100*/ uint32 gender; // Player Gender - 0 Male, 1 Female + /*0104*/ uint32 race; // Player race + /*0108*/ uint32 class_; // Player class + /*0112*/ uint32 unknown0112; // + /*0116*/ uint32 level; // Level of player (might be one byte) + /*0120*/ Convert::BindStruct binds[5]; // Bind points (primary is first, home city is fifth) + /*0220*/ uint32 deity; // deity + /*0224*/ uint32 guild_id; + /*0228*/ uint32 birthday; // characters bday + /*0232*/ uint32 lastlogin; // last login or zone time + /*0236*/ uint32 timePlayedMin; // in minutes + /*0240*/ uint8 pvp; + /*0241*/ uint8 level2; //no idea why this is here, but thats how it is on live + /*0242*/ uint8 anon; // 2=roleplay, 1=anon, 0=not anon + /*0243*/ uint8 gm; + /*0244*/ uint8 guildrank; + /*0245*/ uint8 guildbanker; + /*0246*/ uint8 unknown0246[6]; // + /*0252*/ uint32 intoxication; + /*0256*/ uint32 spellSlotRefresh[MAX_PP_REF_MEMSPELL]; //in ms + /*0292*/ uint32 abilitySlotRefresh; + /*0296*/ uint8 haircolor; // Player hair color + /*0297*/ uint8 beardcolor; // Player beard color + /*0298*/ uint8 eyecolor1; // Player left eye color + /*0299*/ uint8 eyecolor2; // Player right eye color + /*0300*/ uint8 hairstyle; // Player hair style + /*0301*/ uint8 beard; // Beard type + /*0302*/ uint8 ability_time_seconds; //The following four spots are unknown right now..... + /*0303*/ uint8 ability_number; //ability used + /*0304*/ uint8 ability_time_minutes; + /*0305*/ uint8 ability_time_hours; //place holder + /*0306*/ uint8 unknown0306[6]; // @bp Spacer/Flag? + /*0312*/ uint32 item_material[_MaterialCount]; // Item texture/material of worn/held items + /*0348*/ uint8 unknown0348[44]; + /*0392*/ Convert::Color_Struct item_tint[_MaterialCount]; + /*0428*/ Convert::AA_Array aa_array[MAX_PP_AA_ARRAY]; + /*2348*/ float unknown2384; //seen ~128, ~47 + /*2352*/ char servername[32]; // length probably not right + /*2384*/ char title[32]; // length might be wrong + /*2416*/ char suffix[32]; // length might be wrong + /*2448*/ uint32 guildid2; // + /*2452*/ uint32 exp; // Current Experience + /*2456*/ uint32 unknown2492; + /*2460*/ uint32 points; // Unspent Practice points + /*2464*/ uint32 mana; // current mana + /*2468*/ uint32 cur_hp; // current hp + /*2472*/ uint32 unknown2508; // 0x05 + /*2476*/ uint32 STR; // Strength + /*2480*/ uint32 STA; // Stamina + /*2484*/ uint32 CHA; // Charisma + /*2488*/ uint32 DEX; // Dexterity + /*2492*/ uint32 INT; // Intelligence + /*2496*/ uint32 AGI; // Agility + /*2500*/ uint32 WIS; // Wisdom + /*2504*/ uint8 face; // Player face + /*2505*/ uint8 unknown2541[47]; // ? + /*2552*/ uint8 languages[MAX_PP_LANGUAGE]; + /*2580*/ uint8 unknown2616[4]; + /*2584*/ uint32 spell_book[MAX_PP_REF_SPELLBOOK]; + /*4504*/ uint8 unknown4540[128]; // Was [428] all 0xff + /*4632*/ uint32 mem_spells[MAX_PP_REF_MEMSPELL]; + /*4668*/ uint8 unknown4704[32]; // + /*4700*/ float y; // Player y position + /*4704*/ float x; // Player x position + /*4708*/ float z; // Player z position + /*4712*/ float heading; // Direction player is facing + /*4716*/ uint8 unknown4752[4]; // + /*4720*/ int32 platinum; // Platinum Pieces on player + /*4724*/ int32 gold; // Gold Pieces on player + /*4728*/ int32 silver; // Silver Pieces on player + /*4732*/ int32 copper; // Copper Pieces on player + /*4736*/ int32 platinum_bank; // Platinum Pieces in Bank + /*4740*/ int32 gold_bank; // Gold Pieces in Bank + /*4744*/ int32 silver_bank; // Silver Pieces in Bank + /*4748*/ int32 copper_bank; // Copper Pieces in Bank + /*4752*/ int32 platinum_cursor; // Platinum on cursor + /*4756*/ int32 gold_cursor; // Gold on cursor + /*4760*/ int32 silver_cursor; // Silver on cursor + /*4764*/ int32 copper_cursor; // Copper on cursor + /*4768*/ int32 platinum_shared; // Platinum shared between characters + /*4772*/ uint8 unknown4808[24]; + /*4796*/ uint32 skills[MAX_PP_SKILL]; // [400] List of skills // 100 dword buffer + /*5196*/ uint8 unknown5132[184]; + /*5380*/ uint32 pvp2; // + /*5384*/ uint32 unknown5420; // + /*5388*/ uint32 pvptype; // + /*5392*/ uint32 unknown5428; // + /*5396*/ uint32 ability_down; // Guessing + /*5400*/ uint8 unknown5436[8]; // + /*5408*/ uint32 autosplit; //not used right now + /*5412*/ uint8 unknown5448[8]; + /*5420*/ uint32 zone_change_count; // Number of times user has zoned in their career (guessing) + /*5424*/ uint8 unknown5460[16]; // + /*5440*/ uint32 drakkin_heritage; // + /*5444*/ uint32 drakkin_tattoo; // + /*5448*/ uint32 drakkin_details; // + /*5452*/ uint32 expansions; // expansion setting, bit field of expansions avaliable + /*5456*/ int32 toxicity; //from drinking potions, seems to increase by 3 each time you drink + /*5460*/ char unknown5496[16]; // + /*5476*/ int32 hunger_level; + /*5480*/ int32 thirst_level; + /*5484*/ uint32 ability_up; + /*5488*/ char unknown5524[16]; + /*5504*/ uint16 zone_id; // Current zone of the player + /*5506*/ uint16 zoneInstance; // Instance ID + /*5508*/ Convert::SpellBuff_Struct buffs[BUFF_COUNT]; // Buffs currently on the player + /*6008*/ char groupMembers[6][64];// + /*6392*/ char unknown6428[656]; + /*7048*/ uint32 entityid; + /*7052*/ uint32 leadAAActive; + /*7056*/ uint32 unknown7092; + /*7060*/ int32 ldon_points_guk; //client uses these as signed + /*7064*/ int32 ldon_points_mir; + /*7068*/ int32 ldon_points_mmc; + /*7072*/ int32 ldon_points_ruj; + /*7076*/ int32 ldon_points_tak; + /*7080*/ int32 ldon_points_available; + /*7084*/ int32 ldon_wins_guk; + /*7088*/ int32 ldon_wins_mir; + /*7092*/ int32 ldon_wins_mmc; + /*7096*/ int32 ldon_wins_ruj; + /*7100*/ int32 ldon_wins_tak; + /*7104*/ int32 ldon_losses_guk; + /*7108*/ int32 ldon_losses_mir; + /*7112*/ int32 ldon_losses_mmc; + /*7116*/ int32 ldon_losses_ruj; + /*7120*/ int32 ldon_losses_tak; + /*7124*/ uint8 unknown7160[72]; + /*7196*/ uint32 tribute_time_remaining; //in miliseconds + /*7200*/ uint32 showhelm; + /*7204*/ uint32 career_tribute_points; + /*7208*/ uint32 unknown7244; + /*7212*/ uint32 tribute_points; + /*7216*/ uint32 unknown7252; + /*7220*/ uint32 tribute_active; //1=active + /*7224*/ Convert::Tribute_Struct tributes[EmuConstants::TRIBUTE_SIZE]; + /*7264*/ Convert::Disciplines_Struct disciplines; + /*7664*/ uint32 recastTimers[MAX_RECAST_TYPES]; // Timers (GMT of last use) + /*7744*/ char unknown7780[160]; + /*7904*/ uint32 endurance; + /*7908*/ uint32 group_leadership_exp; //0-1000 + /*7912*/ uint32 raid_leadership_exp; //0-2000 + /*7916*/ uint32 group_leadership_points; + /*7920*/ uint32 raid_leadership_points; + /*7924*/ Convert::LeadershipAA_Struct leader_abilities; + /*8052*/ uint8 unknown8088[132]; + /*8184*/ uint32 air_remaining; + /*8188*/ uint32 PVPKills; + /*8192*/ uint32 PVPDeaths; + /*8196*/ uint32 PVPCurrentPoints; + /*8200*/ uint32 PVPCareerPoints; + /*8204*/ uint32 PVPBestKillStreak; + /*8208*/ uint32 PVPWorstDeathStreak; + /*8212*/ uint32 PVPCurrentKillStreak; + /*8216*/ Convert::PVPStatsEntry_Struct PVPLastKill; + /*8304*/ Convert::PVPStatsEntry_Struct PVPLastDeath; + /*8392*/ uint32 PVPNumberOfKillsInLast24Hours; + /*8396*/ Convert::PVPStatsEntry_Struct PVPRecentKills[50]; + /*12796*/ uint32 aapoints_spent; + /*12800*/ uint32 expAA; + /*12804*/ uint32 aapoints; //avaliable, unspent + /*12808*/ uint8 unknown12844[36]; + /*12844*/ Convert::Bandolier_Struct bandoliers[EmuConstants::BANDOLIERS_COUNT]; + /*14124*/ uint8 unknown14160[4506]; + /*18630*/ Convert::SuspendedMinion_Struct SuspendedMinion; // No longer in use + /*19240*/ uint32 timeentitledonaccount; + /*19244*/ Convert::PotionBelt_Struct potionbelt; //there should be 3 more of these + /*19532*/ uint8 unknown19568[8]; + /*19540*/ uint32 currentRadCrystals; // Current count of radiant crystals + /*19544*/ uint32 careerRadCrystals; // Total count of radiant crystals ever + /*19548*/ uint32 currentEbonCrystals;// Current count of ebon crystals + /*19552*/ uint32 careerEbonCrystals; // Total count of ebon crystals ever + /*19556*/ uint8 groupAutoconsent; // 0=off, 1=on + /*19557*/ uint8 raidAutoconsent; // 0=off, 1=on + /*19558*/ uint8 guildAutoconsent; // 0=off, 1=on + /*19559*/ uint8 unknown19595[5]; // ***Placeholder (6/29/2005) + /*19564*/ uint32 RestTimer; + /*19568*/ + }; + + + namespace player_lootitem_temp + { + struct ServerLootItem_Struct_temp { + uint32 item_id; + int16 equipSlot; + uint8 charges; + uint16 lootslot; + uint32 aug1; + uint32 aug2; + uint32 aug3; + uint32 aug4; + uint32 aug5; + uint32 aug6; + uint8 attuned; + }; + } + + struct DBPlayerCorpse_Struct_temp { + uint32 crc; + bool locked; + uint32 itemcount; + uint32 exp; + float size; + uint8 level; + uint8 race; + uint8 gender; + uint8 class_; + uint8 deity; + uint8 texture; + uint8 helmtexture; + uint32 copper; + uint32 silver; + uint32 gold; + uint32 plat; + Color_Struct item_tint[9]; + uint8 haircolor; + uint8 beardcolor; + uint8 eyecolor1; + uint8 eyecolor2; + uint8 hairstyle; + uint8 face; + uint8 beard; + uint32 drakkin_heritage; + uint32 drakkin_tattoo; + uint32 drakkin_details; + player_lootitem_temp::ServerLootItem_Struct_temp items[0]; + }; + + namespace classic_db_temp { + struct DBPlayerCorpse_Struct_temp { + uint32 crc; + bool locked; + uint32 itemcount; + uint32 exp; + float size; + uint8 level; + uint8 race; + uint8 gender; + uint8 class_; + uint8 deity; + uint8 texture; + uint8 helmtexture; + uint32 copper; + uint32 silver; + uint32 gold; + uint32 plat; + Color_Struct item_tint[9]; + uint8 haircolor; + uint8 beardcolor; + uint8 eyecolor1; + uint8 eyecolor2; + uint8 hairstyle; + uint8 face; + uint8 beard; + player_lootitem_temp::ServerLootItem_Struct_temp items[0]; + }; + } +} + +#pragma pack() + +static inline void loadbar(unsigned int x, unsigned int n, unsigned int w = 50) { + if ((x != n) && (x % (n / 100 + 1) != 0)) return; + float ratio = x / (float)n; + int c = ratio * w; + std::cout << std::setw(3) << (int)(ratio * 100) << "% ["; + for (int x = 0; x < c; x++) std::cout << "="; + for (int x = c; x < w; x++) std::cout << " "; + std::cout << "]\r" << std::flush; +} + + +bool Database::CheckDatabaseConversions() { + CheckDatabaseConvertPPDeblob(); + CheckDatabaseConvertBotsPostPPDeblob(); + CheckDatabaseConvertCorpseDeblob(); + + /* Fetch Automatic Database Upgrade Script */ + // if (!std::ifstream("db_update.pl")){ + std::cout << "Pulling down automatic database upgrade script...\n" << std::endl; +#ifdef _WIN32 + system("perl -MLWP::UserAgent -e \"require LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get('https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/db_update.pl'); if ($response->is_success){ open(FILE, '> db_update.pl'); print FILE $response->decoded_content; close(FILE); }\""); +#else + system("wget -O db_update.pl https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/db_update.pl"); +#endif + // } + + /* + Automatic Database Upgrade Script + Script: db_update.pl V 1 - the number that world passes to the script will + force the script to check for a newer version to update itself with + db_update.pl ran_from_world - won't bring up a menu if your database versions match + db_update.pl - ran standalone will bring up a menu prompt + */ + + /* Check for a new version of this script, the arg passed + would have to be higher than the copy they have downloaded + locally and they will re fetch */ + system("perl db_update.pl V 1"); + + /* Run Automatic Database Upgrade Script */ + system("perl db_update.pl ran_from_world"); + + return true; +} + +bool Database::CheckDatabaseConvertPPDeblob(){ + unsigned int lengths; + unsigned int lengths_e; + std::string squery; + Convert::PlayerProfile_Struct* pp; + ExtendedProfile_Struct* e_pp; + uint32 pplen = 0; + uint32 i; + int character_id = 0; + int account_id = 0; + int number_of_characters = 0; + int printppdebug = 0; /* Prints Player Profile */ + int runconvert = 0; + + /* Check For Legacy Storage Method */ + std::string rquery = StringFormat("SHOW TABLES LIKE 'character_'"); + auto results = QueryDatabase(rquery); + if (results.RowCount() == 1){ + runconvert = 1; + printf("\n\n::: Legacy Character Data Binary Blob Storage Detected... \n"); + printf("----------------------------------------------------------\n\n"); + printf(" Database currently has character data being stored via \n"); + printf(" the legacy character storage method and will proceed with converting...\n\n"); + printf(" It is recommended that you backup your database \n"); + printf(" before continuing the automatic conversion process...\n\n"); + printf("----------------------------------------------------------\n\n"); + std::cout << "Press ENTER to continue....." << std::endl << std::endl; + std::cin.ignore(1); + } + + // runconvert = 0; + // printppdebug = 1; + + if (runconvert == 1){ + printf("Running character binary blob to database conversion... \n"); + /* Get the number of characters */ + rquery = StringFormat("SELECT COUNT(`id`) FROM `character_`"); + results = QueryDatabase(rquery); + for (auto row = results.begin(); row != results.end(); ++row) { + number_of_characters = atoi(row[0]); + printf("Number of Characters in Database: %i \n", number_of_characters); + } + + /* Check for table `character_data` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_data'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_data` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_data` ( " + "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + "`account_id` int(11) NOT NULL DEFAULT '0', " + "`name` varchar(64) NOT NULL DEFAULT '', " + "`last_name` varchar(64) NOT NULL DEFAULT '', " + "`title` varchar(32) NOT NULL DEFAULT '', " + "`suffix` varchar(32) NOT NULL DEFAULT '', " + "`zone_id` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`zone_instance` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`y` float NOT NULL DEFAULT '0', " + "`x` float NOT NULL DEFAULT '0', " + "`z` float NOT NULL DEFAULT '0', " + "`heading` float NOT NULL DEFAULT '0', " + "`gender` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`race` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`class` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`level` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`deity` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`birthday` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`last_login` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`time_played` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`level2` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`anon` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`gm` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`face` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`hair_color` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`hair_style` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`beard` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`beard_color` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`eye_color_1` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`eye_color_2` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`drakkin_heritage` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`drakkin_tattoo` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`drakkin_details` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ability_time_seconds` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ability_number` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ability_time_minutes` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ability_time_hours` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`exp` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`aa_points_spent` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`aa_exp` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`aa_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`group_leadership_exp` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`raid_leadership_exp` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`group_leadership_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`raid_leadership_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`cur_hp` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`mana` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`endurance` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`intoxication` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`str` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`sta` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`cha` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`dex` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`int` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`agi` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`wis` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`zone_change_count` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`toxicity` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`hunger_level` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`thirst_level` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ability_up` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ldon_points_guk` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ldon_points_mir` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ldon_points_mmc` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ldon_points_ruj` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ldon_points_tak` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ldon_points_available` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`tribute_time_remaining` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`career_tribute_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`tribute_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`tribute_active` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_status` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_kills` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_deaths` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_current_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_career_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_best_kill_streak` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_worst_death_streak` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_current_kill_streak` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp2` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_type` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`show_helm` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`group_auto_consent` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`raid_auto_consent` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`guild_auto_consent` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`leadership_exp_on` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`RestTimer` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`air_remaining` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`autosplit_enabled` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`lfp` tinyint(1) unsigned NOT NULL DEFAULT '0', " + "`lfg` tinyint(1) unsigned NOT NULL DEFAULT '0', " + "`mailkey` char(16) NOT NULL DEFAULT '', " + "`xtargets` tinyint(3) unsigned NOT NULL DEFAULT '5', " + "`firstlogon` tinyint(3) NOT NULL DEFAULT '0', " + "`e_aa_effects` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`e_percent_to_aa` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`e_expended_aa_spent` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "PRIMARY KEY(`id`), " + "UNIQUE KEY `name` (`name`), " + "KEY `account_id` (`account_id`) " + ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1; " + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_currency` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_currency'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_currency` doesn't exist... creating..."); + rquery = StringFormat( + " CREATE TABLE `character_currency` ( " + " `id` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `platinum` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `gold` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `silver` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `copper` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `platinum_bank` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `gold_bank` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `silver_bank` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `copper_bank` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `platinum_cursor` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `gold_cursor` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `silver_cursor` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `copper_cursor` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `radiant_crystals` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `career_radiant_crystals` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `ebon_crystals` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `career_ebon_crystals` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " PRIMARY KEY (`id`), " + " KEY `id` (`id`) " + " ) ENGINE=InnoDB DEFAULT CHARSET=latin1; " + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_alternate_abilities` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_alternate_abilities'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_alternate_abilities` doesn't exist... creating..."); + rquery = StringFormat( + " CREATE TABLE `character_alternate_abilities` ( " + " `id` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `slot` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `aa_id` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `aa_value` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " + " PRIMARY KEY(`id`,`slot`), " + " KEY `id` (`id`) " + " ) ENGINE = InnoDB DEFAULT CHARSET = latin1; " + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_bind` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_bind'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_bind` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_bind` ( " + "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + "`is_home` tinyint(11) UNSIGNED NOT NULL DEFAULT '0', " + "`zone_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "`instance_id` mediumint(11) UNSIGNED NOT NULL DEFAULT '0', " + "`x` float NOT NULL DEFAULT '0', " + "`y` float NOT NULL DEFAULT '0', " + "`z` float NOT NULL DEFAULT '0', " + "`heading` float NOT NULL DEFAULT '0', " + "PRIMARY KEY(`id`, `is_home`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_languages` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_languages'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_languages` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_languages` ( " + "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + "`lang_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "`value` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "PRIMARY KEY(`id`, `lang_id`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_skills` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_skills'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_skills` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_skills` ( " + "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + "`skill_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "`value` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "PRIMARY KEY(`id`, `skill_id`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_spells` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_spells'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_spells` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_spells` ( " + "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + "`slot_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "`spell_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "PRIMARY KEY(`id`, `slot_id`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_memmed_spells` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_memmed_spells'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_memmed_spells` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_memmed_spells` ( " + "`id` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`slot_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "`spell_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "PRIMARY KEY(`id`, `slot_id`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_disciplines` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_disciplines'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_disciplines` doesn't exist... creating..."); + rquery = StringFormat( + " CREATE TABLE `character_disciplines` ( " + " `id` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `slot_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + " `disc_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + " PRIMARY KEY(`id`, `slot_id`), " + " KEY `id` (`id`) " + " ) ENGINE = InnoDB DEFAULT CHARSET = latin1; " + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_material` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_material'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_material` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_material` ( " + "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT," + "`slot` tinyint(11) UNSIGNED NOT NULL DEFAULT '0'," + "`blue` tinyint(11) UNSIGNED NOT NULL DEFAULT '0'," + "`green` tinyint(11) UNSIGNED NOT NULL DEFAULT '0'," + "`red` tinyint(11) UNSIGNED NOT NULL DEFAULT '0'," + "`use_tint` tinyint(11) UNSIGNED NOT NULL DEFAULT '0'," + "`color` int(11) UNSIGNED NOT NULL DEFAULT '0'," + "PRIMARY KEY(`id`, `slot`)," + "KEY `id` (`id`)" + ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1;" + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_tribute` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_tribute'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_tribute` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_tribute` ( " + "`id` int(11) unsigned NOT NULL DEFAULT 0, " + "`tier` tinyint(11) unsigned NOT NULL DEFAULT '0', " + "`tribute` int(11) UNSIGNED NOT NULL DEFAULT '0', " + "KEY `id` (`id`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_bandolier` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_bandolier'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_bandolier` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_bandolier` ( " + "`id` int(11) unsigned NOT NULL DEFAULT 0, " + "`bandolier_id` tinyint(11) unsigned NOT NULL DEFAULT '0', " + "`bandolier_slot` tinyint(11) unsigned NOT NULL DEFAULT '0', " + "`item_id` int(11) UNSIGNED NOT NULL DEFAULT '0', " + "`icon` int(11) UNSIGNED NOT NULL DEFAULT '0', " + "`bandolier_name` varchar(32) NOT NULL DEFAULT '0', " + "PRIMARY KEY(`id`,`bandolier_id`, `bandolier_slot`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1; " + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_potionbelt` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_potionbelt'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_potionbelt` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_potionbelt` ( " + "`id` int(11) unsigned NOT NULL DEFAULT 0, " + "`potion_id` tinyint(11) unsigned NOT NULL DEFAULT '0', " + "`item_id` int(11) UNSIGNED NOT NULL DEFAULT '0', " + "`icon` int(11) UNSIGNED NOT NULL DEFAULT '0', " + "PRIMARY KEY(`id`,`potion_id`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_potionbelt` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_inspect_messages'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_inspect_messages` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_inspect_messages` ( " + "`id` int(11) unsigned NOT NULL DEFAULT 0, " + "`inspect_message` varchar(255) NOT NULL DEFAULT '', " + "PRIMARY KEY(`id`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_leadership_abilities` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_leadership_abilities'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_leadership_abilities` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_leadership_abilities` (" + "`id` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`slot` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`rank` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " + "PRIMARY KEY(`id`,`slot`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1; " + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + + /* Done */ + printf("Starting conversion...\n\n"); + + + int char_iter_count = 0; + rquery = StringFormat("SELECT `id` FROM `character_`"); + results = QueryDatabase(rquery); + + uint8 firstlogon = 0; + uint8 lfg = 0; + uint8 lfp = 0; + std::string mailkey; + uint8 xtargets = 0; + std::string inspectmessage; + + for (auto row = results.begin(); row != results.end(); ++row) { + char_iter_count++; + squery = StringFormat("SELECT `id`, `profile`, `name`, `level`, `account_id`, `firstlogon`, `lfg`, `lfp`, `mailkey`, `xtargets`, `inspectmessage`, `extprofile` FROM `character_` WHERE `id` = %i", atoi(row[0])); + auto results2 = QueryDatabase(squery); + auto row2 = results2.begin(); + pp = (Convert::PlayerProfile_Struct*)row2[1]; + e_pp = (ExtendedProfile_Struct*)row2[11]; + character_id = atoi(row[0]); + account_id = atoi(row2[4]); + /* Convert some data from the character_ table that is still relevant */ + firstlogon = atoi(row2[5]); + lfg = atoi(row2[6]); + lfp = atoi(row2[7]); + mailkey = row2[8]; + xtargets = atoi(row2[9]); + inspectmessage = row2[10]; + + /* Verify PP Integrity */ + lengths = results2.LengthOfColumn(1); + if (lengths == sizeof(Convert::PlayerProfile_Struct)) { /* If PP is the size it is expected to be */ + memcpy(pp, row2[1], sizeof(Convert::PlayerProfile_Struct)); + } + /* Continue of PP Size does not match (Usually a created character never logged in) */ + else { + std::cout << (row2[2] ? row2[2] : "Unknown") << " ID: " << character_id << " size mismatch. Expected Size: " << sizeof(Convert::PlayerProfile_Struct) << " Seen: " << lengths << std::endl; + continue; + } + + lengths_e = results2.LengthOfColumn(11); + if (lengths_e == sizeof(ExtendedProfile_Struct)) { + memcpy(e_pp, row2[11], sizeof(ExtendedProfile_Struct)); + } + if (e_pp->expended_aa > 4000000){ e_pp->expended_aa = 0; } + + /* Loading Status on conversion */ + if (runconvert == 1){ + std::cout << "\r" << char_iter_count << "/" << number_of_characters << " " << std::flush; + loadbar(char_iter_count, number_of_characters, 50); + + /* Run inspect message convert */ + if (inspectmessage != ""){ + std::string rquery = StringFormat("REPLACE INTO `character_inspect_messages` (id, inspect_message)" + "VALUES (%u, '%s')", + character_id, + EscapeString(inspectmessage).c_str() + ); + auto results = QueryDatabase(rquery); + } + + /* Run Currency Convert */ + std::string rquery = StringFormat("REPLACE INTO `character_currency` (id, platinum, gold, silver, copper," + "platinum_bank, gold_bank, silver_bank, copper_bank," + "platinum_cursor, gold_cursor, silver_cursor, copper_cursor, " + "radiant_crystals, career_radiant_crystals, ebon_crystals, career_ebon_crystals)" + "VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u)", + character_id, + pp->platinum, + pp->gold, + pp->silver, + pp->copper, + pp->platinum_bank, + pp->gold_bank, + pp->silver_bank, + pp->copper_bank, + pp->platinum_cursor, + pp->gold_cursor, + pp->silver_cursor, + pp->copper_cursor, + pp->currentRadCrystals, + pp->careerRadCrystals, + pp->currentEbonCrystals, + pp->careerEbonCrystals + ); + auto results = QueryDatabase(rquery); + + if (pp->tribute_time_remaining < 0 || pp->tribute_time_remaining == 4294967295){ pp->tribute_time_remaining = 0; } + + /* Run Character Data Convert */ + rquery = StringFormat( + "REPLACE INTO `character_data` (" + "id," + "account_id," + "`name`," + "last_name," + "gender," + "race," + "class," + "`level`," + "deity," + "birthday," + "last_login," + "time_played," + "pvp_status," + "level2," + "anon," + "gm," + "intoxication," + "hair_color," + "beard_color," + "eye_color_1," + "eye_color_2," + "hair_style," + "beard," + "ability_time_seconds," + "ability_number," + "ability_time_minutes," + "ability_time_hours," + "title," + "suffix," + "exp," + "points," + "mana," + "cur_hp," + "str," + "sta," + "cha," + "dex," + "`int`," + "agi," + "wis," + "face," + "y," + "x," + "z," + "heading," + "pvp2," + "pvp_type," + "autosplit_enabled," + "zone_change_count," + "drakkin_heritage," + "drakkin_tattoo," + "drakkin_details," + "toxicity," + "hunger_level," + "thirst_level," + "ability_up," + "zone_id," + "zone_instance," + "leadership_exp_on," + "ldon_points_guk," + "ldon_points_mir," + "ldon_points_mmc," + "ldon_points_ruj," + "ldon_points_tak," + "ldon_points_available," + "tribute_time_remaining," + "show_helm," + "career_tribute_points," + "tribute_points," + "tribute_active," + "endurance," + "group_leadership_exp," + "raid_leadership_exp," + "group_leadership_points," + "raid_leadership_points," + "air_remaining," + "pvp_kills," + "pvp_deaths," + "pvp_current_points," + "pvp_career_points," + "pvp_best_kill_streak," + "pvp_worst_death_streak," + "pvp_current_kill_streak," + "aa_points_spent," + "aa_exp," + "aa_points," + "group_auto_consent," + "raid_auto_consent," + "guild_auto_consent," + "RestTimer," + "firstlogon," + "lfg," + "lfp," + "mailkey," + "xtargets," + "e_aa_effects," + "e_percent_to_aa," + "e_expended_aa_spent" + ")" + "VALUES (" + "%u," // id + "%u," // account_id + "'%s'," // `name` + "'%s'," // last_name + "%u," // gender + "%u," // race + "%u," // class + "%u," // `level` + "%u," // deity + "%u," // birthday + "%u," // last_login + "%u," // time_played + "%u," // pvp_status + "%u," // level2 + "%u," // anon + "%u," // gm + "%u," // intoxication + "%u," // hair_color + "%u," // beard_color + "%u," // eye_color_1 + "%u," // eye_color_2 + "%u," // hair_style + "%u," // beard + "%u," // ability_time_seconds + "%u," // ability_number + "%u," // ability_time_minutes + "%u," // ability_time_hours + "'%s'," // title + "'%s'," // suffix + "%u," // exp + "%u," // points + "%u," // mana + "%u," // cur_hp + "%u," // str + "%u," // sta + "%u," // cha + "%u," // dex + "%u," // `int` + "%u," // agi + "%u," // wis + "%u," // face + "%f," // y + "%f," // x + "%f," // z + "%f," // heading + "%u," // pvp2 + "%u," // pvp_type + "%u," // autosplit_enabled + "%u," // zone_change_count + "%u," // drakkin_heritage + "%u," // drakkin_tattoo + "%u," // drakkin_details + "%i," // toxicity + "%u," // hunger_level + "%u," // thirst_level + "%u," // ability_up + "%u," // zone_id + "%u," // zone_instance + "%u," // leadership_exp_on + "%u," // ldon_points_guk + "%u," // ldon_points_mir + "%u," // ldon_points_mmc + "%u," // ldon_points_ruj + "%u," // ldon_points_tak + "%u," // ldon_points_available + "%u," // tribute_time_remaining + "%u," // show_helm + "%u," // career_tribute_points + "%u," // tribute_points + "%u," // tribute_active + "%u," // endurance + "%u," // group_leadership_exp + "%u," // raid_leadership_exp + "%u," // group_leadership_points + "%u," // raid_leadership_points + "%u," // air_remaining + "%u," // pvp_kills + "%u," // pvp_deaths + "%u," // pvp_current_points + "%u," // pvp_career_points + "%u," // pvp_best_kill_streak + "%u," // pvp_worst_death_streak + "%u," // pvp_current_kill_streak + "%u," // aa_points_spent + "%u," // aa_exp + "%u," // aa_points + "%u," // group_auto_consent + "%u," // raid_auto_consent + "%u," // guild_auto_consent + "%u," // RestTimer + "%u," // First Logon - References online status for EVENT_CONNECT/EVENT_DISCONNECt + "%u," // Looking for Group + "%u," // Looking for P? + "'%s'," // Mailkey + "%u," // X Targets + "%u," // AA Effects + "%u," // Percent to AA + "%u" // e_expended_aa_spent + ")", + character_id, + account_id, + EscapeString(pp->name).c_str(), + EscapeString(pp->last_name).c_str(), + pp->gender, + pp->race, + pp->class_, + pp->level, + pp->deity, + pp->birthday, + pp->lastlogin, + pp->timePlayedMin, + pp->pvp, + pp->level2, + pp->anon, + pp->gm, + pp->intoxication, + pp->haircolor, + pp->beardcolor, + pp->eyecolor1, + pp->eyecolor2, + pp->hairstyle, + pp->beard, + pp->ability_time_seconds, + pp->ability_number, + pp->ability_time_minutes, + pp->ability_time_hours, + EscapeString(pp->title).c_str(), + EscapeString(pp->suffix).c_str(), + pp->exp, + pp->points, + pp->mana, + pp->cur_hp, + pp->STR, + pp->STA, + pp->CHA, + pp->DEX, + pp->INT, + pp->AGI, + pp->WIS, + pp->face, + pp->y, + pp->x, + pp->z, + pp->heading, + pp->pvp2, + pp->pvptype, + pp->autosplit, + pp->zone_change_count, + pp->drakkin_heritage, + pp->drakkin_tattoo, + pp->drakkin_details, + pp->toxicity, + pp->hunger_level, + pp->thirst_level, + pp->ability_up, + pp->zone_id, + pp->zoneInstance, + pp->leadAAActive == 0 ? 0 : 1, + pp->ldon_points_guk, + pp->ldon_points_mir, + pp->ldon_points_mmc, + pp->ldon_points_ruj, + pp->ldon_points_tak, + pp->ldon_points_available, + pp->tribute_time_remaining, + pp->showhelm, + pp->career_tribute_points, + pp->tribute_points, + pp->tribute_active, + pp->endurance, + pp->group_leadership_exp, + pp->raid_leadership_exp, + pp->group_leadership_points, + pp->raid_leadership_points, + pp->air_remaining, + pp->PVPKills, + pp->PVPDeaths, + pp->PVPCurrentPoints, + pp->PVPCareerPoints, + pp->PVPBestKillStreak, + pp->PVPWorstDeathStreak, + pp->PVPCurrentKillStreak, + pp->aapoints_spent, + pp->expAA, + pp->aapoints, + pp->groupAutoconsent, + pp->raidAutoconsent, + pp->guildAutoconsent, + pp->RestTimer, + firstlogon, + lfg, + lfp, + mailkey.c_str(), + xtargets, + e_pp->aa_effects, + e_pp->perAA, + e_pp->expended_aa + ); + results = QueryDatabase(rquery); + + + /* + We set a first entry variable because we need the first initial piece of the query to be declared + This is to speed up the INSERTS and trim down the amount of individual sends during the process. + The speed difference is dramatic + */ + /* Run AA Convert */ + int first_entry = 0; rquery = ""; + for (i = 0; i < MAX_PP_AA_ARRAY; i++){ + if (pp->aa_array[i].AA > 0 && pp->aa_array[i].value > 0){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value)" + " VALUES (%u, %u, %u, %u)", character_id, i, pp->aa_array[i].AA, pp->aa_array[i].value); + first_entry = 1; + } + else { + rquery = rquery + StringFormat(", (%u, %u, %u, %u)", character_id, i, pp->aa_array[i].AA, pp->aa_array[i].value); + } + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + + /* Run Bind Home Convert */ + if (pp->binds[4].zoneId < 999 && !_ISNAN_(pp->binds[4].x) && !_ISNAN_(pp->binds[4].y) && !_ISNAN_(pp->binds[4].z) && !_ISNAN_(pp->binds[4].heading)) { + rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + " VALUES (%u, %u, %u, %f, %f, %f, %f, 1)", + character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading); + if (rquery != ""){ results = QueryDatabase(rquery); } + } + + /* Run Bind Convert */ + if (pp->binds[0].zoneId < 999 && !_ISNAN_(pp->binds[0].x) && !_ISNAN_(pp->binds[0].y) && !_ISNAN_(pp->binds[0].z) && !_ISNAN_(pp->binds[0].heading)) { + rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + " VALUES (%u, %u, %u, %f, %f, %f, %f, 0)", + character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading); + if (rquery != ""){ results = QueryDatabase(rquery); } + } + /* Run Language Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < MAX_PP_LANGUAGE; i++){ + if (pp->languages[i] > 0){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)", character_id, i, pp->languages[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->languages[i]); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + /* Run Skill Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < MAX_PP_SKILL; i++){ + if (pp->skills[i] > 0){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)", character_id, i, pp->skills[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->skills[i]); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + /* Run Spell Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < MAX_PP_REF_SPELLBOOK; i++){ + if (pp->spell_book[i] > 0 && pp->spell_book[i] != 4294967295 && pp->spell_book[i] < 40000 && pp->spell_book[i] != 1){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->spell_book[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->spell_book[i]); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + /* Run Max Memmed Spell Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < MAX_PP_REF_MEMSPELL; i++){ + if (pp->mem_spells[i] > 0 && pp->mem_spells[i] != 65535 && pp->mem_spells[i] != 4294967295){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_memmed_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->mem_spells[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->mem_spells[i]); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + /* Run Discipline Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < MAX_PP_DISCIPLINES; i++){ + if (pp->disciplines.values[i] > 0 && pp->disciplines.values[i] < 60000){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_disciplines` (id, slot_id, disc_id) VALUES (%u, %u, %u)", character_id, i, pp->disciplines.values[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->disciplines.values[i]); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + /* Run Material Color Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < _MaterialCount; i++){ + if (pp->item_tint[i].color > 0){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_material` (id, slot, blue, green, red, use_tint, color) VALUES (%u, %u, %u, %u, %u, %u, %u)", character_id, i, pp->item_tint[i].rgb.blue, pp->item_tint[i].rgb.green, pp->item_tint[i].rgb.red, pp->item_tint[i].rgb.use_tint, pp->item_tint[i].color); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u, %u, %u, %u, %u)", character_id, i, pp->item_tint[i].rgb.blue, pp->item_tint[i].rgb.green, pp->item_tint[i].rgb.red, pp->item_tint[i].rgb.use_tint, pp->item_tint[i].color); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + /* Run Tribute Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ + if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != 4294967295){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + /* Run Bandolier Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < EmuConstants::BANDOLIERS_COUNT; i++){ + if (strlen(pp->bandoliers[i].name) < 32) { + for (int si = 0; si < EmuConstants::BANDOLIER_SIZE; si++){ + if (pp->bandoliers[i].items[si].item_id > 0){ + if (first_entry != 1) { + rquery = StringFormat("REPLACE INTO `character_bandolier` (id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name) VALUES (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name); + } + } + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + /* Run Potion Belt Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < EmuConstants::POTION_BELT_SIZE; i++){ + if (pp->potionbelt.items[i].item_id > 0){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_potionbelt` (id, potion_id, item_id, icon) VALUES (%i, %u, %u, %u)", character_id, i, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].icon); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%i, %u, %u, %u)", character_id, i, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].icon); + + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + /* Run Leadership AA Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < MAX_LEADERSHIP_AA_ARRAY; i++){ + if (pp->leader_abilities.ranks[i] > 0 && pp->leader_abilities.ranks[i] < 6){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_leadership_abilities` (id, slot, rank) VALUES (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + } + } + if (runconvert == 1){ + std::string rquery = StringFormat("RENAME TABLE `character_` TO `character_old`"); QueryDatabase(rquery); + printf("\n\nRenaming `character_` table to `character_old`, this is a LARGE table so when you don't need it anymore, I would suggest deleting it yourself...\n"); + printf("\n\nCharacter blob conversion complete, continuing world bootup...\n"); + } + } + return true; +} + +bool Database::CheckDatabaseConvertBotsPostPPDeblob(){ +#ifdef BOTS + int runbotsconvert = 0; + + /* Check For Legacy Bot References */ + std::string rquery = StringFormat("SHOW CREATE VIEW `vwBotCharacterMobs`"); + auto results = QueryDatabase(rquery); + if (results.RowCount() == 1){ + auto row = results.begin(); + std::string table_check = row[1]; + + if (table_check.find("character_data") == -1){ + runbotsconvert = 1; + printf("\n\n::: Legacy Bot Views and Function Detected... \n"); + printf("----------------------------------------------------------\n\n"); + printf(" Database currently has bot view/function linkage to obselete \n"); + printf(" table references and will now be converted...\n\n"); + printf(" It is recommended that you backup your database \n"); + printf(" before continuing the automatic conversion process...\n\n"); + printf("----------------------------------------------------------\n\n"); + std::cout << "Press ENTER to continue....." << std::endl << std::endl; + std::cin.ignore(1); + } + } + + if (runbotsconvert == 1){ + printf("Running bot views/function database conversion... \n"); + + /* Update view `vwbotcharactermobs` */ + rquery = StringFormat("DROP VIEW `vwBotCharacterMobs`;"); + results = QueryDatabase(rquery); + + rquery = StringFormat( + "CREATE VIEW `vwBotCharacterMobs` AS\n" + "SELECT _utf8'C' AS mobtype,\n" // Natedog: '_utf8' + "c.`id`,\n" + "c.`name`,\n" + "c.`class`,\n" + "c.`level`,\n" + "c.`last_login`,\n" + "c.`zone_id`\n" + "FROM `character_data` AS c\n" + "UNION ALL\n" + "SELECT _utf8'B' AS mobtype,\n" // Natedog: '_utf8' + "b.`BotID` AS id,\n" + "b.`Name` AS name,\n" + "b.`Class` AS class,\n" + "b.`BotLevel` AS level,\n" + "0 AS timelaston,\n" + "0 AS zoneid\n" + "FROM bots AS b;" + ); + results = QueryDatabase(rquery); + + + /* Update function `GetMobType` */ + rquery = StringFormat("DROP FUNCTION IF EXISTS `GetMobType`;"); + results = QueryDatabase(rquery); + + rquery = StringFormat( + "CREATE FUNCTION `GetMobType` (mobname VARCHAR(64)) RETURNS CHAR(1)\n" + "BEGIN\n" + " DECLARE Result CHAR(1);\n" + "\n" + " SET Result = NULL;\n" + "\n" + " IF (SELECT COUNT(*) FROM `character_data` WHERE `name` = mobname) > 0 THEN\n" + " SET Result = 'C';\n" + " ELSEIF (SELECT COUNT(*) FROM `bots` WHERE `Name` = mobname) > 0 THEN\n" + " SET Result = 'B';\n" + " END IF;\n " + "\n" + " RETURN Result;\n" + "END" + ); + results = QueryDatabase(rquery); + + + /* Update view `vwgroups` */ + rquery = StringFormat("DROP VIEW IF EXISTS `vwGroups`;"); + results = QueryDatabase(rquery); + + rquery = StringFormat( + "CREATE VIEW `vwGroups` AS\n" + "SELECT g.`groupid` AS groupid,\n" + "GetMobType(g.`name`) AS mobtype,\n" + "g.`name` AS name,\n" + "g.`charid` AS mobid,\n" + "IFNULL(c.`level`, b.`BotLevel`) AS level\n" + "FROM `group_id` AS g\n" + "LEFT JOIN `character_data` AS c ON g.`name` = c.`name`\n" + "LEFT JOIN `bots` AS b ON g.`name` = b.`Name`;" + ); + results = QueryDatabase(rquery); + + + /* Update view `vwbotgroups` */ + rquery = StringFormat("DROP VIEW IF EXISTS `vwBotGroups`;"); + results = QueryDatabase(rquery); + + rquery = StringFormat( + "CREATE VIEW `vwBotGroups` AS\n" + "SELECT g.`BotGroupId`,\n" + "g.`BotGroupName`,\n" + "g.`BotGroupLeaderBotId`,\n" + "b.`Name` AS BotGroupLeaderName,\n" + "b.`BotOwnerCharacterId`,\n" + "c.`name` AS BotOwnerCharacterName\n" + "FROM `botgroup` AS g\n" + "JOIN `bots` AS b ON g.`BotGroupLeaderBotId` = b.`BotID`\n" + "JOIN `character_data` AS c ON b.`BotOwnerCharacterID` = c.`id`\n" + "ORDER BY b.`BotOwnerCharacterId`, g.`BotGroupName`;" + ); + results = QueryDatabase(rquery); + + + /* Update view `vwguildmembers` */ + rquery = StringFormat("DROP VIEW IF EXISTS `vwGuildMembers`;"); + results = QueryDatabase(rquery); + + rquery = StringFormat( + "CREATE VIEW `vwGuildMembers` AS\n" + "SELECT 'C' AS mobtype,\n" + "cm.`char_id`,\n" + "cm.`guild_id`,\n" + "cm.`rank`,\n" + "cm.`tribute_enable`,\n" + "cm.`total_tribute`,\n" + "cm.`last_tribute`,\n" + "cm.`banker`,\n" + "cm.`public_note`,\n" + "cm.`alt`\n" + "FROM `guild_members` AS cm\n" + "UNION ALL\n" + "SELECT 'B' AS mobtype,\n" + "bm.`char_id`,\n" + "bm.`guild_id`,\n" + "bm.`rank`,\n" + "bm.`tribute_enable`,\n" + "bm.`total_tribute`,\n" + "bm.`last_tribute`,\n" + "bm.`banker`,\n" + "bm.`public_note`,\n" + "bm.`alt`\n" + "FROM `botguildmembers` AS bm;" + ); + results = QueryDatabase(rquery); + } + + if (runbotsconvert == 1){ + printf("\n\nBot views/function conversion complete, continuing world bootup...\n"); + } + +#endif + return true; +} + +bool Database::CheckDatabaseConvertCorpseDeblob(){ + Convert::DBPlayerCorpse_Struct_temp* dbpc; + Convert::classic_db_temp::DBPlayerCorpse_Struct_temp* dbpc_c; + uint32 in_datasize; + bool is_sof = false; + std::string c_type; + std::string scquery; + int8 first_entry = 0; + + std::string query = StringFormat("SHOW TABLES LIKE 'player_corpses'"); + auto results = QueryDatabase(query); + if (results.RowCount() != 0){ + query = StringFormat( + "CREATE TABLE `character_corpse_items` ( " + "`corpse_id` int(11) unsigned NOT NULL, " + "`equip_slot` int(11) unsigned NOT NULL, " + "`item_id` int(11) unsigned DEFAULT NULL, " + "`charges` int(11) unsigned DEFAULT NULL, " + "`aug_1` int(11) unsigned DEFAULT '0', " + "`aug_2` int(11) unsigned DEFAULT '0', " + "`aug_3` int(11) unsigned DEFAULT '0', " + "`aug_4` int(11) unsigned DEFAULT '0', " + "`aug_5` int(11) unsigned DEFAULT '0', " + "`aug_6` int(11) unsigned DEFAULT '0', " + "`attuned` smallint(5) NOT NULL DEFAULT '0', " + "PRIMARY KEY(`corpse_id`, `equip_slot`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1; " + ); + results = QueryDatabase(query); + query = StringFormat("RENAME TABLE `player_corpses` TO `character_corpses`"); + results = QueryDatabase(query); + query = StringFormat( + " ALTER TABLE `character_corpses` \n" + " ADD COLUMN `is_locked` tinyint(11) NULL DEFAULT 0 AFTER `WasAtGraveyard`, \n" + " ADD COLUMN `exp` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `size` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `level` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `race` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `gender` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `class` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `deity` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `texture` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `helm_texture` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `copper` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `silver` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `gold` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `platinum` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `hair_color` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `beard_color` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `eye_color_1` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `eye_color_2` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `hair_style` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `face` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `beard` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `drakkin_heritage` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `drakkin_tattoo` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `drakkin_details` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `wc_1` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `wc_2` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `wc_3` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `wc_4` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `wc_5` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `wc_6` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `wc_7` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `wc_8` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `wc_9` int(11) UNSIGNED NULL DEFAULT 0, \n" + " CHANGE COLUMN `zoneid` `zone_id` smallint(5) NOT NULL DEFAULT 0 AFTER `charname`, \n" + " CHANGE COLUMN `instanceid` `instance_id` smallint(5) UNSIGNED NOT NULL DEFAULT 0 AFTER `zone_id`, \n" + " CHANGE COLUMN `timeofdeath` `time_of_death` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `data`, \n" + " CHANGE COLUMN `rezzed` `is_rezzed` tinyint(3) UNSIGNED NULL DEFAULT 0 AFTER `time_of_death`, \n" + " CHANGE COLUMN `IsBurried` `is_buried` tinyint(3) NOT NULL DEFAULT 0 AFTER `is_rezzed`; \n" + + ); + results = QueryDatabase(query); + query = StringFormat( + " ALTER TABLE `character_corpses` \n" + " CHANGE COLUMN `WasAtGraveyard` `was_at_graveyard` tinyint(3) NOT NULL DEFAULT 0 AFTER `is_buried` \n" + ); + results = QueryDatabase(query); + } + + std::string rquery = StringFormat("SHOW COLUMNS FROM `character_corpses` LIKE 'data'"); + results = QueryDatabase(rquery); + if (results.RowCount() != 0){ + rquery = StringFormat("SELECT DISTINCT charid FROM character_corpses"); + results = QueryDatabase(rquery); + for (auto row = results.begin(); row != results.end(); ++row) { + std::string squery = StringFormat("SELECT id, charname, data, time_of_death, is_rezzed FROM character_corpses WHERE `charid` = %i", atoi(row[0])); + auto results2 = QueryDatabase(squery); + for (auto row2 = results2.begin(); row2 != results2.end(); ++row2) { + in_datasize = results2.LengthOfColumn(2); + dbpc = (Convert::DBPlayerCorpse_Struct_temp*)row2[2]; + dbpc_c = (Convert::classic_db_temp::DBPlayerCorpse_Struct_temp*)row2[2]; + + if (dbpc == nullptr) + continue; + if (dbpc_c == nullptr) + continue; + + + /* SoF+ */ + uint32 esize1 = (sizeof(Convert::DBPlayerCorpse_Struct_temp) + (dbpc->itemcount * sizeof(Convert::player_lootitem_temp::ServerLootItem_Struct_temp))); + uint32 esize2 = (sizeof(Convert::classic_db_temp::DBPlayerCorpse_Struct_temp) + (dbpc_c->itemcount * sizeof(Convert::player_lootitem_temp::ServerLootItem_Struct_temp))); + + /* SoF */ + if (in_datasize == esize1) { + is_sof = true; + c_type = "SOF"; + } + /* Classic */ + if (in_datasize == esize2) { + is_sof = false; + c_type = "Legacy"; + } + if (in_datasize != esize2 && in_datasize != esize1) { + is_sof = false; + c_type = "NULL"; + continue; + } + std::cout << "Converting Corpse: [OK] [" << c_type << "]: " << "ID: " << atoi(row2[0]) << std::endl; + + if (is_sof){ + scquery = StringFormat("UPDATE `character_corpses` SET \n" + "`is_locked` = %d,\n" + "`exp` = %u,\n" + "`size` = %f,\n" + "`level` = %u,\n" + "`race` = %u,\n" + "`gender` = %u,\n" + "`class` = %u,\n" + "`deity` = %u,\n" + "`texture` = %u,\n" + "`helm_texture` = %u,\n" + "`copper` = %u,\n" + "`silver` = %u,\n" + "`gold` = %u,\n" + "`platinum` = %u,\n" + "`hair_color` = %u,\n" + "`beard_color` = %u,\n" + "`eye_color_1` = %u,\n" + "`eye_color_2` = %u,\n" + "`hair_style` = %u,\n" + "`face` = %u,\n" + "`beard` = %u,\n" + "`drakkin_heritage` = %u,\n" + "`drakkin_tattoo` = %u,\n" + "`drakkin_details` = %u,\n" + "`wc_1` = %u,\n" + "`wc_2` = %u,\n" + "`wc_3` = %u,\n" + "`wc_4` = %u,\n" + "`wc_5` = %u,\n" + "`wc_6` = %u,\n" + "`wc_7` = %u,\n" + "`wc_8` = %u,\n" + "`wc_9` = %u \n" + "WHERE `id` = %u \n", + dbpc->locked, + dbpc->exp, + dbpc->size, + dbpc->level, + dbpc->race, + dbpc->gender, + dbpc->class_, + dbpc->deity, + dbpc->texture, + dbpc->helmtexture, + dbpc->copper, + dbpc->silver, + dbpc->gold, + dbpc->plat, + dbpc->haircolor, + dbpc->beardcolor, + dbpc->eyecolor1, + dbpc->eyecolor2, + dbpc->hairstyle, + dbpc->face, + dbpc->beard, + dbpc->drakkin_heritage, + dbpc->drakkin_tattoo, + dbpc->drakkin_details, + dbpc->item_tint[0].color, + dbpc->item_tint[1].color, + dbpc->item_tint[2].color, + dbpc->item_tint[3].color, + dbpc->item_tint[4].color, + dbpc->item_tint[5].color, + dbpc->item_tint[6].color, + dbpc->item_tint[7].color, + dbpc->item_tint[8].color, + atoi(row2[0]) + ); + if (scquery != ""){ auto sc_results = QueryDatabase(scquery); } + + first_entry = 0; + scquery = ""; + /* Print Items */ + for (unsigned int i = 0; i < dbpc->itemcount; i++) { + if (first_entry != 1){ + scquery = StringFormat("REPLACE INTO `character_corpse_items` \n" + " (corpse_id, equip_slot, item_id, charges, aug_1, aug_2, aug_3, aug_4, aug_5, aug_6, attuned) \n" + " VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", + atoi(row2[0]), + dbpc->items[i].equipSlot, + dbpc->items[i].item_id, + dbpc->items[i].charges, + dbpc->items[i].aug1, + dbpc->items[i].aug2, + dbpc->items[i].aug3, + dbpc->items[i].aug4, + dbpc->items[i].aug5, + dbpc->items[i].aug6, + dbpc->items[i].attuned + ); + first_entry = 1; + } + else{ + scquery = scquery + StringFormat(", (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", + atoi(row2[0]), + dbpc->items[i].equipSlot, + dbpc->items[i].item_id, + dbpc->items[i].charges, + dbpc->items[i].aug1, + dbpc->items[i].aug2, + dbpc->items[i].aug3, + dbpc->items[i].aug4, + dbpc->items[i].aug5, + dbpc->items[i].aug6, + dbpc->items[i].attuned + ); + } + } + if (scquery != ""){ auto sc_results = QueryDatabase(scquery); } + } + else{ + /* Classic Converter */ + scquery = StringFormat("UPDATE `character_corpses` SET \n" + "`is_locked` = %d,\n" + "`exp` = %u,\n" + "`size` = %f,\n" + "`level` = %u,\n" + "`race` = %u,\n" + "`gender` = %u,\n" + "`class` = %u,\n" + "`deity` = %u,\n" + "`texture` = %u,\n" + "`helm_texture` = %u,\n" + "`copper` = %u,\n" + "`silver` = %u,\n" + "`gold` = %u,\n" + "`platinum` = %u,\n" + "`hair_color` = %u,\n" + "`beard_color` = %u,\n" + "`eye_color_1` = %u,\n" + "`eye_color_2` = %u,\n" + "`hair_style` = %u,\n" + "`face` = %u,\n" + "`beard` = %u,\n" + "`wc_1` = %u,\n" + "`wc_2` = %u,\n" + "`wc_3` = %u,\n" + "`wc_4` = %u,\n" + "`wc_5` = %u,\n" + "`wc_6` = %u,\n" + "`wc_7` = %u,\n" + "`wc_8` = %u,\n" + "`wc_9` = %u \n" + "WHERE `id` = %u \n", + dbpc_c->locked, + dbpc_c->exp, + dbpc_c->size, + dbpc_c->level, + dbpc_c->race, + dbpc_c->gender, + dbpc_c->class_, + dbpc_c->deity, + dbpc_c->texture, + dbpc_c->helmtexture, + dbpc_c->copper, + dbpc_c->silver, + dbpc_c->gold, + dbpc_c->plat, + dbpc_c->haircolor, + dbpc_c->beardcolor, + dbpc_c->eyecolor1, + dbpc_c->eyecolor2, + dbpc_c->hairstyle, + dbpc_c->face, + dbpc_c->beard, + dbpc_c->item_tint[0].color, + dbpc_c->item_tint[1].color, + dbpc_c->item_tint[2].color, + dbpc_c->item_tint[3].color, + dbpc_c->item_tint[4].color, + dbpc_c->item_tint[5].color, + dbpc_c->item_tint[6].color, + dbpc_c->item_tint[7].color, + dbpc_c->item_tint[8].color, + atoi(row2[0]) + ); + if (scquery != ""){ auto sc_results = QueryDatabase(scquery); } + + first_entry = 0; + scquery = ""; + + /* Print Items */ + for (unsigned int i = 0; i < dbpc_c->itemcount; i++) { + if (first_entry != 1){ + scquery = StringFormat("REPLACE INTO `character_corpse_items` \n" + " (corpse_id, equip_slot, item_id, charges, aug_1, aug_2, aug_3, aug_4, aug_5, aug_6, attuned) \n" + " VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", + atoi(row2[0]), + dbpc_c->items[i].equipSlot, + dbpc_c->items[i].item_id, + dbpc_c->items[i].charges, + dbpc_c->items[i].aug1, + dbpc_c->items[i].aug2, + dbpc_c->items[i].aug3, + dbpc_c->items[i].aug4, + dbpc_c->items[i].aug5, + dbpc_c->items[i].aug6, + dbpc_c->items[i].attuned + ); + first_entry = 1; + } + else{ + scquery = scquery + StringFormat(", (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", + atoi(row2[0]), + dbpc_c->items[i].equipSlot, + dbpc_c->items[i].item_id, + dbpc_c->items[i].charges, + dbpc_c->items[i].aug1, + dbpc_c->items[i].aug2, + dbpc_c->items[i].aug3, + dbpc_c->items[i].aug4, + dbpc_c->items[i].aug5, + dbpc_c->items[i].aug6, + dbpc_c->items[i].attuned + ); + } + } + if (scquery != ""){ auto sc_results = QueryDatabase(scquery); } + } + } + } + QueryDatabase(StringFormat("ALTER TABLE `character_corpses` DROP COLUMN `data`")); + } + return true; +}