State of Commit: Testable if you ask me (Akkadius) what you need to do

- Need to convert a list of functions and columns and should be ready to start intensive testing phase
 - All preliminary tests show things working great

- All of player profile is saved and loaded from the database
- DBAsync has been completely removed from all code
	- Removed zone/dbasync.cpp/.h
	- Removed common/dbasync.cpp/.h
	- Removed dbasync from cmake commmon and zone
- Cleaned up a ton of functions
- Added several tables to world CheckDatabaseConversions script:
	- `character_skills`
	- `character_languages`
	- `character_bind`
	- `character_alternate_abilities`
	- `character_currency`
	- `character_data`
	- `character_spells`
	- `character_memmed_spells`
	- `character_disciplines`
	- `character_material`
	- `character_tribute`
	- `character_bandolier`
	- `character_potionbelt`
- Character select now loads from `character_data`
- Character creation now creates to `character_data`
- Updated function Database::UpdateName to use `character_data`
- Updated function Database::CheckUsedName to use `character_data`
- Updated function Database::MoveCharacterToZone to use `character_data`
- Updated function Database::SetLoginFlags to use `character_data`
- Updated function Database::SetFirstLogon to use `character_data`
- Updated function Database::SetLFG to use `character_data`
- Removed CopyCharacter functions and commands, to be recreated later since it never worked to begin with
- Removed SharedDatabase::SetPlayerProfile
- Trimmed down redundant case switch statements for World sendpackets to QueryServ
- Added Character Methods to Database class:
	Loads:
		bool	LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp);
		bool	LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
		bool	LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp);
	Saves:
		bool	SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading, uint8 is_home);
		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);
		bool	SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color);
		bool	SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value);
		bool	SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value);
		bool	SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id);
		bool	SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
		bool	SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name);
		bool	SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon);
	Deletes:
		bool	DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
		bool	DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
		bool	DeleteCharacterDisc(uint32 character_id, uint32 slot_id);
		bool	DeleteCharacterBandolier(uint32 character_id, uint32 band_id);
This commit is contained in:
Akkadius 2014-09-04 07:24:17 -05:00
parent 0a9222e1ee
commit 4432c07081
37 changed files with 1235 additions and 2370 deletions

View File

@ -8,7 +8,6 @@ SET(common_sources
crc16.cpp
crc32.cpp
database.cpp
dbasync.cpp
dbcore.cpp
debug.cpp
emu_opcodes.cpp
@ -103,7 +102,6 @@ SET(common_headers
crc16.h
crc32.h
database.h
dbasync.h
dbcore.h
debug.h
deity.h

File diff suppressed because it is too large Load Diff

View File

@ -105,10 +105,16 @@ public:
Database(const char* host, const char* user, const char* passwd, const char* database,uint32 port);
bool Connect(const char* host, const char* user, const char* passwd, const char* database,uint32 port);
~Database();
bool ThrowDBError(std::string ErrorMessage, std::string query_title, std::string query);
/*
* General Character Related Stuff
*/
/* Character Creation */
bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp);
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);
@ -118,16 +124,15 @@ public:
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, ExtendedProfile_Struct *ext);
bool StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv);
bool DeleteCharacter(char* name);
uint8 CopyCharacter(const char* oldname, const char* newname, uint32 acctid);
/*
* General Information Getting Queries
*/
bool CheckNameFilter(const char* name, bool surname = false);
bool CheckUsedName(const char* name);
uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0);
uint32 GetAccountIDByChar(const char* charname);
uint32 GetAccountIDByChar(uint32 char_id);
uint32 GetAccountIDByName(const char* accname, int16* status = 0, uint32* lsid = 0);
uint32 GetGuildIDByCharID(uint32 char_id);
@ -252,10 +257,6 @@ public:
void SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon);
void AddReport(std::string who, std::string against, std::string lines);
protected:
void HandleMysqlError(uint32 errnum);
private:
void DBInitVars();

View File

@ -1,669 +0,0 @@
#include "debug.h"
#ifdef _WINDOWS
#include <windows.h>
#include <process.h>
#include <winsock2.h>
#endif
#include <iostream>
#include "dbasync.h"
#include "database.h"
#include <errmsg.h>
#include <mysqld_error.h>
#include <limits.h>
#include "dbcore.h"
#include <string.h>
//#include "../common/misc_functions.h"
#include "string_util.h"
#define ASYNC_LOOP_GRANULARITY 4 //# of ms between checking our work
bool DBAsyncCB_LoadVariables(DBAsyncWork* iWork) {
char errbuf[MYSQL_ERRMSG_SIZE];
MYSQL_RES* result = 0;
DBAsyncQuery* dbaq = iWork->PopAnswer();
if (dbaq->GetAnswer(errbuf, &result))
iWork->GetDB()->LoadVariables_result(result);
else
std::cout << "Error: DBAsyncCB_LoadVariables failed: !GetAnswer: '" << errbuf << "'" << std::endl;
return true;
}
void AsyncLoadVariables(DBAsync *dba, Database *db) {
char* query = 0;
DBAsyncWork* dbaw = new DBAsyncWork(db, &DBAsyncCB_LoadVariables, 0, DBAsync::Read);
dbaw->AddQuery(0, &query, db->LoadVariables_MQ(&query));
dba->AddWork(&dbaw);
}
//we only need to do anything when somebody puts work on the queue
//so instead of checking all the time, we will wait on a condition
//which will get signaled when somebody puts something on the queue
ThreadReturnType DBAsyncLoop(void* tmp) {
DBAsync* dba = (DBAsync*) tmp;
#ifndef WIN32
_log(COMMON__THREADS, "Starting DBAsyncLoop with thread ID %d", pthread_self());
#endif
dba->MLoopRunning.lock();
while (dba->RunLoop()) {
//wait before working so we check the loop condition
//as soon as were done working
dba->CInList.Wait();
//we could check dba->RunLoop() again to see if we
//got turned off while we were waiting
{
dba->Process();
}
}
dba->MLoopRunning.unlock();
#ifndef WIN32
_log(COMMON__THREADS, "Ending DBAsyncLoop with thread ID %d", pthread_self());
#endif
THREAD_RETURN(nullptr);
}
DBAsync::DBAsync(DBcore* iDBC)
: Timeoutable(10000)
{
pDBC = iDBC;
pRunLoop = true;
pNextID = 1;
#ifdef _WINDOWS
_beginthread(DBAsyncLoop, 0, this);
#else
pthread_t thread;
pthread_create(&thread, nullptr, DBAsyncLoop, this);
#endif
}
DBAsync::~DBAsync() {
StopThread();
}
bool DBAsync::StopThread() {
bool ret;
MRunLoop.lock();
ret = pRunLoop;
pRunLoop = false;
MRunLoop.unlock();
//signal the condition so we exit the loop if were waiting
CInList.Signal();
//this effectively waits for the processing thread to finish
MLoopRunning.lock();
MLoopRunning.unlock();
return ret;
}
uint32 DBAsync::AddWork(DBAsyncWork** iWork, uint32 iDelay) {
MInList.lock();
uint32 ret = GetNextID();
if (!(*iWork)->SetWorkID(ret)) {
MInList.unlock();
return 0;
}
InList.Append(*iWork);
(*iWork)->SetStatus(Queued);
if (iDelay)
(*iWork)->pExecuteAfter = Timer::GetCurrentTime() + iDelay;
#if DEBUG_MYSQL_QUERIES >= 2
std::cout << "Adding AsyncWork #" << (*iWork)->GetWorkID() << std::endl;
std::cout << "ExecuteAfter = " << (*iWork)->pExecuteAfter << " (" << Timer::GetCurrentTime() << " + " << iDelay << ")" << std::endl;
#endif
*iWork = 0;
MInList.unlock();
//wake up the processing thread and tell it to get to work.
CInList.Signal();
return ret;
}
bool DBAsync::CancelWork(uint32 iWorkID) {
if (iWorkID == 0)
return false;
#if DEBUG_MYSQL_QUERIES >= 2
std::cout << "DBAsync::CancelWork: " << iWorkID << std::endl;
#endif
MCurrentWork.lock();
if (CurrentWork && CurrentWork->GetWorkID() == iWorkID) {
CurrentWork->Cancel();
MCurrentWork.unlock();
return true;
}
MCurrentWork.unlock();
MInList.lock();
LinkedListIterator<DBAsyncWork*> iterator(InList);
iterator.Reset();
while (iterator.MoreElements()) {
if (iterator.GetData()->GetWorkID() == iWorkID) {
iterator.RemoveCurrent(true);
MInList.unlock();
return true;
}
iterator.Advance();
}
MInList.unlock();
return false;
}
bool DBAsync::RunLoop() {
bool ret;
MRunLoop.lock();
ret = pRunLoop;
MRunLoop.unlock();
return ret;
}
DBAsyncWork* DBAsync::InListPop() {
DBAsyncWork* ret = 0;
MInList.lock();
LinkedListIterator<DBAsyncWork*> iterator(InList);
iterator.Reset();
while (iterator.MoreElements()) {
if (iterator.GetData()->pExecuteAfter <= Timer::GetCurrentTime()) {
ret = iterator.GetData();
#if DEBUG_MYSQL_QUERIES >= 2
std::cout << "Poping AsyncWork #" << ret->GetWorkID() << std::endl;
std::cout << ret->pExecuteAfter << " <= " << Timer::GetCurrentTime() << std::endl;
#endif
iterator.RemoveCurrent(false);
break;
}
iterator.Advance();
}
MInList.unlock();
return ret;
}
DBAsyncWork* DBAsync::InListPopWrite() {
MInList.lock();
LinkedListIterator<DBAsyncWork*> iterator(InList);
DBAsyncWork* ret = 0;
DBAsync::Type tmpType;
iterator.Reset();
while (iterator.MoreElements()) {
tmpType = iterator.GetData()->Type();
if (tmpType == Write || tmpType == Both) {
ret = iterator.GetData();
iterator.RemoveCurrent(false);
break;
}
iterator.Advance();
}
MInList.unlock();
return ret;
}
void DBAsync::AddFQ(DBAsyncFinishedQueue* iDBAFQ) {
MFQList.lock();
DBAsyncFinishedQueue** tmp = new DBAsyncFinishedQueue*;
*tmp = iDBAFQ;
FQList.Append(tmp);
MFQList.unlock();
}
void DBAsync::Process() {
DBAsyncWork* tmpWork;
MCurrentWork.lock();
while ((CurrentWork = InListPop())) {
MCurrentWork.unlock();
//move from queued to executing
Status tmpStatus = CurrentWork->SetStatus(Executing);
if (tmpStatus == Queued) {
//execute the work
ProcessWork(CurrentWork);
tmpWork = CurrentWork;
MCurrentWork.lock();
CurrentWork = 0;
MCurrentWork.unlock();
//move from executing to finished
tmpStatus = tmpWork->SetStatus(DBAsync::Finished);
if (tmpStatus != Executing) {
if (tmpStatus != Canceled) {
std::cout << "Error: Unexpected DBAsyncWork->Status in DBAsync::Process #1" << std::endl;
}
MCurrentWork.lock();
safe_delete(tmpWork);
}
else {
//call callbacks or put results on finished queue
DispatchWork(tmpWork);
Sleep(25);
MCurrentWork.lock();
}
}
else {
if (tmpStatus != Canceled) {
std::cout << "Error: Unexpected DBAsyncWork->Status in DBAsync::Process #2" << std::endl;
}
MCurrentWork.lock();
safe_delete(CurrentWork);
}
}
MCurrentWork.unlock();
}
void DBAsync::CheckTimeout() {
try{
MFQList.lock();
LinkedListIterator<DBAsyncFinishedQueue**> iterator(FQList);
iterator.Reset();
while (iterator.MoreElements()) {
(*iterator.GetData())->CheckTimeouts();
iterator.Advance();
}
MFQList.unlock();
}
catch(...){
}
}
void DBAsync::CommitWrites() {
#if DEBUG_MYSQL_QUERIES >= 2
std::cout << "DBAsync::CommitWrites() called." << std::endl;
#endif
DBAsyncWork* tmpWork;
while ((tmpWork = InListPopWrite())) {
Status tmpStatus = tmpWork->SetStatus(Executing);
if (tmpStatus == Queued) {
ProcessWork(tmpWork);
tmpStatus = tmpWork->SetStatus(DBAsync::Finished);
if (tmpStatus != Executing) {
if (tmpStatus != Canceled) {
std::cout << "Error: Unexpected DBAsyncWork->Status in DBAsync::CommitWrites #1" << std::endl;
}
safe_delete(tmpWork);
}
else {
DispatchWork(tmpWork);
}
}
else {
if (tmpStatus != Canceled) {
std::cout << "Error: Unexpected DBAsyncWork->Status in DBAsync::CommitWrites #2" << std::endl;
}
safe_delete(tmpWork);
}
}
}
void DBAsync::ProcessWork(DBAsyncWork* iWork, bool iSleep) {
DBAsyncQuery* CurrentQuery;
while ((CurrentQuery = iWork->PopQuery())) {
CurrentQuery->Process(pDBC);
iWork->PushAnswer(CurrentQuery);
if (iSleep)
Sleep(1);
}
}
void DBAsync::DispatchWork(DBAsyncWork* iWork) {
//if this work has a callback, call it
//otherwise, stick the work on the finish queue
if (iWork->pCB) {
if (iWork->pCB(iWork))
safe_delete(iWork);
}
else {
if (!iWork->pDBAFQ->Push(iWork))
safe_delete(iWork);
}
}
DBAsyncFinishedQueue::DBAsyncFinishedQueue(uint32 iTimeout) {
pTimeout = iTimeout;
}
DBAsyncFinishedQueue::~DBAsyncFinishedQueue() {
}
void DBAsyncFinishedQueue::CheckTimeouts() {
if (pTimeout == 0xFFFFFFFF)
return;
MLock.lock();
LinkedListIterator<DBAsyncWork*> iterator(list);
iterator.Reset();
while (iterator.MoreElements()) {
if (iterator.GetData()->CheckTimeout(pTimeout))
iterator.RemoveCurrent(true);
iterator.Advance();
}
MLock.unlock();
}
DBAsyncWork* DBAsyncFinishedQueue::Pop() {
DBAsyncWork* ret = 0;
MLock.lock();
ret = list.Pop();
MLock.unlock();
return ret;
}
DBAsyncWork* DBAsyncFinishedQueue::Find(uint32 iWorkID) {
DBAsyncWork* ret = 0;
MLock.lock();
LinkedListIterator<DBAsyncWork*> iterator(list);
iterator.Reset();
while (iterator.MoreElements()) {
if (iterator.GetData()->GetWorkID() == iWorkID) {
ret = iterator.GetData();
iterator.RemoveCurrent(false);
break;
}
iterator.Advance();
}
MLock.unlock();
return ret;
}
DBAsyncWork* DBAsyncFinishedQueue::PopByWPT(uint32 iWPT) {
DBAsyncWork* ret = 0;
MLock.lock();
LinkedListIterator<DBAsyncWork*> iterator(list);
iterator.Reset();
while (iterator.MoreElements()) {
if (iterator.GetData()->WPT() == iWPT) {
ret = iterator.GetData();
iterator.RemoveCurrent(false);
break;
}
iterator.Advance();
}
MLock.unlock();
return ret;
}
bool DBAsyncFinishedQueue::Push(DBAsyncWork* iDBAW) {
if (!this)
return false;
MLock.lock();
list.Append(iDBAW);
MLock.unlock();
return true;
}
DBAsyncWork::DBAsyncWork(Database *db, DBAsyncFinishedQueue* iDBAFQ, uint32 iWPT, DBAsync::Type iType, uint32 iTimeout)
: m_db(db)
{
pstatus = DBAsync::AddingWork;
pType = iType;
pExecuteAfter = 0;
pWorkID = 0;
pDBAFQ = iDBAFQ;
pCB = 0;
pWPT = iWPT;
pQuestionCount = 0;
pAnswerCount = 0;
pTimeout = iTimeout;
pTSFinish = 0;
}
DBAsyncWork::DBAsyncWork(Database *db, DBWorkCompleteCallBack iCB, uint32 iWPT, DBAsync::Type iType, uint32 iTimeout)
: m_db(db)
{
pstatus = DBAsync::AddingWork;
pType = iType;
pExecuteAfter = 0;
pWorkID = 0;
pDBAFQ = 0;
pCB = iCB;
pWPT = iWPT;
pQuestionCount = 0;
pAnswerCount = 0;
pTimeout = iTimeout;
pTSFinish = 0;
}
DBAsyncWork::~DBAsyncWork() {
DBAsyncQuery* dbaq = 0;
while ((dbaq = todo.pop()))
safe_delete(dbaq);
while ((dbaq = done.pop()))
safe_delete(dbaq);
while ((dbaq = todel.pop()))
safe_delete(dbaq);
}
bool DBAsyncWork::AddQuery(DBAsyncQuery** iDBAQ) {
bool ret;
MLock.lock();
if (pstatus != DBAsync::AddingWork)
ret = false;
else {
ret = true;
pQuestionCount++;
todo.push(*iDBAQ);
(*iDBAQ)->pstatus = DBAsync::Queued;
*iDBAQ = 0;
}
MLock.unlock();
return ret;
}
bool DBAsyncWork::AddQuery(uint32 iQPT, char** iQuery, uint32 iQueryLen, bool iGetResultSet, bool iGetErrbuf) {
DBAsyncQuery* DBAQ = new DBAsyncQuery(iQPT, iQuery, iQueryLen, iGetResultSet, iGetErrbuf);
if (AddQuery(&DBAQ))
return true;
else {
safe_delete(DBAQ);
return false;
}
}
bool DBAsyncWork::SetWorkID(uint32 iWorkID) {
bool ret = true;
MLock.lock();
if (pWorkID)
ret = false;
else
pWorkID = iWorkID;
MLock.unlock();
return ret;
}
uint32 DBAsyncWork::GetWorkID() {
uint32 ret;
MLock.lock();
ret = pWorkID;
MLock.unlock();
return ret;
}
uint32 DBAsyncWork::WPT() {
uint32 ret;
MLock.lock();
ret = pWPT;
MLock.unlock();
return ret;
}
DBAsync::Type DBAsyncWork::Type() {
DBAsync::Type ret;
MLock.lock();
ret = pType;
MLock.unlock();
return ret;
}
DBAsyncQuery* DBAsyncWork::PopAnswer() {
DBAsyncQuery* ret;
MLock.lock();
ret = done.pop();
if (ret)
pAnswerCount--;
todel.push(ret);
MLock.unlock();
return ret;
}
bool DBAsyncWork::CheckTimeout(uint32 iFQTimeout) {
if (pTimeout == 0xFFFFFFFF)
return false;
bool ret = false;
MLock.lock();
if (pTimeout > iFQTimeout)
iFQTimeout = pTimeout;
if (Timer::GetCurrentTime() > (pTSFinish + iFQTimeout))
ret = true;
MLock.unlock();
return ret;
}
//sets the work's status to the supplied value and returns
//the revious status
DBAsync::Status DBAsyncWork::SetStatus(DBAsync::Status iStatus) {
DBAsync::Status ret;
MLock.lock();
if (iStatus == DBAsync::Finished)
pTSFinish = Timer::GetCurrentTime();
ret = pstatus;
pstatus = iStatus;
MLock.unlock();
return ret;
}
bool DBAsyncWork::Cancel() {
bool ret;
MLock.lock();
if (pstatus != DBAsync::Finished) {
pstatus = DBAsync::Canceled;
ret = true;
}
else
ret = false;
MLock.unlock();
return ret;
}
bool DBAsyncWork::IsCancled() {
bool ret;
MLock.lock();
ret = (bool) (pstatus == DBAsync::Canceled);
MLock.unlock();
return ret;
}
DBAsyncQuery* DBAsyncWork::PopQuery() {
DBAsyncQuery* ret = 0;
MLock.lock();
ret = todo.pop();
if (ret)
pQuestionCount--;
MLock.unlock();
return ret;
}
void DBAsyncWork::PushAnswer(DBAsyncQuery* iDBAQ) {
MLock.lock();
done.push(iDBAQ);
pAnswerCount++;
MLock.unlock();
}
DBAsyncQuery::DBAsyncQuery(uint32 iQPT, char** iQuery, uint32 iQueryLen, bool iGetResultSet, bool iGetErrbuf) {
if (iQueryLen == 0xFFFFFFFF)
pQueryLen = strlen(*iQuery);
else
pQueryLen = iQueryLen;
pQuery = *iQuery;
*iQuery = 0;
Init(iQPT, iGetResultSet, iGetErrbuf);
}
DBAsyncQuery::DBAsyncQuery(uint32 iQPT, const char* iQuery, uint32 iQueryLen, bool iGetResultSet, bool iGetErrbuf) {
if (iQueryLen == 0xFFFFFFFF)
pQueryLen = strlen(iQuery);
else
pQueryLen = iQueryLen;
pQuery = strn0cpy(new char[pQueryLen+1], iQuery, pQueryLen+1);
Init(iQPT, iGetResultSet, iGetErrbuf);
}
void DBAsyncQuery::Init(uint32 iQPT, bool iGetResultSet, bool iGetErrbuf) {
pstatus = DBAsync::AddingWork;
pQPT = iQPT;
pGetResultSet = iGetResultSet;
pGetErrbuf = iGetErrbuf;
pmysqlsuccess = false;
perrbuf = 0;
perrnum = 0;
presult = 0;
paffected_rows = 0;
plast_insert_id = 0;
}
DBAsyncQuery::~DBAsyncQuery() {
safe_delete_array(perrbuf);
safe_delete_array(pQuery);
if (presult)
mysql_free_result(presult);
}
bool DBAsyncQuery::GetAnswer(char* errbuf, MYSQL_RES** result, uint32* affected_rows, uint32* last_insert_id, uint32* errnum) {
if (pstatus != DBAsync::Finished) {
if (errbuf)
snprintf(errbuf, MYSQL_ERRMSG_SIZE, "Error: Query not finished.");
if (errnum)
*errnum = UINT_MAX;
return false;
}
if (errbuf) {
if (pGetErrbuf) {
if (perrbuf)
strn0cpy(errbuf, perrbuf, MYSQL_ERRMSG_SIZE);
else
snprintf(errbuf, MYSQL_ERRMSG_SIZE, "Error message should've been saved, but hasnt. errno: %u", perrnum);
}
else
snprintf(errbuf, MYSQL_ERRMSG_SIZE, "Error message not saved. errno: %u", perrnum);
}
if (errnum)
*errnum = perrnum;
if (affected_rows)
*affected_rows = paffected_rows;
if (last_insert_id)
*last_insert_id = plast_insert_id;
if (result)
*result = presult;
return pmysqlsuccess;
}
void DBAsyncQuery::Process(DBcore* iDBC) {
pstatus = DBAsync::Executing;
if (pGetErrbuf)
perrbuf = new char[MYSQL_ERRMSG_SIZE];
MYSQL_RES** resultPP = 0;
if (pGetResultSet)
resultPP = &presult;
pmysqlsuccess = iDBC->RunQuery(pQuery, pQueryLen, perrbuf, resultPP, &paffected_rows, &plast_insert_id, &perrnum);
pstatus = DBAsync::Finished;
}

