Fix void Database::GetCharName(uint32 char_id, char* name)

Increased MAX_PP_SPELLBOOK to 720 for UF/RoF
Increased MAX_PP_MEMSPELL to 12
Implemented up to 12 spell slots
Fix for public_note default value in bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank)
Updated all CastSpell entries to use the appropriate slot type defines located now in zone/common.h
Fixed Guild Loading from character_data
Fixed #guild list
Refactored Merchantlist loading
Refactored Temp Merchantlist loading
Gutted most of dbasync

Added:
LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot);
SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);

Removed Zone::LoadTempMerchantData_result(MYSQL_RES* result)
Removed Zone::LoadMerchantData_result(MYSQL_RES* result)
Removed SharedDatabase::GetPlayerProfile
Removed SharedDatabase::SetPlayerProfile
Removed SharedDatabase::SetPlayerProfile_MQ
Removed Zone::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) from zone.cpp
This commit is contained in:
Akkadius 2014-08-31 17:52:43 -05:00
parent f8439fd6e6
commit ca430e2494
22 changed files with 423 additions and 521 deletions

View File

@ -758,17 +758,18 @@ void Database::GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID
void Database::GetCharName(uint32 char_id, char* name) {
std::string query = StringFormat("SELECT name FROM character_ WHERE id='%i'", char_id);
std::string query = StringFormat("SELECT `name` FROM `character_data` WHERE id='%i'", char_id);
auto results = QueryDatabase(query);
if (!results.Success())
{
if (!results.Success()) {
std::cerr << "Error in GetCharName query '" << query << "' " << results.ErrorMessage() << std::endl;
return;
return;
}
auto row = results.begin();
strcpy(name, row[0]);
for (auto row = results.begin(); row != results.end(); ++row) {
strcpy(name, row[0]);
}
}
static inline void loadbar(unsigned int x, unsigned int n, unsigned int w = 50) {
@ -849,7 +850,7 @@ bool Database::CheckDatabaseConversions() {
" `level2` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, "
" `anon` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, "
" `gm` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, "
" `intoxication` int(11) UNSIGNED NOT NULL, "
" `intoxication` int(11) UNSIGNED NOT NULL DEFAULT 0, "
" `hair_color` 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, "
@ -885,9 +886,9 @@ bool Database::CheckDatabaseConversions() {
" `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, "
" `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, "
" `toxicity` int(11) NOT NULL DEFAULT 0, "
" `hunger_level` int(11) NOT NULL DEFAULT 0, "
" `thirst_level` int(11) NOT NULL DEFAULT 0, "
" `ability_up` int(11) UNSIGNED NOT NULL DEFAULT 0, "
" `zone_id` int(11) UNSIGNED NOT NULL DEFAULT 0, "
" `zone_instance` int(11) UNSIGNED NOT NULL DEFAULT 0, "
@ -1092,7 +1093,7 @@ bool Database::CheckDatabaseConversions() {
// querylen = MakeAnyLenString(&query, "SELECT `id` FROM `character_` WHERE `id` = 61238");
int char_iter_count = 0;
querylen = MakeAnyLenString(&query, "SELECT `id` FROM `character_` WHERE `id` >= 61238 LIMIT 1");
querylen = MakeAnyLenString(&query, "SELECT `id` FROM `character_` WHERE `id` >= 61238 LIMIT 100");
if (RunQuery(query, querylen, errbuf, &result)) {
safe_delete_array(query);
while (row = mysql_fetch_row(result)) {
@ -1147,6 +1148,8 @@ bool Database::CheckDatabaseConversions() {
);
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` ("

View File

@ -801,8 +801,8 @@ struct SuspendedMinion_Struct
** OpCode: 0x006a
*/
static const uint32 MAX_PP_LANGUAGE = 28;
static const uint32 MAX_PP_SPELLBOOK = 480; // Increased to 480 to support SoF
static const uint32 MAX_PP_MEMSPELL = 9;
static const uint32 MAX_PP_SPELLBOOK = 720; // Increased to 480 to support SoF
static const uint32 MAX_PP_MEMSPELL = 12;
static const uint32 MAX_PP_SKILL = _SkillPacketArraySize; // 100 - actual skills buffer size
static const uint32 MAX_PP_AA_ARRAY = 240;
static const uint32 MAX_GROUP_MEMBERS = 6;

View File

@ -751,7 +751,7 @@ bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank) {
std::string query;
if(guild_id != GUILD_NONE) {
query = StringFormat("REPLACE INTO guild_members (char_id,guild_id,rank) VALUES(%d,%d,%d)", charid, guild_id, rank);
query = StringFormat("REPLACE INTO guild_members (char_id,guild_id,rank,public_note) VALUES(%d,%d,%d,'')", charid, guild_id, rank);
auto results = m_db->QueryDatabase(query);
if (!results.Success()) {

View File

@ -479,7 +479,6 @@ ENCODE(OP_PlayerProfile) {
uint32 r;
eq->available_slots=0xffffffff;
memset(eq->unknown06284, 0xff, sizeof(eq->unknown06284));
memset(eq->unknown07284, 0xff, sizeof(eq->unknown07284));
// OUT(checksum);
@ -546,7 +545,7 @@ ENCODE(OP_PlayerProfile) {
OUT(gold);
OUT(silver);
OUT(copper);
OUT(platinum_cursor);
OUT(platinum_cursor);
OUT(gold_cursor);
OUT(silver_cursor);
OUT(copper_cursor);

View File

@ -766,7 +766,7 @@ struct BindStruct {
** OpCode: 0x006a
*/
static const uint32 MAX_PP_LANGUAGE = 25; //
static const uint32 MAX_PP_SPELLBOOK = 480; // Confirmed 60 pages on Underfoot now
static const uint32 MAX_PP_SPELLBOOK = 720; // Confirmed 60 pages on Underfoot now
static const uint32 MAX_PP_MEMSPELL = 10; //was 9 now 10 on Underfoot
static const uint32 MAX_PP_SKILL = _SkillPacketArraySize; // 100 - actual skills buffer size
static const uint32 MAX_PP_AA_ARRAY = 300; //was 299
@ -879,7 +879,6 @@ struct PlayerProfile_Struct
/*04216*/ uint8 face; // Player face - Actually uint32?
/*04217*/ uint8 unknown04217[147]; // was [175]
/*04364*/ uint32 spell_book[MAX_PP_SPELLBOOK]; // List of the Spells in spellbook 720 = 90 pages [2880] was [1920]
/*06284*/ uint8 unknown06284[960]; // Spacer for the end of the book for now (pages 60 to 90)
/*07244*/ uint32 mem_spells[MAX_PP_MEMSPELL]; // List of spells memorized
/*07284*/ uint8 unknown07284[28]; //#### uint8 unknown04396[32]; in Titanium ####[28]
/*07312*/ uint32 platinum; // Platinum Pieces on player

View File

@ -1209,106 +1209,6 @@ bool SharedDatabase::LoadNPCFactionLists() {
return true;
}
// Get the player profile and inventory for the given account "account_id" and
// character name "name". Return true if the character was found, otherwise false.
// False will also be returned if there is a database error.
bool SharedDatabase::GetPlayerProfile(uint32 account_id, char* name, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, char* current_zone, uint32 *current_instance) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES* result;
MYSQL_ROW row;
bool ret = false;
unsigned long* lengths;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT profile,zonename,x,y,z,extprofile,instanceid FROM character_ WHERE account_id=%i AND name='%s'", account_id, name), errbuf, &result)) {
if (mysql_num_rows(result) == 1) {
row = mysql_fetch_row(result);
lengths = mysql_fetch_lengths(result);
if (lengths[0] == sizeof(PlayerProfile_Struct)) {
memcpy(pp, row[0], sizeof(PlayerProfile_Struct));
if (current_zone)
strcpy(current_zone, row[1]);
pp->zone_id = GetZoneID(row[1]);
pp->x = atof(row[2]);
pp->y = atof(row[3]);
pp->z = atof(row[4]);
pp->zoneInstance = atoi(row[6]);
if (pp->x == -1 && pp->y == -1 && pp->z == -1)
GetSafePoints(pp->zone_id, GetInstanceVersion(pp->zoneInstance), &pp->x, &pp->y, &pp->z);
if(current_instance)
*current_instance = pp->zoneInstance;
if(ext) {
//SetExtendedProfile handles any conversion
SetExtendedProfile(ext, row[5], lengths[5]);
}
// Retrieve character inventory
ret = GetInventory(account_id, name, inv);
}
else {
LogFile->write(EQEMuLog::Error, "Player profile length mismatch in GetPlayerProfile. Found: %i, Expected: %i",
lengths[0], sizeof(PlayerProfile_Struct));
}
}
mysql_free_result(result);
}
else {
LogFile->write(EQEMuLog::Error, "GetPlayerProfile query '%s' %s", query, errbuf);
}
safe_delete_array(query);
return ret;
}
bool SharedDatabase::SetPlayerProfile(uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
uint32 affected_rows = 0;
bool ret = false;
clock_t t = std::clock(); /* Function timer start */
if (RunQuery(query, SetPlayerProfile_MQ(&query, account_id, charid, pp, inv, ext, current_zone, current_instance, MaxXTargets), errbuf, 0, &affected_rows)) {
ret = (affected_rows != 0);
}
LogFile->write(EQEMuLog::Status, "SharedDatabase::SetPlayerProfile SetPlayerProfile_MQ done... Took %f seconds", ((float)(std::clock() - t)) / CLOCKS_PER_SEC);
if (!ret) {
LogFile->write(EQEMuLog::Error, "SetPlayerProfile query '%s' %s", query, errbuf);
}
safe_delete_array(query);
return ret;
}
// Generate SQL for updating player profile
uint32 SharedDatabase::SetPlayerProfile_MQ(char** query, uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets) {
*query = new char[396 + sizeof(PlayerProfile_Struct)*2 + sizeof(ExtendedProfile_Struct)*2 + 4];
char* end = *query;
if (!current_zone)
current_zone = pp->zone_id;
if (!current_instance)
current_instance = pp->zoneInstance;
if(strlen(pp->name) == 0) /* Sanity check in case pp never loaded */
return false;
end += sprintf(end, "UPDATE character_ SET timelaston=unix_timestamp(now()),name=\'%s\', zonename=\'%s\', zoneid=%u, instanceid=%u, x = %f, y = %f, z = %f, profile=\'", pp->name, GetZoneName(current_zone), current_zone, current_instance, pp->x, pp->y, pp->z);
end += DoEscapeString(end, (char*)pp, sizeof(PlayerProfile_Struct));
end += sprintf(end,"\', extprofile=\'");
end += DoEscapeString(end, (char*)ext, sizeof(ExtendedProfile_Struct));
end += sprintf(end,"\',class=%d,level=%d,xtargets=%u WHERE id=%u", pp->class_, pp->level, MaxXTargets, charid);
return (uint32) (end - (*query));
}
// Create appropriate ItemInst class
ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5)
{

View File

@ -40,9 +40,6 @@ public:
bool SetGMSpeed(uint32 account_id, uint8 gmspeed);
uint8 GetGMSpeed(uint32 account_id);
bool SetHideMe(uint32 account_id, uint8 hideme);
bool GetPlayerProfile(uint32 account_id, char* name, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, char* current_zone = 0, uint32 *current_instance = 0);
bool SetPlayerProfile(uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets);
uint32 SetPlayerProfile_MQ(char** query, uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets);
int32 DeleteStalePlayerCorpses();
int32 DeleteStalePlayerBackups();
void GetPlayerInspectMessage(char* playername, InspectMessage_Struct* message);

View File

@ -41,11 +41,12 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct*
MYSQL_ROW row;
Inventory *inv;
/* Initialize Variables */
for (int i=0; i<10; i++) {
strcpy(cs->name[i], "<none>");
cs->zone[i] = 0;
cs->level[i] = 0;
cs->tutorial[i] = 0;
cs->tutorial[i] = 0;
cs->gohome[i] = 0;
}
@ -165,7 +166,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct*
if(result2) {
row2 = mysql_fetch_row(result2);
ExtendedProfile_Struct* ext = (ExtendedProfile_Struct*)row2[0];
SetPlayerProfile(account_id,char_id,pp,inv,ext, 0, 0, 5);
// SetPlayerProfile(account_id,char_id,pp,inv,ext, 0, 0, 5);
}
mysql_free_result(result2);
}

View File

@ -300,7 +300,7 @@ void Client::ActivateAA(aaID activate){
return;
}
} else {
if(!CastSpell(caa->spell_id, target_id, 10, -1, -1, 0, -1, AATimerID + pTimerAAStart, timer_base, 1)) {
if (!CastSpell(caa->spell_id, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, AATimerID + pTimerAAStart, timer_base, 1)) {
//Reset on failed cast
SendAATimer(AATimerID, 0, 0xFFFFFF);
Message_StringID(15,ABILITY_FAILED);
@ -525,7 +525,7 @@ void Client::HandleAAAction(aaID activate) {
//cast the spell, if we have one
if(IsValidSpell(spell_id)) {
int aatid = GetAATimerID(activate);
if(!CastSpell(spell_id, target_id , 10, -1, -1, 0, -1, pTimerAAStart + aatid , CalcAAReuseTimer(caa), 1)) {
if (!CastSpell(spell_id, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, pTimerAAStart + aatid, CalcAAReuseTimer(caa), 1)) {
SendAATimer(aatid, 0, 0xFFFFFF);
Message_StringID(15,ABILITY_FAILED);
p_timers.Clear(&database, pTimerAAStart + aatid);
@ -1822,8 +1822,7 @@ void ZoneDatabase::LoadAAs(SendAA_Struct **load){
}
AALevelCost_Struct aalcs;
for (auto row = results.begin(); row != results.end(); ++row)
{
for (auto row = results.begin(); row != results.end(); ++row) {
aalcs.Level = atoi(row[1]);
aalcs.Cost = atoi(row[2]);
AARequiredLevelAndCost[atoi(row[0])] = aalcs;

View File

@ -311,11 +311,11 @@ public:
virtual float GetAOERange(uint16 spell_id);
virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100);
virtual void DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caster_level, Mob* caster = 0);
virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr);
virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr);
virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar);
virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster);
virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction);
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF);
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF);
// Bot Action Command Methods
bool MesmerizeTarget(Mob* target);

View File

@ -545,7 +545,7 @@ bool Client::Save(uint8 iCommitNow) {
database.SaveCharacterCurrency(this->CharacterID(), &m_pp);
/* Save Character AA */
SaveAA();
// SaveAA();
/* Save Character Buffs */
database.SaveBuffs(this);
@ -591,31 +591,31 @@ bool Client::Save(uint8 iCommitNow) {
/* Save Character Data */
database.SaveCharacterData(this->CharacterID(), this->AccountID(), &m_pp);
if (iCommitNow <= 1) {
char* query = 0;
uint32_breakdown workpt;
workpt.b4() = DBA_b4_Entity;
workpt.w2_3() = GetID();
workpt.b1() = DBA_b1_Entity_Client_Save;
DBAsyncWork* dbaw = new DBAsyncWork(&database, &MTdbafq, workpt, DBAsync::Write, 0xFFFFFFFF);
dbaw->AddQuery(iCommitNow == 0 ? true : false, &query, database.SetPlayerProfile_MQ(&query, account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets), false);
if (iCommitNow == 0){
pQueuedSaveWorkID = dbasync->AddWork(&dbaw, 2500);
}
else {
dbasync->AddWork(&dbaw, 0);
SaveBackup();
}
safe_delete_array(query);
return true;
}
else if (database.SetPlayerProfile(account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets)) {
SaveBackup();
}
else {
std::cerr << "Failed to update player profile" << std::endl;
return false;
}
// if (iCommitNow <= 1) {
// char* query = 0;
// uint32_breakdown workpt;
// workpt.b4() = DBA_b4_Entity;
// workpt.w2_3() = GetID();
// workpt.b1() = DBA_b1_Entity_Client_Save;
// DBAsyncWork* dbaw = new DBAsyncWork(&database, &MTdbafq, workpt, DBAsync::Write, 0xFFFFFFFF);
// dbaw->AddQuery(iCommitNow == 0 ? true : false, &query, database.SetPlayerProfile_MQ(&query, account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets), false);
// if (iCommitNow == 0){
// pQueuedSaveWorkID = dbasync->AddWork(&dbaw, 2500);
// }
// else {
// dbasync->AddWork(&dbaw, 0);
// SaveBackup();
// }
// safe_delete_array(query);
// return true;
// }
// else if (database.SetPlayerProfile(account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets)) {
// SaveBackup();
// }
// else {
// std::cerr << "Failed to update player profile" << std::endl;
// return false;
// }
/* Mirror Character Data */
database.StoreCharacterLookup(this->CharacterID());

View File

@ -37,6 +37,7 @@ class Client;
#include "../common/item_struct.h"
#include "../common/clientversions.h"
#include "common.h"
#include "zonedb.h"
#include "errno.h"
#include "mob.h"
@ -102,11 +103,6 @@ enum { //scribing argument to MemorizeSpell
memSpellSpellbar = 3
};
#define USE_ITEM_SPELL_SLOT 10
#define POTION_BELT_SPELL_SLOT 11
#define DISCIPLINE_SPELL_SLOT 10
#define ABILITY_SPELL_SLOT 9
//Modes for the zoning state of the client.
typedef enum {
ZoneToSafeCoords, // Always send ZonePlayerToBind_Struct to client: Succor/Evac
@ -239,7 +235,6 @@ public:
void KeyRingList();
virtual bool IsClient() const { return true; }
virtual void DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw);
bool FinishConnState2(DBAsyncWork* dbaw);
void CompleteConnect();
bool TryStacking(ItemInst* item, uint8 type = ItemPacketTrade, bool try_worn = true, bool try_cursor = true);
void SendTraderPacket(Client* trader, uint32 Unknown72 = 51);

View File

@ -506,19 +506,18 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
if(strlen(cze->char_name) > 63)
return;
conn_state = ReceivedZoneEntry;
conn_state = ReceivedZoneEntry;
ClientVersion = Connection()->ClientVersion();
ClientVersionBit = 1 << (ClientVersion - 1);
// Antighost code
// tmp var is so the search doesnt find this object
/* Antighost code
tmp var is so the search doesnt find this object
*/
Client* client = entity_list.GetClientByName(cze->char_name);
if (!zone->GetAuth(ip, cze->char_name, &WID, &account_id, &character_id, &admin, lskey, &tellsoff)) {
LogFile->write(EQEMuLog::Error, "GetAuth() returned false kicking client");
if (client != 0)
{
if (client != 0) {
client->Save();
client->Kick();
}
@ -527,7 +526,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
return;
}
strcpy(name, cze->char_name);
/* Check for Client Spoofing */
if (client != 0) {
struct in_addr ghost_addr;
ghost_addr.s_addr = eqs->GetRemoteIP();
@ -554,8 +555,10 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
uint32 cid = CharacterID();
character_id = cid;
/* Flush and reload factions */
database.RemoveTempFactions(this);
database.LoadCharacterFactionValues(cid, factionvalues);
/* Load Character Account Data: Temp until I move */
query = StringFormat("SELECT `status`, `name`, `lsaccount_id`, `gmspeed`, `revoked`, `hideme` FROM `account` WHERE `id` = %i", this->AccountID());
auto results = database.QueryDatabase(query);
@ -565,74 +568,75 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
if (lsaccountid && atoi(row[2]) > 0){ lsaccountid = atoi(row[2]); }
else{ lsaccountid = 0; }
if (gmspeed){ gmspeed = atoi(row[3]); }
if (revoked){ revoked = atoi(row[4]); }
if (revoked){ revoked = atoi(row[4]); }
if (gmhideme){ gmhideme = atoi(row[5]); }
if (account_creation){ account_creation = atoul(row[6]); }
}
/* Load Character Legacy Data: Temp until I move */
query = StringFormat("id,profile,zonename,x,y,z,guild_id,rank,extprofile,class,level,lfp,lfg,instanceid,xtargets,firstlogon FROM character_ LEFT JOIN guild_members ON id=char_id WHERE id=%i", cid);
query = StringFormat("SELECT id,profile,zonename,x,y,z,guild_id,rank,extprofile,class,level,lfp,lfg,instanceid,xtargets,firstlogon FROM character_ LEFT JOIN guild_members ON id=char_id WHERE id=%i", cid);
results = database.QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) {
m_pp.lastlogin = time(nullptr);
if (row[6]){
guild_id = atoi(row[6]);
if (guildrank) {
if (row[7] != nullptr){ guildrank = atoi(row[7]); }
else{ guildrank = GUILD_RANK_NONE; }
}
}
if (RuleB(Character, SharedBankPlat))
m_pp.platinum_shared = database.GetSharedPlatinum(database.GetAccountIDByChar(cid));
if (guildrank) {
if (row[7] != nullptr)
guildrank = atoi(row[7]);
else
guildrank = GUILD_RANK_NONE;
}
// if (ext) { SetExtendedProfile(ext, row[8], lengths[8]); }
if (level){ level = atoi(row[10]); }
if (LFP){ LFP = atoi(row[11]); }
if (LFG){ LFG = atoi(row[12]); }
if (firstlogon){ firstlogon = atoi(row[15]); }
}
/* Load Character Inventory */
loaditems = database.GetInventory(cid, &m_inv);
/* Load Character Currency into PP */
database.LoadCharacterCurrency(cid, &m_pp);
/* Load Character Data from DB into PP */
database.LoadCharacterData(cid, &m_pp);
/* Move to another method when can, this is pointless... */
database.GetPlayerInspectMessage(m_pp.name, &m_inspect_message);
/* Load Character Currency */
database.LoadCharacterCurrency(cid, &m_pp);
/* Load Character Skills */
database.LoadCharacterSkills(cid, &m_pp);
/* Load Character Disciplines */
database.LoadCharacterDisciplines(cid, &m_pp);
loaditems = database.GetInventory(cid, &m_inv); /* Load Character Inventory */
database.LoadCharacterBindPoint(cid, &m_pp); /* Load Character Bind */
database.LoadCharacterCurrency(cid, &m_pp); /* Load Character Currency into PP */
database.LoadCharacterData(cid, &m_pp); /* Load Character Data from DB into PP */
database.GetPlayerInspectMessage(m_pp.name, &m_inspect_message); /* Move to another method when can, this is pointless... */
database.LoadCharacterCurrency(cid, &m_pp); /* Load Character Currency */
database.LoadCharacterSkills(cid, &m_pp); /* Load Character Skills */
database.LoadCharacterLanguages(cid, &m_pp); /* Load Character Languages */
database.LoadCharacterSpellBook(cid, &m_pp); /* Load Character Spell Book */
database.LoadCharacterMemmedSpells(cid, &m_pp); /* Load Character Memorized Spells */
database.LoadCharacterDisciplines(cid, &m_pp); /* Load Character Disciplines */
/* If GM, not trackable */
if (gmhideme) { trackable = false; }
/* Set Con State for Reporting */
conn_state = PlayerProfileLoaded;
/* Set Current zone */
// m_pp.zone_id = zone->GetZoneID();
// m_pp.zoneInstance = zone->GetInstanceID();
/* Set Total Seconds Played */
TotalSecondsPlayed = m_pp.timePlayedMin * 60;
/* Set Max AA XP */
max_AAXP = RuleI(AA, ExpPerPoint);
/* If we can maintain intoxication across zones, check for it */
if (!RuleB(Character, MaintainIntoxicationAcrossZones))
m_pp.intoxication = 0;
m_pp.intoxication = 0;
strcpy(name, m_pp.name);
strcpy(lastname, m_pp.last_name);
/* If PP is set to wierd coordinates */
if ((m_pp.x == -1 && m_pp.y == -1 && m_pp.z == -1) || (m_pp.x == -2 && m_pp.y == -2 && m_pp.z == -2)) {
m_pp.x = zone->safe_x();
m_pp.y = zone->safe_y();
m_pp.z = zone->safe_z();
}
}
/* If too far below ground, then fix */
float ground_z = GetGroundZ(m_pp.x, m_pp.y, m_pp.z);
if (m_pp.z < (ground_z - 500))
m_pp.z = ground_z;
class_ = m_pp.class_;
/* Set Mob variables for spawn */
class_ = m_pp.class_;
level = m_pp.level;
x_pos = m_pp.x;
y_pos = m_pp.y;
@ -642,7 +646,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
base_race = m_pp.race;
gender = m_pp.gender;
base_gender = m_pp.gender;
deity = m_pp.deity; //FYI: DEITY_AGNOSTIC = 396; still valid?
deity = m_pp.deity;
haircolor = m_pp.haircolor;
beardcolor = m_pp.beardcolor;
eyecolor1 = m_pp.eyecolor1;
@ -654,42 +658,41 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
drakkin_tattoo = m_pp.drakkin_tattoo;
drakkin_details = m_pp.drakkin_details;
/* If GM not set in DB, and does not meet min status to be GM, reset */
if (m_pp.gm && admin < minStatusToBeGM)
m_pp.gm = 0;
/* Load Guild */
if (!IsInAGuild()) { m_pp.guild_id = GUILD_NONE; }
else {
m_pp.guild_id = GuildID();
m_pp.guild_id = GuildID();
if (zone->GetZoneID() == RuleI(World, GuildBankZoneID))
GuildBanker = (guild_mgr.IsGuildLeader(GuildID(), CharacterID()) || guild_mgr.GetBankerFlag(CharacterID()));
}
m_pp.guildbanker = GuildBanker;
switch (race)
{
case OGRE:
size = 9; break;
case TROLL:
size = 8; break;
case VAHSHIR: case BARBARIAN:
size = 7; break;
case HUMAN: case HIGH_ELF: case ERUDITE: case IKSAR: case DRAKKIN:
size = 6; break;
case HALF_ELF:
size = 5.5; break;
case WOOD_ELF: case DARK_ELF: case FROGLOK:
size = 5; break;
case DWARF:
size = 4; break;
case HALFLING:
size = 3.5; break;
case GNOME:
size = 3; break;
default:
size = 0;
case OGRE:
size = 9; break;
case TROLL:
size = 8; break;
case VAHSHIR: case BARBARIAN:
size = 7; break;
case HUMAN: case HIGH_ELF: case ERUDITE: case IKSAR: case DRAKKIN:
size = 6; break;
case HALF_ELF:
size = 5.5; break;
case WOOD_ELF: case DARK_ELF: case FROGLOK:
size = 5; break;
case DWARF:
size = 4; break;
case HALFLING:
size = 3.5; break;
case GNOME:
size = 3; break;
default:
size = 0;
}
/* Check for Invalid points */
@ -700,6 +703,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
if (m_pp.ldon_points_tak < 0 || m_pp.ldon_points_tak > 2000000000){ m_pp.ldon_points_tak = 0; }
if (m_pp.ldon_points_available < 0 || m_pp.ldon_points_available > 2000000000){ m_pp.ldon_points_available = 0; }
/* Set Swimming Skill 100 by default if under 100 */
if (GetSkill(SkillSwimming) < 100)
SetSkill(SkillSwimming, 100);
@ -859,29 +863,20 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
Mob::SetMana(m_pp.mana);
SetEndurance(m_pp.endurance);
if (IsLFP()) {
// Update LFP in case any (or all) of our group disbanded while we were zoning.
UpdateLFP();
}
if (m_pp.z <= zone->newzone_data.underworld) {
m_pp.x = zone->newzone_data.safe_x;
m_pp.y = zone->newzone_data.safe_y;
m_pp.z = zone->newzone_data.safe_z;
}
/* Update LFP in case any (or all) of our group disbanded while we were zoning. */
if (IsLFP()) { UpdateLFP(); }
/* Get Expansions from variables table and ship via PP */
char val[20] = { 0 };
if (database.GetVariable("Expansions", val, 20))
m_pp.expansions = atoi(val);
else
m_pp.expansions = 0x3FF;
if (database.GetVariable("Expansions", val, 20)){ m_pp.expansions = atoi(val); }
else{ m_pp.expansions = 0x3FF; }
p_timers.SetCharID(CharacterID());
if (!p_timers.Load(&database)) {
LogFile->write(EQEMuLog::Error, "Unable to load ability timers from the database for %s (%i)!", GetCleanName(), CharacterID());
}
/* Load Spell Slot Refresh from Currently Memoried Spells */
for (unsigned int i = 0; i < MAX_PP_MEMSPELL; ++i)
if (IsValidSpell(m_pp.mem_spells[i]))
m_pp.spellSlotRefresh[i] = p_timers.GetRemainingTime(pTimerSpellStart + m_pp.mem_spells[i]) * 1000;
@ -904,14 +899,12 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
m_inv.dumpEntireInventory();
#endif
//lost in current PP
// strcpy(m_pp.servername,"eqemulator");
m_pp.air_remaining = 60; //Reset to max so they dont drown on zone in if its underwater
/* Reset to max so they dont drown on zone in if its underwater */
m_pp.air_remaining = 60;
/* Check for PVP Zone status*/
if (zone->IsPVPZone())
m_pp.pvp = 1;
/* Time entitled on Account: Move to account */
m_pp.timeentitledonaccount = database.GetTotalTimeEntitledOnAccount(AccountID()) / 1440;
/* Reset rest timer if the durations have been lowered in the database */
@ -934,9 +927,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
database.LoadPetInfo(this);
/*
This was moved before the spawn packets are sent
in hopes that it adds more consistency...
Remake pet
This was moved before the spawn packets are sent
in hopes that it adds more consistency...
Remake pet
*/
if (m_petinfo.SpellID > 1 && !GetPet() && m_petinfo.SpellID <= SPDAT_RECORDS)
{
@ -985,16 +978,15 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
}
/*
Character Inventory Packet
this is not quite where live sends inventory, they do it after tribute
Character Inventory Packet
this is not quite where live sends inventory, they do it after tribute
*/
if (loaditems) { //dont load if a length error occurs
if (loaditems) { /* Dont load if a length error occurs */
BulkSendInventoryItems();
// Send stuff on the cursor which isnt sent in bulk
/* Send stuff on the cursor which isnt sent in bulk */
iter_queue it;
for (it = m_inv.cursor_begin(); it != m_inv.cursor_end(); ++it) {
// First item cursor is sent in bulk inventory packet
/* First item cursor is sent in bulk inventory packet */
if (it == m_inv.cursor_begin())
continue;
const ItemInst *inst = *it;
@ -1005,15 +997,13 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
/* Task Packets */
LoadClientTaskState();
if (GetClientVersion() >= EQClientRoF)
{
if (GetClientVersion() >= EQClientRoF) {
outapp = new EQApplicationPacket(OP_ReqNewZone, 0);
Handle_Connect_OP_ReqNewZone(outapp);
safe_delete(outapp);
}
if (ClientVersionBit & BIT_UnderfootAndLater)
{
if (ClientVersionBit & BIT_UnderfootAndLater) {
outapp = new EQApplicationPacket(OP_XTargetResponse, 8);
outapp->WriteUInt32(GetMaxXTargets());
outapp->WriteUInt32(0);
@ -1021,17 +1011,16 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
}
/*
Weather Packet
This shouldent be moved, this seems to be what the client
uses to advance to the next state (sending ReqNewZone)
Weather Packet
This shouldent be moved, this seems to be what the client
uses to advance to the next state (sending ReqNewZone)
*/
outapp = new EQApplicationPacket(OP_Weather, 12);
Weather_Struct *ws = (Weather_Struct *)outapp->pBuffer;
ws->val1 = 0x000000FF;
if (zone->zone_weather == 1)
ws->type = 0x31; // Rain
if (zone->zone_weather == 2)
{
if (zone->zone_weather == 2) {
outapp->pBuffer[8] = 0x01;
ws->type = 0x02;
}
@ -2585,7 +2574,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
}
if(i == 0) {
CastSpell(item->Click.Effect, target_id, 10, item->CastTime, 0, 0, slot_id);
CastSpell(item->Click.Effect, target_id, USE_ITEM_SPELL_SLOT, item->CastTime, 0, 0, slot_id);
}
}
else
@ -2612,7 +2601,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
}
if(i == 0) {
CastSpell(augitem->Click.Effect, target_id, 10, augitem->CastTime, 0, 0, slot_id);
CastSpell(augitem->Click.Effect, target_id, USE_ITEM_SPELL_SLOT, augitem->CastTime, 0, 0, slot_id);
}
}
else
@ -4947,6 +4936,7 @@ void Client::Handle_OP_MemorizeSpell(const EQApplicationPacket *app)
void Client::Handle_OP_SwapSpell(const EQApplicationPacket *app)
{
if (app->size != sizeof(SwapSpell_Struct)) {
std::cout << "Wrong size on OP_SwapSpell. Got: " << app->size << ", Expected: " << sizeof(SwapSpell_Struct) << std::endl;
return;
@ -4958,8 +4948,13 @@ void Client::Handle_OP_SwapSpell(const EQApplicationPacket *app)
return;
swapspelltemp = m_pp.spell_book[swapspell->from_slot];
if (swapspelltemp < 0){
return;
}
m_pp.spell_book[swapspell->from_slot] = m_pp.spell_book[swapspell->to_slot];
m_pp.spell_book[swapspell->to_slot] = swapspelltemp;
database.SaveCharacterSpellSwap(this->CharacterID(), swapspelltemp, swapspell->from_slot, swapspell->to_slot);
QueuePacket(app);
return;
@ -4991,7 +4986,27 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
#endif
LogFile->write(EQEMuLog::Debug, "OP CastSpell: slot=%d, spell=%d, target=%d, inv=%lx", castspell->slot, castspell->spell_id, castspell->target_id, (unsigned long)castspell->inventoryslot);
if ((castspell->slot == USE_ITEM_SPELL_SLOT) || (castspell->slot == POTION_BELT_SPELL_SLOT)) // ITEM or POTION cast
std::cout << "OP_CastSpell " << castspell->slot << " spell " << castspell->spell_id << " inventory slot " << castspell->inventoryslot << "\n" << std::endl;
/* Memorized Spell */
if (m_pp.mem_spells[castspell->slot] && m_pp.mem_spells[castspell->slot] == castspell->spell_id){
uint16 spell_to_cast = 0;
if (castspell->slot < MAX_PP_MEMSPELL) {
spell_to_cast = m_pp.mem_spells[castspell->slot];
if (spell_to_cast != castspell->spell_id) {
InterruptSpell(castspell->spell_id); //CHEATER!!!
return;
}
}
else if (castspell->slot >= MAX_PP_MEMSPELL) {
InterruptSpell();
return;
}
CastSpell(spell_to_cast, castspell->target_id, castspell->slot);
}
/* Spell Slot or Potion Belt Slot */
else if ((castspell->slot == USE_ITEM_SPELL_SLOT) || (castspell->slot == POTION_BELT_SPELL_SLOT)) // ITEM or POTION cast
{
//discipline, using the item spell slot
if (castspell->inventoryslot == 0xFFFFFFFF) {
@ -5070,14 +5085,16 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
InterruptSpell(castspell->spell_id);
}
}
else if (castspell->slot == DISCIPLINE_SPELL_SLOT) { // DISCIPLINE cast
/* Discipline */
else if (castspell->slot == DISCIPLINE_SPELL_SLOT) {
if (!UseDiscipline(castspell->spell_id, castspell->target_id)) {
printf("Unknown ability being used by %s, spell being cast is: %i\n", GetName(), castspell->spell_id);
InterruptSpell(castspell->spell_id);
return;
}
}
else if (castspell->slot == ABILITY_SPELL_SLOT) { // ABILITY cast (LoH and Harm Touch)
/* ABILITY cast (LoH and Harm Touch) */
else if (castspell->slot == ABILITY_SPELL_SLOT) {
uint16 spell_to_cast = 0;
if (castspell->spell_id == SPELL_LAY_ON_HANDS && GetClass() == PALADIN) {
@ -5109,26 +5126,6 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
if (spell_to_cast > 0) // if we've matched LoH or HT, cast now
CastSpell(spell_to_cast, castspell->target_id, castspell->slot);
}
else // MEMORIZED SPELL (first confirm that it's a valid memmed spell slot, then validate that the spell is currently memorized)
{
uint16 spell_to_cast = 0;
if(castspell->slot < MAX_PP_MEMSPELL)
{
spell_to_cast = m_pp.mem_spells[castspell->slot];
if(spell_to_cast != castspell->spell_id)
{
InterruptSpell(castspell->spell_id); //CHEATER!!!
return;
}
}
else if (castspell->slot >= MAX_PP_MEMSPELL) {
InterruptSpell();
return;
}
CastSpell(spell_to_cast, castspell->target_id, castspell->slot);
}
return;
}
@ -9224,8 +9221,7 @@ void Client::CompleteConnect() {
SendAppearancePacket(AT_GuildID, GuildID(), false);
SendAppearancePacket(AT_GuildRank, GuildRank(), false);
}
for (uint32 spellInt = 0; spellInt < MAX_PP_SPELLBOOK; spellInt++)
{
for (uint32 spellInt = 0; spellInt < MAX_PP_SPELLBOOK; spellInt++) {
if (m_pp.spell_book[spellInt] < 3 || m_pp.spell_book[spellInt] > 50000)
m_pp.spell_book[spellInt] = 0xFFFFFFFF;
}

View File

@ -2491,14 +2491,14 @@ void command_castspell(Client *c, const Seperator *sep)
else
if (c->GetTarget() == 0)
if(c->Admin() >= commandInstacast)
c->SpellFinished(spellid, 0, 10, 0, -1, spells[spellid].ResistDiff);
c->SpellFinished(spellid, 0, USE_ITEM_SPELL_SLOT, 0, -1, spells[spellid].ResistDiff);
else
c->CastSpell(spellid, 0, 10, 0);
c->CastSpell(spellid, 0, USE_ITEM_SPELL_SLOT, 0);
else
if(c->Admin() >= commandInstacast)
c->SpellFinished(spellid, c->GetTarget(), 10, 0, -1, spells[spellid].ResistDiff);
else
c->CastSpell(spellid, c->GetTarget()->GetID(), 10, 0);
c->CastSpell(spellid, c->GetTarget()->GetID(), USE_ITEM_SPELL_SLOT, 0);
}
}

View File

@ -17,6 +17,10 @@
#define _NPCPET(x) (x && x->IsNPC() && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsNPC())
#define _BECOMENPCPET(x) (x && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsClient() && x->CastToMob()->GetOwner()->CastToClient()->IsBecomeNPC())
#define USE_ITEM_SPELL_SLOT 10
#define POTION_BELT_SPELL_SLOT 11
#define DISCIPLINE_SPELL_SLOT 10
#define ABILITY_SPELL_SLOT 9
//LOS Parameters:
#define HEAD_POSITION 0.9f //ratio of GetSize() where NPCs see from

View File

@ -205,7 +205,7 @@ public:
void SendSpellBarEnable(uint16 spellid);
void ZeroCastingVars();
virtual void SpellProcess();
virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1,
virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1,
int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF,
uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, uint32 type = 0, int16 *resist_adjust = nullptr);
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1,

View File

@ -4843,6 +4843,8 @@ void Client::MemSpell(uint16 spell_id, int slot, bool update_client)
m_pp.mem_spells[slot] = spell_id;
mlog(CLIENT__SPELLS, "Spell %d memorized into slot %d", spell_id, slot);
database.SaveCharacterMemorizedSpell(this->CharacterID(), m_pp.mem_spells[slot], slot);
if(update_client)
{
MemorizeSpell(slot, spell_id, memSpellMemorize);
@ -4857,6 +4859,8 @@ void Client::UnmemSpell(int slot, bool update_client)
mlog(CLIENT__SPELLS, "Spell %d forgotten from slot %d", m_pp.mem_spells[slot], slot);
m_pp.mem_spells[slot] = 0xFFFFFFFF;
database.DeleteCharacterMemorizedSpell(this->CharacterID(), m_pp.mem_spells[slot], slot);
if(update_client)
{
MemorizeSpell(slot, m_pp.mem_spells[slot], memSpellForget);
@ -4884,6 +4888,7 @@ void Client::ScribeSpell(uint16 spell_id, int slot, bool update_client)
}
m_pp.spell_book[slot] = spell_id;
database.SaveCharacterSpell(this->CharacterID(), spell_id, slot);
mlog(CLIENT__SPELLS, "Spell %d scribed into spell book slot %d", spell_id, slot);
if(update_client)
@ -4899,7 +4904,8 @@ void Client::UnscribeSpell(int slot, bool update_client)
mlog(CLIENT__SPELLS, "Spell %d erased from spell book slot %d", m_pp.spell_book[slot], slot);
m_pp.spell_book[slot] = 0xFFFFFFFF;
database.DeleteCharacterSpell(this->CharacterID(), m_pp.spell_book[slot], slot);
if(update_client)
{
EQApplicationPacket* outapp = new EQApplicationPacket(OP_DeleteSpell, sizeof(DeleteSpell_Struct));

View File

@ -401,40 +401,33 @@ uint32 Zone::GetTempMerchantQuantity(uint32 NPCID, uint32 Slot) {
void Zone::LoadTempMerchantData(){
LogFile->write(EQEMuLog::Status, "Loading Temporary Merchant Lists...");
char* query = 0;
uint32_breakdown workpt;
workpt.b4() = DBA_b4_Zone;
workpt.w2_3() = 0;
workpt.b1() = DBA_b1_Zone_MerchantListsTemp;
DBAsyncWork* dbaw = new DBAsyncWork(&database, &MTdbafq, workpt, DBAsync::Read);
dbaw->AddQuery(1, &query, MakeAnyLenString(&query,
"select ml.npcid,ml.slot,ml.itemid,ml.charges "
"from "
" merchantlist_temp ml, "
" spawnentry se, "
" spawn2 s2 "
"where "
" ml.npcid=se.npcid "
" and se.spawngroupid=s2.spawngroupid "
" and s2.zone='%s' and s2.version=%u", GetShortName(), GetInstanceVersion()));
if (!(pQueuedMerchantsWorkID = dbasync->AddWork(&dbaw))) {
safe_delete(dbaw);
LogFile->write(EQEMuLog::Error, "dbasync->AddWork() failed adding merchant list query");
std::string query = StringFormat(
"SELECT "
"ml.npcid, "
"ml.slot, "
"ml.charges, "
"ml.itemid "
"FROM "
"merchantlist_temp ml, "
"spawnentry se, "
"spawn2 s2 "
"WHERE "
"ml.npcid = se.npcid "
"AND se.spawngroupid = s2.spawngroupid "
"AND s2.zone = '%s' AND s2.version = %i", GetShortName(), GetInstanceVersion());
auto results = database.QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in LoadTempMerchantData query '%s' %s", query.c_str(), results.ErrorMessage().c_str());
return;
}
}
void Zone::LoadTempMerchantData_result(MYSQL_RES* result) {
MYSQL_ROW row;
std::map<uint32,std::list<TempMerchantList> >::iterator cur;
std::map<uint32, std::list<TempMerchantList> >::iterator cur;
uint32 npcid = 0;
while((row = mysql_fetch_row(result))) {
for (auto row = results.begin(); row != results.end(); ++row) {
TempMerchantList ml;
ml.npcid = atoul(row[0]);
if(npcid != ml.npcid){
if (npcid != ml.npcid){
cur = tmpmerchanttable.find(ml.npcid);
if(cur == tmpmerchanttable.end()) {
if (cur == tmpmerchanttable.end()) {
std::list<TempMerchantList> empty;
tmpmerchanttable[ml.npcid] = empty;
cur = tmpmerchanttable.find(ml.npcid);
@ -447,9 +440,9 @@ void Zone::LoadTempMerchantData_result(MYSQL_RES* result) {
ml.origslot = ml.slot;
cur->second.push_back(ml);
}
pQueuedMerchantsWorkID = 0;
}
//there should prolly be a temp counterpart of this...
void Zone::LoadNewMerchantData(uint32 merchantid){
std::list<MerchantList> merlist;
@ -476,16 +469,35 @@ void Zone::LoadNewMerchantData(uint32 merchantid){
merchanttable[merchantid] = merlist;
}
void Zone::LoadMerchantData_result(MYSQL_RES* result) {
MYSQL_ROW row;
std::map<uint32,std::list<MerchantList> >::iterator cur;
void Zone::GetMerchantDataForZoneLoad(){
LogFile->write(EQEMuLog::Status, "Loading Merchant Lists...");
std::string query = StringFormat(
"SELECT "
"ml.merchantid, "
"ml.slot, "
"ml.item, "
"ml.faction_required, "
"ml.level_required, "
"ml.alt_currency_cost, "
"ml.classes_required, "
"ml.probability "
"FROM "
"merchantlist AS ml, "
"npc_types AS nt, "
"spawnentry AS se, "
"spawn2 AS s2 "
"WHERE nt.merchant_id = ml.merchantid AND nt.id = se.npcid "
"AND se.spawngroupid = s2.spawngroupid AND s2.zone = '%s' AND s2.version = %i ", GetShortName(), GetInstanceVersion());
auto results = database.QueryDatabase(query);
std::map<uint32, std::list<MerchantList> >::iterator cur;
uint32 npcid = 0;
while((row = mysql_fetch_row(result))) {
if (results.RowCount() == 0){ LogFile->write(EQEMuLog::Error, "Error in loading Merchant Data for zone"); return; }
for (auto row = results.begin(); row != results.end(); ++row) {
MerchantList ml;
ml.id = atoul(row[0]);
if(npcid != ml.id){
if (npcid != ml.id){
cur = merchanttable.find(ml.id);
if(cur == merchanttable.end()) {
if (cur == merchanttable.end()) {
std::list<MerchantList> empty;
merchanttable[ml.id] = empty;
cur = merchanttable.find(ml.id);
@ -495,15 +507,15 @@ void Zone::LoadMerchantData_result(MYSQL_RES* result) {
std::list<MerchantList>::iterator iter = cur->second.begin();
bool found = false;
while(iter != cur->second.end()) {
if((*iter).item == ml.id) {
while (iter != cur->second.end()) {
if ((*iter).item == ml.id) {
found = true;
break;
}
++iter;
}
if(found) {
if (found) {
continue;
}
@ -516,28 +528,7 @@ void Zone::LoadMerchantData_result(MYSQL_RES* result) {
ml.probability = atoul(row[7]);
cur->second.push_back(ml);
}
}
void Zone::GetMerchantDataForZoneLoad(){
LogFile->write(EQEMuLog::Status, "Loading Merchant Lists...");
char* query = 0;
uint32_breakdown workpt;
workpt.b4() = DBA_b4_Zone;
workpt.w2_3() = 0;
workpt.b1() = DBA_b1_Zone_MerchantLists;
DBAsyncWork* dbaw = new DBAsyncWork(&database, &MTdbafq, workpt, DBAsync::Read);
dbaw->AddQuery(1, &query, MakeAnyLenString(&query,
"select ml.merchantid,ml.slot,ml.item,ml.faction_required,ml.level_required,ml.alt_currency_cost,ml.classes_required,ml.probability "
"from merchantlist ml, npc_types nt, spawnentry se, spawn2 s2 "
"where nt.merchant_id=ml.merchantid and nt.id=se.npcid "
"and se.spawngroupid=s2.spawngroupid and s2.zone='%s' and s2.version=%u "
//"group by ml.merchantid,slot order by merchantid,slot asc" //this made the query use a temp table/filesort (very slow)... so we handle unsorted data on our end.
, GetShortName(), GetInstanceVersion()));
if (!(pQueuedMerchantsWorkID = dbasync->AddWork(&dbaw))) {
safe_delete(dbaw);
LogFile->write(EQEMuLog::Error,"dbasync->AddWork() failed adding merchant list query");
return;
}
}
void Zone::LoadMercTemplates(){
@ -663,61 +654,6 @@ void Zone::LoadMercSpells(){
}
void Zone::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) {
// LogFile->write(EQEMuLog::Debug, "Zone work complete...");
switch (workpt_b1) {
case DBA_b1_Zone_MerchantLists: {
char errbuf[MYSQL_ERRMSG_SIZE];
MYSQL_RES* result = 0;
DBAsyncQuery* dbaq = dbaw->PopAnswer();
if(dbaq == nullptr) {
LogFile->write(EQEMuLog::Error, "nullptr answer provided for async merchant list load.");
break;
}
if(!dbaq->GetAnswer(errbuf, &result)) {
LogFile->write(EQEMuLog::Error, "Zone::DBAWComplete(): Unable to get results for merchant lists");
break;
}
if(dbaq->QPT() != 1) {
LogFile->write(EQEMuLog::Error, "Zone::DBAWComplete(): Invalid query part for merchant lists");
break;
}
LoadMerchantData_result(result);
pQueuedMerchantsWorkID = 0;
break;
}
case DBA_b1_Zone_MerchantListsTemp: {
char errbuf[MYSQL_ERRMSG_SIZE];
MYSQL_RES* result = 0;
DBAsyncQuery* dbaq = dbaw->PopAnswer();
if(dbaq == nullptr) {
LogFile->write(EQEMuLog::Error, "nullptr answer provided for async temp merchant list load.");
break;
}
if(!dbaq->GetAnswer(errbuf, &result)) {
LogFile->write(EQEMuLog::Error, "Zone::DBAWComplete(): Unable to get results for temp merchant lists");
break;
}
if(dbaq->QPT() != 1) {
LogFile->write(EQEMuLog::Error, "Zone::DBAWComplete(): Invalid query part for temp merchant lists");
break;
}
LoadTempMerchantData_result(result);
pQueuedMerchantsWorkID = 0;
break;
}
default: {
LogFile->write(EQEMuLog::Error, "Zone::DBAWComplete(): Unknown workpt_b1");
break;
}
}
}
bool Zone::IsLoaded() {
return ZoneLoaded;
}

View File

@ -166,7 +166,6 @@ public:
void SetStaticZone(bool sz) { staticzone = sz; }
inline bool IsStaticZone() { return staticzone; }
inline void GotCurTime(bool time) { gottime = time; }
void DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw);
void SpawnConditionChanged(const SpawnCondition &c, int16 old_value);
@ -174,8 +173,6 @@ public:
void LoadNewMerchantData(uint32 merchantid);
void LoadTempMerchantData();
uint32 GetTempMerchantQuantity(uint32 NPCID, uint32 Slot);
void LoadTempMerchantData_result(MYSQL_RES* result);
void LoadMerchantData_result(MYSQL_RES* result);
int SaveTempItem(uint32 merchantid, uint32 npcid, uint32 item, int32 charges, bool sold=false);
void LoadMercTemplates();
void LoadMercSpells();

View File

@ -1022,6 +1022,45 @@ bool ZoneDatabase::LoadCharacterFactionValues(uint32 character_id, faction_map &
return true;
}
bool ZoneDatabase::LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp){
std::string query = StringFormat(
"SELECT "
"slot_id, "
"`spell_id` "
"FROM "
"`character_memmed_spells` "
"WHERE `id` = %u ORDER BY `slot_id`", character_id);
auto results = database.QueryDatabase(query); int i = 0;
for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); pp->mem_spells[i] = atoi(row[1]); }
return true;
}
bool ZoneDatabase::LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp){
std::string query = StringFormat(
"SELECT "
"slot_id, "
"`spell_id` "
"FROM "
"`character_spells` "
"WHERE `id` = %u ORDER BY `slot_id`", character_id);
auto results = database.QueryDatabase(query); int i = 0;
for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); pp->spell_book[i] = atoi(row[1]); }
return true;
}
bool ZoneDatabase::LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp){
std::string query = StringFormat(
"SELECT "
"lang_id, "
"`value` "
"FROM "
"`character_languages` "
"WHERE `id` = %u ORDER BY `language_id`", character_id);
auto results = database.QueryDatabase(query); int i = 0;
for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); pp->languages[i] = atoi(row[1]); }
return true;
}
bool ZoneDatabase::LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp){
std::string query = StringFormat(
"SELECT "
@ -1092,8 +1131,23 @@ bool ZoneDatabase::LoadCharacterCurrency(uint32 character_id, PlayerProfile_Stru
return true;
}
bool ZoneDatabase::LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp){
std::string query = StringFormat("SELECT id, zone_id, instance_id, x, y, z, heading FROM character_bind_home WHERE `id` = %u", character_id);
auto results = database.QueryDatabase(query); int i = 0;
for (auto row = results.begin(); row != results.end(); ++row) {
pp->binds[4].zoneId = atoi(row[i]); i++;
i++; /* Instance ID can go here eventually */
pp->binds[4].x = atoi(row[i]); i++;
pp->binds[4].y = atoi(row[i]); i++;
pp->binds[4].z = atoi(row[i]); i++;
pp->binds[4].heading = atoi(row[i]); i++;
}
return true;
}
bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp){
clock_t t = std::clock(); /* Function timer start */
if (pp->tribute_time_remaining < 0 || pp->tribute_time_remaining == 4294967295){ pp->tribute_time_remaining = 0; }
std::string query = StringFormat(
"REPLACE INTO `character_data` ("
" id, "
@ -1187,96 +1241,96 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla
" guild_auto_consent, "
" RestTimer) "
"VALUES ("
"%i," // id " id, "
"%i," // account_id " account_id, "
"%u," // id " id, "
"%u," // account_id " account_id, "
"'%s'," // `name` pp->name, " `name`, "
"'%s'," // last_name pp->last_name, " last_name, "
"%i," // gender pp->gender, " gender, "
"%i," // race pp->race, " race, "
"%i," // class pp->class_, " class, "
"%i," // `level` pp->level, " `level`, "
"%i," // deity pp->deity, " deity, "
"%i," // birthday pp->birthday, " birthday, "
"%i," // last_login pp->lastlogin, " last_login, "
"%i," // time_played pp->timePlayedMin, " time_played, "
"%i," // pvp_status pp->pvp, " pvp_status, "
"%i," // level2 pp->level2, " level2, "
"%i," // anon pp->anon, " anon, "
"%i," // gm pp->gm, " gm, "
"%i," // intoxication pp->intoxication, " intoxication, "
"%i," // hair_color pp->haircolor, " hair_color, "
"%i," // beard_color pp->beardcolor, " beard_color, "
"%i," // eye_color_1 pp->eyecolor1, " eye_color_1, "
"%i," // eye_color_2 pp->eyecolor2, " eye_color_2, "
"%i," // hair_style pp->hairstyle, " hair_style, "
"%i," // beard pp->beard, " beard, "
"%i," // ability_time_seconds pp->ability_time_seconds, " ability_time_seconds, "
"%i," // ability_number pp->ability_number, " ability_number, "
"%i," // ability_time_minutes pp->ability_time_minutes, " ability_time_minutes, "
"%i," // ability_time_hours pp->ability_time_hours, " ability_time_hours, "
"%u," // gender pp->gender, " gender, "
"%u," // race pp->race, " race, "
"%u," // class pp->class_, " class, "
"%u," // `level` pp->level, " `level`, "
"%u," // deity pp->deity, " deity, "
"%u," // birthday pp->birthday, " birthday, "
"%u," // last_login pp->lastlogin, " last_login, "
"%u," // time_played pp->timePlayedMin, " time_played, "
"%u," // pvp_status pp->pvp, " pvp_status, "
"%u," // level2 pp->level2, " level2, "
"%u," // anon pp->anon, " anon, "
"%u," // gm pp->gm, " gm, "
"%u," // intoxication pp->intoxication, " intoxication, "
"%u," // hair_color pp->haircolor, " hair_color, "
"%u," // beard_color pp->beardcolor, " beard_color, "
"%u," // eye_color_1 pp->eyecolor1, " eye_color_1, "
"%u," // eye_color_2 pp->eyecolor2, " eye_color_2, "
"%u," // hair_style pp->hairstyle, " hair_style, "
"%u," // beard pp->beard, " beard, "
"%u," // ability_time_seconds pp->ability_time_seconds, " ability_time_seconds, "
"%u," // ability_number pp->ability_number, " ability_number, "
"%u," // ability_time_minutes pp->ability_time_minutes, " ability_time_minutes, "
"%u," // ability_time_hours pp->ability_time_hours, " ability_time_hours, "
"'%s'," // title pp->title, " title, " "
"'%s'," // suffix pp->suffix, " suffix, "
"%i," // exp pp->exp, " exp, "
"%i," // points pp->points, " points, "
"%i," // mana pp->mana, " mana, "
"%i," // cur_hp pp->cur_hp, " cur_hp, "
"%i," // str pp->STR, " str, "
"%i," // sta pp->STA, " sta, "
"%i," // cha pp->CHA, " cha, "
"%i," // dex pp->DEX, " dex, "
"%i," // `int` pp->INT, " `int`, "
"%i," // agi pp->AGI, " agi, "
"%i," // wis pp->WIS, " wis, "
"%i," // face pp->face, " face, "
"%u," // exp pp->exp, " exp, "
"%u," // points pp->points, " points, "
"%u," // mana pp->mana, " mana, "
"%u," // cur_hp pp->cur_hp, " cur_hp, "
"%u," // str pp->STR, " str, "
"%u," // sta pp->STA, " sta, "
"%u," // cha pp->CHA, " cha, "
"%u," // dex pp->DEX, " dex, "
"%u," // `int` pp->INT, " `int`, "
"%u," // agi pp->AGI, " agi, "
"%u," // wis pp->WIS, " wis, "
"%u," // face pp->face, " face, "
"%f," // y pp->y, " y, "
"%f," // x pp->x, " x, "
"%f," // z pp->z, " z, "
"%f," // heading pp->heading, " heading, "
"%i," // pvp2 pp->pvp2, " pvp2, "
"%i," // pvp_type pp->pvptype, " pvp_type, "
"%i," // autosplit_enabled pp->autosplit, " autosplit_enabled, "
"%i," // zone_change_count pp->zone_change_count, " zone_change_count, "
"%i," // drakkin_heritage pp->drakkin_heritage, " drakkin_heritage, "
"%i," // drakkin_tattoo pp->drakkin_tattoo, " drakkin_tattoo, "
"%i," // drakkin_details pp->drakkin_details, " drakkin_details, "
"%u," // pvp2 pp->pvp2, " pvp2, "
"%u," // pvp_type pp->pvptype, " pvp_type, "
"%u," // autosplit_enabled pp->autosplit, " autosplit_enabled, "
"%u," // zone_change_count pp->zone_change_count, " zone_change_count, "
"%u," // drakkin_heritage pp->drakkin_heritage, " drakkin_heritage, "
"%u," // drakkin_tattoo pp->drakkin_tattoo, " drakkin_tattoo, "
"%u," // drakkin_details pp->drakkin_details, " drakkin_details, "
"%i," // toxicity pp->toxicity, " toxicity, "
"%i," // hunger_level pp->hunger_level, " hunger_level, "
"%i," // thirst_level pp->thirst_level, " thirst_level, "
"%i," // ability_up pp->ability_up, " ability_up, "
"%i," // zone_id pp->zone_id, " zone_id, "
"%i," // zone_instance pp->zoneInstance, " zone_instance, "
"%i," // leadership_exp_on pp->leadAAActive, " leadership_exp_on, "
"%i," // ldon_points_guk pp->ldon_points_guk, " ldon_points_guk, "
"%i," // ldon_points_mir pp->ldon_points_mir, " ldon_points_mir, "
"%i," // ldon_points_mmc pp->ldon_points_mmc, " ldon_points_mmc, "
"%i," // ldon_points_ruj pp->ldon_points_ruj, " ldon_points_ruj, "
"%i," // ldon_points_tak pp->ldon_points_tak, " ldon_points_tak, "
"%i," // ldon_points_available pp->ldon_points_available, " ldon_points_available, "
"%i," // tribute_time_remaining pp->tribute_time_remaining, " tribute_time_remaining, "
"%i," // show_helm pp->showhelm, " show_helm, "
"%i," // career_tribute_points pp->career_tribute_points, " career_tribute_points, "
"%i," // tribute_points pp->tribute_points, " tribute_points, "
"%i," // tribute_active pp->tribute_active, " tribute_active, "
"%i," // endurance pp->endurance, " endurance, "
"%i," // group_leadership_exp pp->group_leadership_exp, " group_leadership_exp, "
"%i," // raid_leadership_exp pp->raid_leadership_exp, " raid_leadership_exp, "
"%i," // group_leadership_points pp->group_leadership_points, " group_leadership_points, "
"%i," // raid_leadership_points pp->raid_leadership_points, " raid_leadership_points, "
"%i," // air_remaining pp->air_remaining, " air_remaining, "
"%i," // pvp_kills pp->PVPKills, " pvp_kills, "
"%i," // pvp_deaths pp->PVPDeaths, " pvp_deaths, "
"%i," // pvp_current_points pp->PVPCurrentPoints, " pvp_current_points, "
"%i," // pvp_career_points pp->PVPCareerPoints, " pvp_career_points, "
"%i," // pvp_best_kill_streak pp->PVPBestKillStreak, " pvp_best_kill_streak, "
"%i," // pvp_worst_death_streak pp->PVPWorstDeathStreak, " pvp_worst_death_streak, "
"%i," // pvp_current_kill_streak pp->PVPCurrentKillStreak, " pvp_current_kill_streak, "
"%i," // aa_points_spent pp->aapoints_spent, " aa_points_spent, "
"%i," // aa_exp pp->expAA, " aa_exp, "
"%i," // aa_points pp->aapoints, " aa_points, "
"%i," // group_auto_consent pp->groupAutoconsent, " group_auto_consent, "
"%i," // raid_auto_consent pp->raidAutoconsent, " raid_auto_consent, "
"%i," // guild_auto_consent pp->guildAutoconsent, " guild_auto_consent, "
"%i" // RestTimer pp->RestTimer, " RestTimer) "
"%u," // ability_up pp->ability_up, " ability_up, "
"%u," // zone_id pp->zone_id, " zone_id, "
"%u," // zone_instance pp->zoneInstance, " zone_instance, "
"%u," // leadership_exp_on pp->leadAAActive, " leadership_exp_on, "
"%u," // ldon_points_guk pp->ldon_points_guk, " ldon_points_guk, "
"%u," // ldon_points_mir pp->ldon_points_mir, " ldon_points_mir, "
"%u," // ldon_points_mmc pp->ldon_points_mmc, " ldon_points_mmc, "
"%u," // ldon_points_ruj pp->ldon_points_ruj, " ldon_points_ruj, "
"%u," // ldon_points_tak pp->ldon_points_tak, " ldon_points_tak, "
"%u," // ldon_points_available pp->ldon_points_available, " ldon_points_available, "
"%u," // tribute_time_remaining pp->tribute_time_remaining, " tribute_time_remaining, "
"%u," // show_helm pp->showhelm, " show_helm, "
"%u," // career_tribute_points pp->career_tribute_points, " career_tribute_points, "
"%u," // tribute_points pp->tribute_points, " tribute_points, "
"%u," // tribute_active pp->tribute_active, " tribute_active, "
"%u," // endurance pp->endurance, " endurance, "
"%u," // group_leadership_exp pp->group_leadership_exp, " group_leadership_exp, "
"%u," // raid_leadership_exp pp->raid_leadership_exp, " raid_leadership_exp, "
"%u," // group_leadership_points pp->group_leadership_points, " group_leadership_points, "
"%u," // raid_leadership_points pp->raid_leadership_points, " raid_leadership_points, "
"%u," // air_remaining pp->air_remaining, " air_remaining, "
"%u," // pvp_kills pp->PVPKills, " pvp_kills, "
"%u," // pvp_deaths pp->PVPDeaths, " pvp_deaths, "
"%u," // pvp_current_points pp->PVPCurrentPoints, " pvp_current_points, "
"%u," // pvp_career_points pp->PVPCareerPoints, " pvp_career_points, "
"%u," // pvp_best_kill_streak pp->PVPBestKillStreak, " pvp_best_kill_streak, "
"%u," // pvp_worst_death_streak pp->PVPWorstDeathStreak, " pvp_worst_death_streak, "
"%u," // pvp_current_kill_streak pp->PVPCurrentKillStreak, " pvp_current_kill_streak, "
"%u," // aa_points_spent pp->aapoints_spent, " aa_points_spent, "
"%u," // aa_exp pp->expAA, " aa_exp, "
"%u," // aa_points pp->aapoints, " aa_points, "
"%u," // group_auto_consent pp->groupAutoconsent, " group_auto_consent, "
"%u," // raid_auto_consent pp->raidAutoconsent, " raid_auto_consent, "
"%u," // guild_auto_consent pp->guildAutoconsent, " guild_auto_consent, "
"%u" // RestTimer pp->RestTimer, " RestTimer) "
")",
character_id,
account_id,
@ -1370,7 +1424,12 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla
pp->RestTimer
);
auto results = database.QueryDatabase(query);
LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterData %i, done... Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC);
//if (results.RowsAffected() != 2) {
// LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::SaveCharacterData Error! Query: %s \n", query); return false;
//}
//else{
LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterData %i, done... Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC);
//}
return true;
}
@ -1407,7 +1466,7 @@ bool ZoneDatabase::SaveCharacterCurrency(uint32 character_id, PlayerProfile_Stru
pp->currentEbonCrystals,
pp->careerEbonCrystals);
auto results = database.QueryDatabase(query);
LogFile->write(EQEMuLog::Status, "Saving Currency for character ID: %i, done", character_id);
LogFile->write(EQEMuLog::Status, "Saving Currency for character ID: %i, done", character_id);
return true;
}
@ -1416,10 +1475,35 @@ bool ZoneDatabase::SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 cur
" VALUES (%u, %u, %u)",
character_id, aa_id, current_level);
auto results = QueryDatabase(rquery);
LogFile->write(EQEMuLog::Status, "Saving AA for character ID: %i, aa_id: %u current_level: %i", character_id, aa_id, current_level);
LogFile->write(EQEMuLog::Status, "Saving AA for character ID: %u, aa_id: %u current_level: %u", character_id, aa_id, current_level);
return true;
}
bool ZoneDatabase::SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot){
std::string rquery = StringFormat("UPDATE `character_spells` SET `slot_id` = %u WHERE `slot_id` = %u AND `id` = %u",
to_slot, from_slot, character_id);
clock_t t = std::clock(); /* Function timer start */
auto results = QueryDatabase(rquery);
LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterSpellSwap for character ID: %u, from_slot: %u to_slot: %u spell: %u time: %f seconds", character_id, from_slot, to_slot, spell_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC);
return true;
}
bool ZoneDatabase::SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id){
std::string query = StringFormat("REPLACE INTO `character_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, slot_id, spell_id); QueryDatabase(query); return true;
}
bool ZoneDatabase::DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id){
std::string query = StringFormat("DELETE FROM `character_spells` WHERE `slot_id` = %u AND `id` = %u", slot_id, character_id); QueryDatabase(query); return true;
}
bool ZoneDatabase::SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id){
std::string query = StringFormat("REPLACE INTO `character_memmed_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, slot_id, spell_id); QueryDatabase(query); return true;
}
bool ZoneDatabase::DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id){
std::string query = StringFormat("DELETE FROM `character_memmed_spells` WHERE `slot_id` = %u AND `id` = %u", slot_id, character_id); QueryDatabase(query); return true;
}
bool ZoneDatabase::NoRentExpired(const char* name){
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
@ -1429,7 +1513,7 @@ bool ZoneDatabase::NoRentExpired(const char* name){
safe_delete_array(query);
if (mysql_num_rows(result) == 1) {
row = mysql_fetch_row(result);
uint32 seconds = atoi(row[0]);
uint32 seconds = atoi(row[0]);
mysql_free_result(result);
return (seconds>1800);
}

View File

@ -256,18 +256,28 @@ public:
void SavePetInfo(Client *c);
void RemoveTempFactions(Client *c);
/* Player Profile Loaders */
/* Character Data Loaders */
bool LoadCharacterFactionValues(uint32 character_id, faction_map & val_list);
bool LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterData(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
/* Player Profile Saves */
/* Character Data Saves */
bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp);
bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level);
bool SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot);
bool SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
/* Character Data Deletes */
bool DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
/*
* Character Inventory

View File

@ -12,30 +12,6 @@ void DispatchFinishedDBAsync(DBAsyncWork* dbaw) {
uint32_breakdown workpt;
workpt = dbaw->WPT();
switch (workpt.b4()) {
/* case DBA_b4_Main: {
switch (workpt.i24_1()) {
case DBA_i24_1_Main_LoadVariables: {
char errbuf[MYSQL_ERRMSG_SIZE];
MYSQL_RES* result;
DBAsyncQuery* dbaq = dbaw->PopAnswer();
if (dbaq->GetAnswer(errbuf, result))
database.LoadVariables_result(result);
else
std::cout << "Async DB.LoadVariables() failed: '" << errbuf << "'" << std::endl;
break;
}
default: {
std::cout << "Error: DispatchFinishedDBAsync(): Unknown workpt.b4" << std::endl;
break;
}
}
}*/
case DBA_b4_Zone: {
if(zone == nullptr)
break;
zone->DBAWComplete(workpt.b1(), dbaw);
break;
}
case DBA_b4_Entity: {
Entity* entity = entity_list.GetID(workpt.w2_3());
if (!entity)