View File

@ -1,176 +0,0 @@
#ifndef DBASYNC_H
#define DBASYNC_H
#include "../common/dbcore.h"
#include "../common/timeoutmgr.h"
class DBAsyncFinishedQueue;
class DBAsyncWork;
class DBAsyncQuery;
class Database;
// Big daddy that owns the threads and does the work
class DBAsync : private Timeoutable {
public:
enum Status { AddingWork, Queued, Executing, Finished, Canceled };
enum Type { Read, Write, Both };
DBAsync(DBcore* iDBC);
~DBAsync();
bool StopThread();
uint32 AddWork(DBAsyncWork** iWork, uint32 iDelay = 0);
bool CancelWork(uint32 iWorkID);
void CommitWrites();
void AddFQ(DBAsyncFinishedQueue* iDBAFQ);
protected:
//things related to the processing thread:
friend ThreadReturnType DBAsyncLoop(void* tmp);
Mutex MLoopRunning;
Condition CInList;
bool RunLoop();
void Process();
private:
virtual void CheckTimeout();
void ProcessWork(DBAsyncWork* iWork, bool iSleep = true);
void DispatchWork(DBAsyncWork* iWork);
inline uint32 GetNextID() { return pNextID++; }
DBAsyncWork* InListPop();
DBAsyncWork* InListPopWrite(); // Ignores delay
void OutListPush(DBAsyncWork* iDBAW);
Mutex MRunLoop;
bool pRunLoop;
DBcore* pDBC;
uint32 pNextID;
Mutex MInList;
LinkedList<DBAsyncWork*> InList;
Mutex MFQList;
LinkedList<DBAsyncFinishedQueue**> FQList;
// Mutex for outside access to current work & when current work is being changed.
// NOT locked when CurrentWork is being accessed by the DBAsync thread.
// Never change pointer from outside DBAsync thread!
// Only here for access to thread-safe DBAsyncWork functions.
Mutex MCurrentWork;
DBAsyncWork* CurrentWork;
};
/*
DB Work Complete Callback:
This will be called under the DBAsync thread! Never access any non-threadsafe
data/functions/classes. (ie: zone, entitylist, client, etc are not threadsafe)
Function prototype:
return value: true if we should delete the data, false if we should keep it
*/
typedef bool(*DBWorkCompleteCallBack)(DBAsyncWork*);
class DBAsyncFinishedQueue {
public:
DBAsyncFinishedQueue(uint32 iTimeout = 90000);
~DBAsyncFinishedQueue();
DBAsyncWork* Pop();
DBAsyncWork* PopByWPT(uint32 iWPT);
DBAsyncWork* Find(uint32 iWPT);
bool Push(DBAsyncWork* iDBAW);
void CheckTimeouts();
private:
Mutex MLock;
uint32 pTimeout;
LinkedList<DBAsyncWork*> list;
};
// Container class for multiple queries
class DBAsyncWork {
public:
DBAsyncWork(Database *db, DBAsyncFinishedQueue* iDBAFQ, uint32 iWPT = 0, DBAsync::Type iType = DBAsync::Both, uint32 iTimeout = 0);
DBAsyncWork(Database *db, DBWorkCompleteCallBack iCB, uint32 iWPT = 0, DBAsync::Type iType = DBAsync::Both, uint32 iTimeout = 0);
~DBAsyncWork();
bool AddQuery(DBAsyncQuery** iDBAQ);
bool AddQuery(uint32 iQPT, char** iQuery, uint32 iQueryLen = 0xFFFFFFFF, bool iGetResultSet = true, bool iGetErrbuf = true);
uint32 WPT();
DBAsync::Type Type();
// Pops finished queries off the work
DBAsyncQuery* PopAnswer();
uint32 QueryCount();
Database *GetDB() const { return(m_db); }
bool CheckTimeout(uint32 iFQTimeout);
bool SetWorkID(uint32 iWorkID);
uint32 GetWorkID();
protected:
friend class DBAsync;
DBAsync::Status SetStatus(DBAsync::Status iStatus);
bool Cancel();
bool IsCancled();
DBAsyncQuery* PopQuery(); // Get query to be run
void PushAnswer(DBAsyncQuery* iDBAQ); // Push answer back into workset
// not mutex'd cause only to be accessed from dbasync class
uint32 pExecuteAfter;
private:
Mutex MLock;
uint32 pQuestionCount;
uint32 pAnswerCount;
uint32 pWorkID;
uint32 pWPT;
uint32 pTimeout;
uint32 pTSFinish; // timestamp when finished
DBAsyncFinishedQueue* pDBAFQ; //we do now own this pointer
DBWorkCompleteCallBack pCB;
DBAsync::Status pstatus;
DBAsync::Type pType;
MyQueue<DBAsyncQuery> todo;
MyQueue<DBAsyncQuery> done;
MyQueue<DBAsyncQuery> todel;
Database *const m_db; //we do now own this pointer
};
// Container class for the query information
class DBAsyncQuery {
public:
DBAsyncQuery(uint32 iQPT, char** iQuery, uint32 iQueryLen = 0xFFFFFFFF, bool iGetResultSet = true, bool iGetErrbuf = true);
DBAsyncQuery(uint32 iQPT, const char* iQuery, uint32 iQueryLen = 0xFFFFFFFF, bool iGetResultSet = true, bool iGetErrbuf = true);
~DBAsyncQuery();
bool GetAnswer(char* errbuf = 0, MYSQL_RES** result = 0, uint32* affected_rows = 0, uint32* last_insert_id = 0, uint32* errnum = 0);
inline uint32 QPT() { return pQPT; }
protected:
friend class DBAsyncWork;
uint32 pQPT;
friend class DBAsync;
void Process(DBcore* iDBC);
void Init(uint32 iQPT, bool iGetResultSet, bool iGetErrbuf);
DBAsync::Status pstatus;
char* pQuery;
uint32 pQueryLen;
bool pGetResultSet;
bool pGetErrbuf;
bool pmysqlsuccess;
char* perrbuf;
uint32 perrnum;
uint32 paffected_rows;
uint32 plast_insert_id;
MYSQL_RES* presult;
};
void AsyncLoadVariables(DBAsync *dba, Database *db);
#endif

View File

@ -800,9 +800,12 @@ struct SuspendedMinion_Struct
** Length: 4308 bytes
** 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_LANGUAGE = 28;
static const uint32 MAX_PP_SPELLBOOK = 720; // Set for all functions
static const uint32 MAX_PP_MEMSPELL = 12; // Set to latest client so functions can work right
static const uint32 MAX_PP_REF_SPELLBOOK = 480; // Set for Player Profile size retain
static const uint32 MAX_PP_REF_MEMSPELL = 9; // Set for Player Profile size retain
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;
@ -880,7 +883,7 @@ struct PlayerProfile_Struct
/*0245*/ uint8 guildbanker;
/*0246*/ uint8 unknown0246[6]; //
/*0252*/ uint32 intoxication;
/*0256*/ uint32 spellSlotRefresh[MAX_PP_MEMSPELL]; //in ms
/*0256*/ uint32 spellSlotRefresh[MAX_PP_REF_MEMSPELL]; //in ms
/*0292*/ uint32 abilitySlotRefresh;
/*0296*/ uint8 haircolor; // Player hair color
/*0297*/ uint8 beardcolor; // Player beard color
@ -919,9 +922,9 @@ struct PlayerProfile_Struct
/*2505*/ uint8 unknown2541[47]; // ?
/*2552*/ uint8 languages[MAX_PP_LANGUAGE];
/*2580*/ uint8 unknown2616[4];
/*2584*/ uint32 spell_book[MAX_PP_SPELLBOOK];
/*2584*/ uint32 spell_book[MAX_PP_REF_SPELLBOOK];
/*4504*/ uint8 unknown4540[128]; // Was [428] all 0xff
/*4632*/ uint32 mem_spells[MAX_PP_MEMSPELL];
/*4632*/ uint32 mem_spells[MAX_PP_REF_MEMSPELL];
/*4668*/ uint8 unknown4704[32]; //
/*4700*/ float y; // Player y position
/*4704*/ float x; // Player x position

View File

@ -32,6 +32,7 @@ MySQLRequestResult::MySQLRequestResult(MYSQL_RES* result, uint32 rowsAffected, u
void MySQLRequestResult::FreeInternals()
{
safe_delete_array(m_ErrorBuffer);
if (m_Result != nullptr)

View File

@ -40,7 +40,7 @@ public:
MySQLRequestResult& operator=(MySQLRequestResult&& other);
bool Success() const { return m_Success;}
std::string ErrorMessage() const {return std::string(m_ErrorBuffer);}
std::string ErrorMessage() const { return m_ErrorBuffer ? std::string(m_ErrorBuffer) : std::string(""); }
uint32 ErrorNumber() const {return m_ErrorNumber;}
uint32 RowsAffected() const {return m_RowsAffected;}
uint32 RowCount() const {return m_RowCount;}

View File

@ -61,46 +61,6 @@ bool SharedDatabase::SetHideMe(uint32 account_id, uint8 hideme)
return true;
}
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;
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);
}
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, ", 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));
}
uint8 SharedDatabase::GetGMSpeed(uint32 account_id)
{
@ -386,12 +346,11 @@ int32 SharedDatabase::GetSharedPlatinum(uint32 account_id)
return 0;
}
bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add)
{
bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE account SET sharedplat = sharedplat + %i WHERE id = %i", amount_to_add, account_id), errbuf)) {
if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE `account` SET `sharedplat` = `sharedplat` + %i WHERE id = %i", amount_to_add, account_id), errbuf)) {
std::cerr << "Error in SetSharedPlatinum query '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
return false;
@ -401,35 +360,24 @@ bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add)
return true;
}
bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) {
const Item_Struct* myitem;
RunQuery
(
query,
MakeAnyLenString
(
&query,
"SELECT itemid, item_charges, slot FROM starting_items "
"WHERE (race = %i or race = 0) AND (class = %i or class = 0) AND "
"(deityid = %i or deityid=0) AND (zoneid = %i or zoneid = 0) AND "
"gm <= %i ORDER BY id",
si_race, si_class, si_deity, si_current_zone, admin_level
),
errbuf,
&result
);
safe_delete_array(query);
while((row = mysql_fetch_row(result))) {
int itemid = atoi(row[0]);
int charges = atoi(row[1]);
int slot = atoi(row[2]);
uint32 itemid = 0;
uint32 charges = 0;
uint32 slot = 0;
auto query = StringFormat(
"SELECT `itemid`, `item_charges`, `slot` FROM `starting_items`"
" WHERE (`race` = %i OR `race` = 0)"
" AND (`class` = %i OR `class` = 0)"
" AND (`deityid` = %i OR `deityid` = 0)"
" AND (`zoneid` = %i OR `zoneid` = 0)"
" AND gm <= %i ORDER BY id",
si_race, si_class, si_deity, si_current_zone, admin_level);
auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) {
itemid = atoi(row[0]);
charges = atoi(row[1]);
slot = atoi(row[2]);
myitem = GetItem(itemid);
if(!myitem)
continue;
@ -439,9 +387,6 @@ bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv,
inv->PutItem(slot, *myinst);
safe_delete(myinst);
}
if(result) mysql_free_result(result);
return true;
}
@ -675,8 +620,13 @@ bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv)
bool ret = false;
// Retrieve character inventory
if (RunQuery(query, MakeAnyLenString(&query, "SELECT slotid,itemid,charges,color,augslot1,augslot2,augslot3,augslot4,augslot5,"
"instnodrop,custom_data FROM inventory INNER JOIN character_ ch ON ch.id=charid WHERE ch.name='%s' AND ch.account_id=%i ORDER BY slotid",
if (RunQuery(query, MakeAnyLenString(&query,
" SELECT `slotid`, `itemid`, `charges`, `color`, `augslot1`, `augslot2`, `augslot3`, `augslot4`, `augslot5`, `instnodrop`, `custom_data`"
" FROM `inventory`"
" INNER JOIN character_ ch ON ch.id = charid"
" WHERE ch.NAME = '%s'"
" AND ch.account_id = % i"
" ORDER BY `slotid`",
name, account_id), errbuf, &result))
{
while ((row = mysql_fetch_row(result))) {
@ -736,7 +686,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv)
}
}
}
if (slot_id>=8000 && slot_id <= 8999)
if (slot_id >= 8000 && slot_id <= 8999)
put_slot_id = inv->PushCursor(*inst);
else
put_slot_id = inv->PutItem(slot_id, *inst);
@ -2053,8 +2003,7 @@ const LootDrop_Struct* SharedDatabase::GetLootDrop(uint32 lootdrop_id) {
return nullptr;
}
void SharedDatabase::GetPlayerInspectMessage(char* playername, InspectMessage_Struct* message) {
void SharedDatabase::GetPlayerInspectMessage(char* playername, InspectMessage_Struct* message) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;

View File

@ -34,9 +34,6 @@ public:
SharedDatabase(const char* host, const char* user, const char* passwd, const char* database,uint32 port);
virtual ~SharedDatabase();
/* Temp */
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);
bool SetPlayerProfile(uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets);
/*
* General Character Related Stuff
*/

View File

@ -64,8 +64,6 @@ extern ClientList client_list;
extern uint32 numclients;
extern volatile bool RunLoops;
Client::Client(EQStreamInterface* ieqs)
: autobootup_timeout(RuleI(World, ZoneAutobootTimeoutMS)),
CLE_keepalive_timer(RuleI(World, ClientKeepaliveTimeoutMS)),
@ -128,9 +126,8 @@ void Client::SendLogServer()
safe_delete(outapp);
}
void Client::SendEnterWorld(std::string name)
{
char char_name[32]= { 0 };
void Client::SendEnterWorld(std::string name) {
char char_name[32]= { 0 };
if (pZoning && database.GetLiveChar(GetAccountID(), char_name)) {
if(database.GetAccountIDByChar(char_name) != GetAccountID()) {
eqs->Close();
@ -472,7 +469,6 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) {
}
bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) {
if (GetAccountID() == 0) {
clog(WORLD__CLIENT_ERR,"Name approval request with no logged in account");
return false;
@ -491,19 +487,10 @@ bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) {
outapp->size = 1;
bool valid;
if(!database.CheckNameFilter(char_name)) {
valid = false;
}
else if(char_name[0] < 'A' && char_name[0] > 'Z') {
//name must begin with an upper-case letter.
valid = false;
}
else if (database.ReserveName(GetAccountID(), char_name)) {
valid = true;
}
else {
valid = false;
}
if(!database.CheckNameFilter(char_name)) { valid = false; }
else if (char_name[0] < 'A' && char_name[0] > 'Z') { valid = false; } /* Name must begin with an upper-case letter. */
else if (database.ReserveName(GetAccountID(), char_name)) { valid = true; }
else { valid = false; }
outapp->pBuffer[0] = valid? 1 : 0;
QueuePacket(outapp);
safe_delete(outapp);
@ -642,13 +629,11 @@ bool Client::HandleCharacterCreateRequestPacket(const EQApplicationPacket *app)
}
bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) {
if (GetAccountID() == 0)
{
if (GetAccountID() == 0) {
clog(WORLD__CLIENT_ERR,"Account ID not set; unable to create character.");
return false;
}
else if (app->size != sizeof(CharCreate_Struct))
{
else if (app->size != sizeof(CharCreate_Struct)) {
clog(WORLD__CLIENT_ERR,"Wrong size on OP_CharacterCreate. Got: %d, Expected: %d",app->size,sizeof(CharCreate_Struct));
DumpPacket(app);
// the previous behavior was essentially returning true here
@ -657,8 +642,7 @@ bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) {
}
CharCreate_Struct *cc = (CharCreate_Struct*)app->pBuffer;
if(OPCharCreate(char_name, cc) == false)
{
if(OPCharCreate(char_name, cc) == false) {
database.DeleteCharacter(char_name);
EQApplicationPacket *outapp = new EQApplicationPacket(OP_ApproveName, 1);
outapp->pBuffer[0] = 0;
@ -675,8 +659,7 @@ bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) {
return true;
}
bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
if (GetAccountID() == 0) {
clog(WORLD__CLIENT_ERR,"Enter world with no logged in account");
eqs->Close();
@ -713,8 +696,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
return true;
}
if(!pZoning && ew->return_home && !ew->tutorial)
{
if(!pZoning && ew->return_home && !ew->tutorial) {
CharacterSelect_Struct* cs = new CharacterSelect_Struct;
memset(cs, 0, sizeof(CharacterSelect_Struct));
database.GetCharSelectInfo(GetAccountID(), cs);
@ -733,12 +715,10 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
}
safe_delete(cs);
if(home_enabled)
{
if(home_enabled) {
zoneID = database.MoveCharacterToBind(charid,4);
}
else
{
else {
clog(WORLD__CLIENT_ERR,"'%s' is trying to go home before they're able...",char_name);
database.SetHackerFlag(GetAccountName(), char_name, "MQGoHome: player tried to go home before they were able.");
eqs->Close();
@ -807,16 +787,16 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
database.SetLoginFlags(charid, false, false, 1);
}
else{
uint32 groupid=database.GetGroupID(char_name);
if(groupid>0){
char* leader=0;
char leaderbuf[64]={0};
if((leader=database.GetGroupLeaderForLogin(char_name,leaderbuf)) && strlen(leader)>1){
uint32 groupid = database.GetGroupID(char_name);
if(groupid > 0){
char* leader = 0;
char leaderbuf[64] = {0};
if((leader = database.GetGroupLeaderForLogin(char_name, leaderbuf)) && strlen(leader)>1){
EQApplicationPacket* outapp3 = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct));
GroupJoin_Struct* gj=(GroupJoin_Struct*)outapp3->pBuffer;
gj->action=8;
strcpy(gj->yourname,char_name);
strcpy(gj->membername,leader);
strcpy(gj->yourname, char_name);
strcpy(gj->membername, leader);
QueuePacket(outapp3);
safe_delete(outapp3);
}
@ -895,8 +875,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
bool Client::HandleDeleteCharacterPacket(const EQApplicationPacket *app) {
uint32 char_acct_id = database.GetAccountIDByChar((char*)app->pBuffer);
if(char_acct_id == GetAccountID())
{
if(char_acct_id == GetAccountID()) {
clog(WORLD__CLIENT,"Delete character: %s",app->pBuffer);
database.DeleteCharacter((char *)app->pBuffer);
SendCharInfo();
@ -1347,8 +1326,7 @@ void Client::SendApproveWorld()
safe_delete(outapp);
}
bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
{
bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) {
PlayerProfile_Struct pp;
ExtendedProfile_Struct ext;
Inventory inv;
@ -1356,12 +1334,11 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
char startzone[50]={0};
uint32 i;
struct in_addr in;
int stats_sum = cc->STR + cc->STA + cc->AGI + cc->DEX +
cc->WIS + cc->INT + cc->CHA;
int stats_sum = cc->STR + cc->STA + cc->AGI + cc->DEX + cc->WIS + cc->INT + cc->CHA;
in.s_addr = GetIP();
clog(WORLD__CLIENT,"Character creation request from %s LS#%d (%s:%d) : ", GetCLE()->LSName(), GetCLE()->LSID(), inet_ntoa(in), GetPort());
clog(WORLD__CLIENT,"Name: %s", name);
clog(WORLD__CLIENT,"Race: %d Class: %d Gender: %d Deity: %d Start zone: %d",
@ -1374,38 +1351,23 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
clog(WORLD__CLIENT,"Hairstyle: %d Haircolor: %d", cc->hairstyle, cc->haircolor);
clog(WORLD__CLIENT,"Beard: %d Beardcolor: %d", cc->beard, cc->beardcolor);
// validate the char creation struct
/* Validate the char creation struct */
if(ClientVersionBit & BIT_SoFAndLater) {
if(!CheckCharCreateInfoSoF(cc))
{
if(!CheckCharCreateInfoSoF(cc)) {
clog(WORLD__CLIENT_ERR,"CheckCharCreateInfo did not validate the request (bad race/class/stats)");
return false;
}
} else {
if(!CheckCharCreateInfoTitanium(cc))
{
if(!CheckCharCreateInfoTitanium(cc)) {
clog(WORLD__CLIENT_ERR,"CheckCharCreateInfo did not validate the request (bad race/class/stats)");
return false;
}
}
// Convert incoming cc_s to the new PlayerProfile_Struct
/* Convert incoming cc_s to the new PlayerProfile_Struct */
memset(&pp, 0, sizeof(PlayerProfile_Struct)); // start building the profile
InitExtendedProfile(&ext);
strn0cpy(pp.name, name, 63);
// clean the capitalization of the name
#if 0 // on second thought, don't - this will just make the creation fail
// because the name won't match what was already reserved earlier
for (i = 0; pp.name[i] && i < 63; i++)
{
if(!isalpha(pp.name[i]))
return false;
pp.name[i] = tolower(pp.name[i]);
}
pp.name[0] = toupper(pp.name[0]);
#endif
pp.race = cc->race;
pp.class_ = cc->class_;
@ -1432,44 +1394,39 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
pp.lastlogin = bday;
pp.level = 1;
pp.points = 5;
pp.cur_hp = 1000; // 1k hp during dev only
//what was the point of this? zone dosent handle this:
//pp.expAA = 0xFFFFFFFF;
pp.cur_hp = 1000; // 1k hp during dev only
pp.hunger_level = 6000;
pp.thirst_level = 6000;
// FIXME: FV roleplay, database goodness...
// Racial Languages
SetRacialLanguages( &pp ); // bUsh
SetRaceStartingSkills( &pp ); // bUsh
SetClassStartingSkills( &pp ); // bUsh
/* Racial Languages */
SetRacialLanguages( &pp );
SetRaceStartingSkills( &pp );
SetClassStartingSkills( &pp );
pp.skills[SkillSenseHeading] = 200;
// Some one fucking fix this to use a field name. -Doodman
//pp.unknown3596[28] = 15; // @bp: This is to enable disc usage
// strcpy(pp.servername, WorldConfig::get()->ShortName.c_str());
for(i = 0; i < MAX_PP_SPELLBOOK; i++)
for (i = 0; i < MAX_PP_REF_SPELLBOOK; i++)
pp.spell_book[i] = 0xFFFFFFFF;
for(i = 0; i < MAX_PP_MEMSPELL; i++)
for(i = 0; i < MAX_PP_REF_MEMSPELL; i++)
pp.mem_spells[i] = 0xFFFFFFFF;
for(i = 0; i < BUFF_COUNT; i++)
pp.buffs[i].spellid = 0xFFFF;
/*
Was memset(pp.unknown3704, 0xffffffff, 8);
but I dont think thats what you really wanted to do...
memset is byte based
*/
//was memset(pp.unknown3704, 0xffffffff, 8);
//but I dont think thats what you really wanted to do...
//memset is byte based
//If server is PVP by default, make all character set to it.
/* If server is PVP by default, make all character set to it. */
pp.pvp = database.GetServerType() == 1 ? 1 : 0;
//If it is an SoF Client and the SoF Start Zone rule is set, send new chars there
/* If it is an SoF Client and the SoF Start Zone rule is set, send new chars there */
if((ClientVersionBit & BIT_SoFAndLater) && (RuleI(World, SoFStartZoneID) > 0)) {
clog(WORLD__CLIENT,"Found 'SoFStartZoneID' rule setting: %i", (RuleI(World, SoFStartZoneID)));
pp.zone_id = (RuleI(World, SoFStartZoneID));
@ -1478,11 +1435,9 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
else
clog(WORLD__CLIENT_ERR,"Error getting zone id for Zone ID %i", (RuleI(World, SoFStartZoneID)));
}
else
{
// if there's a startzone variable put them in there
if(database.GetVariable("startzone", startzone, 50))
{
else {
/* if there's a startzone variable put them in there */
if(database.GetVariable("startzone", startzone, 50)) {
clog(WORLD__CLIENT,"Found 'startzone' variable setting: %s", startzone);
pp.zone_id = database.GetZoneID(startzone);
if(pp.zone_id)
@ -1490,8 +1445,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
else
clog(WORLD__CLIENT_ERR,"Error getting zone id for '%s'", startzone);
}
else // otherwise use normal starting zone logic
{
else{ /* otherwise use normal starting zone logic */
bool ValidStartZone = false;
if(ClientVersionBit & BIT_TitaniumAndEarlier)
@ -1504,14 +1458,12 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
}
}
if(!pp.zone_id)
{
if(!pp.zone_id) {
pp.zone_id = 1; // qeynos
pp.x = pp.y = pp.z = -1;
}
if(!pp.binds[0].zoneId)
{
if(!pp.binds[0].zoneId) {
pp.binds[0].zoneId = pp.zone_id;
pp.binds[0].x = pp.x;
pp.binds[0].y = pp.y;
@ -1519,7 +1471,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
pp.binds[0].heading = pp.heading;
}
// set starting city location to the initial bind point
/* Set Starting city */
pp.binds[4] = pp.binds[0];
@ -1528,28 +1480,23 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
clog(WORLD__CLIENT,"Bind location: %s %0.2f, %0.2f, %0.2f",
database.GetZoneName(pp.binds[0].zoneId), pp.binds[0].x, pp.binds[0].y, pp.binds[0].z);
// Starting Items inventory
/* Starting Items inventory */
database.SetStartingItems(&pp, &inv, pp.race, pp.class_, pp.deity, pp.zone_id, pp.name, GetAdmin());
// now we give the pp and the inv we made to StoreCharacter
// to see if we can store it
if (!database.StoreCharacter(GetAccountID(), &pp, &inv, &ext))
{
if (!database.StoreCharacter(GetAccountID(), &pp, &inv)) {
clog(WORLD__CLIENT_ERR,"Character creation failed: %s", pp.name);
return false;
}
else
{
else {
clog(WORLD__CLIENT,"Character creation successful: %s", pp.name);
return true;
}
}
// returns true if the request is ok, false if there's an error
bool CheckCharCreateInfoSoF(CharCreate_Struct *cc)
{
bool CheckCharCreateInfoSoF(CharCreate_Struct *cc) {
if(!cc) return false;
_log(WORLD__CLIENT, "Validating char creation info...");

View File

@ -67,7 +67,6 @@
#endif
#include "../common/dbasync.h"
#include "../common/emu_tcp_server.h"
#include "../common/patches/patches.h"
#include "zoneserver.h"
@ -98,7 +97,6 @@ UCSConnection UCSLink;
QueryServConnection QSLink;
LauncherList launcher_list;
AdventureManager adventure_manager;
DBAsync *dbasync = nullptr;
volatile bool RunLoops = true;
uint32 numclients = 0;
uint32 numzones = 0;
@ -175,7 +173,6 @@ int main(int argc, char** argv) {
_log(WORLD__INIT_ERR, "Cannot continue without a database connection.");
return 1;
}
dbasync = new DBAsync(&database);
guild_mgr.SetDatabase(&database);
if (argc >= 2) {

View File

@ -21,7 +21,6 @@
#include "../common/string_util.h"
#include "../common/eq_packet_structs.h"
#include "../common/item.h"
#include "../common/dbasync.h"
#include "../common/rulesys.h"
#include <iostream>
#include <cstdlib>
@ -390,12 +389,16 @@ bool WorldDatabase::GetStartZoneSoF(PlayerProfile_Struct* in_pp, CharCreate_Stru
in_pp->x = in_pp->y = in_pp->z = in_pp->heading = in_pp->zone_id = 0;
in_pp->binds[0].x = in_pp->binds[0].y = in_pp->binds[0].z = in_pp->binds[0].zoneId = 0;
if(!RunQuery(query, MakeAnyLenString(&query, "SELECT x,y,z,heading,bind_id FROM start_zones WHERE zone_id=%i AND player_class=%i "
"AND player_deity=%i AND player_race=%i",
in_cc->start_zone,
in_cc->class_,
in_cc->deity,
in_cc->race), errbuf, &result))
if(!RunQuery(query, MakeAnyLenString(&query, "SELECT `x`, `y`, ``z, `heading`, `bind_id` "
" FROM `start_zones` "
" WHERE `zone_id` = %i "
" AND `player_class` = %i "
" AND player_deity=%i"
" AND player_race=%i",
in_cc->start_zone,
in_cc->class_,
in_cc->deity,
in_cc->race), errbuf, &result))
{
LogFile->write(EQEMuLog::Status, "SoF Start zone query failed: %s : %s\n", query, errbuf);
safe_delete_array(query);

View File

@ -652,17 +652,17 @@ bool ZoneServer::Process() {
client->Clearance(wtz->response);
}
case ServerOP_ZoneToZoneRequest: {
//
// solar: ZoneChange is received by the zone the player is in, then the
// zone sends a ZTZ which ends up here. This code then find the target
// (ingress point) and boots it if needed, then sends the ZTZ to it.
// The ingress server will decide wether the player can enter, then will
// send back the ZTZ to here. This packet is passed back to the egress
// server, which will send a ZoneChange response back to the client
// which can be an error, or a success, in which case the client will
// disconnect, and their zone location will be saved when ~Client is
// called, so it will be available when they ask to zone.
//
//
// solar: ZoneChange is received by the zone the player is in, then the
// zone sends a ZTZ which ends up here. This code then find the target
// (ingress point) and boots it if needed, then sends the ZTZ to it.
// The ingress server will decide wether the player can enter, then will
// send back the ZTZ to here. This packet is passed back to the egress
// server, which will send a ZoneChange response back to the client
// which can be an error, or a success, in which case the client will
// disconnect, and their zone location will be saved when ~Client is
// called, so it will be available when they ask to zone.
//
if(pack->size != sizeof(ZoneToZone_Struct))
@ -675,43 +675,31 @@ bool ZoneServer::Process() {
zlog(WORLD__ZONE,"ZoneToZone request for %s current zone %d req zone %d\n",
ztz->name, ztz->current_zone_id, ztz->requested_zone_id);
printf("\n\n ZoneToZone request for %s current zone %d req zone %d\n\n",
ztz->name, ztz->current_zone_id, ztz->requested_zone_id);
if(GetZoneID() == ztz->current_zone_id && GetInstanceID() == ztz->current_instance_id) // this is a request from the egress zone
{
/* This is a request from the egress zone */
if(GetZoneID() == ztz->current_zone_id && GetInstanceID() == ztz->current_instance_id) {
zlog(WORLD__ZONE,"Processing ZTZ for egress from zone for client %s\n", ztz->name);
if
(
ztz->admin < 80 &&
ztz->ignorerestrictions < 2 &&
zoneserver_list.IsZoneLocked(ztz->requested_zone_id)
)
{
if (ztz->admin < 80 && ztz->ignorerestrictions < 2 && zoneserver_list.IsZoneLocked(ztz->requested_zone_id)) {
ztz->response = 0;
SendPacket(pack);
break;
}
ZoneServer *ingress_server = nullptr;
if(ztz->requested_instance_id > 0)
{
if(ztz->requested_instance_id > 0) {
ingress_server = zoneserver_list.FindByInstanceID(ztz->requested_instance_id);
}
else
{
ingress_server = zoneserver_list.FindByZoneID(ztz->requested_zone_id);
else {
ingress_server = zoneserver_list.FindByZoneID(ztz->requested_zone_id);
}
if(ingress_server) // found a zone already running
{
/* Zone was already running*/
if(ingress_server) {
_log(WORLD__ZONE,"Found a zone already booted for %s\n", ztz->name);
ztz->response = 1;
}
else // need to boot one
{
/* Boot the Zone*/
else {
int server_id;
if ((server_id = zoneserver_list.TriggerBootup(ztz->requested_zone_id, ztz->requested_instance_id))){
_log(WORLD__ZONE,"Successfully booted a zone for %s\n", ztz->name);
@ -719,8 +707,7 @@ bool ZoneServer::Process() {
ztz->response = 1;
ingress_server = zoneserver_list.FindByID(server_id);
}
else
{
else {
_log(WORLD__ZONE_ERR,"FAILED to boot a zone for %s\n", ztz->name);
// bootup failed, send back error code 0
ztz->response = 0;
@ -728,27 +715,24 @@ bool ZoneServer::Process() {
}
if(ztz->response!=0 && client)
client->LSZoneChange(ztz);
SendPacket(pack); // send back to egress server
if(ingress_server) // if we couldn't boot one, this is 0
{
ingress_server->SendPacket(pack); // inform target server
}
SendPacket(pack); // send back to egress server
if(ingress_server) {
ingress_server->SendPacket(pack); // inform target server
}
}
else // this is response from the ingress server, route it back to the egress server
{
/* Response from Ingress server, route back to egress */
else{
zlog(WORLD__ZONE,"Processing ZTZ for ingress to zone for client %s\n", ztz->name);
ZoneServer *egress_server = nullptr;
if(ztz->current_instance_id > 0)
{
if(ztz->current_instance_id > 0) {
egress_server = zoneserver_list.FindByInstanceID(ztz->current_instance_id);
}
else
{
else {
egress_server = zoneserver_list.FindByZoneID(ztz->current_zone_id);
}
if(egress_server)
{
if(egress_server) {
egress_server->SendPacket(pack);
}
}
@ -786,21 +770,18 @@ bool ZoneServer::Process() {
delete whom;
break;
}
case ServerOP_RequestOnlineGuildMembers:
{
case ServerOP_RequestOnlineGuildMembers: {
ServerRequestOnlineGuildMembers_Struct *srogms = (ServerRequestOnlineGuildMembers_Struct*) pack->pBuffer;
zlog(GUILDS__IN_PACKETS, "ServerOP_RequestOnlineGuildMembers Recieved. FromID=%i GuildID=%i", srogms->FromID, srogms->GuildID);
client_list.SendOnlineGuildMembers(srogms->FromID, srogms->GuildID);
break;
}
case ServerOP_ClientVersionSummary:
{
case ServerOP_ClientVersionSummary: {
ServerRequestClientVersionSummary_Struct *srcvss = (ServerRequestClientVersionSummary_Struct*) pack->pBuffer;
client_list.SendClientVersionSummary(srcvss->Name);
break;
}
case ServerOP_ReloadRules:
{
case ServerOP_ReloadRules: {
zoneserver_list.SendPacket(pack);
RuleManager::Instance()->LoadRules(&database, "default");
break;
@ -1275,30 +1256,10 @@ bool ZoneServer::Process() {
case ServerOP_QueryServGeneric:
case ServerOP_Speech:
case ServerOP_QSPlayerLogTrades:
{
QSLink.SendPacket(pack);
break;
}
case ServerOP_QSPlayerLogHandins:
{
QSLink.SendPacket(pack);
break;
}
case ServerOP_QSPlayerLogNPCKills:
{
QSLink.SendPacket(pack);
break;
}
case ServerOP_QSPlayerLogDeletes:
{
QSLink.SendPacket(pack);
break;
}
case ServerOP_QSPlayerLogMoves:
{
QSLink.SendPacket(pack);
break;
}
case ServerOP_QSPlayerLogMerchantTransactions:
{
QSLink.SendPacket(pack);

View File

@ -119,7 +119,6 @@ SET(zone_sources
zone_logsys.cpp
zone_config.cpp
zonedb.cpp
zonedbasync.cpp
zoning.cpp
)
@ -207,7 +206,6 @@ SET(zone_headers
zone.h
zone_config.h
zonedb.h
zonedbasync.h
zonedump.h
)

View File

@ -73,8 +73,6 @@ extern uint32 numclients;
extern PetitionList petition_list;
bool commandlogged;
char entirecommand[255];
extern DBAsyncFinishedQueue MTdbafq;
extern DBAsync *dbasync;
Client::Client(EQStreamInterface* ieqs)
: Mob("No name", // name
@ -544,8 +542,9 @@ bool Client::Save(uint8 iCommitNow) {
/* Save Character Currency */
database.SaveCharacterCurrency(this->CharacterID(), &m_pp);
/* Save Character AA */
// SaveAA();
/* Save Current Bind Points : Sets Instance to 0 because it is currently not implemented */
database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[0].zoneId, 0, m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, 0, 0); /* Regular bind */
database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[4].zoneId, 0, m_pp.binds[4].x, m_pp.binds[4].y, m_pp.binds[4].z, 0, 1); /* Home Bind */
/* Save Character Buffs */
database.SaveBuffs(this);
@ -557,15 +556,11 @@ bool Client::Save(uint8 iCommitNow) {
/* Save Mercs */
if (GetMercInfo().MercTimerRemaining > RuleI(Mercs, UpkeepIntervalMS)){ GetMercInfo().MercTimerRemaining = RuleI(Mercs, UpkeepIntervalMS); }
if(GetMercTimer()->Enabled()) { GetMercInfo().MercTimerRemaining = GetMercTimer()->GetRemainingTime(); }
if (GetMercTimer()->Enabled()) { GetMercInfo().MercTimerRemaining = GetMercTimer()->GetRemainingTime(); }
if (GetMerc() && !dead) { }
else { memset(&m_mercinfo, 0, sizeof(struct MercInfo)); }
m_pp.lastlogin = time(nullptr);
if (pQueuedSaveWorkID) {
dbasync->CancelWork(pQueuedSaveWorkID);
pQueuedSaveWorkID = 0;
}
if (GetPet() && !GetPet()->IsFamiliar() && GetPet()->CastToNPC()->GetPetSpellID() && !dead) {
NPC *pet = GetPet()->CastToNPC();
@ -585,34 +580,10 @@ bool Client::Save(uint8 iCommitNow) {
p_timers.Store(&database);
/* Save Character Task */
SaveTaskState();
database.SaveCharacterTribute(this->CharacterID(), &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;
// }
/* Save Character Task */
SaveTaskState();
/* Save Character Data */
database.SaveCharacterData(this->CharacterID(), this->AccountID(), &m_pp);
@ -624,12 +595,6 @@ bool Client::Save(uint8 iCommitNow) {
}
void Client::SaveBackup() {
if (!RunLoops)
return;
char* query = 0;
DBAsyncWork* dbaw = new DBAsyncWork(&database, &DBAsyncCB_CharacterBackup, this->CharacterID(), DBAsync::Read);
dbaw->AddQuery(0, &query, MakeAnyLenString(&query, "Select id, UNIX_TIMESTAMP()-UNIX_TIMESTAMP(ts) as age from character_backup where charid=%u and backupreason=0 order by ts asc", this->CharacterID()), true);
dbasync->AddWork(&dbaw, 0);
}
CLIENTPACKET::CLIENTPACKET()
@ -1393,12 +1358,14 @@ bool Client::UpdateLDoNPoints(int32 points, uint32 theme)
void Client::SetSkill(SkillUseTypes skillid, uint16 value) {
if (skillid > HIGHEST_SKILL)
return;
m_pp.skills[skillid] = value; // We need to be able to #setskill 254 and 255 to reset skills
return;
m_pp.skills[skillid] = value; // We need to be able to #setskill 254 and 255 to reset skills
database.SaveCharacterSkill(this->CharacterID(), skillid, value);
EQApplicationPacket* outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct));
SkillUpdate_Struct* skill = (SkillUpdate_Struct*)outapp->pBuffer;
skill->skillId=skillid;
skill->skillId=skillid;
skill->value=value;
QueuePacket(outapp);
safe_delete(outapp);
@ -1414,10 +1381,12 @@ void Client::IncreaseLanguageSkill(int skill_id, int value) {
if (m_pp.languages[skill_id] > 100) //Lang skill above max
m_pp.languages[skill_id] = 100;
database.SaveCharacterLanguage(this->CharacterID(), skill_id, m_pp.languages[skill_id]);
EQApplicationPacket* outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct));
SkillUpdate_Struct* skill = (SkillUpdate_Struct*)outapp->pBuffer;
skill->skillId = 100 + skill_id;
skill->value = m_pp.languages[skill_id];
skill->value = m_pp.languages[skill_id];
QueuePacket(outapp);
safe_delete(outapp);
@ -2165,32 +2134,27 @@ void Client::AddMoneyToPP(uint64 copper, bool updateclient){
uint64 tmp2;
tmp = copper;
// Add Amount of Platinum
/* Add Amount of Platinum */
tmp2 = tmp/1000;
int32 new_val = m_pp.platinum + tmp2;
if(new_val < 0) {
m_pp.platinum = 0;
} else {
m_pp.platinum = m_pp.platinum + tmp2;
}
if(new_val < 0) { m_pp.platinum = 0; }
else { m_pp.platinum = m_pp.platinum + tmp2; }
tmp-=tmp2*1000;
//if (updateclient)
// SendClientMoneyUpdate(3,tmp2);
// Add Amount of Gold
/* Add Amount of Gold */
tmp2 = tmp/100;
new_val = m_pp.gold + tmp2;
if(new_val < 0) {
m_pp.gold = 0;
} else {
m_pp.gold = m_pp.gold + tmp2;
}
if(new_val < 0) { m_pp.gold = 0; }
else { m_pp.gold = m_pp.gold + tmp2; }
tmp-=tmp2*100;
//if (updateclient)
// SendClientMoneyUpdate(2,tmp2);
// Add Amount of Silver
/* Add Amount of Silver */
tmp2 = tmp/10;
new_val = m_pp.silver + tmp2;
if(new_val < 0) {
@ -2226,8 +2190,7 @@ void Client::AddMoneyToPP(uint64 copper, bool updateclient){
LogFile->write(EQEMuLog::Debug, "Client::AddMoneyToPP() %s should have: plat:%i gold:%i silver:%i copper:%i", GetName(), m_pp.platinum, m_pp.gold, m_pp.silver, m_pp.copper);
}
void Client::AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, bool updateclient){
void Client::EVENT_ITEM_ScriptStopReturn(){
/* Set a timestamp in an entity variable for plugin check_handin.pl in return_items
This will stopgap players from items being returned if global_npc.pl has a catch all return_items
*/
@ -2236,6 +2199,10 @@ void Client::AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 plat
gettimeofday(&read_time, 0);
sprintf(buffer, "%li.%li \n", read_time.tv_sec, read_time.tv_usec);
this->SetEntityVariable("Stop_Return", buffer);
}
void Client::AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, bool updateclient){
this->EVENT_ITEM_ScriptStopReturn();
int32 new_value = m_pp.platinum + platinum;
if(new_value >= 0 && new_value > m_pp.platinum)
@ -3184,6 +3151,7 @@ void Client::SetLanguageSkill(int langid, int value)
value = 100; //Max lang value
m_pp.languages[langid] = value;
database.SaveCharacterLanguage(this->CharacterID(), langid, value);
EQApplicationPacket* outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct));
SkillUpdate_Struct* skill = (SkillUpdate_Struct*)outapp->pBuffer;

View File

@ -234,7 +234,6 @@ public:
bool KeyRingCheck(uint32 item_id);
void KeyRingList();
virtual bool IsClient() const { return true; }
virtual void DBAWComplete(uint8 workpt_b1, 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);
@ -654,14 +653,14 @@ public:
void OnDisconnect(bool hard_disconnect);
uint16 GetSkillPoints() {return m_pp.points;}
void SetSkillPoints(int inp) {m_pp.points = inp;}
uint16 GetSkillPoints() { return m_pp.points;}
void SetSkillPoints(int inp) { m_pp.points = inp;}
void IncreaseSkill(int skill_id, int value = 1) { if (skill_id <= HIGHEST_SKILL) { m_pp.skills[skill_id] += value; } }
void IncreaseLanguageSkill(int skill_id, int value = 1);
virtual uint16 GetSkill(SkillUseTypes skill_id) const { if (skill_id <= HIGHEST_SKILL) { return((itembonuses.skillmod[skill_id] > 0)? m_pp.skills[skill_id]*(100 + itembonuses.skillmod[skill_id])/100 : m_pp.skills[skill_id]); } return 0; }
virtual uint16 GetSkill(SkillUseTypes skill_id) const { if (skill_id <= HIGHEST_SKILL) { return((itembonuses.skillmod[skill_id] > 0) ? m_pp.skills[skill_id] * (100 + itembonuses.skillmod[skill_id]) / 100 : m_pp.skills[skill_id]); } return 0; }
uint32 GetRawSkill(SkillUseTypes skill_id) const { if (skill_id <= HIGHEST_SKILL) { return(m_pp.skills[skill_id]); } return 0; }
bool HasSkill(SkillUseTypes skill_id) const;
bool HasSkill(SkillUseTypes skill_id) const;
bool CanHaveSkill(SkillUseTypes skill_id) const;
void SetSkill(SkillUseTypes skill_num, uint16 value);
void AddSkill(SkillUseTypes skillid, uint16 value);
@ -782,6 +781,7 @@ public:
int16 acmod();
// Item methods
void EVENT_ITEM_ScriptStopReturn();
uint32 NukeItem(uint32 itemnum, uint8 where_to_check =
(invWhereWorn | invWherePersonal | invWhereBank | invWhereSharedBank | invWhereTrading | invWhereCursor));
void SetTint(int16 slot_id, uint32 color);

View File

@ -77,9 +77,6 @@ extern volatile bool ZoneLoaded;
extern WorldServer worldserver;
extern PetitionList petition_list;
extern EntityList entity_list;
extern DBAsyncFinishedQueue MTdbafq;
extern DBAsync *dbasync;
typedef void (Client::*ClientPacketProc)(const EQApplicationPacket *app);
//Use a map for connecting opcodes since it dosent get used a lot and is sparse
@ -525,7 +522,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
client_state = CLIENT_KICKED;
return;
}
strcpy(name, cze->char_name);
/* Check for Client Spoofing */
@ -592,19 +588,20 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
if (LFG){ LFG = atoi(row[12]); }
if (firstlogon){ firstlogon = atoi(row[15]); }
}
loaditems = database.GetInventory(cid, &m_inv); /* Load Character Inventory */
database.LoadCharacterBandolier(cid, &m_pp); /* Load Character Bandolier */
database.LoadCharacterBindPoint(cid, &m_pp); /* Load Character Bind */
database.LoadCharacterMaterialColor(cid, &m_pp); /* Load Character Material */
database.LoadCharacterPotions(cid, &m_pp); /* Load Character Potion Belt */
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.GetPlayerInspectMessage(m_pp.name, &m_inspect_message); /* Move to another method when can, this is pointless... */
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 */
database.LoadCharacterLanguages(cid, &m_pp); /* Load Character Languages */
if (level){ level = m_pp.level; }
@ -612,9 +609,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
if (gmhideme) { trackable = false; }
/* Set Con State for Reporting */
conn_state = PlayerProfileLoaded;
// m_pp.zone_id = zone->GetZoneID();
// m_pp.zoneInstance = zone->GetInstanceID();
/* Set Total Seconds Played */
TotalSecondsPlayed = m_pp.timePlayedMin * 60;
@ -9168,38 +9162,6 @@ void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app)
return;
}
void Client::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) {
Entity::DBAWComplete(workpt_b1, dbaw);
switch (workpt_b1) {
case DBA_b1_Entity_Client_Save: {
clock_t t = std::clock(); /* Function timer start */
char errbuf[MYSQL_ERRMSG_SIZE];
uint32 affected_rows = 0;
DBAsyncQuery* dbaq = dbaw->PopAnswer();
if (dbaq->GetAnswer(errbuf, 0, &affected_rows) && affected_rows == 1) {
if (dbaq->QPT()) {
SaveBackup();
}
}
else {
std::cout << "Async client save failed. '" << errbuf << "'" << std::endl;
Message(13, "Error: Asyncronous save of your character failed.");
if (Admin() >= 200)
Message(13, "errbuf: %s", errbuf);
}
pQueuedSaveWorkID = 0;
LogFile->write(EQEMuLog::Status, "Client::DBAWComplete Save Character Async done... Took %f seconds", ((float)(std::clock() - t)) / CLOCKS_PER_SEC);
break;
}
default: {
std::cout << "Error: Client::DBAWComplete(): Unknown workpt_b1" << std::endl;
break;
}
}
}
/* Finish client connecting state */
void Client::CompleteConnect() {
UpdateWho();
@ -9221,7 +9183,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_REF_SPELLBOOK; spellInt++) {
if (m_pp.spell_book[spellInt] < 3 || m_pp.spell_book[spellInt] > 50000)
m_pp.spell_book[spellInt] = 0xFFFFFFFF;
}
@ -9417,7 +9379,7 @@ void Client::CompleteConnect() {
SendWearChange(x);
Mob *pet = GetPet();
if (pet != nullptr) {
for (x = 0; x < 8; x++)
for (x = 0; x < 8; x++)
pet->SendWearChange(x);
}
@ -9497,6 +9459,8 @@ void Client::CompleteConnect() {
alternate_currency_loaded = true;
ProcessAlternateCurrencyQueue();
CalcItemScale();
DoItemEnterZone();
@ -10504,8 +10468,7 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app) {
}
}
void Client::Handle_OP_PotionBelt(const EQApplicationPacket *app) {
void Client::Handle_OP_PotionBelt(const EQApplicationPacket *app) {
if(app->size != sizeof(MovePotionToBelt_Struct)) {
LogFile->write(EQEMuLog::Debug, "Size mismatch in OP_PotionBelt expected %i got %i",
sizeof(MovePotionToBelt_Struct), app->size);
@ -10519,6 +10482,7 @@ void Client::Handle_OP_PotionBelt(const EQApplicationPacket *app) {
m_pp.potionbelt.items[mptbs->SlotNumber].item_id = BaseItem->ID;
m_pp.potionbelt.items[mptbs->SlotNumber].icon = BaseItem->Icon;
strn0cpy(m_pp.potionbelt.items[mptbs->SlotNumber].item_name, BaseItem->Name, sizeof(BaseItem->Name));
database.SaveCharacterPotionBelt(this->CharacterID(), mptbs->SlotNumber, m_pp.potionbelt.items[mptbs->SlotNumber].item_id, m_pp.potionbelt.items[mptbs->SlotNumber].icon);
}
}
else {
@ -10526,9 +10490,6 @@ void Client::Handle_OP_PotionBelt(const EQApplicationPacket *app) {
m_pp.potionbelt.items[mptbs->SlotNumber].icon = 0;
strncpy(m_pp.potionbelt.items[mptbs->SlotNumber].item_name, "\0", 1);
}
Save();
}
void Client::Handle_OP_LFGGetMatchesRequest(const EQApplicationPacket *app) {

View File

@ -1717,6 +1717,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
}
uint16 skilllevel = GetRawSkill(skill);
if(skilllevel == 0) {
//this is a new skill..
uint16 t_level = SkillTrainLevel(skill, GetClass());
@ -1726,7 +1727,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
}
SetSkill(skill, t_level);
} else {
} else {
switch(skill) {
case SkillBrewing:
case SkillMakePoison:

View File

@ -225,7 +225,6 @@ int command_init(void) {
command_add("worldshutdown","- Shut down world and all zones",200,command_worldshutdown) ||
command_add("sendzonespawns","- Refresh spawn list for all clients in zone",150,command_sendzonespawns) ||
command_add("dbspawn2","[spawngroup] [respawn] [variance] - Spawn an NPC from a predefined row in the spawn2 table",100,command_dbspawn2) ||
command_add("copychar","[character name] [new character] [new account id] - Create a copy of a character",100,command_copychar) ||
command_add("shutdown","- Shut this zone process down",150,command_shutdown) ||
command_add("delacct","[accountname] - Delete an account",150,command_delacct) ||
command_add("setpass","[accountname] [password] - Set local password for accountname",150,command_setpass) ||
@ -2227,28 +2226,6 @@ void command_dbspawn2(Client *c, const Seperator *sep)
}
}
void command_copychar(Client *c, const Seperator *sep)
{
if(sep->arg[1][0]==0 || sep->arg[2][0] == 0 || sep->arg[3][0] == 0)
c->Message(0, "Usage: #copychar [character name] [new character] [new account id]");
//CheckUsedName.... TRUE=No Char, FALSE=Char/Error
//If there is no source...
else if (database.CheckUsedName((char*)sep->arg[1])) {
c->Message(0, "Source character not found!");
}
else {
//If there is a name is not used....
if (database.CheckUsedName((char*) sep->arg[2])) {
if (!database.CopyCharacter((char*) sep->arg[1], (char*) sep->arg[2], atoi(sep->arg[3])))
c->Message(0, "Character copy operation failed!");
else
c->Message(0, "Character copy complete.");
}
else
c->Message(0, "Target character already exists!");
}
}
void command_shutdown(Client *c, const Seperator *sep)
{
CatchSignal(2);
@ -2423,8 +2400,8 @@ void command_showskills(Client *c, const Seperator *sep)
c->Message(0, "Skills for %s", t->GetName());
for (SkillUseTypes i=Skill1HBlunt; i <= HIGHEST_SKILL; i=(SkillUseTypes)(i+1))
c->Message(0, "Skill [%d] is at [%d]", i, t->GetSkill(i));
}
c->Message(0, "Skill [%d] is at [%d] - %u", i, t->GetSkill(i), t->GetRawSkill(i));
}
void command_findspell(Client *c, const Seperator *sep)
{
@ -2801,7 +2778,7 @@ void command_charbackup(Client *c, const Seperator *sep)
if (sep->IsNumber(2))
charid = atoi(sep->arg[2]);
else
database.GetAccountIDByChar(sep->arg[2], &charid);
database.GetAccountIDByChar(sep->arg[2]);
if (charid) {
if (database.RunQuery(query, MakeAnyLenString(&query,
"Select id, backupreason, charid, account_id, zoneid, DATE_FORMAT(ts, '%%m/%%d/%%Y %%H:%%i:%%s') "
@ -2828,7 +2805,7 @@ void command_charbackup(Client *c, const Seperator *sep)
if (sep->IsNumber(2))
charid = atoi(sep->arg[2]);
else
database.GetAccountIDByChar(sep->arg[2], &charid);
database.GetAccountIDByChar(sep->arg[2]);
if (charid && sep->IsNumber(3)) {
uint32 cbid = atoi(sep->arg[3]);
@ -8725,6 +8702,7 @@ void command_traindisc(Client *c, const Seperator *sep)
break; //continue the 1st loop
} else if(t->GetPP().disciplines.values[r] == 0) {
t->GetPP().disciplines.values[r] = curspell;
database.SaveCharacterDisc(c->CharacterID(), r, curspell);
t->SendDisciplineUpdate();
t->Message(0, "You have learned a new discipline!");
count++; //success counter

View File

@ -125,7 +125,6 @@ void command_worldshutdown(Client *c, const Seperator *sep);
void command_sendzonespawns(Client *c, const Seperator *sep);
void command_zsave(Client *c, const Seperator *sep);
void command_dbspawn2(Client *c, const Seperator *sep);
void command_copychar(Client *c, const Seperator *sep);
void command_shutdown(Client *c, const Seperator *sep);
void command_delacct(Client *c, const Seperator *sep);
void command_setpass(Client *c, const Seperator *sep);

View File

@ -606,6 +606,7 @@ bool Client::TrainDiscipline(uint32 itemid) {
return(false);
} else if(m_pp.disciplines.values[r] == 0) {
m_pp.disciplines.values[r] = spell_id;
database.SaveCharacterDisc(this->CharacterID(), r, spell_id);
SendDisciplineUpdate();
Message(0, "You have learned a new discipline!");
return(true);

View File

@ -40,7 +40,6 @@
#include "../common/spdat.h"
#include "../common/features.h"
#include "string_ids.h"
#include "../common/dbasync.h"
#include "guild_mgr.h"
#include "raids.h"
#include "quest_parser_collection.h"
@ -57,7 +56,6 @@ extern WorldServer worldserver;
extern NetConnection net;
extern uint32 numclients;
extern PetitionList petition_list;
extern DBAsync *dbasync;
extern char errorname[32];
extern uint16 adverrornum;
@ -65,12 +63,11 @@ extern uint16 adverrornum;
Entity::Entity()
{
id = 0;
pDBAsyncWorkID = 0;
}
Entity::~Entity()
{
dbasync->CancelWork(pDBAsyncWorkID);
}
Client *Entity::CastToClient()

View File

@ -28,7 +28,6 @@
#include "zonedb.h"
#include "zonedump.h"
#include "zonedbasync.h"
#include "qglobals.h"
class EQApplicationPacket;
@ -53,7 +52,7 @@ class Bot;
class BotRaids;
#endif
extern EntityList entity_list;
extern EntityList entity_list;
class Entity
{
@ -100,7 +99,6 @@ public:
inline const uint16& GetID() const { return id; }
virtual const char* GetName() { return ""; }
virtual void DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) { pDBAsyncWorkID = 0; }
bool CheckCoordLosNoZLeaps(float cur_x, float cur_y, float cur_z, float trg_x, float trg_y, float trg_z, float perwalk=1);
#ifdef BOTS

View File

@ -51,14 +51,7 @@ static uint32 MaxBankedRaidLeadershipPoints(int Level)
void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) {
/* Set a timestamp in an entity variable for plugin check_handin.pl in return_items
This will stopgap players from items being returned if global_npc.pl has a catch all return_items
*/
struct timeval read_time;
char buffer[50];
gettimeofday(&read_time, 0);
sprintf(buffer, "%li.%li \n", read_time.tv_sec, read_time.tv_usec);
this->SetEntityVariable("Stop_Return", buffer);
this->EVENT_ITEM_ScriptStopReturn();
uint32 add_exp = in_add_exp;

View File

@ -200,14 +200,7 @@ bool Client::CheckLoreConflict(const Item_Struct* item) {
}
bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool attuned, uint16 to_slot) {
/* Set a timestamp in an entity variable for plugin check_handin.pl in return_items
This will stopgap players from items being returned if global_npc.pl has a catch all return_items
*/
struct timeval read_time;
char buffer[50];
gettimeofday(&read_time, 0);
sprintf(buffer, "%li.%li \n", read_time.tv_sec, read_time.tv_usec);
this->SetEntityVariable("Recieved_Item", buffer);
this->EVENT_ITEM_ScriptStopReturn();
// TODO: update calling methods and script apis to handle a failure return
@ -2320,10 +2313,8 @@ void Client::CreateBandolier(const EQApplicationPacket *app) {
_log(INVENTORY__BANDOLIER, "Char: %s Creating Bandolier Set %i, Set Name: %s", GetName(), bs->number, bs->name);
strcpy(m_pp.bandoliers[bs->number].name, bs->name);
const ItemInst* InvItem;
const Item_Struct *BaseItem;
const ItemInst* InvItem;
const Item_Struct *BaseItem;
int16 WeaponSlot;
for(int BandolierSlot = bandolierMainHand; BandolierSlot <= bandolierAmmo; BandolierSlot++) {
@ -2334,6 +2325,7 @@ void Client::CreateBandolier(const EQApplicationPacket *app) {
_log(INVENTORY__BANDOLIER, "Char: %s adding item %s to slot %i", GetName(),BaseItem->Name, WeaponSlot);
m_pp.bandoliers[bs->number].items[BandolierSlot].item_id = BaseItem->ID;
m_pp.bandoliers[bs->number].items[BandolierSlot].icon = BaseItem->Icon;
database.SaveCharacterBandolier(this->CharacterID(), bs->number, BandolierSlot, m_pp.bandoliers[bs->number].items[BandolierSlot].item_id, m_pp.bandoliers[bs->number].items[BandolierSlot].icon, bs->name);
}
else {
_log(INVENTORY__BANDOLIER, "Char: %s no item in slot %i", GetName(), WeaponSlot);
@ -2341,21 +2333,17 @@ void Client::CreateBandolier(const EQApplicationPacket *app) {
m_pp.bandoliers[bs->number].items[BandolierSlot].icon = 0;
}
}
Save();
}
void Client::RemoveBandolier(const EQApplicationPacket *app) {
// Delete bandolier with the specified number
BandolierDelete_Struct *bds = (BandolierDelete_Struct*)app->pBuffer;
_log(INVENTORY__BANDOLIER, "Char: %s removing set", GetName(), bds->number);
memset(m_pp.bandoliers[bds->number].name, 0, 32);
for(int i = bandolierMainHand; i <= bandolierAmmo; i++) {
m_pp.bandoliers[bds->number].items[i].item_id = 0;
m_pp.bandoliers[bds->number].items[i].icon = 0;
m_pp.bandoliers[bds->number].items[i].icon = 0;
}
Save();
database.DeleteCharacterBandolier(this->CharacterID(), bds->number);
}
void Client::SetBandolier(const EQApplicationPacket *app) {

View File

@ -97,8 +97,6 @@ extern Zone* zone;
EQStreamFactory eqsf(ZoneStream);
npcDecayTimes_Struct npcCorpseDecayTimes[100];
TitleManager title_manager;
DBAsyncFinishedQueue MTdbafq;
DBAsync *dbasync = nullptr;
QueryServ *QServ = 0;
TaskManager *taskmanager = 0;
QuestParserCollection *parse = 0;
@ -168,8 +166,6 @@ int main(int argc, char** argv) {
_log(ZONE__INIT_ERR, "Cannot continue without a database connection.");
return 1;
}
dbasync = new DBAsync(&database);
dbasync->AddFQ(&MTdbafq);
guild_mgr.SetDatabase(&database);
GuildBanks = nullptr;
@ -444,10 +440,6 @@ int main(int argc, char** argv) {
}
}
DBAsyncWork* dbaw = 0;
while ((dbaw = MTdbafq.Pop())) {
DispatchFinishedDBAsync(dbaw);
}
if (InterserverTimer.Check()) {
InterserverTimer.Start();
database.ping();
@ -507,8 +499,6 @@ int main(int argc, char** argv) {
//Fix for Linux world server problem.
eqsf.Close();
worldserver.Disconnect();
dbasync->CommitWrites();
dbasync->StopThread();
safe_delete(taskmanager);
command_deinit();
safe_delete(parse);

View File

@ -974,6 +974,7 @@ uint16 QuestManager::traindiscs(uint8 max_level, uint8 min_level) {
SpellGlobalCheckResult = initiator->SpellGlobalCheck(curspell, Char_ID);
if (SpellGlobalCheckResult) {
initiator->GetPP().disciplines.values[r] = curspell;
database.SaveCharacterDisc(Char_ID, r, curspell);
initiator->SendDisciplineUpdate();
initiator->Message(0, "You have learned a new discipline!");
count++; //success counter
@ -981,11 +982,12 @@ uint16 QuestManager::traindiscs(uint8 max_level, uint8 min_level) {
break; //continue the 1st loop
}
else {
initiator->GetPP().disciplines.values[r] = curspell;
initiator->SendDisciplineUpdate();
initiator->Message(0, "You have learned a new discipline!");
count++; //success counter
break; //continue the 1st loop
initiator->GetPP().disciplines.values[r] = curspell;
database.SaveCharacterDisc(Char_ID, r, curspell);
initiator->SendDisciplineUpdate();
initiator->Message(0, "You have learned a new discipline!");
count++; //success counter
break; //continue the 1st loop
}
} //if we get to this point, there's already a discipline in this slot, so we skip it
}

View File

@ -4933,8 +4933,9 @@ void Client::UntrainDisc(int slot, bool update_client)
if(slot >= MAX_PP_DISCIPLINES || slot < 0)
return;
mlog(CLIENT__SPELLS, "Discipline %d untrained from slot %d", m_pp.disciplines.values[slot], slot);
mlog(CLIENT__SPELLS, "Discipline %d untrained from slot %d", m_pp.disciplines.values[slot], slot);
m_pp.disciplines.values[slot] = 0;
database.DeleteCharacterDisc(this->CharacterID(), slot);
if(update_client)
{

View File

@ -913,14 +913,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st
if(!tradingWith->IsMoving())
tradingWith->FaceTarget(this);
/* Set a timestamp in an entity variable for plugin check_handin.pl in return_items
This will stopgap players from items being returned if global_npc.pl has a catch all return_items
*/
struct timeval read_time;
char buffer[50];
gettimeofday(&read_time, 0);
sprintf(buffer, "%li.%li \n", read_time.tv_sec, read_time.tv_usec);
this->SetEntityVariable("Stop_Return", buffer);
this->EVENT_ITEM_ScriptStopReturn();
}
}
@ -938,7 +931,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st
parse->AddVar(temp1, temp2);
snprintf(temp1, 100, "platinum.%d", tradingWith->GetNPCTypeID());
snprintf(temp2, 100, "%u", trade->pp);
parse->AddVar(temp1, temp2);
parse->AddVar(temp1, temp2);
if(tradingWith->GetAppearance() != eaDead) {
tradingWith->FaceTarget(this);

View File

@ -254,8 +254,10 @@ int32 Client::TributeItem(uint32 slot, uint32 quantity) {
return(0);
}
//make sure they have enough of them
//and remove it from inventory
/*
Make sure they have enough of them
and remove it from inventory
*/
if(inst->IsStackable()) {
if(inst->GetCharges() < (int32)quantity) //dont have enough....
return(0);
@ -267,7 +269,7 @@ int32 Client::TributeItem(uint32 slot, uint32 quantity) {
pts *= quantity;
//add the tribute value in points
/* Add the tribute value in points */
AddTributePoints(pts);
return(pts);
}
@ -279,7 +281,7 @@ int32 Client::TributeMoney(uint32 platinum) {
return(0);
}
//add the tribute value in points
/* Add the tribute value in points */
AddTributePoints(platinum);
return(platinum);
}

View File

@ -77,8 +77,6 @@ extern bool staticzone;
Zone* zone = 0;
volatile bool ZoneLoaded = false;
extern QuestParserCollection* parse;
extern DBAsyncFinishedQueue MTdbafq;
extern DBAsync *dbasync;
bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) {
const char* zonename = database.GetZoneName(iZoneID);
@ -705,7 +703,6 @@ void Zone::Shutdown(bool quite)
zone->ResetAuth();
safe_delete(zone);
dbasync->CommitWrites();
entity_list.ClearAreas();
parse->ReloadQuests(true);
UpdateWindowTitle();
@ -844,8 +841,6 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name)
}
Zone::~Zone() {
if(pQueuedMerchantsWorkID != 0)
dbasync->CancelWork(pQueuedMerchantsWorkID);
spawn2_list.Clear();
safe_delete(zonemap);
safe_delete(watermap);

View File

@ -626,8 +626,7 @@ TraderCharges_Struct* ZoneDatabase::LoadTraderItemWithCharges(uint32 char_id){
return loadti;
}
ItemInst* ZoneDatabase::LoadSingleTraderItem(uint32 CharID, int SerialNumber) {
ItemInst* ZoneDatabase::LoadSingleTraderItem(uint32 CharID, int SerialNumber) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
@ -687,8 +686,7 @@ void ZoneDatabase::SaveTraderItem(uint32 CharID, uint32 ItemID, uint32 SerialNum
safe_delete_array(query);
}
void ZoneDatabase::UpdateTraderItemCharges(int CharID, uint32 SerialNumber, int32 Charges) {
void ZoneDatabase::UpdateTraderItemCharges(int CharID, uint32 SerialNumber, int32 Charges) {
_log(TRADING__CLIENT, "ZoneDatabase::UpdateTraderItemCharges(%i, %i, %i)", CharID, SerialNumber, Charges);
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
@ -784,8 +782,7 @@ void ZoneDatabase::DeleteBuyLines(uint32 CharID){
safe_delete_array(query);
}
void ZoneDatabase::AddBuyLine(uint32 CharID, uint32 BuySlot, uint32 ItemID, const char* ItemName, uint32 Quantity, uint32 Price) {
void ZoneDatabase::AddBuyLine(uint32 CharID, uint32 BuySlot, uint32 ItemID, const char* ItemName, uint32 Quantity, uint32 Price) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
if (!(RunQuery(query,MakeAnyLenString(&query, "replace INTO buyer VALUES(%i,%i, %i,\"%s\",%i,%i)",
@ -795,8 +792,7 @@ void ZoneDatabase::AddBuyLine(uint32 CharID, uint32 BuySlot, uint32 ItemID, cons
safe_delete_array(query);
}
void ZoneDatabase::RemoveBuyLine(uint32 CharID, uint32 BuySlot) {
void ZoneDatabase::RemoveBuyLine(uint32 CharID, uint32 BuySlot) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
@ -806,8 +802,7 @@ void ZoneDatabase::RemoveBuyLine(uint32 CharID, uint32 BuySlot) {
safe_delete_array(query);
}
void ZoneDatabase::UpdateBuyLine(uint32 CharID, uint32 BuySlot, uint32 Quantity) {
void ZoneDatabase::UpdateBuyLine(uint32 CharID, uint32 BuySlot, uint32 Quantity) {
if(Quantity <= 0) {
RemoveBuyLine(CharID, BuySlot);
return;
@ -1016,7 +1011,7 @@ bool ZoneDatabase::LoadCharacterData(uint32 character_id, PlayerProfile_Struct*
}
bool ZoneDatabase::LoadCharacterFactionValues(uint32 character_id, faction_map & val_list) {
std::string query = StringFormat("SELECT faction_id,current_value FROM faction_values WHERE char_id = %i", character_id);
std::string query = StringFormat("SELECT `faction_id`, `current_value` FROM `faction_values` WHERE `char_id` = %i", character_id);
auto results = database.QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) { val_list[atoi(row[0])] = atoi(row[1]); }
return true;
@ -1055,8 +1050,12 @@ bool ZoneDatabase::LoadCharacterLanguages(uint32 character_id, PlayerProfile_Str
"`value` "
"FROM "
"`character_languages` "
"WHERE `id` = %u ORDER BY `language_id`", character_id);
"WHERE `id` = %u ORDER BY `lang_id`", character_id);
auto results = database.QueryDatabase(query); int i = 0;
/* Initialize Languages */
for (i = 0; i < MAX_PP_LANGUAGE; i++){
pp->languages[i] = 0;
}
for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); pp->languages[i] = atoi(row[1]); }
return true;
}
@ -1069,8 +1068,8 @@ bool ZoneDatabase::LoadCharacterDisciplines(uint32 character_id, PlayerProfile_S
"`character_disciplines`"
"WHERE `id` = %u ORDER BY `disc_id`", character_id);
auto results = database.QueryDatabase(query); int i = 0;
for (auto row = results.begin(); row != results.end(); ++row) { pp->disciplines.values[i] = atoi(row[0]); i++; }
return true;
for (auto row = results.begin(); row != results.end(); ++row) { pp->disciplines.values[i] = atoi(row[0]); i++; }
return true;
}
bool ZoneDatabase::LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct* pp){
@ -1081,7 +1080,11 @@ bool ZoneDatabase::LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct
"FROM "
"`character_skills` "
"WHERE `id` = %u ORDER BY `skill_id`", character_id);
auto results = database.QueryDatabase(query); int i = 0;
auto results = database.QueryDatabase(query); int i = 0;
/* Initialize Skill */
for (i = 0; i < MAX_PP_SKILL; i++){
pp->skills[i] = 0;
}
for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); pp->skills[i] = atoi(row[1]); }
return true;
}
@ -1131,44 +1134,162 @@ bool ZoneDatabase::LoadCharacterCurrency(uint32 character_id, PlayerProfile_Stru
return true;
}
bool ZoneDatabase::LoadCharacterMaterialColor(uint32 character_id, PlayerProfile_Struct* pp){
std::string query = StringFormat("SELECT slot, blue, green, red, use_tint, color FROM `character_material` WHERE `id` = %u LIMIT 9", character_id);
auto results = database.QueryDatabase(query); int i = 0; int r = 0;
for (auto row = results.begin(); row != results.end(); ++row) {
r = 0;
i = atoi(row[r]); /* Slot */ r++;
pp->item_tint[i].rgb.blue = atoi(row[r]); r++;
pp->item_tint[i].rgb.green = atoi(row[r]); r++;
pp->item_tint[i].rgb.red = atoi(row[r]); r++;
pp->item_tint[i].rgb.use_tint = atoi(row[r]);
}
return true;
}
bool ZoneDatabase::LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp){
std::string query = StringFormat("SELECT `bandolier_id`, `bandolier_slot`, `item_id`, `icon`, `bandolier_name` FROM `character_bandolier` WHERE `id` = %u LIMIT 16", character_id);
auto results = database.QueryDatabase(query); int i = 0; int r = 0; int si = 0;
for (i = 0; i <= EmuConstants::BANDOLIERS_COUNT; i++){
for (int si = 0; si < EmuConstants::BANDOLIER_SIZE; si++){
pp->bandoliers[i].items[si].icon = 0;
}
}
for (auto row = results.begin(); row != results.end(); ++row) {
r = 0;
i = atoi(row[r]); /* Bandolier ID */ r++;
si = atoi(row[r]); /* Bandolier Slot */ r++;
pp->bandoliers[i].items[si].item_id = atoi(row[r]); r++;
pp->bandoliers[i].items[si].icon = atoi(row[r]); r++;
strcpy(pp->bandoliers[i].name, row[r]); r++;
si++;
}
return true;
}
bool ZoneDatabase::LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp){
std::string query = StringFormat("SELECT `tier`, `tribute` FROM `character_tribute` WHERE `id` = %u", character_id);
auto results = database.QueryDatabase(query); int i = 0;
for (i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){
pp->tributes[i].tribute = 0;
pp->tributes[i].tier = 0;
}
for (auto row = results.begin(); row != results.end(); ++row) {
pp->tributes[i].tier = atoi(row[0]);
pp->tributes[i].tribute = atoi(row[1]);
}
return true;
}
bool ZoneDatabase::LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp){
std::string query = StringFormat("SELECT `potion_id`, `item_id`, `icon` FROM `character_potionbelt` WHERE `id` = %u LIMIT 4", character_id);
auto results = database.QueryDatabase(query); int i = 0;
for (i = 0; i < EmuConstants::POTION_BELT_SIZE; i++){
pp->potionbelt.items[i].icon = 0;
pp->potionbelt.items[i].item_id = 0;
strncpy(pp->potionbelt.items[i].item_name, "\0", 1);
}
for (auto row = results.begin(); row != results.end(); ++row) {
i = atoi(row[0]); /* Potion belt slot number */
pp->potionbelt.items[i].item_id = atoi(row[1]);
pp->potionbelt.items[i].icon = atoi(row[2]);
}
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);
std::string query = StringFormat("SELECT zone_id, instance_id, x, y, z, heading, is_home FROM character_bind WHERE `id` = %u LIMIT 2", 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++;
i = 0;
/* Is home bind */
if (atoi(row[6]) == 1){
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++;
}
/* Is regular bind point */
else{
pp->binds[0].zoneId = atoi(row[i]); i++;
i++; /* Instance ID can go here eventually */
pp->binds[0].x = atoi(row[i]); i++;
pp->binds[0].y = atoi(row[i]); i++;
pp->binds[0].z = atoi(row[i]); i++;
pp->binds[0].heading = atoi(row[i]); i++;
}
}
return true;
}
bool ZoneDatabase::SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value){
std::string query = StringFormat("REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)", character_id, lang_id, value); QueryDatabase(query);
LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterLanguage for character ID: %i, lang_id:%u value:%u done", character_id, lang_id, value);
return true;
}
bool ZoneDatabase::SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading, uint8 is_home){
/* Save Home Bind Point */
std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)"
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i)", character_id, zone_id, instance_id, x, y, z, heading, is_home);
LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterBindPoint for character ID: %i zone_id: %u instance_id: %u x: %f y: %f z: %f heading: %f ishome: %u", character_id, zone_id, instance_id, x, y, z, heading, is_home);
auto results = QueryDatabase(query); if (!results.RowsAffected()){ std::cout << "ERROR Bind Home Save: " << results.ErrorMessage() << "\n\n" << query << "\n" << std::endl; }
return true;
}
bool ZoneDatabase::SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color){
std::string query = StringFormat("REPLACE INTO `character_material` (id, slot, color, use_tint) VALUES (%u, %u, %u, 255)", character_id, slot_id, color); QueryDatabase(query);
LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterMaterialColor for character ID: %i, slot_id: %u color: %u done", character_id, slot_id, color);
return true;
}
bool ZoneDatabase::LoadCharacterMaterialColor(uint32 character_id, PlayerProfile_Struct* pp){
std::string query = StringFormat("SELECT slot, blue, green, red, use_tint, color FROM `character_material` WHERE `id` = %u LIMIT 9", character_id);
auto results = database.QueryDatabase(query); int i = 0; int r = 0;
for (auto row = results.begin(); row != results.end(); ++row) {
r = 0;
i = atoi(row[r]); /* Slot */ r++;
pp->item_tint[i].rgb.blue = atoi(row[r]); r++;
pp->item_tint[i].rgb.green = atoi(row[r]); r++;
pp->item_tint[i].rgb.red = atoi(row[r]); r++;
pp->item_tint[i].rgb.use_tint = atoi(row[r]);
printf("Material Load: %u %u %u %u\n", 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);
bool ZoneDatabase::SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value){
std::string query = StringFormat("REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)", character_id, skill_id, value); QueryDatabase(query);
LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterSkill for character ID: %i, skill_id:%u value:%u done", character_id, skill_id, value);
return true;
}
bool ZoneDatabase::SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id){
std::string query = StringFormat("REPLACE INTO `character_disciplines` (id, slot_id, disc_id) VALUES (%u, %u, %u)", character_id, slot_id, disc_id); QueryDatabase(query);
LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterDisc for character ID: %i, slot:%u disc_id:%u value:%u done", character_id, slot_id, disc_id);
return true;
}
bool ZoneDatabase::SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp){
std::string query = StringFormat("DELETE FROM `character_tribute` WHERE `id` = %u", character_id); QueryDatabase(query);
/* Save Tributes only if we have values... */
for (int i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){
if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != UINT32_MAX){
std::string query = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); QueryDatabase(query);
LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterTribute for character ID: %i, tier:%u tribute:%u done", character_id, pp->tributes[i].tier, pp->tributes[i].tribute);
}
}
return true;
}
bool ZoneDatabase::SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name){
char bandolier_name_esc[64];
DoEscapeString(bandolier_name_esc, bandolier_name, strlen(bandolier_name));
std::string query = StringFormat("REPLACE INTO `character_bandolier` (id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name) VALUES (%u, %u, %u, %u, %u,'%s')", character_id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name_esc);
auto results = QueryDatabase(query);
LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterBandolier for character ID: %i, bandolier_id: %u, bandolier_slot: %u item_id: %u, icon:%u band_name:%s done", character_id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name);
if (!results.RowsAffected()){ std::cout << "ERROR Bandolier Save: " << results.ErrorMessage() << "\n\n" << query << "\n" << std::endl; }
return true;
}
bool ZoneDatabase::SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon) {
std::string query = StringFormat("REPLACE INTO `character_potionbelt` (id, potion_id, item_id, icon) VALUES (%u, %u, %u, %u)", character_id, potion_id, item_id, icon);
auto results = QueryDatabase(query);
if (!results.RowsAffected()){ std::cout << "ERROR Potionbelt Save: " << results.ErrorMessage() << "\n\n" << query << "\n" << std::endl; }
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, "
@ -1352,97 +1473,97 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla
"%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,
pp->name,
pp->last_name,
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,
pp->title,
pp->suffix,
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,
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
")",
character_id, // " id, "
account_id, // " account_id, "
pp->name, // " `name`, "
pp->last_name, // " last_name, "
pp->gender, // " gender, "
pp->race, // " race, "
pp->class_, // " class, "
pp->level, // " `level`, "
pp->deity, // " deity, "
pp->birthday, // " birthday, "
pp->lastlogin, // " last_login, "
pp->timePlayedMin, // " time_played, "
pp->pvp, // " pvp_status, "
pp->level2, // " level2, "
pp->anon, // " anon, "
pp->gm, // " gm, "
pp->intoxication, // " intoxication, "
pp->haircolor, // " hair_color, "
pp->beardcolor, // " beard_color, "
pp->eyecolor1, // " eye_color_1, "
pp->eyecolor2, // " eye_color_2, "
pp->hairstyle, // " hair_style, "
pp->beard, // " beard, "
pp->ability_time_seconds, // " ability_time_seconds, "
pp->ability_number, // " ability_number, "
pp->ability_time_minutes, // " ability_time_minutes, "
pp->ability_time_hours, // " ability_time_hours, "
pp->title, // " title, "
pp->suffix, // " suffix, "
pp->exp, // " exp, "
pp->points, // " points, "
pp->mana, // " mana, "
pp->cur_hp, // " cur_hp, "
pp->STR, // " str, "
pp->STA, // " sta, "
pp->CHA, // " cha, "
pp->DEX, // " dex, "
pp->INT, // " `int`, "
pp->AGI, // " agi, "
pp->WIS, // " wis, "
pp->face, // " face, "
pp->y, // " y, "
pp->x, // " x, "
pp->z, // " z, "
pp->heading, // " heading, "
pp->pvp2, // " pvp2, "
pp->pvptype, // " pvp_type, "
pp->autosplit, // " autosplit_enabled, "
pp->zone_change_count, // " zone_change_count, "
pp->drakkin_heritage, // " drakkin_heritage, "
pp->drakkin_tattoo, // " drakkin_tattoo, "
pp->drakkin_details, // " drakkin_details, "
pp->toxicity, // " toxicity, "
pp->hunger_level, // " hunger_level, "
pp->thirst_level, // " thirst_level, "
pp->ability_up, // " ability_up, "
pp->zone_id, // " zone_id, "
pp->zoneInstance, // " zone_instance, "
pp->leadAAActive, // " leadership_exp_on, "
pp->ldon_points_guk, // " ldon_points_guk, "
pp->ldon_points_mir, // " ldon_points_mir, "
pp->ldon_points_mmc, // " ldon_points_mmc, "
pp->ldon_points_ruj, // " ldon_points_ruj, "
pp->ldon_points_tak, // " ldon_points_tak, "
pp->ldon_points_available, // " ldon_points_available, "
pp->tribute_time_remaining, // " tribute_time_remaining, "
pp->showhelm, // " show_helm, "
pp->career_tribute_points, // " career_tribute_points, "
pp->tribute_points, // " tribute_points, "
pp->tribute_active, // " tribute_active, "
pp->endurance, // " endurance, "
pp->group_leadership_exp, // " group_leadership_exp, "
pp->raid_leadership_exp, // " raid_leadership_exp, "
pp->group_leadership_points, // " group_leadership_points, "
pp->raid_leadership_points, // " raid_leadership_points, "
pp->air_remaining, // " air_remaining, "
pp->PVPKills, // " pvp_kills, "
pp->PVPDeaths, // " pvp_deaths, "
pp->PVPCurrentPoints, // " pvp_current_points, "
pp->PVPCareerPoints, // " pvp_career_points, "
pp->PVPBestKillStreak, // " pvp_best_kill_streak, "
pp->PVPWorstDeathStreak, // " pvp_worst_death_streak, "
pp->PVPCurrentKillStreak, // " pvp_current_kill_streak, "
pp->aapoints_spent, // " aa_points_spent, "
pp->expAA, // " aa_exp, "
pp->aapoints, // " aa_points, "
pp->groupAutoconsent, // " group_auto_consent, "
pp->raidAutoconsent, // " raid_auto_consent, "
pp->guildAutoconsent, // " guild_auto_consent, "
pp->RestTimer // " RestTimer) "
);
auto results = database.QueryDatabase(query);
if (!results.RowsAffected()){ std::cout << "ERROR ZoneDatabase:SaveCharacterData: " << results.ErrorMessage() << "\n\n" << query << "\n" << std::endl; }
@ -1459,6 +1580,10 @@ bool ZoneDatabase::SaveCharacterCurrency(uint32 character_id, PlayerProfile_Stru
if (pp->silver_bank < 0) { pp->silver_bank = 0; }
if (pp->gold_bank < 0) { pp->gold_bank = 0; }
if (pp->platinum_bank < 0) { pp->platinum_bank = 0; }
if (pp->platinum_cursor < 0) { pp->platinum_cursor = 0; }
if (pp->gold_cursor < 0) { pp->gold_cursor = 0; }
if (pp->silver_cursor < 0) { pp->silver_cursor = 0; }
if (pp->copper_cursor < 0) { pp->copper_cursor = 0; }
std::string query = StringFormat(
"REPLACE INTO `character_currency` (id, platinum, gold, silver, copper,"
"platinum_bank, gold_bank, silver_bank, copper_bank,"
@ -1499,12 +1624,16 @@ bool ZoneDatabase::SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 cur
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 */
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::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::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;
}
@ -1513,8 +1642,12 @@ bool ZoneDatabase::DeleteCharacterSpell(uint32 character_id, uint32 spell_id, ui
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::DeleteCharacterDisc(uint32 character_id, uint32 slot_id){
std::string query = StringFormat("DELETE FROM `character_disciplines` WHERE `slot_id` = %u AND `id` = %u", slot_id, character_id); QueryDatabase(query); return true;
}
bool ZoneDatabase::DeleteCharacterBandolier(uint32 character_id, uint32 band_id){
std::string query = StringFormat("DELETE FROM `character_bandolier` WHERE `bandolier_id` = %u AND `id` = %u", band_id, character_id); QueryDatabase(query); return true;
}
bool ZoneDatabase::DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id){
@ -1715,7 +1848,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) {
tmpNPCType->aggroradius = (int32)atoi(row[r++]);
// set defaultvalue for aggroradius
if (tmpNPCType->aggroradius <= 0)
tmpNPCType->aggroradius = 70;
tmpNPCType->aggroradius = 70;
tmpNPCType->assistradius = (int32)atoi(row[r++]);
if (tmpNPCType->assistradius <= 0)
tmpNPCType->assistradius = tmpNPCType->aggroradius;
@ -3715,4 +3848,6 @@ void ZoneDatabase::StoreCharacterLookup(uint32 char_id) {
" FROM `character_` "
" WHERE `id` = %i ", char_id);
QueryDatabase(c_lookup);
}
}

View File

@ -6,6 +6,7 @@
#include "../common/loottable.h"
#include "zonedump.h"
#include "../common/faction.h"
#include <stdint.h>
//#include "doors.h"
struct wplist {
@ -212,9 +213,7 @@ public:
ZoneDatabase(const char* host, const char* user, const char* passwd, const char* database,uint32 port);
virtual ~ZoneDatabase();
/*
* Objects and World Containers
*/
/* Objects and World Containers */
void LoadWorldContainer(uint32 parentid, ItemInst* container);
void SaveWorldContainer(uint32 zone_id, uint32 parent_id, const ItemInst* container);
void DeleteWorldContainer(uint32 parent_id,uint32 zone_id);
@ -223,10 +222,7 @@ public:
void DeleteObject(uint32 id);
Ground_Spawns* LoadGroundSpawns(uint32 zone_id, int16 version, Ground_Spawns* gs);
/*
* Traders
*/
/* Traders */
void SaveTraderItem(uint32 char_id,uint32 itemid,uint32 uniqueid, int32 charges,uint32 itemcost,uint8 slot);
void UpdateTraderItemCharges(int char_id, uint32 ItemInstID, int32 charges);
void UpdateTraderItemPrice(int CharID, uint32 ItemID, uint32 Charges, uint32 NewPrice);
@ -236,16 +232,13 @@ public:
Trader_Struct* LoadTraderItem(uint32 char_id);
TraderCharges_Struct* LoadTraderItemWithCharges(uint32 char_id);
// Buyer/Barter
//
/* Buyer/Barter */
void AddBuyLine(uint32 CharID, uint32 BuySlot, uint32 ItemID, const char *ItemName, uint32 Quantity, uint32 Price);
void RemoveBuyLine(uint32 CharID, uint32 BuySlot);
void DeleteBuyLines(uint32 CharID);
void UpdateBuyLine(uint32 CharID, uint32 BuySlot, uint32 Quantity);
/*
* General Character Related Stuff
*/
/* General Character Related Stuff */
void StoreCharacterLookup(uint32 char_id);
bool SetServerFilters(char* name, ServerSideFilters_Struct *ssfs);
uint32 GetServerFilters(char* name, ServerSideFilters_Struct *ssfs);
@ -267,28 +260,36 @@ public:
bool LoadCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterMaterialColor(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp);
/* 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);
bool SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color);
bool SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading, uint8 is_home);
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);
bool SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color);
bool SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value);
bool SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value);
bool SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id);
bool SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
bool SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name);
bool SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon);
/* 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);
bool DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool DeleteCharacterDisc(uint32 character_id, uint32 slot_id);
bool DeleteCharacterBandolier(uint32 character_id, uint32 band_id);
/*
* Character Inventory
*/
/* Character Inventory */
bool NoRentExpired(const char* name);
/*
* Corpses
*/
/* Corpses */
bool GetDecayTimes(npcDecayTimes_Struct* npcCorpseDecayTimes);
uint32 CreatePlayerCorpse(uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, uchar* data, uint32 datasize, float x, float y, float z, float heading);
bool CreatePlayerCorpseBackup(uint32 dbid, uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, uchar* data, uint32 datasize, float x, float y, float z, float heading);
@ -314,9 +315,7 @@ public:
uint32 GetPlayerCorpseItemAt(uint32 corpse_id, uint16 slotid);
uint32 GetPlayerCorpseTimeLeft(uint8 corpse, uint8 type);
/*
* Faction
*/
/* Faction */
bool GetNPCFactionList(uint32 npcfaction_id, int32* faction_id, int32* value, uint8* temp, int32* primary_faction = 0);
bool GetFactionData(FactionMods* fd, uint32 class_mod, uint32 race_mod, uint32 deity_mod, int32 faction_id); //rembrant, needed for factions Dec, 16 2001
bool GetFactionName(int32 faction_id, char* name, uint32 buflen); // rembrant, needed for factions Dec, 16 2001
@ -324,9 +323,7 @@ public:
bool SetCharacterFactionLevel(uint32 char_id, int32 faction_id, int32 value, uint8 temp, faction_map &val_list); // rembrant, needed for factions Dec, 16 2001
bool LoadFactionData();
/*
* AAs
*/
/* AAs */
bool LoadAAEffects();
bool LoadAAEffects2();
bool LoadSwarmSpells();
@ -338,9 +335,7 @@ public:
uint32 CountAAEffects();
void FillAAEffects(SendAA_Struct* aa_struct);
/*
* Zone related
*/
/* Zone related */
bool GetZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct *data, bool &can_bind, bool &can_combat, bool &can_levitate, bool &can_castoutdoor, bool &is_city, bool &is_hotzone, bool &allow_mercs, uint8 &zone_type, int &ruleset, char **map_filename);
bool SaveZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct* zd);
bool LoadStaticZonePoints(LinkedList<ZonePoint*>* zone_point_list,const char* zonename, uint32 version);
@ -348,9 +343,7 @@ public:
uint8 GetUseCFGSafeCoords();
int getZoneShutDownDelay(uint32 zoneID, uint32 version);
/*
* Spawns and Spawn Points
*/
/* Spawns and Spawn Points */
bool LoadSpawnGroups(const char* zone_name, uint16 version, SpawnGroupList* spawn_group_list);
bool LoadSpawnGroupsByID(int spawngroupid, SpawnGroupList* spawn_group_list);
bool PopulateZoneSpawnList(uint32 zoneid, LinkedList<Spawn2*> &spawn2_list, int16 version, uint32 repopdelay = 0);
@ -360,9 +353,7 @@ public:
uint32 GetSpawnTimeLeft(uint32 id, uint16 instance_id);
void UpdateSpawn2Status(uint32 id, uint8 new_status);
/*
* Grids/Paths
*/
/* Grids/Paths */
uint32 GetFreeGrid(uint16 zoneid);
void DeleteGrid(Client *c, uint32 sg2, uint32 grid_num, bool grid_too,uint16 zoneid);
void DeleteWaypoint(Client *c, uint32 grid_num, uint32 wp_num,uint16 zoneid);
@ -378,9 +369,7 @@ public:
int GetHighestGrid(uint32 zoneid);
int GetHighestWaypoint(uint32 zoneid, uint32 gridid);
/*
* NPCs
*/
/* NPCs */
const NPCType* GetNPCType(uint32 id);
uint32 NPCSpawnDB(uint8 command, const char* zone, uint32 zone_version, Client *c, NPC* spawn = 0, uint32 extra = 0); // 0 = Create 1 = Add; 2 = Update; 3 = Remove; 4 = Delete
bool SetSpecialAttkFlag(uint8 id, const char* flag);
@ -394,9 +383,7 @@ public:
DBnpcspells_Struct* GetNPCSpells(uint32 iDBSpellsID);
DBnpcspellseffects_Struct* GetNPCSpellsEffects(uint32 iDBSpellsEffectsID);
/*
* Mercs
*/
/* Mercs */
const NPCType* GetMercType(uint32 id, uint16 raceid, uint32 clientlevel);
void LoadMercEquipment(Merc *merc);
void SaveMercBuffs(Merc *merc);
@ -408,9 +395,7 @@ public:
//void LoadMercTypesForMercMerchant(NPC *merchant);
//void LoadMercsForMercMerchant(NPC *merchant);
/*
* Petitions
*/
/* Petitions */
void UpdateBug(BugStruct* bug);
void UpdateBug(PetitionBug_Struct* bug);
void DeletePetitionFromDB(Petition* wpet);
@ -418,16 +403,11 @@ public:
void InsertPetitionToDB(Petition* wpet);
void RefreshPetitionsFromDB();
/*
* Merchants
*/
/* Merchants */
void SaveMerchantTemp(uint32 npcid, uint32 slot, uint32 item, uint32 charges);
void DeleteMerchantTemp(uint32 npcid, uint32 slot);
/*
* Tradeskills
*/
/* Tradeskills */
bool GetTradeRecipe(const ItemInst* container, uint8 c_type, uint32 some_id, uint32 char_id, DBTradeskillRecipe_Struct *spec);
bool GetTradeRecipe(uint32 recipe_id, uint8 c_type, uint32 some_id, uint32 char_id, DBTradeskillRecipe_Struct *spec);
uint32 GetZoneForage(uint32 ZoneID, uint8 skill); /* for foraging */
@ -436,14 +416,10 @@ public:
bool EnableRecipe(uint32 recipe_id);
bool DisableRecipe(uint32 recipe_id);
/*
* Tribute
*/
/* Tribute */
bool LoadTributes();
/*
* Doors
*/
/* Doors */
bool DoorIsOpen(uint8 door_id,const char* zone_name);
void SetDoorPlace(uint8 value,uint8 door_id,const char* zone_name);
bool LoadDoors(int32 iDoorCount, Door *into, const char *zone_name, int16 version);
@ -456,64 +432,46 @@ public:
int32 GetDoorsDBCountPlusOne(const char *zone_name, int16 version);
void InsertDoor(uint32 did, uint16 ddoorid, const char* ddoor_name, float dxpos, float dypos, float dzpos, float dheading, uint8 dopentype, uint16 dguildid, uint32 dlockpick, uint32 dkeyitem, uint8 ddoor_param, uint8 dinvert, int dincline, uint16 dsize);
/*
* Blocked Spells
*/
/* Blocked Spells */
int32 GetBlockedSpellsCount(uint32 zoneid);
bool LoadBlockedSpells(int32 blockedSpellsCount, ZoneSpellsBlocked* into, uint32 zoneid);
/*
* Traps
*/
/* Traps */
bool LoadTraps(const char* zonename, int16 version);
char* GetTrapMessage(uint32 trap_id);
/*
* Time
*/
/* Time */
uint32 GetZoneTZ(uint32 zoneid, uint32 version);
bool SetZoneTZ(uint32 zoneid, uint32 version, uint32 tz);
/*
* Group
*/
/* Group */
void RefreshGroupFromDB(Client *c);
uint8 GroupCount(uint32 groupid);
/*
* Raid
*/
/* Raid */
uint8 RaidGroupCount(uint32 raidid, uint32 groupid);
/*
* Instancing
*/
/* Instancing */
void ListAllInstances(Client* c, uint32 charid);
/*
* QGlobals
*/
/* QGlobals */
void QGlobalPurge();
/*
* Alternate Currency
*/
/* Alternate Currency */
void LoadAltCurrencyValues(uint32 char_id, std::map<uint32, uint32> &currency);
void UpdateAltCurrencyValue(uint32 char_id, uint32 currency_id, uint32 value);
/*
* Misc stuff.
* PLEASE DO NOT ADD TO THIS COLLECTION OF CRAP UNLESS YOUR METHOD
* REALLY HAS NO BETTER SECTION
* Misc stuff.
* PLEASE DO NOT ADD TO THIS COLLECTION OF CRAP UNLESS YOUR METHOD
* REALLY HAS NO BETTER SECTION
*/
bool logevents(const char* accountname,uint32 accountid,uint8 status,const char* charname,const char* target, const char* descriptiontype, const char* description,int event_nid);
void GetEventLogs(const char* name,char* target,uint32 account_id=0,uint8 eventid=0,char* detail=0,char* timestamp=0, CharacterEventLog_Struct* cel=0);
uint32 GetKarma(uint32 acct_id);
void UpdateKarma(uint32 acct_id, uint32 amount);
/*
* Things which really dont belong here...
*/
/* Things which really dont belong here... */
int16 CommandRequirement(const char* commandname);
protected:

View File

@ -1,103 +0,0 @@
#include "../common/debug.h"
#include <iostream>
#include "entity.h"
#include "masterentity.h"
#include "../common/string_util.h"
#include "../common/breakdowns.h"
#include <stdlib.h>
extern EntityList entity_list;
void DispatchFinishedDBAsync(DBAsyncWork* dbaw) {
uint32_breakdown workpt;
workpt = dbaw->WPT();
switch (workpt.b4()) {
case DBA_b4_Entity: {
Entity* entity = entity_list.GetID(workpt.w2_3());
if (!entity)
break;
entity->DBAWComplete(workpt.b1(), dbaw);
break;
}
default: {
std::cout << "Error: DispatchFinishedDBAsync(): Unknown workpt.b4: " << (int) workpt.b4() << ", workpt=" << workpt << std::endl;
break;
}
}
safe_delete(dbaw);
}
#define MAX_TO_DELETE 10
#define MAX_BACKUPS 5
bool DBAsyncCB_CharacterBackup(DBAsyncWork* iWork) { // return true means delete data
char errbuf[MYSQL_ERRMSG_SIZE] = "dbaq == 0";
MYSQL_RES* result = 0;
MYSQL_ROW row;
char* query = 0;
uint32 i;
uint8 ToDeleteIndex = 0;
uint32 ToDelete[MAX_TO_DELETE];
memset(ToDelete, 0, sizeof(ToDelete));
uint32 BackupAges[MAX_BACKUPS]; // must be sorted, highest value in lowest index
memset(BackupAges, 0, sizeof(BackupAges));
bool FoundBackup[MAX_BACKUPS];
memset(FoundBackup, 0, sizeof(FoundBackup));
BackupAges[0] = 86400;
BackupAges[1] = 3600;
DBAsyncQuery* dbaq = iWork->PopAnswer();
if (dbaq && dbaq->GetAnswer(errbuf, &result)) {
while ((row = mysql_fetch_row(result))) {
for (i=0; i<MAX_BACKUPS; i++) {
if (BackupAges[i] == 0 || (uint32)atoi(row[1]) > BackupAges[i])
i = MAX_BACKUPS;
else if (!FoundBackup[i]) {
FoundBackup[i] = true;
break;
}
}
if (i >= MAX_BACKUPS)
ToDelete[ToDeleteIndex++] = atoi(row[0]);
if (ToDeleteIndex >= MAX_TO_DELETE)
break;
}
if (ToDelete[0]) {
uint32 len = 0, size = 0;
AppendAnyLenString(&query, &size, &len, "Delete from character_backup where id=%u", ToDelete[0]);
for (uint8 i=1; i<ToDeleteIndex; i++) {
AppendAnyLenString(&query, &size, &len, " or id=%u", ToDelete[i]);
}
if (!database.RunQuery(query, len, errbuf)) {
LogFile->write(EQEMuLog::Error, "Error in DBAsyncCB_CharacterBackup query2 '%s' %s", query, errbuf);
safe_delete_array(query);
return true;
}
safe_delete_array(query);
}
bool needtoinsert = false;
for (i=0; i<MAX_BACKUPS; i++) {
if (BackupAges[i] != 0 && !FoundBackup[i])
needtoinsert = true;
}
if (needtoinsert) {
if (!database.RunQuery(query, MakeAnyLenString(&query,
"Insert Delayed into character_backup (charid, account_id, name, profile, level, class, x, y, z, zoneid) "
"select id, account_id, name, profile, level, class, x, y, z, zoneid "
"from character_ where id=%u", iWork->WPT()), errbuf)) {
std::cout << "Error in DBAsyncCB_CharacterBackup query3 '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
return true;
}
safe_delete_array(query);
}
}
else {
// std::cout << "Error in DBAsyncCB_CharacterBackup query1 '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
return true;
}
return true;
}

View File

@ -1,22 +0,0 @@
#ifndef ZONEDBASYNC_H
#define ZONEDBASYNC_H
#include "../common/dbasync.h"
void DispatchFinishedDBAsync(DBAsyncWork* iDBAW);
bool DBAsyncCB_CharacterBackup(DBAsyncWork* iWork);
#define DBA_b4_Main 1
#define DBA_b4_Worldserver 2
#define DBA_b4_Zone 3
#define DBA_b4_Entity 4
#define DBA_b1_Entity_SeeQPT 0
#define DBA_b1_Entity_Client_InfoForLogin 1
#define DBA_b1_Entity_Client_Save 2
#define DBA_b1_Entity_Client_Backup 3
#define DBA_b1_Entity_Corpse_Backup 4
#define DBA_b1_Zone_MerchantLists 5
#define DBA_b1_Zone_MerchantListsTemp 6
#endif

View File

@ -50,10 +50,6 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
#endif
ZoneChange_Struct* zc=(ZoneChange_Struct*)app->pBuffer;
printf("INCOMING CLIENT\n\n");
printf("%s\n", zc->char_name);
printf("%u\n", zc->zoneID);
uint16 target_zone_id = 0;
uint16 target_instance_id = zc->instanceID;
ZonePoint* zone_point = nullptr;
@ -568,7 +564,6 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z
if(ReadyToZone) {
zone_mode = zm;
printf("\n\n ZONE MODE %u \n\n", zm);
if(zm == ZoneToBindPoint) {
EQApplicationPacket* outapp = new EQApplicationPacket(OP_ZonePlayerToBind, sizeof(ZonePlayerToBind_Struct) + iZoneNameLength);
ZonePlayerToBind_Struct* gmg = (ZonePlayerToBind_Struct*) outapp->pBuffer;
@ -602,10 +597,6 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z
gmg->instance_id = instance_id;
gmg->type = 0x01; //an observed value, not sure of meaning
printf("gmg->zone_id %u \n", gmg->zone_id);
printf("gmg->x %u \n", gmg->x);
printf("gmg->y %u \n", gmg->y);
outapp->priority = 6;
FastQueuePacket(&outapp);
safe_delete(outapp);
@ -726,6 +717,7 @@ void Client::SetBindPoint(int to_zone, float new_x, float new_y, float new_z) {
m_pp.binds[0].y = new_y;
m_pp.binds[0].z = new_z;
}
database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[0].zoneId, 0, m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, 0, 0);
}
void Client::GoToBind(uint8 bindnum) {