From 699b27ceccbb1cc1e93d0e8aea0521df32fb5a7f Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 15:48:17 -0700 Subject: [PATCH 001/288] Added LastInsertID() to MySQLRequestResult --- common/MySQLRequestResult.h | 1 + 1 file changed, 1 insertion(+) diff --git a/common/MySQLRequestResult.h b/common/MySQLRequestResult.h index 807efdfc0..ef2dcd104 100644 --- a/common/MySQLRequestResult.h +++ b/common/MySQLRequestResult.h @@ -41,6 +41,7 @@ public: uint32 RowsAffected() const {return m_RowsAffected;} uint32 RowCount() const {return m_RowCount;} uint32 ColumnCount() const {return m_ColumnCount;} + uint32 LastInsertedID() const {return m_LastInsertedID;} MySQLRequestRow& begin() { return m_CurrentRow; } MySQLRequestRow& end() { return m_OneBeyondRow;} From e6023a701355a178bf681394d8888eeb142d645b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 15:19:50 -0700 Subject: [PATCH 002/288] CheckBannedIPs converted to QueryDatabase --- common/database.cpp | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 4dcee568e..47d88cc82 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -196,33 +196,22 @@ uint32 Database::CheckLogin(const char* name, const char* password, int16* oStat //Lieka: Get Banned IP Address List - Only return false if the incoming connection's IP address is not present in the banned_ips table. bool Database::CheckBannedIPs(const char* loginIP) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - //std::cout << "Checking against Banned IPs table."<< std::endl; //Lieka: Debugging - if (RunQuery(query, MakeAnyLenString(&query, "SELECT ip_address FROM Banned_IPs WHERE ip_address='%s'", loginIP), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) != 0) - { - //std::cout << loginIP << " was present in the banned IPs table" << std::endl; //Lieka: Debugging - mysql_free_result(result); - return true; - } - else - { - //std::cout << loginIP << " was not present in the banned IPs table." << std::endl; //Lieka: Debugging - mysql_free_result(result); - return false; - } - mysql_free_result(result); - } - else + char *query = nullptr; + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT ip_address FROM Banned_IPs WHERE ip_address='%s'", loginIP)); + + safe_delete_array(query); + + if (!results.Success()) { - std::cerr << "Error in CheckBannedIPs query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + std::cerr << "Error in CheckBannedIPs query '" << query << "' " << results.ErrorMessage() << std::endl; return true; } - return true; + + if (results.RowCount() != 0) + return true; + + return false; } bool Database::AddBannedIP(char* bannedIP, const char* notes) From 02f21ad7c951d6985454660f866a590070822028 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 15:15:42 -0700 Subject: [PATCH 003/288] CheckLogin converted to DatabaseQuery --- common/database.cpp | 47 ++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 47d88cc82..46e31bbe3 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -148,48 +148,39 @@ Return the account id or zero if no account matches. Zero will also be returned if there is a database error. */ uint32 Database::CheckLogin(const char* name, const char* password, int16* oStatus) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + + char *query = nullptr; if(strlen(name) >= 50 || strlen(password) >= 50) return(0); char tmpUN[100]; char tmpPW[100]; + DoEscapeString(tmpUN, name, strlen(name)); DoEscapeString(tmpPW, password, strlen(password)); - if (RunQuery(query, MakeAnyLenString(&query, + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT id, status FROM account WHERE name='%s' AND password is not null " "and length(password) > 0 and (password='%s' or password=MD5('%s'))", - tmpUN, tmpPW, tmpPW), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) - { - row = mysql_fetch_row(result); - uint32 id = atoi(row[0]); - if (oStatus) - *oStatus = atoi(row[1]); - mysql_free_result(result); - return id; - } - else - { - mysql_free_result(result); - return 0; - } - mysql_free_result(result); - } - else + tmpUN, tmpPW, tmpPW)); + + safe_delete_array(query); + + if (!results.Success()) { - std::cerr << "Error in CheckLogin query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; + std::cerr << "Error in CheckLogin query '" << query << "' " << results.ErrorMessage() << std::endl; + return 0; } - return 0; + auto row = results.begin(); + + uint32 id = atoi(row[0]); + + if (oStatus) + *oStatus = atoi(row[1]); + + return id; } From 7f135d6e55d8740aef10566e4267a87e81fca6ea Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 15:24:09 -0700 Subject: [PATCH 004/288] AddBannedIP converted to QueryDatabase --- common/database.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 46e31bbe3..9acb6e216 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -184,7 +184,7 @@ uint32 Database::CheckLogin(const char* name, const char* password, int16* oStat } -//Lieka: Get Banned IP Address List - Only return false if the incoming connection's IP address is not present in the banned_ips table. +//Get Banned IP Address List - Only return false if the incoming connection's IP address is not present in the banned_ips table. bool Database::CheckBannedIPs(const char* loginIP) { char *query = nullptr; @@ -207,18 +207,20 @@ bool Database::CheckBannedIPs(const char* loginIP) bool Database::AddBannedIP(char* bannedIP, const char* notes) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + char *query = nullptr; - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT into Banned_IPs SET ip_address='%s', notes='%s'", bannedIP, notes), errbuf)) { - std::cerr << "Error in ReserveName query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + auto results = QueryDatabase(query, MakeAnyLenString(&query, "INSERT into Banned_IPs SET ip_address='%s', notes='%s'", bannedIP, notes)); + + safe_delete_array(query); + + if (!results.Success()) + { + std::cerr << "Error in ReserveName query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } - safe_delete_array(query); + return true; } - //End Lieka Edit bool Database::CheckGMIPs(const char* ip_address, uint32 account_id) { char errbuf[MYSQL_ERRMSG_SIZE]; From cbf49b303b62343e189ec22bfbef3bd3564c7d80 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 15:26:39 -0700 Subject: [PATCH 005/288] CheckGMIPs to QueryDatabase --- common/database.cpp | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 9acb6e216..5a47c5b61 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -223,24 +223,17 @@ bool Database::AddBannedIP(char* bannedIP, const char* notes) } bool Database::CheckGMIPs(const char* ip_address, uint32 account_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT * FROM `gm_ips` WHERE `ip_address` = '%s' AND `account_id` = %i", ip_address, account_id), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - mysql_free_result(result); - return true; - } else { - mysql_free_result(result); - return false; - } - mysql_free_result(result); + char *query = nullptr; - } else { - safe_delete_array(query); + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT * FROM `gm_ips` WHERE `ip_address` = '%s' AND `account_id` = %i", ip_address, account_id)); + + safe_delete_array(query); + + if (!results.Success()) return false; - } + + if (results.RowCount() == 1) + return true; return false; } From 418e4ffee8d072e35719be1735ac5db24528e050 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 15:31:37 -0700 Subject: [PATCH 006/288] AddGMIP converted to QueryDatabase --- common/database.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 5a47c5b61..e7b75b132 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -239,15 +239,13 @@ bool Database::AddBannedIP(char* bannedIP, const char* notes) } bool Database::AddGMIP(char* ip_address, char* name) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + char *query = nullptr; + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "INSERT into `gm_ips` SET `ip_address` = '%s', `name` = '%s'", ip_address, name)); - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT into `gm_ips` SET `ip_address` = '%s', `name` = '%s'", ip_address, name), errbuf)) { - safe_delete_array(query); - return false; - } safe_delete_array(query); - return true; + + return results.Success(); } void Database::LoginIP(uint32 AccountID, const char* LoginIP) From 1bfdeeeb1691b97abc74e5eadce367451d3eceba Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 15:34:42 -0700 Subject: [PATCH 007/288] fixed query release order and converted LoginIP to QueryDatabase --- common/database.cpp | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index e7b75b132..0ca1a47ca 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -165,14 +165,17 @@ uint32 Database::CheckLogin(const char* name, const char* password, int16* oStat "and length(password) > 0 and (password='%s' or password=MD5('%s'))", tmpUN, tmpPW, tmpPW)); - safe_delete_array(query); + if (!results.Success()) { + safe_delete_array(query); std::cerr << "Error in CheckLogin query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } + safe_delete_array(query); + auto row = results.begin(); uint32 id = atoi(row[0]); @@ -191,14 +194,16 @@ bool Database::CheckBannedIPs(const char* loginIP) auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT ip_address FROM Banned_IPs WHERE ip_address='%s'", loginIP)); - safe_delete_array(query); - + if (!results.Success()) { std::cerr << "Error in CheckBannedIPs query '" << query << "' " << results.ErrorMessage() << std::endl; + safe_delete_array(query); return true; } + safe_delete_array(query); + if (results.RowCount() != 0) return true; @@ -211,14 +216,15 @@ bool Database::AddBannedIP(char* bannedIP, const char* notes) auto results = QueryDatabase(query, MakeAnyLenString(&query, "INSERT into Banned_IPs SET ip_address='%s', notes='%s'", bannedIP, notes)); - safe_delete_array(query); - if (!results.Success()) { std::cerr << "Error in ReserveName query '" << query << "' " << results.ErrorMessage() << std::endl; + safe_delete_array(query); return false; } - + + safe_delete_array(query); + return true; } @@ -250,12 +256,13 @@ bool Database::AddGMIP(char* ip_address, char* name) { void Database::LoginIP(uint32 AccountID, const char* LoginIP) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + char *query = nullptr; + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "INSERT INTO account_ip SET accid=%i, ip='%s' ON DUPLICATE KEY UPDATE count=count+1, lastused=now()", AccountID, LoginIP)); + + if (!results.Success()) + std::cerr << "Error in Log IP query '" << query << "' " << results.ErrorMessage() << std::endl; - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO account_ip SET accid=%i, ip='%s' ON DUPLICATE KEY UPDATE count=count+1, lastused=now()", AccountID, LoginIP), errbuf)) { - std::cerr << "Error in Log IP query '" << query << "' " << errbuf << std::endl; - } safe_delete_array(query); } From 95c82d9968e428eb8356b95f3bf4814dc325c006 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 15:41:26 -0700 Subject: [PATCH 008/288] CheckStatus using QueryDatabase --- common/database.cpp | 66 +++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 38 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 0ca1a47ca..8e4c1c734 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -268,49 +268,39 @@ void Database::LoginIP(uint32 AccountID, const char* LoginIP) int16 Database::CheckStatus(uint32 account_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT `status`, UNIX_TIMESTAMP(`suspendeduntil`) as `suspendeduntil`, UNIX_TIMESTAMP() as `current`" - " FROM `account` WHERE `id` = %i", account_id), errbuf, &result)) + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT `status`, UNIX_TIMESTAMP(`suspendeduntil`) as `suspendeduntil`, UNIX_TIMESTAMP() as `current`" + " FROM `account` WHERE `id` = %i", account_id)); + + if (!results.Success()) { + std::cerr << "Error in CheckStatus query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); - - if (mysql_num_rows(result) == 1) - { - row = mysql_fetch_row(result); - - int16 status = atoi(row[0]); - - int32 suspendeduntil = 0; - // MariaDB initalizes with NULL if unix_timestamp() is out of range - if (row[1] != NULL) { - suspendeduntil = atoi(row[1]); - } - - int32 current = atoi(row[2]); - - mysql_free_result(result); - - if(suspendeduntil > current) - return -1; - - return status; - } - else - { - mysql_free_result(result); - return 0; - } - mysql_free_result(result); + return 0; } - else + + safe_delete_array(query); + + if (results.RowCount() == 1) { - std::cerr << "Error in CheckStatus query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; + auto row = results.begin(); + + int16 status = atoi(row[0]); + + int32 suspendeduntil = 0; + + // MariaDB initalizes with NULL if unix_timestamp() is out of range + if (row[1] != nullptr) { + suspendeduntil = atoi(row[1]); + } + + int32 current = atoi(row[2]); + + if(suspendeduntil > current) + return -1; + + return status; } return 0; From 0ab8c2481bf9220f7e8313fec1137bc0b9a5e7a6 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 15:57:32 -0700 Subject: [PATCH 009/288] CreateAccount converted to QueryDatabase --- common/database.cpp | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 8e4c1c734..47ba02aec 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -307,30 +307,34 @@ int16 Database::CheckStatus(uint32 account_id) } uint32 Database::CreateAccount(const char* name, const char* password, int16 status, uint32 lsaccount_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 querylen; - uint32 last_insert_id; + char *query = nullptr; + + uint32 queryLen; if (password) - querylen = MakeAnyLenString(&query, "INSERT INTO account SET name='%s', password='%s', status=%i, lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",name,password,status, lsaccount_id); + queryLen = MakeAnyLenString(&query, "INSERT INTO account SET name='%s', password='%s', status=%i, lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",name,password,status, lsaccount_id); else - querylen = MakeAnyLenString(&query, "INSERT INTO account SET name='%s', status=%i, lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",name, status, lsaccount_id); + queryLen = MakeAnyLenString(&query, "INSERT INTO account SET name='%s', status=%i, lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",name, status, lsaccount_id); std::cerr << "Account Attempting to be created:" << name << " " << (int16) status << std::endl; - if (!RunQuery(query, querylen, errbuf, 0, 0, &last_insert_id)) { - std::cerr << "Error in CreateAccount query '" << query << "' " << errbuf << std::endl; + + auto results = QueryDatabase(query, queryLen); + + if (!results.Success()) + { + std::cerr << "Error in CreateAccount query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); return 0; } - safe_delete_array(query); - if (last_insert_id == 0) { - std::cerr << "Error in CreateAccount query '" << query << "' " << errbuf << std::endl; + if (results.LastInsertedID() == 0) + { + std::cerr << "Error in CreateAccount query '" << query << "' " << results.ErrorMessage() << std::endl; + safe_delete_array(query); return 0; } - return last_insert_id; + return results.LastInsertedID(); } bool Database::DeleteAccount(const char* name) { From ed6db3e7b047102d01906559c4c4efbd7956e98d Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 16:03:05 -0700 Subject: [PATCH 010/288] DeleteAccount converted to QueryDatabase --- common/database.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 47ba02aec..16dc2b6b5 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -338,24 +338,22 @@ uint32 Database::CreateAccount(const char* name, const char* password, int16 sta } bool Database::DeleteAccount(const char* name) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; + char *query = nullptr; std::cerr << "Account Attempting to be deleted:" << name << std::endl; - if (RunQuery(query, MakeAnyLenString(&query, "DELETE FROM account WHERE name='%s';",name), errbuf, 0, &affected_rows)) { - safe_delete_array(query); - if (affected_rows == 1) { - return true; - } - } - else { - std::cerr << "Error in DeleteAccount query '" << query << "' " << errbuf << std::endl; + auto results = QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM account WHERE name='%s';",name)); + + if (!results.Success()) + { + std::cerr << "Error in DeleteAccount query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); + return false; } - return false; + safe_delete_array(query); + + return results.RowsAffected() == 1; } bool Database::SetLocalPassword(uint32 accid, const char* password) { From 2e7f7ad477b98791305219dbdea9f185982e6977 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 16:04:50 -0700 Subject: [PATCH 011/288] SetLocalPassword converted to QueryDatabase --- common/database.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 16dc2b6b5..373e7db3d 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -357,11 +357,12 @@ bool Database::DeleteAccount(const char* name) { } bool Database::SetLocalPassword(uint32 accid, const char* password) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + char *query = nullptr; - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE account SET password=MD5('%s') where id=%i;", password, accid), errbuf)) { - std::cerr << "Error in SetLocalPassword query '" << query << "' " << errbuf << std::endl; + auto results = QueryDatabase(query, MakeAnyLenString(&query, "UPDATE account SET password=MD5('%s') where id=%i;", password, accid)); + + if (!results.Success()) { + std::cerr << "Error in SetLocalPassword query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); return false; } From e3de570f2939418a5f66915ddab467f32a948851 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 16:08:28 -0700 Subject: [PATCH 012/288] SetAccountStatus converted to QueryDatabase --- common/database.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 373e7db3d..adfb2c51e 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -372,18 +372,19 @@ bool Database::SetLocalPassword(uint32 accid, const char* password) { } bool Database::SetAccountStatus(const char* name, int16 status) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; + char *query = nullptr; std::cout << "Account being GM Flagged:" << name << ", Level: " << (int16) status << std::endl; - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE account SET status=%i WHERE name='%s';", status, name), errbuf, 0, &affected_rows)) { - safe_delete_array(query); - return false; - } + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "UPDATE account SET status=%i WHERE name='%s';", status, name)); + safe_delete_array(query); - if (affected_rows == 0) { + if (!results.Success()) + return false; + + if (results.RowsAffected() == 0) + { std::cout << "Account: " << name << " does not exist, therefore it cannot be flagged\n"; return false; } From 02b1b5ac0c57a3ac55f4ab01222a7a2e1e97550c Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 16:10:29 -0700 Subject: [PATCH 013/288] ReserveName converted to QueryDatabase --- common/database.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index adfb2c51e..780454fc0 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -394,14 +394,17 @@ bool Database::SetAccountStatus(const char* name, int16 status) { bool Database::ReserveName(uint32 account_id, char* name) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + char *query = nullptr; - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT into character_ SET account_id=%i, name='%s', profile=NULL", account_id, name), errbuf)) { - std::cerr << "Error in ReserveName query '" << query << "' " << errbuf << std::endl; + auto results = QueryDatabase(query, MakeAnyLenString(&query, "INSERT into character_ SET account_id=%i, name='%s', profile=NULL", account_id, name)); + + if (!results.Success()) + { + std::cerr << "Error in ReserveName query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); return false; } + safe_delete_array(query); return true; } From 3cb7d9e3fe6bb5b5038ceaa5dfb5d21711f98adb Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 16:22:15 -0700 Subject: [PATCH 014/288] removed printf from DeleteCharacter switched to cerr and cout --- common/database.cpp | 54 ++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 780454fc0..e6ee0df87 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -424,14 +424,14 @@ bool Database::DeleteCharacter(char *name) if(!name || !strlen(name)) { - printf("DeleteCharacter: request to delete without a name (empty char slot)\n"); + std::cerr << "DeleteCharacter: request to delete without a name (empty char slot)" << std::endl; return false; } // get id from character_ before deleting record so we can clean up inventory and qglobal #if DEBUG >= 5 - printf("DeleteCharacter: Attempting to delete '%s'\n", name); + std::cout << "DeleteCharacter: Attempting to delete '" << name << "'" << std::endl; #endif RunQuery(query, MakeAnyLenString(&query, "SELECT id from character_ WHERE name='%s'", name), errbuf, &result); if (query) @@ -445,12 +445,12 @@ bool Database::DeleteCharacter(char *name) row = mysql_fetch_row(result); charid = atoi(row[0]); #if DEBUG >= 5 - printf("DeleteCharacter: found '%s' with char id: %d\n", name, charid); + std::cout << "DeleteCharacter: found '" << name << "' with char id: " << charid << std::endl; #endif } else { - printf("DeleteCharacter: error: got %d rows matching '%s'\n", matches, name); + std::cerr << "DeleteCharacter error: got " << matches << " rows matching '" << name << "'" << std::endl; if(result) { mysql_free_result(result); @@ -468,8 +468,8 @@ bool Database::DeleteCharacter(char *name) #if DEBUG >= 5 - printf("DeleteCharacter: deleting '%s' (id %d): ", name, charid); - printf(" quest_globals"); + std::cout << "DeleteCharacter: deleting << '" << name << "' (id " << charid << "): " << std::endl; + std::cout << " quest_globals"; #endif RunQuery(query, MakeAnyLenString(&query, "DELETE from quest_globals WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); if(query) @@ -479,7 +479,7 @@ bool Database::DeleteCharacter(char *name) } #if DEBUG >= 5 - printf(" character_tasks"); + std::cout << " character_tasks"; #endif RunQuery(query, MakeAnyLenString(&query, "DELETE from character_tasks WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); if(query) @@ -489,7 +489,7 @@ bool Database::DeleteCharacter(char *name) } #if DEBUG >= 5 - printf(" character_activities"); + std::cout << " character_activities"; #endif RunQuery(query, MakeAnyLenString(&query, "DELETE from character_activities WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); if(query) @@ -499,7 +499,7 @@ bool Database::DeleteCharacter(char *name) } #if DEBUG >= 5 - printf(" character_enabledtasks"); + std::cout << " character_enabledtasks"; #endif RunQuery(query, MakeAnyLenString(&query, "DELETE from character_enabledtasks WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); if(query) @@ -509,7 +509,7 @@ bool Database::DeleteCharacter(char *name) } #if DEBUG >= 5 - printf(" completed_tasks"); + std::cout << " completed_tasks"; #endif RunQuery(query, MakeAnyLenString(&query, "DELETE from completed_tasks WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); if(query) @@ -519,7 +519,7 @@ bool Database::DeleteCharacter(char *name) } #if DEBUG >= 5 - printf(" friends"); + std::cout << " friends"; #endif RunQuery(query, MakeAnyLenString(&query, "DELETE from friends WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); if(query) @@ -529,7 +529,7 @@ bool Database::DeleteCharacter(char *name) } #if DEBUG >= 5 - printf(" mail"); + std::cout << " mail"; #endif RunQuery(query, MakeAnyLenString(&query, "DELETE from mail WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); if(query) @@ -539,7 +539,7 @@ bool Database::DeleteCharacter(char *name) } #if DEBUG >= 5 - printf(" ptimers"); + std::cout << " ptimers"; #endif RunQuery(query, MakeAnyLenString(&query, "DELETE from timers WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); if(query) @@ -549,7 +549,7 @@ bool Database::DeleteCharacter(char *name) } #if DEBUG >= 5 - printf(" inventory"); + std::cout << " inventory"; #endif RunQuery(query, MakeAnyLenString(&query, "DELETE from inventory WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); if(query) @@ -559,7 +559,7 @@ bool Database::DeleteCharacter(char *name) } #if DEBUG >= 5 - printf(" guild_members"); + std::cout << " guild_members"; #endif #ifdef BOTS RunQuery(query, MakeAnyLenString(&query, "DELETE FROM guild_members WHERE char_id='%d' AND GetMobTypeById(%i) = 'C'", charid), errbuf, nullptr, &affected_rows); @@ -573,7 +573,7 @@ bool Database::DeleteCharacter(char *name) } #if DEBUG >= 5 - printf(" recipes"); + std::cout << " recipes"; #endif RunQuery(query, MakeAnyLenString(&query, "DELETE FROM char_recipe_list WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); if(query) @@ -583,7 +583,7 @@ bool Database::DeleteCharacter(char *name) } #if DEBUG >= 5 - printf(" adventure_stats"); + std::cout << " adventure_stats"; #endif RunQuery(query, MakeAnyLenString(&query, "DELETE FROM adventure_stats WHERE player_id='%d'", charid), errbuf, nullptr, &affected_rows); if(query) @@ -593,7 +593,7 @@ bool Database::DeleteCharacter(char *name) } #if DEBUG >= 5 - printf(" zone_flags"); + std::cout << " zone_flags"; #endif RunQuery(query, MakeAnyLenString(&query, "DELETE FROM zone_flags WHERE charID='%d'", charid), errbuf, nullptr, &affected_rows); if(query) @@ -603,7 +603,7 @@ bool Database::DeleteCharacter(char *name) } #if DEBUG >= 5 - printf(" titles"); + std::cout << " titles"; #endif RunQuery(query, MakeAnyLenString(&query, "DELETE FROM titles WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); if(query) @@ -613,7 +613,7 @@ bool Database::DeleteCharacter(char *name) } #if DEBUG >= 5 - printf(" titlesets"); + std::cout << " titlesets"; #endif RunQuery(query, MakeAnyLenString(&query, "DELETE FROM player_titlesets WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); if(query) @@ -623,7 +623,7 @@ bool Database::DeleteCharacter(char *name) } #if DEBUG >= 5 - printf(" keyring"); + std::cout << " keyring"; #endif RunQuery(query, MakeAnyLenString(&query, "DELETE FROM keyring WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); if(query) @@ -633,7 +633,7 @@ bool Database::DeleteCharacter(char *name) } #if DEBUG >= 5 - printf(" factions"); + std::cout << " factions"; #endif RunQuery(query, MakeAnyLenString(&query, "DELETE FROM faction_values WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); if(query) @@ -643,7 +643,7 @@ bool Database::DeleteCharacter(char *name) } #if DEBUG >= 5 - printf(" instances"); + std::cout << " instances"; #endif RunQuery(query, MakeAnyLenString(&query, "DELETE FROM instance_list_player WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); if(query) @@ -653,7 +653,7 @@ bool Database::DeleteCharacter(char *name) } #if DEBUG >= 5 - printf(" _character"); + std::cout << " _character"; #endif RunQuery(query, MakeAnyLenString(&query, "DELETE from character_ WHERE id='%d'", charid), errbuf, nullptr, &affected_rows); if(query) @@ -668,7 +668,7 @@ bool Database::DeleteCharacter(char *name) } #if DEBUG >= 5 - printf(" alternate currency"); + std::cout << " alternate currency"; #endif RunQuery(query, MakeAnyLenString(&query, "DELETE FROM character_alt_currency WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); if(query) @@ -678,9 +678,9 @@ bool Database::DeleteCharacter(char *name) } #if DEBUG >= 5 - printf("\n"); + std::cout << std::endl; #endif - printf("DeleteCharacter: successfully deleted '%s' (id %d)\n", name, charid); + std::cout << "DeleteCharacter: successfully deleted '" << name << "' (id " << charid << ")" << std::endl; return true; } From 3aacf7df6a1645e7a1b76d19bfca05f4df6839d9 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 16:43:24 -0700 Subject: [PATCH 015/288] DeleteCharacter converted to QueryDatabase --- common/database.cpp | 234 ++++++++++++++------------------------------ 1 file changed, 76 insertions(+), 158 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index e6ee0df87..74de058e5 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -415,12 +415,8 @@ returns false on failure, true otherwise */ bool Database::DeleteCharacter(char *name) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query=0; - MYSQL_RES *result; - MYSQL_ROW row; - int charid, matches; - uint32 affected_rows; + char *query=nullptr; + int charid; if(!name || !strlen(name)) { @@ -433,249 +429,171 @@ bool Database::DeleteCharacter(char *name) #if DEBUG >= 5 std::cout << "DeleteCharacter: Attempting to delete '" << name << "'" << std::endl; #endif - RunQuery(query, MakeAnyLenString(&query, "SELECT id from character_ WHERE name='%s'", name), errbuf, &result); - if (query) + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT id from character_ WHERE name='%s'", name)); + + safe_delete_array(query); + + if(results.RowCount() != 1) { - safe_delete_array(query); - query = nullptr; - } - matches = mysql_num_rows(result); - if(matches == 1) - { - row = mysql_fetch_row(result); - charid = atoi(row[0]); -#if DEBUG >= 5 - std::cout << "DeleteCharacter: found '" << name << "' with char id: " << charid << std::endl; -#endif - } - else - { - std::cerr << "DeleteCharacter error: got " << matches << " rows matching '" << name << "'" << std::endl; - if(result) - { - mysql_free_result(result); - result = nullptr; - } + std::cerr << "DeleteCharacter error: got " << results.RowCount() << " rows matching '" << name << "'" << std::endl; return false; } - if(result) - { - mysql_free_result(result); - result = nullptr; - } - - + auto row = results.begin(); + charid = atoi(row[0]); #if DEBUG >= 5 + std::cout << "DeleteCharacter: found '" << name << "' with char id: " << charid << std::endl; std::cout << "DeleteCharacter: deleting << '" << name << "' (id " << charid << "): " << std::endl; std::cout << " quest_globals"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE from quest_globals WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + QueryDatabase(query, MakeAnyLenString(&query, "DELETE from quest_globals WHERE charid='%d'", charid)); + safe_delete_array(query); #if DEBUG >= 5 std::cout << " character_tasks"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE from character_tasks WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + QueryDatabase(query, MakeAnyLenString(&query, "DELETE from character_tasks WHERE charid='%d'", charid)); + safe_delete_array(query); #if DEBUG >= 5 std::cout << " character_activities"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE from character_activities WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + QueryDatabase(query, MakeAnyLenString(&query, "DELETE from character_activities WHERE charid='%d'", charid)); + safe_delete_array(query); #if DEBUG >= 5 std::cout << " character_enabledtasks"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE from character_enabledtasks WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + QueryDatabase(query, MakeAnyLenString(&query, "DELETE from character_enabledtasks WHERE charid='%d'", charid)); + safe_delete_array(query); #if DEBUG >= 5 std::cout << " completed_tasks"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE from completed_tasks WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + QueryDatabase(query, MakeAnyLenString(&query, "DELETE from completed_tasks WHERE charid='%d'", charid)); + safe_delete_array(query); #if DEBUG >= 5 std::cout << " friends"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE from friends WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + QueryDatabase(query, MakeAnyLenString(&query, "DELETE from friends WHERE charid='%d'", charid)); + safe_delete_array(query); #if DEBUG >= 5 std::cout << " mail"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE from mail WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + QueryDatabase(query, MakeAnyLenString(&query, "DELETE from mail WHERE charid='%d'", charid)); + safe_delete_array(query); #if DEBUG >= 5 std::cout << " ptimers"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE from timers WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + QueryDatabase(query, MakeAnyLenString(&query, "DELETE from timers WHERE char_id='%d'", charid)); + safe_delete_array(query); #if DEBUG >= 5 std::cout << " inventory"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE from inventory WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + QueryDatabase(query, MakeAnyLenString(&query, "DELETE from inventory WHERE charid='%d'", charid)); + safe_delete_array(query); #if DEBUG >= 5 std::cout << " guild_members"; #endif + #ifdef BOTS - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM guild_members WHERE char_id='%d' AND GetMobTypeById(%i) = 'C'", charid), errbuf, nullptr, &affected_rows); + QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM guild_members WHERE char_id='%d' AND GetMobTypeById(%i) = 'C'", charid)); #else - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM guild_members WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); + QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM guild_members WHERE char_id='%d'", charid)); #endif - if(query) - { - safe_delete_array(query); - query = nullptr; - } + safe_delete_array(query); #if DEBUG >= 5 std::cout << " recipes"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM char_recipe_list WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM char_recipe_list WHERE char_id='%d'", charid)); + safe_delete_array(query); #if DEBUG >= 5 std::cout << " adventure_stats"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM adventure_stats WHERE player_id='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM adventure_stats WHERE player_id='%d'", charid)); + safe_delete_array(query); #if DEBUG >= 5 std::cout << " zone_flags"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM zone_flags WHERE charID='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM zone_flags WHERE charID='%d'", charid)); + safe_delete_array(query); #if DEBUG >= 5 std::cout << " titles"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM titles WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM titles WHERE char_id='%d'", charid)); + safe_delete_array(query); #if DEBUG >= 5 std::cout << " titlesets"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM player_titlesets WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM player_titlesets WHERE char_id='%d'", charid)); + safe_delete_array(query); #if DEBUG >= 5 std::cout << " keyring"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM keyring WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM keyring WHERE char_id='%d'", charid)); + safe_delete_array(query); #if DEBUG >= 5 std::cout << " factions"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM faction_values WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM faction_values WHERE char_id='%d'", charid)); + safe_delete_array(query); #if DEBUG >= 5 std::cout << " instances"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM instance_list_player WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM instance_list_player WHERE charid='%d'", charid)); + safe_delete_array(query); #if DEBUG >= 5 std::cout << " _character"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE from character_ WHERE id='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) + + results = QueryDatabase(query, MakeAnyLenString(&query, "DELETE from character_ WHERE id='%d'", charid)); + safe_delete_array(query); + + if(results.RowsAffected() != 1) // here we have to have a match or it's an error { - safe_delete_array(query); - query = nullptr; - } - if(affected_rows != 1) // here we have to have a match or it's an error - { - LogFile->write(EQEMuLog::Error, "DeleteCharacter: error: delete operation affected %d rows\n", affected_rows); + LogFile->write(EQEMuLog::Error, "DeleteCharacter: error: delete operation affected %d rows\n", results.RowsAffected()); return false; } #if DEBUG >= 5 std::cout << " alternate currency"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM character_alt_currency WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM character_alt_currency WHERE char_id='%d'", charid)); + safe_delete_array(query); #if DEBUG >= 5 std::cout << std::endl; From 0aacecbee563ab4ea4a667f212e4f82d76d8719c Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 16:50:14 -0700 Subject: [PATCH 016/288] GetAccountIDByChar converted to QueryDatabase --- common/database.cpp | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 74de058e5..2cd4ce712 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -747,27 +747,29 @@ the name "name" or zero if no character with that name was found Zero will also be returned if there is a database error. */ uint32 Database::GetAccountIDByChar(const char* charname, uint32* oCharID) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT account_id, id FROM character_ WHERE name='%s'", charname), errbuf, &result)) { + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT account_id, id FROM character_ WHERE name='%s'", charname)); + + if (!results.Success()) + { + std::cerr << "Error in GetAccountIDByChar query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); - if (mysql_num_rows(result) == 1) - { - row = mysql_fetch_row(result); - uint32 tmp = atoi(row[0]); // copy to temp var because gotta free the result before exitting this function - if (oCharID) - *oCharID = atoi(row[1]); - mysql_free_result(result); - return tmp; - } - mysql_free_result(result); + return 0; } - else { - std::cerr << "Error in GetAccountIDByChar query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + + safe_delete_array(query); + + if (results.RowCount() == 1) + { + auto row = results.begin(); + + uint32 accountId = atoi(row[0]); + + if (oCharID) + *oCharID = atoi(row[1]); + + return accountId; } return 0; From 5e629a3e5c9a4583739a796fc521dea8eca3f097 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 16:57:02 -0700 Subject: [PATCH 017/288] GetAccountIDByChar converted to QueryDatabase --- common/database.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 2cd4ce712..7009b43a9 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -777,25 +777,25 @@ uint32 Database::GetAccountIDByChar(const char* charname, uint32* oCharID) { // Retrieve account_id for a given char_id uint32 Database::GetAccountIDByChar(uint32 char_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint32 ret = 0; + char* query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT account_id FROM character_ WHERE id=%i", char_id), errbuf, &result)) { - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - ret = atoi(row[0]); // copy to temp var because gotta free the result before exitting this function - } - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "Error in GetAccountIDByChar query '%s': %s", query, errbuf); + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT account_id FROM character_ WHERE id=%i", char_id)); + + if (!results.Success()) + { + LogFile->write(EQEMuLog::Error, "Error in GetAccountIDByChar query '%s': %s", query, results.ErrorMessage()); + safe_delete_array(query); + return 0; } safe_delete_array(query); - return ret; + + if (results.RowCount() != 1) + return 0; + + auto row = results.begin(); + + return atoi(row[0]); } uint32 Database::GetAccountIDByName(const char* accname, int16* status, uint32* lsid) { From 9c6b5381764b364eddf2a0a4ea38bc5ed7355d34 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 17:07:35 -0700 Subject: [PATCH 018/288] GetAccountIDByName converted to QueryDatabase --- common/database.cpp | 52 +++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 7009b43a9..53065269f 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -799,11 +799,7 @@ uint32 Database::GetAccountIDByChar(uint32 char_id) { } uint32 Database::GetAccountIDByName(const char* accname, int16* status, uint32* lsid) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - + char *query = nullptr; for (unsigned int i=0; i 'z') && @@ -812,30 +808,36 @@ uint32 Database::GetAccountIDByName(const char* accname, int16* status, uint32* return 0; } - if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, status, lsaccount_id FROM account WHERE name='%s'", accname), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - uint32 tmp = atoi(row[0]); // copy to temp var because gotta free the result before exitting this function - if (status) - *status = atoi(row[1]); - if (lsid) { - if (row[2]) - *lsid = atoi(row[2]); - else - *lsid = 0; - } - mysql_free_result(result); - return tmp; - } - mysql_free_result(result); - } - else { + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT id, status, lsaccount_id FROM account WHERE name='%s'", accname)); + + if (!results.Success()) + { std::cerr << "Error in GetAccountIDByAcc query '" << query << "' " << errbuf << std::endl; safe_delete_array(query); + return 0; } - return 0; + safe_delete_array(query); + + if (results.RowCount() != 1) + return 0; + + auto row = results.begin(); + + uint32 id = atoi(row[0]); + + if (status) + *status = atoi(row[1]); + + if (lsid) + { + if (row[2]) + *lsid = atoi(row[2]); + else + *lsid = 0; + } + + return id; } void Database::GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID) { From 20e80ebb921d160274cf035c7c94a708e4f09514 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 17:18:13 -0700 Subject: [PATCH 019/288] errbuff fixed, also moved alphanumeric account check to function in StringUtil --- common/StringUtil.cpp | 12 ++++++++++++ common/StringUtil.h | 2 ++ common/database.cpp | 10 +++------- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/common/StringUtil.cpp b/common/StringUtil.cpp index 71bb961e1..b89a1455d 100644 --- a/common/StringUtil.cpp +++ b/common/StringUtil.cpp @@ -384,3 +384,15 @@ std::string EscapeString(const std::string &s) { return ret; } + +bool isAlphaNumeric(const char *text) +{ + for (unsigned int charIndex=0; charIndex 'z') && + (text[charIndex] < 'A' || text[charIndex] > 'Z') && + (text[charIndex] < '0' || text[charIndex] > '9')) + return false; + } + + return true; +} \ No newline at end of file diff --git a/common/StringUtil.h b/common/StringUtil.h index 46ff43183..2e4182bf8 100644 --- a/common/StringUtil.h +++ b/common/StringUtil.h @@ -51,4 +51,6 @@ char *RemoveApostrophes(const char *s); std::vector SplitString(const std::string &s, char delim); +bool isAlphaNumeric(const char *text); + #endif diff --git a/common/database.cpp b/common/database.cpp index 53065269f..16c2bf89e 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -801,18 +801,14 @@ uint32 Database::GetAccountIDByChar(uint32 char_id) { uint32 Database::GetAccountIDByName(const char* accname, int16* status, uint32* lsid) { char *query = nullptr; - for (unsigned int i=0; i 'z') && - (accname[i] < 'A' || accname[i] > 'Z') && - (accname[i] < '0' || accname[i] > '9')) - return 0; - } + if (!isAlphaNumeric(accname)) + return 0; auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT id, status, lsaccount_id FROM account WHERE name='%s'", accname)); if (!results.Success()) { - std::cerr << "Error in GetAccountIDByAcc query '" << query << "' " << errbuf << std::endl; + std::cerr << "Error in GetAccountIDByAcc query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); return 0; } From 5ef05d1bb6b224714fb35b55545208343288ac20 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 17:34:25 -0700 Subject: [PATCH 020/288] GetAccountName converted to QueryDatabase --- common/database.cpp | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 16c2bf89e..4cdc6f3c0 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -837,28 +837,29 @@ uint32 Database::GetAccountIDByName(const char* accname, int16* status, uint32* } void Database::GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT name, lsaccount_id FROM account WHERE id='%i'", accountid), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT name, lsaccount_id FROM account WHERE id='%i'", accountid)); - strcpy(name, row[0]); - if (row[1] && oLSAccountID) { - *oLSAccountID = atoi(row[1]); - } - } - - mysql_free_result(result); - } - else { - safe_delete_array(query); + if (!results.Success()) + { std::cerr << "Error in GetAccountName query '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); + return; } + + safe_delete_array(query); + + if (results.RowCount() != 1) + return; + + auto row = results.begin(); + + strcpy(name, row[0]); + if (row[1] && oLSAccountID) { + *oLSAccountID = atoi(row[1]); + } + } void Database::GetCharName(uint32 char_id, char* name) { From 4e25f4b68c867c0acee264c6298afc83833c540a Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 17:36:56 -0700 Subject: [PATCH 021/288] GetCharName converted to QueryDatabase --- common/database.cpp | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 4cdc6f3c0..ffc493c2b 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -863,26 +863,21 @@ void Database::GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID } void Database::GetCharName(uint32 char_id, char* name) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT name FROM character_ WHERE id='%i'", char_id), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT name FROM character_ WHERE id='%i'", char_id)); - strcpy(name, row[0]); - } - - mysql_free_result(result); - } - else { - safe_delete_array(query); + if (!results.Success()) + { std::cerr << "Error in GetCharName query '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); + return; } + safe_delete_array(query); + + auto row = results.begin(); + strcpy(name, row[0]); } bool Database::LoadVariables() { From 87cb659dc2029693b05b4b9b49a1a96f1058bf51 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 17:38:47 -0700 Subject: [PATCH 022/288] errbuf issue again --- common/database.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/database.cpp b/common/database.cpp index ffc493c2b..83daf8657 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -869,7 +869,7 @@ void Database::GetCharName(uint32 char_id, char* name) { if (!results.Success()) { - std::cerr << "Error in GetCharName query '" << query << "' " << errbuf << std::endl; + std::cerr << "Error in GetCharName query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); return; } From 74d65f6fdae5c5e02c091cc62dda5f1b5ad996df Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 17:42:35 -0700 Subject: [PATCH 023/288] Converted LoadVariables, and LoadVariables_result to QueryDatabase --- common/database.cpp | 123 +++++++++++++++++++++++--------------------- common/database.h | 2 +- 2 files changed, 64 insertions(+), 61 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 83daf8657..9cbf7beab 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -843,7 +843,7 @@ void Database::GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID if (!results.Success()) { - std::cerr << "Error in GetAccountName query '" << query << "' " << errbuf << std::endl; + std::cerr << "Error in GetAccountName query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); return; } @@ -881,82 +881,85 @@ void Database::GetCharName(uint32 char_id, char* name) { } bool Database::LoadVariables() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; + char *query = nullptr; - if (RunQuery(query, LoadVariables_MQ(&query), errbuf, &result)) { + auto results = QueryDatabase(query, LoadVariables_MQ(&query)); + + if (!results.Success()) + { + std::cerr << "Error in LoadVariables query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); - bool ret = LoadVariables_result(result); - mysql_free_result(result); - return ret; + return false; } - else { - std::cerr << "Error in LoadVariables query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - } - return false; + + safe_delete_array(query); + return LoadVariables_result(results); } -uint32 Database::LoadVariables_MQ(char** query) { -// the read of this single variable should be atomic... this was causing strange problems -// LockMutex lock(&Mvarcache); +uint32 Database::LoadVariables_MQ(char** query) +{ return MakeAnyLenString(query, "SELECT varname, value, unix_timestamp() FROM variables where unix_timestamp(ts) >= %d", varcache_lastupdate); } -bool Database::LoadVariables_result(MYSQL_RES* result) { - uint32 i; - MYSQL_ROW row; +// always returns true? not sure about this. +bool Database::LoadVariables_result(MySQLRequestResult results) { + uint32 i = 0; LockMutex lock(&Mvarcache); - if (mysql_num_rows(result) > 0) { - if (!varcache_array) { - varcache_max = mysql_num_rows(result); - varcache_array = new VarCache_Struct*[varcache_max]; - for (i=0; ivarname, row[0]) == 0) { - delete varcache_array[i]; - varcache_array[i] = (VarCache_Struct*) new uint8[sizeof(VarCache_Struct) + strlen(row[1]) + 1]; - strn0cpy(varcache_array[i]->varname, row[0], sizeof(varcache_array[i]->varname)); - strcpy(varcache_array[i]->value, row[1]); - break; - } - } - else { + + if (results.RowCount() == 0) + return true; + + if (!varcache_array) { + varcache_max = results.RowCount(); + varcache_array = new VarCache_Struct*[varcache_max]; + for (i=0; ivarname, row[0]) == 0) { + delete varcache_array[i]; varcache_array[i] = (VarCache_Struct*) new uint8[sizeof(VarCache_Struct) + strlen(row[1]) + 1]; - strcpy(varcache_array[i]->varname, row[0]); + strn0cpy(varcache_array[i]->varname, row[0], sizeof(varcache_array[i]->varname)); strcpy(varcache_array[i]->value, row[1]); break; } } - } - uint32 max_used = 0; - for (i=0; i max_used) - max_used = i; + else { + varcache_array[i] = (VarCache_Struct*) new uint8[sizeof(VarCache_Struct) + strlen(row[1]) + 1]; + strcpy(varcache_array[i]->varname, row[0]); + strcpy(varcache_array[i]->value, row[1]); + break; } } - max_used++; - varcache_max = max_used; } + + uint32 max_used = 0; + for (i=0; i max_used) + max_used = i; + } + } + + varcache_max = max_used + 1; + return true; } diff --git a/common/database.h b/common/database.h index 300fc9875..4d2b15de7 100644 --- a/common/database.h +++ b/common/database.h @@ -223,7 +223,7 @@ public: bool SetVariable(const char* varname, const char* varvalue); bool LoadVariables(); uint32 LoadVariables_MQ(char** query); - bool LoadVariables_result(MYSQL_RES* result); + bool LoadVariables_result(MySQLRequestResult results); /* * General Queries From 6d6746f5a4fbe2f16930bb5be5c550685e04ac7f Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 18:21:21 -0700 Subject: [PATCH 024/288] SetVariable converted to QueryDatabase --- common/database.cpp | 51 ++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 9cbf7beab..2f02645d4 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -986,9 +986,7 @@ bool Database::GetVariable(const char* varname, char* varvalue, uint16 varvalue_ } bool Database::SetVariable(const char* varname_in, const char* varvalue_in) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; + char *query = nullptr; char *varname,*varvalue; @@ -997,32 +995,37 @@ bool Database::SetVariable(const char* varname_in, const char* varvalue_in) { DoEscapeString(varname, varname_in, strlen(varname_in)); DoEscapeString(varvalue, varvalue_in, strlen(varvalue_in)); - if (RunQuery(query, MakeAnyLenString(&query, "Update variables set value='%s' WHERE varname like '%s'", varvalue, varname), errbuf, 0, &affected_rows)) { + auto results = QueryDatabase(query, MakeAnyLenString(&query, "Update variables set value='%s' WHERE varname like '%s'", varvalue, varname)); + + if (!results.Success()) + { + std::cerr << "Error in SetVariable query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); - if (affected_rows == 1) { - LoadVariables(); // refresh cache - free(varname); - free(varvalue); - return true; - } - else { - if (RunQuery(query, MakeAnyLenString(&query, "Insert Into variables (varname, value) values ('%s', '%s')", varname, varvalue), errbuf, 0, &affected_rows)) { - safe_delete_array(query); - if (affected_rows == 1) { - LoadVariables(); // refresh cache - free(varname); - free(varvalue); - return true; - } - } - } + free(varname); + free(varvalue); + return false; } - else { - std::cerr << "Error in SetVariable query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + + safe_delete_array(query); + + if (results.RowsAffected() == 1) + { + LoadVariables(); // refresh cache + free(varname); + free(varvalue); + return true; } + + results = QueryDatabase(query, MakeAnyLenString(&query, "Insert Into variables (varname, value) values ('%s', '%s')", varname, varvalue)); + safe_delete_array(query); free(varname); free(varvalue); + + if (results.RowsAffected() == 1) { + LoadVariables(); // refresh cache + return true; + } + return false; } From 3dfff739faf539338a5d173d98ed00a627c2e735 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 18:24:02 -0700 Subject: [PATCH 025/288] GetMiniLoginAccount converted to QueryDatabase --- common/database.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 2f02645d4..1b71e5493 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1030,23 +1030,21 @@ bool Database::SetVariable(const char* varname_in, const char* varvalue_in) { } uint32 Database::GetMiniLoginAccount(char* ip){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint32 retid = 0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT id FROM account WHERE minilogin_ip='%s'", ip), errbuf, &result)) { - safe_delete_array(query); - if ((row = mysql_fetch_row(result))) - retid = atoi(row[0]); - mysql_free_result(result); - } - else + char *query = nullptr; + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT id FROM account WHERE minilogin_ip='%s'", ip)); + + if (!results.Success()) { std::cerr << "Error in GetMiniLoginAccount query '" << query << "' " << errbuf << std::endl; safe_delete_array(query); + return 0; } - return retid; + safe_delete_array(query); + + auto row = results.begin(); + + return atoi(row[0]); } // Pyro: Get zone starting points from DB From ee696c212251aa4a02a809e61ab0ee9790f7cd67 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 18:28:49 -0700 Subject: [PATCH 026/288] errbuf fix (again) and GetSafePoints converted to QueryDatabase --- common/database.cpp | 63 +++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 1b71e5493..9f88c843b 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1036,7 +1036,7 @@ uint32 Database::GetMiniLoginAccount(char* ip){ if (!results.Success()) { - std::cerr << "Error in GetMiniLoginAccount query '" << query << "' " << errbuf << std::endl; + std::cerr << "Error in GetMiniLoginAccount query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); return 0; } @@ -1047,51 +1047,48 @@ uint32 Database::GetMiniLoginAccount(char* ip){ return atoi(row[0]); } -// Pyro: Get zone starting points from DB +// Get zone starting points from DB bool Database::GetSafePoints(const char* short_name, uint32 version, float* safe_x, float* safe_y, float* safe_z, int16* minstatus, uint8* minlevel, char *flag_needed) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - // int buf_len = 256; - // int chars = -1; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT safe_x, safe_y, safe_z, min_status, min_level, " " flag_needed FROM zone " - " WHERE short_name='%s' AND (version=%i OR version=0) ORDER BY version DESC", short_name, version), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) > 0) { - row = mysql_fetch_row(result); - if (safe_x != 0) - *safe_x = atof(row[0]); - if (safe_y != 0) - *safe_y = atof(row[1]); - if (safe_z != 0) - *safe_z = atof(row[2]); - if (minstatus != 0) - *minstatus = atoi(row[3]); - if (minlevel != 0) - *minlevel = atoi(row[4]); - if (flag_needed != nullptr) - strcpy(flag_needed, row[5]); - mysql_free_result(result); - return true; - } + " WHERE short_name='%s' AND (version=%i OR version=0) ORDER BY version DESC", short_name, version)); - mysql_free_result(result); - } - else + if (!results.Success()) { - std::cerr << "Error in GetSafePoint query '" << query << "' " << errbuf << std::endl; + std::cerr << "Error in GetSafePoint query '" << query << "' " << results.ErrorMessage() << std::endl; std::cerr << "If it errors, run the following querys:\n"; std::cerr << "ALTER TABLE `zone` CHANGE `minium_level` `min_level` TINYINT(3) UNSIGNED DEFAULT \"0\" NOT NULL;\n"; std::cerr << "ALTER TABLE `zone` CHANGE `minium_status` `min_status` TINYINT(3) UNSIGNED DEFAULT \"0\" NOT NULL;\n"; std::cerr << "ALTER TABLE `zone` ADD flag_needed VARCHAR(128) NOT NULL DEFAULT '';\n"; safe_delete_array(query); + return false; } - return false; + + safe_delete_array(query); + + if (results.RowCount() == 0) + return false; + + auto row = results.begin(); + + if (safe_x != nullptr) + *safe_x = atof(row[0]); + if (safe_y != nullptr) + *safe_y = atof(row[1]); + if (safe_z != nullptr) + *safe_z = atof(row[2]); + if (minstatus != nullptr) + *minstatus = atoi(row[3]); + if (minlevel != nullptr) + *minlevel = atoi(row[4]); + if (flag_needed != nullptr) + strcpy(flag_needed, row[5]); + + return true; } From 91c8233a719c63f1eaf1aef4b94793646da216a4 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 18:32:52 -0700 Subject: [PATCH 027/288] GetZoneLongName converted to QueryDatabase --- common/database.cpp | 68 +++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 9f88c843b..e39543475 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1093,48 +1093,44 @@ bool Database::GetSafePoints(const char* short_name, uint32 version, float* safe bool Database::GetZoneLongName(const char* short_name, char** long_name, char* file_name, float* safe_x, float* safe_y, float* safe_z, uint32* graveyard_id, uint32* maxclients) { - char errbuf[MYSQL_ERRMSG_SIZE]; char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT long_name, file_name, safe_x, safe_y, safe_z, graveyard_id, maxclients FROM zone WHERE short_name='%s' AND version=0", short_name), errbuf, &result)) - { - safe_delete_array(query); - if (mysql_num_rows(result) > 0) { - row = mysql_fetch_row(result); - if (long_name != 0) { - *long_name = strcpy(new char[strlen(row[0])+1], row[0]); - } - if (file_name != 0) { - if (row[1] == 0) - strcpy(file_name, short_name); - else - strcpy(file_name, row[1]); - } - if (safe_x != 0) - *safe_x = atof(row[2]); - if (safe_y != 0) - *safe_y = atof(row[3]); - if (safe_z != 0) - *safe_z = atof(row[4]); - if (graveyard_id != 0) - *graveyard_id = atoi(row[5]); - if (maxclients) - *maxclients = atoi(row[6]); - mysql_free_result(result); - return true; - } - mysql_free_result(result); - } - else - { - std::cerr << "Error in GetZoneLongName query '" << query << "' " << errbuf << std::endl; + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT long_name, file_name, safe_x, safe_y, safe_z, graveyard_id, maxclients FROM zone WHERE short_name='%s' AND version=0", short_name)); + + if (!results.Success()) { + std::cerr << "Error in GetZoneLongName query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); return false; } + safe_delete_array(query); - return false; + if (results.RowCount() == 0) + return false; + + auto row = results.begin(); + + if (long_name != nullptr) + *long_name = strcpy(new char[strlen(row[0])+1], row[0]); + + if (file_name != nullptr) { + if (row[1] == nullptr) + strcpy(file_name, short_name); + else + strcpy(file_name, row[1]); + } + + if (safe_x != nullptr) + *safe_x = atof(row[2]); + if (safe_y != nullptr) + *safe_y = atof(row[3]); + if (safe_z != nullptr) + *safe_z = atof(row[4]); + if (graveyard_id != nullptr) + *graveyard_id = atoi(row[5]); + if (maxclients != nullptr) + *maxclients = atoi(row[6]); + + return true; } uint32 Database::GetZoneGraveyardID(uint32 zone_id, uint32 version) { char errbuf[MYSQL_ERRMSG_SIZE]; From 329fcc8302137fb0a25029f5e013c75cfda4e7f5 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 18:36:16 -0700 Subject: [PATCH 028/288] GetZoneGraveyardID converted to QueryDatabase --- common/database.cpp | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index e39543475..aa3fffb5e 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1133,28 +1133,23 @@ bool Database::GetZoneLongName(const char* short_name, char** long_name, char* f return true; } uint32 Database::GetZoneGraveyardID(uint32 zone_id, uint32 version) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint32 GraveyardID = 0; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT graveyard_id FROM zone WHERE zoneidnumber='%u' AND (version=%i OR version=0) ORDER BY version DESC", zone_id, version), errbuf, &result)) + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT graveyard_id FROM zone WHERE zoneidnumber='%u' AND (version=%i OR version=0) ORDER BY version DESC", zone_id, version)); + + if (!results.Success()) { - if (mysql_num_rows(result) > 0) { - row = mysql_fetch_row(result); - GraveyardID = atoi(row[0]); - } - mysql_free_result(result); + std::cerr << "Error in GetZoneGraveyardID query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); - return GraveyardID; - } - else - { - std::cerr << "Error in GetZoneGraveyardID query '" << query << "' " << errbuf << std::endl; + return 0; } safe_delete_array(query); - return GraveyardID; + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + return atoi(row[0]); } bool Database::GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid, float* graveyard_x, float* graveyard_y, float* graveyard_z, float* graveyard_heading) { From 24d08857e831ffb65b9ffdd4897a1a712aaff5ca Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 18:39:51 -0700 Subject: [PATCH 029/288] GetZoneGraveyard converted to QueryDatabase --- common/database.cpp | 51 ++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index aa3fffb5e..3a9a8758a 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1153,39 +1153,34 @@ uint32 Database::GetZoneGraveyardID(uint32 zone_id, uint32 version) { } bool Database::GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid, float* graveyard_x, float* graveyard_y, float* graveyard_z, float* graveyard_heading) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT zone_id, x, y, z, heading FROM graveyard WHERE id=%i", graveyard_id), errbuf, &result)) - { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - if(graveyard_zoneid != 0) - *graveyard_zoneid = atoi(row[0]); - if(graveyard_x != 0) - *graveyard_x = atof(row[1]); - if(graveyard_y != 0) - *graveyard_y = atof(row[2]); - if(graveyard_z != 0) - *graveyard_z = atof(row[3]); - if(graveyard_heading != 0) - *graveyard_heading = atof(row[4]); - mysql_free_result(result); - return true; - } - mysql_free_result(result); - } - else - { - std::cerr << "Error in GetZoneGraveyard query '" << query << "' " << errbuf << std::endl; + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT zone_id, x, y, z, heading FROM graveyard WHERE id=%i", graveyard_id)); + + if (!results.Success()){ + std::cerr << "Error in GetZoneGraveyard query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); return false; } + safe_delete_array(query); - return false; + if (results.RowCount() != 1) + return false; + + auto row = results.begin(); + + if(graveyard_zoneid != nullptr) + *graveyard_zoneid = atoi(row[0]); + if(graveyard_x != nullptr) + *graveyard_x = atof(row[1]); + if(graveyard_y != nullptr) + *graveyard_y = atof(row[2]); + if(graveyard_z != nullptr) + *graveyard_z = atof(row[3]); + if(graveyard_heading != nullptr) + *graveyard_heading = atof(row[4]); + + return true; } bool Database::LoadZoneNames() { From 2a19a3ced4e08021673eaa69520ca4f565a7e156 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 18:51:24 -0700 Subject: [PATCH 030/288] LoadZoneNames converted to QueryDatabase --- common/database.cpp | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 3a9a8758a..8ac8d58a0 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1184,25 +1184,24 @@ bool Database::GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zon } bool Database::LoadZoneNames() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT zoneidnumber, short_name FROM zone"), errbuf, &result)) { - safe_delete_array(query); - while ((row = mysql_fetch_row(result))) { - uint32 zoneid = atoi(row[0]); - std::string zonename = row[1]; - zonename_array.insert(std::pair(zoneid,zonename)); - } - } - else { + auto results = QueryDatabase(query,MakeAnyLenString(&query, "SELECT zoneidnumber, short_name FROM zone")); + + if (!results.Success()) + { std::cerr << "Error in LoadZoneNames query '" << query << "' " << errbuf << std::endl; safe_delete_array(query); return false; } - mysql_free_result(result); + safe_delete_array(query); + + for (auto row= results.begin();row != results.end();++row) + { + uint32 zoneid = atoi(row[0]); + std::string zonename = row[1]; + zonename_array.insert(std::pair(zoneid,zonename)); + } return true; } From 5c8cd194778d349531f8b75389fdda98bfd60373 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 18:55:16 -0700 Subject: [PATCH 031/288] GetPEQZone converted to QueryDatabase --- common/database.cpp | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 8ac8d58a0..9d61d65f0 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1190,7 +1190,7 @@ bool Database::LoadZoneNames() { if (!results.Success()) { - std::cerr << "Error in LoadZoneNames query '" << query << "' " << errbuf << std::endl; + std::cerr << "Error in LoadZoneNames query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); return false; } @@ -1233,29 +1233,24 @@ const char* Database::GetZoneName(uint32 zoneID, bool ErrorUnknown) { } uint8 Database::GetPEQZone(uint32 zoneID, uint32 version){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - int peqzone = 0; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT peqzone from zone where zoneidnumber='%i' AND (version=%i OR version=0) ORDER BY version DESC", zoneID, version), errbuf, &result)) + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT peqzone from zone where zoneidnumber='%i' AND (version=%i OR version=0) ORDER BY version DESC", zoneID, version)); + + if (!results.Success()) { - if (mysql_num_rows(result) > 0) - { - row = mysql_fetch_row(result); - peqzone = atoi(row[0]); - } + std::cerr << "Error in GetPEQZone query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); - mysql_free_result(result); - return peqzone; - } - else - { - std::cerr << "Error in GetPEQZone query '" << query << "' " << errbuf << std::endl; + return 0; } safe_delete_array(query); - return peqzone; + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + + return atoi(row[0]); } bool Database::CheckNameFilter(const char* name, bool surname) From da2673d35e1392c038cdbfebc62019cc4a15746b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 19:00:15 -0700 Subject: [PATCH 032/288] CheckNameFilter converted to QueryDatabase --- common/database.cpp | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 9d61d65f0..146faf7e0 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1256,10 +1256,7 @@ uint8 Database::GetPEQZone(uint32 zoneID, uint32 version){ bool Database::CheckNameFilter(const char* name, bool surname) { std::string str_name = name; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; if(surname) { @@ -1310,29 +1307,26 @@ bool Database::CheckNameFilter(const char* name, bool surname) } } - if (RunQuery(query, MakeAnyLenString(&query, "SELECT name FROM name_filter"), errbuf, &result)) { + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT name FROM name_filter")); + + if (!results.Success()) + { + std::cerr << "Error in CheckNameFilter query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); - while((row = mysql_fetch_row(result))) - { - std::string current_row = row[0]; - for(size_t x = 0; x < current_row.size(); ++x) - { - current_row[x] = tolower(current_row[x]); - } - - if(str_name.find(current_row) != std::string::npos) - { - return false; - } - } - - mysql_free_result(result); + // false through to true? shouldn't it be falls through to false? return true; } - else + safe_delete_array(query); + + for (auto row = results.begin();row != results.end();++row) { - std::cerr << "Error in CheckNameFilter query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + std::string current_row = row[0]; + + for(size_t x = 0; x < current_row.size(); ++x) + current_row[x] = tolower(current_row[x]); + + if(str_name.find(current_row) != std::string::npos) + return false; } return true; From 20e40a9a9c670c48ad44004956c673c041ca69f0 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 19:02:39 -0700 Subject: [PATCH 033/288] AddToNameFilter converted to QueryDatabase --- common/database.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 146faf7e0..182047832 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1333,21 +1333,20 @@ bool Database::CheckNameFilter(const char* name, bool surname) } bool Database::AddToNameFilter(const char* name) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; + char *query = nullptr; - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO name_filter (name) values ('%s')", name), errbuf, 0, &affected_rows)) { - std::cerr << "Error in AddToNameFilter query '" << query << "' " << errbuf << std::endl; + auto results = QueryDatabase(query, MakeAnyLenString(&query, "INSERT INTO name_filter (name) values ('%s')", name)); + + if (!results.Success()) + { + std::cerr << "Error in AddToNameFilter query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); return false; } - safe_delete_array(query); - if (affected_rows == 0) { + if (results.RowsAffected() == 0) return false; - } return true; } From e20e5e59b8b22f5b857ca87c7a3f65e0ba430bd7 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 19:06:00 -0700 Subject: [PATCH 034/288] GetAccountIDFromLSID converted to QueryDatabase --- common/database.cpp | 45 +++++++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 182047832..5634db4b7 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1352,38 +1352,31 @@ bool Database::AddToNameFilter(const char* name) { } uint32 Database::GetAccountIDFromLSID(uint32 iLSID, char* oAccountName, int16* oStatus) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, name, status FROM account WHERE lsaccount_id=%i", iLSID), errbuf, &result)) + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT id, name, status FROM account WHERE lsaccount_id=%i", iLSID)); + + if (!results.Success()) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - uint32 account_id = atoi(row[0]); - if (oAccountName) - strcpy(oAccountName, row[1]); - if (oStatus) - *oStatus = atoi(row[2]); - mysql_free_result(result); - return account_id; - } - else - { - mysql_free_result(result); - return 0; - } - mysql_free_result(result); - } - else { - std::cerr << "Error in GetAccountIDFromLSID query '" << query << "' " << errbuf << std::endl; + std::cerr << "Error in GetAccountIDFromLSID query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); return 0; } + safe_delete_array(query); - return 0; + if (results.RowCount() != 1) + return 0; + + auto row = results.begin(); + + uint32 account_id = atoi(row[0]); + + if (oAccountName) + strcpy(oAccountName, row[1]); + if (oStatus) + *oStatus = atoi(row[2]); + + return account_id; } void Database::GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus) { From 397f7050efb020f11c64b232cca5f74225fcd451 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 19:08:46 -0700 Subject: [PATCH 035/288] GetAccountFromID converted to QueryDatabase --- common/database.cpp | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 5634db4b7..c402ba889 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1380,25 +1380,27 @@ uint32 Database::GetAccountIDFromLSID(uint32 iLSID, char* oAccountName, int16* o } void Database::GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT name, status FROM account WHERE id=%i", id), errbuf, &result)) + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT name, status FROM account WHERE id=%i", id)); + + if (!results.Success()) { - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - if (oAccountName) - strcpy(oAccountName, row[0]); - if (oStatus) - *oStatus = atoi(row[1]); - } - mysql_free_result(result); + std::cerr << "Error in GetAccountFromID query '" << query << "' " << results.ErrorMessage() << std::endl; + safe_delete_array(query); + return; } - else - std::cerr << "Error in GetAccountFromID query '" << query << "' " << errbuf << std::endl; safe_delete_array(query); + + if (results.RowCount() != 1) + return; + + auto row = results.begin(); + + if (oAccountName) + strcpy(oAccountName, row[0]); + if (oStatus) + *oStatus = atoi(row[1]); } void Database::ClearMerchantTemp(){ From e607f5c0797c0f31d941bceba07b2b7c14038f83 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 19:12:17 -0700 Subject: [PATCH 036/288] ClearMerchantTemp converted to QueryDatabase --- common/database.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index c402ba889..43cb2bd58 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1404,12 +1404,13 @@ void Database::GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus) { } void Database::ClearMerchantTemp(){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + char *query = nullptr; + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from merchantlist_temp")); + + if (!results.Success()) + std::cerr << "Error in ClearMerchantTemp query '" << query << "' " << results.ErrorMessage() << std::endl; - if (!RunQuery(query, MakeAnyLenString(&query, "delete from merchantlist_temp"), errbuf)) { - std::cerr << "Error in ClearMerchantTemp query '" << query << "' " << errbuf << std::endl; - } safe_delete_array(query); } From cf8cfd8b17a67020f1953d0233876a54700d5570 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 19:15:43 -0700 Subject: [PATCH 037/288] UpdateName converted to QueryDatabase --- common/database.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 43cb2bd58..77af6c5b6 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1415,21 +1415,18 @@ void Database::ClearMerchantTemp(){ } bool Database::UpdateName(const char* oldname, const char* newname) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; + char *query = nullptr; std::cout << "Renaming " << oldname << " to " << newname << "..." << std::endl; - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET name='%s' WHERE name='%s';", newname, oldname), errbuf, 0, &affected_rows)) { - safe_delete_array(query); - return false; - } + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "UPDATE character_ SET name='%s' WHERE name='%s';", newname, oldname)); safe_delete_array(query); - if (affected_rows == 0) - { + if (!results.Success()) + return false; + + if (results.RowsAffected() == 0) return false; - } return true; } From a0d5e5ad72649c7bd5ffebaf2897c5657ca2d505 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 19:19:13 -0700 Subject: [PATCH 038/288] CheckUsedName converted to QueryDatabase --- common/database.cpp | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 77af6c5b6..0e68ddc91 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1434,25 +1434,22 @@ bool Database::UpdateName(const char* oldname, const char* newname) { // If the name is used or an error occurs, it returns false, otherwise it returns true bool Database::CheckUsedName(const char* name) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - //if (strlen(name) > 15) - // return false; - if (!RunQuery(query, MakeAnyLenString(&query, "SELECT id FROM character_ where name='%s'", name), errbuf, &result)) { - std::cerr << "Error in CheckUsedName query '" << query << "' " << errbuf << std::endl; + char *query = nullptr; + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT id FROM character_ where name='%s'", name)); + + if (!results.Success()) + { + std::cerr << "Error in CheckUsedName query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); return false; } - else { // It was a valid Query, so lets do our counts! - safe_delete_array(query); - uint32 tmp = mysql_num_rows(result); - mysql_free_result(result); - if (tmp > 0) // There is a Name! No change (Return False) - return false; - else // Everything is okay, so we go and do this. - return true; - } + safe_delete_array(query); + + if (results.RowCount() > 0) + return false; + + return true; } uint8 Database::GetServerType() From 31a774a92a97ec6f29c6ee1375161e2722f0a400 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Tue, 17 Jun 2014 09:45:12 -0400 Subject: [PATCH 039/288] Implemented SE_AStacker, BStacker, CStacker, DStacker Effects are buff stacking blockers. --- changelog.txt | 5 +++++ common/spdat.cpp | 13 +++++++++++++ common/spdat.h | 9 +++++---- zone/bonuses.cpp | 16 ++++++++++++++++ zone/common.h | 4 ++++ zone/mob.h | 2 +- zone/spell_effects.cpp | 4 ++++ zone/spells.cpp | 24 +++++++++++++++++++++--- 8 files changed, 69 insertions(+), 8 deletions(-) diff --git a/changelog.txt b/changelog.txt index eabbad6fd..87c9144d4 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,10 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 06/17/2014 == +Kayen: Implemented SE_AStacker, SE_BStacker, SE_CStacker, SE_DStacker. +These effects when present in buffs prevent each other from stacking, +Any effect with B prevents A, C prevents B, D prevents C. + == 06/13/2014 == Kayen: For table 'npc_spell_effects_entries' setting se_max for damage shield effects (59) will now determine the DS Type (ie burning) Setting se_max to 1 for SkillDamageTaken effects (127) will allow for stackable mitigation/weakness same as quest function ModSkillDmgTaken. diff --git a/common/spdat.cpp b/common/spdat.cpp index 013a917f1..3c4989a67 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -1009,6 +1009,19 @@ uint32 GetMorphTrigger(uint32 spell_id) return 0; } +bool IsCastonFadeDurationSpell(uint16 spell_id) +{ + for (int i = 0; i < EFFECT_COUNT; ++i) { + if (spells[spell_id].effectid[i] == SE_ImprovedSpellEffect + || spells[spell_id].effectid[i] == SE_BossSpellTrigger + || spells[spell_id].effectid[i] == SE_CastOnWearoff){ + + return true; + } + } + return false; +} + uint32 GetPartialMeleeRuneReduction(uint32 spell_id) { for (int i = 0; i < EFFECT_COUNT; ++i) diff --git a/common/spdat.h b/common/spdat.h index ada9e3249..1ef44e15b 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -593,10 +593,10 @@ typedef enum { #define SE_TriggerOnReqCaster 443 // implemented - triggers a spell which a certain criteria are met (below X amount of hp,mana,end, number of pets on hatelist) #define SE_ImprovedTaunt 444 // implemented - Locks Aggro On Caster and Decrease other Players Aggro by X% on NPC targets below level Y //#define SE_AddMercSlot 445 // *not implemented[AA] - [Hero's Barracks] Allows you to conscript additional mercs. -//#define SE_AStacker 446 // *not implementet - bufff stacking blocker ? (26219 | Qirik's Watch) -//#define SE_BStacker 447 // *not implemented -//#define SE_CStacker 448 // *not implemented -//#define SE_DStacker 449 // *not implemented +#define SE_AStacker 446 // implementet - bufff stacking blocker (26219 | Qirik's Watch) +#define SE_BStacker 447 // implemented +#define SE_CStacker 448 // implemented +#define SE_DStacker 449 // implemented #define SE_MitigateDotDamage 450 // implemented DOT spell mitigation rune with max value #define SE_MeleeThresholdGuard 451 // implemented Partial Melee Rune that only is lowered if melee hits are over X amount of damage #define SE_SpellThresholdGuard 452 // implemented Partial Spell Rune that only is lowered if spell hits are over X amount of damage @@ -833,6 +833,7 @@ bool IsBuffSpell(uint16 spell_id); bool IsPersistDeathSpell(uint16 spell_id); bool IsSuspendableSpell(uint16 spell_id); uint32 GetMorphTrigger(uint32 spell_id); +bool IsCastonFadeDurationSpell(uint16 spell_id); uint32 GetPartialMeleeRuneReduction(uint32 spell_id); uint32 GetPartialMagicRuneReduction(uint32 spell_id); uint32 GetPartialMeleeRuneAmount(uint32 spell_id); diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index d699cdde2..bdbbe6b4e 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -2661,6 +2661,22 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne } break; + case SE_AStacker: + newbon->AStacker = true; + break; + + case SE_BStacker: + newbon->BStacker = true; + break; + + case SE_CStacker: + newbon->CStacker = true; + break; + + case SE_DStacker: + newbon->DStacker = true; + break; + //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { diff --git a/zone/common.h b/zone/common.h index d5f516f63..dfb500d47 100644 --- a/zone/common.h +++ b/zone/common.h @@ -350,6 +350,10 @@ struct StatBonuses { bool NegateIfCombat; // Bool Drop buff if cast or melee int8 Screech; // -1 = Will be blocked if another Screech is +(1) int16 AlterNPCLevel; // amount of lvls +/- + bool AStacker; // For buff stack blocking + bool BStacker; // For buff stack blocking + bool CStacker; // For buff stack blocking + bool DStacker; // For buff stack blocking // AAs int8 Packrat; //weight reduction for items, 1 point = 10% diff --git a/zone/mob.h b/zone/mob.h index c3de2b576..4ab9d8a84 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -800,7 +800,7 @@ public: uint16 GetInstrumentMod(uint16 spell_id) const; int CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level = 1, Mob *caster = nullptr, int ticsremaining = 0); int CalcSpellEffectValue_formula(int formula, int base, int max, int caster_level, uint16 spell_id, int ticsremaining = 0); - virtual int CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1 = nullptr, Mob* caster2 = nullptr); + virtual int CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1 = nullptr, Mob* caster2 = nullptr, int buffslot = -1); uint32 GetCastedSpellInvSlot() const { return casting_spell_inventory_slot; } // HP Event diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 4e10160ed..2c83ef1cd 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2886,6 +2886,10 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_LimitCastTimeMax: case SE_TriggerOnReqCaster: case SE_FrenziedDevastation: + case SE_AStacker: + case SE_BStacker: + case SE_CStacker: + case SE_DStacker: { break; } diff --git a/zone/spells.cpp b/zone/spells.cpp index 54e98613e..21a2fe749 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2542,7 +2542,7 @@ int CalcBuffDuration_formula(int level, int formula, int duration) // -1 if they can't stack and spellid2 should be stopped //currently, a spell will not land if it would overwrite a better spell on any effect //if all effects are better or the same, we overwrite, else we do nothing -int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1, Mob* caster2) +int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1, Mob* caster2, int buffslot) { const SPDat_Spell_Struct &sp1 = spells[spellid1]; const SPDat_Spell_Struct &sp2 = spells[spellid2]; @@ -2621,6 +2621,24 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, } } + /*Buff stacking prevention spell effects (446 - 449) works as follows... If B prevent A, if C prevent B, if D prevent C. + Special check is added to make sure the buffs stack properly when applied from fade on duration effect, since the buff + is not fully removed at the time of the trgger*/ + if (spellbonuses.BStacker) { + if ((effect2 == SE_AStacker) && (!IsCastonFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_BStacker))) + return -1; + } + + if (spellbonuses.CStacker) { + if ((effect2 == SE_BStacker) && (!IsCastonFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_CStacker))) + return -1; + } + + if (spellbonuses.DStacker) { + if ((effect2 == SE_CStacker) && (!IsCastonFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_DStacker))) + return -1; + } + if(effect2 == SE_StackingCommand_Overwrite) { overwrite_effect = sp2.base[i]; @@ -2901,7 +2919,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid if (curbuf.spellid != SPELL_UNKNOWN) { // there's a buff in this slot ret = CheckStackConflict(curbuf.spellid, curbuf.casterlevel, spell_id, - caster_level, entity_list.GetMobID(curbuf.casterid), caster); + caster_level, entity_list.GetMobID(curbuf.casterid), caster, buffslot); if (ret == -1) { // stop the spell mlog(SPELLS__BUFFS, "Adding buff %d failed: stacking prevented by spell %d in slot %d with caster level %d", spell_id, curbuf.spellid, buffslot, curbuf.casterlevel); @@ -3047,7 +3065,7 @@ int Mob::CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite) return(-1); //do not recast a buff we already have on, we recast fast enough that we dont need to refresh our buffs // there's a buff in this slot - ret = CheckStackConflict(curbuf.spellid, curbuf.casterlevel, spellid, caster_level); + ret = CheckStackConflict(curbuf.spellid, curbuf.casterlevel, spellid, caster_level, nullptr, nullptr, i); if(ret == 1) { // should overwrite current slot if(iFailIfOverwrite) { From 3253f7494eb176f0f4ebd58b8a0013c66dba9258 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Tue, 17 Jun 2014 15:23:07 -0400 Subject: [PATCH 040/288] Implemented SE_DamageModifier2 --- changelog.txt | 1 + common/spdat.h | 2 +- zone/bonuses.cpp | 29 +++++++++++++++++++++++++++++ zone/common.h | 1 + zone/mob.cpp | 3 +++ 5 files changed, 35 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 87c9144d4..7002939e6 100644 --- a/changelog.txt +++ b/changelog.txt @@ -4,6 +4,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) Kayen: Implemented SE_AStacker, SE_BStacker, SE_CStacker, SE_DStacker. These effects when present in buffs prevent each other from stacking, Any effect with B prevents A, C prevents B, D prevents C. +Kayen: Implemented SE_DamageModifier2 (Stacks with SE_DamageModifier, mods damage by skill type) == 06/13/2014 == Kayen: For table 'npc_spell_effects_entries' setting se_max for damage shield effects (59) will now determine the DS Type (ie burning) diff --git a/common/spdat.h b/common/spdat.h index 1ef44e15b..7e0367fd7 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -606,7 +606,7 @@ typedef enum { //#define SE_AddHateOverTimePct 456 // not used //#define SE_ResourceTap 457 // not used //#define SE_FactionModPct 458 // not used -//#define SE_DamageModifier2 459 // *not implemented - Modifies melee damage by skill type +#define SE_DamageModifier2 459 // implemented - Modifies melee damage by skill type // LAST diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index bdbbe6b4e..03e1d76f6 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1099,6 +1099,15 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) break; } + case SE_DamageModifier2: + { + if(base2 == -1) + newbon->DamageModifier2[HIGHEST_SKILL+1] += base1; + else + newbon->DamageModifier2[base2] += base1; + break; + } + case SE_SlayUndead: { if(newbon->SlayUndead[1] < base1) @@ -1909,6 +1918,15 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne break; } + case SE_DamageModifier2: + { + if(base2 == -1) + newbon->DamageModifier2[HIGHEST_SKILL+1] += effect_value; + else + newbon->DamageModifier2[base2] += effect_value; + break; + } + case SE_MinDamageModifier: { if(base2 == -1) @@ -3454,6 +3472,17 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) break; } + case SE_DamageModifier2: + { + for(int e = 0; e < HIGHEST_SKILL+1; e++) + { + spellbonuses.DamageModifier2[e] = effect_value; + aabonuses.DamageModifier2[e] = effect_value; + itembonuses.DamageModifier2[e] = effect_value; + } + break; + } + case SE_MinDamageModifier: { for(int e = 0; e < HIGHEST_SKILL+1; e++) diff --git a/zone/common.h b/zone/common.h index dfb500d47..67386d910 100644 --- a/zone/common.h +++ b/zone/common.h @@ -279,6 +279,7 @@ struct StatBonuses { int16 HitChance; //HitChance/15 == % increase i = Accuracy (Item: Accuracy) int16 HitChanceEffect[HIGHEST_SKILL+2]; //Spell effect Chance to Hit, straight percent increase int16 DamageModifier[HIGHEST_SKILL+2]; //i + int16 DamageModifier2[HIGHEST_SKILL+2]; //i int16 MinDamageModifier[HIGHEST_SKILL+2]; //i int16 ProcChance; // ProcChance/10 == % increase i = CombatEffects int16 ProcChanceSPA; // ProcChance from spell effects diff --git a/zone/mob.cpp b/zone/mob.cpp index d5ff23a7d..5faeffa65 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -4277,6 +4277,9 @@ int16 Mob::GetMeleeDamageMod_SE(uint16 skill) dmg_mod += itembonuses.DamageModifier[HIGHEST_SKILL+1] + spellbonuses.DamageModifier[HIGHEST_SKILL+1] + aabonuses.DamageModifier[HIGHEST_SKILL+1] + itembonuses.DamageModifier[skill] + spellbonuses.DamageModifier[skill] + aabonuses.DamageModifier[skill]; + dmg_mod += itembonuses.DamageModifier2[HIGHEST_SKILL+1] + spellbonuses.DamageModifier2[HIGHEST_SKILL+1] + aabonuses.DamageModifier2[HIGHEST_SKILL+1] + + itembonuses.DamageModifier2[skill] + spellbonuses.DamageModifier2[skill] + aabonuses.DamageModifier2[skill]; + if (HasShieldEquiped() && !IsOffHandAtk()) dmg_mod += itembonuses.ShieldEquipDmgMod[0] + spellbonuses.ShieldEquipDmgMod[0] + aabonuses.ShieldEquipDmgMod[0]; From 606bd86e3a90271fd82021dcee4ecaa9cfefa3bc Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Tue, 17 Jun 2014 15:49:56 -0400 Subject: [PATCH 041/288] Implemented SE_AddHatePct (Modifies +/- your total hate on NPC by percent) --- changelog.txt | 1 + common/spdat.h | 2 +- zone/spell_effects.cpp | 8 ++++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 7002939e6..698d84044 100644 --- a/changelog.txt +++ b/changelog.txt @@ -5,6 +5,7 @@ Kayen: Implemented SE_AStacker, SE_BStacker, SE_CStacker, SE_DStacker. These effects when present in buffs prevent each other from stacking, Any effect with B prevents A, C prevents B, D prevents C. Kayen: Implemented SE_DamageModifier2 (Stacks with SE_DamageModifier, mods damage by skill type) +Kayen: Implemented SE_AddHatePct (Modifies +/- your total hate on NPC by percent) == 06/13/2014 == Kayen: For table 'npc_spell_effects_entries' setting se_max for damage shield effects (59) will now determine the DS Type (ie burning) diff --git a/common/spdat.h b/common/spdat.h index 7e0367fd7..f03e944c9 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -602,7 +602,7 @@ typedef enum { #define SE_SpellThresholdGuard 452 // implemented Partial Spell Rune that only is lowered if spell hits are over X amount of damage #define SE_TriggerMeleeThreshold 453 // implemented Trigger effect on X amount of melee damage taken #define SE_TriggerSpellThreshold 454 // implemented Trigger effect on X amount of spell damage taken -//#define SE_AddHatePct 455 // not used +#define SE_AddHatePct 455 // implement - Modify total hate by % //#define SE_AddHateOverTimePct 456 // not used //#define SE_ResourceTap 457 // not used //#define SE_FactionModPct 458 // not used diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 2c83ef1cd..f78d0e5c5 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2668,6 +2668,14 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) SlowMitigation(caster); break; + case SE_AddHatePct: + { + if (IsNPC()) + CastToNPC()->SetHate(caster, (CastToNPC()->GetHateAmount(caster) * (100 + spell.base[i]) / 100)); + + break; + } + // Handled Elsewhere case SE_ImmuneFleeing: case SE_NegateSpellEffect: From 5a4f80621b0323a1b5bdd7202ad5a0bc567c922a Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Tue, 17 Jun 2014 16:08:19 -0400 Subject: [PATCH 042/288] Kayen: Implemented SE_AddHateOverTimePct (Modifies +/- your total hate on NPC by percent over time) --- changelog.txt | 1 + common/spdat.h | 4 ++-- zone/spell_effects.cpp | 8 ++++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index 698d84044..6c87c8534 100644 --- a/changelog.txt +++ b/changelog.txt @@ -6,6 +6,7 @@ These effects when present in buffs prevent each other from stacking, Any effect with B prevents A, C prevents B, D prevents C. Kayen: Implemented SE_DamageModifier2 (Stacks with SE_DamageModifier, mods damage by skill type) Kayen: Implemented SE_AddHatePct (Modifies +/- your total hate on NPC by percent) +Kayen: Implemented SE_AddHateOverTimePct (Modifies +/- your total hate on NPC by percent over time) == 06/13/2014 == Kayen: For table 'npc_spell_effects_entries' setting se_max for damage shield effects (59) will now determine the DS Type (ie burning) diff --git a/common/spdat.h b/common/spdat.h index f03e944c9..4edd6543b 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -602,8 +602,8 @@ typedef enum { #define SE_SpellThresholdGuard 452 // implemented Partial Spell Rune that only is lowered if spell hits are over X amount of damage #define SE_TriggerMeleeThreshold 453 // implemented Trigger effect on X amount of melee damage taken #define SE_TriggerSpellThreshold 454 // implemented Trigger effect on X amount of spell damage taken -#define SE_AddHatePct 455 // implement - Modify total hate by % -//#define SE_AddHateOverTimePct 456 // not used +#define SE_AddHatePct 455 // implemented Modify total hate by % +#define SE_AddHateOverTimePct 456 // implemented Modify total hate by % over time. //#define SE_ResourceTap 457 // not used //#define SE_FactionModPct 458 // not used #define SE_DamageModifier2 459 // implemented - Modifies melee damage by skill type diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index f78d0e5c5..9a536b832 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3530,6 +3530,14 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste } } + case SE_AddHateOverTimePct: + { + if (IsNPC()) + CastToNPC()->SetHate(caster, (CastToNPC()->GetHateAmount(caster) * (100 + spell.base[i]) / 100)); + + break; + } + default: { // do we need to do anyting here? From 611f0e2aba16c9a1cc78896a1f86d6b0b5bc3ebe Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Wed, 18 Jun 2014 06:25:14 -0400 Subject: [PATCH 043/288] Implemented SE_DoubleRiposte --- changelog.txt | 1 + common/spdat.h | 2 +- zone/attack.cpp | 4 ++++ zone/bonuses.cpp | 16 ++++++++++++++++ zone/common.h | 1 + 5 files changed, 23 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 6c87c8534..3f4572dce 100644 --- a/changelog.txt +++ b/changelog.txt @@ -7,6 +7,7 @@ Any effect with B prevents A, C prevents B, D prevents C. Kayen: Implemented SE_DamageModifier2 (Stacks with SE_DamageModifier, mods damage by skill type) Kayen: Implemented SE_AddHatePct (Modifies +/- your total hate on NPC by percent) Kayen: Implemented SE_AddHateOverTimePct (Modifies +/- your total hate on NPC by percent over time) +Kayen: Implemented SE_DoubleRiposte (Modifies +/- your double riposte chance) == 06/13/2014 == Kayen: For table 'npc_spell_effects_entries' setting se_max for damage shield effects (59) will now determine the DS Type (ie burning) diff --git a/common/spdat.h b/common/spdat.h index 4edd6543b..ba671acea 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -370,7 +370,7 @@ typedef enum { #define SE_SkillDamageAmount 220 // implemented #define SE_Packrat 221 // implemented as bonus #define SE_BlockBehind 222 // implemented - Chance to block from behind (with our without Shield) -//#define SE_DoubleRiposte 223 // not used +#define SE_DoubleRiposte 223 // implemented - Chance to double riposte [not used on live] #define SE_GiveDoubleRiposte 224 // implemented[AA] #define SE_GiveDoubleAttack 225 // implemented[AA] - Allow any class to double attack with set chance. #define SE_TwoHandBash 226 // *not implemented as bonus diff --git a/zone/attack.cpp b/zone/attack.cpp index 34a1de47d..a3e5c37cd 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4449,6 +4449,10 @@ void Mob::DoRiposte(Mob* defender) { defender->spellbonuses.GiveDoubleRiposte[0] + defender->itembonuses.GiveDoubleRiposte[0]; + DoubleRipChance = defender->aabonuses.DoubleRiposte + + defender->spellbonuses.DoubleRiposte + + defender->itembonuses.DoubleRiposte; + //Live AA - Double Riposte if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) { mlog(COMBAT__ATTACKS, "Preforming a double riposed (%d percent chance)", DoubleRipChance); diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 03e1d76f6..c549bdf72 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1116,6 +1116,11 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) break; } + case SE_DoubleRiposte: + { + newbon->DoubleRiposte += base1; + } + case SE_GiveDoubleRiposte: { //0=Regular Riposte 1=Skill Attack Riposte 2=Skill @@ -2571,6 +2576,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne break; } + case SE_DoubleRiposte: + { + newbon->DoubleRiposte += effect_value; + } + case SE_GiveDoubleRiposte: { //Only allow for regular double riposte chance. @@ -3978,6 +3988,12 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) itembonuses.MasteryofPast = effect_value; break; + case SE_DoubleRiposte: + spellbonuses.DoubleRiposte = effect_value; + itembonuses.DoubleRiposte = effect_value; + aabonuses.DoubleRiposte = effect_value; + break; + case SE_GiveDoubleRiposte: spellbonuses.GiveDoubleRiposte[0] = effect_value; itembonuses.GiveDoubleRiposte[0] = effect_value; diff --git a/zone/common.h b/zone/common.h index 67386d910..a88d8adda 100644 --- a/zone/common.h +++ b/zone/common.h @@ -383,6 +383,7 @@ struct StatBonuses { int16 PetCriticalHit; // Allow pets to critical hit with % value. int16 PetAvoidance; // Pet avoidance chance. int16 CombatStability; // Melee damage mitigation. + int16 DoubleRiposte; // Chance to double riposte int16 GiveDoubleRiposte[3]; // 0=Regular Chance, 1=Skill Attack Chance, 2=Skill uint16 RaiseSkillCap[2]; // Raise a specific skill cap (1 = value, 2=skill) int16 Ambidexterity; // Increase chance to duel wield by adding bonus 'skill'. From b732133184224d3e65c79e056acdc5c2c6adbc9c Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 20 Jun 2014 18:10:29 -0400 Subject: [PATCH 044/288] Implemention for SE_Berserk, SE_Vampirism (These are not used on live) Fix for NPC not receiving spell bonus derived HP regen. --- changelog.txt | 6 +++++- common/spdat.h | 6 +++--- zone/attack.cpp | 20 ++++++++++++-------- zone/bonuses.cpp | 28 ++++++++++++++++++++++++++++ zone/common.h | 4 +++- zone/mob.cpp | 21 +++++++++------------ zone/npc.cpp | 12 ++++++------ zone/npc.h | 1 + 8 files changed, 67 insertions(+), 31 deletions(-) diff --git a/changelog.txt b/changelog.txt index 3f4572dce..58955e931 100644 --- a/changelog.txt +++ b/changelog.txt @@ -7,7 +7,11 @@ Any effect with B prevents A, C prevents B, D prevents C. Kayen: Implemented SE_DamageModifier2 (Stacks with SE_DamageModifier, mods damage by skill type) Kayen: Implemented SE_AddHatePct (Modifies +/- your total hate on NPC by percent) Kayen: Implemented SE_AddHateOverTimePct (Modifies +/- your total hate on NPC by percent over time) -Kayen: Implemented SE_DoubleRiposte (Modifies +/- your double riposte chance) +Kayen: Implemented SE_DoubleRiposte (Modifies +/- your double riposte chance) *Not used in any live effects +Kayen: Implemented SE_Berserk (Sets client as 'Berserk' giving chance to crippling blow) *Not used in any live effects +Kayen: Implemented SE_Vampirsm (Stackable lifetap from melee effect) *Not used in any live effects +Kayen: Minor fixes to how lifetap from melee effects are calced. Removed arbitrary hard cap of 100%, Negative value will now dmg client. +Kayen: Fix to issue that prevented NPC's from receiving HP Regeneration derived from spell buffs. == 06/13/2014 == Kayen: For table 'npc_spell_effects_entries' setting se_max for damage shield effects (59) will now determine the DS Type (ie burning) diff --git a/common/spdat.h b/common/spdat.h index ba671acea..c0813ea40 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -190,9 +190,9 @@ typedef enum { #define SE_DivineAura 40 // implemented #define SE_Destroy 41 // implemented - Disintegrate, Banishment of Shadows #define SE_ShadowStep 42 // implemented -//#define SE_Berserk 43 // not used -#define SE_Lycanthropy 44 // implemented -//#define SE_Vampirism 45 // not used +#define SE_Berserk 43 // implemented (*not used in any known live spell) Makes client 'Berserk' giving crip blow chance. +#define SE_Lycanthropy 44 // implemented +#define SE_Vampirism 45 // implemented (*not used in any known live spell) Stackable lifetap from melee. #define SE_ResistFire 46 // implemented #define SE_ResistCold 47 // implemented #define SE_ResistPoison 48 // implemented diff --git a/zone/attack.cpp b/zone/attack.cpp index a3e5c37cd..074288c3d 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4283,6 +4283,7 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack float critChance = 0.0f; + bool IsBerskerSPA = false; //1: Try Slay Undead if(defender && defender->GetBodyType() == BT_Undead || defender->GetBodyType() == BT_SummonedUndead || defender->GetBodyType() == BT_Vampire){ @@ -4310,12 +4311,15 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack //are defined you will have an innate chance to hit at Level 1 regardless of bonuses. //Warning: Do not define these rules if you want live like critical hits. critChance += RuleI(Combat, MeleeBaseCritChance); - + if (IsClient()) { - critChance += RuleI(Combat, ClientBaseCritChance); + critChance += RuleI(Combat, ClientBaseCritChance); - if ((GetClass() == WARRIOR || GetClass() == BERSERKER) && GetLevel() >= 12) { - if (IsBerserk()) + if (spellbonuses.BerserkSPA || itembonuses.BerserkSPA || aabonuses.BerserkSPA) + IsBerskerSPA = true; + + if (((GetClass() == WARRIOR || GetClass() == BERSERKER) && GetLevel() >= 12) || IsBerskerSPA) { + if (IsBerserk() || IsBerskerSPA) critChance += RuleI(Combat, BerserkBaseCritChance); else critChance += RuleI(Combat, WarBerBaseCritChance); @@ -4360,15 +4364,15 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack uint16 critMod = 200; bool crip_success = false; int16 CripplingBlowChance = GetCrippBlowChance(); - + //Crippling Blow Chance: The percent value of the effect is applied //to the your Chance to Critical. (ie You have 10% chance to critical and you //have a 200% Chance to Critical Blow effect, therefore you have a 20% Chance to Critical Blow. - if (CripplingBlowChance || IsBerserk()) { - if (!IsBerserk()) + if (CripplingBlowChance || (IsBerserk() || IsBerskerSPA)) { + if (!IsBerserk() && !IsBerskerSPA) critChance *= float(CripplingBlowChance)/100.0f; - if (IsBerserk() || MakeRandomFloat(0, 1) < critChance) { + if ((IsBerserk() || IsBerskerSPA) || MakeRandomFloat(0, 1) < critChance) { critMod = 400; crip_success = true; } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index c549bdf72..09d7766a7 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1248,6 +1248,10 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) break; } + case SE_Vampirism: + newbon->Vampirism += base1; + break; + case SE_FrenziedDevastation: newbon->FrenziedDevastation += base2; break; @@ -1256,6 +1260,10 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) newbon->SpellProcChance += base1; break; + case SE_Berserk: + newbon->BerserkSPA = true; + break; + } } } @@ -1827,6 +1835,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne break; } + case SE_Vampirism: + newbon->Vampirism += effect_value; + break; + case SE_AllInstrumentMod: { if(effect_value > newbon->singingMod) @@ -2705,6 +2717,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne newbon->DStacker = true; break; + case SE_Berserk: + newbon->BerserkSPA = true; + break; + //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { @@ -4094,6 +4110,18 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) spellbonuses.AbsorbMagicAtt[0] = effect_value; spellbonuses.AbsorbMagicAtt[1] = -1; break; + + case SE_Berserk: + spellbonuses.BerserkSPA = false; + aabonuses.BerserkSPA = false; + itembonuses.BerserkSPA = false; + break; + + case SE_Vampirism: + spellbonuses.Vampirism = effect_value; + aabonuses.Vampirism = effect_value; + itembonuses.Vampirism = effect_value; + break; } } diff --git a/zone/common.h b/zone/common.h index a88d8adda..67b616248 100644 --- a/zone/common.h +++ b/zone/common.h @@ -290,7 +290,8 @@ struct StatBonuses { int16 FlurryChance; int16 Accuracy[HIGHEST_SKILL+2]; //Accuracy/15 == % increase [Spell Effect: Accuracy) int16 HundredHands; //extra haste, stacks with all other haste i - int8 MeleeLifetap; //i + int16 MeleeLifetap; //i + int16 Vampirism; //i int16 HealRate; // Spell effect that influences effectiveness of heals int32 MaxHPChange; // Spell Effect int16 SkillDmgTaken[HIGHEST_SKILL+2]; // All Skills + -1 @@ -355,6 +356,7 @@ struct StatBonuses { bool BStacker; // For buff stack blocking bool CStacker; // For buff stack blocking bool DStacker; // For buff stack blocking + bool BerserkSPA; // berserk effect // AAs int8 Packrat; //weight reduction for items, 1 point = 10% diff --git a/zone/mob.cpp b/zone/mob.cpp index 5faeffa65..06dbe4519 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -4337,22 +4337,19 @@ int16 Mob::GetSkillDmgAmt(uint16 skill) void Mob::MeleeLifeTap(int32 damage) { - if(damage > 0 && (spellbonuses.MeleeLifetap || itembonuses.MeleeLifetap || aabonuses.MeleeLifetap )) - { - int lifetap_amt = spellbonuses.MeleeLifetap + itembonuses.MeleeLifetap + aabonuses.MeleeLifetap; - - if(lifetap_amt > 100) - lifetap_amt = 100; - - else if (lifetap_amt < -99) - lifetap_amt = -99; + int16 lifetap_amt = 0; + lifetap_amt = spellbonuses.MeleeLifetap + itembonuses.MeleeLifetap + aabonuses.MeleeLifetap + + spellbonuses.Vampirism + itembonuses.Vampirism + aabonuses.Vampirism; + if(lifetap_amt && damage > 0){ lifetap_amt = damage * lifetap_amt / 100; - mlog(COMBAT__DAMAGE, "Melee lifetap healing for %d damage.", damage); - //heal self for damage done.. - HealDamage(lifetap_amt); + + if (lifetap_amt > 0) + HealDamage(lifetap_amt); //Heal self for modified damage amount. + else + Damage(this, -lifetap_amt,0, SkillEvocation,false); //Dmg self for modified damage amount. } } diff --git a/zone/npc.cpp b/zone/npc.cpp index 3886d7c66..38989bccb 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -599,19 +599,19 @@ bool NPC::Process() //Lieka Edit:Fixing NPC regen.NPCs should regen to full during a set duration, not based on their HPs.Increase NPC's HPs by % of total HPs / tick. if((GetHP() < GetMaxHP()) && !IsPet()) { if(!IsEngaged()) {//NPC out of combat - if(hp_regen > OOCRegen) - SetHP(GetHP() + hp_regen); + if(GetNPCHPRegen() > OOCRegen) + SetHP(GetHP() + GetNPCHPRegen()); else SetHP(GetHP() + OOCRegen); } else - SetHP(GetHP()+hp_regen); + SetHP(GetHP()+GetNPCHPRegen()); } else if(GetHP() < GetMaxHP() && GetOwnerID() !=0) { if(!IsEngaged()) //pet - SetHP(GetHP()+hp_regen+bonus+(GetLevel()/5)); + SetHP(GetHP()+GetNPCHPRegen()+bonus+(GetLevel()/5)); else - SetHP(GetHP()+hp_regen+bonus); + SetHP(GetHP()+GetNPCHPRegen()+bonus); } else - SetHP(GetHP()+hp_regen); + SetHP(GetHP()+GetNPCHPRegen()); if(GetMana() < GetMaxMana()) { SetMana(GetMana()+mana_regen+bonus); diff --git a/zone/npc.h b/zone/npc.h index ae444c099..07c81e79b 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -256,6 +256,7 @@ public: virtual void DoClassAttacks(Mob *target); void CheckSignal(); inline bool IsTargetableWithHotkey() const { return no_target_hotkey; } + int32 GetNPCHPRegen() const { return hp_regen + itembonuses.HPRegen + spellbonuses.HPRegen; } //waypoint crap int GetMaxWp() const { return max_wp; } From 60dcdbd181be734df85822ebed012b33eb945507 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sat, 21 Jun 2014 10:12:24 -0400 Subject: [PATCH 045/288] minor fix --- zone/spell_effects.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 9a536b832..af20d3734 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2897,7 +2897,10 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_AStacker: case SE_BStacker: case SE_CStacker: - case SE_DStacker: + case SE_DStacker: + case SE_DoubleRiposte: + case SE_Berserk: + case SE_Vampirism: { break; } From ef7e107443d2cba5b7be68cd21d83ec975b2ce11 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 22 Jun 2014 06:16:34 -0400 Subject: [PATCH 046/288] Fixes and Updates to spell and melee mitigation runes. -Fix for calculation error when rune was to be removed. -Updated to support these spell effect limit values which give a max amount per hit/spell that can be mitigated. -Updated to allow support for these spells effects when the max (rune value) is set to zero, which essentially gives you unlimited mitigation but typically there is a limit value set. --- changelog.txt | 1 + common/spdat.h | 2 +- zone/attack.cpp | 46 +++++++++++++++++++++++++++++++++------------- zone/bonuses.cpp | 6 ++++++ zone/common.h | 6 +++--- 5 files changed, 44 insertions(+), 17 deletions(-) diff --git a/changelog.txt b/changelog.txt index 58955e931..97e4beb4a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -12,6 +12,7 @@ Kayen: Implemented SE_Berserk (Sets client as 'Berserk' giving chance to crippli Kayen: Implemented SE_Vampirsm (Stackable lifetap from melee effect) *Not used in any live effects Kayen: Minor fixes to how lifetap from melee effects are calced. Removed arbitrary hard cap of 100%, Negative value will now dmg client. Kayen: Fix to issue that prevented NPC's from receiving HP Regeneration derived from spell buffs. +Kayen: Fixes and Updates for melee and spell mitigation runes. == 06/13/2014 == Kayen: For table 'npc_spell_effects_entries' setting se_max for damage shield effects (59) will now determine the DS Type (ie burning) diff --git a/common/spdat.h b/common/spdat.h index c0813ea40..3cd4a232a 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -307,7 +307,7 @@ typedef enum { #define SE_SpellDamageShield 157 // implemented - Petrad's Protection #define SE_Reflect 158 // implemented #define SE_AllStats 159 // implemented -#define SE_MakeDrunk 160 // implemented - poorly though, should check against tolerance +//#define SE_MakeDrunk 160 // *not implemented - Effect works entirely client side (Should check against tolerance) #define SE_MitigateSpellDamage 161 // implemented - rune with max value #define SE_MitigateMeleeDamage 162 // implemented - rune with max value #define SE_NegateAttacks 163 // implemented diff --git a/zone/attack.cpp b/zone/attack.cpp index 074288c3d..f3cdedc1c 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3188,11 +3188,11 @@ int32 Mob::ReduceDamage(int32 damage) { DisableMeleeRune = true; int damage_to_reduce = damage * spellbonuses.MeleeThresholdGuard[0] / 100; - if(damage_to_reduce > buffs[slot].melee_rune) + if(damage_to_reduce >= buffs[slot].melee_rune) { mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MeleeThresholdGuard %d damage negated, %d" " damage remaining, fading buff.", damage_to_reduce, buffs[slot].melee_rune); - damage -= damage_to_reduce; + damage -= buffs[slot].melee_rune; if(!TryFadeEffect(slot)) BuffFadeBySlot(slot); } @@ -3212,11 +3212,15 @@ int32 Mob::ReduceDamage(int32 damage) if(slot >= 0) { int damage_to_reduce = damage * spellbonuses.MitigateMeleeRune[0] / 100; - if(damage_to_reduce > buffs[slot].melee_rune) + + if (spellbonuses.MitigateMeleeRune[2] && (damage_to_reduce > spellbonuses.MitigateMeleeRune[2])) + damage_to_reduce = spellbonuses.MitigateMeleeRune[2]; + + if(spellbonuses.MitigateMeleeRune[3] && (damage_to_reduce >= buffs[slot].melee_rune)) { mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d" " damage remaining, fading buff.", damage_to_reduce, buffs[slot].melee_rune); - damage -= damage_to_reduce; + damage -= buffs[slot].melee_rune; if(!TryFadeEffect(slot)) BuffFadeBySlot(slot); } @@ -3224,7 +3228,10 @@ int32 Mob::ReduceDamage(int32 damage) { mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d" " damage remaining.", damage_to_reduce, buffs[slot].melee_rune); - buffs[slot].melee_rune = (buffs[slot].melee_rune - damage_to_reduce); + + if (spellbonuses.MitigateMeleeRune[3]) + buffs[slot].melee_rune = (buffs[slot].melee_rune - damage_to_reduce); + damage -= damage_to_reduce; } } @@ -3286,15 +3293,21 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi if(slot >= 0) { int damage_to_reduce = damage * spellbonuses.MitigateDotRune[0] / 100; - if(damage_to_reduce > buffs[slot].dot_rune) + + if (spellbonuses.MitigateDotRune[2] && (damage_to_reduce > spellbonuses.MitigateDotRune[2])) + damage_to_reduce = spellbonuses.MitigateDotRune[2]; + + if(spellbonuses.MitigateDotRune[3] && (damage_to_reduce >= buffs[slot].dot_rune)) { - damage -= damage_to_reduce; + damage -= buffs[slot].dot_rune; if(!TryFadeEffect(slot)) BuffFadeBySlot(slot); } else { - buffs[slot].dot_rune = (buffs[slot].dot_rune - damage_to_reduce); + if (spellbonuses.MitigateDotRune[3]) + buffs[slot].dot_rune = (buffs[slot].dot_rune - damage_to_reduce); + damage -= damage_to_reduce; } } @@ -3316,9 +3329,9 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi { DisableSpellRune = true; int damage_to_reduce = damage * spellbonuses.SpellThresholdGuard[0] / 100; - if(damage_to_reduce > buffs[slot].magic_rune) + if(damage_to_reduce >= buffs[slot].magic_rune) { - damage -= damage_to_reduce; + damage -= buffs[slot].magic_rune; if(!TryFadeEffect(slot)) BuffFadeBySlot(slot); } @@ -3337,11 +3350,15 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi if(slot >= 0) { int damage_to_reduce = damage * spellbonuses.MitigateSpellRune[0] / 100; - if(damage_to_reduce > buffs[slot].magic_rune) + + if (spellbonuses.MitigateSpellRune[2] && (damage_to_reduce > spellbonuses.MitigateSpellRune[2])) + damage_to_reduce = spellbonuses.MitigateSpellRune[2]; + + if(spellbonuses.MitigateSpellRune[3] && (damage_to_reduce >= buffs[slot].magic_rune)) { mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateSpellDamage %d damage negated, %d" " damage remaining, fading buff.", damage_to_reduce, buffs[slot].magic_rune); - damage -= damage_to_reduce; + damage -= buffs[slot].magic_rune; if(!TryFadeEffect(slot)) BuffFadeBySlot(slot); } @@ -3349,7 +3366,10 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi { mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d" " damage remaining.", damage_to_reduce, buffs[slot].magic_rune); - buffs[slot].magic_rune = (buffs[slot].magic_rune - damage_to_reduce); + + if (spellbonuses.MitigateSpellRune[3]) + buffs[slot].magic_rune = (buffs[slot].magic_rune - damage_to_reduce); + damage -= damage_to_reduce; } } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 09d7766a7..ed5be19e7 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -2303,6 +2303,8 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne if (newbon->MitigateMeleeRune[0] < effect_value){ newbon->MitigateMeleeRune[0] = effect_value; newbon->MitigateMeleeRune[1] = buffslot; + newbon->MitigateMeleeRune[2] = base2; + newbon->MitigateMeleeRune[3] = max; } break; } @@ -2333,6 +2335,8 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne if (newbon->MitigateSpellRune[0] < effect_value){ newbon->MitigateSpellRune[0] = effect_value; newbon->MitigateSpellRune[1] = buffslot; + newbon->MitigateSpellRune[2] = base2; + newbon->MitigateSpellRune[3] = max; } break; } @@ -2342,6 +2346,8 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne if (newbon->MitigateDotRune[0] < effect_value){ newbon->MitigateDotRune[0] = effect_value; newbon->MitigateDotRune[1] = buffslot; + newbon->MitigateDotRune[2] = base2; + newbon->MitigateDotRune[3] = max; } break; } diff --git a/zone/common.h b/zone/common.h index 67b616248..0cec22336 100644 --- a/zone/common.h +++ b/zone/common.h @@ -329,11 +329,11 @@ struct StatBonuses { bool NegateEffects; // Check if you contain a buff with negate effect. (only spellbonuses) int16 SkillDamageAmount2[HIGHEST_SKILL+2]; // Adds skill specific damage uint16 NegateAttacks[2]; // 0 = bool HasEffect 1 = Buff Slot - uint16 MitigateMeleeRune[2]; // 0 = Mitigation value 1 = Buff Slot + uint16 MitigateMeleeRune[4]; // 0 = Mitigation value 1 = Buff Slot 2 = Max mitigation per hit 3 = Rune Amt uint16 MeleeThresholdGuard[3]; // 0 = Mitigation value 1 = Buff Slot 2 = Min damage to trigger. uint16 SpellThresholdGuard[3]; // 0 = Mitigation value 1 = Buff Slot 2 = Min damage to trigger. - uint16 MitigateSpellRune[2]; // 0 = Mitigation value 1 = Buff Slot - uint16 MitigateDotRune[2]; // 0 = Mitigation value 1 = Buff Slot + uint16 MitigateSpellRune[4]; // 0 = Mitigation value 1 = Buff Slot 2 = Max mitigation per spell 3 = Rune Amt + uint16 MitigateDotRune[4]; // 0 = Mitigation value 1 = Buff Slot 2 = Max mitigation per tick 3 = Rune Amt uint32 TriggerMeleeThreshold[3]; // 0 = Spell Effect ID 1 = Buff slot 2 = Damage Amount to Trigger uint32 TriggerSpellThreshold[3]; // 0 = Spell Effect ID 1 = Buff slot 2 = Damage Amount to Trigger uint16 ManaAbsorbPercentDamage[2]; // 0 = Mitigation value 1 = Buff Slot From 6821dc27f56641885d413e297d3bf698e5feb84d Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 22 Jun 2014 10:30:18 -0400 Subject: [PATCH 047/288] Update to SE_NegateAttack, 'max' value can now set upper limit of damage absorbed. DOT ticks will no longer be absorbed. --- changelog.txt | 1 + zone/attack.cpp | 14 +++++++++++--- zone/bonuses.cpp | 1 + zone/common.h | 2 +- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/changelog.txt b/changelog.txt index 97e4beb4a..e22f02697 100644 --- a/changelog.txt +++ b/changelog.txt @@ -13,6 +13,7 @@ Kayen: Implemented SE_Vampirsm (Stackable lifetap from melee effect) *Not used i Kayen: Minor fixes to how lifetap from melee effects are calced. Removed arbitrary hard cap of 100%, Negative value will now dmg client. Kayen: Fix to issue that prevented NPC's from receiving HP Regeneration derived from spell buffs. Kayen: Fixes and Updates for melee and spell mitigation runes. +Kayen: Update to SE_NegateAttack, 'max' value can now set upper limit of damage absorbed. DOT ticks will no longer be absorbed. == 06/13/2014 == Kayen: For table 'npc_spell_effects_entries' setting se_max for damage shield effects (59) will now determine the DS Type (ie burning) diff --git a/zone/attack.cpp b/zone/attack.cpp index f3cdedc1c..99682eee5 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3176,7 +3176,11 @@ int32 Mob::ReduceDamage(int32 damage) if(!TryFadeEffect(slot)) BuffFadeBySlot(slot , true); } - return -6; + + if (spellbonuses.NegateAttacks[2] && (damage > spellbonuses.NegateAttacks[2])) + damage -= spellbonuses.NegateAttacks[2]; + else + return -6; } } @@ -3272,7 +3276,7 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi int32 slot = -1; // See if we block the spell outright first - if (spellbonuses.NegateAttacks[0]){ + if (!iBuffTic && spellbonuses.NegateAttacks[0]){ slot = spellbonuses.NegateAttacks[1]; if(slot >= 0) { if(--buffs[slot].numhits == 0) { @@ -3280,7 +3284,11 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi if(!TryFadeEffect(slot)) BuffFadeBySlot(slot , true); } - return 0; + + if (spellbonuses.NegateAttacks[2] && (damage > spellbonuses.NegateAttacks[2])) + damage -= spellbonuses.NegateAttacks[2]; + else + return 0; } } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index ed5be19e7..ffb13edd8 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -2294,6 +2294,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne if (!newbon->NegateAttacks[0]){ newbon->NegateAttacks[0] = 1; newbon->NegateAttacks[1] = buffslot; + newbon->NegateAttacks[2] = max; } break; } diff --git a/zone/common.h b/zone/common.h index 0cec22336..b687d07df 100644 --- a/zone/common.h +++ b/zone/common.h @@ -328,7 +328,7 @@ struct StatBonuses { uint16 FocusEffects[HIGHEST_FOCUS+1]; // Stores the focus effectid for each focustype you have. bool NegateEffects; // Check if you contain a buff with negate effect. (only spellbonuses) int16 SkillDamageAmount2[HIGHEST_SKILL+2]; // Adds skill specific damage - uint16 NegateAttacks[2]; // 0 = bool HasEffect 1 = Buff Slot + uint16 NegateAttacks[3]; // 0 = bool HasEffect 1 = Buff Slot 2 = Max damage absorbed per hit uint16 MitigateMeleeRune[4]; // 0 = Mitigation value 1 = Buff Slot 2 = Max mitigation per hit 3 = Rune Amt uint16 MeleeThresholdGuard[3]; // 0 = Mitigation value 1 = Buff Slot 2 = Min damage to trigger. uint16 SpellThresholdGuard[3]; // 0 = Mitigation value 1 = Buff Slot 2 = Min damage to trigger. From ad31de5f7830f071fb2ae5e4dd6ca63301d5aead Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 22 Jun 2014 15:55:04 -0400 Subject: [PATCH 048/288] SE_NegateAttacks buff stacking optimized. --- zone/bonuses.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index ffb13edd8..481ec668a 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -2291,7 +2291,8 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_NegateAttacks: { - if (!newbon->NegateAttacks[0]){ + if (!newbon->NegateAttacks[0] || + ((newbon->NegateAttacks[0] && newbon->NegateAttacks[2]) && (newbon->NegateAttacks[2] < max))){ newbon->NegateAttacks[0] = 1; newbon->NegateAttacks[1] = buffslot; newbon->NegateAttacks[2] = max; From 53fb53e822d0b153e0038181dcba06e767a7aa6c Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 22 Jun 2014 23:10:29 -0400 Subject: [PATCH 049/288] Kayen: Implemented SE_Metabolism - Modifies food/drink consumption rates. [Data for AA is already in database] --- changelog.txt | 1 + common/spdat.h | 2 +- zone/bonuses.cpp | 15 +++++++++++++++ zone/client.cpp | 20 ++++++-------------- zone/common.h | 3 ++- zone/spell_effects.cpp | 1 + 6 files changed, 26 insertions(+), 16 deletions(-) diff --git a/changelog.txt b/changelog.txt index e22f02697..f0dd21757 100644 --- a/changelog.txt +++ b/changelog.txt @@ -14,6 +14,7 @@ Kayen: Minor fixes to how lifetap from melee effects are calced. Removed arbitra Kayen: Fix to issue that prevented NPC's from receiving HP Regeneration derived from spell buffs. Kayen: Fixes and Updates for melee and spell mitigation runes. Kayen: Update to SE_NegateAttack, 'max' value can now set upper limit of damage absorbed. DOT ticks will no longer be absorbed. +Kayen: Implemented SE_Metabolism - Modifies food/drink consumption rates. [Data for AA is already in database] == 06/13/2014 == Kayen: For table 'npc_spell_effects_entries' setting se_max for damage shield effects (59) will now determine the DS Type (ie burning) diff --git a/common/spdat.h b/common/spdat.h index 3cd4a232a..b302e8314 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -380,7 +380,7 @@ typedef enum { //#define SE_ExtendedShielding 230 // not used as bonus - increase range of /shield ability #define SE_StunBashChance 231 // implemented - increase chance to stun from bash. #define SE_DivineSave 232 // implemented (base1 == % chance on death to insta-res) (base2 == spell cast on save) -//#define SE_Metabolism 233 // *not implemented - (Crown of Feathers) Increase metabolism? +#define SE_Metabolism 233 // implemented - Modifies food/drink consumption rates. //#define SE_ReduceApplyPoisonTime 234 // not implemented as bonus - reduces the time to apply poison #define SE_ChannelChanceSpells 235 // implemented[AA] - chance to channel from SPELLS *No longer used on live. //#define SE_FreePet 236 // not used diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 481ec668a..3ce6becca 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1264,6 +1264,10 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) newbon->BerserkSPA = true; break; + case SE_Metabolism: + newbon->Metabolism += base1; + break; + } } } @@ -2729,6 +2733,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne newbon->BerserkSPA = true; break; + + case SE_Metabolism: + newbon->Metabolism += effect_value; + break; + //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { @@ -4130,6 +4139,12 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) aabonuses.Vampirism = effect_value; itembonuses.Vampirism = effect_value; break; + + case SE_Metabolism: + spellbonuses.Metabolism = effect_value; + aabonuses.Metabolism = effect_value; + itembonuses.Metabolism = effect_value; + break; } } diff --git a/zone/client.cpp b/zone/client.cpp index 7aa7bd748..2ce193346 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8134,20 +8134,12 @@ void Client::Consume(const Item_Struct *item, uint8 type, int16 slot, bool auto_ uint16 cons_mod = 180; - switch(GetAA(aaInnateMetabolism)){ - case 1: - cons_mod = cons_mod * 110 * RuleI(Character, ConsumptionMultiplier) / 10000; - break; - case 2: - cons_mod = cons_mod * 125 * RuleI(Character, ConsumptionMultiplier) / 10000; - break; - case 3: - cons_mod = cons_mod * 150 * RuleI(Character, ConsumptionMultiplier) / 10000; - break; - default: - cons_mod = cons_mod * RuleI(Character, ConsumptionMultiplier) / 100; - break; - } + int16 metabolism_bonus = spellbonuses.Metabolism + itembonuses.Metabolism + aabonuses.Metabolism; + + if (metabolism_bonus) + cons_mod = cons_mod * metabolism_bonus* RuleI(Character, ConsumptionMultiplier) / 10000; + else + cons_mod = cons_mod * RuleI(Character, ConsumptionMultiplier) / 100; if(type == ItemTypeFood) { diff --git a/zone/common.h b/zone/common.h index b687d07df..f94962ee1 100644 --- a/zone/common.h +++ b/zone/common.h @@ -356,7 +356,8 @@ struct StatBonuses { bool BStacker; // For buff stack blocking bool CStacker; // For buff stack blocking bool DStacker; // For buff stack blocking - bool BerserkSPA; // berserk effect + bool BerserkSPA; // berserk effect + int16 Metabolism; // Food/drink consumption rates. // AAs int8 Packrat; //weight reduction for items, 1 point = 10% diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index af20d3734..b46f34a6e 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2901,6 +2901,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_DoubleRiposte: case SE_Berserk: case SE_Vampirism: + case SE_Metabolism: { break; } From 11918fccbf477145a4ff539bc48e0d3de43b6a5d Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Mon, 23 Jun 2014 08:37:23 -0400 Subject: [PATCH 050/288] Update to SE_BalanaceMana, SE_BalanceHP to support limit value which caps max mana/hp that can be taken per player. --- changelog.txt | 1 + zone/client.cpp | 2 +- zone/groups.cpp | 26 ++++++++++++++++++++------ zone/groups.h | 4 ++-- zone/raids.cpp | 23 +++++++++++++++++------ zone/raids.h | 4 ++-- zone/spell_effects.cpp | 8 ++++---- 7 files changed, 47 insertions(+), 21 deletions(-) diff --git a/changelog.txt b/changelog.txt index f0dd21757..c4fa6cecf 100644 --- a/changelog.txt +++ b/changelog.txt @@ -15,6 +15,7 @@ Kayen: Fix to issue that prevented NPC's from receiving HP Regeneration derived Kayen: Fixes and Updates for melee and spell mitigation runes. Kayen: Update to SE_NegateAttack, 'max' value can now set upper limit of damage absorbed. DOT ticks will no longer be absorbed. Kayen: Implemented SE_Metabolism - Modifies food/drink consumption rates. [Data for AA is already in database] +Kayen: Update to SE_BalanaceMana, SE_BalanceHP to support limit value which caps max mana/hp that can be taken per player. == 06/13/2014 == Kayen: For table 'npc_spell_effects_entries' setting se_max for damage shield effects (59) will now determine the DS Type (ie burning) diff --git a/zone/client.cpp b/zone/client.cpp index 2ce193346..4ec3ce2d7 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8137,7 +8137,7 @@ void Client::Consume(const Item_Struct *item, uint8 type, int16 slot, bool auto_ int16 metabolism_bonus = spellbonuses.Metabolism + itembonuses.Metabolism + aabonuses.Metabolism; if (metabolism_bonus) - cons_mod = cons_mod * metabolism_bonus* RuleI(Character, ConsumptionMultiplier) / 10000; + cons_mod = cons_mod * metabolism_bonus * RuleI(Character, ConsumptionMultiplier) / 10000; else cons_mod = cons_mod * RuleI(Character, ConsumptionMultiplier) / 100; diff --git a/zone/groups.cpp b/zone/groups.cpp index aa50ba2c9..245765c32 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -1095,7 +1095,7 @@ void Group::HealGroup(uint32 heal_amt, Mob* caster, int32 range) } -void Group::BalanceHP(int32 penalty, int32 range, Mob* caster) +void Group::BalanceHP(int32 penalty, int32 range, Mob* caster, int32 limit) { if (!caster) return; @@ -1103,7 +1103,7 @@ void Group::BalanceHP(int32 penalty, int32 range, Mob* caster) if (!range) range = 200; - int dmgtaken = 0, numMem = 0; + int dmgtaken = 0, numMem = 0, dmgtaken_tmp = 0; float distance; float range2 = range*range; @@ -1114,7 +1114,12 @@ void Group::BalanceHP(int32 penalty, int32 range, Mob* caster) if(members[gi]){ distance = caster->DistNoRoot(*members[gi]); if(distance <= range2){ - dmgtaken += (members[gi]->GetMaxHP() - members[gi]->GetHP()); + + dmgtaken_tmp = members[gi]->GetMaxHP() - members[gi]->GetHP(); + if (limit && (dmgtaken_tmp > limit)) + dmgtaken_tmp = limit; + + dmgtaken += (dmgtaken_tmp); numMem += 1; } } @@ -1140,7 +1145,7 @@ void Group::BalanceHP(int32 penalty, int32 range, Mob* caster) } } -void Group::BalanceMana(int32 penalty, int32 range, Mob* caster) +void Group::BalanceMana(int32 penalty, int32 range, Mob* caster, int32 limit) { if (!caster) return; @@ -1151,14 +1156,19 @@ void Group::BalanceMana(int32 penalty, int32 range, Mob* caster) float distance; float range2 = range*range; - int manataken = 0, numMem = 0; + int manataken = 0, numMem = 0, manataken_tmp = 0; unsigned int gi = 0; for(; gi < MAX_GROUP_MEMBERS; gi++) { if(members[gi]){ distance = caster->DistNoRoot(*members[gi]); if(distance <= range2){ - manataken += (members[gi]->GetMaxMana() - members[gi]->GetMana()); + + manataken_tmp = members[gi]->GetMaxMana() - members[gi]->GetMana(); + if (limit && (manataken_tmp > limit)) + manataken_tmp = limit; + + manataken += (manataken_tmp); numMem += 1; } } @@ -1166,6 +1176,10 @@ void Group::BalanceMana(int32 penalty, int32 range, Mob* caster) manataken += manataken * penalty / 100; manataken /= numMem; + + if (limit && (manataken > limit)) + manataken = limit; + for(gi = 0; gi < MAX_GROUP_MEMBERS; gi++) { if(members[gi]){ diff --git a/zone/groups.h b/zone/groups.h index c5a3f8ab1..fe21ff3a4 100644 --- a/zone/groups.h +++ b/zone/groups.h @@ -86,8 +86,8 @@ public: uint16 GetAvgLevel(); bool LearnMembers(); void VerifyGroup(); - void BalanceHP(int32 penalty, int32 range = 0, Mob* caster = nullptr); - void BalanceMana(int32 penalty, int32 range = 0, Mob* caster = nullptr); + void BalanceHP(int32 penalty, int32 range = 0, Mob* caster = nullptr, int32 limit = 0); + void BalanceMana(int32 penalty, int32 range = 0, Mob* caster = nullptr, int32 limit = 0); void HealGroup(uint32 heal_amt, Mob* caster, int32 range = 0); inline void SetGroupAAs(GroupLeadershipAA_Struct *From) { memcpy(&LeaderAbilities, From, sizeof(GroupLeadershipAA_Struct)); } inline void GetGroupAAs(GroupLeadershipAA_Struct *Into) { memcpy(Into, &LeaderAbilities, sizeof(GroupLeadershipAA_Struct)); } diff --git a/zone/raids.cpp b/zone/raids.cpp index bf6f76d5c..be0b697db 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -504,7 +504,7 @@ void Raid::HealGroup(uint32 heal_amt, Mob* caster, uint32 gid, int32 range) } -void Raid::BalanceHP(int32 penalty, uint32 gid, int32 range, Mob* caster) +void Raid::BalanceHP(int32 penalty, uint32 gid, int32 range, Mob* caster, int32 limit) { if (!caster) return; @@ -512,7 +512,7 @@ void Raid::BalanceHP(int32 penalty, uint32 gid, int32 range, Mob* caster) if (!range) range = 200; - int dmgtaken = 0, numMem = 0; + int dmgtaken = 0, numMem = 0, dmgtaken_tmp = 0; int gi = 0; float distance; @@ -525,7 +525,12 @@ void Raid::BalanceHP(int32 penalty, uint32 gid, int32 range, Mob* caster) { distance = caster->DistNoRoot(*members[gi].member); if(distance <= range2){ - dmgtaken += (members[gi].member->GetMaxHP() - members[gi].member->GetHP()); + + dmgtaken_tmp = members[gi].member->GetMaxHP() - members[gi].member->GetHP(); + if (limit && (dmgtaken_tmp > limit)) + dmgtaken_tmp = limit; + + dmgtaken += (dmgtaken_tmp); numMem += 1; } } @@ -555,7 +560,7 @@ void Raid::BalanceHP(int32 penalty, uint32 gid, int32 range, Mob* caster) } } -void Raid::BalanceMana(int32 penalty, uint32 gid, int32 range, Mob* caster) +void Raid::BalanceMana(int32 penalty, uint32 gid, int32 range, Mob* caster, int32 limit) { if (!caster) return; @@ -566,7 +571,7 @@ void Raid::BalanceMana(int32 penalty, uint32 gid, int32 range, Mob* caster) float distance; float range2 = range*range; - int manataken = 0, numMem = 0; + int manataken = 0, numMem = 0, manataken_tmp = 0; int gi = 0; for(; gi < MAX_RAID_MEMBERS; gi++) { @@ -575,7 +580,12 @@ void Raid::BalanceMana(int32 penalty, uint32 gid, int32 range, Mob* caster) { distance = caster->DistNoRoot(*members[gi].member); if(distance <= range2){ - manataken += (members[gi].member->GetMaxMana() - members[gi].member->GetMana()); + + manataken_tmp = members[gi].member->GetMaxMana() - members[gi].member->GetMana(); + if (limit && (manataken_tmp > limit)) + manataken_tmp = limit; + + manataken += (manataken_tmp); numMem += 1; } } @@ -584,6 +594,7 @@ void Raid::BalanceMana(int32 penalty, uint32 gid, int32 range, Mob* caster) manataken += manataken * penalty / 100; manataken /= numMem; + for(gi = 0; gi < MAX_RAID_MEMBERS; gi++) { if(members[gi].member){ diff --git a/zone/raids.h b/zone/raids.h index c8c2f61e4..be12788e6 100644 --- a/zone/raids.h +++ b/zone/raids.h @@ -147,8 +147,8 @@ public: void CastGroupSpell(Mob* caster,uint16 spellid, uint32 gid); void SplitExp(uint32 exp, Mob* other); uint32 GetTotalRaidDamage(Mob* other); - void BalanceHP(int32 penalty, uint32 gid, int32 range = 0, Mob* caster = nullptr); - void BalanceMana(int32 penalty, uint32 gid, int32 range = 0, Mob* caster = nullptr); + void BalanceHP(int32 penalty, uint32 gid, int32 range = 0, Mob* caster = nullptr, int32 limit = 0); + void BalanceMana(int32 penalty, uint32 gid, int32 range = 0, Mob* caster = nullptr, int32 limit = 0); void HealGroup(uint32 heal_amt, Mob* caster, uint32 gid, int32 range = 0); void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter = nullptr); void GroupBardPulse(Mob* caster, uint16 spellid, uint32 gid); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index b46f34a6e..b846e0058 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2393,7 +2393,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) gid = r->GetGroup(caster->GetName()); if(gid < 11) { - r->BalanceHP(spell.base[i], gid, spell.range, caster); + r->BalanceHP(spell.base[i], gid, spell.range, caster, spell.base2[i]); break; } } @@ -2403,7 +2403,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) if(!g) break; - g->BalanceHP(spell.base[i], spell.range, caster); + g->BalanceHP(spell.base[i], spell.range, caster, spell.base2[i]); break; } @@ -2421,7 +2421,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) gid = r->GetGroup(caster->GetName()); if(gid < 11) { - r->BalanceMana(spell.base[i], gid, spell.range, caster); + r->BalanceMana(spell.base[i], gid, spell.range, caster, spell.base2[i]); break; } } @@ -2431,7 +2431,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) if(!g) break; - g->BalanceMana(spell.base[i], spell.range, caster); + g->BalanceMana(spell.base[i], spell.range, caster, spell.base2[i]); break; } From 9680f3920346797b0f3cdede233fbe3e7532e803 Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 23 Jun 2014 16:56:37 -0700 Subject: [PATCH 051/288] Some potential fixes for clang, not complete --- luabind/luabind/detail/format_signature.hpp | 15 ++- zone/groups.cpp | 2 +- zone/lua_general.cpp | 52 +++++----- zone/lua_mob.cpp | 8 +- zone/lua_mob.h | 4 +- zone/lua_parser.cpp | 22 ++-- zone/lua_parser.h | 12 ++- zone/lua_parser_events.cpp | 106 ++++++++++---------- 8 files changed, 114 insertions(+), 107 deletions(-) diff --git a/luabind/luabind/detail/format_signature.hpp b/luabind/luabind/detail/format_signature.hpp index 56e796363..ec56b6196 100644 --- a/luabind/luabind/detail/format_signature.hpp +++ b/luabind/luabind/detail/format_signature.hpp @@ -13,12 +13,17 @@ # include # include -namespace luabind { +namespace luabind { namespace adl { -class object; -class argument; -template -struct table; + class object; + class argument; + template + struct table; +} // namespace adl + +using adl::object; +using adl::argument; +using adl::table; } // namespace luabind diff --git a/zone/groups.cpp b/zone/groups.cpp index 245765c32..1af5cc34e 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -447,7 +447,7 @@ bool Group::UpdatePlayer(Mob* update){ //update their player profile PlayerProfile_Struct &pp = update->CastToClient()->GetPP(); for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(membername[0] == '\0') + if(membername[i][0] == '\0') memset(pp.groupMembers[i], 0, 64); else strn0cpy(pp.groupMembers[i], membername[i], 64); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index cfe21dc51..645932d1b 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -27,7 +27,7 @@ struct Appearances { }; struct lua_registered_event { std::string encounter_name; - luabind::object lua_reference; + luabind::adl::object lua_reference; QuestEventID event_id; }; @@ -43,7 +43,7 @@ void unload_encounter(std::string name) { parse->EventEncounter(EVENT_ENCOUNTER_UNLOAD, name, 0); } -void register_event(std::string package_name, std::string name, int evt, luabind::object func) { +void register_event(std::string package_name, std::string name, int evt, luabind::adl::object func) { lua_registered_event e; e.encounter_name = name; e.lua_reference = func; @@ -84,7 +84,7 @@ void unregister_event(std::string package_name, std::string name, int evt) { } } -void register_npc_event(std::string name, int evt, int npc_id, luabind::object func) { +void register_npc_event(std::string name, int evt, int npc_id, luabind::adl::object func) { if(luabind::type(func) == LUA_TFUNCTION) { std::stringstream package_name; package_name << "npc_" << npc_id; @@ -100,7 +100,7 @@ void unregister_npc_event(std::string name, int evt, int npc_id) { unregister_event(package_name.str(), name, evt); } -void register_player_event(std::string name, int evt, luabind::object func) { +void register_player_event(std::string name, int evt, luabind::adl::object func) { if(luabind::type(func) == LUA_TFUNCTION) { register_event("player", name, evt, func); } @@ -110,7 +110,7 @@ void unregister_player_event(std::string name, int evt) { unregister_event("player", name, evt); } -void register_item_event(std::string name, int evt, int item_id, luabind::object func) { +void register_item_event(std::string name, int evt, int item_id, luabind::adl::object func) { std::string package_name = "item_"; package_name += std::to_string(static_cast(item_id)); @@ -126,7 +126,7 @@ void unregister_item_event(std::string name, int evt, int item_id) { unregister_event(package_name, name, evt); } -void register_spell_event(std::string name, int evt, int spell_id, luabind::object func) { +void register_spell_event(std::string name, int evt, int spell_id, luabind::adl::object func) { if(luabind::type(func) == LUA_TFUNCTION) { std::stringstream package_name; package_name << "spell_" << spell_id; @@ -392,7 +392,7 @@ bool lua_bury_player_corpse(uint32 char_id) { return quest_manager.buryplayercorpse(char_id); } -void lua_task_selector(luabind::object table) { +void lua_task_selector(luabind::adl::object table) { if(luabind::type(table) != LUA_TTABLE) { return; } @@ -422,7 +422,7 @@ void lua_task_set_selector(int task_set) { quest_manager.tasksetselector(task_set); } -void lua_enable_task(luabind::object table) { +void lua_enable_task(luabind::adl::object table) { if(luabind::type(table) != LUA_TTABLE) { return; } @@ -449,7 +449,7 @@ void lua_enable_task(luabind::object table) { quest_manager.enabletask(count, tasks); } -void lua_disable_task(luabind::object table) { +void lua_disable_task(luabind::adl::object table) { if(luabind::type(table) != LUA_TTABLE) { return; } @@ -743,8 +743,8 @@ void lua_cross_zone_message_player_by_name(uint32 type, const char *player, cons quest_manager.CrossZoneMessagePlayerByName(type, player, message); } -luabind::object lua_get_qglobals(lua_State *L, Lua_NPC npc, Lua_Client client) { - luabind::object ret = luabind::newtable(L); +luabind::adl::object lua_get_qglobals(lua_State *L, Lua_NPC npc, Lua_Client client) { + luabind::adl::object ret = luabind::newtable(L); NPC *n = npc; Client *c = client; @@ -759,8 +759,8 @@ luabind::object lua_get_qglobals(lua_State *L, Lua_NPC npc, Lua_Client client) { return ret; } -luabind::object lua_get_qglobals(lua_State *L, Lua_Client client) { - luabind::object ret = luabind::newtable(L); +luabind::adl::object lua_get_qglobals(lua_State *L, Lua_Client client) { + luabind::adl::object ret = luabind::newtable(L); NPC *n = nullptr; Client *c = client; @@ -775,8 +775,8 @@ luabind::object lua_get_qglobals(lua_State *L, Lua_Client client) { return ret; } -luabind::object lua_get_qglobals(lua_State *L, Lua_NPC npc) { - luabind::object ret = luabind::newtable(L); +luabind::adl::object lua_get_qglobals(lua_State *L, Lua_NPC npc) { + luabind::adl::object ret = luabind::newtable(L); NPC *n = npc; Client *c = nullptr; @@ -791,8 +791,8 @@ luabind::object lua_get_qglobals(lua_State *L, Lua_NPC npc) { return ret; } -luabind::object lua_get_qglobals(lua_State *L) { - luabind::object ret = luabind::newtable(L); +luabind::adl::object lua_get_qglobals(lua_State *L) { + luabind::adl::object ret = luabind::newtable(L); NPC *n = nullptr; Client *c = nullptr; @@ -846,8 +846,8 @@ int lua_get_zone_instance_version() { return zone->GetInstanceVersion(); } -luabind::object lua_get_characters_in_instance(lua_State *L, uint16 instance_id) { - luabind::object ret = luabind::newtable(L); +luabind::adl::object lua_get_characters_in_instance(lua_State *L, uint16 instance_id) { + luabind::adl::object ret = luabind::newtable(L); std::list charid_list; uint16 i = 1; @@ -868,11 +868,11 @@ int lua_get_zone_weather() { return zone->zone_weather; } -luabind::object lua_get_zone_time(lua_State *L) { +luabind::adl::object lua_get_zone_time(lua_State *L) { TimeOfDay_Struct eqTime; zone->zone_time.getEQTimeOfDay(time(0), &eqTime); - luabind::object ret = luabind::newtable(L); + luabind::adl::object ret = luabind::newtable(L); ret["zone_hour"] = eqTime.hour - 1; ret["zone_minute"] = eqTime.minute; ret["zone_time"] = (eqTime.hour - 1) * 100 + eqTime.minute; @@ -909,7 +909,7 @@ void lua_remove_spawn_point(uint32 spawn2_id) { } } -void lua_add_spawn_point(luabind::object table) { +void lua_add_spawn_point(luabind::adl::object table) { if(!zone) return; @@ -1280,10 +1280,10 @@ luabind::scope lua_register_general() { luabind::def("cross_zone_signal_client_by_char_id", &lua_cross_zone_signal_client_by_char_id), luabind::def("cross_zone_signal_client_by_name", &lua_cross_zone_signal_client_by_name), luabind::def("cross_zone_message_player_by_name", &lua_cross_zone_message_player_by_name), - luabind::def("get_qglobals", (luabind::object(*)(lua_State*,Lua_NPC,Lua_Client))&lua_get_qglobals), - luabind::def("get_qglobals", (luabind::object(*)(lua_State*,Lua_Client))&lua_get_qglobals), - luabind::def("get_qglobals", (luabind::object(*)(lua_State*,Lua_NPC))&lua_get_qglobals), - luabind::def("get_qglobals", (luabind::object(*)(lua_State*))&lua_get_qglobals), + luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_NPC,Lua_Client))&lua_get_qglobals), + luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_Client))&lua_get_qglobals), + luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_NPC))&lua_get_qglobals), + luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*))&lua_get_qglobals), luabind::def("get_entity_list", &lua_get_entity_list), luabind::def("get_zone_id", &lua_get_zone_id), luabind::def("get_zone_long_name", &lua_get_zone_long_name), diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 17588caef..50a8b50a7 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -103,7 +103,7 @@ bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_striket return self->Attack(other, hand, from_riposte, is_strikethrough, is_from_spell); } -bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_strikethrough, bool is_from_spell, luabind::object opts) { +bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_strikethrough, bool is_from_spell, luabind::adl::object opts) { Lua_Safe_Call_Bool(); ExtraAttackOptions options; @@ -1429,7 +1429,7 @@ void Lua_Mob::SetGender(int in) { self->SendIllusionPacket(self->GetRace(), in); } -void Lua_Mob::SendIllusionPacket(luabind::object illusion) { +void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) { Lua_Safe_Call_Void(); if(luabind::type(illusion) != LUA_TTABLE) { @@ -1881,7 +1881,7 @@ luabind::scope lua_register_mob() { .def("Attack", (bool(Lua_Mob::*)(Lua_Mob,int,bool))&Lua_Mob::Attack) .def("Attack", (bool(Lua_Mob::*)(Lua_Mob,int,bool,bool))&Lua_Mob::Attack) .def("Attack", (bool(Lua_Mob::*)(Lua_Mob,int,bool,bool,bool))&Lua_Mob::Attack) - .def("Attack", (bool(Lua_Mob::*)(Lua_Mob,int,bool,bool,bool,luabind::object))&Lua_Mob::Attack) + .def("Attack", (bool(Lua_Mob::*)(Lua_Mob,int,bool,bool,bool,luabind::adl::object))&Lua_Mob::Attack) .def("Damage", (void(Lua_Mob::*)(Lua_Mob,int,int,int))&Lua_Mob::Damage) .def("Damage", (void(Lua_Mob::*)(Lua_Mob,int,int,int,bool))&Lua_Mob::Damage) .def("Damage", (void(Lua_Mob::*)(Lua_Mob,int,int,int,bool,int))&Lua_Mob::Damage) @@ -2125,7 +2125,7 @@ luabind::scope lua_register_mob() { .def("SetTexture", (void(Lua_Mob::*)(int))&Lua_Mob::SetTexture) .def("SetRace", (void(Lua_Mob::*)(int))&Lua_Mob::SetRace) .def("SetGender", (void(Lua_Mob::*)(int))&Lua_Mob::SetGender) - .def("SendIllusionPacket", (void(Lua_Mob::*)(luabind::object))&Lua_Mob::SendIllusionPacket) + .def("SendIllusionPacket", (void(Lua_Mob::*)(luabind::adl::object))&Lua_Mob::SendIllusionPacket) .def("QuestReward", (void(Lua_Mob::*)(Lua_Client))&Lua_Mob::QuestReward) .def("QuestReward", (void(Lua_Mob::*)(Lua_Client,uint32))&Lua_Mob::QuestReward) .def("QuestReward", (void(Lua_Mob::*)(Lua_Client,uint32,uint32))&Lua_Mob::QuestReward) diff --git a/zone/lua_mob.h b/zone/lua_mob.h index b3e44805a..a5c00c5f0 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -47,7 +47,7 @@ public: bool Attack(Lua_Mob other, int hand, bool from_riposte); bool Attack(Lua_Mob other, int hand, bool from_riposte, bool is_strikethrough); bool Attack(Lua_Mob other, int hand, bool from_riposte, bool is_strikethrough, bool is_from_spell); - bool Attack(Lua_Mob other, int hand, bool from_riposte, bool is_strikethrough, bool is_from_spell, luabind::object opts); + bool Attack(Lua_Mob other, int hand, bool from_riposte, bool is_strikethrough, bool is_from_spell, luabind::adl::object opts); void Damage(Lua_Mob from, int damage, int spell_id, int attack_skill); void Damage(Lua_Mob from, int damage, int spell_id, int attack_skill, bool avoidable); void Damage(Lua_Mob from, int damage, int spell_id, int attack_skill, bool avoidable, int buffslot); @@ -294,7 +294,7 @@ public: void SetTexture(int in); void SetRace(int in); void SetGender(int in); - void SendIllusionPacket(luabind::object illusion); + void SendIllusionPacket(luabind::adl::object illusion); void QuestReward(Lua_Client c); void QuestReward(Lua_Client c, uint32 silver); void QuestReward(Lua_Client c, uint32 silver, uint32 gold); diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index c3cb841af..9f082993c 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -121,7 +121,7 @@ extern Zone *zone; struct lua_registered_event { std::string encounter_name; - luabind::object lua_reference; + luabind::adl::object lua_reference; QuestEventID event_id; }; @@ -257,7 +257,7 @@ int LuaParser::EventGlobalNPC(QuestEventID evt, NPC* npc, Mob *init, std::string } int LuaParser::_EventNPC(std::string package_name, QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers, luabind::object *l_func) { + std::vector *extra_pointers, luabind::adl::object *l_func) { const char *sub_name = LuaEvents[evt]; int start = lua_gettop(L); @@ -275,7 +275,7 @@ int LuaParser::_EventNPC(std::string package_name, QuestEventID evt, NPC* npc, M lua_createtable(L, 0, 0); //always push self Lua_NPC l_npc(npc); - luabind::object l_npc_o = luabind::object(L, l_npc); + luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc); l_npc_o.push(L); lua_setfield(L, -2, "self"); @@ -352,7 +352,7 @@ int LuaParser::EventGlobalPlayer(QuestEventID evt, Client *client, std::string d } int LuaParser::_EventPlayer(std::string package_name, QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers, luabind::object *l_func) { + std::vector *extra_pointers, luabind::adl::object *l_func) { const char *sub_name = LuaEvents[evt]; int start = lua_gettop(L); @@ -369,7 +369,7 @@ int LuaParser::_EventPlayer(std::string package_name, QuestEventID evt, Client * lua_createtable(L, 0, 0); //push self Lua_Client l_client(client); - luabind::object l_client_o = luabind::object(L, l_client); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); l_client_o.push(L); lua_setfield(L, -2, "self"); @@ -429,7 +429,7 @@ int LuaParser::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob * } int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *client, ItemInst *item, Mob *mob, - std::string data, uint32 extra_data, std::vector *extra_pointers, luabind::object *l_func) { + std::string data, uint32 extra_data, std::vector *extra_pointers, luabind::adl::object *l_func) { const char *sub_name = LuaEvents[evt]; int start = lua_gettop(L); @@ -446,12 +446,12 @@ int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *cl lua_createtable(L, 0, 0); //always push self Lua_ItemInst l_item(item); - luabind::object l_item_o = luabind::object(L, l_item); + luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "self"); Lua_Client l_client(client); - luabind::object l_client_o = luabind::object(L, l_client); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); l_client_o.push(L); lua_setfield(L, -2, "owner"); @@ -508,7 +508,7 @@ int LuaParser::EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spe } int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data, - std::vector *extra_pointers, luabind::object *l_func) { + std::vector *extra_pointers, luabind::adl::object *l_func) { const char *sub_name = LuaEvents[evt]; int start = lua_gettop(L); @@ -528,11 +528,11 @@ int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, NPC* npc, //always push self even if invalid if(IsValidSpell(spell_id)) { Lua_Spell l_spell(&spells[spell_id]); - luabind::object l_spell_o = luabind::object(L, l_spell); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); l_spell_o.push(L); } else { Lua_Spell l_spell(nullptr); - luabind::object l_spell_o = luabind::object(L, l_spell); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); l_spell_o.push(L); } lua_setfield(L, -2, "self"); diff --git a/zone/lua_parser.h b/zone/lua_parser.h index 7c4843ccd..b30e3d3b7 100644 --- a/zone/lua_parser.h +++ b/zone/lua_parser.h @@ -17,7 +17,9 @@ class NPC; struct lua_registered_event; namespace luabind { - class object; + namespace adl { + class object; + } } class LuaParser : public QuestInterface { @@ -73,13 +75,13 @@ public: private: int _EventNPC(std::string package_name, QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, - std::vector *extra_pointers, luabind::object *l_func = nullptr); + std::vector *extra_pointers, luabind::adl::object *l_func = nullptr); int _EventPlayer(std::string package_name, QuestEventID evt, Client *client, std::string data, uint32 extra_data, - std::vector *extra_pointers, luabind::object *l_func = nullptr); + std::vector *extra_pointers, luabind::adl::object *l_func = nullptr); int _EventItem(std::string package_name, QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, - uint32 extra_data, std::vector *extra_pointers, luabind::object *l_func = nullptr); + uint32 extra_data, std::vector *extra_pointers, luabind::adl::object *l_func = nullptr); int _EventSpell(std::string package_name, QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data, - std::vector *extra_pointers, luabind::object *l_func = nullptr); + std::vector *extra_pointers, luabind::adl::object *l_func = nullptr); int _EventEncounter(std::string package_name, QuestEventID evt, std::string encounter_name, uint32 extra_data, std::vector *extra_pointers); diff --git a/zone/lua_parser_events.cpp b/zone/lua_parser_events.cpp index c46107844..8064106dc 100644 --- a/zone/lua_parser_events.cpp +++ b/zone/lua_parser_events.cpp @@ -31,7 +31,7 @@ void handle_npc_event_say(QuestInterface *parse, lua_State* L, NPC* npc, Mob *in npc->DoQuestPause(init); Lua_Client l_client(reinterpret_cast(init)); - luabind::object l_client_o = luabind::object(L, l_client); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); l_client_o.push(L); lua_setfield(L, -2, "other"); @@ -45,7 +45,7 @@ void handle_npc_event_say(QuestInterface *parse, lua_State* L, NPC* npc, Mob *in void handle_npc_event_trade(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_Client l_client(reinterpret_cast(init)); - luabind::object l_client_o = luabind::object(L, l_client); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); l_client_o.push(L); lua_setfield(L, -2, "other"); @@ -57,7 +57,7 @@ void handle_npc_event_trade(QuestInterface *parse, lua_State* L, NPC* npc, Mob * for(size_t i = 0; i < extra_pointers->size(); ++i) { std::string prefix = "item" + std::to_string(static_cast(i + 1)); Lua_ItemInst l_inst = reinterpret_cast(extra_pointers->at(i)); - luabind::object l_inst_o = luabind::object(L, l_inst); + luabind::adl::object l_inst_o = luabind::adl::object(L, l_inst); l_inst_o.push(L); lua_setfield(L, -2, prefix.c_str()); @@ -98,7 +98,7 @@ void handle_npc_event_hp(QuestInterface *parse, lua_State* L, NPC* npc, Mob *ini void handle_npc_single_mob(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_Mob l_mob(init); - luabind::object l_mob_o = luabind::object(L, l_mob); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); l_mob_o.push(L); lua_setfield(L, -2, "other"); } @@ -106,7 +106,7 @@ void handle_npc_single_mob(QuestInterface *parse, lua_State* L, NPC* npc, Mob *i void handle_npc_single_client(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_Client l_client(reinterpret_cast(init)); - luabind::object l_client_o = luabind::object(L, l_client); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); l_client_o.push(L); lua_setfield(L, -2, "other"); } @@ -114,7 +114,7 @@ void handle_npc_single_client(QuestInterface *parse, lua_State* L, NPC* npc, Mob void handle_npc_single_npc(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_NPC l_npc(reinterpret_cast(init)); - luabind::object l_npc_o = luabind::object(L, l_npc); + luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc); l_npc_o.push(L); lua_setfield(L, -2, "other"); } @@ -122,7 +122,7 @@ void handle_npc_single_npc(QuestInterface *parse, lua_State* L, NPC* npc, Mob *i void handle_npc_task_accepted(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_Client l_client(reinterpret_cast(init)); - luabind::object l_client_o = luabind::object(L, l_client); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); l_client_o.push(L); lua_setfield(L, -2, "other"); @@ -133,7 +133,7 @@ void handle_npc_task_accepted(QuestInterface *parse, lua_State* L, NPC* npc, Mob void handle_npc_popup(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_Mob l_mob(init); - luabind::object l_mob_o = luabind::object(L, l_mob); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); l_mob_o.push(L); lua_setfield(L, -2, "other"); @@ -144,7 +144,7 @@ void handle_npc_popup(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, void handle_npc_waypoint(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_Mob l_mob(init); - luabind::object l_mob_o = luabind::object(L, l_mob); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); l_mob_o.push(L); lua_setfield(L, -2, "other"); @@ -155,7 +155,7 @@ void handle_npc_waypoint(QuestInterface *parse, lua_State* L, NPC* npc, Mob *ini void handle_npc_hate(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_Mob l_mob(init); - luabind::object l_mob_o = luabind::object(L, l_mob); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); l_mob_o.push(L); lua_setfield(L, -2, "other"); @@ -179,7 +179,7 @@ void handle_npc_timer(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, void handle_npc_death(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_Mob l_mob(init); - luabind::object l_mob_o = luabind::object(L, l_mob); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); l_mob_o.push(L); lua_setfield(L, -2, "other"); @@ -190,12 +190,12 @@ void handle_npc_death(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, int spell_id = std::stoi(sep.arg[1]); if(IsValidSpell(spell_id)) { Lua_Spell l_spell(&spells[spell_id]); - luabind::object l_spell_o = luabind::object(L, l_spell); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); l_spell_o.push(L); lua_setfield(L, -2, "spell"); } else { Lua_Spell l_spell(nullptr); - luabind::object l_spell_o = luabind::object(L, l_spell); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); l_spell_o.push(L); lua_setfield(L, -2, "spell"); } @@ -209,12 +209,12 @@ void handle_npc_cast(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, s int spell_id = std::stoi(data); if(IsValidSpell(spell_id)) { Lua_Spell l_spell(&spells[spell_id]); - luabind::object l_spell_o = luabind::object(L, l_spell); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); l_spell_o.push(L); lua_setfield(L, -2, "spell"); } else { Lua_Spell l_spell(nullptr); - luabind::object l_spell_o = luabind::object(L, l_spell); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); l_spell_o.push(L); lua_setfield(L, -2, "spell"); } @@ -249,7 +249,7 @@ void handle_player_death(QuestInterface *parse, lua_State* L, Client* client, st Mob *o = entity_list.GetMobID(std::stoi(sep.arg[0])); Lua_Mob l_mob(o); - luabind::object l_mob_o = luabind::object(L, l_mob); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); l_mob_o.push(L); lua_setfield(L, -2, "other"); @@ -259,12 +259,12 @@ void handle_player_death(QuestInterface *parse, lua_State* L, Client* client, st int spell_id = std::stoi(sep.arg[2]); if(IsValidSpell(spell_id)) { Lua_Spell l_spell(&spells[spell_id]); - luabind::object l_spell_o = luabind::object(L, l_spell); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); l_spell_o.push(L); lua_setfield(L, -2, "spell"); } else { Lua_Spell l_spell(nullptr); - luabind::object l_spell_o = luabind::object(L, l_spell); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); l_spell_o.push(L); lua_setfield(L, -2, "spell"); } @@ -284,12 +284,12 @@ void handle_player_discover_item(QuestInterface *parse, lua_State* L, Client* cl const Item_Struct *item = database.GetItem(extra_data); if(item) { Lua_Item l_item(item); - luabind::object l_item_o = luabind::object(L, l_item); + luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "item"); } else { Lua_Item l_item(nullptr); - luabind::object l_item_o = luabind::object(L, l_item); + luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "item"); } @@ -298,7 +298,7 @@ void handle_player_discover_item(QuestInterface *parse, lua_State* L, Client* cl void handle_player_fish_forage_success(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_ItemInst l_item(reinterpret_cast(extra_pointers->at(0))); - luabind::object l_item_o = luabind::object(L, l_item); + luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "item"); } @@ -306,7 +306,7 @@ void handle_player_fish_forage_success(QuestInterface *parse, lua_State* L, Clie void handle_player_click_object(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_Object l_object(reinterpret_cast(extra_pointers->at(0))); - luabind::object l_object_o = luabind::object(L, l_object); + luabind::adl::object l_object_o = luabind::adl::object(L, l_object); l_object_o.push(L); lua_setfield(L, -2, "object"); } @@ -314,7 +314,7 @@ void handle_player_click_object(QuestInterface *parse, lua_State* L, Client* cli void handle_player_click_door(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_Door l_door(reinterpret_cast(extra_pointers->at(0))); - luabind::object l_door_o = luabind::object(L, l_door); + luabind::adl::object l_door_o = luabind::adl::object(L, l_door); l_door_o.push(L); lua_setfield(L, -2, "door"); } @@ -334,7 +334,7 @@ void handle_player_popup_response(QuestInterface *parse, lua_State* L, Client* c void handle_player_pick_up(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_ItemInst l_item(reinterpret_cast(extra_pointers->at(0))); - luabind::object l_item_o = luabind::object(L, l_item); + luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "item"); } @@ -344,11 +344,11 @@ void handle_player_cast(QuestInterface *parse, lua_State* L, Client* client, std int spell_id = std::stoi(data); if(IsValidSpell(spell_id)) { Lua_Spell l_spell(&spells[spell_id]); - luabind::object l_spell_o = luabind::object(L, l_spell); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); l_spell_o.push(L); } else { Lua_Spell l_spell(nullptr); - luabind::object l_spell_o = luabind::object(L, l_spell); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); l_spell_o.push(L); } @@ -370,7 +370,7 @@ void handle_player_zone(QuestInterface *parse, lua_State* L, Client* client, std void handle_player_duel_win(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_Client l_client(reinterpret_cast(extra_pointers->at(1))); - luabind::object l_client_o = luabind::object(L, l_client); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); l_client_o.push(L); lua_setfield(L, -2, "other"); } @@ -378,7 +378,7 @@ void handle_player_duel_win(QuestInterface *parse, lua_State* L, Client* client, void handle_player_duel_loss(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_Client l_client(reinterpret_cast(extra_pointers->at(0))); - luabind::object l_client_o = luabind::object(L, l_client); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); l_client_o.push(L); lua_setfield(L, -2, "other"); } @@ -386,12 +386,12 @@ void handle_player_duel_loss(QuestInterface *parse, lua_State* L, Client* client void handle_player_loot(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_ItemInst l_item(reinterpret_cast(extra_pointers->at(0))); - luabind::object l_item_o = luabind::object(L, l_item); + luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "item"); Lua_Corpse l_corpse(reinterpret_cast(extra_pointers->at(1))); - luabind::object l_corpse_o = luabind::object(L, l_corpse); + luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse); l_corpse_o.push(L); lua_setfield(L, -2, "corpse"); } @@ -426,7 +426,7 @@ void handle_player_command(QuestInterface *parse, lua_State* L, Client* client, lua_pushstring(L, command.c_str()); lua_setfield(L, -2, "command"); - luabind::object args = luabind::newtable(L); + luabind::adl::object args = luabind::newtable(L); int max_args = sep.GetMaxArgNum(); for(int i = 1; i < max_args; ++i) { if(strlen(sep.arg[i]) > 0) { @@ -450,7 +450,7 @@ void handle_player_combine(QuestInterface *parse, lua_State* L, Client* client, void handle_player_feign(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_NPC l_npc(reinterpret_cast(extra_pointers->at(0))); - luabind::object l_npc_o = luabind::object(L, l_npc); + luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc); l_npc_o.push(L); lua_setfield(L, -2, "other"); } @@ -476,7 +476,7 @@ void handle_player_respawn(QuestInterface *parse, lua_State* L, Client* client, void handle_player_packet(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_Packet l_packet(reinterpret_cast(extra_pointers->at(0))); - luabind::object l_packet_o = luabind::object(L, l_packet); + luabind::adl::object l_packet_o = luabind::adl::object(L, l_packet); l_packet_o.push(L); lua_setfield(L, -2, "packet"); @@ -505,18 +505,18 @@ void handle_item_proc(QuestInterface *parse, lua_State* L, Client* client, ItemI std::vector *extra_pointers) { Lua_Mob l_mob(mob); - luabind::object l_mob_o = luabind::object(L, l_mob); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); l_mob_o.push(L); lua_setfield(L, -2, "target"); if(IsValidSpell(extra_data)) { Lua_Spell l_spell(&spells[extra_data]); - luabind::object l_spell_o = luabind::object(L, l_spell); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); l_spell_o.push(L); lua_setfield(L, -2, "spell"); } else { Lua_Spell l_spell(nullptr); - luabind::object l_spell_o = luabind::object(L, l_spell); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); l_spell_o.push(L); lua_setfield(L, -2, "spell"); } @@ -526,12 +526,12 @@ void handle_item_loot(QuestInterface *parse, lua_State* L, Client* client, ItemI std::vector *extra_pointers) { if(mob && mob->IsCorpse()) { Lua_Corpse l_corpse(mob->CastToCorpse()); - luabind::object l_corpse_o = luabind::object(L, l_corpse); + luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse); l_corpse_o.push(L); lua_setfield(L, -2, "corpse"); } else { Lua_Corpse l_corpse(nullptr); - luabind::object l_corpse_o = luabind::object(L, l_corpse); + luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse); l_corpse_o.push(L); lua_setfield(L, -2, "corpse"); } @@ -546,7 +546,7 @@ void handle_item_equip(QuestInterface *parse, lua_State* L, Client* client, Item void handle_item_augment(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_ItemInst l_item(reinterpret_cast(extra_pointers->at(0))); - luabind::object l_item_o = luabind::object(L, l_item); + luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "aug"); @@ -557,7 +557,7 @@ void handle_item_augment(QuestInterface *parse, lua_State* L, Client* client, It void handle_item_augment_insert(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_ItemInst l_item(reinterpret_cast(extra_pointers->at(0))); - luabind::object l_item_o = luabind::object(L, l_item); + luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "item"); @@ -568,7 +568,7 @@ void handle_item_augment_insert(QuestInterface *parse, lua_State* L, Client* cli void handle_item_augment_remove(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_ItemInst l_item(reinterpret_cast(extra_pointers->at(0))); - luabind::object l_item_o = luabind::object(L, l_item); + luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "item"); @@ -588,15 +588,15 @@ void handle_spell_effect(QuestInterface *parse, lua_State* L, NPC* npc, Client* std::vector *extra_pointers) { if(npc) { Lua_Mob l_npc(npc); - luabind::object l_npc_o = luabind::object(L, l_npc); + luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc); l_npc_o.push(L); } else if(client) { Lua_Mob l_client(client); - luabind::object l_client_o = luabind::object(L, l_client); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); l_client_o.push(L); } else { Lua_Mob l_mob(nullptr); - luabind::object l_mob_o = luabind::object(L, l_mob); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); l_mob_o.push(L); } @@ -613,15 +613,15 @@ void handle_spell_tic(QuestInterface *parse, lua_State* L, NPC* npc, Client* cli std::vector *extra_pointers) { if(npc) { Lua_Mob l_npc(npc); - luabind::object l_npc_o = luabind::object(L, l_npc); + luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc); l_npc_o.push(L); } else if(client) { Lua_Mob l_client(client); - luabind::object l_client_o = luabind::object(L, l_client); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); l_client_o.push(L); } else { Lua_Mob l_mob(nullptr); - luabind::object l_mob_o = luabind::object(L, l_mob); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); l_mob_o.push(L); } @@ -644,15 +644,15 @@ void handle_spell_fade(QuestInterface *parse, lua_State* L, NPC* npc, Client* cl std::vector *extra_pointers) { if(npc) { Lua_Mob l_npc(npc); - luabind::object l_npc_o = luabind::object(L, l_npc); + luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc); l_npc_o.push(L); } else if(client) { Lua_Mob l_client(client); - luabind::object l_client_o = luabind::object(L, l_client); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); l_client_o.push(L); } else { Lua_Mob l_mob(nullptr); - luabind::object l_mob_o = luabind::object(L, l_mob); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); l_mob_o.push(L); } @@ -669,15 +669,15 @@ void handle_translocate_finish(QuestInterface *parse, lua_State* L, NPC* npc, Cl std::vector *extra_pointers) { if(npc) { Lua_Mob l_npc(npc); - luabind::object l_npc_o = luabind::object(L, l_npc); + luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc); l_npc_o.push(L); } else if(client) { Lua_Mob l_client(client); - luabind::object l_client_o = luabind::object(L, l_client); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); l_client_o.push(L); } else { Lua_Mob l_mob(nullptr); - luabind::object l_mob_o = luabind::object(L, l_mob); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); l_mob_o.push(L); } From e7051d02894674b85e22434b13e6f552cd23b620 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Tue, 24 Jun 2014 08:24:11 -0400 Subject: [PATCH 052/288] Fix to SE_BlanaceMana to only check classes in group that have mana. --- zone/groups.cpp | 2 +- zone/raids.cpp | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/zone/groups.cpp b/zone/groups.cpp index 1af5cc34e..6aee5f38b 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -1160,7 +1160,7 @@ void Group::BalanceMana(int32 penalty, int32 range, Mob* caster, int32 limit) unsigned int gi = 0; for(; gi < MAX_GROUP_MEMBERS; gi++) { - if(members[gi]){ + if(members[gi] && (members[gi]->GetMaxMana() > 0)){ distance = caster->DistNoRoot(*members[gi]); if(distance <= range2){ diff --git a/zone/raids.cpp b/zone/raids.cpp index be0b697db..c712fc4bd 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -578,15 +578,17 @@ void Raid::BalanceMana(int32 penalty, uint32 gid, int32 range, Mob* caster, int3 if(members[gi].member){ if(members[gi].GroupNumber == gid) { - distance = caster->DistNoRoot(*members[gi].member); - if(distance <= range2){ + if (members[gi].member->GetMaxMana() > 0) { + distance = caster->DistNoRoot(*members[gi].member); + if(distance <= range2){ - manataken_tmp = members[gi].member->GetMaxMana() - members[gi].member->GetMana(); - if (limit && (manataken_tmp > limit)) - manataken_tmp = limit; + manataken_tmp = members[gi].member->GetMaxMana() - members[gi].member->GetMana(); + if (limit && (manataken_tmp > limit)) + manataken_tmp = limit; - manataken += (manataken_tmp); - numMem += 1; + manataken += (manataken_tmp); + numMem += 1; + } } } } From ee6a4bd2444780b179ab13095dcd3bc77c4e5437 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Tue, 24 Jun 2014 22:04:13 -0400 Subject: [PATCH 053/288] Implemented an enumerator list for numhits type variables. Implemented type 4 outgoing spell damage numhits type. --- zone/attack.cpp | 20 ++++++++++---------- zone/bot.cpp | 6 +++--- zone/common.h | 14 ++++++++++++++ zone/mob.cpp | 6 +++--- zone/special_attacks.cpp | 10 +++++----- zone/spell_effects.cpp | 8 ++++---- zone/spells.cpp | 18 ++++++++++++------ 7 files changed, 51 insertions(+), 31 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 99682eee5..4592f2fdf 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1350,7 +1350,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b MeleeLifeTap(damage); if (damage > 0) - CheckNumHitsRemaining(5); + CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess); //break invis when you attack if(invisible) { @@ -1965,7 +1965,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool MeleeLifeTap(damage); if (damage > 0) - CheckNumHitsRemaining(5); + CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess); //break invis when you attack if(invisible) { @@ -3421,7 +3421,7 @@ int32 Mob::ReduceAllDamage(int32 damage) TryTriggerOnValueAmount(false, true); } - CheckNumHitsRemaining(8); + CheckNumHitsRemaining(NUMHIT_IncomingDamage); return(damage); } @@ -3527,10 +3527,10 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons } if (spell_id == SPELL_UNKNOWN && skill_used) { - CheckNumHitsRemaining(1); //Incoming Hit Attempts + CheckNumHitsRemaining(NUMHIT_IncomingHitAttempts); if (attacker) - attacker->CheckNumHitsRemaining(2); //Outgoing Hit Attempts + attacker->CheckNumHitsRemaining(NUMHIT_OutgoingHitAttempts); } if(attacker){ @@ -3604,7 +3604,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons } if (skill_used) - CheckNumHitsRemaining(6); //Incomming Hit Success on Defender + CheckNumHitsRemaining(NUMHIT_IncomingHitSuccess); ReduceAllDamage(damage); @@ -4021,7 +4021,7 @@ void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand, int dam int chance = ProcChance * (DefensiveProcs[i].chance); if ((MakeRandomInt(0, 100) < chance)) { ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on); - CheckNumHitsRemaining(10,0,DefensiveProcs[i].base_spellID); + CheckNumHitsRemaining(NUMHIT_DefensiveSpellProcs,0,DefensiveProcs[i].base_spellID); } } } @@ -4208,7 +4208,7 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, "Spell proc %d procing spell %d (%.2f percent chance)", i, SpellProcs[i].spellID, chance); ExecWeaponProc(nullptr, SpellProcs[i].spellID, on); - CheckNumHitsRemaining(11, 0, SpellProcs[i].base_spellID); + CheckNumHitsRemaining(NUMHIT_OffensiveSpellProcs, 0, SpellProcs[i].base_spellID); } else { mlog(COMBAT__PROCS, "Spell proc %d failed to proc %d (%.2f percent chance)", @@ -4224,7 +4224,7 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, "Ranged proc %d procing spell %d (%.2f percent chance)", i, RangedProcs[i].spellID, chance); ExecWeaponProc(nullptr, RangedProcs[i].spellID, on); - CheckNumHitsRemaining(11, 0, RangedProcs[i].base_spellID); + CheckNumHitsRemaining(NUMHIT_OffensiveSpellProcs, 0, RangedProcs[i].base_spellID); } else { mlog(COMBAT__PROCS, "Ranged proc %d failed to proc %d (%.2f percent chance)", @@ -4594,7 +4594,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, float chance) int ProcChance = chance * (float)SkillProcs[i].chance; if ((MakeRandomInt(0, 100) < ProcChance)) { ExecWeaponProc(nullptr, SkillProcs[i].spellID, on); - CheckNumHitsRemaining(11,0, SkillProcs[i].base_spellID); + CheckNumHitsRemaining(NUMHIT_OffensiveSpellProcs,0, SkillProcs[i].base_spellID); } } } diff --git a/zone/bot.cpp b/zone/bot.cpp index 3b996e7a8..5bdf3cb02 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -3389,7 +3389,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes return; if (damage > 0) - CheckNumHitsRemaining(5); + CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess); if((skillinuse == SkillDragonPunch) && GetAA(aaDragonPunch) && MakeRandomInt(0, 99) < 25){ SpellFinished(904, other, 10, 0, -1, spells[904].ResistDiff); @@ -6632,7 +6632,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b MeleeLifeTap(damage); if (damage > 0) - CheckNumHitsRemaining(5); + CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess); //break invis when you attack if(invisible) { @@ -8092,7 +8092,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, if (HasDied()) return; if (max_damage > 0) - CheckNumHitsRemaining(5); + CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess); //[AA Dragon Punch] value[0] = 100 for 25%, chance value[1] = skill if(aabonuses.SpecialAttackKBProc[0] && aabonuses.SpecialAttackKBProc[1] == skill){ diff --git a/zone/common.h b/zone/common.h index f94962ee1..a8e8a17c9 100644 --- a/zone/common.h +++ b/zone/common.h @@ -150,6 +150,20 @@ enum TradeState { TradeCompleting }; +enum { //Numhits type + NUMHIT_IncomingHitAttempts = 1, //Attempted incoming melee attacks (hit or miss) on YOU. + NUMHIT_OutgoingHitAttempts = 2, //Attempted outgoing melee attacks (hit or miss) on YOUR TARGET. + NUMHIT_IncomingSpells = 3, //Incoming detrimental spells + NUMHIT_OutgoingSpells = 4, //Outgoing deterimental spells + NUMHIT_OutgoingHitSuccess = 5, //Successful outgoing melee attack HIT on YOUR TARGET. + NUMHIT_IncomingHitSuccess = 6, //Successful incoming melee attack HIT on YOU. + NUMHIT_MatchingSpells = 7, //Any casted spell matching/triggering a focus effect. + NUMHIT_IncomingDamage = 8, //Successful incoming spell or melee dmg attack on YOU + NUMHIT_ReflectSpell = 9, //Incoming Reflected spells. + NUMHIT_DefensiveSpellProcs = 10, //Defensive buff procs + NUMHIT_OffensiveSpellProcs = 11 //Offensive buff procs +}; + //this is our internal representation of the BUFF struct, can put whatever we want in it struct Buffs_Struct { uint16 spellid; diff --git a/zone/mob.cpp b/zone/mob.cpp index 06dbe4519..138c159cd 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3155,7 +3155,7 @@ void Mob::TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger) if(IsValidSpell(trigger_spell_id) && GetTarget()){ SpellFinished(trigger_spell_id, GetTarget(),10, 0, -1, spells[trigger_spell_id].ResistDiff); - CheckNumHitsRemaining(7,0, focus_spell); + CheckNumHitsRemaining(NUMHIT_MatchingSpells,0, focus_spell); } } } @@ -3408,7 +3408,7 @@ int32 Mob::GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining) value += tmp_focus; if (tmp_buffslot >= 0) - CheckNumHitsRemaining(7, tmp_buffslot); + CheckNumHitsRemaining(NUMHIT_MatchingSpells, tmp_buffslot); } return value; } @@ -3509,7 +3509,7 @@ void Mob::TrySympatheticProc(Mob *target, uint32 spell_id) SpellFinished(focus_trigger, target, 10, 0, -1, spells[focus_trigger].ResistDiff); } - CheckNumHitsRemaining(7, 0, focus_spell); + CheckNumHitsRemaining(NUMHIT_MatchingSpells, 0, focus_spell); } } diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 4bbd808cc..f9f324b6d 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -156,7 +156,7 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, if (HasDied()) return; if (max_damage > 0) - CheckNumHitsRemaining(5); + CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess); //[AA Dragon Punch] value[0] = 100 for 25%, chance value[1] = skill if(aabonuses.SpecialAttackKBProc[0] && aabonuses.SpecialAttackKBProc[1] == skill){ @@ -951,7 +951,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item TryCriticalHit(other, SkillArchery, TotalDmg); other->AddToHateList(this, hate, 0, false); - CheckNumHitsRemaining(5); + CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess); } } else @@ -1056,7 +1056,7 @@ void NPC::RangedAttack(Mob* other) TryCriticalHit(GetTarget(), SkillArchery, TotalDmg); GetTarget()->AddToHateList(this, hate, 0, false); GetTarget()->Damage(this, TotalDmg, SPELL_UNKNOWN, SkillArchery); - CheckNumHitsRemaining(5); + CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess); } else { @@ -1281,7 +1281,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite TryCriticalHit(other, SkillThrowing, TotalDmg); int32 hate = (2*WDmg); other->AddToHateList(this, hate, 0, false); - CheckNumHitsRemaining(5); + CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess); } } @@ -2196,7 +2196,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes if (HasDied()) return; - CheckNumHitsRemaining(5); + CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess); if(aabonuses.SpecialAttackKBProc[0] && aabonuses.SpecialAttackKBProc[1] == skillinuse){ int kb_chance = 25; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index b846e0058..6f71a56eb 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5275,7 +5275,7 @@ void Mob::CheckNumHitsRemaining(uint8 type, uint32 buff_slot, uint16 spell_id) 1: [Incoming Hit Attempts] (323=SE_DefensiveProc, 172=SE_AvoidMeleeChance, 1=SE_ArmorClass, 40=SE_DivineAura) 2: [Outgoing Hit Attempts] (185=SE_DamageModifer, 184=SE_HitChance) 3: [Incoming Spells] (180=SE_ResistSpellChance, 296=SE_FcSpellVulnerability) //Note: Determinetal spells only unless proven otherwise - 4: NONE + 4: [Outgoing Spells] 5: [Outgoing Hit Successes] (220=SE_SkillDamageAmount, 178=SE_MeleeLifetap, 121=SE_ReverseDS, ?373=SE_CastOnWearoff) 6: [Incoming Hit Successes] (59=SE_DamageShield, 197=SE_SkillDamageTaken, 162=define SE_MitigateMeleeDamage) 7: [Matching Spells] *When focus is triggered (focus effects) @@ -5591,7 +5591,7 @@ int32 Mob::GetFcDamageAmtIncoming(Mob *caster, uint32 spell_id, bool use_skill, } if ((!limit_exists) || (limit_exists && skill_found)){ dmg += temp_dmg; - CheckNumHitsRemaining(7,i); + CheckNumHitsRemaining(NUMHIT_MatchingSpells,i); } } @@ -5599,7 +5599,7 @@ int32 Mob::GetFcDamageAmtIncoming(Mob *caster, uint32 spell_id, bool use_skill, int32 focus = caster->CalcFocusEffect(focusFcDamageAmtIncoming, buffs[i].spellid, spell_id); if(focus){ dmg += focus; - CheckNumHitsRemaining(7,i); + CheckNumHitsRemaining(NUMHIT_MatchingSpells,i); } } } @@ -5653,7 +5653,7 @@ int32 Mob::GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spel value = tmp_focus; if (tmp_buffslot >= 0) - CheckNumHitsRemaining(7, tmp_buffslot); + CheckNumHitsRemaining(NUMHIT_MatchingSpells, tmp_buffslot); } } diff --git a/zone/spells.cpp b/zone/spells.cpp index 21a2fe749..32140849b 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1250,7 +1250,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, } if(IsClient()) { - CheckNumHitsRemaining(7); + CheckNumHitsRemaining(NUMHIT_MatchingSpells); TrySympatheticProc(target, spell_id); } @@ -3401,7 +3401,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r if(IsEffectInSpell(buffs[b].spellid, SE_BlockNextSpellFocus)) { focus = CalcFocusEffect(focusBlockNextSpell, buffs[b].spellid, spell_id); if(focus) { - CheckNumHitsRemaining(7,b); + CheckNumHitsRemaining(NUMHIT_MatchingSpells,b); Message_StringID(MT_SpellFailure, SPELL_WOULDNT_HOLD); safe_delete(action_packet); return false; @@ -3450,7 +3450,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r } if(reflect_chance) { Message_StringID(MT_Spells, SPELL_REFLECT, GetCleanName(), spelltar->GetCleanName()); - CheckNumHitsRemaining(9); + CheckNumHitsRemaining(NUMHIT_ReflectSpell); SpellOnTarget(spell_id, this, true, use_resist_adjust, resist_adjust); safe_delete(action_packet); return false; @@ -3501,7 +3501,8 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r } } - spelltar->CheckNumHitsRemaining(3); + spelltar->CheckNumHitsRemaining(NUMHIT_IncomingSpells); + CheckNumHitsRemaining(NUMHIT_OutgoingSpells); safe_delete(action_packet); return false; @@ -3654,8 +3655,13 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r } - if (spelltar && IsDetrimentalSpell(spell_id)) - spelltar->CheckNumHitsRemaining(3); //Incoming spells + if (IsDetrimentalSpell(spell_id)) { + + CheckNumHitsRemaining(NUMHIT_OutgoingSpells); + + if (spelltar) + spelltar->CheckNumHitsRemaining(NUMHIT_IncomingSpells); + } // send the action packet again now that the spell is successful // NOTE: this is what causes the buff icon to appear on the client, if From b7cc19f983d69bd20e5d6628fc42c2fb84a2b637 Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 30 Jun 2014 14:09:03 -0700 Subject: [PATCH 054/288] Removed older AZone build options, use eqemu-zone-utils instead --- CMakeLists.txt | 5 -- utils/CMakeLists.txt | 7 --- utils/azone2/CMakeLists.txt | 119 ------------------------------------ 3 files changed, 131 deletions(-) delete mode 100644 utils/CMakeLists.txt delete mode 100644 utils/azone2/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 45d3f6c50..4732ca8d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -229,7 +229,6 @@ ENDIF(EQEMU_ENABLE_BOTS) #What to build OPTION(EQEMU_BUILD_SERVER "Build the game server." ON) OPTION(EQEMU_BUILD_LOGIN "Build the login server." OFF) -OPTION(EQEMU_BUILD_AZONE "Build azone utility." OFF) OPTION(EQEMU_BUILD_TESTS "Build utility tests." OFF) OPTION(EQEMU_BUILD_PERL "Build Perl parser." ON) OPTION(EQEMU_BUILD_LUA "Build Lua parser." OFF) @@ -319,10 +318,6 @@ IF(EQEMU_BUILD_LOGIN) ADD_SUBDIRECTORY(loginserver) ENDIF(EQEMU_BUILD_LOGIN) -IF(EQEMU_BUILD_AZONE) - ADD_SUBDIRECTORY(utils) -ENDIF(EQEMU_BUILD_AZONE) - IF(EQEMU_BUILD_TESTS) ADD_SUBDIRECTORY(tests) ENDIF(EQEMU_BUILD_TESTS) diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt deleted file mode 100644 index 4aec544ee..000000000 --- a/utils/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) - -IF(UNIX) - ADD_DEFINITIONS(-fPIC) -ENDIF(UNIX) - -ADD_SUBDIRECTORY(azone2) diff --git a/utils/azone2/CMakeLists.txt b/utils/azone2/CMakeLists.txt deleted file mode 100644 index 3567df948..000000000 --- a/utils/azone2/CMakeLists.txt +++ /dev/null @@ -1,119 +0,0 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) - -IF(NOT MSVC) - ADD_DEFINITIONS(-fpermissive) -ENDIF(NOT MSVC) - -#azone common -SET(azone_common_sources - dat.cpp - file.cpp - global.cpp - pfs.cpp - ter.cpp - wld.cpp - zon.cpp - zonv4.cpp -) - -SET(azone_common_headers - 3d.hpp - 3d_base.hpp - archive.hpp - dat.hpp - file.hpp - file_loader.hpp - global.hpp - octree.hpp - pfs.hpp - s3d.h - ter.hpp - types.h - wld.hpp - wld_structs.hpp - zon.hpp - zonv4.hpp -) - -ADD_LIBRARY(azone_common ${azone_common_sources} ${azone_common_headers}) -SET(LIBRARY_OUTPUT_PATH ../../Bin) - -#azone -SET(azone_sources - azone.cpp -) - -SET(azone_headers - azone.h -) - -ADD_EXECUTABLE(azone ${azone_sources} ${azone_headers}) -TARGET_LINK_LIBRARIES(azone azone_common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE}) -IF(MSVC) - SET_TARGET_PROPERTIES(azone PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF") - TARGET_LINK_LIBRARIES(azone "Ws2_32.lib") -ENDIF(MSVC) - -IF(UNIX) - TARGET_LINK_LIBRARIES(azone "z") -ENDIF(UNIX) - -SET(EXECUTABLE_OUTPUT_PATH ../../Bin) - -#awater -SET(awater_sources - awater.cpp -) - -SET(awater_headers - awater.h -) - -ADD_EXECUTABLE(awater ${awater_sources} ${awater_headers}) -TARGET_LINK_LIBRARIES(awater azone_common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE}) -IF(MSVC) - SET_TARGET_PROPERTIES(awater PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF") - TARGET_LINK_LIBRARIES(awater "Ws2_32.lib") -ENDIF(MSVC) - -IF(UNIX) - TARGET_LINK_LIBRARIES(awater "z") -ENDIF(UNIX) - -SET(EXECUTABLE_OUTPUT_PATH ../../Bin) - -#listobj -SET(listobj_sources - listobj.cpp -) - -SET(listobj_headers -) - -ADD_EXECUTABLE(listobj ${listobj_sources} ${listobj_headers}) -TARGET_LINK_LIBRARIES(listobj azone_common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE}) -IF(MSVC) - SET_TARGET_PROPERTIES(listobj PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF") - TARGET_LINK_LIBRARIES(listobj "Ws2_32.lib") -ENDIF(MSVC) - -IF(UNIX) - TARGET_LINK_LIBRARIES(listobj "z") -ENDIF(UNIX) - -#on windows: glmodelviewer -IF(MSVC) - SET(glmodelviewer_sources - GLModelViewer.cpp - ) - - SET(glmodelviewer_headers - GLModelViewer.h - ) - - ADD_EXECUTABLE(glmodelviewer WIN32 ${glmodelviewer_sources} ${glmodelviewer_headers}) - TARGET_LINK_LIBRARIES(glmodelviewer azone_common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} "opengl32.lib" "GLU32.lib" "Ws2_32.lib") - SET_TARGET_PROPERTIES(glmodelviewer PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF") - - SET(EXECUTABLE_OUTPUT_PATH ../../Bin) -ENDIF(MSVC) From dc6154f71fffe061bcbc81e82b0cb2fa5272aa6d Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Wed, 25 Jun 2014 14:14:55 -0400 Subject: [PATCH 055/288] Updated SE_Hate (Renamed from SE_Hate2) to now properly work for instant +/- hate spells. --- changelog.txt | 4 ++++ common/spdat.h | 2 +- zone/spell_effects.cpp | 27 +++++++++++++++++++++++++-- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/changelog.txt b/changelog.txt index c4fa6cecf..97a68ad24 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- + +== 06/25/2014 == +Kayen: Updated SE_Hate (Renamed from SE_Hate2) to now properly work for instant +/- hate spells. + == 06/17/2014 == Kayen: Implemented SE_AStacker, SE_BStacker, SE_CStacker, SE_DStacker. These effects when present in buffs prevent each other from stacking, diff --git a/common/spdat.h b/common/spdat.h index b302e8314..fd9ba923f 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -339,7 +339,7 @@ typedef enum { #define SE_CurrentEndurance 189 // implemented #define SE_EndurancePool 190 // implemented #define SE_Amnesia 191 // implemented - Silence vs Melee Effect -#define SE_Hate2 192 // implemented +#define SE_Hate 192 // implemented - Instant and hate over time. #define SE_SkillAttack 193 // implemented #define SE_FadingMemories 194 // implemented #define SE_StunResist 195 // implemented diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 6f71a56eb..e32170e67 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2676,6 +2676,30 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) break; } + case SE_Hate:{ + + if (buffslot >= 0) + break; + + if(caster){ + if(effect_value > 0){ + if(caster){ + if(caster->IsClient() && !caster->CastToClient()->GetFeigned()) + AddToHateList(caster, effect_value); + else if(!caster->IsClient()) + AddToHateList(caster, effect_value); + } + }else{ + int32 newhate = GetHateAmount(caster) + effect_value; + if (newhate < 1) + SetHate(caster,1); + else + SetHate(caster,newhate); + } + } + break; + } + // Handled Elsewhere case SE_ImmuneFleeing: case SE_NegateSpellEffect: @@ -2746,7 +2770,6 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_ChangeFrenzyRad: case SE_Harmony: case SE_ChangeAggro: - case SE_Hate2: case SE_Identify: case SE_InstantHate: case SE_ReduceHate: @@ -3340,7 +3363,7 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste break; } - case SE_Hate2:{ + case SE_Hate:{ effect_value = CalcSpellEffectValue(spell_id, i, caster_level); if(caster){ if(effect_value > 0){ From a1f2e1c8fdd40d627e333b9b3b2900963f2bc238 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Wed, 25 Jun 2014 14:31:35 -0400 Subject: [PATCH 056/288] Updated SE_FadingMemories - Base value will be properly utilized to set % chance for fade effect to work. --- changelog.txt | 1 + zone/spell_effects.cpp | 15 +++++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/changelog.txt b/changelog.txt index 97a68ad24..9b890da6a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 06/25/2014 == Kayen: Updated SE_Hate (Renamed from SE_Hate2) to now properly work for instant +/- hate spells. +Kayen: Updated SE_FadingMemories - Base value will be properly utilized to set % chance for fade effect to work. == 06/17/2014 == Kayen: Implemented SE_AStacker, SE_BStacker, SE_CStacker, SE_DStacker. diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index e32170e67..5861d31e6 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2183,12 +2183,15 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Fading Memories"); #endif - if(caster && caster->IsClient()) - caster->CastToClient()->Escape(); - else - { - entity_list.RemoveFromTargets(caster); - SetInvisible(1); + if(MakeRandomInt(0, 99) < spells[spell_id].base[i] ) { + + if(caster && caster->IsClient()) + caster->CastToClient()->Escape(); + else + { + entity_list.RemoveFromTargets(caster); + SetInvisible(1); + } } break; } From 75fb34934d1f695721ade8bc41ecaf8d6fbbb9c2 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Wed, 25 Jun 2014 14:41:15 -0400 Subject: [PATCH 057/288] Implemented SE_StrikeThough (Was incorrectly defined as implemented previously) - Works same as item bonus. --- common/spdat.h | 2 +- zone/bonuses.cpp | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/common/spdat.h b/common/spdat.h index fd9ba923f..f4883552b 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -343,7 +343,7 @@ typedef enum { #define SE_SkillAttack 193 // implemented #define SE_FadingMemories 194 // implemented #define SE_StunResist 195 // implemented -#define SE_Strikethrough 196 // implemented +#define SE_StrikeThrough 196 // implemented #define SE_SkillDamageTaken 197 // implemented #define SE_CurrentEnduranceOnce 198 // implemented #define SE_Taunt 199 // implemented - % chance to taunt the target diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 3ce6becca..f46328ea6 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -953,6 +953,8 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) case SE_BlockBehind: newbon->BlockBehind += base1; break; + + case SE_StrikeThrough: case SE_StrikeThrough2: newbon->StrikeThrough += base1; break; @@ -2469,6 +2471,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne newbon->SecondaryDmgInc = true; break; + case SE_StrikeThrough: case SE_StrikeThrough2: newbon->StrikeThrough += effect_value; break; @@ -3909,6 +3912,12 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) itembonuses.SecondaryDmgInc = false; break; + case SE_StrikeThrough: + spellbonuses.StrikeThrough = effect_value; + aabonuses.StrikeThrough = effect_value; + itembonuses.StrikeThrough = effect_value; + break; + case SE_StrikeThrough2: spellbonuses.StrikeThrough = effect_value; aabonuses.StrikeThrough = effect_value; From 4684d927582ef70d15d3d3900fd0e9377f68c293 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Wed, 25 Jun 2014 15:25:22 -0400 Subject: [PATCH 058/288] Update SE_Taunt - Limit value if present will now add instant hate. --- changelog.txt | 2 ++ zone/spell_effects.cpp | 25 ++++++++++++++++++------- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/changelog.txt b/changelog.txt index 9b890da6a..5a77ec900 100644 --- a/changelog.txt +++ b/changelog.txt @@ -4,6 +4,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 06/25/2014 == Kayen: Updated SE_Hate (Renamed from SE_Hate2) to now properly work for instant +/- hate spells. Kayen: Updated SE_FadingMemories - Base value will be properly utilized to set % chance for fade effect to work. +Kayen: Implemented SE_StrikeThough (Was incorrectly defined as implemented previously) - Works same as item bonus. +Kayen: Update SE_Taunt - Limit value if present will now add instant hate. == 06/17/2014 == Kayen: Implemented SE_AStacker, SE_BStacker, SE_CStacker, SE_DStacker. diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 5861d31e6..b073b65e2 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2646,9 +2646,12 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_Taunt: { - if (IsNPC()) + if (IsNPC()){ caster->Taunt(this->CastToNPC(), false, spell.base[i]); - + + if (spell.base2[i] > 0) + CastToNPC()->SetHate(caster, (CastToNPC()->GetHateAmount(caster) + spell.base2[i])); + } break; } @@ -2673,9 +2676,13 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_AddHatePct: { - if (IsNPC()) - CastToNPC()->SetHate(caster, (CastToNPC()->GetHateAmount(caster) * (100 + spell.base[i]) / 100)); + if (IsNPC()){ + int32 new_hate = CastToNPC()->GetHateAmount(caster) * (100 + spell.base[i]) / 100; + if (new_hate <= 0) + new_hate = 1; + CastToNPC()->SetHate(caster, new_hate); + } break; } @@ -3562,9 +3569,13 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste case SE_AddHateOverTimePct: { - if (IsNPC()) - CastToNPC()->SetHate(caster, (CastToNPC()->GetHateAmount(caster) * (100 + spell.base[i]) / 100)); - + if (IsNPC()){ + int32 new_hate = CastToNPC()->GetHateAmount(caster) * (100 + spell.base[i]) / 100; + if (new_hate <= 0) + new_hate = 1; + + CastToNPC()->SetHate(caster, new_hate); + } break; } From 54d1cff546fa6444735f261300319cc025ec1304 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Thu, 26 Jun 2014 05:40:09 -0400 Subject: [PATCH 059/288] Implemented SE_MassGroupBuff as spell effect (no longer hard coded for AA only). Run required SQL to update AA tables. Updated spells_new field175 -> numhits_type --- changelog.txt | 4 ++++ common/spdat.h | 2 +- zone/AA.cpp | 5 ----- zone/AA.h | 2 +- zone/mob.cpp | 1 + zone/mob.h | 3 +++ zone/spell_effects.cpp | 10 +++++++++- zone/spells.cpp | 6 +++--- 8 files changed, 22 insertions(+), 11 deletions(-) diff --git a/changelog.txt b/changelog.txt index 5a77ec900..991ffbba5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -6,6 +6,10 @@ Kayen: Updated SE_Hate (Renamed from SE_Hate2) to now properly work for instant Kayen: Updated SE_FadingMemories - Base value will be properly utilized to set % chance for fade effect to work. Kayen: Implemented SE_StrikeThough (Was incorrectly defined as implemented previously) - Works same as item bonus. Kayen: Update SE_Taunt - Limit value if present will now add instant hate. +Kayen: Implemented SE_MassGroupBuff - Allows next group buff cast to be a MGB (AA now uses this) + +Required SQL: utils/sql/git/required/2014_06_25_MGB_AA.sql + == 06/17/2014 == Kayen: Implemented SE_AStacker, SE_BStacker, SE_CStacker, SE_DStacker. diff --git a/common/spdat.h b/common/spdat.h index f4883552b..956d40b31 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -350,7 +350,7 @@ typedef enum { #define SE_ProcChance 200 // implemented #define SE_RangedProc 201 // implemented //#define SE_IllusionOther 202 // *not implemented as bonus(Project Illusion) -//#define SE_MassGroupBuff 203 // *not implemented as bonus +#define SE_MassGroupBuff 203 // implemented #define SE_GroupFearImmunity 204 // *not implemented as bonus #define SE_Rampage 205 // implemented #define SE_AETaunt 206 // implemented diff --git a/zone/AA.cpp b/zone/AA.cpp index 8566c09b5..bd1e568b3 100644 --- a/zone/AA.cpp +++ b/zone/AA.cpp @@ -352,11 +352,6 @@ void Client::HandleAAAction(aaID activate) { entity_list.AETaunt(this); break; - case aaActionMassBuff: - EnableAAEffect(aaEffectMassGroupBuff, 3600); - Message_StringID(MT_Disciplines, MGB_STRING); //The next group buff you cast will hit all targets in range. - break; - case aaActionFlamingArrows: //toggle it if(CheckAAEffect(aaEffectFlamingArrows)) diff --git a/zone/AA.h b/zone/AA.h index ccdddf317..36cc886af 100644 --- a/zone/AA.h +++ b/zone/AA.h @@ -43,7 +43,7 @@ typedef enum { //use these for AAs which dont cast spells, yet need effects //if this list grows beyond 32, more work is needed in *AAEffect typedef enum { //AA Effect IDs - aaEffectMassGroupBuff = 1, + aaEffectMassGroupBuff = 1, //unused - Handled via spell effect. aaEffectRampage, aaEffectSharedHealth, aaEffectFlamingArrows, diff --git a/zone/mob.cpp b/zone/mob.cpp index 138c159cd..e10a1aeb1 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -180,6 +180,7 @@ Mob::Mob(const char* in_name, trackable = true; has_shieldequiped = false; has_numhits = false; + has_MGB = false; if(in_aa_title>0) aa_title = in_aa_title; diff --git a/zone/mob.h b/zone/mob.h index 4ab9d8a84..599fa3b69 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -268,6 +268,8 @@ public: void CheckNumHitsRemaining(uint8 type, uint32 buff_slot=0, uint16 spell_id=SPELL_UNKNOWN); bool HasNumhits() const { return has_numhits; } inline void Numhits(bool val) { has_numhits = val; } + bool HasMGB() const { return has_MGB; } + inline void SetMGB(bool val) { has_MGB = val; } void SpreadVirus(uint16 spell_id, uint16 casterID); bool IsNimbusEffectActive(uint32 nimbus_effect); void SetNimbusEffect(uint32 nimbus_effect); @@ -1097,6 +1099,7 @@ protected: bool offhand; bool has_shieldequiped; bool has_numhits; + bool has_MGB; // Bind wound Timer bindwound_timer; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index b073b65e2..35e8ecf66 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2710,6 +2710,13 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) break; } + case SE_MassGroupBuff:{ + + SetMGB(true); + Message_StringID(MT_Disciplines, MGB_STRING); + break; + } + // Handled Elsewhere case SE_ImmuneFleeing: case SE_NegateSpellEffect: @@ -2864,7 +2871,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_ACv2: case SE_ManaRegen_v2: case SE_FcDamagePctCrit: - case SE_FcHealAmt: + case SE_FcHealAmt: case SE_FcHealPctIncoming: case SE_CriticalHealDecay: case SE_CriticalRegenDecay: @@ -2878,6 +2885,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_PetCriticalHit: case SE_SlayUndead: case SE_GiveDoubleAttack: + case SE_StrikeThrough: case SE_StrikeThrough2: case SE_SecondaryDmgInc: case SE_ArcheryDamageModifier: diff --git a/zone/spells.cpp b/zone/spells.cpp index 32140849b..041f13fce 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -399,7 +399,7 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, mana_cost = GetActSpellCost(spell_id, mana_cost); } - if(IsClient() && CastToClient()->CheckAAEffect(aaEffectMassGroupBuff) && spells[spell_id].can_mgb) + if(HasMGB() && spells[spell_id].can_mgb) mana_cost *= 2; // mana is checked for clients on the frontend. we need to recheck it for NPCs though @@ -1969,11 +1969,11 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 } #endif //BOTS - if(spells[spell_id].can_mgb && IsClient() && CastToClient()->CheckAAEffect(aaEffectMassGroupBuff)) + if(spells[spell_id].can_mgb && HasMGB()) { SpellOnTarget(spell_id, this); entity_list.MassGroupBuff(this, this, spell_id, true); - CastToClient()->DisableAAEffect(aaEffectMassGroupBuff); + SetMGB(false); } else { From 34bbb9236ec5a1972e5242559ea2e9cd59234571 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Thu, 26 Jun 2014 06:23:27 -0400 Subject: [PATCH 060/288] Implemented SE_IllusionOther - Allows next Illusion buff (self only) cast to be cast on target. (AA ProjectIllusion now uses this) Run required SLQ to update AA. --- changelog.txt | 1 + common/spdat.h | 2 +- utils/sql/git/required/2014_06_25_AA_Updates..sql | 10 ++++++++++ zone/AA.cpp | 6 ------ zone/AA.h | 2 +- zone/mob.cpp | 1 + zone/mob.h | 3 +++ zone/spell_effects.cpp | 6 ++++++ zone/spells.cpp | 8 ++++---- 9 files changed, 27 insertions(+), 12 deletions(-) create mode 100644 utils/sql/git/required/2014_06_25_AA_Updates..sql diff --git a/changelog.txt b/changelog.txt index 991ffbba5..d54a8d52d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -7,6 +7,7 @@ Kayen: Updated SE_FadingMemories - Base value will be properly utilized to set % Kayen: Implemented SE_StrikeThough (Was incorrectly defined as implemented previously) - Works same as item bonus. Kayen: Update SE_Taunt - Limit value if present will now add instant hate. Kayen: Implemented SE_MassGroupBuff - Allows next group buff cast to be a MGB (AA now uses this) +Kayen: Implemented SE_IllusionOther - Allows next Illusion buff (self only) cast to be cast on target. (AA now uses this) Required SQL: utils/sql/git/required/2014_06_25_MGB_AA.sql diff --git a/common/spdat.h b/common/spdat.h index 956d40b31..ea4218ff1 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -349,7 +349,7 @@ typedef enum { #define SE_Taunt 199 // implemented - % chance to taunt the target #define SE_ProcChance 200 // implemented #define SE_RangedProc 201 // implemented -//#define SE_IllusionOther 202 // *not implemented as bonus(Project Illusion) +#define SE_IllusionOther 202 // implemented - Project Illusion #define SE_MassGroupBuff 203 // implemented #define SE_GroupFearImmunity 204 // *not implemented as bonus #define SE_Rampage 205 // implemented diff --git a/utils/sql/git/required/2014_06_25_AA_Updates..sql b/utils/sql/git/required/2014_06_25_AA_Updates..sql new file mode 100644 index 000000000..2e2b7579f --- /dev/null +++ b/utils/sql/git/required/2014_06_25_AA_Updates..sql @@ -0,0 +1,10 @@ +-- AA MGB update +UPDATE altadv_vars SET spellid = 5228 WHERE skill_id = 128; +UPDATE aa_actions SET spell_id = 5228, nonspell_action = 0 WHERE aaid = 128; + +-- AA Project Illusion update +UPDATE altadv_vars SET spellid = 5227 WHERE skill_id = 643; +UPDATE aa_actions SET spell_id = 5227, nonspell_action = 0 WHERE aaid = 643; + +-- spells_new update +ALTER TABLE `spells_new` CHANGE `field175` `numhits_type` INT(11) NOT NULL DEFAULT '0'; \ No newline at end of file diff --git a/zone/AA.cpp b/zone/AA.cpp index bd1e568b3..6e5569c3c 100644 --- a/zone/AA.cpp +++ b/zone/AA.cpp @@ -454,12 +454,6 @@ void Client::HandleAAAction(aaID activate) { } break; - case aaActionProjectIllusion: - EnableAAEffect(aaEffectProjectIllusion, 3600); - Message(10, "The power of your next illusion spell will flow to your grouped target in your place."); - break; - - case aaActionEscape: Escape(); break; diff --git a/zone/AA.h b/zone/AA.h index 36cc886af..3adc887e3 100644 --- a/zone/AA.h +++ b/zone/AA.h @@ -50,7 +50,7 @@ typedef enum { //AA Effect IDs aaEffectFrostArrows, aaEffectWarcry, aaEffectLeechTouch, - aaEffectProjectIllusion // seveian 2008-09-23 + aaEffectProjectIllusion // unused - Handled via spell effect } aaEffectType; diff --git a/zone/mob.cpp b/zone/mob.cpp index e10a1aeb1..ed2072e21 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -181,6 +181,7 @@ Mob::Mob(const char* in_name, has_shieldequiped = false; has_numhits = false; has_MGB = false; + has_ProjectIllusion = false; if(in_aa_title>0) aa_title = in_aa_title; diff --git a/zone/mob.h b/zone/mob.h index 599fa3b69..61a2220d6 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -270,6 +270,8 @@ public: inline void Numhits(bool val) { has_numhits = val; } bool HasMGB() const { return has_MGB; } inline void SetMGB(bool val) { has_MGB = val; } + bool HasProjectIllusion() const { return has_ProjectIllusion ; } + inline void SetProjectIllusion(bool val) { has_ProjectIllusion = val; } void SpreadVirus(uint16 spell_id, uint16 casterID); bool IsNimbusEffectActive(uint32 nimbus_effect); void SetNimbusEffect(uint32 nimbus_effect); @@ -1100,6 +1102,7 @@ protected: bool has_shieldequiped; bool has_numhits; bool has_MGB; + bool has_ProjectIllusion; // Bind wound Timer bindwound_timer; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 35e8ecf66..635fc9270 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2717,6 +2717,12 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) break; } + case SE_IllusionOther: { + SetProjectIllusion(true); + Message(10, "The power of your next illusion spell will flow to your grouped target in your place."); + break; + } + // Handled Elsewhere case SE_ImmuneFleeing: case SE_NegateSpellEffect: diff --git a/zone/spells.cpp b/zone/spells.cpp index 041f13fce..78dce3379 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1371,7 +1371,7 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce && IsClient() && (IsGrouped() // still self only if not grouped || IsRaidGrouped()) - && CastToClient()->CheckAAEffect(aaEffectProjectIllusion)){ + && (HasProjectIllusion())){ mlog(AA__MESSAGE, "Project Illusion overwrote target caster: %s spell id: %d was ON", GetName(), spell_id); targetType = ST_GroupClientAndPet; } @@ -1853,7 +1853,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 range = GetActSpellRange(spell_id, range); if(IsPlayerIllusionSpell(spell_id) && IsClient() - && CastToClient()->CheckAAEffect(aaEffectProjectIllusion)){ + && (HasProjectIllusion())){ range = 100; } if(spell_target != nullptr && spell_target != this) { @@ -1912,9 +1912,9 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 if(IsPlayerIllusionSpell(spell_id) && IsClient() - && CastToClient()->CheckAAEffect(aaEffectProjectIllusion)){ + && (HasProjectIllusion())){ mlog(AA__MESSAGE, "Effect Project Illusion for %s on spell id: %d was ON", GetName(), spell_id); - CastToClient()->DisableAAEffect(aaEffectProjectIllusion); + SetProjectIllusion(false); } else{ mlog(AA__MESSAGE, "Effect Project Illusion for %s on spell id: %d was OFF", GetName(), spell_id); From fbdc104c12a97bd48c5e639ff65b493beec41192 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Thu, 26 Jun 2014 06:45:18 -0400 Subject: [PATCH 061/288] changelog fix --- changelog.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index d54a8d52d..a2d099bab 100644 --- a/changelog.txt +++ b/changelog.txt @@ -9,7 +9,7 @@ Kayen: Update SE_Taunt - Limit value if present will now add instant hate. Kayen: Implemented SE_MassGroupBuff - Allows next group buff cast to be a MGB (AA now uses this) Kayen: Implemented SE_IllusionOther - Allows next Illusion buff (self only) cast to be cast on target. (AA now uses this) -Required SQL: utils/sql/git/required/2014_06_25_MGB_AA.sql +Required SQL: utils/sql/git/required/2014_06_25_AA_Update.sql == 06/17/2014 == From ef79a0607bc7d0603f7b716d24fcafd22ef9e66c Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Thu, 26 Jun 2014 10:04:21 -0400 Subject: [PATCH 062/288] Update SE_AETaunt - Base value will now determine AE taunt range (This will not result in any change to currently used spells). --- changelog.txt | 1 + common/spdat.h | 4 ++-- zone/spell_effects.cpp | 9 +++++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/changelog.txt b/changelog.txt index a2d099bab..a177460ee 100644 --- a/changelog.txt +++ b/changelog.txt @@ -8,6 +8,7 @@ Kayen: Implemented SE_StrikeThough (Was incorrectly defined as implemented previ Kayen: Update SE_Taunt - Limit value if present will now add instant hate. Kayen: Implemented SE_MassGroupBuff - Allows next group buff cast to be a MGB (AA now uses this) Kayen: Implemented SE_IllusionOther - Allows next Illusion buff (self only) cast to be cast on target. (AA now uses this) +Kayen: Update SE_AETaunt - Base value will now determine AE taunt range (This will not result in any change to currently used spells). Required SQL: utils/sql/git/required/2014_06_25_AA_Update.sql diff --git a/common/spdat.h b/common/spdat.h index ea4218ff1..7773a95c4 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -237,7 +237,7 @@ typedef enum { #define SE_MagnifyVision 87 // implemented - Telescope #define SE_Succor 88 // implemented - Evacuate/Succor lines #define SE_ModelSize 89 // implemented - Shrink, Growth -#define SE_Cloak 90 // *not implemented - Used in only 2 spells +//#define SE_Cloak 90 // *not implemented - Used in only 2 spells #define SE_SummonCorpse 91 // implemented #define SE_InstantHate 92 // implemented - add hate #define SE_StopRain 93 // implemented - Wake of Karana @@ -351,7 +351,7 @@ typedef enum { #define SE_RangedProc 201 // implemented #define SE_IllusionOther 202 // implemented - Project Illusion #define SE_MassGroupBuff 203 // implemented -#define SE_GroupFearImmunity 204 // *not implemented as bonus +#define SE_GroupFearImmunity 204 // implemented - (Does not use bonus) #define SE_Rampage 205 // implemented #define SE_AETaunt 206 // implemented #define SE_FleshToBone 207 // implemented diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 635fc9270..f2587a0d3 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2237,8 +2237,13 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "AE Taunt"); #endif - if(caster && caster->IsClient()) - entity_list.AETaunt(caster->CastToClient()); + if(caster && caster->IsClient()){ + float range = 0.0f; + if (spells[spell_id].base2[i]) + range = (float)spells[spell_id].base[i]; + + entity_list.AETaunt(caster->CastToClient(), range); + } break; } From 6c4e69a71dbf78b2da6967ec719a08a9503b4b64 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Thu, 26 Jun 2014 10:54:18 -0400 Subject: [PATCH 063/288] Slight change to TryDispel formula for better accuracy. Live PATCH 5-20-14 Note: "Updated all spells which use Remove Detrimental and Cancel Beneficial spell effects to use a new method. The chances for those spells to affect their targets have not changed unless otherwise noted" Support added for new base values to give a nearly equivelent result. (Ie. Will work for values pre and post change) --- zone/spell_effects.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index f2587a0d3..e3fb89d6f 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5798,16 +5798,25 @@ uint16 Mob::GetSpellEffectResistChance(uint16 spell_id) bool Mob::TryDispel(uint8 caster_level, uint8 buff_level, int level_modifier){ + /*Live 5-20-14 Patch Note: Updated all spells which use Remove Detrimental and + Cancel Beneficial spell effects to use a new method. The chances for those spells to + affect their targets have not changed unless otherwise noted.*/ + + /*This should provide a somewhat accurate conversion between pre 5/14 base values and post. + until more information is avialble - Kayen*/ + if (level_modifier > 100) + level_modifier = level_modifier/100; + //Dispels - Check level of caster agianst buffs level (level of the caster who cast the buff) //Effect value of dispels are treated as a level modifier. //Values for scaling were obtain from live parses, best estimates. caster_level += level_modifier - 1; - int dispel_chance = 36; //Baseline chance if no level difference and no modifier + int dispel_chance = 32; //Baseline chance if no level difference and no modifier int level_diff = caster_level - buff_level; if (level_diff > 0) - dispel_chance += level_diff * 8; + dispel_chance += level_diff * 7; else if (level_diff < 0) dispel_chance += level_diff * 2; From 786b8c80fd44b56fb24d03221b716164528a9ae3 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 27 Jun 2014 20:55:17 -0400 Subject: [PATCH 064/288] Udpated SE_ReclaimPet - Correct forumla for mana returned to properly return 75% of actual pet spell mana cost. Implemented SE_ImprovedReclaimEnergy - Modifies % mana returned from SE_ReclaimPet. Required SQL update. --- changelog.txt | 2 ++ common/spdat.h | 6 +++--- .../git/required/2014_06_25_AA_Updates..sql | 3 +++ zone/bonuses.cpp | 19 +++++++++++++++++ zone/client_mods.cpp | 2 +- zone/common.h | 1 + zone/spell_effects.cpp | 21 ++++++++++++------- 7 files changed, 43 insertions(+), 11 deletions(-) diff --git a/changelog.txt b/changelog.txt index a177460ee..e02571f44 100644 --- a/changelog.txt +++ b/changelog.txt @@ -9,6 +9,8 @@ Kayen: Update SE_Taunt - Limit value if present will now add instant hate. Kayen: Implemented SE_MassGroupBuff - Allows next group buff cast to be a MGB (AA now uses this) Kayen: Implemented SE_IllusionOther - Allows next Illusion buff (self only) cast to be cast on target. (AA now uses this) Kayen: Update SE_AETaunt - Base value will now determine AE taunt range (This will not result in any change to currently used spells). +Kayen: Udpated SE_ReclaimPet - Correct forumla for mana returned to properly return 75% of actual pet spell mana cost. +Kayen: Implemented SE_ImprovedReclaimEnergy - Modifies % mana returned from SE_ReclaimPet. Required SQL: utils/sql/git/required/2014_06_25_AA_Update.sql diff --git a/common/spdat.h b/common/spdat.h index 7773a95c4..bb3951019 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -358,7 +358,7 @@ typedef enum { //#define SE_PurgePoison 208 // not used #define SE_DispelBeneficial 209 // implemented //#define SE_PetShield 210 // *not implemented -#define SE_AEMelee 211 // implemented +#define SE_AEMelee 211 // implemented TO DO: Implement to allow NPC use (client only atm). #define SE_FrenziedDevastation 212 // implemented - increase spell criticals + all DD spells cast 2x mana. #define SE_PetMaxHP 213 // implemented[AA] - increases the maximum hit points of your pet #define SE_MaxHPChange 214 // implemented @@ -375,7 +375,7 @@ typedef enum { #define SE_GiveDoubleAttack 225 // implemented[AA] - Allow any class to double attack with set chance. #define SE_TwoHandBash 226 // *not implemented as bonus #define SE_ReduceSkillTimer 227 // implemented -#define SE_ReduceFallDamage 228 // not implented as bonus - reduce the damage that you take from falling +//#define SE_ReduceFallDamage 228 // not implented as bonus - reduce the damage that you take from falling #define SE_PersistantCasting 229 // implemented //#define SE_ExtendedShielding 230 // not used as bonus - increase range of /shield ability #define SE_StunBashChance 231 // implemented - increase chance to stun from bash. @@ -388,7 +388,7 @@ typedef enum { //#define SE_IllusionPersistence 238 // *not implemented - lends persistence to your illusionary disguises, causing them to last until you die or the illusion is forcibly removed. //#define SE_FeignedCastOnChance 239 // *not implemented as bonus - ability gives you an increasing chance for your feigned deaths to not be revealed by spells cast upon you. //#define SE_StringUnbreakable 240 // not used [Likely related to above - you become immune to feign breaking on a resisted spell and have a good chance of feigning through a spell that successfully lands upon you.] -#define SE_ImprovedReclaimEnergy 241 // not implemented as bonus - increase the amount of mana returned to you when reclaiming your pet. +#define SE_ImprovedReclaimEnergy 241 // implemented - increase the amount of mana returned to you when reclaiming your pet. #define SE_IncreaseChanceMemwipe 242 // implemented - increases the chance to wipe hate with memory blurr #define SE_CharmBreakChance 243 // implemented - Total Domination #define SE_RootBreakChance 244 // implemented[AA] reduce the chance that your root will break. diff --git a/utils/sql/git/required/2014_06_25_AA_Updates..sql b/utils/sql/git/required/2014_06_25_AA_Updates..sql index 2e2b7579f..13522e93c 100644 --- a/utils/sql/git/required/2014_06_25_AA_Updates..sql +++ b/utils/sql/git/required/2014_06_25_AA_Updates..sql @@ -6,5 +6,8 @@ UPDATE aa_actions SET spell_id = 5228, nonspell_action = 0 WHERE aaid = 128; UPDATE altadv_vars SET spellid = 5227 WHERE skill_id = 643; UPDATE aa_actions SET spell_id = 5227, nonspell_action = 0 WHERE aaid = 643; +-- AA Improved Reclaim Energy +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('180', '1', '241', '95', '0'); + -- spells_new update ALTER TABLE `spells_new` CHANGE `field175` `numhits_type` INT(11) NOT NULL DEFAULT '0'; \ No newline at end of file diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index f46328ea6..be847b280 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1270,6 +1270,15 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) newbon->Metabolism += base1; break; + case SE_ImprovedReclaimEnergy: + { + if((base1 < 0) && (newbon->ImprovedReclaimEnergy > base1)) + newbon->ImprovedReclaimEnergy = base1; + + else if(newbon->ImprovedReclaimEnergy < base1) + newbon->ImprovedReclaimEnergy = base1; + break; + } } } } @@ -2741,6 +2750,16 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne newbon->Metabolism += effect_value; break; + case SE_ImprovedReclaimEnergy: + { + if((effect_value < 0) && (newbon->ImprovedReclaimEnergy > effect_value)) + newbon->ImprovedReclaimEnergy = effect_value; + + else if(newbon->ImprovedReclaimEnergy < effect_value) + newbon->ImprovedReclaimEnergy = effect_value; + break; + } + //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 955a29d38..7ffc1e797 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1177,7 +1177,7 @@ uint32 Client::CalcCurrentWeight() { Total += (m_pp.platinum + m_pp.gold + m_pp.silver + m_pp.copper) / 4; } - float Packrat = (float)spellbonuses.Packrat + (float)aabonuses.Packrat; + float Packrat = (float)spellbonuses.Packrat + (float)aabonuses.Packrat + (float)itembonuses.Packrat; if (Packrat > 0) Total = (uint32)((float)Total * (1.0f - ((Packrat * 1.0f) / 100.0f))); //AndMetal: 1% per level, up to 5% (calculated from Titanium client). verified thru client that it reduces coin weight by the same % //without casting to float & back to uint32, this didn't work right diff --git a/zone/common.h b/zone/common.h index a8e8a17c9..421474eec 100644 --- a/zone/common.h +++ b/zone/common.h @@ -422,6 +422,7 @@ struct StatBonuses { int8 StunBashChance; // chance to stun with bash. int8 IncreaseChanceMemwipe; // increases chance to memory wipe int8 CriticalMend; // chance critical monk mend + int16 ImprovedReclaimEnergy; // Modifies amount of mana returned from reclaim energy }; typedef struct diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index e3fb89d6f..8eab0b329 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1551,15 +1551,22 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) GetPetType() != petCharmed ) { - int lvlmod = 4; - if(caster->IsClient() && caster->CastToClient()->GetAA(aaImprovedReclaimEnergy)) - lvlmod = 8; //this is an unconfirmed number, I made it up - if(caster->IsClient() && caster->CastToClient()->GetAA(aaImprovedReclaimEnergy2)) - lvlmod = 8; //this is an unconfirmed number, I made it up - caster->SetMana(caster->GetMana()+(GetLevel()*lvlmod)); + uint16 pet_spellid = CastToNPC()->GetPetSpellID(); + uint16 pet_ActSpellCost = caster->GetActSpellCost(pet_spellid, spells[pet_spellid].mana); + int16 ImprovedReclaimMod = caster->spellbonuses.ImprovedReclaimEnergy + + caster->itembonuses.ImprovedReclaimEnergy + + caster->aabonuses.ImprovedReclaimEnergy; + + if (!ImprovedReclaimMod) + ImprovedReclaimMod = 75; //Reclaim Energy default is 75% of actual mana cost + + pet_ActSpellCost = pet_ActSpellCost*ImprovedReclaimMod/100; + + caster->SetMana(caster->GetMana() + pet_ActSpellCost); if(caster->IsClient()) caster->CastToClient()->SetPet(0); + SetOwnerID(0); // this will kill the pet } break; @@ -5804,7 +5811,7 @@ bool Mob::TryDispel(uint8 caster_level, uint8 buff_level, int level_modifier){ /*This should provide a somewhat accurate conversion between pre 5/14 base values and post. until more information is avialble - Kayen*/ - if (level_modifier > 100) + if (level_modifier >= 100) level_modifier = level_modifier/100; //Dispels - Check level of caster agianst buffs level (level of the caster who cast the buff) From 25c20f062974508429f6e08b8db7b6bedd917475 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 29 Jun 2014 01:10:19 -0400 Subject: [PATCH 065/288] Implemented SE_HeadShot, SE_HeadShotLevel - Defines headshot damage and level requirements. Revised HeadShot mechanic so damage now recieves all archery bonuses, proc chance can be set to either (lives new Proc Per minute system, or flat chance based on dex (formula updated). Required SQL for AA data Optional SQL for rules --- changelog.txt | 4 + common/ruletypes.h | 2 + common/spdat.h | 8 +- .../git/optional/2014_06_29_HeadShotRules.sql | 2 + .../git/required/2014_06_25_AA_Updates..sql | 4 + zone/bonuses.cpp | 73 ++++++++++++- zone/client_mods.cpp | 2 +- zone/common.h | 7 +- zone/mob.h | 3 +- zone/special_attacks.cpp | 101 ++++++++++++++---- zone/spell_effects.cpp | 2 + 11 files changed, 176 insertions(+), 32 deletions(-) create mode 100644 utils/sql/git/optional/2014_06_29_HeadShotRules.sql diff --git a/changelog.txt b/changelog.txt index e02571f44..43c045ce8 100644 --- a/changelog.txt +++ b/changelog.txt @@ -11,8 +11,12 @@ Kayen: Implemented SE_IllusionOther - Allows next Illusion buff (self only) cast Kayen: Update SE_AETaunt - Base value will now determine AE taunt range (This will not result in any change to currently used spells). Kayen: Udpated SE_ReclaimPet - Correct forumla for mana returned to properly return 75% of actual pet spell mana cost. Kayen: Implemented SE_ImprovedReclaimEnergy - Modifies % mana returned from SE_ReclaimPet. +Kayen: Implemented SE_HeadShot, SE_HeadShotLevel - Defines headshot damage and level requirements. +Revised HeadShot mechanic so damage now recieves all archery bonuses, proc chance can be set to either (lives new Proc Per minute +system, or flat chance based on dex (formula updated). Required SQL: utils/sql/git/required/2014_06_25_AA_Update.sql +Optional SQL: utils/sql/git/optiional/2014_06_29_HeadShotRules.sql == 06/17/2014 == diff --git a/common/ruletypes.h b/common/ruletypes.h index 70e4ba0d2..6f5fe0769 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -333,6 +333,8 @@ RULE_REAL ( Combat, AvgProcsPerMinute, 2.0) RULE_REAL ( Combat, ProcPerMinDexContrib, 0.075) RULE_REAL ( Combat, BaseProcChance, 0.035) RULE_REAL ( Combat, ProcDexDivideBy, 11000) +RULE_BOOL ( Combat, AdjustSpecialProcPerMinute, true) //Set PPM for special abilities like HeadShot (Live does this as of 4-14) +RULE_REAL ( Combat, AvgSpecialProcsPerMinute, 2.0) //Unclear what best value is atm. RULE_REAL ( Combat, BaseHitChance, 69.0) RULE_REAL ( Combat, NPCBonusHitChance, 26.0) RULE_REAL ( Combat, HitFalloffMinor, 5.0) //hit will fall off up to 5% over the initial level range diff --git a/common/spdat.h b/common/spdat.h index bb3951019..65bb9f692 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -364,7 +364,7 @@ typedef enum { #define SE_MaxHPChange 214 // implemented #define SE_PetAvoidance 215 // implemented[AA] - increases pet ability to avoid melee damage #define SE_Accuracy 216 // implemented -//#define SE_HeadShot 217 // not implemented as bonus - ability to head shot (base2 = damage) +#define SE_HeadShot 217 // implemented - ability to head shot (base2 = damage) #define SE_PetCriticalHit 218 // implemented[AA] - gives pets a baseline critical hit chance #define SE_SlayUndead 219 // implemented - Allow extra damage against undead (base1 = rate, base2 = damage mod). #define SE_SkillDamageAmount 220 // implemented @@ -492,8 +492,8 @@ typedef enum { #define SE_ImmuneFleeing 342 // implemented - stop mob from fleeing #define SE_InterruptCasting 343 // implemented - % chance to interrupt spells being cast every tic. Cacophony (8272) #define SE_ChannelChanceItems 344 // implemented[AA] - chance to not have ITEM effects interrupted when you take damage. -//#define SE_AssassinationLevel 345 // not implemented as bonus - AA Assisination max level to kill -//#define SE_HeadShotLevel 346 // not implemented as bonus - AA HeadShot max level to kill +#define SE_AssassinateLevel 345 // implemented as bonus - AA Assisination max level to kill +#define SE_HeadShotLevel 346 // implemented[AA] - HeadShot max level to kill #define SE_DoubleRangedAttack 347 // implemented - chance at an additional archery attack (consumes arrow) #define SE_LimitManaMin 348 // implemented #define SE_ShieldEquipHateMod 349 // implemented[AA] Increase melee hate when wearing a shield. @@ -586,7 +586,7 @@ typedef enum { //#define SE_BeneficialCountDownHold 436 // not used ( 23491 | ABTest Buff Hold) //#define SE_TeleporttoAnchor 437 // *not implemented - Teleport Guild Hall Anchor(33099) //#define SE_TranslocatetoAnchor 438 // *not implemented - Translocate Primary Anchor (27750) -//#define SE_IncreaseAssassinationLvl 439 // *not implemented[AA] - increases the maximum level of humanoid that can be affected by assassination +#define SE_Assassinate 439 // implemented[AA] - Assassinate damage #define SE_FinishingBlowLvl 440 // implemented[AA] - Sets the level Finishing blow can be triggered on an NPC #define SE_DistanceRemoval 441 // implemented - Buff is removed from target when target moves X amount of distance away from where initially hit. #define SE_TriggerOnReqTarget 442 // implemented - triggers a spell which a certain criteria are met (below X amount of hp,mana,end, number of pets on hatelist) diff --git a/utils/sql/git/optional/2014_06_29_HeadShotRules.sql b/utils/sql/git/optional/2014_06_29_HeadShotRules.sql new file mode 100644 index 000000000..ad3de19b6 --- /dev/null +++ b/utils/sql/git/optional/2014_06_29_HeadShotRules.sql @@ -0,0 +1,2 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Combat:AdjustSpecialProcPerMinute', 'false', 'Allow PPM for special abilities HeadShot, Assassinate, Decap ect.'); +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Combat:AvgSpecialProcsPerMinute', '2.0', 'Set PPM for special abilities HeadShot, Assassinate, Decap ect. (Unknown what value live uses) .'); \ No newline at end of file diff --git a/utils/sql/git/required/2014_06_25_AA_Updates..sql b/utils/sql/git/required/2014_06_25_AA_Updates..sql index 13522e93c..c9ae42237 100644 --- a/utils/sql/git/required/2014_06_25_AA_Updates..sql +++ b/utils/sql/git/required/2014_06_25_AA_Updates..sql @@ -9,5 +9,9 @@ UPDATE aa_actions SET spell_id = 5227, nonspell_action = 0 WHERE aaid = 643; -- AA Improved Reclaim Energy INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('180', '1', '241', '95', '0'); +-- AA Headshot +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('644', '1', '217', '0', '32000'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('644', '2', '346', '46', '0'); + -- spells_new update ALTER TABLE `spells_new` CHANGE `field175` `numhits_type` INT(11) NOT NULL DEFAULT '0'; \ No newline at end of file diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index be847b280..345f602f8 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -637,7 +637,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) continue; _log(AA__BONUSES, "Applying Effect %d from AA %u in slot %d (base1: %d, base2: %d) on %s", effect, aaid, slot, base1, base2, this->GetCleanName()); - + uint8 focus = IsFocusEffect(0, 0, true,effect); if (focus) { @@ -1279,6 +1279,23 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) newbon->ImprovedReclaimEnergy = base1; break; } + + case SE_HeadShot: + { + if(newbon->HeadShot[1] < base2){ + newbon->HeadShot[0] = base1; + newbon->HeadShot[1] = base2; + } + break; + } + + case SE_HeadShotLevel: + { + if(newbon->HSLevel < base1) + newbon->HSLevel = base1; + break; + } + } } } @@ -2760,6 +2777,38 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne break; } + case SE_HeadShot: + { + if(newbon->HeadShot[1] < base2){ + newbon->HeadShot[0] = effect_value; + newbon->HeadShot[1] = base2; + } + break; + } + + case SE_HeadShotLevel: + { + if(newbon->HSLevel < effect_value) + newbon->HSLevel = effect_value; + break; + } + + case SE_Assassinate: + { + if(newbon->Assassinate[1] < base2){ + newbon->Assassinate[0] = effect_value; + newbon->Assassinate[1] = base2; + } + break; + } + + case SE_AssassinateLevel: + { + if(newbon->AssassinateLevel < effect_value) + newbon->AssassinateLevel = effect_value; + break; + } + //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { @@ -4173,7 +4222,27 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) aabonuses.Metabolism = effect_value; itembonuses.Metabolism = effect_value; break; - + + case SE_ImprovedReclaimEnergy: + spellbonuses.ImprovedReclaimEnergy = effect_value; + aabonuses.ImprovedReclaimEnergy = effect_value; + itembonuses.ImprovedReclaimEnergy = effect_value; + break; + + case SE_HeadShot: + spellbonuses.HeadShot[0] = effect_value; + aabonuses.HeadShot[0] = effect_value; + itembonuses.HeadShot[0] = effect_value; + spellbonuses.HeadShot[1] = effect_value; + aabonuses.HeadShot[1] = effect_value; + itembonuses.HeadShot[1] = effect_value; + break; + + case SE_HeadShotLevel: + spellbonuses.HSLevel = effect_value; + aabonuses.HSLevel = effect_value; + itembonuses.HSLevel = effect_value; + } } } diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 7ffc1e797..3bf2217cb 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1864,7 +1864,7 @@ uint16 Mob::GetInstrumentMod(uint16 spell_id) const break; } - effectmodcap += aabonuses.songModCap + spellbonuses.songModCap; + effectmodcap += aabonuses.songModCap + spellbonuses.songModCap + itembonuses.songModCap; if (effectmod < 10) effectmod = 10; diff --git a/zone/common.h b/zone/common.h index 421474eec..95f1df783 100644 --- a/zone/common.h +++ b/zone/common.h @@ -422,7 +422,12 @@ struct StatBonuses { int8 StunBashChance; // chance to stun with bash. int8 IncreaseChanceMemwipe; // increases chance to memory wipe int8 CriticalMend; // chance critical monk mend - int16 ImprovedReclaimEnergy; // Modifies amount of mana returned from reclaim energy + int16 ImprovedReclaimEnergy; // Modifies amount of mana returned from reclaim energy + int32 HeadShot[2]; // Headshot AA (Massive dmg vs humaniod w/ archery) 0= ? 1= Dmg + uint8 HSLevel; // Max Level Headshot will be effective at. + int32 Assassinate[2]; // Assassinate AA (Massive dmg vs humaniod w/ assassinate) 0= ? 1= Dmg + uint8 AssassinateLevel; // Max Level Assassinate will be effective at. + }; typedef struct diff --git a/zone/mob.h b/zone/mob.h index 61a2220d6..b5e21c932 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -141,7 +141,7 @@ public: virtual void TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttackOptions *opts = nullptr); void TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage); virtual bool TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse); - virtual bool TryHeadShot(Mob* defender, SkillUseTypes skillInUse); + uint32 TryHeadShot(Mob* defender, SkillUseTypes skillInUse); virtual void DoRiposte(Mob* defender); void ApplyMeleeDamageBonus(uint16 skill, int32 &damage); virtual void MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttackOptions *opts = nullptr); @@ -991,6 +991,7 @@ protected: void ExecWeaponProc(const ItemInst* weapon, uint16 spell_id, Mob *on); virtual float GetProcChances(float ProcBonus, uint16 weapon_speed = 30, uint16 hand = 13); virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 weapon_speed = 30, uint16 hand = 13); + virtual float GetSpecialProcChances(uint16 hand = 13); int GetWeaponDamage(Mob *against, const Item_Struct *weapon_item); int GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate = nullptr); int GetKickDamage(); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index f9f324b6d..55e919bc3 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -861,8 +861,12 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item } else { mlog(COMBAT__RANGED, "Ranged attack hit %s.", other->GetName()); - if(!TryHeadShot(other, SkillArchery)) - { + + bool HeadShot = false; + uint32 HeadShot_Dmg = TryHeadShot(other, SkillArchery); + if (HeadShot_Dmg) + HeadShot = true; + int32 TotalDmg = 0; int16 WDmg = 0; int16 ADmg = 0; @@ -882,6 +886,9 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item uint32 MaxDmg = (RuleR(Combat, ArcheryBaseDamageBonus)*(WDmg+ADmg)*GetDamageTable(SkillArchery)) / 100; int32 hate = ((WDmg+ADmg)); + if (HeadShot) + MaxDmg = HeadShot_Dmg; + uint16 bonusArcheryDamageModifier = aabonuses.ArcheryDamageModifier + itembonuses.ArcheryDamageModifier + spellbonuses.ArcheryDamageModifier; MaxDmg += MaxDmg*bonusArcheryDamageModifier / 100; @@ -938,7 +945,9 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item hate += (2*((GetLevel()-25)/3)); } - other->AvoidDamage(this, TotalDmg, false); + if (!HeadShot) + other->AvoidDamage(this, TotalDmg, false); + other->MeleeMitigation(this, TotalDmg, minDmg); if(TotalDmg > 0) { @@ -957,8 +966,11 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item else TotalDmg = -5; + if (HeadShot) + entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FATAL_BOW_SHOT, GetName()); + other->Damage(this, TotalDmg, SPELL_UNKNOWN, SkillArchery); - } + } //try proc on hits and misses @@ -2074,30 +2086,73 @@ void Mob::InstillDoubt(Mob *who) { } } -bool Mob::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) { - bool Result = false; +uint32 Mob::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) { - if(defender && skillInUse == SkillArchery) { - if(GetAA(aaHeadshot) && defender->GetBodyType() == BT_Humanoid) { - if((GetLevelCon(GetLevel(), defender->GetLevel()) == CON_LIGHTBLUE || GetLevelCon(GetLevel(), defender->GetLevel()) == CON_GREEN) && defender->GetLevel() <= 60 && !defender->IsClient()) { - // WildcardX: These chance formula's below are arbitrary. If someone has a better formula that is more - // consistent with live, feel free to update these. - int AttackerChance = 20 + ((GetLevel() - 51) / 2) + (itembonuses.HeroicDEX / 10); - int DefenderChance = MakeRandomInt(0, 100); - if(AttackerChance > DefenderChance) { - mlog(COMBAT__ATTACKS, "Landed a headshot: Attacker chance was %f and Defender chance was %f.", AttackerChance, DefenderChance); - entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FATAL_BOW_SHOT, GetName()); - defender->Damage(this, 32000, SPELL_UNKNOWN, skillInUse); - Result = true; - } - else { - mlog(COMBAT__ATTACKS, "FAILED a headshot: Attacker chance was %f and Defender chance was %f.", AttackerChance, DefenderChance); - } + //Only works on YOUR target. + if(defender && (skillInUse == SkillArchery) && (GetTarget() == defender)) { + + int32 HeadShot_Dmg = aabonuses.HeadShot[1] + spellbonuses.HeadShot[1] + itembonuses.HeadShot[1]; + + uint8 HeadShot_Level = 0; //Get Highest Headshot Level + HeadShot_Level = aabonuses.HSLevel; + if (HeadShot_Level < spellbonuses.HSLevel) + HeadShot_Level = spellbonuses.HSLevel; + else if (HeadShot_Level < itembonuses.HSLevel) + HeadShot_Level = itembonuses.HSLevel; + + if(HeadShot_Dmg && defender->GetBodyType() == BT_Humanoid) { + if(HeadShot_Level && (defender->GetLevel() <= HeadShot_Level) && !defender->IsClient()){ + + float ProcChance = GetSpecialProcChances(11); + if(ProcChance > MakeRandomFloat(0,1)) + return HeadShot_Dmg; + } } } - return Result; + return 0; +} + +float Mob::GetSpecialProcChances(uint16 hand) +{ + int mydex = GetDEX(); + + if (mydex > 255) + mydex = 255; + + uint16 weapon_speed; + float ProcChance = 0.0f; + float ProcBonus = 0.0f; + + switch (hand) { + case 13: + weapon_speed = attack_timer.GetDuration(); + break; + case 14: + weapon_speed = attack_dw_timer.GetDuration(); + break; + case 11: + weapon_speed = ranged_timer.GetDuration(); + break; + } + + if (weapon_speed < RuleI(Combat, MinHastedDelay)) + weapon_speed = RuleI(Combat, MinHastedDelay); + + if (RuleB(Combat, AdjustSpecialProcPerMinute)) { + ProcChance = (static_cast(weapon_speed) * + RuleR(Combat, AvgSpecialProcsPerMinute) / 60000.0f); + ProcBonus += static_cast(mydex/35) + static_cast(itembonuses.HeroicDEX / 25); + ProcChance += ProcChance * ProcBonus / 100.0f; + } else { + /*PRE 2014 CHANGE Dev Quote - "Elidroth SOE:Proc chance is a function of your base hardcapped Dexterity / 35 + Heroic Dexterity / 25.” + Kayen: Most reports suggest a ~ 6% chance to Headshot which consistent with above.*/ + + ProcChance = (static_cast(mydex/35) + static_cast(itembonuses.HeroicDEX / 25))/100.0f; + } + + return ProcChance; } void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod, int16 focus, bool CanRiposte) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 8eab0b329..51979eddc 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2922,6 +2922,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_CombatStability: case SE_AddSingingMod: case SE_SongModCap: + case SE_HeadShot: + case SE_HeadShotLevel: case SE_PetAvoidance: case SE_GiveDoubleRiposte: case SE_Ambidexterity: From 2afa08e361a2cfd0f173c2a4d3bd5dd484867e75 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 29 Jun 2014 23:26:22 -0400 Subject: [PATCH 066/288] Implemented SE_Assassinate, SE_AssassinateLevel - Defines assassinate damage and level requirements. Revised Assassinate mechanic so damage now receives all backstab bonuses, proc chance can be set to either (lives new Proc Per minute system, or flat chance based on dex (formula updated). Assassinate can now proc from THROW if behind target, various other adjustments. Required SQL for AA updates --- changelog.txt | 5 +- .../git/required/2014_06_25_AA_Updates..sql | 10 +- zone/bonuses.cpp | 16 ++ zone/common.h | 4 +- zone/mob.h | 6 +- zone/special_attacks.cpp | 263 ++++++++---------- 6 files changed, 157 insertions(+), 147 deletions(-) diff --git a/changelog.txt b/changelog.txt index 43c045ce8..53585d982 100644 --- a/changelog.txt +++ b/changelog.txt @@ -12,8 +12,11 @@ Kayen: Update SE_AETaunt - Base value will now determine AE taunt range (This wi Kayen: Udpated SE_ReclaimPet - Correct forumla for mana returned to properly return 75% of actual pet spell mana cost. Kayen: Implemented SE_ImprovedReclaimEnergy - Modifies % mana returned from SE_ReclaimPet. Kayen: Implemented SE_HeadShot, SE_HeadShotLevel - Defines headshot damage and level requirements. -Revised HeadShot mechanic so damage now recieves all archery bonuses, proc chance can be set to either (lives new Proc Per minute +Revised HeadShot mechanic so damage now receives all archery bonuses, proc chance can be set to either (lives new Proc Per minute system, or flat chance based on dex (formula updated). +Kayen: Implemented SE_Assassinate, SE_AssassinateLevel - Defines assassinate damage and level requirements. +Revised Assassinate mechanic so damage now receives all backstab bonuses, proc chance can be set to either (lives new Proc Per minute +system, or flat chance based on dex (formula updated). Assassinate can now proc from THROW if behind target, various other adjustments. Required SQL: utils/sql/git/required/2014_06_25_AA_Update.sql Optional SQL: utils/sql/git/optiional/2014_06_29_HeadShotRules.sql diff --git a/utils/sql/git/required/2014_06_25_AA_Updates..sql b/utils/sql/git/required/2014_06_25_AA_Updates..sql index c9ae42237..d51948af9 100644 --- a/utils/sql/git/required/2014_06_25_AA_Updates..sql +++ b/utils/sql/git/required/2014_06_25_AA_Updates..sql @@ -13,5 +13,11 @@ INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ( INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('644', '1', '217', '0', '32000'); INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('644', '2', '346', '46', '0'); --- spells_new update -ALTER TABLE `spells_new` CHANGE `field175` `numhits_type` INT(11) NOT NULL DEFAULT '0'; \ No newline at end of file +-- AA Anatomy (Rogue Assassinate) +INSERT INTO `altadv_vars` (`skill_id`, `name`, `cost`, `max_level`, `hotkey_sid`, `hotkey_sid2`, `title_sid`, `desc_sid`, `type`, `spellid`, `prereq_skill`, `prereq_minpoints`, `spell_type`, `spell_refresh`, `classes`, `berserker`, `class_type`, `cost_inc`, `aa_expansion`, `special_category`, `sof_type`, `sof_cost_inc`, `sof_max_level`, `sof_next_skill`, `clientver`, `account_time_required`, `sof_current_level`,`sof_next_id`,`level_inc`) VALUES ('1604', 'Anatomy', '5', '3', '4294967295', '4294967295', '1604', '1604', '1', '4294967295', '0', '0', '0', '0', '512', '0', '60', '1', '10', '4294967295', '3', '0', '3', '1604', '1', '0', '0', '0', '0'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1604', '1', '439', '0', '32000'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1604', '2', '345', '48', '0'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1605', '1', '439', '0', '32000'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1605', '2', '345', '51', '0'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1606', '1', '439', '0', '32000'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1606', '2', '345', '53', '0'); \ No newline at end of file diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 345f602f8..0871e3679 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1296,6 +1296,22 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) break; } + case SE_Assassinate: + { + if(newbon->Assassinate[1] < base2){ + newbon->Assassinate[0] = base1; + newbon->Assassinate[1] = base2; + } + break; + } + + case SE_AssassinateLevel: + { + if(newbon->AssassinateLevel < base1) + newbon->AssassinateLevel = base1; + break; + } + } } } diff --git a/zone/common.h b/zone/common.h index 95f1df783..6d6ae581f 100644 --- a/zone/common.h +++ b/zone/common.h @@ -423,9 +423,9 @@ struct StatBonuses { int8 IncreaseChanceMemwipe; // increases chance to memory wipe int8 CriticalMend; // chance critical monk mend int16 ImprovedReclaimEnergy; // Modifies amount of mana returned from reclaim energy - int32 HeadShot[2]; // Headshot AA (Massive dmg vs humaniod w/ archery) 0= ? 1= Dmg + uint32 HeadShot[2]; // Headshot AA (Massive dmg vs humaniod w/ archery) 0= ? 1= Dmg uint8 HSLevel; // Max Level Headshot will be effective at. - int32 Assassinate[2]; // Assassinate AA (Massive dmg vs humaniod w/ assassinate) 0= ? 1= Dmg + uint32 Assassinate[2]; // Assassinate AA (Massive dmg vs humaniod w/ assassinate) 0= ? 1= Dmg uint8 AssassinateLevel; // Max Level Assassinate will be effective at. }; diff --git a/zone/mob.h b/zone/mob.h index b5e21c932..5c1240e83 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -142,6 +142,7 @@ public: void TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage); virtual bool TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse); uint32 TryHeadShot(Mob* defender, SkillUseTypes skillInUse); + uint32 TryAssassinate(Mob* defender, SkillUseTypes skillInUse, uint16 ReuseTime); virtual void DoRiposte(Mob* defender); void ApplyMeleeDamageBonus(uint16 skill, int32 &damage); virtual void MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttackOptions *opts = nullptr); @@ -694,7 +695,7 @@ public: int32 AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTic, Mob* attacker); int32 ReduceAllDamage(int32 damage); - virtual void DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance=false); + virtual void DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance=false, bool CanAvoid=true); virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const Item_Struct* item=nullptr, uint16 weapon_damage=0, int16 chance_mod=0,int16 focus=0); virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod=0, int16 focus=0, bool CanRiposte=false); virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const ItemInst* Ammo=nullptr, uint16 weapon_damage=0, int16 chance_mod=0, int16 focus=0); @@ -991,7 +992,8 @@ protected: void ExecWeaponProc(const ItemInst* weapon, uint16 spell_id, Mob *on); virtual float GetProcChances(float ProcBonus, uint16 weapon_speed = 30, uint16 hand = 13); virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 weapon_speed = 30, uint16 hand = 13); - virtual float GetSpecialProcChances(uint16 hand = 13); + virtual float GetSpecialProcChances(uint16 hand); + virtual float GetAssassinateProcChances(uint16 ReuseTime); int GetWeaponDamage(Mob *against, const Item_Struct *weapon_item); int GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate = nullptr); int GetKickDamage(); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 55e919bc3..4ffa21ab4 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -100,7 +100,8 @@ void Mob::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg) } } -void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage, int32 hate_override,int ReuseTime, bool HitChance) { +void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage, int32 hate_override,int ReuseTime, + bool HitChance, bool CanAvoid) { //this really should go through the same code as normal melee damage to //pick up all the special behavior there @@ -135,7 +136,9 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, if(skill == SkillThrowing || skill == SkillArchery) // changed from '&&' CanRiposte = false; - who->AvoidDamage(this, max_damage, CanRiposte); + if (CanAvoid) + who->AvoidDamage(this, max_damage, CanRiposte); + who->MeleeMitigation(this, max_damage, min_damage); if(max_damage > 0) { @@ -373,8 +376,8 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { if (ca_atk->m_atk != 100 || ca_atk->m_skill != SkillBackstab) { break; } - TryBackstab(GetTarget(), ReuseTime); ReuseTime = BackstabReuseTime-1 - skill_reduction; + TryBackstab(GetTarget(), ReuseTime); break; } default: @@ -527,64 +530,47 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { if (FrontalBSChance && (FrontalBSChance > MakeRandomInt(0, 100))) bCanFrontalBS = true; } - + if (bIsBehind || bCanFrontalBS){ // Player is behind other OR can do Frontal Backstab - if (bCanFrontalBS) { + if (bCanFrontalBS) CastToClient()->Message(0,"Your fierce attack is executed with such grace, your target did not see it coming!"); - } + + RogueBackstab(other,false,ReuseTime); + if (level > 54) { - // solar - chance to assassinate - int chance = 10 + (GetDEX()/10) + (itembonuses.HeroicDEX/10); //18.5% chance at 85 dex 40% chance at 300 dex - if( - level >= 60 && // player is 60 or higher - other->GetLevel() <= 45 && // mob 45 or under - !other->CastToNPC()->IsEngaged() && // not aggro - other->GetHP()<=32000 - && other->IsNPC() - && MakeRandomFloat(0, 99) < chance // chance - ) { - entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, GetName()); - if(IsClient()) - CastToClient()->CheckIncreaseSkill(SkillBackstab, other, 10); - RogueAssassinate(other); - } - else { - RogueBackstab(other); - if (level > 54) { - float DoubleAttackProbability = (GetSkill(SkillDoubleAttack) + GetLevel()) / 500.0f; // 62.4 max - // Check for double attack with main hand assuming maxed DA Skill (MS) + if(IsClient() && CastToClient()->CheckDoubleAttack(false)) + { + if(other->GetHP() > 0) + RogueBackstab(other,false,ReuseTime); - if(MakeRandomFloat(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA - { - if(other->GetHP() > 0) - RogueBackstab(other,false,ReuseTime); - - if (tripleChance && other->GetHP() > 0 && tripleChance > MakeRandomInt(0, 100)) - RogueBackstab(other,false,ReuseTime); - } + if (tripleChance && other->GetHP() > 0 && tripleChance > MakeRandomInt(0, 100)) + RogueBackstab(other,false,ReuseTime); } - if(IsClient()) - CastToClient()->CheckIncreaseSkill(SkillBackstab, other, 10); } + + if(IsClient()) + CastToClient()->CheckIncreaseSkill(SkillBackstab, other, 10); + } //Live AA - Chaotic Backstab else if(aabonuses.FrontalBackstabMinDmg || itembonuses.FrontalBackstabMinDmg || spellbonuses.FrontalBackstabMinDmg) { //we can stab from any angle, we do min damage though. - RogueBackstab(other, true); + RogueBackstab(other, true, ReuseTime); if (level > 54) { - float DoubleAttackProbability = (GetSkill(SkillDoubleAttack) + GetLevel()) / 500.0f; // 62.4 max - if(IsClient()) - CastToClient()->CheckIncreaseSkill(SkillBackstab, other, 10); + // Check for double attack with main hand assuming maxed DA Skill (MS) - if(MakeRandomFloat(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA + if(IsClient() && CastToClient()->CheckDoubleAttack(false)) if(other->GetHP() > 0) RogueBackstab(other,true, ReuseTime); if (tripleChance && other->GetHP() > 0 && tripleChance > MakeRandomInt(0, 100)) RogueBackstab(other,false,ReuseTime); } + + if(IsClient()) + CastToClient()->CheckIncreaseSkill(SkillBackstab, other, 10); } else { //We do a single regular attack if we attack from the front without chaotic stab Attack(other, 13); @@ -594,6 +580,9 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { //heko: backstab void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) { + if (!other) + return; + int32 ndamage = 0; int32 max_hit = 0; int32 min_hit = 0; @@ -668,12 +657,20 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) } ndamage = mod_backstab_damage(ndamage); + + uint32 Assassinate_Dmg = 0; + Assassinate_Dmg = TryAssassinate(other, SkillBackstab, ReuseTime); + + if (Assassinate_Dmg) { + ndamage = Assassinate_Dmg; + entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, GetName()); + } - DoSpecialAttackDamage(other, SkillBackstab, ndamage, min_hit, hate, ReuseTime); + DoSpecialAttackDamage(other, SkillBackstab, ndamage, min_hit, hate, ReuseTime, false, false); DoAnim(animPiercing); } -// solar - assassinate +// solar - assassinate [Kayen: No longer used for regular assassinate 6-29-14] void Mob::RogueAssassinate(Mob* other) { //can you dodge, parry, etc.. an assassinate?? @@ -1276,13 +1273,24 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite int32 TotalDmg = 0; + uint32 Assassinate_Dmg = 0; + if (GetClass() == ROGUE && (BehindMob(other, GetX(), GetY()))) + Assassinate_Dmg = TryAssassinate(other, SkillThrowing, ranged_timer.GetDuration()); + if(WDmg > 0) { int minDmg = 1; uint16 MaxDmg = GetThrownDamage(WDmg, TotalDmg, minDmg); + if (Assassinate_Dmg) { + TotalDmg = Assassinate_Dmg; + entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, GetName()); + } + mlog(COMBAT__RANGED, "Item DMG %d. Max Damage %d. Hit for damage %d", WDmg, MaxDmg, TotalDmg); - other->AvoidDamage(this, TotalDmg, false); //CanRiposte=false - Can not riposte throw attacks. + if (!Assassinate_Dmg) + other->AvoidDamage(this, TotalDmg, false); //CanRiposte=false - Can not riposte throw attacks. + other->MeleeMitigation(this, TotalDmg, minDmg); if(TotalDmg > 0) { @@ -1866,92 +1874,6 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) } } -/* -void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus) { - - if (who == nullptr) - return; - - if(DivineAura()) - return; - - if(!CombatRange(who)) - return; - - if(!always_succeed && IsClient()) - CastToClient()->CheckIncreaseSkill(TAUNT, who, 10); - - int level = GetLevel(); - Mob *hate_top = who->GetHateMost(); - - // Check to see if we're already at the top of the target's hate list - // a mob will not be taunted if its target's health is below 20% - if ((hate_top != this) - && (who->GetLevel() < level) - && (hate_top == nullptr || hate_top->GetHPRatio() >= 20) ) { - int32 newhate, tauntvalue; - - float tauntchance; - if(always_succeed) { - tauntchance = 101; - } else { - - // no idea how taunt success is actually calculated - // TODO: chance for level 50+ mobs should be lower - int level_difference = level - who->GetLevel(); - if (level_difference <= 5) { - tauntchance = 25.0; // minimum - tauntchance += tauntchance * (float)GetSkill(TAUNT) / 200.0; // skill modifier - if (tauntchance > 65.0) - tauntchance = 65.0; - } - else if (level_difference <= 10) { - tauntchance = 30.0; // minimum - tauntchance += tauntchance * (float)GetSkill(TAUNT) / 200.0; // skill modifier - if (tauntchance > 85.0) - tauntchance = 85.0; - } - else if (level_difference <= 15) { - tauntchance = 40.0; // minimum - tauntchance += tauntchance * (float)GetSkill(TAUNT) / 200.0; // skill modifier - if (tauntchance > 90.0) - tauntchance = 90.0; - } - else { - tauntchance = 50.0; // minimum - tauntchance += tauntchance * (float)GetSkill(TAUNT) / 200.0; // skill modifier - if (tauntchance > 95.0) - tauntchance = 95.0; - } - } - - if (chance_bonus) - tauntchance = tauntchance + (tauntchance*chance_bonus/100.0f); - - if (tauntchance > MakeRandomFloat(0, 100)) { - // this is the max additional hate added per succesfull taunt - tauntvalue = (MakeRandomInt(2, 4) * level); - //tauntvalue = (int32) ((float)level * 10.0 * (float)rand()/(float)RAND_MAX + 1); - // new hate: find diff of player's hate and whoever's at top of list, add that plus tauntvalue to players hate - newhate = who->GetNPCHate(hate_top) - who->GetNPCHate(this) + tauntvalue; - // add the hate - who->CastToNPC()->AddToHateList(this, newhate); - } - else{ - //generate at least some hate reguardless of the outcome. - who->CastToNPC()->AddToHateList(this, (MakeRandomInt(2, 4)*level)); - } - } - - //generate at least some hate reguardless of the outcome. - who->CastToNPC()->AddToHateList(this, (MakeRandomInt(2, 4)*level)); - if (HasSkillProcs()){ - float chance = (float)TauntReuseTime*RuleR(Combat, AvgProcsPerMinute)/60000.0f; - TrySkillProc(who, TAUNT, chance); - } -} -*/ - void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus) { if (who == nullptr) @@ -2089,9 +2011,10 @@ void Mob::InstillDoubt(Mob *who) { uint32 Mob::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) { //Only works on YOUR target. - if(defender && (skillInUse == SkillArchery) && (GetTarget() == defender)) { + if(defender && (defender->GetBodyType() == BT_Humanoid) && !defender->IsClient() + && (skillInUse == SkillArchery) && (GetTarget() == defender)) { - int32 HeadShot_Dmg = aabonuses.HeadShot[1] + spellbonuses.HeadShot[1] + itembonuses.HeadShot[1]; + uint32 HeadShot_Dmg = aabonuses.HeadShot[1] + spellbonuses.HeadShot[1] + itembonuses.HeadShot[1]; uint8 HeadShot_Level = 0; //Get Highest Headshot Level HeadShot_Level = aabonuses.HSLevel; @@ -2100,14 +2023,11 @@ uint32 Mob::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) { else if (HeadShot_Level < itembonuses.HSLevel) HeadShot_Level = itembonuses.HSLevel; - if(HeadShot_Dmg && defender->GetBodyType() == BT_Humanoid) { - if(HeadShot_Level && (defender->GetLevel() <= HeadShot_Level) && !defender->IsClient()){ + if(HeadShot_Dmg && HeadShot_Level && (defender->GetLevel() <= HeadShot_Level)){ - float ProcChance = GetSpecialProcChances(11); - if(ProcChance > MakeRandomFloat(0,1)) - return HeadShot_Dmg; - - } + float ProcChance = GetSpecialProcChances(11); + if(ProcChance > MakeRandomFloat(0,1)) + return HeadShot_Dmg; } } @@ -2119,7 +2039,7 @@ float Mob::GetSpecialProcChances(uint16 hand) int mydex = GetDEX(); if (mydex > 255) - mydex = 255; + mydex = 255; uint16 weapon_speed; float ProcChance = 0.0f; @@ -2155,6 +2075,69 @@ float Mob::GetSpecialProcChances(uint16 hand) return ProcChance; } +uint32 Mob::TryAssassinate(Mob* defender, SkillUseTypes skillInUse, uint16 ReuseTime) { + + if(defender && (defender->GetBodyType() == BT_Humanoid) && !defender->IsClient() && + (skillInUse == SkillBackstab || skillInUse == SkillThrowing)) { + + uint32 Assassinate_Dmg = aabonuses.Assassinate[1] + spellbonuses.Assassinate[1] + itembonuses.Assassinate[1]; + + uint8 Assassinate_Level = 0; //Get Highest Headshot Level + Assassinate_Level = aabonuses.AssassinateLevel; + if (Assassinate_Level < spellbonuses.AssassinateLevel) + Assassinate_Level = spellbonuses.AssassinateLevel; + else if (Assassinate_Level < itembonuses.AssassinateLevel) + Assassinate_Level = itembonuses.AssassinateLevel; + + if (GetLevel() >= 60){ //Innate Assassinate Ability if client as no bonuses. + if (!Assassinate_Level) + Assassinate_Level = 45; + + if (!Assassinate_Dmg) + Assassinate_Dmg = 32000; + } + + if(Assassinate_Dmg && Assassinate_Level && (defender->GetLevel() <= Assassinate_Level)){ + float ProcChance = 0.0f; + + if (skillInUse == SkillThrowing) + ProcChance = GetSpecialProcChances(11); + else + ProcChance = GetAssassinateProcChances(ReuseTime); + + if(ProcChance > MakeRandomFloat(0,1)) + return Assassinate_Dmg; + } + } + + return 0; +} + +float Mob::GetAssassinateProcChances(uint16 ReuseTime) +{ + int mydex = GetDEX(); + + if (mydex > 255) + mydex = 255; + + float ProcChance = 0.0f; + float ProcBonus = 0.0f; + + if (RuleB(Combat, AdjustSpecialProcPerMinute)) { + ProcChance = (static_cast(ReuseTime*1000) * + RuleR(Combat, AvgSpecialProcsPerMinute) / 60000.0f); + ProcBonus += (10 + (static_cast(mydex/10) + static_cast(itembonuses.HeroicDEX /10)))/100.0f; + ProcChance += ProcChance * ProcBonus / 100.0f; + + } else { + /*Kayen: Unable to find data on old proc rate of assassinate, no idea if our formula is real or made up.*/ + ProcChance = (10 + (static_cast(mydex/10) + static_cast(itembonuses.HeroicDEX /10)))/100.0f; + + } + + return ProcChance; +} + void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod, int16 focus, bool CanRiposte) { if (!CanDoSpecialAttack(other)) From d3ce9792b50a5f8b454e086f25cafa1199687f04 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Mon, 30 Jun 2014 06:34:12 -0400 Subject: [PATCH 067/288] Fix for AA Finishg Blow rank 1-3. AA Data was missing and incorrectly added to wrong aaid. Required SQL --- utils/sql/git/required/2014_06_25_AA_Updates..sql | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/utils/sql/git/required/2014_06_25_AA_Updates..sql b/utils/sql/git/required/2014_06_25_AA_Updates..sql index d51948af9..3d7a048b6 100644 --- a/utils/sql/git/required/2014_06_25_AA_Updates..sql +++ b/utils/sql/git/required/2014_06_25_AA_Updates..sql @@ -20,4 +20,15 @@ INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ( INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1605', '1', '439', '0', '32000'); INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1605', '2', '345', '51', '0'); INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1606', '1', '439', '0', '32000'); -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1606', '2', '345', '53', '0'); \ No newline at end of file +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1606', '2', '345', '53', '0'); + +-- AA Finishing Blow Fix +DELETE FROM aa_effects WHERE aaid = 199 AND slot = 2; +DELETE FROM aa_effects WHERE aaid = 200 AND slot = 2; +DELETE FROM aa_effects WHERE aaid = 201 AND slot = 2; +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('119', '1', '278', '500', '32000'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('119', '2', '440', '50', '200'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('120', '1', '278', '500', '32000'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('120', '2', '440', '52', '200'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('121', '1', '278', '500', '32000'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('121', '2', '440', '54', '200'); \ No newline at end of file From 32d20f22efca137576edd63c1348b7f052757b5c Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Mon, 30 Jun 2014 07:18:47 -0400 Subject: [PATCH 068/288] Revised Finishing blow so that damage now receives all melee bonus. Support also for this effect if placed on items or spells. --- changelog.txt | 2 ++ zone/attack.cpp | 28 ++++++++++++------------ zone/bonuses.cpp | 55 +++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 69 insertions(+), 16 deletions(-) diff --git a/changelog.txt b/changelog.txt index 53585d982..82dcc497f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -17,6 +17,8 @@ system, or flat chance based on dex (formula updated). Kayen: Implemented SE_Assassinate, SE_AssassinateLevel - Defines assassinate damage and level requirements. Revised Assassinate mechanic so damage now receives all backstab bonuses, proc chance can be set to either (lives new Proc Per minute system, or flat chance based on dex (formula updated). Assassinate can now proc from THROW if behind target, various other adjustments. +Kayen: Fix to AA Finishing Blow missing aa_effects data, update required SQL. +Revised Finishing blow so that damage now receives all melee bonus. Support also for this effect if placed on items or spells. Required SQL: utils/sql/git/required/2014_06_25_AA_Update.sql Optional SQL: utils/sql/git/optiional/2014_06_29_HeadShotRules.sql diff --git a/zone/attack.cpp b/zone/attack.cpp index 4592f2fdf..3346f4aa7 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4443,27 +4443,25 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack bool Mob::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse) { + if (defender && !defender->IsClient() && defender->GetHPRatio() < 10){ - if (!defender) - return false; + uint32 FB_Dmg = aabonuses.FinishingBlow[1] + spellbonuses.FinishingBlow[1] + itembonuses.FinishingBlow[1]; + + uint16 FB_Level = 0; //Get Highest Headshot Level + FB_Level = aabonuses.FinishingBlowLvl[0]; + if (FB_Level < spellbonuses.FinishingBlowLvl[0]) + FB_Level = spellbonuses.FinishingBlowLvl[0]; + else if (FB_Level < itembonuses.FinishingBlowLvl[0]) + FB_Level = itembonuses.FinishingBlowLvl[0]; - if (aabonuses.FinishingBlow[1] && !defender->IsClient() && defender->GetHPRatio() < 10){ + //Proc Chance value of 500 = 5% + uint32 ProcChance = (aabonuses.FinishingBlow[0] + spellbonuses.FinishingBlow[0] + spellbonuses.FinishingBlow[0])/10; - uint32 chance = aabonuses.FinishingBlow[0]/10; //500 = 5% chance. - uint32 damage = aabonuses.FinishingBlow[1]; - uint16 levelreq = aabonuses.FinishingBlowLvl[0]; - - if(defender->GetLevel() <= levelreq && (chance >= MakeRandomInt(0, 1000))){ - mlog(COMBAT__ATTACKS, "Landed a finishing blow: levelreq at %d, other level %d", levelreq , defender->GetLevel()); + if(FB_Level && FB_Dmg && (defender->GetLevel() <= FB_Level) && (ProcChance >= MakeRandomInt(0, 1000))){ entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName()); - defender->Damage(this, damage, SPELL_UNKNOWN, skillinuse); + DoSpecialAttackDamage(defender, skillinuse, FB_Dmg, 1, -1, 10, false, false); return true; } - else - { - mlog(COMBAT__ATTACKS, "FAILED a finishing blow: levelreq at %d, other level %d", levelreq , defender->GetLevel()); - return false; - } } return false; } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 0871e3679..8b46773fc 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1204,7 +1204,6 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) case SE_FinishingBlow: { - //base1 = chance, base2 = damage if (newbon->FinishingBlow[1] < base2){ newbon->FinishingBlow[0] = base1; @@ -2825,6 +2824,26 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne break; } + case SE_FinishingBlow: + { + //base1 = chance, base2 = damage + if (newbon->FinishingBlow[1] < base2){ + newbon->FinishingBlow[0] = effect_value; + newbon->FinishingBlow[1] = base2; + } + break; + } + + case SE_FinishingBlowLvl: + { + //base1 = level, base2 = ??? (Set to 200 in AA data, possible proc rate mod?) + if (newbon->FinishingBlowLvl[0] < effect_value){ + newbon->FinishingBlowLvl[0] = effect_value; + newbon->FinishingBlowLvl[1] = base2; + } + break; + } + //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { @@ -4258,6 +4277,40 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) spellbonuses.HSLevel = effect_value; aabonuses.HSLevel = effect_value; itembonuses.HSLevel = effect_value; + break; + + case SE_Assassinate: + spellbonuses.Assassinate[0] = effect_value; + aabonuses.Assassinate[0] = effect_value; + itembonuses.Assassinate[0] = effect_value; + spellbonuses.Assassinate[1] = effect_value; + aabonuses.Assassinate[1] = effect_value; + itembonuses.Assassinate[1] = effect_value; + break; + + case SE_AssassinateLevel: + spellbonuses.AssassinateLevel = effect_value; + aabonuses.AssassinateLevel = effect_value; + itembonuses.AssassinateLevel = effect_value; + break; + + case SE_FinishingBlow: + spellbonuses.FinishingBlow[0] = effect_value; + aabonuses.FinishingBlow[0] = effect_value; + itembonuses.FinishingBlow[0] = effect_value; + spellbonuses.FinishingBlow[1] = effect_value; + aabonuses.FinishingBlow[1] = effect_value; + itembonuses.FinishingBlow[1] = effect_value; + break; + + case SE_FinishingBlowLvl: + spellbonuses.FinishingBlowLvl[0] = effect_value; + aabonuses.FinishingBlowLvl[0] = effect_value; + itembonuses.FinishingBlowLvl[0] = effect_value; + spellbonuses.FinishingBlowLvl[1] = effect_value; + aabonuses.FinishingBlowLvl[1] = effect_value; + itembonuses.FinishingBlowLvl[1] = effect_value; + break; } } From 718ba3edbf8c01b4e8c92034cb1be0a5483af4b0 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Mon, 30 Jun 2014 16:17:55 -0400 Subject: [PATCH 069/288] Implemented SE_PetMeleeMitigation - Bonus applied to pet owner. Gives AC to owner's pet. Related AA's to be added in a seperate update. --- changelog.txt | 1 + common/spdat.h | 2 +- zone/attack.cpp | 14 ++++++++++++-- zone/bonuses.cpp | 14 ++++++++++++++ zone/common.h | 1 + 5 files changed, 29 insertions(+), 3 deletions(-) diff --git a/changelog.txt b/changelog.txt index 82dcc497f..0a22ccf8d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -19,6 +19,7 @@ Revised Assassinate mechanic so damage now receives all backstab bonuses, proc c system, or flat chance based on dex (formula updated). Assassinate can now proc from THROW if behind target, various other adjustments. Kayen: Fix to AA Finishing Blow missing aa_effects data, update required SQL. Revised Finishing blow so that damage now receives all melee bonus. Support also for this effect if placed on items or spells. +Kayen: Implemented SE_PetMeleeMitigation - Bonus applied to pet owner. Gives AC to owner's pet. Required SQL: utils/sql/git/required/2014_06_25_AA_Update.sql Optional SQL: utils/sql/git/optiional/2014_06_29_HeadShotRules.sql diff --git a/common/spdat.h b/common/spdat.h index 65bb9f692..23a50fc3f 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -544,7 +544,7 @@ typedef enum { #define SE_FcHealAmtIncoming 394 // implemented - Adds/Removes amount of healing on target by X value with foucs restrictions. #define SE_FcHealPctCritIncoming 395 // implemented[AA] - Increases chance of having a heal crit when cast on you. [focus limited] #define SE_FcHealAmtCrit 396 // implemented - Adds a direct healing amount to spells -//#define SE_PetMeleeMitigation 397 // *not implemented[AA] - additional mitigation to your pets. +#define SE_PetMeleeMitigation 397 // implemented[AA] - additional mitigation to your pets. Adds AC. #define SE_SwarmPetDuration 398 // implemented - Affects the duration of swarm pets #define SE_FcTwincast 399 // implemented - cast 2 spells for every 1 #define SE_HealGroupFromMana 400 // implemented - Drains mana and heals for each point of mana drained diff --git a/zone/attack.cpp b/zone/attack.cpp index 3346f4aa7..7b641bd96 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -560,11 +560,21 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttac weight = (CastToClient()->CalcCurrentWeight() / 10.0); } else if (IsNPC()) { armor = CastToNPC()->GetRawAC(); + int PetACBonus = 0; if (!IsPet()) armor = (armor / RuleR(Combat, NPCACFactor)); + else{ + Mob *owner = nullptr; + owner = GetOwner(); + if (owner){ + PetACBonus = owner->aabonuses.PetMeleeMitigation + + owner->itembonuses.PetMeleeMitigation + + owner->spellbonuses.PetMeleeMitigation; + } + } - armor += spellbonuses.AC + itembonuses.AC + 1; + armor += spellbonuses.AC + itembonuses.AC + PetACBonus + 1; } if (opts) { @@ -4447,7 +4457,7 @@ bool Mob::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse) uint32 FB_Dmg = aabonuses.FinishingBlow[1] + spellbonuses.FinishingBlow[1] + itembonuses.FinishingBlow[1]; - uint16 FB_Level = 0; //Get Highest Headshot Level + uint16 FB_Level = 0; FB_Level = aabonuses.FinishingBlowLvl[0]; if (FB_Level < spellbonuses.FinishingBlowLvl[0]) FB_Level = spellbonuses.FinishingBlowLvl[0]; diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 8b46773fc..5a13f2ccb 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1311,6 +1311,10 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) break; } + case SE_PetMeleeMitigation: + newbon->PetMeleeMitigation += base1; + break; + } } } @@ -2844,6 +2848,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne break; } + case SE_PetMeleeMitigation: + newbon->PetMeleeMitigation += effect_value; + break; + //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { @@ -4075,6 +4083,12 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) itembonuses.GivePetGroupTarget = false; break; + case SE_PetMeleeMitigation: + spellbonuses.PetMeleeMitigation = effect_value; + itembonuses.PetMeleeMitigation = effect_value; + aabonuses.PetMeleeMitigation = effect_value; + break; + case SE_RootBreakChance: spellbonuses.RootBreakChance = effect_value; aabonuses.RootBreakChance = effect_value; diff --git a/zone/common.h b/zone/common.h index 6d6ae581f..d9b0d53d3 100644 --- a/zone/common.h +++ b/zone/common.h @@ -427,6 +427,7 @@ struct StatBonuses { uint8 HSLevel; // Max Level Headshot will be effective at. uint32 Assassinate[2]; // Assassinate AA (Massive dmg vs humaniod w/ assassinate) 0= ? 1= Dmg uint8 AssassinateLevel; // Max Level Assassinate will be effective at. + int32 PetMeleeMitigation; // Add AC to owner's pet. }; From 042f6f3789cf850d72b027496d0254f18e396d56 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Tue, 1 Jul 2014 04:53:24 -0400 Subject: [PATCH 070/288] Updated SE_WaketheDead , max will now set duration. --- common/spdat.h | 2 +- zone/spell_effects.cpp | 9 +-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/common/spdat.h b/common/spdat.h index 23a50fc3f..c8fd7d845 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -410,7 +410,7 @@ typedef enum { #define SE_AddSingingMod 260 // implemented[AA] - Instrument/Singing Mastery, base1 is the mod, base2 is the ItemType #define SE_SongModCap 261 // implemented[AA] - Song Mod cap increase (no longer used on live) #define SE_RaiseStatCap 262 // implemented -#define SE_TradeSkillMastery 263 // implemented - lets you raise more than one tradeskill above master. +//#define SE_TradeSkillMastery 263 // not implemented - lets you raise more than one tradeskill above master. //#define SE_HastenedAASkill 264 // not implemented as bonus - Use redux field in aa_actions table for this effect #define SE_MasteryofPast 265 // implemented[AA] - Spells less than effect values level can not be fizzled #define SE_ExtraAttackChance 266 // implemented - increase chance to score an extra attack with a 2-Handed Weapon. diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 51979eddc..be09bef4c 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2294,14 +2294,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) #endif //meh dupe issue with npc casting this if(caster->IsClient()){ - //this spell doesn't appear to actually contain the information on duration inside of it oddly - int dur = 60; - if(spell_id == 3269) - dur += 15; - else if(spell_id == 3270) - dur += 30; - - caster->WakeTheDead(spell_id, caster->GetTarget(), dur); + caster->WakeTheDead(spell_id, caster->GetTarget(), spells[spell_id].max[i]); } break; } From 4672f223c18dff5ad53a5e40174508a4a7b12141 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Tue, 1 Jul 2014 04:55:50 -0400 Subject: [PATCH 071/288] minor fix --- zone/spell_effects.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index be09bef4c..376dcae7c 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2294,7 +2294,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) #endif //meh dupe issue with npc casting this if(caster->IsClient()){ - caster->WakeTheDead(spell_id, caster->GetTarget(), spells[spell_id].max[i]); + int dur = spells[spell_id].max[i]; + if (!dur) + dur = 60; + + caster->WakeTheDead(spell_id, caster->GetTarget(), dur); } break; } From 1cd20c65e22b72307b921e45f9f0f0136c416bdb Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Tue, 1 Jul 2014 16:52:28 -0400 Subject: [PATCH 072/288] Renamed a few spell effects more appropriately. --- common/spdat.h | 6 +++--- zone/bonuses.cpp | 6 +++--- zone/bot.cpp | 2 +- zone/mob.cpp | 4 ++-- zone/spell_effects.cpp | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/common/spdat.h b/common/spdat.h index c8fd7d845..75d351fc2 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -506,13 +506,13 @@ typedef enum { //#define SE_ChangeTriggerType 356 // not used #define SE_FcMute 357 // implemented - silences casting of spells that contain specific spell effects (focus limited) #define SE_CurrentManaOnce 358 // implemented -#define SE_Invulnerabilty 359 // *not implemented - Invulnerability (Brell's Blessing) -#define SE_SpellOnKill 360 // implemented - a buff that has a base1 % to cast spell base2 when you kill a "challenging foe" base3 min level +//#define SE_PassiveSenseTrap 359 // *not implemented - Invulnerability (Brell's Blessing) +#define SE_ProcOnKillShot 360 // implemented - a buff that has a base1 % to cast spell base2 when you kill a "challenging foe" base3 min level #define SE_SpellOnDeath 361 // implemented - casts spell on death of buffed //#define SE_PotionBeltSlots 362 // *not implemented[AA] 'Quick Draw' expands the potion belt by one additional available item slot per rank. //#define SE_BandolierSlots 363 // *not implemented[AA] 'Battle Ready' expands the bandolier by one additional save slot per rank. #define SE_TripleAttackChance 364 // implemented -#define SE_SpellOnKill2 365 // implemented - chance to trigger a spell on kill when the kill is caused by a specific spell with this effect in it (10470 Venin) +#define SE_ProcOnSpellKillShot 365 // implemented - chance to trigger a spell on kill when the kill is caused by a specific spell with this effect in it (10470 Venin) #define SE_ShieldEquipDmgMod 366 // implemented[AA] Damage modifier to melee if shield equiped. (base1 = dmg mod , base2 = ?) ie Shield Specialist AA #define SE_SetBodyType 367 // implemented - set body type of base1 so it can be affected by spells that are limited to that type (Plant, Animal, Undead, etc) //#define SE_FactionMod 368 // *not implemented - increases faction with base1 (faction id, live won't match up w/ ours) by base2 diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 5a13f2ccb..9072a2c9b 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -989,7 +989,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) newbon->CrippBlowChance += base1; break; - case SE_SpellOnKill: + case SE_ProcOnKillShot: for(int i = 0; i < MAX_SPELL_TRIGGER*3; i+=3) { if(!newbon->SpellOnKill[i] || ((newbon->SpellOnKill[i] == base2) && (newbon->SpellOnKill[i+1] < base1))) @@ -2179,7 +2179,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne newbon->CriticalDoTChance += effect_value; break; - case SE_SpellOnKill: + case SE_ProcOnKillShot: { for(int e = 0; e < MAX_SPELL_TRIGGER*3; e+=3) { @@ -3785,7 +3785,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) itembonuses.CriticalDoTChance = effect_value; break; - case SE_SpellOnKill: + case SE_ProcOnKillShot: { for(int e = 0; e < MAX_SPELL_TRIGGER*3; e=3) { diff --git a/zone/bot.cpp b/zone/bot.cpp index 5bdf3cb02..e961bd7ec 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1900,7 +1900,7 @@ void Bot::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) newbon->UnfailingDivinity += base1; break; - case SE_SpellOnKill: + case SE_ProcOnKillShot: for(int i = 0; i < MAX_SPELL_TRIGGER*3; i+=3) { if(!newbon->SpellOnKill[i] || ((newbon->SpellOnKill[i] == base2) && (newbon->SpellOnKill[i+1] < base1))) diff --git a/zone/mob.cpp b/zone/mob.cpp index ed2072e21..ee468a0e6 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -4139,9 +4139,9 @@ void Mob::TrySpellOnKill(uint8 level, uint16 spell_id) { if (spell_id != SPELL_UNKNOWN) { - if(IsEffectInSpell(spell_id, SE_SpellOnKill2)) { + if(IsEffectInSpell(spell_id, SE_ProcOnSpellKillShot)) { for (int i = 0; i < EFFECT_COUNT; i++) { - if (spells[spell_id].effectid[i] == SE_SpellOnKill2) + if (spells[spell_id].effectid[i] == SE_ProcOnSpellKillShot) { if (IsValidSpell(spells[spell_id].base2[i]) && spells[spell_id].max[i] <= level) { diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 376dcae7c..090fb4b75 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2860,8 +2860,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_CriticalHealChance: case SE_CriticalHealOverTime: case SE_CriticalDoTChance: - case SE_SpellOnKill: - case SE_SpellOnKill2: + case SE_ProcOnKillShot: + case SE_ProcOnSpellKillShot: case SE_CriticalDamageMob: case SE_LimitSpellGroup: case SE_ResistCorruption: From 6877e40b385ad15a873bf94f1de897d8d40a8c00 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Tue, 1 Jul 2014 17:34:36 -0400 Subject: [PATCH 073/288] Update to SE_AStacker, B, C, D Will correclty use base value to stack with same type ie (A vs A) Highest base value will take hold. --- zone/bonuses.cpp | 12 ++++++++---- zone/common.h | 8 ++++---- zone/spells.cpp | 18 +++++++++++++++--- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 9072a2c9b..a316c4b3b 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -2762,19 +2762,23 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne break; case SE_AStacker: - newbon->AStacker = true; + newbon->AStacker[0] = 1; + newbon->AStacker[1] = effect_value; break; case SE_BStacker: - newbon->BStacker = true; + newbon->BStacker[0] = 1; + newbon->BStacker[1] = effect_value; break; case SE_CStacker: - newbon->CStacker = true; + newbon->CStacker[0] = 1; + newbon->CStacker[1] = effect_value; break; case SE_DStacker: - newbon->DStacker = true; + newbon->DStacker[0] = 1; + newbon->DStacker[1] = effect_value; break; case SE_Berserk: diff --git a/zone/common.h b/zone/common.h index d9b0d53d3..88600492e 100644 --- a/zone/common.h +++ b/zone/common.h @@ -366,10 +366,10 @@ struct StatBonuses { bool NegateIfCombat; // Bool Drop buff if cast or melee int8 Screech; // -1 = Will be blocked if another Screech is +(1) int16 AlterNPCLevel; // amount of lvls +/- - bool AStacker; // For buff stack blocking - bool BStacker; // For buff stack blocking - bool CStacker; // For buff stack blocking - bool DStacker; // For buff stack blocking + int16 AStacker[1]; // For buff stack blocking 0=Exists 1=Effect_value + int16 BStacker[1]; // For buff stack blocking 0=Exists 1=Effect_value + int16 CStacker[1]; // For buff stack blocking 0=Exists 1=Effect_value + int16 DStacker[1]; // For buff stack blocking 0=Exists 1=Effect_value bool BerserkSPA; // berserk effect int16 Metabolism; // Food/drink consumption rates. diff --git a/zone/spells.cpp b/zone/spells.cpp index 78dce3379..59dbb6625 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2622,19 +2622,31 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, } /*Buff stacking prevention spell effects (446 - 449) works as follows... If B prevent A, if C prevent B, if D prevent C. + If checking same type ie A vs A, which ever effect base value is higher will take hold. Special check is added to make sure the buffs stack properly when applied from fade on duration effect, since the buff is not fully removed at the time of the trgger*/ - if (spellbonuses.BStacker) { + if (spellbonuses.AStacker[0]) { + if ((effect2 == SE_AStacker) && (sp2.effectid[i] <= spellbonuses.AStacker[1])) + return -1; + } + + if (spellbonuses.BStacker[0]) { + if ((effect2 == SE_BStacker) && (sp2.effectid[i] <= spellbonuses.BStacker[1])) + return -1; if ((effect2 == SE_AStacker) && (!IsCastonFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_BStacker))) return -1; } - if (spellbonuses.CStacker) { + if (spellbonuses.CStacker[0]) { + if ((effect2 == SE_CStacker) && (sp2.effectid[i] <= spellbonuses.CStacker[1])) + return -1; if ((effect2 == SE_BStacker) && (!IsCastonFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_CStacker))) return -1; } - if (spellbonuses.DStacker) { + if (spellbonuses.DStacker[0]) { + if ((effect2 == SE_DStacker) && (sp2.effectid[i] <= spellbonuses.DStacker[1])) + return -1; if ((effect2 == SE_CStacker) && (!IsCastonFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_DStacker))) return -1; } From 3e0f6b85209444b292bbda096e53720f02af41ad Mon Sep 17 00:00:00 2001 From: Chris M Date: Wed, 2 Jul 2014 22:17:45 -0500 Subject: [PATCH 074/288] Initial Socket Server implementation with CMakeLists.txt updated. Socket server will connect to world at this point. --- CMakeLists.txt | 1 + common/EmuTCPConnection.cpp | 27 ++++- common/EmuTCPConnection.h | 2 +- common/logtypes.h | 7 ++ common/platform.h | 1 + socket_server/CMakeLists.txt | 44 +++++++++ socket_server/database.cpp | 131 +++++++++++++++++++++++++ socket_server/database.h | 54 ++++++++++ socket_server/socket_server.cpp | 115 ++++++++++++++++++++++ socket_server/socket_server_config.cpp | 28 ++++++ socket_server/socket_server_config.h | 55 +++++++++++ socket_server/worldserver.cpp | 69 +++++++++++++ socket_server/worldserver.h | 35 +++++++ world/CMakeLists.txt | 2 + world/console.cpp | 16 ++- world/net.cpp | 4 + world/socket_server.cpp | 127 ++++++++++++++++++++++++ world/socket_server.h | 23 +++++ 18 files changed, 735 insertions(+), 6 deletions(-) create mode 100644 socket_server/CMakeLists.txt create mode 100644 socket_server/database.cpp create mode 100644 socket_server/database.h create mode 100644 socket_server/socket_server.cpp create mode 100644 socket_server/socket_server_config.cpp create mode 100644 socket_server/socket_server_config.h create mode 100644 socket_server/worldserver.cpp create mode 100644 socket_server/worldserver.h create mode 100644 world/socket_server.cpp create mode 100644 world/socket_server.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4732ca8d0..1d3adcc25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -312,6 +312,7 @@ IF(EQEMU_BUILD_SERVER) ADD_SUBDIRECTORY(zone) ADD_SUBDIRECTORY(ucs) ADD_SUBDIRECTORY(queryserv) + ADD_SUBDIRECTORY(socket_server) ADD_SUBDIRECTORY(eqlaunch) ENDIF(EQEMU_BUILD_SERVER) IF(EQEMU_BUILD_LOGIN) diff --git a/common/EmuTCPConnection.cpp b/common/EmuTCPConnection.cpp index 465d16c1e..39c297ccf 100644 --- a/common/EmuTCPConnection.cpp +++ b/common/EmuTCPConnection.cpp @@ -366,7 +366,22 @@ bool EmuTCPConnection::LineOutQueuePush(char* line) { safe_delete_array(line); return(true); } - + if (strcmp(line, "**PACKETMODESS**") == 0) { + MSendQueue.lock(); + safe_delete_array(sendbuf); + if (TCPMode == modeConsole) + Send((const uchar*) "\0**PACKETMODESS**\r", 18); + TCPMode = modePacket; + PacketMode = packetModeSocket_Server; + EmuTCPNetPacket_Struct* tnps = 0; + while ((tnps = InModeQueue.pop())) { + SendPacket(tnps); + safe_delete_array(tnps); + } + MSendQueue.unlock(); + safe_delete_array(line); + return(true); + } } return(TCPConnection::LineOutQueuePush(line)); @@ -419,7 +434,15 @@ bool EmuTCPConnection::ConnectIP(uint32 irIP, uint16 irPort, char* errbuf) { sendbuf_used = sendbuf_size; sendbuf = new uchar[sendbuf_size]; memcpy(sendbuf, "\0**PACKETMODEQS**\r", sendbuf_size); - } else { + } + else if (PacketMode == packetModeSocket_Server) { + safe_delete_array(sendbuf); + sendbuf_size = 18; + sendbuf_used = sendbuf_size; + sendbuf = new uchar[sendbuf_size]; + memcpy(sendbuf, "\0**PACKETMODESS**\r", sendbuf_size); + } + else { //default: packetModeZone safe_delete_array(sendbuf); sendbuf_size = 20; diff --git a/common/EmuTCPConnection.h b/common/EmuTCPConnection.h index ff7dd8995..947ee9480 100644 --- a/common/EmuTCPConnection.h +++ b/common/EmuTCPConnection.h @@ -30,7 +30,7 @@ class EmuTCPServer; class EmuTCPConnection : public TCPConnection { public: enum eTCPMode { modeConsole, modeTransition, modePacket }; - enum ePacketMode { packetModeZone, packetModeLauncher, packetModeLogin, packetModeUCS, packetModeQueryServ }; + enum ePacketMode { packetModeZone, packetModeLauncher, packetModeLogin, packetModeUCS, packetModeQueryServ, packetModeSocket_Server }; EmuTCPConnection(uint32 ID, EmuTCPServer* iServer, SOCKET iSock, uint32 irIP, uint16 irPort, bool iOldFormat = false); EmuTCPConnection(bool iOldFormat = false, EmuTCPServer* iRelayServer = 0, eTCPMode iMode = modePacket); // for outgoing connections diff --git a/common/logtypes.h b/common/logtypes.h index cadfbf71a..1776c9518 100644 --- a/common/logtypes.h +++ b/common/logtypes.h @@ -65,6 +65,13 @@ LOG_TYPE( QUERYSERV, CLIENT, DISABLED ) LOG_TYPE( QUERYSERV, TRACE, DISABLED ) LOG_TYPE( QUERYSERV, PACKETS, DISABLED) +LOG_CATEGORY(SOCKET_SERVER) +LOG_TYPE(SOCKET_SERVER, INIT, ENABLED) +LOG_TYPE(SOCKET_SERVER, ERROR, ENABLED) +LOG_TYPE(SOCKET_SERVER, CLIENT, DISABLED) +LOG_TYPE(SOCKET_SERVER, TRACE, DISABLED) +LOG_TYPE(SOCKET_SERVER, PACKETS, DISABLED) + LOG_CATEGORY( SPAWNS ) LOG_TYPE( SPAWNS, MAIN, DISABLED ) LOG_TYPE( SPAWNS, CONDITIONS, DISABLED ) diff --git a/common/platform.h b/common/platform.h index efb176ec4..7eaae045b 100644 --- a/common/platform.h +++ b/common/platform.h @@ -8,6 +8,7 @@ enum EQEmuExePlatform ExePlatformWorld, ExePlatformLogin, ExePlatformQueryServ, + ExePlatformSocket_Server, ExePlatformUCS, ExePlatformLaunch, ExePlatformSharedMemory, diff --git a/socket_server/CMakeLists.txt b/socket_server/CMakeLists.txt new file mode 100644 index 000000000..f647863d9 --- /dev/null +++ b/socket_server/CMakeLists.txt @@ -0,0 +1,44 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +SET(socket_server_sources + database.cpp + socket_server.cpp + socket_server_config.cpp + worldserver.cpp +) + +SET(socket_server_headers + database.h + socket_server_config.h + worldserver.h +) + +ADD_EXECUTABLE(socket_server ${socket_server_sources} ${socket_server_headers}) + +INSTALL(TARGETS socket_server RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}) + +ADD_DEFINITIONS(-DQSERV) + +TARGET_LINK_LIBRARIES(socket_server Common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY}) + +IF(MSVC) + SET_TARGET_PROPERTIES(socket_server PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF") + TARGET_LINK_LIBRARIES(socket_server "Ws2_32.lib") +ENDIF(MSVC) + +IF(MINGW) + TARGET_LINK_LIBRARIES(socket_server "WS2_32") +ENDIF(MINGW) + +IF(UNIX) + TARGET_LINK_LIBRARIES(socket_server "${CMAKE_DL_LIBS}") + TARGET_LINK_LIBRARIES(socket_server "z") + TARGET_LINK_LIBRARIES(socket_server "m") + IF(NOT DARWIN) + TARGET_LINK_LIBRARIES(socket_server "rt") + ENDIF(NOT DARWIN) + TARGET_LINK_LIBRARIES(socket_server "pthread") + ADD_DEFINITIONS(-fPIC) +ENDIF(UNIX) + +SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/Bin) diff --git a/socket_server/database.cpp b/socket_server/database.cpp new file mode 100644 index 000000000..a2c04bbb4 --- /dev/null +++ b/socket_server/database.cpp @@ -0,0 +1,131 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + + +#include "../common/debug.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Disgrace: for windows compile +#ifdef _WINDOWS +#include +#define snprintf _snprintf +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +#else +#include "../common/unix.h" +#include +#endif + +#include "database.h" +#include "../common/eq_packet_structs.h" +#include "../common/StringUtil.h" +#include "../common/servertalk.h" + +Database::Database () +{ + DBInitVars(); +} + +/* +Establish a connection to a mysql database with the supplied parameters +*/ + +Database::Database(const char* host, const char* user, const char* passwd, const char* database, uint32 port) +{ + DBInitVars(); + Connect(host, user, passwd, database, port); +} + +bool Database::Connect(const char* host, const char* user, const char* passwd, const char* database, uint32 port) +{ + uint32 errnum= 0; + char errbuf[MYSQL_ERRMSG_SIZE]; + if (!Open(host, user, passwd, database, port, &errnum, errbuf)) + { + LogFile->write(EQEMuLog::Error, "Failed to connect to database: Error: %s", errbuf); + HandleMysqlError(errnum); + + return false; + } + else + { + LogFile->write(EQEMuLog::Status, "Using database '%s' at %s:%d",database,host,port); + return true; + } +} + +void Database::DBInitVars() { + +} + + + +void Database::HandleMysqlError(uint32 errnum) { +} + +/* + +Close the connection to the database +*/ +Database::~Database() +{ +} + +bool Database::GetVariable(const char* varname, char* varvalue, uint16 varvalue_len) { + + char errbuf[MYSQL_ERRMSG_SIZE]; + char* query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + + if (!RunQuery(query,MakeAnyLenString(&query, "select `value` from `variables` where `varname`='%s'", varname), errbuf, &result)) { + + _log(UCS__ERROR, "Unable to get message count from database. %s %s", query, errbuf); + + safe_delete_array(query); + + return false; + } + + safe_delete_array(query); + + if (mysql_num_rows(result) != 1) { + + mysql_free_result(result); + + return false; + } + + row = mysql_fetch_row(result); + + snprintf(varvalue, varvalue_len, "%s", row[0]); + + mysql_free_result(result); + + return true; +} \ No newline at end of file diff --git a/socket_server/database.h b/socket_server/database.h new file mode 100644 index 000000000..6500ffad6 --- /dev/null +++ b/socket_server/database.h @@ -0,0 +1,54 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#ifndef CHATSERVER_DATABASE_H +#define CHATSERVER_DATABASE_H + +#define AUTHENTICATION_TIMEOUT 60 +#define INVALID_ID 0xFFFFFFFF + +#include "../common/debug.h" +#include "../common/types.h" +#include "../common/dbcore.h" +#include "../common/linked_list.h" +#include "../common/servertalk.h" +#include +#include +#include + +//atoi is not uint32 or uint32 safe!!!! +#define atoul(str) strtoul(str, nullptr, 10) + +class Database : public DBcore { +public: + Database(); + 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 GetVariable(const char* varname, char* varvalue, uint16 varvalue_len); +protected: + void HandleMysqlError(uint32 errnum); +private: + void DBInitVars(); + +}; + +#endif + diff --git a/socket_server/socket_server.cpp b/socket_server/socket_server.cpp new file mode 100644 index 000000000..eed4751d1 --- /dev/null +++ b/socket_server/socket_server.cpp @@ -0,0 +1,115 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "../common/debug.h" +#include "../common/opcodemgr.h" +#include "../common/EQStreamFactory.h" +#include "../common/rulesys.h" +#include "../common/servertalk.h" +#include "../common/platform.h" +#include "../common/crash.h" +#include "database.h" +#include "socket_server_config.h" +#include "worldserver.h" +#include + +#include +volatile bool RunLoops = true; +TimeoutManager timeout_manager; +Database database; +std::string WorldShortName; + +const socket_server_config *Config; +WorldServer *worldserver = 0; + +void CatchSignal(int sig_num) { + RunLoops = false; + if(worldserver) + worldserver->Disconnect(); +} + +int main() { + RegisterExecutablePlatform(ExePlatformSocket_Server); + set_exception_handler(); + Timer InterserverTimer(INTERSERVER_TIMER); // does auto-reconnect + _log(SOCKET_SERVER__INIT, "Starting EQEmu Socket Server."); + if (!socket_server_config::LoadConfig()) { + _log(SOCKET_SERVER__INIT, "Loading server configuration failed."); + return 1; + } + + Config = socket_server_config::get(); + + if(!load_log_settings(Config->LogSettingsFile.c_str())) + _log(SOCKET_SERVER__INIT, "Warning: Unable to read %s", Config->LogSettingsFile.c_str()); + else + _log(SOCKET_SERVER__INIT, "Log settings loaded from %s", Config->LogSettingsFile.c_str()); + + WorldShortName = Config->ShortName; + + /* + _log(SOCKET_SERVER__INIT, "Connecting to MySQL..."); + + if (!database.Connect( + Config->QSDatabaseHost.c_str(), + Config->QSDatabaseUsername.c_str(), + Config->QSDatabasePassword.c_str(), + Config->QSDatabaseDB.c_str(), + Config->QSDatabasePort)) { + _log(WORLD__INIT_ERR, "Cannot continue without a database connection."); + return 1; + } + */ + + if (signal(SIGINT, CatchSignal) == SIG_ERR) { + _log(SOCKET_SERVER__ERROR, "Could not set signal handler"); + return 1; + } + if (signal(SIGTERM, CatchSignal) == SIG_ERR) { + _log(SOCKET_SERVER__ERROR, "Could not set signal handler"); + return 1; + } + + worldserver = new WorldServer; + worldserver->Connect(); + + while(RunLoops) { + Timer::SetCurrentTime(); + if (InterserverTimer.Check()) { + if (worldserver->TryReconnect() && (!worldserver->Connected())) + worldserver->AsyncConnect(); + } + worldserver->Process(); + timeout_manager.CheckTimeouts(); + Sleep(100); + } +} + +void UpdateWindowTitle(char* iNewTitle) { +#ifdef _WINDOWS + char tmp[500]; + if (iNewTitle) { + snprintf(tmp, sizeof(tmp), "SOCKET_SERVER: %s", iNewTitle); + } + else { + snprintf(tmp, sizeof(tmp), "SOCKET_SERVER"); + } + SetConsoleTitle(tmp); +#endif +} diff --git a/socket_server/socket_server_config.cpp b/socket_server/socket_server_config.cpp new file mode 100644 index 000000000..8f08eba9d --- /dev/null +++ b/socket_server/socket_server_config.cpp @@ -0,0 +1,28 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "../common/debug.h" +#include "socket_server_config.h" + +socket_server_config *socket_server_config::_chat_config = nullptr; + +std::string socket_server_config::GetByName(const std::string &var_name) const { + return(EQEmuConfig::GetByName(var_name)); +} + diff --git a/socket_server/socket_server_config.h b/socket_server/socket_server_config.h new file mode 100644 index 000000000..bc86107d3 --- /dev/null +++ b/socket_server/socket_server_config.h @@ -0,0 +1,55 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#ifndef __socket_server_config_H +#define __socket_server_config_H + +#include "../common/EQEmuConfig.h" + +class socket_server_config : public EQEmuConfig { +public: + virtual std::string GetByName(const std::string &var_name) const; + +private: + + static socket_server_config *_chat_config; + +public: + + // Produce a const singleton + static const socket_server_config *get() { + if (_chat_config == nullptr) + LoadConfig(); + return(_chat_config); + } + + // Load the config + static bool LoadConfig() { + if (_chat_config != nullptr) + delete _chat_config; + _chat_config=new socket_server_config; + _config=_chat_config; + + return _config->ParseFile(EQEmuConfig::ConfigFile.c_str(),"server"); + } + +}; + +#endif + diff --git a/socket_server/worldserver.cpp b/socket_server/worldserver.cpp new file mode 100644 index 000000000..f4e7cdf76 --- /dev/null +++ b/socket_server/worldserver.cpp @@ -0,0 +1,69 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include "../common/debug.h" +#include +#include +#include +#include +#include +#include +#include + +#include "../common/servertalk.h" +#include "worldserver.h" +#include "socket_server_config.h" +#include "database.h" +#include "lfguild.h" +#include "../common/packet_functions.h" +#include "../common/md5.h" +#include "../common/packet_dump.h" + +extern WorldServer worldserver; +extern const socket_server_config *Config; +extern Database database; + +WorldServer::WorldServer() +: WorldConnection(EmuTCPConnection::packetModeSocket_Server, Config->SharedKey.c_str()){ + pTryReconnect = true; +} + +WorldServer::~WorldServer(){ +} + +void WorldServer::OnConnected(){ + _log(SOCKET_SERVER__INIT, "Connected to World."); + WorldConnection::OnConnected(); +} + +void WorldServer::Process(){ + WorldConnection::Process(); + if (!Connected()) + return; + + ServerPacket *pack = 0; + while((pack = tcpc.PopPacket())){ + _log(SOCKET_SERVER__TRACE, "Received Opcode: %4X", pack->opcode); + switch(pack->opcode) { + case 0: { break; } + case ServerOP_KeepAlive: { break; } + } + } + + safe_delete(pack); + return; +} \ No newline at end of file diff --git a/socket_server/worldserver.h b/socket_server/worldserver.h new file mode 100644 index 000000000..167342248 --- /dev/null +++ b/socket_server/worldserver.h @@ -0,0 +1,35 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#ifndef WORLDSERVER_H +#define WORLDSERVER_H + +#include "../common/worldconn.h" +#include "../common/eq_packet_structs.h" + +class WorldServer : public WorldConnection +{ + public: + WorldServer(); + virtual ~WorldServer(); + virtual void Process(); + + private: + virtual void OnConnected(); +}; +#endif + diff --git a/world/CMakeLists.txt b/world/CMakeLists.txt index 3ac008267..594f77bc1 100644 --- a/world/CMakeLists.txt +++ b/world/CMakeLists.txt @@ -23,6 +23,7 @@ SET(world_sources perl_EQW.cpp perl_HTTPRequest.cpp queryserv.cpp + socket_server.cpp ucs.cpp wguild_mgr.cpp world_logsys.cpp @@ -53,6 +54,7 @@ SET(world_headers LoginServerList.h net.h queryserv.h + socket_server.h SoFCharCreateData.h ucs.h wguild_mgr.h diff --git a/world/console.cpp b/world/console.cpp index 57161487d..5a9ee60f5 100644 --- a/world/console.cpp +++ b/world/console.cpp @@ -46,6 +46,7 @@ #include "LauncherList.h" #include "ucs.h" #include "queryserv.h" +#include "socket_server.h" #ifdef _WINDOWS #define snprintf _snprintf @@ -60,6 +61,7 @@ extern ClientList client_list; extern LauncherList launcher_list; extern UCSConnection UCSLink; extern QueryServConnection QSLink; +extern Socket_Server_Connection SSLink; extern volatile bool RunLoops; ConsoleList console_list; @@ -250,18 +252,26 @@ bool Console::Process() { _log(WORLD__CONSOLE,"New launcher from %s:%d", inet_ntoa(in), GetPort()); launcher_list.Add(tcpc); tcpc = 0; - } else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeUCS) + } + else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeUCS) { _log(WORLD__CONSOLE,"New UCS Connection from %s:%d", inet_ntoa(in), GetPort()); UCSLink.SetConnection(tcpc); tcpc = 0; } - else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeQueryServ) + else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeQueryServ) { _log(WORLD__CONSOLE,"New QS Connection from %s:%d", inet_ntoa(in), GetPort()); QSLink.SetConnection(tcpc); tcpc = 0; - } else { + } + else if (tcpc->GetPacketMode() == EmuTCPConnection::packetModeSocket_Server) + { + _log(WORLD__CONSOLE, "New Socket Server Connection from %s:%d", inet_ntoa(in), GetPort()); + SSLink.SetConnection(tcpc); + tcpc = 0; + } + else { _log(WORLD__CONSOLE,"Unsupported packet mode from %s:%d", inet_ntoa(in), GetPort()); } return false; diff --git a/world/net.cpp b/world/net.cpp index d7179bffe..f8d3410c0 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -86,6 +86,7 @@ #include "AdventureManager.h" #include "ucs.h" #include "queryserv.h" +#include "socket_server.h" TimeoutManager timeout_manager; EQStreamFactory eqsf(WorldStream,9000); @@ -97,6 +98,7 @@ LoginServerList loginserverlist; EQWHTTPServer http_server; UCSConnection UCSLink; QueryServConnection QSLink; +Socket_Server_Connection SSLink; LauncherList launcher_list; AdventureManager adventure_manager; DBAsync *dbasync = nullptr; @@ -454,6 +456,8 @@ int main(int argc, char** argv) { QSLink.Process(); + SSLink.Process(); + LFPGroupList.Process(); adventure_manager.Process(); diff --git a/world/socket_server.cpp b/world/socket_server.cpp new file mode 100644 index 000000000..826a95620 --- /dev/null +++ b/world/socket_server.cpp @@ -0,0 +1,127 @@ +#include "../common/debug.h" +#include "Socket_Server.h" +#include "WorldConfig.h" +#include "clientlist.h" +#include "zonelist.h" +#include "../common/logsys.h" +#include "../common/logtypes.h" +#include "../common/md5.h" +#include "../common/EmuTCPConnection.h" +#include "../common/packet_dump.h" + +extern ClientList client_list; +extern ZSList zoneserver_list; + +Socket_Server_Connection::Socket_Server_Connection() +{ + Stream = 0; + authenticated = false; +} + +void Socket_Server_Connection::SetConnection(EmuTCPConnection *inStream) +{ + if(Stream) + { + _log(SOCKET_SERVER__ERROR, "Incoming Socket_Server Connection while we were already connected to a Socket_Server."); + Stream->Disconnect(); + } + + Stream = inStream; + + authenticated = false; +} + +bool Socket_Server_Connection::Process() +{ + if (!Stream || !Stream->Connected()) + return false; + + ServerPacket *pack = 0; + + while((pack = Stream->PopPacket())) + { + if (!authenticated) + { + if (WorldConfig::get()->SharedKey.length() > 0) + { + if (pack->opcode == ServerOP_ZAAuth && pack->size == 16) + { + uint8 tmppass[16]; + + MD5::Generate((const uchar*) WorldConfig::get()->SharedKey.c_str(), WorldConfig::get()->SharedKey.length(), tmppass); + + if (memcmp(pack->pBuffer, tmppass, 16) == 0) + authenticated = true; + else + { + struct in_addr in; + in.s_addr = GetIP(); + _log(SOCKET_SERVER__ERROR, "Socket_Server authorization failed."); + ServerPacket* pack = new ServerPacket(ServerOP_ZAAuthFailed); + SendPacket(pack); + delete pack; + Disconnect(); + return false; + } + } + else + { + struct in_addr in; + in.s_addr = GetIP(); + _log(SOCKET_SERVER__ERROR, "Socket_Server_ authorization failed."); + ServerPacket* pack = new ServerPacket(ServerOP_ZAAuthFailed); + SendPacket(pack); + delete pack; + Disconnect(); + return false; + } + } + else + { + _log(SOCKET_SERVER__ERROR,"**WARNING** You have not configured a world shared key in your config file. You should add a STRING element to your element to prevent unauthorized zone access."); + authenticated = true; + } + delete pack; + continue; + } + switch(pack->opcode) + { + case 0: + break; + + case ServerOP_KeepAlive: + { + // ignore this + break; + } + case ServerOP_ZAAuth: + { + _log(SOCKET_SERVER__ERROR, "Got authentication from Socket_Server_ when they are already authenticated."); + break; + } + case ServerOP_LFGuildUpdate: + { + zoneserver_list.SendPacket(pack); + break; + } + default: + { + _log(SOCKET_SERVER__ERROR, "Unknown ServerOPcode from Socket_Server_ 0x%04x, size %d", pack->opcode, pack->size); + DumpPacket(pack->pBuffer, pack->size); + break; + } + } + + delete pack; + } + return(true); +} + +bool Socket_Server_Connection::SendPacket(ServerPacket* pack) +{ + if(!Stream) + return false; + + return Stream->SendPacket(pack); +} + diff --git a/world/socket_server.h b/world/socket_server.h new file mode 100644 index 000000000..7cb39c2d6 --- /dev/null +++ b/world/socket_server.h @@ -0,0 +1,23 @@ +#ifndef Socket_Server__H +#define Socket_Server__H + +#include "../common/types.h" +#include "../common/EmuTCPConnection.h" +#include "../common/servertalk.h" + +class Socket_Server_Connection +{ +public: + Socket_Server_Connection(); + void SetConnection(EmuTCPConnection *inStream); + bool Process(); + bool SendPacket(ServerPacket* pack); + void Disconnect() { if(Stream) Stream->Disconnect(); } + void SendMessage(const char *From, const char *Message); +private: + inline uint32 GetIP() const { return Stream ? Stream->GetrIP() : 0; } + EmuTCPConnection *Stream; + bool authenticated; +}; + +#endif /*Socket_Server__H_*/ From d0416d5f35f140532bc50addbfe8a63ad33f42c3 Mon Sep 17 00:00:00 2001 From: Chris M Date: Thu, 3 Jul 2014 03:25:58 -0500 Subject: [PATCH 075/288] More Socket Server work. Made Socket server a by default disabled option in the CMake configuration while development is underway. For now, do not use. --- CMakeLists.txt | 8 ++ socket_server/CMakeLists.txt | 2 +- socket_server/socket_server.cpp | 166 ++++++++++++++++++++++++++++++++ socket_server/worldserver.cpp | 1 - 4 files changed, 175 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d3adcc25..55d9a4cfb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -229,6 +229,7 @@ ENDIF(EQEMU_ENABLE_BOTS) #What to build OPTION(EQEMU_BUILD_SERVER "Build the game server." ON) OPTION(EQEMU_BUILD_LOGIN "Build the login server." OFF) +OPTION(EQEMU_BUILD_SOCKET_SERVER "Build the socket server." OFF) OPTION(EQEMU_BUILD_TESTS "Build utility tests." OFF) OPTION(EQEMU_BUILD_PERL "Build Perl parser." ON) OPTION(EQEMU_BUILD_LUA "Build Lua parser." OFF) @@ -297,6 +298,13 @@ IF(EQEMU_BUILD_LUA) ENDIF(EQEMU_SANITIZE_LUA_LIBS) ENDIF(EQEMU_BUILD_LUA) +IF(EQEMU_BUILD_SOCKET_SERVER) + FIND_PACKAGE(Boost COMPONENTS system filesystem thread REQUIRED) + INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/dependencies/websocketpp") + ADD_DEFINITIONS(-D_WEBSOCKETPP_CPP11_STL_) + +ENDIF(EQEMU_BUILD_SOCKET_SERVER) + INCLUDE_DIRECTORIES("${ZLIB_INCLUDE_DIRS}" "${MySQL_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/common/glm/glm") IF(EQEMU_BUILD_LUA) diff --git a/socket_server/CMakeLists.txt b/socket_server/CMakeLists.txt index f647863d9..abaec0f21 100644 --- a/socket_server/CMakeLists.txt +++ b/socket_server/CMakeLists.txt @@ -19,7 +19,7 @@ INSTALL(TARGETS socket_server RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}) ADD_DEFINITIONS(-DQSERV) -TARGET_LINK_LIBRARIES(socket_server Common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY}) +TARGET_LINK_LIBRARIES(socket_server Common ${Boost_LIBRARIES} debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY}) IF(MSVC) SET_TARGET_PROPERTIES(socket_server PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF") diff --git a/socket_server/socket_server.cpp b/socket_server/socket_server.cpp index eed4751d1..997d9965f 100644 --- a/socket_server/socket_server.cpp +++ b/socket_server/socket_server.cpp @@ -17,6 +17,26 @@ */ +#include +#include +#include +/*#include +#include +#include */ +#include + +typedef websocketpp::server server; + +using websocketpp::connection_hdl; +using websocketpp::lib::placeholders::_1; +using websocketpp::lib::placeholders::_2; +using websocketpp::lib::bind; + +using websocketpp::lib::thread; +using websocketpp::lib::mutex; +using websocketpp::lib::unique_lock; +using websocketpp::lib::condition_variable; + #include "../common/debug.h" #include "../common/opcodemgr.h" #include "../common/EQStreamFactory.h" @@ -44,7 +64,150 @@ void CatchSignal(int sig_num) { worldserver->Disconnect(); } +/* Web Sockets Start Shit */ + +enum action_type { + SUBSCRIBE, + UNSUBSCRIBE, + MESSAGE +}; + +struct action { + action(action_type t, connection_hdl h) : type(t), hdl(h) {} + action(action_type t, connection_hdl h, server::message_ptr m) + : type(t), hdl(h), msg(m) {} + + action_type type; + websocketpp::connection_hdl hdl; + server::message_ptr msg; +}; + +class broadcast_server { +public: + broadcast_server() { + // Initialize Asio Transport + m_server.init_asio(); + + // Register handler callbacks + m_server.set_open_handler(bind(&broadcast_server::on_open, this, ::_1)); + m_server.set_close_handler(bind(&broadcast_server::on_close, this, ::_1)); + m_server.set_message_handler(bind(&broadcast_server::on_message, this, ::_1, ::_2)); + } + + void run(uint16_t port) { + // listen on specified port + m_server.listen(port); + + // Start the server accept loop + m_server.start_accept(); + + // Start the ASIO io_service run loop + try { + m_server.run(); + } + catch (const std::exception & e) { + std::cout << e.what() << std::endl; + } + catch (websocketpp::lib::error_code e) { + std::cout << e.message() << std::endl; + } + catch (...) { + std::cout << "other exception" << std::endl; + } + } + + void on_open(connection_hdl hdl) { + unique_lock lock(m_action_lock); + //std::cout << "on_open" << std::endl; + m_actions.push(action(SUBSCRIBE, hdl)); + lock.unlock(); + m_action_cond.notify_one(); + } + + void on_close(connection_hdl hdl) { + unique_lock lock(m_action_lock); + //std::cout << "on_close" << std::endl; + m_actions.push(action(UNSUBSCRIBE, hdl)); + lock.unlock(); + m_action_cond.notify_one(); + } + + void on_message(connection_hdl hdl, server::message_ptr msg) { + // queue message up for sending by processing thread + unique_lock lock(m_action_lock); + msg->set_payload("Niggers"); + // std::cout << "on_message" << std::endl; + m_actions.push(action(MESSAGE, hdl, msg)); + lock.unlock(); + m_action_cond.notify_one(); + } + + void process_messages() { + while (1) { + unique_lock lock(m_action_lock); + + while (m_actions.empty()) { + m_action_cond.wait(lock); + } + + action a = m_actions.front(); + m_actions.pop(); + + lock.unlock(); + + if (a.type == SUBSCRIBE) { + unique_lock con_lock(m_connection_lock); + m_connections.insert(a.hdl); + } + else if (a.type == UNSUBSCRIBE) { + unique_lock con_lock(m_connection_lock); + m_connections.erase(a.hdl); + } + else if (a.type == MESSAGE) { + unique_lock con_lock(m_connection_lock); + + con_list::iterator it; + for (it = m_connections.begin(); it != m_connections.end(); ++it) { + m_server.send(*it, a.msg); + } + } + else { + // undefined. + } + } + } +private: + typedef std::set> con_list; + + server m_server; + con_list m_connections; + std::queue m_actions; + + mutex m_action_lock; + mutex m_connection_lock; + condition_variable m_action_cond; +}; + +/* Web Sockets Shit End*/ + int main() { + + try { + broadcast_server server_instance; + + // Start a thread to run the processing loop + thread t(bind(&broadcast_server::process_messages, &server_instance)); + + // Run the asio loop with the main thread + server_instance.run(9002); + + t.join(); + + } + catch (std::exception & e) { + std::cout << e.what() << std::endl; + } + RegisterExecutablePlatform(ExePlatformSocket_Server); set_exception_handler(); Timer InterserverTimer(INTERSERVER_TIMER); // does auto-reconnect @@ -99,6 +262,9 @@ int main() { timeout_manager.CheckTimeouts(); Sleep(100); } + + + } void UpdateWindowTitle(char* iNewTitle) { diff --git a/socket_server/worldserver.cpp b/socket_server/worldserver.cpp index f4e7cdf76..9c6afa138 100644 --- a/socket_server/worldserver.cpp +++ b/socket_server/worldserver.cpp @@ -28,7 +28,6 @@ #include "worldserver.h" #include "socket_server_config.h" #include "database.h" -#include "lfguild.h" #include "../common/packet_functions.h" #include "../common/md5.h" #include "../common/packet_dump.h" From 9a634a2056747c857d19173a67d1c6f36c578d24 Mon Sep 17 00:00:00 2001 From: Chris M Date: Thu, 3 Jul 2014 18:16:43 -0500 Subject: [PATCH 076/288] Removing socket server from cmake for now and maintaining it in its own branch until push to master --- CMakeLists.txt | 8 -------- 1 file changed, 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 55d9a4cfb..a9dd5a96b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -298,13 +298,6 @@ IF(EQEMU_BUILD_LUA) ENDIF(EQEMU_SANITIZE_LUA_LIBS) ENDIF(EQEMU_BUILD_LUA) -IF(EQEMU_BUILD_SOCKET_SERVER) - FIND_PACKAGE(Boost COMPONENTS system filesystem thread REQUIRED) - INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/dependencies/websocketpp") - ADD_DEFINITIONS(-D_WEBSOCKETPP_CPP11_STL_) - -ENDIF(EQEMU_BUILD_SOCKET_SERVER) - INCLUDE_DIRECTORIES("${ZLIB_INCLUDE_DIRS}" "${MySQL_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/common/glm/glm") IF(EQEMU_BUILD_LUA) @@ -320,7 +313,6 @@ IF(EQEMU_BUILD_SERVER) ADD_SUBDIRECTORY(zone) ADD_SUBDIRECTORY(ucs) ADD_SUBDIRECTORY(queryserv) - ADD_SUBDIRECTORY(socket_server) ADD_SUBDIRECTORY(eqlaunch) ENDIF(EQEMU_BUILD_SERVER) IF(EQEMU_BUILD_LOGIN) From 6a59b83d43b7b92ab528df913bd71fe269b14fbf Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 18:57:54 -0700 Subject: [PATCH 077/288] StringFormat converted to move semantics --- client_files/import/main.cpp | 6 +++--- common/Item.cpp | 6 ++---- common/StringUtil.cpp | 33 ++++++++++++++------------------- common/StringUtil.h | 5 +++-- common/logsys_eqemu.cpp | 4 +--- world/world_logsys.cpp | 9 ++++----- 6 files changed, 27 insertions(+), 36 deletions(-) diff --git a/client_files/import/main.cpp b/client_files/import/main.cpp index 8115600bf..cba52e584 100644 --- a/client_files/import/main.cpp +++ b/client_files/import/main.cpp @@ -175,14 +175,14 @@ void ImportSkillCaps(SharedDatabase *db) { continue; } - std::string sql; + int class_id, skill_id, level, cap; class_id = atoi(split[0].c_str()); skill_id = atoi(split[1].c_str()); level = atoi(split[2].c_str()); cap = atoi(split[3].c_str()); - StringFormat(sql, "INSERT INTO skill_caps(class, skillID, level, cap) VALUES(%d, %d, %d, %d)", + std::string sql = StringFormat("INSERT INTO skill_caps(class, skillID, level, cap) VALUES(%d, %d, %d, %d)", class_id, skill_id, level, cap); db->RunQuery(sql.c_str(), (uint32)sql.length()); @@ -226,7 +226,7 @@ void ImportBaseData(SharedDatabase *db) { mana_fac = atof(split[8].c_str()); end_fac = atof(split[9].c_str()); - StringFormat(sql, "INSERT INTO base_data(level, class, hp, mana, end, unk1, unk2, hp_fac, " + sql = StringFormat("INSERT INTO base_data(level, class, hp, mana, end, unk1, unk2, hp_fac, " "mana_fac, end_fac) VALUES(%d, %d, %f, %f, %f, %f, %f, %f, %f, %f)", level, class_id, hp, mana, end, unk1, unk2, hp_fac, mana_fac, end_fac); diff --git a/common/Item.cpp b/common/Item.cpp index 975275c41..74c76d778 100644 --- a/common/Item.cpp +++ b/common/Item.cpp @@ -893,8 +893,7 @@ void Inventory::dumpItemCollection(const std::map &collection) if (!inst || !inst->GetItem()) continue; - std::string slot; - StringFormat(slot, "Slot %d: %s (%d)", it->first, it->second->GetItem()->Name, (inst->GetCharges() <= 0) ? 1 : inst->GetCharges()); + std::string slot = StringFormat("Slot %d: %s (%d)", it->first, it->second->GetItem()->Name, (inst->GetCharges() <= 0) ? 1 : inst->GetCharges()); std::cout << slot << std::endl; dumpBagContents(inst, &it); @@ -913,8 +912,7 @@ void Inventory::dumpBagContents(ItemInst *inst, iter_inst *it) { if (!baginst || !baginst->GetItem()) continue; - std::string subSlot; - StringFormat(subSlot, " Slot %d: %s (%d)", Inventory::CalcSlotId((*it)->first, itb->first), + std::string subSlot = StringFormat(" Slot %d: %s (%d)", Inventory::CalcSlotId((*it)->first, itb->first), baginst->GetItem()->Name, (baginst->GetCharges() <= 0) ? 1 : baginst->GetCharges()); std::cout << subSlot << std::endl; } diff --git a/common/StringUtil.cpp b/common/StringUtil.cpp index b89a1455d..80c92fa88 100644 --- a/common/StringUtil.cpp +++ b/common/StringUtil.cpp @@ -38,8 +38,9 @@ // original source: // https://github.com/facebook/folly/blob/master/folly/String.cpp // -void vStringFormat(std::string& output, const char* format, va_list args) +const std::string vStringFormat(const char* format, va_list args) { + std::string output; va_list tmpargs; va_copy(tmpargs,args); @@ -48,11 +49,8 @@ void vStringFormat(std::string& output, const char* format, va_list args) if (characters_used < 0) { // Looks like we have an invalid format string. - // error out. - std::string errorMessage("Invalid format string; snprintf returned negative with format string: "); - errorMessage.append(format); - - throw std::runtime_error(errorMessage); + // return empty string. + return ""; } else if ((unsigned int)characters_used > output.capacity()) { output.resize(characters_used+1); @@ -62,12 +60,10 @@ void vStringFormat(std::string& output, const char* format, va_list args) if (characters_used < 0) { // We shouldn't have a format error by this point, but I can't imagine what error we - // could have by this point. Still, error out and report it. - std::string errorMessage("Invalid format string or unknown vsnprintf error; vsnprintf returned negative with format string: "); - errorMessage.append(format); - - throw std::runtime_error(errorMessage); + // could have by this point. Still, return empty string; + return ""; } + return std::move(output); } else { output.resize(characters_used + 1); @@ -78,24 +74,23 @@ void vStringFormat(std::string& output, const char* format, va_list args) if (characters_used < 0) { // We shouldn't have a format error by this point, but I can't imagine what error we - // could have by this point. still error out and report it. - std::string errorMessage("Invalid format string or unknown vsnprintf error; vsnprintf returned negative with format string: "); - errorMessage.append(format); - - throw std::runtime_error(errorMessage); + // could have by this point. Still, return empty string; + return ""; } - + return std::move(output); } } -void StringFormat(std::string& output, const char* format, ...) +const std::string StringFormat(const char* format, ...) { va_list args; va_start(args, format); - vStringFormat(output,format,args); + std::string output = vStringFormat(format,args); va_end(args); + return std::move(output); } + // normal strncpy doesnt put a null term on copied strings, this one does // ref: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcecrt/htm/_wcecrt_strncpy_wcsncpy.asp char* strn0cpy(char* dest, const char* source, uint32 size) { diff --git a/common/StringUtil.h b/common/StringUtil.h index 2e4182bf8..fe7e83edf 100644 --- a/common/StringUtil.h +++ b/common/StringUtil.h @@ -19,11 +19,12 @@ #include #include #include +#include #include "types.h" -void vStringFormat(std::string& output, const char* format, va_list args); -void StringFormat(std::string& output, const char* format, ...); +const std::string vStringFormat(const char* format, va_list args); +const std::string StringFormat(const char* format, ...); std::string EscapeString(const std::string &s); const char *MakeLowerString(const char *source); diff --git a/common/logsys_eqemu.cpp b/common/logsys_eqemu.cpp index 5086114f5..e1e75996c 100644 --- a/common/logsys_eqemu.cpp +++ b/common/logsys_eqemu.cpp @@ -33,9 +33,7 @@ void log_message(LogType type, const char *fmt, ...) { } void log_messageVA(LogType type, const char *fmt, va_list args) { - std::string prefix_buffer; - - StringFormat(prefix_buffer, "[%s] ", log_type_info[type].name); + std::string prefix_buffer = StringFormat("[%s] ", log_type_info[type].name); LogFile->writePVA(EQEMuLog::Debug, prefix_buffer.c_str(), fmt, args); } diff --git a/world/world_logsys.cpp b/world/world_logsys.cpp index f60186a86..d7f798b6c 100644 --- a/world/world_logsys.cpp +++ b/world/world_logsys.cpp @@ -12,8 +12,7 @@ void log_message_clientVA(LogType type, Client *who, const char *fmt, va_list args) { - std::string prefix_buffer; - StringFormat(prefix_buffer,"[%s] %s: ", log_type_info[type].name, who->GetAccountName()); + std::string prefix_buffer = StringFormat("[%s] %s: ", log_type_info[type].name, who->GetAccountName()); LogFile->writePVA(EQEMuLog::Debug, prefix_buffer.c_str(), fmt, args); } @@ -31,11 +30,11 @@ void log_message_zoneVA(LogType type, ZoneServer *who, const char *fmt, va_list const char *zone_name=who->GetZoneName(); if (zone_name == nullptr) - StringFormat(zone_tag,"[%d]", who->GetID()); + zone_tag = StringFormat("[%d]", who->GetID()); else - StringFormat(zone_tag,"[%d] [%s]",who->GetID(),zone_name); + zone_tag = StringFormat("[%d] [%s]",who->GetID(),zone_name); - StringFormat(prefix_buffer, "[%s] %s ", log_type_info[type].name, zone_tag.c_str()); + prefix_buffer = StringFormat("[%s] %s ", log_type_info[type].name, zone_tag.c_str()); LogFile->writePVA(EQEMuLog::Debug, prefix_buffer.c_str(), fmt, args); } From 2fe133fa0e72bddc24bc0bc308009d66e458beb0 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 19:29:38 -0700 Subject: [PATCH 078/288] GetServerType converted to QueryDatabase --- common/database.cpp | 43 ++++++++++++++++--------------------------- 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 0e68ddc91..40e02312a 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1454,34 +1454,23 @@ bool Database::CheckUsedName(const char* name) uint8 Database::GetServerType() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT value FROM variables WHERE varname='ServerType'"), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) - { - row = mysql_fetch_row(result); - uint8 ServerType = atoi(row[0]); - mysql_free_result(result); - return ServerType; - } - else - { - mysql_free_result(result); - return 0; - } - mysql_free_result(result); - } - else - { - std::cerr << "Error in GetServerType query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; - } - return 0; + char *query = nullptr; + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT value FROM variables WHERE varname='ServerType'")); + + if (!results.Success()) + { + std::cerr << "Error in GetServerType query '" << query << "' " << results.ErrorMessage() << std::endl; + safe_delete_array(query); + return 0; + } + safe_delete_array(query); + + if (results.RowCount() != 1) + return 0; + + auto row = results.begin(); + return atoi(row[0]); } bool Database::MoveCharacterToZone(const char* charname, const char* zonename,uint32 zoneid) { From fdbb16607680850b63be7ec23080cd25fef0c6b5 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 19:31:41 -0700 Subject: [PATCH 079/288] MoveCharacterToZone converted to QueryDatabase --- common/database.cpp | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 40e02312a..160391c3b 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1474,20 +1474,22 @@ uint8 Database::GetServerType() } bool Database::MoveCharacterToZone(const char* charname, const char* zonename,uint32 zoneid) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; + char *query = nullptr; if(zonename == nullptr || strlen(zonename) == 0) - return(false); + return false; - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET zonename = '%s',zoneid=%i,x=-1, y=-1, z=-1 WHERE name='%s'", zonename,zoneid, charname), errbuf, 0,&affected_rows)) { - std::cerr << "Error in MoveCharacterToZone(name) query '" << query << "' " << errbuf << std::endl; + auto results = QueryDatabase(query, MakeAnyLenString(&query, "UPDATE character_ SET zonename = '%s',zoneid=%i,x=-1, y=-1, z=-1 WHERE name='%s'", zonename,zoneid, charname)); + + if (!results.Success()) + { + std::cerr << "Error in MoveCharacterToZone(name) query '" << query << "' " << results.ErrorMessage() << std::endl; + safe_delete_array(query); return false; } safe_delete_array(query); - if (affected_rows == 0) + if (results.RowsAffected() == 0) return false; return true; @@ -1498,19 +1500,19 @@ bool Database::MoveCharacterToZone(const char* charname, const char* zonename) { } bool Database::MoveCharacterToZone(uint32 iCharID, const char* iZonename) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET zonename = '%s', zoneid=%i, x=-1, y=-1, z=-1 WHERE id=%i", iZonename, GetZoneID(iZonename), iCharID), errbuf, 0,&affected_rows)) { + char *query = nullptr; + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "UPDATE character_ SET zonename = '%s', zoneid=%i, x=-1, y=-1, z=-1 WHERE id=%i", iZonename, GetZoneID(iZonename), iCharID)); + + if (!results.Success()) + { std::cerr << "Error in MoveCharacterToZone(id) query '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); return false; } safe_delete_array(query); - if (affected_rows == 0) - return false; - - return true; + return results.RowsAffected() != 0; } uint8 Database::CopyCharacter(const char* oldname, const char* newname, uint32 acctid) { From 7b551f0399fc137bdff63c66ce0cd65fdc60de47 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 19:57:52 -0700 Subject: [PATCH 080/288] CopyCharacter converted to QueryDatabase --- common/database.cpp | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 160391c3b..827288f2b 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1516,34 +1516,28 @@ bool Database::MoveCharacterToZone(uint32 iCharID, const char* iZonename) { } uint8 Database::CopyCharacter(const char* oldname, const char* newname, uint32 acctid) { - //TODO: Rewrite better function - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; PlayerProfile_Struct* pp; ExtendedProfile_Struct* ext; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT profile, extprofile FROM character_ WHERE name='%s'", oldname), errbuf, &result)) { - safe_delete_array(query); + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT profile, extprofile FROM character_ WHERE name='%s'", oldname)); - row = mysql_fetch_row(result); - - pp = (PlayerProfile_Struct*)row[0]; - strcpy(pp->name, newname); - - ext = (ExtendedProfile_Struct*)row[1]; - - mysql_free_result(result); - } - - else { - std::cerr << "Error in CopyCharacter read query '" << query << "' " << errbuf << std::endl; + if (!results.Success()) + { + std::cerr << "Error in CopyCharacter read query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); return 0; } + safe_delete_array(query); + + auto row = results.begin(); + + pp = (PlayerProfile_Struct*)row[0]; + strcpy(pp->name, newname); + + ext = (ExtendedProfile_Struct*)row[1]; + - uint32 affected_rows = 0; char query2[276 + sizeof(PlayerProfile_Struct)*2 + sizeof(ExtendedProfile_Struct)*2 + 1]; char* end=query2; @@ -1553,6 +1547,14 @@ uint8 Database::CopyCharacter(const char* oldname, const char* newname, uint32 a end += DoEscapeString(end, (char*) ext, sizeof(ExtendedProfile_Struct)); end += sprintf(end, "\', account_id=%d, name='%s'", acctid, newname); + results = QueryDatabase(query2, (uint32) (end - query2)); + + if (!results.Success()) + { + std::cerr << "Error in CopyCharacter query '" << query2 << "' " << results.ErrorMessage() << std::endl; + return 0; + } + if (!RunQuery(query2, (uint32) (end - query2), errbuf, 0, &affected_rows)) { std::cerr << "Error in CopyCharacter query '" << query << "' " << errbuf << std::endl; return 0; From bf2d65d7e96ab637f87541d07734a0d8c355a7cb Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 19:59:35 -0700 Subject: [PATCH 081/288] SetHackerFlag converted to QueryDatabase --- common/database.cpp | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 827288f2b..4b441b955 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1555,34 +1555,26 @@ uint8 Database::CopyCharacter(const char* oldname, const char* newname, uint32 a return 0; } - if (!RunQuery(query2, (uint32) (end - query2), errbuf, 0, &affected_rows)) { - std::cerr << "Error in CopyCharacter query '" << query << "' " << errbuf << std::endl; + if (results.RowsAffected() == 0) return 0; - } - - if (affected_rows == 0) { - return 0; - } return 1; } bool Database::SetHackerFlag(const char* accountname, const char* charactername, const char* hacked) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO hackers(account,name,hacked) values('%s','%s','%s')", accountname, charactername, hacked), errbuf, 0,&affected_rows)) { + char *query = nullptr; + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "INSERT INTO hackers(account,name,hacked) values('%s','%s','%s')", accountname, charactername, hacked)); + + if (!results.Success()) + { std::cerr << "Error in SetHackerFlag query '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); return false; } safe_delete_array(query); - if (affected_rows == 0) - { - return false; - } - - return true; + return results.RowsAffected() != 0; } bool Database::SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone) { //Utilize the "hacker" table, but also give zone information. From 853f1b56e54548fca1ea72385497cd3f1822dbd1 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 20:13:38 -0700 Subject: [PATCH 082/288] SetMQDetectionFlag converted to QueryDatabase --- common/database.cpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 4b441b955..680dc3ce0 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1577,25 +1577,21 @@ bool Database::SetHackerFlag(const char* accountname, const char* charactername, return results.RowsAffected() != 0; } -bool Database::SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone) { //Utilize the "hacker" table, but also give zone information. +bool Database::SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone) { + //Utilize the "hacker" table, but also give zone information. + char *query = nullptr; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; + auto results = QueryDatabase(query, MakeAnyLenString(&query, "INSERT INTO hackers(account,name,hacked,zone) values('%s','%s','%s','%s')", accountname, charactername, hacked, zone)); - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO hackers(account,name,hacked,zone) values('%s','%s','%s','%s')", accountname, charactername, hacked, zone), errbuf, 0,&affected_rows)) { - std::cerr << "Error in SetMQDetectionFlag query '" << query << "' " << errbuf << std::endl; + if (!results.Success()) + { + safe_delete_array(query); + std::cerr << "Error in SetMQDetectionFlag query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } - safe_delete_array(query); - if (affected_rows == 0) - { - return false; - } - - return true; + return results.RowsAffected() != 0; } uint8 Database::GetRaceSkill(uint8 skillid, uint8 in_race) From 4eea1e0468583115ccfda4f15ec5ecc1c08b6fa7 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 20:31:56 -0700 Subject: [PATCH 083/288] GetRaceSkill converted to QueryDatabase --- common/database.cpp | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 680dc3ce0..70c266e8c 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1597,25 +1597,21 @@ bool Database::SetMQDetectionFlag(const char* accountname, const char* character uint8 Database::GetRaceSkill(uint8 skillid, uint8 in_race) { uint16 race_cap = 0; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; //Check for a racial cap! - if (RunQuery(query, MakeAnyLenString(&query, "SELECT skillcap from race_skillcaps where skill = %i && race = %i", skillid, in_race), errbuf, &result, &affected_rows)) - { - if (affected_rows != 0) - { - row = mysql_fetch_row(result); - race_cap = atoi(row[0]); - } - delete[] query; - mysql_free_result(result); - } - return race_cap; + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT skillcap from race_skillcaps where skill = %i && race = %i", skillid, in_race)); + safe_delete_array(query); + + if (!results.Success()) + return 0; + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + return atoi(row[0]); } uint8 Database::GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level) From a054b83b922c8fad89be5abc8ee3df7b43f8223a Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 21:01:55 -0700 Subject: [PATCH 084/288] GetSkillCap converted to QueryDatabase --- common/database.cpp | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 70c266e8c..4507a86bd 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1618,26 +1618,21 @@ uint8 Database::GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 { uint8 skill_level = 0, skill_formula = 0; uint16 base_cap = 0, skill_cap = 0, skill_cap2 = 0, skill_cap3 = 0; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; + //Fetch the data from DB. - if (RunQuery(query, MakeAnyLenString(&query, "SELECT level, formula, pre50cap, post50cap, post60cap from skillcaps where skill = %i && class = %i", skillid, in_class), errbuf, &result, &affected_rows)) + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT level, formula, pre50cap, post50cap, post60cap from skillcaps where skill = %i && class = %i", skillid, in_class)); + safe_delete_array(query); + + if (results.Success() && results.RowsAffected() != 0) { - if (affected_rows != 0) - { - row = mysql_fetch_row(result); - skill_level = atoi(row[0]); - skill_formula = atoi(row[1]); - skill_cap = atoi(row[2]); - if (atoi(row[3]) > skill_cap) - skill_cap2 = (atoi(row[3])-skill_cap)/10; //Split the post-50 skill cap into difference between pre-50 cap and post-50 cap / 10 to determine amount of points per level. - skill_cap3 = atoi(row[4]); - } - delete[] query; - mysql_free_result(result); + auto row = results.begin(); + skill_level = atoi(row[0]); + skill_formula = atoi(row[1]); + skill_cap = atoi(row[2]); + if (atoi(row[3]) > skill_cap) + skill_cap2 = (atoi(row[3])-skill_cap)/10; //Split the post-50 skill cap into difference between pre-50 cap and post-50 cap / 10 to determine amount of points per level. + skill_cap3 = atoi(row[4]); } int race_skill = GetRaceSkill(skillid,in_race); @@ -1656,12 +1651,15 @@ uint8 Database::GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 base_cap = in_level*skill_formula+skill_formula; if (base_cap > skill_cap || skill_formula == 0) base_cap = skill_cap; + //If post 50, add post 50 cap to base cap. if (in_level > 50 && skill_cap2 > 0) base_cap += skill_cap2*(in_level-50); + //No cap should ever go above its post50cap if (skill_cap3 > 0 && base_cap > skill_cap3) base_cap = skill_cap3; + //Base cap is now the max value at the person's level, return it! return base_cap; } From f7c637a0d9e259e01283e5d2654451fc37d71f96 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 21:14:27 -0700 Subject: [PATCH 085/288] Errbuf fix and GetCharacterInfo converted to QueryDatabase --- common/database.cpp | 62 ++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 4507a86bd..b84b4c517 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1506,7 +1506,7 @@ bool Database::MoveCharacterToZone(uint32 iCharID, const char* iZonename) { if (!results.Success()) { - std::cerr << "Error in MoveCharacterToZone(id) query '" << query << "' " << errbuf << std::endl; + std::cerr << "Error in MoveCharacterToZone(id) query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); return false; } @@ -1568,7 +1568,7 @@ bool Database::SetHackerFlag(const char* accountname, const char* charactername, if (!results.Success()) { - std::cerr << "Error in SetHackerFlag query '" << query << "' " << errbuf << std::endl; + std::cerr << "Error in SetHackerFlag query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); return false; } @@ -1665,38 +1665,38 @@ uint8 Database::GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 } uint32 Database::GetCharacterInfo(const char* iName, uint32* oAccID, uint32* oZoneID, uint32* oInstanceID, float* oX, float* oY, float* oZ) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, account_id, zonename, instanceid, x, y, z FROM character_ WHERE name='%s'", iName), errbuf, &result)) { + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT id, account_id, zonename, instanceid, x, y, z FROM character_ WHERE name='%s'", iName)); + + if (!results.Success()) + { + std::cerr << "Error in GetCharacterInfo query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - uint32 charid = atoi(row[0]); - if (oAccID) - *oAccID = atoi(row[1]); - if (oZoneID) - *oZoneID = GetZoneID(row[2]); - if(oInstanceID) - *oInstanceID = atoi(row[3]); - if (oX) - *oX = atof(row[4]); - if (oY) - *oY = atof(row[5]); - if (oZ) - *oZ = atof(row[6]); - mysql_free_result(result); - return charid; - } - mysql_free_result(result); + return 0; } - else { - std::cerr << "Error in GetCharacterInfo query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - } - return 0; + safe_delete_array(query); + + if (results.RowCount() != 1) + return 0; + + auto row = results.begin(); + + uint32 charid = atoi(row[0]); + if (oAccID) + *oAccID = atoi(row[1]); + if (oZoneID) + *oZoneID = GetZoneID(row[2]); + if(oInstanceID) + *oInstanceID = atoi(row[3]); + if (oX) + *oX = atof(row[4]); + if (oY) + *oY = atof(row[5]); + if (oZ) + *oZ = atof(row[6]); + + return charid; } bool Database::UpdateLiveChar(char* charname,uint32 lsaccount_id) { From b169dbd09df3472a44b46d6b22a322ad6a49453b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 3 Jul 2014 21:16:31 -0700 Subject: [PATCH 086/288] UpdateLiveChar converted to QueryDatabase --- common/database.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index b84b4c517..60382d6e8 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1700,15 +1700,18 @@ uint32 Database::GetCharacterInfo(const char* iName, uint32* oAccID, uint32* oZo } bool Database::UpdateLiveChar(char* charname,uint32 lsaccount_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE account SET charname='%s' WHERE id=%i;",charname, lsaccount_id), errbuf)) { - std::cerr << "Error in UpdateLiveChar query '" << query << "' " << errbuf << std::endl; + char *query = nullptr; + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "UPDATE account SET charname='%s' WHERE id=%i;",charname, lsaccount_id)); + + if (!results.Success()) + { + std::cerr << "Error in UpdateLiveChar query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); return false; } - safe_delete_array(query); + return true; } From 7048fcc3582a4bc011d3afe29644fd5250da08e8 Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 3 Jul 2014 21:49:14 -0700 Subject: [PATCH 087/288] Fix for GCC+11 compile --- common/MySQLRequestResult.h | 5 ++++- common/MySQLRequestRow.cpp | 11 ++++++++++- common/MySQLRequestRow.h | 3 ++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/common/MySQLRequestResult.h b/common/MySQLRequestResult.h index ef2dcd104..05f363722 100644 --- a/common/MySQLRequestResult.h +++ b/common/MySQLRequestResult.h @@ -10,6 +10,8 @@ #include <../common/types.h> #include <../common/MySQLRequestRow.h> #include +#include +#include class MySQLRequestResult { private: @@ -52,4 +54,5 @@ private: }; -#endif \ No newline at end of file +#endif + diff --git a/common/MySQLRequestRow.cpp b/common/MySQLRequestRow.cpp index 5fc4a40e8..d00cbc835 100644 --- a/common/MySQLRequestRow.cpp +++ b/common/MySQLRequestRow.cpp @@ -19,6 +19,15 @@ MySQLRequestRow::MySQLRequestRow(MySQLRequestRow&& moveItem) moveItem.m_MySQLRow = nullptr; } +MySQLRequestRow& MySQLRequestRow::operator=(MySQLRequestRow& moveItem) +{ + m_Result = moveItem.m_Result; + m_MySQLRow = moveItem.m_MySQLRow; + + moveItem.m_Result = nullptr; + moveItem.m_MySQLRow = nullptr; +} + MySQLRequestRow::MySQLRequestRow(MYSQL_RES *result) : m_Result(result), m_MySQLRow(mysql_fetch_row(m_Result)) { @@ -51,4 +60,4 @@ char* MySQLRequestRow::operator[](int index) { return m_MySQLRow[index]; -} \ No newline at end of file +} diff --git a/common/MySQLRequestRow.h b/common/MySQLRequestRow.h index 615a75371..8e979acab 100644 --- a/common/MySQLRequestRow.h +++ b/common/MySQLRequestRow.h @@ -23,6 +23,7 @@ public: MySQLRequestRow(MYSQL_RES *result); MySQLRequestRow(const MySQLRequestRow& row); MySQLRequestRow(MySQLRequestRow&& moveItem); + MySQLRequestRow& operator=(MySQLRequestRow& moveItem); MySQLRequestRow& operator++(); MySQLRequestRow operator++(int); bool operator==(const MySQLRequestRow& rhs); @@ -34,4 +35,4 @@ public: -#endif \ No newline at end of file +#endif From cc69e81dabe1dabf0afbed790a887f72eacca1c3 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 4 Jul 2014 00:46:53 -0400 Subject: [PATCH 088/288] Fix case-sensitive issue --- world/socket_server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/world/socket_server.cpp b/world/socket_server.cpp index 826a95620..3c6631c49 100644 --- a/world/socket_server.cpp +++ b/world/socket_server.cpp @@ -1,5 +1,5 @@ #include "../common/debug.h" -#include "Socket_Server.h" +#include "socket_server.h" #include "WorldConfig.h" #include "clientlist.h" #include "zonelist.h" From e599820383d3f98f68829f84171fc6b7db897a18 Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 3 Jul 2014 23:35:19 -0700 Subject: [PATCH 089/288] Missing return value --- common/MySQLRequestRow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/MySQLRequestRow.cpp b/common/MySQLRequestRow.cpp index d00cbc835..46bdaffd9 100644 --- a/common/MySQLRequestRow.cpp +++ b/common/MySQLRequestRow.cpp @@ -26,6 +26,8 @@ MySQLRequestRow& MySQLRequestRow::operator=(MySQLRequestRow& moveItem) moveItem.m_Result = nullptr; moveItem.m_MySQLRow = nullptr; + + return *this; } MySQLRequestRow::MySQLRequestRow(MYSQL_RES *result) From 2c78a47a94d52841cee924af092ad5b775463b7a Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Fri, 4 Jul 2014 00:01:13 -0700 Subject: [PATCH 090/288] Linux compile fixes --- common/database.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 60382d6e8..a8876f0d1 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -165,7 +165,7 @@ uint32 Database::CheckLogin(const char* name, const char* password, int16* oStat "and length(password) > 0 and (password='%s' or password=MD5('%s'))", tmpUN, tmpPW, tmpPW)); - + if (!results.Success()) { @@ -194,7 +194,7 @@ bool Database::CheckBannedIPs(const char* loginIP) auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT ip_address FROM Banned_IPs WHERE ip_address='%s'", loginIP)); - + if (!results.Success()) { std::cerr << "Error in CheckBannedIPs query '" << query << "' " << results.ErrorMessage() << std::endl; @@ -327,7 +327,7 @@ uint32 Database::CreateAccount(const char* name, const char* password, int16 sta return 0; } - if (results.LastInsertedID() == 0) + if (results.LastInsertedID() == 0) { std::cerr << "Error in CreateAccount query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); @@ -783,7 +783,7 @@ uint32 Database::GetAccountIDByChar(uint32 char_id) { if (!results.Success()) { - LogFile->write(EQEMuLog::Error, "Error in GetAccountIDByChar query '%s': %s", query, results.ErrorMessage()); + LogFile->write(EQEMuLog::Error, "Error in GetAccountIDByChar query '%s': %s", query, results.ErrorMessage().c_str()); safe_delete_array(query); return 0; } @@ -805,7 +805,7 @@ uint32 Database::GetAccountIDByName(const char* accname, int16* status, uint32* return 0; auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT id, status, lsaccount_id FROM account WHERE name='%s'", accname)); - + if (!results.Success()) { std::cerr << "Error in GetAccountIDByAcc query '" << query << "' " << results.ErrorMessage() << std::endl; @@ -824,8 +824,8 @@ uint32 Database::GetAccountIDByName(const char* accname, int16* status, uint32* if (status) *status = atoi(row[1]); - - if (lsid) + + if (lsid) { if (row[2]) *lsid = atoi(row[2]); @@ -893,7 +893,7 @@ bool Database::LoadVariables() { } safe_delete_array(query); - return LoadVariables_result(results); + return LoadVariables_result(std::move(results)); } uint32 Database::LoadVariables_MQ(char** query) @@ -1007,7 +1007,7 @@ bool Database::SetVariable(const char* varname_in, const char* varvalue_in) { } safe_delete_array(query); - + if (results.RowsAffected() == 1) { LoadVariables(); // refresh cache @@ -1503,7 +1503,7 @@ bool Database::MoveCharacterToZone(uint32 iCharID, const char* iZonename) { char *query = nullptr; auto results = QueryDatabase(query, MakeAnyLenString(&query, "UPDATE character_ SET zonename = '%s', zoneid=%i, x=-1, y=-1, z=-1 WHERE id=%i", iZonename, GetZoneID(iZonename), iCharID)); - + if (!results.Success()) { std::cerr << "Error in MoveCharacterToZone(id) query '" << query << "' " << results.ErrorMessage() << std::endl; @@ -1577,7 +1577,7 @@ bool Database::SetHackerFlag(const char* accountname, const char* charactername, return results.RowsAffected() != 0; } -bool Database::SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone) { +bool Database::SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone) { //Utilize the "hacker" table, but also give zone information. char *query = nullptr; From 2b204fa756d3497bb6477736f960755105adea8c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 4 Jul 2014 13:57:09 -0400 Subject: [PATCH 091/288] Hopefully fix compile issue with some VS versions --- common/MySQLRequestResult.h | 4 ++-- common/MySQLRequestRow.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/MySQLRequestResult.h b/common/MySQLRequestResult.h index 05f363722..0bf644c98 100644 --- a/common/MySQLRequestResult.h +++ b/common/MySQLRequestResult.h @@ -7,8 +7,8 @@ #endif #include -#include <../common/types.h> -#include <../common/MySQLRequestRow.h> +#include "../common/types.h" +#include "../common/MySQLRequestRow.h" #include #include #include diff --git a/common/MySQLRequestRow.h b/common/MySQLRequestRow.h index 8e979acab..535699fea 100644 --- a/common/MySQLRequestRow.h +++ b/common/MySQLRequestRow.h @@ -8,7 +8,7 @@ #include #include -#include <../common/types.h> +#include "../common/types.h" class MySQLRequestRow : public std::iterator { From 0be08b789969daebdbd9a5cf7ac337a0ab7782f7 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Wed, 2 Jul 2014 08:42:18 -0400 Subject: [PATCH 092/288] Implemented SE_Sanctuary - Places caster at bottom hate list, effect fades if caster cast spell on targets other than self. --- changelog.txt | 3 +++ common/spdat.h | 4 ++-- zone/bonuses.cpp | 8 ++++++++ zone/common.h | 1 + zone/spell_effects.cpp | 36 ++++++++++++++++++++++++++++++++++++ zone/spells.cpp | 3 +++ 6 files changed, 53 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index 0a22ccf8d..08527447b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 07/2/2014 == +Kayen: Implemented SE_Sanctuary - Places caster at bottom hate list, effect fades if caster cast spell on targets other than self. + == 06/25/2014 == Kayen: Updated SE_Hate (Renamed from SE_Hate2) to now properly work for instant +/- hate spells. diff --git a/common/spdat.h b/common/spdat.h index 75d351fc2..0c2cf4b1f 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -455,11 +455,11 @@ typedef enum { #define SE_MitigateDamageShield 305 // implemented - off hand attacks only (Shielding Resistance) //#define SE_ArmyOfTheDead 306 // *not implemented NecroAA - This ability calls up to five shades of nearby corpses back to life to serve the necromancer. The soulless abominations will mindlessly fight the target until called back to the afterlife some time later. The first rank summons up to three shades that serve for 60 seconds, and each additional rank adds one more possible shade and increases their duration by 15 seconds //#define SE_Appraisal 307 // *not implemented Rogue AA - This ability allows you to estimate the selling price of an item you are holding on your cursor. -#define SE_SuspendMinion 308 // not implemented as bonus +#define SE_SuspendMinion 308 // implemented #define SE_GateCastersBindpoint 309 // implemented - Gate to casters bind point #define SE_ReduceReuseTimer 310 // implemented #define SE_LimitCombatSkills 311 // implemented - Excludes focus from procs (except if proc is a memorizable spell) -//#define SE_Sanctuary 312 // *not implemented +#define SE_Sanctuary 312 // implemented - Places caster at bottom hate list, effect fades if cast cast spell on targets other than self. #define SE_ForageAdditionalItems 313 // implemented[AA] - chance to forage additional items #define SE_Invisibility2 314 // implemented - fixed duration invisible #define SE_InvisVsUndead2 315 // implemented - fixed duration ITU diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index a316c4b3b..0e521a6db 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -2856,6 +2856,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne newbon->PetMeleeMitigation += effect_value; break; + case SE_Sanctuary: + newbon->Sanctuary = true; + break; + //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { @@ -4330,6 +4334,10 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) itembonuses.FinishingBlowLvl[1] = effect_value; break; + case SE_Sanctuary: + spellbonuses.Sanctuary = effect_value; + break; + } } } diff --git a/zone/common.h b/zone/common.h index 88600492e..0768a0835 100644 --- a/zone/common.h +++ b/zone/common.h @@ -372,6 +372,7 @@ struct StatBonuses { int16 DStacker[1]; // For buff stack blocking 0=Exists 1=Effect_value bool BerserkSPA; // berserk effect int16 Metabolism; // Food/drink consumption rates. + bool Sanctuary; // Sanctuary effect, lowers place on hate list until cast on others. // AAs int8 Packrat; //weight reduction for items, 1 point = 10% diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 090fb4b75..7bb227bd0 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2732,6 +2732,22 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) break; } + case SE_Sanctuary: + { + std::list npc_list; + entity_list.GetNPCList(npc_list); + + for(std::list::iterator itr = npc_list.begin(); itr != npc_list.end(); ++itr) { + + NPC* npc = *itr; + + if (npc && npc->CheckAggro(this)) + npc->SetHate(caster, 1); + + } + break; + } + // Handled Elsewhere case SE_ImmuneFleeing: case SE_NegateSpellEffect: @@ -2960,6 +2976,10 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_Berserk: case SE_Vampirism: case SE_Metabolism: + case SE_FinishingBlow: + case SE_FinishingBlowLvl: + case SE_Assassinate: + case SE_AssassinateLevel: { break; } @@ -3604,6 +3624,22 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste break; } + case SE_Sanctuary: + { + std::list npc_list; + entity_list.GetNPCList(npc_list); + + for(std::list::iterator itr = npc_list.begin(); itr != npc_list.end(); ++itr) { + + NPC* npc = *itr; + + if (npc && npc->CheckAggro(this)) + npc->SetHate(caster, 1); + + } + break; + } + default: { // do we need to do anyting here? diff --git a/zone/spells.cpp b/zone/spells.cpp index 59dbb6625..6a87f2409 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -183,6 +183,9 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, CastToNPC()->AI_Event_SpellCastFinished(false, casting_spell_slot); return(false); } + //It appears that the Sanctuary effect is removed by a check on the client side (keep this however for redundancy) + if (spellbonuses.Sanctuary && (spells[spell_id].targettype != ST_Self && GetTarget() != this) || IsDetrimentalSpell(spell_id)) + BuffFadeByEffect(SE_Sanctuary); if(IsClient()){ int chance = CastToClient()->GetFocusEffect(focusFcMute, spell_id); From ede9d557a338ca4b81b5dc30a97d52ea7a911c91 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Wed, 2 Jul 2014 11:18:50 -0400 Subject: [PATCH 093/288] Implemented SE_ResourceTap - Coverts a percent of dmg from dmg spells(DD/DoT) to hp/mana/end. --- changelog.txt | 2 +- common/spdat.h | 2 +- zone/mob.h | 1 + zone/spell_effects.cpp | 32 ++++++++++++++++++++++++++++++-- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/changelog.txt b/changelog.txt index 08527447b..ac53a761b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,7 +2,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 07/2/2014 == Kayen: Implemented SE_Sanctuary - Places caster at bottom hate list, effect fades if caster cast spell on targets other than self. - +Kayen: Implemented SE_ResourceTap - Coverts a percent of dmg from dmg spells(DD/DoT) to hp/mana/end. == 06/25/2014 == Kayen: Updated SE_Hate (Renamed from SE_Hate2) to now properly work for instant +/- hate spells. diff --git a/common/spdat.h b/common/spdat.h index 0c2cf4b1f..3b9d88995 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -604,7 +604,7 @@ typedef enum { #define SE_TriggerSpellThreshold 454 // implemented Trigger effect on X amount of spell damage taken #define SE_AddHatePct 455 // implemented Modify total hate by % #define SE_AddHateOverTimePct 456 // implemented Modify total hate by % over time. -//#define SE_ResourceTap 457 // not used +#define SE_ResourceTap 457 // implemented Coverts a percent of dmg from dmg spells(DD/DoT) to hp/mana/end. //#define SE_FactionModPct 458 // not used #define SE_DamageModifier2 459 // implemented - Modifies melee damage by skill type diff --git a/zone/mob.h b/zone/mob.h index 5c1240e83..4f7b47c03 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -229,6 +229,7 @@ public: bool TryDispel(uint8 caster_level, uint8 buff_level, int level_modifier); void SpellProjectileEffect(); bool TrySpellProjectile(Mob* spell_target, uint16 spell_id); + void ResourceTap(int32 damage, uint16 spell_id); //Buff void BuffProcess(); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 7bb227bd0..498e5d7ec 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -224,9 +224,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) dmg = (int32) (dmg * partial / 100); //handles AAs and what not... - if(caster) + if(caster) { dmg = caster->GetActSpellDamage(spell_id, dmg, this); - + caster->ResourceTap(-dmg, spell_id); + } + dmg = -dmg; Damage(caster, dmg, spell_id, spell.skill, false, buffslot, false); } @@ -3367,6 +3369,8 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste if(caster->IsNPC()) effect_value = caster->CastToNPC()->GetActSpellDamage(spell_id, effect_value, this); + + caster->ResourceTap(-effect_value, spell_id); } effect_value = -effect_value; @@ -6283,4 +6287,28 @@ bool Mob::TrySpellProjectile(Mob* spell_target, uint16 spell_id){ return true; } +void Mob::ResourceTap(int32 damage, uint16 spellid){ + //'this' = caster + if (!IsValidSpell(spellid)) + return; + for (int i = 0; i <= EFFECT_COUNT; i++) + { + if (spells[spellid].effectid[i] == SE_ResourceTap){ + + damage += (damage * spells[spellid].base[i])/100; + + if (spells[spellid].max[i] && (damage > spells[spellid].max[i])) + damage = spells[spellid].max[i]; + + if (spells[spellid].base2[i] == 0) //HP Tap + SetHP((GetHP()+ damage)); + + if (spells[spellid].base2[i] == 1) //Mana Tap + SetMana(GetMana() + damage); + + if (spells[spellid].base2[i] == 2 && IsClient()) //Endurance Tap + CastToClient()->SetEndurance(CastToClient()->GetEndurance() + damage); + } + } +} From 9af74e6468b3048dfa86ed5d85b63261e9c12f4a Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Wed, 2 Jul 2014 11:54:59 -0400 Subject: [PATCH 094/288] Implemented SE_FactionModPct - Modifies faction gains and losses by percent. --- changelog.txt | 1 + common/spdat.h | 2 +- zone/bonuses.cpp | 26 ++++++++++++++++++++++++++ zone/client.cpp | 3 +++ zone/common.h | 1 + 5 files changed, 32 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index ac53a761b..26da2b13c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 07/2/2014 == Kayen: Implemented SE_Sanctuary - Places caster at bottom hate list, effect fades if caster cast spell on targets other than self. Kayen: Implemented SE_ResourceTap - Coverts a percent of dmg from dmg spells(DD/DoT) to hp/mana/end. +Kayen: Implemented SE_FactionModPct - Modifies faction gains and losses by percent. == 06/25/2014 == Kayen: Updated SE_Hate (Renamed from SE_Hate2) to now properly work for instant +/- hate spells. diff --git a/common/spdat.h b/common/spdat.h index 3b9d88995..c579a1af7 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -605,7 +605,7 @@ typedef enum { #define SE_AddHatePct 455 // implemented Modify total hate by % #define SE_AddHateOverTimePct 456 // implemented Modify total hate by % over time. #define SE_ResourceTap 457 // implemented Coverts a percent of dmg from dmg spells(DD/DoT) to hp/mana/end. -//#define SE_FactionModPct 458 // not used +#define SE_FactionModPct 458 // implemented Modifies faction gains and losses by percent. #define SE_DamageModifier2 459 // implemented - Modifies melee damage by skill type // LAST diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 0e521a6db..e27378207 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1315,6 +1315,16 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) newbon->PetMeleeMitigation += base1; break; + case SE_FactionModPct: + { + if((base1 < 0) && (newbon->FactionModPct > base1)) + newbon->FactionModPct = base1; + + else if(newbon->FactionModPct < base1) + newbon->FactionModPct = base1; + break; + } + } } } @@ -2860,6 +2870,16 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne newbon->Sanctuary = true; break; + case SE_FactionModPct: + { + if((effect_value < 0) && (newbon->FactionModPct > effect_value)) + newbon->FactionModPct = effect_value; + + else if(newbon->FactionModPct < effect_value) + newbon->FactionModPct = effect_value; + break; + } + //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { @@ -4338,6 +4358,12 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) spellbonuses.Sanctuary = effect_value; break; + case SE_FactionModPct: + spellbonuses.FactionModPct = effect_value; + itembonuses.FactionModPct = effect_value; + aabonuses.FactionModPct = effect_value; + break; + } } } diff --git a/zone/client.cpp b/zone/client.cpp index 4ec3ce2d7..12a9ada67 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -7629,6 +7629,9 @@ void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, ui if(npc_value[i] != 0) { tmpValue = current_value + mod + npc_value[i]; + int16 FactionModPct = spellbonuses.FactionModPct + itembonuses.FactionModPct + aabonuses.FactionModPct; + tmpValue += (tmpValue * FactionModPct) / 100; + // Make sure faction hits don't go to GMs... if (m_pp.gm==1 && (tmpValue < current_value)) { tmpValue = current_value; diff --git a/zone/common.h b/zone/common.h index 0768a0835..9cb80211a 100644 --- a/zone/common.h +++ b/zone/common.h @@ -373,6 +373,7 @@ struct StatBonuses { bool BerserkSPA; // berserk effect int16 Metabolism; // Food/drink consumption rates. bool Sanctuary; // Sanctuary effect, lowers place on hate list until cast on others. + int16 FactionModPct; // Modifies amount of faction gained. // AAs int8 Packrat; //weight reduction for items, 1 point = 10% From effe2149da7abe0f5e0f79685ff9a96221f46519 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Wed, 2 Jul 2014 14:00:50 -0400 Subject: [PATCH 095/288] Re-Implemented SE_TriggerMeleeThreshold and SE_TriggerSpellThreshold correctly - Trigger spell if owner of buff takes more than the specified damage amount in a SINGLE hit, then fade the buff. --- changelog.txt | 2 ++ common/spdat.h | 4 ++-- zone/attack.cpp | 37 +++++-------------------------------- zone/bonuses.cpp | 24 ++++-------------------- zone/mob.cpp | 3 +-- zone/mob.h | 1 + 6 files changed, 15 insertions(+), 56 deletions(-) diff --git a/changelog.txt b/changelog.txt index 26da2b13c..e6d342c55 100644 --- a/changelog.txt +++ b/changelog.txt @@ -4,6 +4,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) Kayen: Implemented SE_Sanctuary - Places caster at bottom hate list, effect fades if caster cast spell on targets other than self. Kayen: Implemented SE_ResourceTap - Coverts a percent of dmg from dmg spells(DD/DoT) to hp/mana/end. Kayen: Implemented SE_FactionModPct - Modifies faction gains and losses by percent. +Kayen: Re-Implemented SE_TriggerMeleeThreshold and SE_TriggerSpellThreshold correctly - Trigger spell if owner of buff +takes more than the specified damage amount in a SINGLE hit, then fade the buff. == 06/25/2014 == Kayen: Updated SE_Hate (Renamed from SE_Hate2) to now properly work for instant +/- hate spells. diff --git a/common/spdat.h b/common/spdat.h index c579a1af7..1b202f19a 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -600,8 +600,8 @@ typedef enum { #define SE_MitigateDotDamage 450 // implemented DOT spell mitigation rune with max value #define SE_MeleeThresholdGuard 451 // implemented Partial Melee Rune that only is lowered if melee hits are over X amount of damage #define SE_SpellThresholdGuard 452 // implemented Partial Spell Rune that only is lowered if spell hits are over X amount of damage -#define SE_TriggerMeleeThreshold 453 // implemented Trigger effect on X amount of melee damage taken -#define SE_TriggerSpellThreshold 454 // implemented Trigger effect on X amount of spell damage taken +#define SE_TriggerMeleeThreshold 453 // implemented Trigger effect on X amount of melee damage taken in a single hit +#define SE_TriggerSpellThreshold 454 // implemented Trigger effect on X amount of spell damage taken in a single hit #define SE_AddHatePct 455 // implemented Modify total hate by % #define SE_AddHateOverTimePct 456 // implemented Modify total hate by % over time. #define SE_ResourceTap 457 // implemented Coverts a percent of dmg from dmg spells(DD/DoT) to hp/mana/end. diff --git a/zone/attack.cpp b/zone/attack.cpp index 7b641bd96..fdbc46d24 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3251,20 +3251,6 @@ int32 Mob::ReduceDamage(int32 damage) } } - if (spellbonuses.TriggerMeleeThreshold[2]){ - slot = spellbonuses.TriggerMeleeThreshold[1]; - - if (slot >= 0) { - if(damage > buffs[slot].melee_rune) { - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - else{ - buffs[slot].melee_rune = (buffs[slot].melee_rune - damage); - } - } - } - if(damage < 1) return -6; @@ -3393,27 +3379,13 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi } } - if (spellbonuses.TriggerSpellThreshold[2]){ - slot = spellbonuses.TriggerSpellThreshold[1]; - - if (slot >= 0) { - if(damage > buffs[slot].magic_rune) { - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - else{ - buffs[slot].magic_rune = (buffs[slot].magic_rune - damage); - } - } - } - if(damage < 1) return 0; if (spellbonuses.AbsorbMagicAtt[0] && spellbonuses.AbsorbMagicAtt[1] >= 0) damage = RuneAbsorb(damage, SE_AbsorbMagicAtt); - + if(damage < 1) return 0; } @@ -3599,6 +3571,8 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons if(spell_id == SPELL_UNKNOWN) { damage = ReduceDamage(damage); mlog(COMBAT__HITS, "Melee Damage reduced to %d", damage); + ReduceAllDamage(damage); + TryTriggerThreshHold(damage, SE_TriggerMeleeThreshold, attacker); } else { int32 origdmg = damage; damage = AffectMagicalDamage(damage, spell_id, iBuffTic, attacker); @@ -3610,14 +3584,13 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons //Kayen: Probably need to add a filter for this - Not sure if this msg is correct but there should be a message for spell negate/runes. Message(263, "%s tries to cast on YOU, but YOUR magical skin absorbs the spell.",attacker->GetCleanName()); } - + ReduceAllDamage(damage); + TryTriggerThreshHold(damage, SE_TriggerSpellThreshold, attacker); } if (skill_used) CheckNumHitsRemaining(NUMHIT_IncomingHitSuccess); - ReduceAllDamage(damage); - if(IsClient() && CastToClient()->sneaking){ CastToClient()->sneaking = false; SendAppearancePacket(AT_Sneak, 0); diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index e27378207..01e2e4f91 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -2425,24 +2425,12 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne } case SE_TriggerMeleeThreshold: - { - if (newbon->TriggerMeleeThreshold[2] < base2){ - newbon->TriggerMeleeThreshold[0] = effect_value; - newbon->TriggerMeleeThreshold[1] = buffslot; - newbon->TriggerMeleeThreshold[2] = base2; - } + newbon->TriggerMeleeThreshold = true; break; - } case SE_TriggerSpellThreshold: - { - if (newbon->TriggerSpellThreshold[2] < base2){ - newbon->TriggerSpellThreshold[0] = effect_value; - newbon->TriggerSpellThreshold[1] = buffslot; - newbon->TriggerSpellThreshold[2] = base2; - } + newbon->TriggerSpellThreshold = true; break; - } case SE_ShieldBlock: newbon->ShieldBlock += effect_value; @@ -4218,15 +4206,11 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) break; case SE_TriggerMeleeThreshold: - spellbonuses.TriggerMeleeThreshold[0] = effect_value; - spellbonuses.TriggerMeleeThreshold[1] = effect_value; - spellbonuses.TriggerMeleeThreshold[2] = effect_value; + spellbonuses.TriggerMeleeThreshold = effect_value; break; case SE_TriggerSpellThreshold: - spellbonuses.TriggerSpellThreshold[0] = effect_value; - spellbonuses.TriggerSpellThreshold[1] = effect_value; - spellbonuses.TriggerSpellThreshold[2] = effect_value; + spellbonuses.TriggerSpellThreshold = effect_value; break; case SE_DivineAura: diff --git a/zone/mob.cpp b/zone/mob.cpp index ee468a0e6..5272b373f 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3452,8 +3452,7 @@ bool Mob::TryFadeEffect(int slot) { for(int i = 0; i < EFFECT_COUNT; i++) { - if (spells[buffs[slot].spellid].effectid[i] == SE_CastOnWearoff || spells[buffs[slot].spellid].effectid[i] == SE_EffectOnFade - || spells[buffs[slot].spellid].effectid[i] == SE_TriggerMeleeThreshold || spells[buffs[slot].spellid].effectid[i] == SE_TriggerSpellThreshold) + if (spells[buffs[slot].spellid].effectid[i] == SE_CastOnWearoff || spells[buffs[slot].spellid].effectid[i] == SE_EffectOnFade) { uint16 spell_id = spells[buffs[slot].spellid].base[i]; BuffFadeBySlot(slot); diff --git a/zone/mob.h b/zone/mob.h index 4f7b47c03..4d6983643 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -230,6 +230,7 @@ public: void SpellProjectileEffect(); bool TrySpellProjectile(Mob* spell_target, uint16 spell_id); void ResourceTap(int32 damage, uint16 spell_id); + void TryTriggerThreshHold(int32 damage, int effect_id, Mob* attacker); //Buff void BuffProcess(); From 41d3b177ea650e5a081bf6e71fac2527d24ec195 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Wed, 2 Jul 2014 21:38:26 -0400 Subject: [PATCH 096/288] Renamed various Cast on Fade spell effects to more accurately describe their functions. Missing code from prior commit. --- common/spdat.cpp | 8 ++--- zone/common.h | 4 +-- zone/mob.cpp | 2 +- zone/spell_effects.cpp | 74 ++++++++++++++++++++++++++++++------------ 4 files changed, 61 insertions(+), 27 deletions(-) diff --git a/common/spdat.cpp b/common/spdat.cpp index 3c4989a67..49cb8fe16 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -1003,7 +1003,7 @@ bool IsSuspendableSpell(uint16 spell_id) uint32 GetMorphTrigger(uint32 spell_id) { for (int i = 0; i < EFFECT_COUNT; ++i) - if (spells[spell_id].effectid[i] == SE_ImprovedSpellEffect) + if (spells[spell_id].effectid[i] == SE_CastOnFadeEffect) return spells[spell_id].base[i]; return 0; @@ -1012,9 +1012,9 @@ uint32 GetMorphTrigger(uint32 spell_id) bool IsCastonFadeDurationSpell(uint16 spell_id) { for (int i = 0; i < EFFECT_COUNT; ++i) { - if (spells[spell_id].effectid[i] == SE_ImprovedSpellEffect - || spells[spell_id].effectid[i] == SE_BossSpellTrigger - || spells[spell_id].effectid[i] == SE_CastOnWearoff){ + if (spells[spell_id].effectid[i] == SE_CastOnFadeEffect + || spells[spell_id].effectid[i] == SE_CastOnFadeEffectNPC + || spells[spell_id].effectid[i] == SE_CastOnFadeEffectAlways){ return true; } diff --git a/zone/common.h b/zone/common.h index 9cb80211a..10b3d2200 100644 --- a/zone/common.h +++ b/zone/common.h @@ -348,8 +348,8 @@ struct StatBonuses { uint16 SpellThresholdGuard[3]; // 0 = Mitigation value 1 = Buff Slot 2 = Min damage to trigger. uint16 MitigateSpellRune[4]; // 0 = Mitigation value 1 = Buff Slot 2 = Max mitigation per spell 3 = Rune Amt uint16 MitigateDotRune[4]; // 0 = Mitigation value 1 = Buff Slot 2 = Max mitigation per tick 3 = Rune Amt - uint32 TriggerMeleeThreshold[3]; // 0 = Spell Effect ID 1 = Buff slot 2 = Damage Amount to Trigger - uint32 TriggerSpellThreshold[3]; // 0 = Spell Effect ID 1 = Buff slot 2 = Damage Amount to Trigger + bool TriggerMeleeThreshold; // Has Melee Threshhold + bool TriggerSpellThreshold; // Has Spell Threshhold uint16 ManaAbsorbPercentDamage[2]; // 0 = Mitigation value 1 = Buff Slot int16 ShieldBlock; // Chance to Shield Block int16 BlockBehind; // Chance to Block Behind (with our without shield) diff --git a/zone/mob.cpp b/zone/mob.cpp index 5272b373f..cf7b2d243 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3452,7 +3452,7 @@ bool Mob::TryFadeEffect(int slot) { for(int i = 0; i < EFFECT_COUNT; i++) { - if (spells[buffs[slot].spellid].effectid[i] == SE_CastOnWearoff || spells[buffs[slot].spellid].effectid[i] == SE_EffectOnFade) + if (spells[buffs[slot].spellid].effectid[i] == SE_CastOnFadeEffectAlways || spells[buffs[slot].spellid].effectid[i] == SE_CastOnRuneFadeEffect) { uint16 spell_id = spells[buffs[slot].spellid].base[i]; BuffFadeBySlot(slot); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 498e5d7ec..c30d03432 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1317,18 +1317,6 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) break; } - case SE_TriggerMeleeThreshold: - { - buffs[buffslot].melee_rune = spells[spell_id].base2[i]; - break; - } - - case SE_TriggerSpellThreshold: - { - buffs[buffslot].magic_rune = spells[spell_id].base2[i]; - break; - } - case SE_DistanceRemoval: { buffs[buffslot].caston_x = int(GetX()); @@ -2864,10 +2852,10 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_FcTwincast: case SE_DelayDeath: case SE_InterruptCasting: - case SE_ImprovedSpellEffect: - case SE_BossSpellTrigger: - case SE_CastOnWearoff: - case SE_EffectOnFade: + case SE_CastOnFadeEffect: + case SE_CastOnFadeEffectNPC: + case SE_CastOnFadeEffectAlways: + case SE_CastOnRuneFadeEffect: case SE_MaxHPChange: case SE_SympatheticProc: case SE_FcDamageAmt: @@ -2982,6 +2970,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_FinishingBlowLvl: case SE_Assassinate: case SE_AssassinateLevel: + case SE_FactionModPct: { break; } @@ -3569,9 +3558,9 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste break; } // These effects always trigger when they fade. - case SE_ImprovedSpellEffect: - case SE_BossSpellTrigger: - case SE_CastOnWearoff: + case SE_CastOnFadeEffect: + case SE_CastOnFadeEffectNPC: + case SE_CastOnFadeEffectAlways: { if (ticsremaining == 1) { @@ -5378,7 +5367,7 @@ void Mob::CheckNumHitsRemaining(uint8 type, uint32 buff_slot, uint16 spell_id) 2: [Outgoing Hit Attempts] (185=SE_DamageModifer, 184=SE_HitChance) 3: [Incoming Spells] (180=SE_ResistSpellChance, 296=SE_FcSpellVulnerability) //Note: Determinetal spells only unless proven otherwise 4: [Outgoing Spells] - 5: [Outgoing Hit Successes] (220=SE_SkillDamageAmount, 178=SE_MeleeLifetap, 121=SE_ReverseDS, ?373=SE_CastOnWearoff) + 5: [Outgoing Hit Successes] (220=SE_SkillDamageAmount, 178=SE_MeleeLifetap, 121=SE_ReverseDS, ?373=SE_CastOnFadeEffectAlways) 6: [Incoming Hit Successes] (59=SE_DamageShield, 197=SE_SkillDamageTaken, 162=define SE_MitigateMeleeDamage) 7: [Matching Spells] *When focus is triggered (focus effects) 8: [Incoming Hits or Spells] (329=SE_ManaAbsorbPercentDamage) @@ -6312,3 +6301,48 @@ void Mob::ResourceTap(int32 damage, uint16 spellid){ } } } + +void Mob::TryTriggerThreshHold(int32 damage, int effect_id, Mob* attacker){ + + if (damage <= 0) + return; + + if ((SE_TriggerMeleeThreshold == effect_id) && !spellbonuses.TriggerMeleeThreshold ) + return; + else if ((SE_TriggerSpellThreshold == effect_id) && !spellbonuses.TriggerSpellThreshold) + return; + + int buff_count = GetMaxTotalSlots(); + + for(int slot = 0; slot < buff_count; slot++) { + + if(IsValidSpell(buffs[slot].spellid)){ + + for(int i = 0; i < EFFECT_COUNT; i++){ + + if (spells[buffs[slot].spellid].effectid[i] == effect_id){ + + uint16 spell_id = spells[buffs[slot].spellid].base[i]; + + if (damage > spells[buffs[slot].spellid].base2[i]){ + + BuffFadeBySlot(slot); + + if (IsValidSpell(spell_id)) { + + if (IsBeneficialSpell(spell_id)) + SpellFinished(spell_id, this, 10, 0, -1, spells[spell_id].ResistDiff); + + else if(attacker) + SpellFinished(spell_id, attacker, 10, 0, -1, spells[spell_id].ResistDiff); + } + } + } + } + } + } +} + + + + \ No newline at end of file From 7b085c80183022bc87b1b05a1d48e89cdc3d22a8 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Thu, 3 Jul 2014 08:48:27 -0400 Subject: [PATCH 097/288] Implemented SE_LimitSpellClass - Focus Limits spell to pre defined categories. (3=Cures,3=Offensive, 6=Lifetap) --- common/spdat.cpp | 18 ++++++ common/spdat.h | 15 ++--- zone/mob.h | 2 + zone/spell_effects.cpp | 121 +++++++++++++++++++++++++++++++++++++---- 4 files changed, 139 insertions(+), 17 deletions(-) diff --git a/common/spdat.cpp b/common/spdat.cpp index 49cb8fe16..75f1e9b88 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -157,6 +157,24 @@ bool IsFearSpell(uint16 spell_id) return IsEffectInSpell(spell_id, SE_Fear); } +bool IsCureSpell(uint16 spell_id) +{ + const SPDat_Spell_Struct &sp = spells[spell_id]; + + bool CureEffect = false; + + for(int i = 0; i < EFFECT_COUNT; i++){ + if (sp.effectid[i] == SE_DiseaseCounter || sp.effectid[i] == SE_PoisonCounter + || sp.effectid[i] == SE_CurseCounter || sp.effectid[i] == SE_CorruptionCounter) + CureEffect = true; + } + + if (CureEffect && IsBeneficialSpell(spell_id)) + return true; + + return false; +} + bool IsSlowSpell(uint16 spell_id) { const SPDat_Spell_Struct &sp = spells[spell_id]; diff --git a/common/spdat.h b/common/spdat.h index 1b202f19a..69b6573b0 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -36,7 +36,7 @@ #define EFFECT_COUNT 12 #define MAX_SPELL_TRIGGER 12 // One for each slot(only 6 for AA since AA use 2) #define MAX_RESISTABLE_EFFECTS 12 // Number of effects that are typcially checked agianst resists. -#define MaxLimitInclude 12 //Number(x 0.5) of focus Limiters that have inclusive checksm used when calcing focus effects +#define MaxLimitInclude 16 //Number(x 0.5) of focus Limiters that have inclusive checks used when calcing focus effects const int Z_AGGRO=10; @@ -436,7 +436,7 @@ typedef enum { #define SE_FcDamageAmt 286 // implemented - adds direct spell damage #define SE_SpellDurationIncByTic 287 // implemented #define SE_SpecialAttackKBProc 288 // implemented[AA] - Chance to to do a knockback from special attacks [AA Dragon Punch]. -#define SE_ImprovedSpellEffect 289 // implemented - Triggers only if fades after natural duration. +#define SE_CastOnFadeEffect 289 // implemented - Triggers only if fades after natural duration. #define SE_IncreaseRunSpeedCap 290 // implemented[AA] - increases run speed over the hard cap #define SE_Purify 291 // implemented - Removes determental effects #define SE_StrikeThrough2 292 // implemented[AA] - increasing chance of bypassing an opponent's special defenses, such as dodge, block, parry, and riposte. @@ -480,7 +480,7 @@ typedef enum { #define SE_CriticalDamageMob 330 // implemented #define SE_Salvage 331 // implemented - chance to recover items that would be destroyed in failed tradeskill combine //#define SE_SummonToCorpse 332 // *not implemented AA - Call of the Wild (Druid/Shaman Res spell with no exp) -#define SE_EffectOnFade 333 // implemented +#define SE_CastOnRuneFadeEffect 333 // implemented #define SE_BardAEDot 334 // implemented #define SE_BlockNextSpellFocus 335 // implemented - base1 chance to block next spell ie Puratus (8494) //#define SE_IllusionaryTarget 336 // not used @@ -520,11 +520,11 @@ typedef enum { #define SE_ResistCorruption 370 // implemented #define SE_AttackSpeed4 371 // implemented - stackable slow effect 'Inhibit Melee' //#define SE_ForageSkill 372 // *not implemented[AA] Will increase the skill cap for those that have the Forage skill and grant the skill and raise the cap to those that do not. -#define SE_CastOnWearoff 373 // implemented - Triggers only if fades after natural duration. +#define SE_CastOnFadeEffectAlways 373 // implemented - Triggers if fades after natural duration OR from rune/numhits fades. #define SE_ApplyEffect 374 // implemented #define SE_DotCritDmgIncrease 375 // implemented - Increase damage of DoT critical amount //#define SE_Fling 376 // *not implemented - used in 2 test spells (12945 | Movement Test Spell 1) -#define SE_BossSpellTrigger 377 // implemented - Triggers only if fades after natural duration. +#define SE_CastOnFadeEffectNPC 377 // implemented - Triggers only if fades after natural duration (On live these are usually players spells that effect an NPC). #define SE_SpellEffectResistChance 378 // implemented - Increase chance to resist specific spell effect (base1=value, base2=spell effect id) #define SE_ShadowStepDirectional 379 // implemented - handled by client #define SE_Knockdown 380 // implemented - small knock back(handled by client) @@ -550,8 +550,8 @@ typedef enum { #define SE_HealGroupFromMana 400 // implemented - Drains mana and heals for each point of mana drained #define SE_ManaDrainWithDmg 401 // implemented - Deals damage based on the amount of mana drained #define SE_EndDrainWithDmg 402 // implemented - Deals damage for the amount of endurance drained -//#define SE_LimitSpellClass 403 // *not implemented - unclear what this refers too (not 'right click' spell bar) -//#define SE_LimitSpellSubclass 404 // *not implemented - unclear what this refers too (not 'right click' spell bar) +#define SE_LimitSpellClass 403 // implemented - Limits to specific types of spells (see CheckSpellCategory) +#define SE_LimitSpellSubclass 404 // *not implemented - Limits to specific types of spells (see CheckSpellCategory) [Categories NOT defined yet] #define SE_TwoHandBluntBlock 405 // implemented - chance to block attacks when using two hand blunt weapons (similiar to shield block) #define SE_CastonNumHitFade 406 // implemented - casts a spell when a buff fades due to its numhits being depleted #define SE_CastonFocusEffect 407 // implemented - casts a spell if focus limits are met (ie triggers when a focus effects is applied) @@ -787,6 +787,7 @@ bool IsSummonSpell(uint16 spellid); bool IsEvacSpell(uint16 spellid); bool IsDamageSpell(uint16 spellid); bool IsFearSpell(uint16 spellid); +bool IsCureSpell(uint16 spellid); bool BeneficialSpell(uint16 spell_id); bool GroupOnlySpell(uint16 spell_id); int GetSpellEffectIndex(uint16 spell_id, int effect); diff --git a/zone/mob.h b/zone/mob.h index 4d6983643..0476a20dc 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -231,6 +231,8 @@ public: bool TrySpellProjectile(Mob* spell_target, uint16 spell_id); void ResourceTap(int32 damage, uint16 spell_id); void TryTriggerThreshHold(int32 damage, int effect_id, Mob* attacker); + bool CheckSpellCategory(uint16 spell_id, int category_id, int effect_id); + //Buff void BuffProcess(); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index c30d03432..dcc6b6e1b 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2971,6 +2971,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_Assassinate: case SE_AssassinateLevel: case SE_FactionModPct: + case SE_LimitSpellClass: { break; } @@ -4128,6 +4129,8 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) 6/7 SE_LimitTarget 8/9 SE_LimitSpellGroup: 10/11 SE_LimitCastingSkill: + 12/13 SE_LimitSpellClass: + 14/15 SE_LimitSpellSubClass: Remember: Update MaxLimitInclude in spdat.h if adding new limits that require Includes */ int FocusCount = 0; @@ -4322,16 +4325,40 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) break; case SE_LimitCastingSkill: - if(base1 < 0) { - if(-base1 == spell.skill) - LimitFailure = true; - } - else { - LimitInclude[10] = true; - if(base1 == spell.skill) - LimitInclude[11] = true; - } - break; + if(base1 < 0) { + if(-base1 == spell.skill) + LimitFailure = true; + } + else { + LimitInclude[10] = true; + if(base1 == spell.skill) + LimitInclude[11] = true; + } + break; + + case SE_LimitSpellClass: + if(base1 < 0) { //Exclude + if (CheckSpellCategory(spell_id, base1, SE_LimitSpellClass)); + return(0); + } + else { + LimitInclude[12] = true; + if (CheckSpellCategory(spell_id, base1, SE_LimitSpellClass)); //Include + LimitInclude[13] = true; + } + break; + + case SE_LimitSpellSubclass: + if(base1 < 0) { //Exclude + if (CheckSpellCategory(spell_id, base1, SE_LimitSpellSubclass)); + return(0); + } + else { + LimitInclude[14] = true; + if (CheckSpellCategory(spell_id, base1, SE_LimitSpellSubclass)); //Include + LimitInclude[15] = true; + } + break; case SE_LimitClass: //Do not use this limit more then once per spell. If multiple class, treat value like items would. @@ -4575,6 +4602,8 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo 6/7 SE_LimitTarget 8/9 SE_LimitSpellGroup: 10/11 SE_LimitCastingSkill: + 12/13 SE_LimitSpellClass: + 14/15 SE_LimitSpellSubClass: Remember: Update MaxLimitInclude in spdat.h if adding new limits that require Includes */ @@ -4764,6 +4793,30 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo Caston_spell_id = focus_spell.base[i]; break; + case SE_LimitSpellClass: + if(focus_spell.base[i] < 0) { //Exclude + if (CheckSpellCategory(spell_id, focus_spell.base[i], SE_LimitSpellClass)); + return(0); + } + else { + LimitInclude[12] = true; + if (CheckSpellCategory(spell_id, focus_spell.base[i], SE_LimitSpellClass)); //Include + LimitInclude[13] = true; + } + break; + + case SE_LimitSpellSubclass: + if(focus_spell.base[i] < 0) { //Exclude + if (CheckSpellCategory(spell_id, focus_spell.base[i], SE_LimitSpellSubclass)); + return(0); + } + else { + LimitInclude[14] = true; + if (CheckSpellCategory(spell_id, focus_spell.base[i], SE_LimitSpellSubclass)); //Include + LimitInclude[15] = true; + } + break; + //handle effects case SE_ImprovedDamage: @@ -6343,6 +6396,54 @@ void Mob::TryTriggerThreshHold(int32 damage, int effect_id, Mob* attacker){ } } +bool Mob::CheckSpellCategory(uint16 spell_id, int category_id, int effect_id){ + if (!IsValidSpell(spell_id) || !category_id) + return false; + int effectid = 0; + int category = 0; + + /*Category ID SE_LimitSpellClass [(+) Include (-) Exclude] + 1 = UNK + 2 = Cures + 3 = Offensive Spells + 4 = UNK + 5 = UNK + 6 = Lifetap + */ + + /*Category ID SE_LimitSpellSubClass [(+) Include (-) Exclude] + 5 = UNK + 8 = UNK + */ + + if (effect_id == SE_LimitSpellClass) { + + switch(category_id) + { + case 2: + if (IsCureSpell(spell_id)) + return true; + break; + + case 3: + if (IsDetrimentalSpell(spell_id)) + return true; + break; + + case 6: + if (spells[spell_id].targettype == ST_Tap || spells[spell_id].targettype == ST_TargetAETap) + return true; + break; + } + } + + else if (effect_id == SE_LimitSpellSubclass) { + //Pending Implementation when category types are figured out. + return false; + } + + return false; +} \ No newline at end of file From 9e26ebb9e51d8cb278b889182a7a7ada199da87d Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Thu, 3 Jul 2014 10:55:59 -0400 Subject: [PATCH 098/288] Changed SE_LimitMaxMana to SE_MeleeVulnerability - Weakness/Mitigation verse melee damage (Despite lives SPA lable as the former it clearly is not what the effect does from all spell examples) --- changelog.txt | 3 +++ common/spdat.h | 2 +- zone/bonuses.cpp | 8 ++++++++ zone/common.h | 1 + zone/mob.cpp | 7 ++++++- zone/spell_effects.cpp | 12 +----------- 6 files changed, 20 insertions(+), 13 deletions(-) diff --git a/changelog.txt b/changelog.txt index e6d342c55..56307b361 100644 --- a/changelog.txt +++ b/changelog.txt @@ -6,6 +6,9 @@ Kayen: Implemented SE_ResourceTap - Coverts a percent of dmg from dmg spells(DD/ Kayen: Implemented SE_FactionModPct - Modifies faction gains and losses by percent. Kayen: Re-Implemented SE_TriggerMeleeThreshold and SE_TriggerSpellThreshold correctly - Trigger spell if owner of buff takes more than the specified damage amount in a SINGLE hit, then fade the buff. +Kayen: Implemented SE_LimitSpellClass - Focus Limits spell to pre defined categories. (3=Cures,3=Offensive, 6=Lifetap) +Kayen: Changed SE_LimitMaxMana to SE_MeleeVulnerability - Weakness/Mitigation verse melee damage +(Despite lives SPA lable as the former it clearly is not what the effect does from all spell examples) == 06/25/2014 == Kayen: Updated SE_Hate (Renamed from SE_Hate2) to now properly work for instant +/- hate spells. diff --git a/common/spdat.h b/common/spdat.h index 69b6573b0..02dca8ff7 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -538,7 +538,7 @@ typedef enum { //#define SE_SummonCorpseZone 388 // *not implemented - summons a corpse from any zone(nec AA) #define SE_FcTimerRefresh 389 // implemented - Refresh spell icons //#define SE_FcTimerLockout 390 // *not implemented - Sets recast timers to specific value, focus limited. -#define SE_LimitManaMax 391 // implemented +#define SE_MeleeVulnerability 391 // implemented [Live SPA has this as LimitManaMax however that is clearly not the effect used] #define SE_FcHealAmt 392 // implemented - Adds or removes healing from spells #define SE_FcHealPctIncoming 393 // implemented - HealRate with focus restrictions. #define SE_FcHealAmtIncoming 394 // implemented - Adds/Removes amount of healing on target by X value with foucs restrictions. diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 01e2e4f91..48a3d95e1 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1315,6 +1315,10 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) newbon->PetMeleeMitigation += base1; break; + case SE_MeleeVulnerability: + newbon->MeleeVulnerability += base1; + break; + case SE_FactionModPct: { if((base1 < 0) && (newbon->FactionModPct > base1)) @@ -2854,6 +2858,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne newbon->PetMeleeMitigation += effect_value; break; + case SE_MeleeVulnerability: + newbon->MeleeVulnerability += effect_value; + break; + case SE_Sanctuary: newbon->Sanctuary = true; break; diff --git a/zone/common.h b/zone/common.h index 10b3d2200..e3a9dfb09 100644 --- a/zone/common.h +++ b/zone/common.h @@ -374,6 +374,7 @@ struct StatBonuses { int16 Metabolism; // Food/drink consumption rates. bool Sanctuary; // Sanctuary effect, lowers place on hate list until cast on others. int16 FactionModPct; // Modifies amount of faction gained. + int16 MeleeVulnerability; // Weakness/mitigation to melee damage // AAs int8 Packrat; //weight reduction for items, 1 point = 10% diff --git a/zone/mob.cpp b/zone/mob.cpp index cf7b2d243..59e02568b 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3419,6 +3419,8 @@ int16 Mob::GetSkillDmgTaken(const SkillUseTypes skill_used) { int skilldmg_mod = 0; + int16 MeleeVuln = spellbonuses.MeleeVulnerability + itembonuses.MeleeVulnerability + aabonuses.MeleeVulnerability; + // All skill dmg mod + Skill specific skilldmg_mod += itembonuses.SkillDmgTaken[HIGHEST_SKILL+1] + spellbonuses.SkillDmgTaken[HIGHEST_SKILL+1] + itembonuses.SkillDmgTaken[skill_used] + spellbonuses.SkillDmgTaken[skill_used]; @@ -3427,6 +3429,8 @@ int16 Mob::GetSkillDmgTaken(const SkillUseTypes skill_used) if ((SkillDmgTaken_Mod[skill_used]) || (SkillDmgTaken_Mod[HIGHEST_SKILL+1])) skilldmg_mod += SkillDmgTaken_Mod[skill_used] + SkillDmgTaken_Mod[HIGHEST_SKILL+1]; + skilldmg_mod += MeleeVuln; + if(skilldmg_mod < -100) skilldmg_mod = -100; @@ -3452,7 +3456,8 @@ bool Mob::TryFadeEffect(int slot) { for(int i = 0; i < EFFECT_COUNT; i++) { - if (spells[buffs[slot].spellid].effectid[i] == SE_CastOnFadeEffectAlways || spells[buffs[slot].spellid].effectid[i] == SE_CastOnRuneFadeEffect) + if (spells[buffs[slot].spellid].effectid[i] == SE_CastOnFadeEffectAlways || + spells[buffs[slot].spellid].effectid[i] == SE_CastOnRuneFadeEffect) { uint16 spell_id = spells[buffs[slot].spellid].base[i]; BuffFadeBySlot(slot); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index dcc6b6e1b..8c49414d7 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2942,7 +2942,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_FcIncreaseNumHits: case SE_CastonFocusEffect: case SE_FcHealAmtIncoming: - case SE_LimitManaMax: + case SE_MeleeVulnerability: case SE_DoubleRangedAttack: case SE_ShieldEquipHateMod: case SE_ShieldEquipDmgMod: @@ -4287,11 +4287,6 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) LimitFailure = true; break; - case SE_LimitManaMax: - if(spell.mana > base1) - LimitFailure = true; - break; - case SE_LimitTarget: if (base1 < 0) { if (-base1 == spell.targettype) //Exclude @@ -4718,11 +4713,6 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo return 0; break; - case SE_LimitManaMax: - if(spell.mana > focus_spell.base[i]) - return 0; - break; - case SE_LimitTarget: if (focus_spell.base[i] < 0) { if (-focus_spell.base[i] == spell.targettype) //Exclude From 8cdcd189f529c24f6721c013538158a22c5fbac6 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Thu, 3 Jul 2014 11:00:23 -0400 Subject: [PATCH 099/288] Updated SE_BardAEDot to no longer damage target while target is moving (consistent with live) --- changelog.txt | 1 + zone/spell_effects.cpp | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 56307b361..c86b926fa 100644 --- a/changelog.txt +++ b/changelog.txt @@ -9,6 +9,7 @@ takes more than the specified damage amount in a SINGLE hit, then fade the buff. Kayen: Implemented SE_LimitSpellClass - Focus Limits spell to pre defined categories. (3=Cures,3=Offensive, 6=Lifetap) Kayen: Changed SE_LimitMaxMana to SE_MeleeVulnerability - Weakness/Mitigation verse melee damage (Despite lives SPA lable as the former it clearly is not what the effect does from all spell examples) +Kayen: Updated SE_BardAEDot to no longer damage target while target is moving (consistent with live) == 06/25/2014 == Kayen: Updated SE_Hate (Renamed from SE_Hate2) to now properly work for instant +/- hate spells. diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 8c49414d7..dfe8489c0 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2328,6 +2328,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) // SE_CurrentHP is calculated at first tick if its a dot/buff if (buffslot >= 0) break; + //This effect does no damage if target is moving. + if (IsMoving()) + break; // for offensive spells check if we have a spell rune on int32 dmg = effect_value; @@ -3391,7 +3394,7 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste { effect_value = CalcSpellEffectValue(spell_id, i, caster_level, caster); - if (invulnerable || /*effect_value > 0 ||*/ DivineAura()) + if (IsMoving() || invulnerable || /*effect_value > 0 ||*/ DivineAura()) break; if(effect_value < 0) { From 705ffa89bc8c9640b2f38574fc707f17addb5a5f Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Thu, 3 Jul 2014 11:37:38 -0400 Subject: [PATCH 100/288] Update SE_InterruptCasting: Will now work for instant spells (as well as over time). --- changelog.txt | 1 + zone/spell_effects.cpp | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index c86b926fa..1e371109d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -10,6 +10,7 @@ Kayen: Implemented SE_LimitSpellClass - Focus Limits spell to pre defined catego Kayen: Changed SE_LimitMaxMana to SE_MeleeVulnerability - Weakness/Mitigation verse melee damage (Despite lives SPA lable as the former it clearly is not what the effect does from all spell examples) Kayen: Updated SE_BardAEDot to no longer damage target while target is moving (consistent with live) +Kayen: Update SE_InterruptCasting: Will now work for instant spells (as well as over time). == 06/25/2014 == Kayen: Updated SE_Hate (Renamed from SE_Hate2) to now properly work for instant +/- hate spells. diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index dfe8489c0..61333edfd 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2712,6 +2712,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) break; } + case SE_InterruptCasting:{ + if (buffslot >= 0) + break; + + if(IsCasting() && MakeRandomInt(0, 100) <= spells[spell_id].base[i]) + InterruptSpell(); + + break; + } + case SE_MassGroupBuff:{ SetMGB(true); @@ -2854,7 +2864,6 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_ApplyEffect: case SE_FcTwincast: case SE_DelayDeath: - case SE_InterruptCasting: case SE_CastOnFadeEffect: case SE_CastOnFadeEffectNPC: case SE_CastOnFadeEffectAlways: From edf24308fb3dd928e1103a2c53135a4e8a4bb4b4 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Fri, 4 Jul 2014 15:31:24 -0700 Subject: [PATCH 101/288] getZoneLongName converted 0 assign of query to nullptr --- common/database.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/database.cpp b/common/database.cpp index a8876f0d1..b657d9a22 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1093,7 +1093,7 @@ bool Database::GetSafePoints(const char* short_name, uint32 version, float* safe bool Database::GetZoneLongName(const char* short_name, char** long_name, char* file_name, float* safe_x, float* safe_y, float* safe_z, uint32* graveyard_id, uint32* maxclients) { - char *query = 0; + char *query = nullptr; auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT long_name, file_name, safe_x, safe_y, safe_z, graveyard_id, maxclients FROM zone WHERE short_name='%s' AND version=0", short_name)); From f0106c90a8199c925560f5e81ed798012dcb1679 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Fri, 4 Jul 2014 15:33:33 -0700 Subject: [PATCH 102/288] GetLiveChar converted to QueryDatabase --- common/database.cpp | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index b657d9a22..593b76c9a 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1716,26 +1716,25 @@ bool Database::UpdateLiveChar(char* charname,uint32 lsaccount_id) { } bool Database::GetLiveChar(uint32 account_id, char* cname) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT charname FROM account WHERE id=%i", account_id), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - strcpy(cname,row[0]); - mysql_free_result(result); - return true; - } - mysql_free_result(result); - } - else { + char *query = nullptr; + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT charname FROM account WHERE id=%i", account_id)); + + if (!results.Success()) + { std::cerr << "Error in GetLiveChar query '" << query << "' " << errbuf << std::endl; safe_delete_array(query); + return false; } + safe_delete_array(query); - return false; + if (results.RowCount() != 1) + return false; + + auto row = results.begin(); + strcpy(cname,row[0]); + + return true; } void Database::SetLFP(uint32 CharID, bool LFP) { From 00db7e5c934b99c0347c66c7d280988a8d1a2d89 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Fri, 4 Jul 2014 15:36:29 -0700 Subject: [PATCH 103/288] SetLFP converted to QueryDatabase --- common/database.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 593b76c9a..533eedf4b 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1738,15 +1738,13 @@ bool Database::GetLiveChar(uint32 account_id, char* cname) { } void Database::SetLFP(uint32 CharID, bool LFP) { + char *query = nullptr; - char ErrBuf[MYSQL_ERRMSG_SIZE]; - char *Query = 0; - - if (!RunQuery(Query, MakeAnyLenString(&Query, "update character_ set lfp=%i where id=%i",LFP, CharID), ErrBuf)) - LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, ErrBuf); - - safe_delete_array(Query); + auto results = QueryDatabase(query, MakeAnyLenString(&query, "update character_ set lfp=%i where id=%i",LFP, CharID)); + safe_delete_array(query); + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, results.ErrorMessage().c_str()); } void Database::SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon) { From c82ce7ceccea984c7716f5790e16e0e158401875 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Fri, 4 Jul 2014 15:41:16 -0700 Subject: [PATCH 104/288] SetLoginFlags and SetLFG converted to QueryDatabase --- common/database.cpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 533eedf4b..a736015a1 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1748,27 +1748,23 @@ void Database::SetLFP(uint32 CharID, bool LFP) { } void Database::SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon) { + char *query = nullptr; - char ErrBuf[MYSQL_ERRMSG_SIZE]; - char *Query = 0; - - if (!RunQuery(Query, MakeAnyLenString(&Query, "update character_ set lfp=%i, lfg=%i, firstlogon=%i where id=%i",LFP, LFG, firstlogon, CharID), ErrBuf)) - LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, ErrBuf); - - safe_delete_array(Query); + auto results = QueryDatabase(query,MakeAnyLenString(&query, "update character_ set lfp=%i, lfg=%i, firstlogon=%i where id=%i",LFP, LFG, firstlogon, CharID)); + safe_delete_array(query); + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, results.ErrorMessage().c_str()); } void Database::SetLFG(uint32 CharID, bool LFG) { + char *query = nullptr; - char ErrBuf[MYSQL_ERRMSG_SIZE]; - char *Query = 0; - - if (!RunQuery(Query, MakeAnyLenString(&Query, "update character_ set lfg=%i where id=%i",LFG, CharID), ErrBuf)) - LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, ErrBuf); - + auto results = QueryDatabase(query, MakeAnyLenString(&query, "update character_ set lfg=%i where id=%i",LFG, CharID)); safe_delete_array(Query); + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, results.ErrorMessage().c_str()); } void Database::SetFirstLogon(uint32 CharID, uint8 firstlogon) { From cc9267707a666f20a6716319df047c6029b0cc70 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Fri, 4 Jul 2014 15:43:21 -0700 Subject: [PATCH 105/288] SetFirstLogon converted to QueryDatabase --- common/database.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index a736015a1..cbb403984 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1768,15 +1768,13 @@ void Database::SetLFG(uint32 CharID, bool LFG) { } void Database::SetFirstLogon(uint32 CharID, uint8 firstlogon) { + char *query = nullptr; - char ErrBuf[MYSQL_ERRMSG_SIZE]; - char *Query = 0; - - if (!RunQuery(Query, MakeAnyLenString(&Query, "update character_ set firstlogon=%i where id=%i",firstlogon, CharID), ErrBuf)) - LogFile->write(EQEMuLog::Error, "Error updating firstlogon for character %i : %s", CharID, ErrBuf); - - safe_delete_array(Query); + auto results = QueryDatabase(query, MakeAnyLenString(&query, "update character_ set firstlogon=%i where id=%i",firstlogon, CharID)); + safe_delete_array(query); + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Error updating firstlogon for character %i : %s", CharID, results.ErrorMessage().c_str()); } void Database::AddReport(std::string who, std::string against, std::string lines) From 61abdeb3f745e959bdb59c248cd46adef09c1bb5 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Fri, 4 Jul 2014 15:45:34 -0700 Subject: [PATCH 106/288] AddReport converted to QueryDatabase --- common/database.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index cbb403984..73cbbe879 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1779,16 +1779,16 @@ void Database::SetFirstLogon(uint32 CharID, uint8 firstlogon) { void Database::AddReport(std::string who, std::string against, std::string lines) { - char ErrBuf[MYSQL_ERRMSG_SIZE]; - char *Query = 0; + char *query = nullptr; char *escape_str = new char[lines.size()*2+1]; DoEscapeString(escape_str, lines.c_str(), lines.size()); - if (!RunQuery(Query, MakeAnyLenString(&Query, "INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", who.c_str(), against.c_str(), escape_str), ErrBuf)) - LogFile->write(EQEMuLog::Error, "Error adding a report for %s: %s", who.c_str(), ErrBuf); - - safe_delete_array(Query); + auto results = QueryDatabase(query, MakeAnyLenString(&query, "INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", who.c_str(), against.c_str(), escape_str)); + safe_delete_array(query); safe_delete_array(escape_str); + + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Error adding a report for %s: %s", who.c_str(), results.ErrorMessage().c_str()); } void Database::SetGroupID(const char* name,uint32 id, uint32 charid, uint32 ismerc){ From 819de185ef8038b3d17aa150736f9c921692b164 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Fri, 4 Jul 2014 15:50:41 -0700 Subject: [PATCH 107/288] SetGroupID converted to QueryDatabase --- common/database.cpp | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 73cbbe879..cbce631a6 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1791,18 +1791,27 @@ void Database::AddReport(std::string who, std::string against, std::string lines LogFile->write(EQEMuLog::Error, "Error adding a report for %s: %s", who.c_str(), results.ErrorMessage().c_str()); } -void Database::SetGroupID(const char* name,uint32 id, uint32 charid, uint32 ismerc){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - if(id == 0){ //removing you from table - if (!RunQuery(query, MakeAnyLenString(&query, "delete from group_id where charid=%i and name='%s' and ismerc=%i",charid, name, ismerc), errbuf)) - LogFile->write(EQEMuLog::Error, "Error deleting character from group id: %s", errbuf); - } - else{ - if (!RunQuery(query, MakeAnyLenString(&query, "replace into group_id set charid=%i, groupid=%i, name='%s', ismerc='%i'",charid, id, name, ismerc), errbuf)) - LogFile->write(EQEMuLog::Error, "Error adding character to group id: %s", errbuf); +void Database::SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ismerc){ + char *query = nullptr; + + if (id == 0) + { + // removing from group + auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from group_id where charid=%i and name='%s' and ismerc=%i",charid, name, ismerc)); + safe_delete_array(query); + + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Error deleting character from group id: %s", results.ErrorMessage().c_str()); + + return; } + + // adding to group + auto results = QueryDatabase(query, MakeAnyLenString(&query, "replace into group_id set charid=%i, groupid=%i, name='%s', ismerc='%i'",charid, id, name, ismerc)); safe_delete_array(query); + + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Error adding character to group id: %s", results.ErrorMessage().c_str()); } void Database::ClearGroup(uint32 gid) { From 632b9b9c27fe023c57d1373f605d39f7369d0331 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Fri, 4 Jul 2014 15:52:14 -0700 Subject: [PATCH 108/288] errbuff and Query to query change --- common/database.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index cbce631a6..14a0633ac 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1722,7 +1722,7 @@ bool Database::GetLiveChar(uint32 account_id, char* cname) { if (!results.Success()) { - std::cerr << "Error in GetLiveChar query '" << query << "' " << errbuf << std::endl; + std::cerr << "Error in GetLiveChar query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); return false; } @@ -1761,7 +1761,7 @@ void Database::SetLFG(uint32 CharID, bool LFG) { char *query = nullptr; auto results = QueryDatabase(query, MakeAnyLenString(&query, "update character_ set lfg=%i where id=%i",LFG, CharID)); - safe_delete_array(Query); + safe_delete_array(query); if (!results.Success()) LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, results.ErrorMessage().c_str()); From 137b624008c02da86036c492ee0774d86e51aa37 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Fri, 4 Jul 2014 19:13:39 -0700 Subject: [PATCH 109/288] ClearGroup converted to QueryDatabase --- common/database.cpp | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 14a0633ac..68ed4e0fb 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1816,18 +1816,28 @@ void Database::SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ism void Database::ClearGroup(uint32 gid) { ClearGroupLeader(gid); - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - if(gid == 0) { //clear all groups - //if (!RunQuery(query, MakeAnyLenString(&query, "update group_id set groupid=0 where groupid!=0"), errbuf)) - if (!RunQuery(query, MakeAnyLenString(&query, "delete from group_id"), errbuf)) - printf("Unable to clear groups: %s\n",errbuf); - } else { //clear a specific group - //if (!RunQuery(query, MakeAnyLenString(&query, "update group_id set groupid=0 where groupid = %lu", gid), errbuf)) - if (!RunQuery(query, MakeAnyLenString(&query, "delete from group_id where groupid = %lu", (unsigned long)gid), errbuf)) - printf("Unable to clear groups: %s\n",errbuf); - } + char *query = nullptr; + + if(gid == 0) + { + //clear all groups + auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from group_id")); + safe_delete_array(query); + + if (!results.Success()) + std::cout << "Unable to clear groups: " << results.ErrorMessage() << std::endl; + + return; + } + + //clear a specific group + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from group_id where groupid = %lu", (unsigned long)gid)); safe_delete_array(query); + + if (!results.Success()) + std::cout << "Unable to clear groups: " << results.ErrorMessage() << std::endl; + } uint32 Database::GetGroupID(const char* name){ From ceccf2b1cac04c286aa24fcd6de91e0c630ed04e Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Fri, 4 Jul 2014 19:17:33 -0700 Subject: [PATCH 110/288] GetGroupID converted to QueryDatabase --- common/database.cpp | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 68ed4e0fb..bd946c1e6 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1841,25 +1841,26 @@ void Database::ClearGroup(uint32 gid) { } uint32 Database::GetGroupID(const char* name){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint32 groupid=0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT groupid from group_id where name='%s'", name), errbuf, &result)) { - if((row = mysql_fetch_row(result))) - { - if(row[0]) - groupid=atoi(row[0]); - } - else - LogFile->write(EQEMuLog::Debug, "Character not in a group: %s", name); - mysql_free_result(result); - } - else - LogFile->write(EQEMuLog::Error, "Error getting group id: %s", errbuf); + char *query = nullptr; + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT groupid from group_id where name='%s'", name)); safe_delete_array(query); - return groupid; + + if (!results.Success()) + { + LogFile->write(EQEMuLog::Error, "Error getting group id: %s", results.ErrorMessage().c_str()); + return 0; + } + + if (results.RowCount() == 0) + { + LogFile->write(EQEMuLog::Debug, "Character not in a group: %s", name); + return 0; + } + + auto row = results.begin(); + + return atoi(row[0]); } char* Database::GetGroupLeaderForLogin(const char* name,char* leaderbuf){ From b0612f8cdfe117ee0ea9550aa3cd19173b94de47 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 5 Jul 2014 10:47:34 -0700 Subject: [PATCH 111/288] Converted StoreCharacter to QueryDatabase --- common/database.cpp | 82 +++++++++++---------------------------------- 1 file changed, 20 insertions(+), 62 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index bd946c1e6..8fe75aa8d 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -602,49 +602,18 @@ bool Database::DeleteCharacter(char *name) return true; } + // Store new character information into the character_ and inventory tables bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext) { - char errbuf[MYSQL_ERRMSG_SIZE]; char query[256+sizeof(PlayerProfile_Struct)*2+sizeof(ExtendedProfile_Struct)*2+5]; char* end = query; - uint32 affected_rows = 0; - int i; + char* invquery = nullptr; uint32 charid = 0; - char* charidquery = 0; - char* invquery = 0; - MYSQL_RES *result; - MYSQL_ROW row = 0; char zone[50]; float x, y, z; -// memset(&playeraa, 0, sizeof(playeraa)); - - // get the char id (used in inventory inserts below) - if(!RunQuery - ( - charidquery, - MakeAnyLenString - ( - &charidquery, - "SELECT id FROM character_ where name='%s'", - pp->name - ), - errbuf, - &result - )) { - safe_delete_array(charidquery); - LogFile->write(EQEMuLog::Error, "Error in char store id query: %s: %s", charidquery, errbuf); - return(false); - } - safe_delete_array(charidquery); - - if(mysql_num_rows(result) == 1) - { - row = mysql_fetch_row(result); - if(row[0]) - charid = atoi(row[0]); - } + charid = GetCharacterID(pp->name); if(!charid) { @@ -659,6 +628,7 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven pp->zone_id = 1; } else strn0cpy(zone, zname, 49); + x=pp->x; y=pp->y; z=pp->z; @@ -674,44 +644,32 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven end += DoEscapeString(end, (char*)ext, sizeof(ExtendedProfile_Struct)); end += sprintf(end, "\' WHERE account_id=%d AND name='%s'",account_id, pp->name); - RunQuery(query, (uint32) (end - query), errbuf, 0, &affected_rows); + auto results = QueryDatabase(query, (uint32) (end - query)); + // stack assigned query, no need to delete it. - if(!affected_rows) + if(!results.RowsAffected()) { - LogFile->write(EQEMuLog::Error, "StoreCharacter query '%s' %s", query, errbuf); + LogFile->write(EQEMuLog::Error, "StoreCharacter query '%s' %s", query, results.ErrorMessage().c_str()); return false; } - affected_rows = 0; - - - // Doodman: Is this even used? // now the inventory - - for (i=0; i<=2270;) + for (int16 i=0; i<=2270;) { - const ItemInst* newinv = inv->GetItem((int16)i); - if (newinv) + const ItemInst* newinv = inv->GetItem(i); + if (!newinv) { - MakeAnyLenString - ( - &invquery, + auto results = QueryDatabase(invquery, MakeAnyLenString(&invquery, "INSERT INTO inventory SET " "charid=%0u, slotid=%0d, itemid=%0u, charges=%0d, color=%0u", charid, i, newinv->GetItem()->ID, - newinv->GetCharges(), newinv->GetColor() - ); + newinv->GetCharges(), newinv->GetColor())); - RunQuery(invquery, strlen(invquery), errbuf, 0, &affected_rows); - if(!affected_rows) - { - LogFile->write(EQEMuLog::Error, "StoreCharacter inventory failed. Query '%s' %s", invquery, errbuf); - } + if (!results.RowsAffected()) + LogFile->write(EQEMuLog::Error, "StoreCharacter inventory failed. Query '%s' %s", invquery, results.ErrorMessage().c_str()); #if EQDEBUG >= 9 else - { - LogFile->write(EQEMuLog::Debug, "StoreCharacter inventory succeeded. Query '%s' %s", invquery, errbuf); - } + LogFile->write(EQEMuLog::Debug, "StoreCharacter inventory succeeded. Query '%s'", invquery); #endif safe_delete_array(invquery); } @@ -1795,7 +1753,7 @@ void Database::SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ism char *query = nullptr; if (id == 0) - { + { // removing from group auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from group_id where charid=%i and name='%s' and ismerc=%i",charid, name, ismerc)); safe_delete_array(query); @@ -1819,7 +1777,7 @@ void Database::ClearGroup(uint32 gid) { char *query = nullptr; if(gid == 0) - { + { //clear all groups auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from group_id")); safe_delete_array(query); @@ -1828,8 +1786,8 @@ void Database::ClearGroup(uint32 gid) { std::cout << "Unable to clear groups: " << results.ErrorMessage() << std::endl; return; - } - + } + //clear a specific group auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from group_id where groupid = %lu", (unsigned long)gid)); From c6f707d95c39db03953c7e054d596e3f905dec60 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 5 Jul 2014 10:49:07 -0700 Subject: [PATCH 112/288] GetZoneID nullptr and formatting clean up --- common/database.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 8fe75aa8d..0e29c41bb 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1165,13 +1165,14 @@ bool Database::LoadZoneNames() { } uint32 Database::GetZoneID(const char* zonename) { - if (zonename == 0) + + if (zonename == nullptr) return 0; - for (auto iter = zonename_array.begin(); iter != zonename_array.end(); ++iter) { - if (strcasecmp(iter->second.c_str(), zonename) == 0) { + + for (auto iter = zonename_array.begin(); iter != zonename_array.end(); ++iter) + if (strcasecmp(iter->second.c_str(), zonename) == 0) return iter->first; - } - } + return 0; } From 7a5afd8597c3c814cd7a21fc7be3694b63d6a8b4 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 5 Jul 2014 10:50:08 -0700 Subject: [PATCH 113/288] GetZoneName formatting cleanup. much easier to read --- common/database.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 0e29c41bb..d268ac13c 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1179,15 +1179,12 @@ uint32 Database::GetZoneID(const char* zonename) { const char* Database::GetZoneName(uint32 zoneID, bool ErrorUnknown) { auto iter = zonename_array.find(zoneID); - if (iter != zonename_array.end()) { + if (iter != zonename_array.end()) return iter->second.c_str(); - } - else { - if (ErrorUnknown) - return "UNKNOWN"; - else - return 0; - } + + if (ErrorUnknown) + return "UNKNOWN"; + return 0; } From 9bbde719647739a78b9f261d8c3d657c530b8dbb Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 5 Jul 2014 11:06:05 -0700 Subject: [PATCH 114/288] SetGroupLeaderName converted to QueryDatabase --- common/database.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index d268ac13c..fdca3d032 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1842,13 +1842,13 @@ char* Database::GetGroupLeaderForLogin(const char* name,char* leaderbuf){ } void Database::SetGroupLeaderName(uint32 gid, const char* name) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - - if (!RunQuery(query, MakeAnyLenString(&query, "Replace into group_leaders set gid=%lu, leadername='%s'",(unsigned long)gid,name), errbuf)) - printf("Unable to set group leader: %s\n",errbuf); + char *query = nullptr; + auto results = QueryDatabase(query, MakeAnyLenString(&query, "Replace into group_leaders set gid=%lu, leadername='%s'",(unsigned long)gid,name)); safe_delete_array(query); + + if (!results.Success()) + std::cout << "Unable to set group leader: " << results.ErrorMessage() << std::endl; } char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank, char* assist, char* puller, char *marknpc, GroupLeadershipAA_Struct* GLAA){ From 695e6f2026b057295559ea0465aa917fcf66c85c Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 5 Jul 2014 11:10:52 -0700 Subject: [PATCH 115/288] ClearGroupLeader converted to QueryDatabase --- common/database.cpp | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index fdca3d032..c80d22a91 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1910,17 +1910,26 @@ char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* mainta return leaderbuf; } -void Database::ClearGroupLeader(uint32 gid){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - if(gid == 0) { //clear all group leaders - if (!RunQuery(query, MakeAnyLenString(&query, "DELETE from group_leaders"), errbuf)) - printf("Unable to clear group leaders: %s\n",errbuf); - } else { //clear a specific group leader - if (!RunQuery(query, MakeAnyLenString(&query, "DELETE from group_leaders where gid = %lu", (unsigned long)gid), errbuf)) - printf("Unable to clear group leader: %s\n",errbuf); +void Database::ClearGroupLeader(uint32 gid) { + char *query = nullptr; + + if(gid == 0) + { + //clear all group leaders + auto results = QueryDatabase(query, MakeAnyLenString(&query, "DELETE from group_leaders")); + safe_delete_array(query); + + if (!results.Success()) + std::cout << "Unable to clear group leaders: " << results.ErrorMessage() << std::endl; + + return; } + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "DELETE from group_leaders where gid = %lu", (unsigned long)gid)); safe_delete_array(query); + + if (!results.Success()) + std::cout << "Unable to clear group leader: " << results.ErrorMessage() << std::endl; } bool FetchRowMap(MYSQL_RES *result, std::map &rowmap) From 586e177f98de984eb10f6c7d551f4c25ad953b75 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 5 Jul 2014 11:33:49 -0700 Subject: [PATCH 116/288] Created private utility methods ClearAllGroups and ClearAllGroupLeaders --- common/database.cpp | 42 ++++++++++++++++++++++++++++-------------- common/database.h | 8 ++++++++ 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index c80d22a91..0bf5749d2 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1770,6 +1770,19 @@ void Database::SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ism LogFile->write(EQEMuLog::Error, "Error adding character to group id: %s", results.ErrorMessage().c_str()); } +void Database::ClearAllGroups(void) +{ + char *query = nullptr; + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from group_id")); + safe_delete_array(query); + + if (!results.Success()) + std::cout << "Unable to clear groups: " << results.ErrorMessage() << std::endl; + + return; +} + void Database::ClearGroup(uint32 gid) { ClearGroupLeader(gid); char *query = nullptr; @@ -1777,17 +1790,11 @@ void Database::ClearGroup(uint32 gid) { if(gid == 0) { //clear all groups - auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from group_id")); - safe_delete_array(query); - - if (!results.Success()) - std::cout << "Unable to clear groups: " << results.ErrorMessage() << std::endl; - + ClearAllGroups(); return; } //clear a specific group - auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from group_id where groupid = %lu", (unsigned long)gid)); safe_delete_array(query); @@ -1910,18 +1917,25 @@ char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* mainta return leaderbuf; } +// Clearing all group leaders +void Database::ClearAllGroupLeaders(void) +{ + char *query = nullptr; + auto results = QueryDatabase(query, MakeAnyLenString(&query, "DELETE from group_leaders")); + safe_delete_array(query); + + if (!results.Success()) + std::cout << "Unable to clear group leaders: " << results.ErrorMessage() << std::endl; + + return; +} + void Database::ClearGroupLeader(uint32 gid) { char *query = nullptr; if(gid == 0) { - //clear all group leaders - auto results = QueryDatabase(query, MakeAnyLenString(&query, "DELETE from group_leaders")); - safe_delete_array(query); - - if (!results.Success()) - std::cout << "Unable to clear group leaders: " << results.ErrorMessage() << std::endl; - + ClearAllGroupLeaders(); return; } diff --git a/common/database.h b/common/database.h index 4d2b15de7..66375fcb6 100644 --- a/common/database.h +++ b/common/database.h @@ -207,6 +207,7 @@ public: char* GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr); void ClearGroupLeader(uint32 gid = 0); + /* * Raids @@ -262,6 +263,13 @@ private: uint32 varcache_max; VarCache_Struct** varcache_array; uint32 varcache_lastupdate; + + + /* + * Groups, utility methods. + */ + void ClearAllGroupLeaders(); + void ClearAllGroups(); }; bool FetchRowMap(MYSQL_RES *result, std::map &rowmap); From 6132fa0cb99e58a4659f7221029b048b2bb6fd71 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 5 Jul 2014 17:03:46 -0700 Subject: [PATCH 117/288] GetAgreementFlag converted to QueryDatabase --- common/database.cpp | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 0bf5749d2..808f3db0b 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1965,26 +1965,20 @@ bool retval=false; uint8 Database::GetAgreementFlag(uint32 acctid) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES* result; - MYSQL_ROW row; + char* query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT rulesflag FROM account WHERE id=%i",acctid), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) - { - row = mysql_fetch_row(result); - uint8 flag = atoi(row[0]); - mysql_free_result(result); - return flag; - } - } - else - { - safe_delete_array(query); - } - return 0; + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT rulesflag FROM account WHERE id=%i",acctid)); + safe_delete_array(query); + + if (!results.Success()) + return 0; + + if (results.RowCount() != 1) + return 0; + + auto row = results.begin(); + + return atoi(row[0]); } void Database::SetAgreementFlag(uint32 acctid) From c80f803ba79dd6a42f5961b3791d7e07bb007724 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 5 Jul 2014 17:07:34 -0700 Subject: [PATCH 118/288] SetAgreementFlag converted to QueryDatabase --- common/database.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 808f3db0b..460e8100d 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1983,14 +1983,9 @@ uint8 Database::GetAgreementFlag(uint32 acctid) void Database::SetAgreementFlag(uint32 acctid) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; + char *query = nullptr; - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE account SET rulesflag=1 where id=%i",acctid), errbuf, 0, &affected_rows)) { - safe_delete_array(query); - } - else + QueryDatabase(query, MakeAnyLenString(&query, "UPDATE account SET rulesflag=1 where id=%i", acctid)); safe_delete_array(query); } From 34739b71b3527dc30145ff13a502d18a9d2ec0b9 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 5 Jul 2014 19:33:45 -0700 Subject: [PATCH 119/288] Converted ClearRaid to QueryDatabase, added ClearAllRaids utility method --- common/database.cpp | 34 +++++++++++++++++++++++++--------- common/database.h | 6 ++++++ 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 460e8100d..809b3c2f9 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1990,16 +1990,32 @@ void Database::SetAgreementFlag(uint32 acctid) } void Database::ClearRaid(uint32 rid) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - if(rid == 0) { //clear all raids - if (!RunQuery(query, MakeAnyLenString(&query, "delete from raid_members"), errbuf)) - printf("Unable to clear raids: %s\n",errbuf); - } else { //clear a specific group - if (!RunQuery(query, MakeAnyLenString(&query, "delete from raid_members where raidid = %lu", (unsigned long)rid), errbuf)) - printf("Unable to clear raids: %s\n",errbuf); - } + char *query = nullptr; + + if(rid == 0) + { + //clear all raids + ClearAllRaids(); + return; + } + + //clear a specific group + auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from raid_members where raidid = %lu", (unsigned long)rid)); safe_delete_array(query); + + if (!results.Success()) + std::cout << "Unable to clear raids: " << results.ErrorMessage() << std::endl; +} + +void Database::ClearAllRaids(void) +{ + char *query = nullptr; + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from raid_members")); + safe_delete_array(query); + + if (!results.Success()) + std::cout << "Unable to clear raids: " << results.ErrorMessage() << std::endl; } void Database::ClearRaidDetails(uint32 rid) { diff --git a/common/database.h b/common/database.h index 66375fcb6..ebcbc4439 100644 --- a/common/database.h +++ b/common/database.h @@ -270,6 +270,12 @@ private: */ void ClearAllGroupLeaders(); void ClearAllGroups(); + + + /* + * Raid, utility methods. + */ + void ClearAllRaids(); }; bool FetchRowMap(MYSQL_RES *result, std::map &rowmap); From e81e47e9c59e0fdd6ceb0398b0d88ce0dce7b379 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 11:44:59 -0700 Subject: [PATCH 120/288] Built utility function ClearAllRaidDetails --- common/database.cpp | 31 ++++++++++++++++++++++--------- common/database.h | 1 + 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 809b3c2f9..536e781d5 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2018,16 +2018,29 @@ void Database::ClearAllRaids(void) std::cout << "Unable to clear raids: " << results.ErrorMessage() << std::endl; } +void Database::ClearAllRaidDetails(void) +{ + char *query = nullptr; + + if (!RunQuery(query, MakeAnyLenString(&query, "delete from raid_details"), errbuf)) + printf("Unable to clear raid details: %s\n",errbuf); + safe_delete_array(query); + return; +} + void Database::ClearRaidDetails(uint32 rid) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - if(rid == 0) { //clear all raids - if (!RunQuery(query, MakeAnyLenString(&query, "delete from raid_details"), errbuf)) - printf("Unable to clear raid details: %s\n",errbuf); - } else { //clear a specific group - if (!RunQuery(query, MakeAnyLenString(&query, "delete from raid_details where raidid = %lu", (unsigned long)rid), errbuf)) - printf("Unable to clear raid details: %s\n",errbuf); - } + char *query = nullptr; + + if(rid == 0) + { + //clear all raids + ClearAllRaidDetails(); + return; + } + + //clear a specific group + if (!RunQuery(query, MakeAnyLenString(&query, "delete from raid_details where raidid = %lu", (unsigned long)rid), errbuf)) + printf("Unable to clear raid details: %s\n",errbuf); safe_delete_array(query); } diff --git a/common/database.h b/common/database.h index ebcbc4439..c7adc7666 100644 --- a/common/database.h +++ b/common/database.h @@ -276,6 +276,7 @@ private: * Raid, utility methods. */ void ClearAllRaids(); + void ClearAllRaidDetails(); }; bool FetchRowMap(MYSQL_RES *result, std::map &rowmap); From 9b4491df571525b2ef9a4ca81b663ec10e4eef41 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 11:46:27 -0700 Subject: [PATCH 121/288] ClearAllRaidDetails converted to QueryDatabase --- common/database.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 536e781d5..282458cf3 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2021,10 +2021,13 @@ void Database::ClearAllRaids(void) void Database::ClearAllRaidDetails(void) { char *query = nullptr; - - if (!RunQuery(query, MakeAnyLenString(&query, "delete from raid_details"), errbuf)) - printf("Unable to clear raid details: %s\n",errbuf); + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from raid_details")); safe_delete_array(query); + + if (!results.Success()) + std::cout << "Unable to clear raid details: " << results.ErrorMessage() << std::endl; + return; } From a08c6c9a00b470abed470a22041178925f101bb3 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 11:48:07 -0700 Subject: [PATCH 122/288] ClearRaidDetails converted to QueryDatabase --- common/database.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 282458cf3..cc0084656 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2042,9 +2042,11 @@ void Database::ClearRaidDetails(uint32 rid) { } //clear a specific group - if (!RunQuery(query, MakeAnyLenString(&query, "delete from raid_details where raidid = %lu", (unsigned long)rid), errbuf)) - printf("Unable to clear raid details: %s\n",errbuf); + auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from raid_details where raidid = %lu", (unsigned long)rid)); safe_delete_array(query); + + if (!results.Success()) + std::cout << "Unable to clear raid details: " << results.ErrorMessage() << std::endl; } uint32 Database::GetRaidID(const char* name){ From 4a09b9b1a0c2109f41f72222b057d2ad5dfdfce9 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 11:56:42 -0700 Subject: [PATCH 123/288] GetRaidID converted to QueryDatabase --- common/database.cpp | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index cc0084656..9427ccc3b 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2049,27 +2049,32 @@ void Database::ClearRaidDetails(uint32 rid) { std::cout << "Unable to clear raid details: " << results.ErrorMessage() << std::endl; } +// returns 0 on error or no raid for that character, or +// the raid id that the character is a member of. uint32 Database::GetRaidID(const char* name){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint32 raidid=0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT raidid from raid_members where name='%s'", name), - errbuf, &result)) { - if((row = mysql_fetch_row(result))) - { - if(row[0]) - raidid=atoi(row[0]); - } - else - printf("Unable to get raid id, char not found!\n"); - mysql_free_result(result); - } - else - printf("Unable to get raid id: %s\n",errbuf); + char *query = nullptr; + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT raidid from raid_members where name='%s'", name)); safe_delete_array(query); - return raidid; + + if (!results.Success()) + { + std::cout << "Unable to get raid id: " << results.ErrorMessage() << std::endl; + return 0; + } + + auto row = results.begin(); + + if (row == results.end()) + { + std::cout << "Unable to get raid id, char not found!" << std::endl; + return 0; + } + + if (row[0]) // would it ever be possible to have a null here? + return atoi(row[0]); + + return 0; } const char *Database::GetRaidLeaderName(uint32 rid) From bc46b1371dae718171432bcb489ee9c2d41b2530 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 13:45:37 -0700 Subject: [PATCH 124/288] GetRaidLeaderName converted to QueryDatabase --- common/database.cpp | 52 ++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 9427ccc3b..9f32629e9 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2077,33 +2077,37 @@ uint32 Database::GetRaidID(const char* name){ return 0; } -const char *Database::GetRaidLeaderName(uint32 rid) +const char* Database::GetRaidLeaderName(uint32 rid) { - static char name[128]; + // Would be a good idea to fix this to be a passed in variable and + // make the caller responsible. static local variables like this are + // not guaranteed to be thread safe (nor is the internal guard + // variable). C++0x standard states this should be thread safe + // but may not be fully supported in some compilers. + static char name[128]; + char *query = nullptr; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT name FROM raid_members WHERE raidid=%u AND israidleader=1", - rid), errbuf, &result)) { - if((row = mysql_fetch_row(result)) != nullptr) - { - memset(name, 0, 128); - strcpy(name, row[0]); - mysql_free_result(result); - safe_delete_array(query); - return name; - } - else - printf("Unable to get raid id, char not found!\n"); - mysql_free_result(result); - } - else - printf("Unable to get raid id: %s\n",errbuf); + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT name FROM raid_members WHERE raidid=%u AND israidleader=1",rid)); safe_delete_array(query); - return "UNKNOWN"; + + if (!results.Success()) + { + std::cout << "Unable to get raid id: " << results.ErrorMessage() << std::endl; + return "UNKNOWN"; + } + + auto row = results.begin(); + + if (row == results.end()) + { + std::cout << "Unable to get raid id, char not found!" << std::endl; + return "UNKNOWN"; + } + + memset(name, 0, sizeof(name)); + strcpy(name, row[0]); + + return name; } bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 char_id) From 7dce9d6c8ef5434d966bfdc3465bff5a5f7ea805 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 13:46:20 -0700 Subject: [PATCH 125/288] formatting cleanup, no functional change --- common/database.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/database.cpp b/common/database.cpp index 9f32629e9..2cdc294d4 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2112,7 +2112,6 @@ const char* Database::GetRaidLeaderName(uint32 rid) bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 char_id) { - //we are not saved to this instance so set our instance to 0 if(!GlobalInstance(instance_id) && !CharacterInInstanceGroup(instance_id, char_id)) { @@ -2124,6 +2123,7 @@ bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 char_id) DeleteInstance(instance_id); return false; } + return true; } From 96c4b283fa09d35b1b949857562fc42abc4374dc Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 13:50:42 -0700 Subject: [PATCH 126/288] VerifyZoneInstance converted to QueryDatabase --- common/database.cpp | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 2cdc294d4..660c933d4 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2114,9 +2114,7 @@ bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 char_id) { //we are not saved to this instance so set our instance to 0 if(!GlobalInstance(instance_id) && !CharacterInInstanceGroup(instance_id, char_id)) - { return false; - } if(CheckInstanceExpired(instance_id)) { @@ -2129,31 +2127,18 @@ bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 char_id) bool Database::VerifyZoneInstance(uint32 zone_id, uint16 instance_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT id FROM instance_list where id=%u AND zone=%u", - instance_id, zone_id), errbuf, &result)) - { - safe_delete_array(query); - if (mysql_num_rows(result) != 0) - { - mysql_free_result(result); - return true; - } - else - { - mysql_free_result(result); - return false; - } - } - else - { - safe_delete_array(query); + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT id FROM instance_list where id=%u AND zone=%u",instance_id, zone_id)); + safe_delete_array(query); + + if (!results.Success()) return false; - } - return false; + + if (results.RowCount() == 0) + return false; + + return true; } bool Database::CharacterInInstanceGroup(uint16 instance_id, uint32 char_id) From 3db115b52faff1bec03e60c53c1c60c1044f2b5b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 13:51:21 -0700 Subject: [PATCH 127/288] CharacterInInstanceGroup converted to QueryDatabase --- common/database.cpp | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 660c933d4..ce31a74ee 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2143,26 +2143,18 @@ bool Database::VerifyZoneInstance(uint32 zone_id, uint16 instance_id) bool Database::CharacterInInstanceGroup(uint16 instance_id, uint32 char_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - bool lockout_instance_player = false; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT charid FROM instance_list_player where id=%u AND charid=%u", - instance_id, char_id), errbuf, &result)) - { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) - { - lockout_instance_player = true; - } - mysql_free_result(result); - } - else - { - safe_delete_array(query); - } - return lockout_instance_player; + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT charid FROM instance_list_player where id=%u AND charid=%u",instance_id, char_id)); + safe_delete_array(query); + + if (!results.Success()) + return false; + + if (results.RowCount() != 1) + return false; + + return true; } void Database::DeleteInstance(uint16 instance_id) From 2f3c1ed1692851f53284944080a488eb8109c748 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 13:52:26 -0700 Subject: [PATCH 128/288] DeleteInstance converted to QueryDatabase --- common/database.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index ce31a74ee..791df6b19 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2159,20 +2159,20 @@ bool Database::CharacterInInstanceGroup(uint16 instance_id, uint32 char_id) void Database::DeleteInstance(uint16 instance_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + char *query = nullptr; - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM instance_list WHERE id=%u", instance_id), errbuf); + QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM instance_list WHERE id=%u", instance_id)); safe_delete_array(query); - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM instance_list_player WHERE id=%u", instance_id), errbuf); + QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM instance_list_player WHERE id=%u", instance_id)); safe_delete_array(query); - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM respawn_times WHERE instance_id=%u", instance_id), errbuf); + QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM respawn_times WHERE instance_id=%u", instance_id)); safe_delete_array(query); - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM spawn_condition_values WHERE instance_id=%u", instance_id), errbuf); + QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM spawn_condition_values WHERE instance_id=%u", instance_id)); safe_delete_array(query); + BuryCorpsesInInstance(instance_id); } From 94e4da945660fbfcab49ba318537ad4289885a10 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 13:56:30 -0700 Subject: [PATCH 129/288] CheckInstanceExpired converted to QueryDatabase --- common/database.cpp | 47 ++++++++++++++++----------------------------- 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 791df6b19..38dbbf1f3 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2178,49 +2178,36 @@ void Database::DeleteInstance(uint16 instance_id) bool Database::CheckInstanceExpired(uint16 instance_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; int32 start_time = 0; int32 duration = 0; uint32 never_expires = 0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", - instance_id), errbuf, &result)) - { - safe_delete_array(query); - if (mysql_num_rows(result) != 0) - { - row = mysql_fetch_row(result); - start_time = atoi(row[0]); - duration = atoi(row[1]); - never_expires = atoi(row[2]); - } - else - { - mysql_free_result(result); - return true; - } - mysql_free_result(result); - } - else - { - safe_delete_array(query); + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", instance_id)); + safe_delete_array(query); + + if (!results.Success()) return true; - } + + if (results.RowCount() == 0) + return true; + + auto row = results.begin(); + + start_time = atoi(row[0]); + duration = atoi(row[1]); + never_expires = atoi(row[2]); if(never_expires == 1) - { return false; - } timeval tv; gettimeofday(&tv, nullptr); + if((start_time + duration) <= tv.tv_sec) - { return true; - } + return false; } From 4541bd536958b2ad5702078fd1c60deba831ff0e Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 13:59:32 -0700 Subject: [PATCH 130/288] ZoneIDFromInstanceID converted to QueryDatabase --- common/database.cpp | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 38dbbf1f3..b6042cdd1 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2213,35 +2213,20 @@ bool Database::CheckInstanceExpired(uint16 instance_id) uint32 Database::ZoneIDFromInstanceID(uint16 instance_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint32 ret; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT zone FROM instance_list where id=%u", instance_id), - errbuf, &result)) - { - safe_delete_array(query); - if (mysql_num_rows(result) != 0) - { - row = mysql_fetch_row(result); - ret = atoi(row[0]); - mysql_free_result(result); - return ret; - } - else - { - mysql_free_result(result); - return 0; - } - } - else - { - safe_delete_array(query); + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT zone FROM instance_list where id=%u", instance_id)); + safe_delete_array(query); + + if (!results.Success()) return 0; - } - return 0; + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + + return atoi(row[0]); } uint32 Database::VersionFromInstanceID(uint16 instance_id) From 903a3a9060ff41357ec0176daded7f9a0bd5e60d Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 14:10:53 -0700 Subject: [PATCH 131/288] VersionFromInstanceID converted to QueryDatabase --- common/database.cpp | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index b6042cdd1..b715d0108 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2231,35 +2231,20 @@ uint32 Database::ZoneIDFromInstanceID(uint16 instance_id) uint32 Database::VersionFromInstanceID(uint16 instance_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint32 ret; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT version FROM instance_list where id=%u", instance_id), - errbuf, &result)) - { - safe_delete_array(query); - if (mysql_num_rows(result) != 0) - { - row = mysql_fetch_row(result); - ret = atoi(row[0]); - mysql_free_result(result); - return ret; - } - else - { - mysql_free_result(result); - return 0; - } - } - else - { - safe_delete_array(query); + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT version FROM instance_list where id=%u", instance_id)); + safe_delete_array(query); + + if (!results.Success()) return 0; - } - return 0; + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + + return atoi(row[0]); } uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma) From 9abdf5f4b35d1779b57908ea19c47c75dcb9f738 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 14:11:35 -0700 Subject: [PATCH 132/288] GetTimeRemainingInstance converted to QueryDatabase --- common/database.cpp | 49 ++++++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index b715d0108..486d1516e 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2249,49 +2249,40 @@ uint32 Database::VersionFromInstanceID(uint16 instance_id) uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; + uint32 start_time = 0; uint32 duration = 0; uint32 never_expires = 0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", - instance_id), errbuf, &result)) + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", instance_id)); + safe_delete_array(query); + + if (!results.Success()) { - safe_delete_array(query); - if (mysql_num_rows(result) != 0) - { - row = mysql_fetch_row(result); - start_time = atoi(row[0]); - duration = atoi(row[1]); - never_expires = atoi(row[2]); - } - else - { - mysql_free_result(result); - is_perma = false; - return 0; - } - mysql_free_result(result); - } - else - { - safe_delete_array(query); is_perma = false; return 0; } + if (results.RowCount() == 0) + { + is_perma = false; + return 0; + } + + auto row = results.begin(); + + start_time = atoi(row[0]); + duration = atoi(row[1]); + never_expires = atoi(row[2]); + if(never_expires == 1) { is_perma = true; return 0; } - else - { - is_perma = false; - } + + is_perma = false; timeval tv; gettimeofday(&tv, nullptr); From 4b647602b36e3e6acad7bb2224b208fffd8925d8 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 14:24:14 -0700 Subject: [PATCH 133/288] GetUnusedInstanceID converted to QueryDatabase --- common/database.cpp | 103 +++++++++++++++++++++++--------------------- 1 file changed, 55 insertions(+), 48 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 486d1516e..f17892fb2 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2291,60 +2291,67 @@ uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma) bool Database::GetUnusedInstanceID(uint16 &instance_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; uint32 count = RuleI(Zone, ReservedInstances); uint32 max = 65535; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT IFNULL(MAX(id),%u)+1 FROM instance_list WHERE id > %u", count,count), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) != 0) { - row = mysql_fetch_row(result); - if(atoi(row[0]) <= max) { - count = atoi(row[0]); - mysql_free_result(result); - } else { - mysql_free_result(result); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT id FROM instance_list where id > %u ORDER BY id", count), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) != 0) { - count++; - while((row = mysql_fetch_row(result))) { - if(count < atoi(row[0])) { - instance_id = count; - mysql_free_result(result); - return true; - } else if(count > max) { - instance_id = 0; - mysql_free_result(result); - return false; - } else { - count++; - } - } - } else { - instance_id = 0; - mysql_free_result(result); - return false; - } - } else { - safe_delete_array(query); - instance_id = 0; - return false; - } - } - } else { - instance_id = 0; - mysql_free_result(result); - return false; - } - } else { - safe_delete_array(query); + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT IFNULL(MAX(id),%u)+1 FROM instance_list WHERE id > %u", count, count)); + safe_delete_array(query); + + if (!results.Success()) + { instance_id = 0; return false; } + + if (results.RowCount() == 0) + { + instance_id = 0; + return false; + } + + auto row = results.begin(); + + if (atoi(row[0]) <= max) + { + instance_id = atoi(row[0]); + return true; + } + + results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT id FROM instance_list where id > %u ORDER BY id", count)); + safe_delete_array(query); + + if (!results.Success()) + { + instance_id = 0; + return false; + } + + if (results.RowCount() == 0) + { + nstance_id = 0; + return false; + } + + count++; + for (auto row = results.begin();row != results.end();++row) + { + if(count < atoi(row[0])) + { + instance_id = count; + return true; + } + + if(count > max) + { + instance_id = 0; + return false; + } + + count++; + } + instance_id = count; return true; } From 010bc76440231c8527a07ea8c66689c9efd89a99 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 14:26:13 -0700 Subject: [PATCH 134/288] CreateInstance converted to QueryDatabase --- common/database.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index f17892fb2..0d7b5030c 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2359,20 +2359,13 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id) //perhaps purge any expireds too bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + char *query = nullptr; - if(RunQuery(query, MakeAnyLenString(&query, "INSERT INTO instance_list (id, zone, version, start_time, duration)" - " values(%lu, %lu, %lu, UNIX_TIMESTAMP(), %lu)", (unsigned long)instance_id, (unsigned long)zone_id, (unsigned long)version, (unsigned long)duration), errbuf)) - { - safe_delete_array(query); - return true; - } - else - { - safe_delete_array(query); - return false; - } + auto results = QueryDatabase(query, MakeAnyLenString(&query, "INSERT INTO instance_list (id, zone, version, start_time, duration)" + " values(%lu, %lu, %lu, UNIX_TIMESTAMP(), %lu)", (unsigned long)instance_id, (unsigned long)zone_id, (unsigned long)version, (unsigned long)duration)); + safe_delete_array(query); + + return results.Success(); } void Database::PurgeExpiredInstances() From 3449f5e11ce24f3438cbb0754b3475a6d9012947 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 14:30:38 -0700 Subject: [PATCH 135/288] PurgeExpiredInstances converted to QueryDatabase --- common/database.cpp | 37 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 0d7b5030c..bff20d99b 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2370,32 +2370,19 @@ bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version void Database::PurgeExpiredInstances() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; - uint16 id = 0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT id FROM instance_list where " - "(start_time+duration) <= UNIX_TIMESTAMP() and never_expires = 0"), errbuf, &result)) - { - safe_delete_array(query); - if (mysql_num_rows(result) > 0) - { - row = mysql_fetch_row(result); - while(row != nullptr) - { - id = atoi(row[0]); - DeleteInstance(id); - row = mysql_fetch_row(result); - } - } - mysql_free_result(result); - } - else - { - safe_delete_array(query); - } + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT id FROM instance_list where (start_time+duration) <= UNIX_TIMESTAMP() and never_expires = 0")); + safe_delete_array(query); + + if (!results.Success()) + return; + + if (results.RowCount() == 0) + return; + + for (auto row = results.begin();row != results.end();++row) + DeleteInstance(atoi(row[0])); } bool Database::AddClientToInstance(uint16 instance_id, uint32 char_id) From e60117cabb545c6c24af7faf7cb9ed080fb2646b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 14:32:11 -0700 Subject: [PATCH 136/288] AddClientToInstance converted to QueryDatabase --- common/database.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index bff20d99b..6908211c2 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2387,20 +2387,13 @@ void Database::PurgeExpiredInstances() bool Database::AddClientToInstance(uint16 instance_id, uint32 char_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + char *query = nullptr; - if(RunQuery(query, MakeAnyLenString(&query, "INSERT INTO instance_list_player(id, charid) " - "values(%lu, %lu)", (unsigned long)instance_id, (unsigned long)char_id), errbuf)) - { - safe_delete_array(query); - return true; - } - else - { - safe_delete_array(query); - return false; - } + auto results = QueryDatabase(query, MakeAnyLenString(&query, "INSERT INTO instance_list_player(id, charid) " + "values(%lu, %lu)", (unsigned long)instance_id, (unsigned long)char_id)); + safe_delete_array(query); + + return results.Success(); } bool Database::RemoveClientFromInstance(uint16 instance_id, uint32 char_id) From e1b251ee8f7d630d713ec4595057e27740badef1 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 14:42:05 -0700 Subject: [PATCH 137/288] CheckInstanceExists converted to QueryDatabase --- common/database.cpp | 65 ++++++++++++++------------------------------- 1 file changed, 20 insertions(+), 45 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 6908211c2..1dbf82df9 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2398,64 +2398,39 @@ bool Database::AddClientToInstance(uint16 instance_id, uint32 char_id) bool Database::RemoveClientFromInstance(uint16 instance_id, uint32 char_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + char *query = nullptr; - if(RunQuery(query, MakeAnyLenString(&query, "DELETE FROM instance_list_player WHERE id=%lu AND charid=%lu", - (unsigned long)instance_id, (unsigned long)char_id), errbuf)) - { - safe_delete_array(query); - return true; - } - else - { - safe_delete_array(query); - return false; - } + auto results = QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM instance_list_player WHERE id=%lu AND charid=%lu", + (unsigned long)instance_id, (unsigned long)char_id)); + safe_delete_array(query); + + return results.Success(); } bool Database::RemoveClientsFromInstance(uint16 instance_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + char *query = nullptr; - if(RunQuery(query, MakeAnyLenString(&query, "DELETE FROM instance_list_player WHERE id=%lu", - (unsigned long)instance_id), errbuf)) - { - safe_delete_array(query); - return true; - } - else - { - safe_delete_array(query); - return false; - } + auto results = QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM instance_list_player WHERE id=%lu", (unsigned long)instance_id)); + safe_delete_array(query); + + return results.Success(); } bool Database::CheckInstanceExists(uint16 instance_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT * FROM instance_list where id=%u", instance_id), - errbuf, &result)) - { - safe_delete_array(query); - if (mysql_num_rows(result) != 0) - { - mysql_free_result(result); - return true; - } - mysql_free_result(result); + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT * FROM instance_list where id=%u", instance_id)); + safe_delete_array(query); + + if (!results.Success()) return false; - } - else - { - safe_delete_array(query); + + if (results.RowCount() == 0) return false; - } - return false; + + return true; } void Database::BuryCorpsesInInstance(uint16 instance_id) From c055b20b938d44b729bef14441a7ae1a46f9dccd Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 14:43:13 -0700 Subject: [PATCH 138/288] BuryCorpsesInInstance converted to QueryDatabase --- common/database.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 1dbf82df9..038937591 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2435,15 +2435,9 @@ bool Database::CheckInstanceExists(uint16 instance_id) void Database::BuryCorpsesInInstance(uint16 instance_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; + char *query = nullptr; - if(RunQuery(query, MakeAnyLenString(&query, "UPDATE player_corpses SET IsBurried=1, instanceid=0 WHERE instanceid=%u", - instance_id), errbuf, &result)) - { - mysql_free_result(result); - } + auto results = QueryDatabase(query, MakeAnyLenString(&query, "UPDATE player_corpses SET IsBurried=1, instanceid=0 WHERE instanceid=%u", instance_id)); safe_delete_array(query); } From c1600596123dcfde7dabb451ddf4ed7656bd0ec6 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 14:47:06 -0700 Subject: [PATCH 139/288] GetInstanceVersion converted to QueryDatabase --- common/database.cpp | 40 ++++++++++++---------------------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 038937591..23bff5861 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2443,38 +2443,22 @@ void Database::BuryCorpsesInInstance(uint16 instance_id) uint16 Database::GetInstanceVersion(uint16 instance_id) { - if(instance_id < 1) + if(instance_id == 0) return 0; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint32 ret; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT version FROM instance_list where id=%u", instance_id), - errbuf, &result)) - { - safe_delete_array(query); - if (mysql_num_rows(result) != 0) - { - row = mysql_fetch_row(result); - ret = atoi(row[0]); - mysql_free_result(result); - return ret; - } - else - { - mysql_free_result(result); - return 0; - } - } - else - { - safe_delete_array(query); + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT version FROM instance_list where id=%u", instance_id)); + safe_delete_array(query); + + if (!results.Success()) return 0; - } - return 0; + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + return atoi(row[0]); } uint16 Database::GetInstanceID(const char* zone, uint32 charid, int16 version) From 41660240fbf80042c68281989c8bd74dee20b6e7 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 14:52:40 -0700 Subject: [PATCH 140/288] GetInstanceID converted to QueryDatabase --- common/database.cpp | 41 +++++++++++++---------------------------- 1 file changed, 13 insertions(+), 28 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 23bff5861..abd13d712 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2463,36 +2463,21 @@ uint16 Database::GetInstanceVersion(uint16 instance_id) uint16 Database::GetInstanceID(const char* zone, uint32 charid, int16 version) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint16 ret; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT instance_list.id FROM instance_list, instance_list_player " - "WHERE instance_list.zone=%u AND instance_list.version=%u AND instance_list.id=instance_list_player.id AND " - "instance_list_player.charid=%u LIMIT 1;", GetZoneID(zone), version, charid, charid), errbuf, &result)) - { - safe_delete_array(query); - if (mysql_num_rows(result) != 0) - { - row = mysql_fetch_row(result); - ret = atoi(row[0]); - mysql_free_result(result); - return ret; - } - else - { - mysql_free_result(result); - return 0; - } - } - else - { - safe_delete_array(query); + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT instance_list.id FROM instance_list, instance_list_player " + "WHERE instance_list.zone=%u AND instance_list.version=%u AND instance_list.id=instance_list_player.id AND " + "instance_list_player.charid=%u LIMIT 1;", GetZoneID(zone), version, charid, charid)); + safe_delete_array(query); + + if (!results.Success()) return 0; - } - return 0; + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + return atoi(row[0]); } uint16 Database::GetInstanceID(uint32 zone, uint32 charid, int16 version) From d32f16fef5abfd74685792d398c9a45abc4773c9 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 14:56:48 -0700 Subject: [PATCH 141/288] GetInstanceID (uint32 zone version) converted to QueryDatabase --- common/database.cpp | 42 ++++++++++++++---------------------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index abd13d712..b6bd1ee58 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2485,36 +2485,22 @@ uint16 Database::GetInstanceID(uint32 zone, uint32 charid, int16 version) if(!zone) return 0; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint16 ret; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT instance_list.id FROM instance_list, instance_list_player " - "WHERE instance_list.zone=%u AND instance_list.version=%u AND instance_list.id=instance_list_player.id AND " - "instance_list_player.charid=%u LIMIT 1;", zone, version, charid), errbuf, &result)) - { - safe_delete_array(query); - if (mysql_num_rows(result) != 0) - { - row = mysql_fetch_row(result); - ret = atoi(row[0]); - mysql_free_result(result); - return ret; - } - else - { - mysql_free_result(result); - return 0; - } - } - else - { - safe_delete_array(query); + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT instance_list.id FROM instance_list, instance_list_player " + "WHERE instance_list.zone=%u AND instance_list.version=%u AND instance_list.id=instance_list_player.id AND " + "instance_list_player.charid=%u LIMIT 1;", zone, version, charid)); + safe_delete_array(query); + + if (!results.Success()) return 0; - } - return 0; + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + + return atoi(row[0]); } void Database::GetCharactersInInstance(uint16 instance_id, std::list &charid_list) { From 4f4f9e8eb38371494a83b3eda10b846061a39151 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 15:00:43 -0700 Subject: [PATCH 142/288] GetUnusedInsanceId converted to QueryDatabase --- common/database.cpp | 48 ++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index b6bd1ee58..0d38ce55c 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1181,10 +1181,10 @@ const char* Database::GetZoneName(uint32 zoneID, bool ErrorUnknown) { if (iter != zonename_array.end()) return iter->second.c_str(); - + if (ErrorUnknown) return "UNKNOWN"; - + return 0; } @@ -1853,7 +1853,7 @@ void Database::SetGroupLeaderName(uint32 gid, const char* name) { auto results = QueryDatabase(query, MakeAnyLenString(&query, "Replace into group_leaders set gid=%lu, leadername='%s'",(unsigned long)gid,name)); safe_delete_array(query); - + if (!results.Success()) std::cout << "Unable to set group leader: " << results.ErrorMessage() << std::endl; } @@ -1917,7 +1917,7 @@ char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* mainta return leaderbuf; } -// Clearing all group leaders +// Clearing all group leaders void Database::ClearAllGroupLeaders(void) { char *query = nullptr; @@ -1933,8 +1933,8 @@ void Database::ClearAllGroupLeaders(void) void Database::ClearGroupLeader(uint32 gid) { char *query = nullptr; - if(gid == 0) - { + if(gid == 0) + { ClearAllGroupLeaders(); return; } @@ -1992,13 +1992,13 @@ void Database::SetAgreementFlag(uint32 acctid) void Database::ClearRaid(uint32 rid) { char *query = nullptr; - if(rid == 0) - { + if(rid == 0) + { //clear all raids ClearAllRaids(); return; - } - + } + //clear a specific group auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from raid_members where raidid = %lu", (unsigned long)rid)); safe_delete_array(query); @@ -2021,7 +2021,7 @@ void Database::ClearAllRaids(void) void Database::ClearAllRaidDetails(void) { char *query = nullptr; - + auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from raid_details")); safe_delete_array(query); @@ -2034,12 +2034,12 @@ void Database::ClearAllRaidDetails(void) void Database::ClearRaidDetails(uint32 rid) { char *query = nullptr; - if(rid == 0) - { + if(rid == 0) + { //clear all raids ClearAllRaidDetails(); return; - } + } //clear a specific group auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from raid_details where raidid = %lu", (unsigned long)rid)); @@ -2049,7 +2049,7 @@ void Database::ClearRaidDetails(uint32 rid) { std::cout << "Unable to clear raid details: " << results.ErrorMessage() << std::endl; } -// returns 0 on error or no raid for that character, or +// returns 0 on error or no raid for that character, or // the raid id that the character is a member of. uint32 Database::GetRaidID(const char* name){ char *query = nullptr; @@ -2081,10 +2081,10 @@ const char* Database::GetRaidLeaderName(uint32 rid) { // Would be a good idea to fix this to be a passed in variable and // make the caller responsible. static local variables like this are - // not guaranteed to be thread safe (nor is the internal guard + // not guaranteed to be thread safe (nor is the internal guard // variable). C++0x standard states this should be thread safe // but may not be fully supported in some compilers. - static char name[128]; + static char name[128]; char *query = nullptr; auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT name FROM raid_members WHERE raidid=%u AND israidleader=1",rid)); @@ -2330,24 +2330,24 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id) if (results.RowCount() == 0) { - nstance_id = 0; + instance_id = 0; return false; } count++; for (auto row = results.begin();row != results.end();++row) { - if(count < atoi(row[0])) + if(count < atoi(row[0])) { instance_id = count; return true; - } - - if(count > max) + } + + if(count > max) { instance_id = 0; return false; - } + } count++; } @@ -2450,7 +2450,7 @@ uint16 Database::GetInstanceVersion(uint16 instance_id) auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT version FROM instance_list where id=%u", instance_id)); safe_delete_array(query); - + if (!results.Success()) return 0; From 0ea1010e3f9ce4c0662410573748c8afd0788cf4 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 15:07:55 -0700 Subject: [PATCH 143/288] GetCharactersInInstance converted to QueryDatabase --- common/database.cpp | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 0d38ce55c..4fbb3fa42 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2504,23 +2504,20 @@ uint16 Database::GetInstanceID(uint32 zone, uint32 charid, int16 version) } void Database::GetCharactersInInstance(uint16 instance_id, std::list &charid_list) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT charid FROM instance_list_player WHERE id=%u", instance_id), errbuf, &result)) { - safe_delete_array(query); - while ((row = mysql_fetch_row(result))) - { - charid_list.push_back(atoi(row[0])); - } - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "Error in GetCharactersInInstace query '%s': %s", query, errbuf); + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT charid FROM instance_list_player WHERE id=%u", instance_id)); + + if (!results.Success()) + { + LogFile->write(EQEMuLog::Error, "Error in GetCharactersInInstace query '%s': %s", query, results.ErrorMessage().c_str()); safe_delete_array(query); + return; } + safe_delete_array(query); + + for(auto row=results.begin();row != results.end();++row) + charid_list.push_back(atoi(row[0])); } void Database::AssignGroupToInstance(uint32 gid, uint32 instance_id) From 989b5d96c59e37fe1a168a5f9a89348a93ff882b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 15:11:09 -0700 Subject: [PATCH 144/288] AssignGroupToInstance converted to QueryDatabase --- common/database.cpp | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 4fbb3fa42..07f635a3f 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2522,30 +2522,21 @@ void Database::GetCharactersInInstance(uint16 instance_id, std::list &ch void Database::AssignGroupToInstance(uint32 gid, uint32 instance_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; uint32 zone_id = ZoneIDFromInstanceID(instance_id); uint16 version = VersionFromInstanceID(instance_id); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT charid FROM group_id WHERE groupid=%u", gid), - errbuf, &result)) + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT charid FROM group_id WHERE groupid=%u", gid)); + safe_delete_array(query); + + if (!results.Success()) + return; + + for (auto row=results.begin();row != results.end();++row) { - safe_delete_array(query); - while((row = mysql_fetch_row(result)) != nullptr) - { - uint32 charid = atoi(row[0]); - if(GetInstanceID(zone_id, charid, version) == 0) - { - AddClientToInstance(instance_id, charid); - } - } - mysql_free_result(result); - } - else - { - safe_delete_array(query); + uint32 charid = atoi(row[0]); + if(GetInstanceID(zone_id, charid, version) == 0) + AddClientToInstance(instance_id, charid); } } From bb2dc991ebee201c750fd333ff8768ed41b53255 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 15:13:12 -0700 Subject: [PATCH 145/288] AssignRaidToInstance converted to QueryDatabase --- common/database.cpp | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 07f635a3f..f9f99f1a9 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2542,30 +2542,21 @@ void Database::AssignGroupToInstance(uint32 gid, uint32 instance_id) void Database::AssignRaidToInstance(uint32 rid, uint32 instance_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; uint32 zone_id = ZoneIDFromInstanceID(instance_id); uint16 version = VersionFromInstanceID(instance_id); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT charid FROM raid_members WHERE raidid=%u", rid), - errbuf, &result)) + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT charid FROM raid_members WHERE raidid=%u", rid)); + safe_delete_array(query); + + if (!results.Success()) + return; + + for (auto row=results.begin();row!=results.end();++row) { - safe_delete_array(query); - while((row = mysql_fetch_row(result)) != nullptr) - { - uint32 charid = atoi(row[0]); - if(GetInstanceID(zone_id, charid, version) == 0) - { - AddClientToInstance(instance_id, charid); - } - } - mysql_free_result(result); - } - else - { - safe_delete_array(query); + uint32 charid = atoi(row[0]); + if(GetInstanceID(zone_id, charid, version) == 0) + AddClientToInstance(instance_id, charid); } } From 167ce7829c40ad521b9c4646d53dac802c1ce55e Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 15:18:39 -0700 Subject: [PATCH 146/288] SetInstanceDuration converted to QueryDatabase --- common/database.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index f9f99f1a9..0aa244590 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2595,19 +2595,11 @@ void Database::FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 chari void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + char *query = nullptr; - if(RunQuery(query, MakeAnyLenString(&query, "UPDATE `instance_list` SET start_time=UNIX_TIMESTAMP(), " - "duration=%u WHERE id=%u", new_duration, instance_id), errbuf)) - { - safe_delete_array(query); - } - else - { - //error - safe_delete_array(query); - } + auto results = QueryDatabase(query, MakeAnyLenString(&query, "UPDATE `instance_list` SET start_time=UNIX_TIMESTAMP(), " + "duration=%u WHERE id=%u", new_duration, instance_id)); + safe_delete_array(query); } bool Database::GlobalInstance(uint16 instance_id) From 22d06bc3d14dac1f37252bbd76ac5bbf894f3b4c Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 15:21:59 -0700 Subject: [PATCH 147/288] GlobalInstance converted to QueryDatabase --- common/database.cpp | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 0aa244590..ea5ff9679 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2604,32 +2604,20 @@ void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration) bool Database::GlobalInstance(uint16 instance_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - bool ret; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT is_global from instance_list where id=%u LIMIT 1", instance_id), errbuf, &result)) - { - safe_delete_array(query); - row = mysql_fetch_row(result); - if(row) - { - ret = (atoi(row[0]) == 1) ? true : false; - } - else - { - mysql_free_result(result); - return false; - } - } - else - { - safe_delete_array(query); + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT is_global from instance_list where id=%u LIMIT 1", instance_id)); + safe_delete_array(query); + + if (!results.Success()) return false; - } - return ret; + + if (results.RowCount() == 0) + return false; + + auto row = results.begin(); + + return (atoi(row[0]) == 1) ? true : false; } void Database::UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win) From 28212ab8f8d991f1564715d643c2404d3a90eaeb Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 15:27:44 -0700 Subject: [PATCH 148/288] UpdateAdventureStatsEntry converted to QueryDatabase --- common/database.cpp | 129 ++++++++++++++------------------------------ 1 file changed, 40 insertions(+), 89 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index ea5ff9679..06a408c73 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2622,107 +2622,58 @@ bool Database::GlobalInstance(uint16 instance_id) void Database::UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected = 0; + char *query = nullptr; std::string field; - if(win) + switch(theme) { - switch(theme) + case 1: { - case 1: - { - field = "guk_wins"; - break; - } - case 2: - { - field = "mir_wins"; - break; - } - case 3: - { - field = "mmc_wins"; - break; - } - case 4: - { - field = "ruj_wins"; - break; - } - case 5: - { - field = "tak_wins"; - break; - } - default: - { - return; - } + field = "guk_"; + break; } - } - else - { - switch(theme) + case 2: { - case 1: - { - field = "guk_losses"; - break; - } - case 2: - { - field = "mir_losses"; - break; - } - case 3: - { - field = "mmc_losses"; - break; - } - case 4: - { - field = "ruj_losses"; - break; - } - case 5: - { - field = "tak_losses"; - break; - } - default: - { - return; - } + field = "mir_"; + break; + } + case 3: + { + field = "mmc_"; + break; + } + case 4: + { + field = "ruj_"; + break; + } + case 5: + { + field = "tak_"; + break; + } + default: + { + return; } } - if(RunQuery(query, MakeAnyLenString(&query, "UPDATE `adventure_stats` SET %s=%s+1 WHERE player_id=%u", - field.c_str(), field.c_str(), char_id), errbuf, nullptr, &affected)) - { - safe_delete_array(query); - } + if (win) + field += "wins"; else - { - //error - safe_delete_array(query); - } + field += "losses"; - if(affected == 0) - { - if(RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `adventure_stats` SET %s=1, player_id=%u", - field.c_str(), char_id), errbuf)) - { - safe_delete_array(query); - } - else - { - //error - safe_delete_array(query); - } - } + auto results = QueryDatabase(query, MakeAnyLenString(&query, "UPDATE `adventure_stats` SET %s=%s+1 WHERE player_id=%u", + field.c_str(), field.c_str(), char_id)); + safe_delete_array(query); + + if (results.RowsAffected() != 0) + return; + + QueryDatabase(query, MakeAnyLenString(&query, "INSERT INTO `adventure_stats` SET %s=1, player_id=%u", + field.c_str(), char_id)); + safe_delete_array(query); } bool Database::GetAdventureStats(uint32 char_id, uint32 &guk_w, uint32 &mir_w, uint32 &mmc_w, uint32 &ruj_w, From 01991f4bebfa04a97ef3dc4b2e04f3052f6e5963 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 15:30:43 -0700 Subject: [PATCH 149/288] GetAdventureStats converted to QueryDatabase --- common/database.cpp | 52 +++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 06a408c73..d4f237ec3 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2679,37 +2679,33 @@ void Database::UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win) bool Database::GetAdventureStats(uint32 char_id, uint32 &guk_w, uint32 &mir_w, uint32 &mmc_w, uint32 &ruj_w, uint32 &tak_w, uint32 &guk_l, uint32 &mir_l, uint32 &mmc_l, uint32 &ruj_l, uint32 &tak_l) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT `guk_wins`, `mir_wins`, `mmc_wins`, `ruj_wins`, `tak_wins`, " + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT `guk_wins`, `mir_wins`, `mmc_wins`, `ruj_wins`, `tak_wins`, " "`guk_losses`, `mir_losses`, `mmc_losses`, `ruj_losses`, `tak_losses` FROM `adventure_stats` WHERE player_id=%u", - char_id), errbuf, &result)) - { - safe_delete_array(query); - while((row = mysql_fetch_row(result)) != nullptr) - { - guk_w = atoi(row[0]); - mir_w = atoi(row[1]); - mmc_w = atoi(row[2]); - ruj_w = atoi(row[3]); - tak_w = atoi(row[4]); - guk_l = atoi(row[5]); - mir_l = atoi(row[6]); - mmc_l = atoi(row[7]); - ruj_l = atoi(row[8]); - tak_l = atoi(row[9]); - } - mysql_free_result(result); - return true; - } - else - { - safe_delete_array(query); + char_id)); + safe_delete_array(query); + + if (!results.Success()) return false; - } + + if (results.RowCount() == 0) + return false; + + auto row = results.begin(); + + guk_w = atoi(row[0]); + mir_w = atoi(row[1]); + mmc_w = atoi(row[2]); + ruj_w = atoi(row[3]); + tak_w = atoi(row[4]); + guk_l = atoi(row[5]); + mir_l = atoi(row[6]); + mmc_l = atoi(row[7]); + ruj_l = atoi(row[8]); + tak_l = atoi(row[9]); + + return true; } uint32 Database::GetGuildDBIDByCharID(uint32 char_id) { From cdcb5e0692093571344e39ae5d0e82cc08b09767 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 15:36:30 -0700 Subject: [PATCH 150/288] renamed GetGuildDBIDByChar to GetGuildIDByChar, converted to QueryDatabase --- common/database.cpp | 31 ++++++++++++++++--------------- common/database.h | 2 +- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index d4f237ec3..fb5d439a0 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2708,22 +2708,23 @@ bool Database::GetAdventureStats(uint32 char_id, uint32 &guk_w, uint32 &mir_w, u return true; } -uint32 Database::GetGuildDBIDByCharID(uint32 char_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - int retVal = 0; +uint32 Database::GetGuildIDByCharID(uint32 char_id) +{ + char *query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT guild_id FROM guild_members WHERE char_id='%i'", char_id), errbuf, &result)) { - if (mysql_num_rows(result) == 1) { - MYSQL_ROW row = mysql_fetch_row(result); - retVal = atoi(row[0]); - } - mysql_free_result(result); - } - else { - std::cerr << "Error in GetAccountIDByChar query '" << query << "' " << errbuf << std::endl; + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT guild_id FROM guild_members WHERE char_id='%i'", char_id)); + + if (!results.Success()) + { + std::cerr << "Error in GetGuildIDByChar query '" << query << "' " << results.ErrorMessage() << std::endl; + safe_delete_array(query); + return 0; } safe_delete_array(query); - return retVal; + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + return atoi(row[0]); } diff --git a/common/database.h b/common/database.h index c7adc7666..2e26a7b90 100644 --- a/common/database.h +++ b/common/database.h @@ -130,7 +130,7 @@ public: uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0); uint32 GetAccountIDByChar(uint32 char_id); uint32 GetAccountIDByName(const char* accname, int16* status = 0, uint32* lsid = 0); - uint32 GetGuildDBIDByCharID(uint32 char_id); + uint32 GetGuildIDByCharID(uint32 char_id); void GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID = 0); void GetCharName(uint32 char_id, char* name); uint32 GetCharacterInfo(const char* iName, uint32* oAccID = 0, uint32* oZoneID = 0, uint32* oInstanceID = 0,float* oX = 0, float* oY = 0, float* oZ = 0); From 727d8a2bf885cf94641b993ba6be0bf477c03438 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 5 Jul 2014 10:10:55 -0700 Subject: [PATCH 151/288] Added LengthOfColumn method because of stupid BLOBs --- common/MySQLRequestResult.cpp | 29 +++++++++++++++++++++++++++++ common/MySQLRequestResult.h | 3 +++ 2 files changed, 32 insertions(+) diff --git a/common/MySQLRequestResult.cpp b/common/MySQLRequestResult.cpp index 16d7fe9a0..8fc47cfca 100644 --- a/common/MySQLRequestResult.cpp +++ b/common/MySQLRequestResult.cpp @@ -32,6 +32,10 @@ MySQLRequestResult::MySQLRequestResult(MYSQL_RES* result, uint32 rowsAffected, u m_RowsAffected = rowsAffected; m_RowCount = rowCount; m_ColumnCount = columnCount; + // If we actually need the column length it will be requested + // at that time, no need to pull it in just to cache it. + // Normal usage would have it as nullptr most likely anyways. + m_ColumnLengths = nullptr; m_LastInsertedID = lastInsertedID; m_ErrorNumber = errorNumber; } @@ -51,6 +55,7 @@ void MySQLRequestResult::ZeroOut() m_Success = false; m_Result = nullptr; m_ErrorBuffer = nullptr; + m_ColumnLengths = nullptr; m_RowCount = 0; m_RowsAffected = 0; m_LastInsertedID = 0; @@ -61,6 +66,28 @@ MySQLRequestResult::~MySQLRequestResult() FreeInternals(); } +uint32 MySQLRequestResult::LengthOfColumn(int columnIndex) +{ + if (m_ColumnLengths == nullptr && m_Result != nullptr) + m_ColumnLengths = mysql_fetch_lengths(m_Result); + + // If someone screws up and tries to get the length of a + // column when no result occured (check Success! argh!) + // then we always return 0. Also applies if mysql screws + // up and can't get the column lengths for whatever reason. + if (m_ColumnLengths == nullptr) + return 0; + + // Want to index check to be sure we don't read passed + // the end of the array. Just default to 0 in that case. + // We *shouldn't* need this or the previous checks if all + // interface code is correctly written. + if (columnIndex >= m_ColumnCount) + return 0; + + return m_ColumnLengths[columnIndex]; +} + MySQLRequestResult::MySQLRequestResult(MySQLRequestResult&& moveItem) : m_CurrentRow(moveItem.m_CurrentRow), m_OneBeyondRow() { @@ -70,6 +97,7 @@ MySQLRequestResult::MySQLRequestResult(MySQLRequestResult&& moveItem) m_RowCount = moveItem.m_RowCount; m_RowsAffected = moveItem.m_RowsAffected; m_LastInsertedID = moveItem.m_LastInsertedID; + m_ColumnLengths = moveItem.m_ColumnLengths; // Keeps deconstructor from double freeing // pre move instance. @@ -95,6 +123,7 @@ MySQLRequestResult& MySQLRequestResult::operator=(MySQLRequestResult&& other) m_LastInsertedID = other.m_LastInsertedID; m_CurrentRow = other.m_CurrentRow; m_OneBeyondRow = other.m_OneBeyondRow; + m_ColumnLengths = other.m_ColumnLengths; // Keeps deconstructor from double freeing // pre move instance. diff --git a/common/MySQLRequestResult.h b/common/MySQLRequestResult.h index 0bf644c98..15488920e 100644 --- a/common/MySQLRequestResult.h +++ b/common/MySQLRequestResult.h @@ -17,6 +17,7 @@ class MySQLRequestResult { private: MYSQL_RES* m_Result; char* m_ErrorBuffer; + unsigned long* m_ColumnLengths; MySQLRequestRow m_CurrentRow; MySQLRequestRow m_OneBeyondRow; @@ -44,6 +45,8 @@ public: uint32 RowCount() const {return m_RowCount;} uint32 ColumnCount() const {return m_ColumnCount;} uint32 LastInsertedID() const {return m_LastInsertedID;} + // default to 0 index since we mostly use it that way anyways. + uint32 LengthOfColumn(int columnIndex = 0); MySQLRequestRow& begin() { return m_CurrentRow; } MySQLRequestRow& end() { return m_OneBeyondRow;} From 9a30c2465469c0a3540576194da398801a5b2899 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 16:01:10 -0700 Subject: [PATCH 152/288] Added FieldName for column name requests --- common/MySQLRequestResult.cpp | 21 ++++++++++++++++++--- common/MySQLRequestResult.h | 2 ++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/common/MySQLRequestResult.cpp b/common/MySQLRequestResult.cpp index 8fc47cfca..56e62ae37 100644 --- a/common/MySQLRequestResult.cpp +++ b/common/MySQLRequestResult.cpp @@ -32,10 +32,11 @@ MySQLRequestResult::MySQLRequestResult(MYSQL_RES* result, uint32 rowsAffected, u m_RowsAffected = rowsAffected; m_RowCount = rowCount; m_ColumnCount = columnCount; - // If we actually need the column length it will be requested - // at that time, no need to pull it in just to cache it. + // If we actually need the column length / fields it will be + // requested at that time, no need to pull it in just to cache it. // Normal usage would have it as nullptr most likely anyways. m_ColumnLengths = nullptr; + m_Fields = nullptr; m_LastInsertedID = lastInsertedID; m_ErrorNumber = errorNumber; } @@ -56,6 +57,7 @@ void MySQLRequestResult::ZeroOut() m_Result = nullptr; m_ErrorBuffer = nullptr; m_ColumnLengths = nullptr; + m_Fields = nullptr; m_RowCount = 0; m_RowsAffected = 0; m_LastInsertedID = 0; @@ -88,6 +90,17 @@ uint32 MySQLRequestResult::LengthOfColumn(int columnIndex) return m_ColumnLengths[columnIndex]; } +const std::string MySQLRequestResult::FieldName(int columnIndex) +{ + if (columnIndex >= m_ColumnCount || m_Result == nullptr) + return std::string(); + + if (m_Fields == nullptr) + m_Fields = mysql_fetch_fields(m_Result); + + return std::string(m_Fields[columnIndex].name); +} + MySQLRequestResult::MySQLRequestResult(MySQLRequestResult&& moveItem) : m_CurrentRow(moveItem.m_CurrentRow), m_OneBeyondRow() { @@ -98,6 +111,7 @@ MySQLRequestResult::MySQLRequestResult(MySQLRequestResult&& moveItem) m_RowsAffected = moveItem.m_RowsAffected; m_LastInsertedID = moveItem.m_LastInsertedID; m_ColumnLengths = moveItem.m_ColumnLengths; + m_Fields = moveItem.m_Fields; // Keeps deconstructor from double freeing // pre move instance. @@ -124,7 +138,8 @@ MySQLRequestResult& MySQLRequestResult::operator=(MySQLRequestResult&& other) m_CurrentRow = other.m_CurrentRow; m_OneBeyondRow = other.m_OneBeyondRow; m_ColumnLengths = other.m_ColumnLengths; - + m_Fields = other.m_Fields; + // Keeps deconstructor from double freeing // pre move instance. other.ZeroOut(); diff --git a/common/MySQLRequestResult.h b/common/MySQLRequestResult.h index 15488920e..0f6cac40e 100644 --- a/common/MySQLRequestResult.h +++ b/common/MySQLRequestResult.h @@ -16,6 +16,7 @@ class MySQLRequestResult { private: MYSQL_RES* m_Result; + MYSQL_FIELD* m_Fields; char* m_ErrorBuffer; unsigned long* m_ColumnLengths; MySQLRequestRow m_CurrentRow; @@ -47,6 +48,7 @@ public: uint32 LastInsertedID() const {return m_LastInsertedID;} // default to 0 index since we mostly use it that way anyways. uint32 LengthOfColumn(int columnIndex = 0); + const std::string FieldName(int columnIndex); MySQLRequestRow& begin() { return m_CurrentRow; } MySQLRequestRow& end() { return m_OneBeyondRow;} From 1655050730f1396d0cbd193ff5add45695a4f454 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 16:15:54 -0700 Subject: [PATCH 153/288] string based QueryDatabase --- common/dbcore.cpp | 5 +++++ common/dbcore.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/common/dbcore.cpp b/common/dbcore.cpp index ce1b41bdc..9b6236e5a 100644 --- a/common/dbcore.cpp +++ b/common/dbcore.cpp @@ -58,6 +58,11 @@ void DBcore::ping() { MDatabase.unlock(); } +MySQLRequestResult DBcore::QueryDatabase(std::string query, bool retryOnFailureOnce) +{ + return QueryDatabase(query.c_str(), query.length(), retryOnFailureOnce); +} + MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, bool retryOnFailureOnce) { LockMutex lock(&MDatabase); diff --git a/common/dbcore.h b/common/dbcore.h index 13a395eac..2c3602a81 100644 --- a/common/dbcore.h +++ b/common/dbcore.h @@ -7,6 +7,7 @@ #endif #include +#include #include "../common/types.h" #include "../common/Mutex.h" #include "../common/linked_list.h" @@ -24,6 +25,7 @@ public: eStatus GetStatus() { return pStatus; } bool RunQuery(const char* query, uint32 querylen, char* errbuf = 0, MYSQL_RES** result = 0, uint32* affected_rows = 0, uint32* last_insert_id = 0, uint32* errnum = 0, bool retry = true); MySQLRequestResult QueryDatabase(const char* query, uint32 querylen, bool retryOnFailureOnce = true); + MySQLRequestResult QueryDatabase(std::string query, bool retryOnFailureOnce = true); uint32 DoEscapeString(char* tobuf, const char* frombuf, uint32 fromlen); void ping(); MYSQL* getMySQL(){ return &mysql; } From 2afd05de980a0f74c48a0bf02178f9b9bab02f75 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 10:17:51 -0700 Subject: [PATCH 154/288] GetGroupLeaderForLogin converted to QueryDatabase --- common/database.cpp | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index fb5d439a0..cba2b8dee 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1827,24 +1827,27 @@ uint32 Database::GetGroupID(const char* name){ } char* Database::GetGroupLeaderForLogin(const char* name,char* leaderbuf){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + char *query = nullptr; + PlayerProfile_Struct pp; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT profile from character_ where name='%s'", name), errbuf, &result)) { - row = mysql_fetch_row(result); - unsigned long* lengths = mysql_fetch_lengths(result); - if (lengths[0] == sizeof(PlayerProfile_Struct)) { - memcpy(&pp, row[0], sizeof(PlayerProfile_Struct)); - strcpy(leaderbuf,pp.groupMembers[0]); - } - mysql_free_result(result); - } - else{ - printf("Unable to get leader name: %s\n",errbuf); - } + + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT profile from character_ where name='%s'", name)); safe_delete_array(query); + + if (!results.Success()) + { + std::cout << "Unable to get leader name: " << results.ErrorMessage() << std::endl; + return leaderbuf; + } + + if (results.LengthOfColumn(0) != sizeof(PlayerProfile_Struct)) + return leaderbuf; + + auto row = results.begin(); + + memcpy(&pp, row[0], sizeof(PlayerProfile_Struct)); + strcpy(leaderbuf,pp.groupMembers[0]); + return leaderbuf; } From 2278ec023f2c10865530b5eee5b4a1fb1d1ea81b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 10:18:35 -0700 Subject: [PATCH 155/288] GetGroupLeadershipInfo converted to QueryDatabase --- common/database.cpp | 62 +++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index cba2b8dee..a68c5ec4d 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1862,60 +1862,50 @@ void Database::SetGroupLeaderName(uint32 gid, const char* name) { } char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank, char* assist, char* puller, char *marknpc, GroupLeadershipAA_Struct* GLAA){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES* result; - MYSQL_ROW row; + char* query = nullptr; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT leadername, maintank, assist, puller, marknpc, leadershipaa FROM group_leaders WHERE gid=%lu",(unsigned long)gid), - errbuf, &result)) { + auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT leadername, maintank, assist, puller, marknpc, leadershipaa FROM group_leaders WHERE gid=%lu",(unsigned long)gid)); + safe_delete_array(query); - safe_delete_array(query); + if (!results.Success() || results.RowCount() == 0) + { + if(leaderbuf) + strcpy(leaderbuf, "UNKNOWN"); - row = mysql_fetch_row(result); - unsigned long* Lengths = mysql_fetch_lengths(result); + if(maintank) + maintank[0] = '\0'; - if(row != nullptr){ + if(assist) + assist[0] = '\0'; - if(leaderbuf) - strcpy(leaderbuf, row[0]); + if(puller) + puller[0] = '\0'; - if(maintank) - strcpy(maintank, row[1]); + if(marknpc) + marknpc[0] = '\0'; - if(assist) - strcpy(assist, row[2]); - - if(puller) - strcpy(puller, row[3]); - - if(marknpc) - strcpy(marknpc, row[4]); - - if(GLAA && (Lengths[5] == sizeof(GroupLeadershipAA_Struct))) - memcpy(GLAA, row[5], sizeof(GroupLeadershipAA_Struct)); - - mysql_free_result(result); - return leaderbuf; - } + return leaderbuf; } - else - safe_delete_array(query); + + auto row = results.begin(); if(leaderbuf) - strcpy(leaderbuf, "UNKNOWN"); + strcpy(leaderbuf, row[0]); if(maintank) - maintank[0] = 0; + strcpy(maintank, row[1]); if(assist) - assist[0] = 0; + strcpy(assist, row[2]); if(puller) - puller[0] = 0; + strcpy(puller, row[3]); if(marknpc) - marknpc[0] = 0; + strcpy(marknpc, row[4]); + + if(GLAA && results.LengthOfColumn(5) == sizeof(GroupLeadershipAA_Struct)) + memcpy(GLAA, row[5], sizeof(GroupLeadershipAA_Struct)); return leaderbuf; } From c39eb3ca869f9142fd19eb67e52e4d32164f9fbb Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 10:48:29 -0700 Subject: [PATCH 156/288] Removed unused FetchRowMap --- common/database.cpp | 17 ----------------- common/database.h | 1 - 2 files changed, 18 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index a68c5ec4d..f4ebe94b5 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1939,23 +1939,6 @@ void Database::ClearGroupLeader(uint32 gid) { std::cout << "Unable to clear group leader: " << results.ErrorMessage() << std::endl; } -bool FetchRowMap(MYSQL_RES *result, std::map &rowmap) -{ -MYSQL_FIELD *fields; -MYSQL_ROW row; -unsigned long num_fields,i; -bool retval=false; - rowmap.clear(); - if (result && (num_fields=mysql_num_fields(result)) && (row = mysql_fetch_row(result))!=nullptr && (fields = mysql_fetch_fields(result))!=nullptr) { - retval=true; - for(i=0;i &rowmap); #endif From 98ebbd50a1ac2e9ee7b3badffc8a6f76384d74f7 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 17:40:42 -0700 Subject: [PATCH 157/288] minor formatting clean up, no functional changes --- common/database.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index f4ebe94b5..3fff533cd 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -43,15 +43,10 @@ #include "database.h" #include "eq_packet_structs.h" #include "guilds.h" -//#include "MiscFunctions.h" #include "StringUtil.h" #include "extprofile.h" extern Client client; -/* -This is the amount of time in seconds the client has to enter the zone -server after the world server, or inbetween zones when that is finished -*/ /* Establish a connection to a mysql database with the supplied parameters @@ -100,8 +95,6 @@ void Database::DBInitVars() { varcache_lastupdate = 0; } - - void Database::HandleMysqlError(uint32 errnum) { /* switch(errnum) { case 0: @@ -141,7 +134,6 @@ Database::~Database() } } - /* Check if there is an account with name "name" and password "password" Return the account id or zero if no account matches. @@ -186,7 +178,6 @@ uint32 Database::CheckLogin(const char* name, const char* password, int16* oStat return id; } - //Get Banned IP Address List - Only return false if the incoming connection's IP address is not present in the banned_ips table. bool Database::CheckBannedIPs(const char* loginIP) { @@ -1049,7 +1040,6 @@ bool Database::GetSafePoints(const char* short_name, uint32 version, float* safe return true; } - bool Database::GetZoneLongName(const char* short_name, char** long_name, char* file_name, float* safe_x, float* safe_y, float* safe_z, uint32* graveyard_id, uint32* maxclients) { char *query = nullptr; @@ -1090,6 +1080,7 @@ bool Database::GetZoneLongName(const char* short_name, char** long_name, char* f return true; } + uint32 Database::GetZoneGraveyardID(uint32 zone_id, uint32 version) { char *query = nullptr; From b23fb0e635524e7cc6b72063984b239084bcffcb Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 19:11:06 -0700 Subject: [PATCH 158/288] CheckBannedIPs converted to StringFormat --- common/database.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 3fff533cd..049de8475 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -181,20 +181,16 @@ uint32 Database::CheckLogin(const char* name, const char* password, int16* oStat //Get Banned IP Address List - Only return false if the incoming connection's IP address is not present in the banned_ips table. bool Database::CheckBannedIPs(const char* loginIP) { - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT ip_address FROM Banned_IPs WHERE ip_address='%s'", loginIP)); + std::string query = StringFormat("SELECT ip_address FROM Banned_IPs WHERE ip_address='%s'", loginIP); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in CheckBannedIPs query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return true; } - safe_delete_array(query); - if (results.RowCount() != 0) return true; From 0ddceb78bacf4925e1406464185b92f409356d54 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 19:13:38 -0700 Subject: [PATCH 159/288] AddBannedIP converted to StringFormat --- common/database.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 049de8475..2c007bb4f 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -199,19 +199,16 @@ bool Database::CheckBannedIPs(const char* loginIP) bool Database::AddBannedIP(char* bannedIP, const char* notes) { - char *query = nullptr; + std::string query = StringFormat("INSERT into Banned_IPs SET ip_address='%s', notes='%s'", bannedIP, notes); - auto results = QueryDatabase(query, MakeAnyLenString(&query, "INSERT into Banned_IPs SET ip_address='%s', notes='%s'", bannedIP, notes)); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in ReserveName query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return false; } - safe_delete_array(query); - return true; } From a0362003693016806de46bf4f4451174f163f9bc Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 19:16:36 -0700 Subject: [PATCH 160/288] CheckGMIPs converted to StringFormat --- common/database.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 2c007bb4f..05a7eb622 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -213,11 +213,9 @@ bool Database::AddBannedIP(char* bannedIP, const char* notes) } bool Database::CheckGMIPs(const char* ip_address, uint32 account_id) { - char *query = nullptr; + std::string query = StringFormat("SELECT * FROM `gm_ips` WHERE `ip_address` = '%s' AND `account_id` = %i", ip_address, account_id); - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT * FROM `gm_ips` WHERE `ip_address` = '%s' AND `account_id` = %i", ip_address, account_id)); - - safe_delete_array(query); + auto results = QueryDatabase(query); if (!results.Success()) return false; From 2424b1d3f1492f4dc7405f189a26077e28d2f96a Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 19:18:18 -0700 Subject: [PATCH 161/288] AddGMIP converted to StringFormat --- common/database.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 05a7eb622..e1e4558dd 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -227,11 +227,9 @@ bool Database::AddBannedIP(char* bannedIP, const char* notes) } bool Database::AddGMIP(char* ip_address, char* name) { - char *query = nullptr; + std::string query = StringFormat("INSERT into `gm_ips` SET `ip_address` = '%s', `name` = '%s'", ip_address, name); - auto results = QueryDatabase(query, MakeAnyLenString(&query, "INSERT into `gm_ips` SET `ip_address` = '%s', `name` = '%s'", ip_address, name)); - - safe_delete_array(query); + auto results = QueryDatabase(query); return results.Success(); } From d9431839941bc9d8fab89e4abb663bfa4b6cac5c Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 19:20:34 -0700 Subject: [PATCH 162/288] LoginIP converted to StringFormat --- common/database.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index e1e4558dd..8ee091f33 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -236,14 +236,12 @@ bool Database::AddGMIP(char* ip_address, char* name) { void Database::LoginIP(uint32 AccountID, const char* LoginIP) { - char *query = nullptr; + std::string query = StringFormat("INSERT INTO account_ip SET accid=%i, ip='%s' ON DUPLICATE KEY UPDATE count=count+1, lastused=now()", AccountID, LoginIP); - auto results = QueryDatabase(query, MakeAnyLenString(&query, "INSERT INTO account_ip SET accid=%i, ip='%s' ON DUPLICATE KEY UPDATE count=count+1, lastused=now()", AccountID, LoginIP)); + auto results = QueryDatabase(query); if (!results.Success()) std::cerr << "Error in Log IP query '" << query << "' " << results.ErrorMessage() << std::endl; - - safe_delete_array(query); } int16 Database::CheckStatus(uint32 account_id) From ddcaf855fe5e8de19e148bcfd999155da5151c8d Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 19:22:27 -0700 Subject: [PATCH 163/288] CheckStatus converted to StringFormat --- common/database.cpp | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 8ee091f33..86c6273d3 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -246,42 +246,37 @@ void Database::LoginIP(uint32 AccountID, const char* LoginIP) int16 Database::CheckStatus(uint32 account_id) { - char *query = nullptr; + std::string query = StringFormat("SELECT `status`, UNIX_TIMESTAMP(`suspendeduntil`) as `suspendeduntil`, UNIX_TIMESTAMP() as `current`" + " FROM `account` WHERE `id` = %i", account_id); - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT `status`, UNIX_TIMESTAMP(`suspendeduntil`) as `suspendeduntil`, UNIX_TIMESTAMP() as `current`" - " FROM `account` WHERE `id` = %i", account_id)); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in CheckStatus query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return 0; } - safe_delete_array(query); + if (results.RowCount() != 1) + return 0; + + auto row = results.begin(); - if (results.RowCount() == 1) - { - auto row = results.begin(); + int16 status = atoi(row[0]); - int16 status = atoi(row[0]); + int32 suspendeduntil = 0; - int32 suspendeduntil = 0; - - // MariaDB initalizes with NULL if unix_timestamp() is out of range - if (row[1] != nullptr) { - suspendeduntil = atoi(row[1]); - } - - int32 current = atoi(row[2]); - - if(suspendeduntil > current) - return -1; - - return status; + // MariaDB initalizes with NULL if unix_timestamp() is out of range + if (row[1] != nullptr) { + suspendeduntil = atoi(row[1]); } - return 0; + int32 current = atoi(row[2]); + + if(suspendeduntil > current) + return -1; + + return status; } uint32 Database::CreateAccount(const char* name, const char* password, int16 status, uint32 lsaccount_id) { From 41f453d5a4ccfa8e3a2c0b990d34303e96d079a4 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 19:24:47 -0700 Subject: [PATCH 164/288] CreateAccount converted to StringFormat --- common/database.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 86c6273d3..16d19f933 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -280,30 +280,26 @@ int16 Database::CheckStatus(uint32 account_id) } uint32 Database::CreateAccount(const char* name, const char* password, int16 status, uint32 lsaccount_id) { - char *query = nullptr; - - uint32 queryLen; + std::string query; if (password) - queryLen = MakeAnyLenString(&query, "INSERT INTO account SET name='%s', password='%s', status=%i, lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",name,password,status, lsaccount_id); + query = StringFormat("INSERT INTO account SET name='%s', password='%s', status=%i, lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",name,password,status, lsaccount_id); else - queryLen = MakeAnyLenString(&query, "INSERT INTO account SET name='%s', status=%i, lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",name, status, lsaccount_id); + query = StringFormat("INSERT INTO account SET name='%s', status=%i, lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",name, status, lsaccount_id); std::cerr << "Account Attempting to be created:" << name << " " << (int16) status << std::endl; - auto results = QueryDatabase(query, queryLen); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in CreateAccount query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return 0; } if (results.LastInsertedID() == 0) { std::cerr << "Error in CreateAccount query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return 0; } From 95c072f692837d78170f5a2ab953b6d623716d8c Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 19:28:02 -0700 Subject: [PATCH 165/288] DeleteAccount converted to StringFormat --- common/database.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 16d19f933..88bcab6e2 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -307,11 +307,11 @@ uint32 Database::CreateAccount(const char* name, const char* password, int16 sta } bool Database::DeleteAccount(const char* name) { - char *query = nullptr; + std::string query = StringFormat("DELETE FROM account WHERE name='%s';",name); std::cerr << "Account Attempting to be deleted:" << name << std::endl; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM account WHERE name='%s';",name)); + auto results = QueryDatabase(query); if (!results.Success()) { From d287d9731ed3c10bae6aa35bb7182276f3a970c8 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 19:29:22 -0700 Subject: [PATCH 166/288] changed cerr message to cout on DeleteAccount --- common/database.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 88bcab6e2..220bb5751 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -309,19 +309,16 @@ uint32 Database::CreateAccount(const char* name, const char* password, int16 sta bool Database::DeleteAccount(const char* name) { std::string query = StringFormat("DELETE FROM account WHERE name='%s';",name); - std::cerr << "Account Attempting to be deleted:" << name << std::endl; + std::cout << "Account Attempting to be deleted:" << name << std::endl; auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in DeleteAccount query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return false; } - safe_delete_array(query); - return results.RowsAffected() == 1; } From 74b73e6f39e51170f47f22a709a51f182c339311 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 19:30:52 -0700 Subject: [PATCH 167/288] SetLocalPassword converted to StringFormat --- common/database.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 220bb5751..5ff869802 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -323,17 +323,15 @@ bool Database::DeleteAccount(const char* name) { } bool Database::SetLocalPassword(uint32 accid, const char* password) { - char *query = nullptr; + std::string query = StringFormat("UPDATE account SET password=MD5('%s') where id=%i;", password, accid); - auto results = QueryDatabase(query, MakeAnyLenString(&query, "UPDATE account SET password=MD5('%s') where id=%i;", password, accid)); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in SetLocalPassword query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return false; } - safe_delete_array(query); return true; } From 4a10bdb91a47f36bd4aa2045703912a0724a02be Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 19:31:53 -0700 Subject: [PATCH 168/288] SetAccountStatus converted to StringFormat --- common/database.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 5ff869802..a4e64abb1 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -336,13 +336,11 @@ bool Database::SetLocalPassword(uint32 accid, const char* password) { } bool Database::SetAccountStatus(const char* name, int16 status) { - char *query = nullptr; + std::string query = StringFormat("UPDATE account SET status=%i WHERE name='%s';", status, name); std::cout << "Account being GM Flagged:" << name << ", Level: " << (int16) status << std::endl; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "UPDATE account SET status=%i WHERE name='%s';", status, name)); - - safe_delete_array(query); + auto results = QueryDatabase(query); if (!results.Success()) return false; From bf5ce11ff1e320c0f777a4b895061456f172b506 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 19:33:38 -0700 Subject: [PATCH 169/288] ReserveName converted to StringFormat --- common/database.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index a4e64abb1..d7ee2f193 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -356,18 +356,16 @@ bool Database::SetAccountStatus(const char* name, int16 status) { bool Database::ReserveName(uint32 account_id, char* name) { - char *query = nullptr; + std::string query = StringFormat("INSERT into character_ SET account_id=%i, name='%s', profile=NULL", account_id, name); - auto results = QueryDatabase(query, MakeAnyLenString(&query, "INSERT into character_ SET account_id=%i, name='%s', profile=NULL", account_id, name)); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in ReserveName query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return false; } - safe_delete_array(query); return true; } From 80a8a1fde31b0ed3e6d90c84fd0129cc83e4d6f5 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 19:47:01 -0700 Subject: [PATCH 170/288] DeleteCharacter converted to StringFormat --- common/database.cpp | 88 ++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 45 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index d7ee2f193..4f813889f 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -375,7 +375,7 @@ returns false on failure, true otherwise */ bool Database::DeleteCharacter(char *name) { - char *query=nullptr; + std::string query=StringFormat("SELECT id from character_ WHERE name='%s'", name); int charid; if(!name || !strlen(name)) @@ -390,9 +390,7 @@ bool Database::DeleteCharacter(char *name) std::cout << "DeleteCharacter: Attempting to delete '" << name << "'" << std::endl; #endif - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT id from character_ WHERE name='%s'", name)); - - safe_delete_array(query); + auto results = QueryDatabase(query); if(results.RowCount() != 1) { @@ -409,138 +407,138 @@ bool Database::DeleteCharacter(char *name) std::cout << " quest_globals"; #endif - QueryDatabase(query, MakeAnyLenString(&query, "DELETE from quest_globals WHERE charid='%d'", charid)); - safe_delete_array(query); + query = StringFormat("DELETE from quest_globals WHERE charid='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 std::cout << " character_tasks"; #endif - QueryDatabase(query, MakeAnyLenString(&query, "DELETE from character_tasks WHERE charid='%d'", charid)); - safe_delete_array(query); + query = StringFormat("DELETE from character_tasks WHERE charid='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 std::cout << " character_activities"; #endif - QueryDatabase(query, MakeAnyLenString(&query, "DELETE from character_activities WHERE charid='%d'", charid)); - safe_delete_array(query); + query = StringFormat("DELETE from character_activities WHERE charid='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 std::cout << " character_enabledtasks"; #endif - QueryDatabase(query, MakeAnyLenString(&query, "DELETE from character_enabledtasks WHERE charid='%d'", charid)); - safe_delete_array(query); + query = StringFormat("DELETE from character_enabledtasks WHERE charid='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 std::cout << " completed_tasks"; #endif - QueryDatabase(query, MakeAnyLenString(&query, "DELETE from completed_tasks WHERE charid='%d'", charid)); - safe_delete_array(query); + query = StringFormat("DELETE from completed_tasks WHERE charid='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 std::cout << " friends"; #endif - QueryDatabase(query, MakeAnyLenString(&query, "DELETE from friends WHERE charid='%d'", charid)); - safe_delete_array(query); + query = StringFormat("DELETE from friends WHERE charid='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 std::cout << " mail"; #endif - QueryDatabase(query, MakeAnyLenString(&query, "DELETE from mail WHERE charid='%d'", charid)); - safe_delete_array(query); + query = StringFormat( "DELETE from mail WHERE charid='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 std::cout << " ptimers"; #endif - QueryDatabase(query, MakeAnyLenString(&query, "DELETE from timers WHERE char_id='%d'", charid)); - safe_delete_array(query); + query = StringFormat("DELETE from timers WHERE char_id='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 std::cout << " inventory"; #endif - QueryDatabase(query, MakeAnyLenString(&query, "DELETE from inventory WHERE charid='%d'", charid)); - safe_delete_array(query); + query = StringFormat("DELETE from inventory WHERE charid='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 std::cout << " guild_members"; #endif #ifdef BOTS - QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM guild_members WHERE char_id='%d' AND GetMobTypeById(%i) = 'C'", charid)); + query = StringFormat("DELETE FROM guild_members WHERE char_id='%d' AND GetMobTypeById(%i) = 'C'", charid); #else - QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM guild_members WHERE char_id='%d'", charid)); + query = StringFormat("DELETE FROM guild_members WHERE char_id='%d'", charid); #endif - safe_delete_array(query); + QueryDatabase(query); #if DEBUG >= 5 std::cout << " recipes"; #endif - QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM char_recipe_list WHERE char_id='%d'", charid)); - safe_delete_array(query); + query = StringFormat("DELETE FROM char_recipe_list WHERE char_id='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 std::cout << " adventure_stats"; #endif - QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM adventure_stats WHERE player_id='%d'", charid)); - safe_delete_array(query); + query = StringFormat("DELETE FROM adventure_stats WHERE player_id='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 std::cout << " zone_flags"; #endif - QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM zone_flags WHERE charID='%d'", charid)); - safe_delete_array(query); + query = StringFormat("DELETE FROM zone_flags WHERE charID='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 std::cout << " titles"; #endif - QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM titles WHERE char_id='%d'", charid)); - safe_delete_array(query); + query = StringFormat("DELETE FROM titles WHERE char_id='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 std::cout << " titlesets"; #endif - QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM player_titlesets WHERE char_id='%d'", charid)); - safe_delete_array(query); + query = StringFormat("DELETE FROM player_titlesets WHERE char_id='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 std::cout << " keyring"; #endif - QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM keyring WHERE char_id='%d'", charid)); - safe_delete_array(query); + query = StringFormat("DELETE FROM keyring WHERE char_id='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 std::cout << " factions"; #endif - QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM faction_values WHERE char_id='%d'", charid)); - safe_delete_array(query); + query = StringFormat("DELETE FROM faction_values WHERE char_id='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 std::cout << " instances"; #endif - QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM instance_list_player WHERE charid='%d'", charid)); - safe_delete_array(query); + query = StringFormat("DELETE FROM instance_list_player WHERE charid='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 std::cout << " _character"; #endif - results = QueryDatabase(query, MakeAnyLenString(&query, "DELETE from character_ WHERE id='%d'", charid)); - safe_delete_array(query); + query = StringFormat("DELETE from character_ WHERE id='%d'", charid); + results = QueryDatabase(query); if(results.RowsAffected() != 1) // here we have to have a match or it's an error { @@ -552,8 +550,8 @@ bool Database::DeleteCharacter(char *name) std::cout << " alternate currency"; #endif - QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM character_alt_currency WHERE char_id='%d'", charid)); - safe_delete_array(query); + query = StringFormat("DELETE FROM character_alt_currency WHERE char_id='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 std::cout << std::endl; From fa3d8c97201f25b2bb3c6501478cc28c6324e3d5 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 19:50:50 -0700 Subject: [PATCH 171/288] StoreCharacter partialy converted to StringFormat --- common/database.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 4f813889f..8c6396bca 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -566,7 +566,6 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven { char query[256+sizeof(PlayerProfile_Struct)*2+sizeof(ExtendedProfile_Struct)*2+5]; char* end = query; - char* invquery = nullptr; uint32 charid = 0; char zone[50]; float x, y, z; @@ -612,24 +611,22 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven } // now the inventory + std::string invquery; for (int16 i=0; i<=2270;) { const ItemInst* newinv = inv->GetItem(i); if (!newinv) { - auto results = QueryDatabase(invquery, MakeAnyLenString(&invquery, - "INSERT INTO inventory SET " - "charid=%0u, slotid=%0d, itemid=%0u, charges=%0d, color=%0u", - charid, i, newinv->GetItem()->ID, - newinv->GetCharges(), newinv->GetColor())); + invquery = StringFormat("INSERT INTO inventory SET charid=%0u, slotid=%0d, itemid=%0u, charges=%0d, color=%0u", + charid, i, newinv->GetItem()->ID,newinv->GetCharges(), newinv->GetColor()); + auto results = QueryDatabase(invquery); if (!results.RowsAffected()) - LogFile->write(EQEMuLog::Error, "StoreCharacter inventory failed. Query '%s' %s", invquery, results.ErrorMessage().c_str()); + LogFile->write(EQEMuLog::Error, "StoreCharacter inventory failed. Query '%s' %s", invquery.c_str(), results.ErrorMessage().c_str()); #if EQDEBUG >= 9 else - LogFile->write(EQEMuLog::Debug, "StoreCharacter inventory succeeded. Query '%s'", invquery); + LogFile->write(EQEMuLog::Debug, "StoreCharacter inventory succeeded. Query '%s'", invquery.c_str()); #endif - safe_delete_array(invquery); } if(i==30){ //end of standard inventory/cursor, jump to internals of bags/cursor From 85895d01eba715872a2c25f1341381631e632b5f Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 19:53:17 -0700 Subject: [PATCH 172/288] GetAccountIDByChar converted to StringFormat --- common/database.cpp | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 8c6396bca..1a30808d8 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -660,32 +660,27 @@ the name "name" or zero if no character with that name was found Zero will also be returned if there is a database error. */ uint32 Database::GetAccountIDByChar(const char* charname, uint32* oCharID) { - char *query = nullptr; + std::string query = StringFormat("SELECT account_id, id FROM character_ WHERE name='%s'", charname); - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT account_id, id FROM character_ WHERE name='%s'", charname)); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in GetAccountIDByChar query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return 0; } - safe_delete_array(query); + if (results.RowCount() != 1) + return 0; - if (results.RowCount() == 1) - { - auto row = results.begin(); + auto row = results.begin(); - uint32 accountId = atoi(row[0]); + uint32 accountId = atoi(row[0]); - if (oCharID) - *oCharID = atoi(row[1]); + if (oCharID) + *oCharID = atoi(row[1]); - return accountId; - } - - return 0; + return accountId; } // Retrieve account_id for a given char_id From a64ef36d065ff89c9edc431586297c8beffbed2d Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 19:55:41 -0700 Subject: [PATCH 173/288] GetAccountIDByChar (id) converted to StringFormat --- common/database.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 1a30808d8..b7c5e7f2f 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -685,19 +685,16 @@ uint32 Database::GetAccountIDByChar(const char* charname, uint32* oCharID) { // Retrieve account_id for a given char_id uint32 Database::GetAccountIDByChar(uint32 char_id) { - char* query = nullptr; + std::string query = StringFormat("SELECT account_id FROM character_ WHERE id=%i", char_id); - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT account_id FROM character_ WHERE id=%i", char_id)); + auto results = QueryDatabase(query); if (!results.Success()) { - LogFile->write(EQEMuLog::Error, "Error in GetAccountIDByChar query '%s': %s", query, results.ErrorMessage().c_str()); - safe_delete_array(query); + LogFile->write(EQEMuLog::Error, "Error in GetAccountIDByChar query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); return 0; } - safe_delete_array(query); - if (results.RowCount() != 1) return 0; From 2f8cc6e57b8b2d6efb431e88bb6dc83e98e53548 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 19:57:37 -0700 Subject: [PATCH 174/288] GetAccountIDByName converted to StringFormat --- common/database.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index b7c5e7f2f..343c06831 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -704,12 +704,11 @@ uint32 Database::GetAccountIDByChar(uint32 char_id) { } uint32 Database::GetAccountIDByName(const char* accname, int16* status, uint32* lsid) { - char *query = nullptr; - if (!isAlphaNumeric(accname)) return 0; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT id, status, lsaccount_id FROM account WHERE name='%s'", accname)); + std::string query = StringFormat("SELECT id, status, lsaccount_id FROM account WHERE name='%s'", accname); + auto results = QueryDatabase(query); if (!results.Success()) { From 2ffc77be3db7e6ceef7e3da08395b2a7a0a2ae32 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 19:59:02 -0700 Subject: [PATCH 175/288] GetAccountName converted to StringFormat --- common/database.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 343c06831..1c9312387 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -713,12 +713,9 @@ uint32 Database::GetAccountIDByName(const char* accname, int16* status, uint32* if (!results.Success()) { std::cerr << "Error in GetAccountIDByAcc query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return 0; } - safe_delete_array(query); - if (results.RowCount() != 1) return 0; @@ -741,19 +738,16 @@ uint32 Database::GetAccountIDByName(const char* accname, int16* status, uint32* } void Database::GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID) { - char *query = nullptr; + std::string query = StringFormat("SELECT name, lsaccount_id FROM account WHERE id='%i'", accountid); - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT name, lsaccount_id FROM account WHERE id='%i'", accountid)); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in GetAccountName query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return; } - safe_delete_array(query); - if (results.RowCount() != 1) return; From 879ab418fdb20cecde3c597202aaa51522fceaf5 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 20:04:15 -0700 Subject: [PATCH 176/288] SetVariable converted to StringFormat --- common/database.cpp | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 1c9312387..15ef08f3a 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -761,19 +761,16 @@ void Database::GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID } void Database::GetCharName(uint32 char_id, char* name) { - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT name FROM character_ WHERE id='%i'", char_id)); + + std::string query = StringFormat("SELECT name FROM character_ WHERE id='%i'", char_id); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in GetCharName query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return; } - safe_delete_array(query); - auto row = results.begin(); strcpy(name, row[0]); } @@ -884,8 +881,7 @@ bool Database::GetVariable(const char* varname, char* varvalue, uint16 varvalue_ } bool Database::SetVariable(const char* varname_in, const char* varvalue_in) { - char *query = nullptr; - + char *varname,*varvalue; varname=(char *)malloc(strlen(varname_in)*2+1); @@ -893,19 +889,17 @@ bool Database::SetVariable(const char* varname_in, const char* varvalue_in) { DoEscapeString(varname, varname_in, strlen(varname_in)); DoEscapeString(varvalue, varvalue_in, strlen(varvalue_in)); - auto results = QueryDatabase(query, MakeAnyLenString(&query, "Update variables set value='%s' WHERE varname like '%s'", varvalue, varname)); + std::string query = StringFormat("Update variables set value='%s' WHERE varname like '%s'", varvalue, varname); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in SetVariable query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); free(varname); free(varvalue); return false; } - safe_delete_array(query); - if (results.RowsAffected() == 1) { LoadVariables(); // refresh cache @@ -914,17 +908,16 @@ bool Database::SetVariable(const char* varname_in, const char* varvalue_in) { return true; } - results = QueryDatabase(query, MakeAnyLenString(&query, "Insert Into variables (varname, value) values ('%s', '%s')", varname, varvalue)); - safe_delete_array(query); + query = StringFormat("Insert Into variables (varname, value) values ('%s', '%s')", varname, varvalue); + results = QueryDatabase(query); free(varname); free(varvalue); - if (results.RowsAffected() == 1) { - LoadVariables(); // refresh cache - return true; - } - - return false; + if (results.RowsAffected() != 1) + return false; + + LoadVariables(); // refresh cache + return true; } uint32 Database::GetMiniLoginAccount(char* ip){ From 869c0418460cee8e9f0b4561a06157b3b952fd4b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 20:05:40 -0700 Subject: [PATCH 177/288] GetMiniLoginAccount converted to StringFormat --- common/database.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 15ef08f3a..21c659311 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -921,17 +921,15 @@ bool Database::SetVariable(const char* varname_in, const char* varvalue_in) { } uint32 Database::GetMiniLoginAccount(char* ip){ - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT id FROM account WHERE minilogin_ip='%s'", ip)); + std::string query = StringFormat("SELECT id FROM account WHERE minilogin_ip='%s'", ip); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in GetMiniLoginAccount query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return 0; } - safe_delete_array(query); auto row = results.begin(); @@ -1044,16 +1042,14 @@ uint32 Database::GetZoneGraveyardID(uint32 zone_id, uint32 version) { } bool Database::GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid, float* graveyard_x, float* graveyard_y, float* graveyard_z, float* graveyard_heading) { - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT zone_id, x, y, z, heading FROM graveyard WHERE id=%i", graveyard_id)); + + std::string query = StringFormat("SELECT zone_id, x, y, z, heading FROM graveyard WHERE id=%i", graveyard_id); + auto results = QueryDatabase(query); if (!results.Success()){ std::cerr << "Error in GetZoneGraveyard query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return false; } - safe_delete_array(query); if (results.RowCount() != 1) return false; From 341121da32c9ff24133913c01491a4998012f75b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 20:07:02 -0700 Subject: [PATCH 178/288] GetSafePoints converted to StringFormat --- common/database.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 21c659311..a4431790a 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -938,12 +938,10 @@ uint32 Database::GetMiniLoginAccount(char* ip){ // Get zone starting points from DB bool Database::GetSafePoints(const char* short_name, uint32 version, float* safe_x, float* safe_y, float* safe_z, int16* minstatus, uint8* minlevel, char *flag_needed) { - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, - "SELECT safe_x, safe_y, safe_z, min_status, min_level, " - " flag_needed FROM zone " - " WHERE short_name='%s' AND (version=%i OR version=0) ORDER BY version DESC", short_name, version)); + + std::string query = StringFormat("SELECT safe_x, safe_y, safe_z, min_status, min_level, flag_needed FROM zone " + " WHERE short_name='%s' AND (version=%i OR version=0) ORDER BY version DESC", short_name, version); + auto results = QueryDatabase(query); if (!results.Success()) { @@ -952,13 +950,9 @@ bool Database::GetSafePoints(const char* short_name, uint32 version, float* safe std::cerr << "ALTER TABLE `zone` CHANGE `minium_level` `min_level` TINYINT(3) UNSIGNED DEFAULT \"0\" NOT NULL;\n"; std::cerr << "ALTER TABLE `zone` CHANGE `minium_status` `min_status` TINYINT(3) UNSIGNED DEFAULT \"0\" NOT NULL;\n"; std::cerr << "ALTER TABLE `zone` ADD flag_needed VARCHAR(128) NOT NULL DEFAULT '';\n"; - - safe_delete_array(query); return false; } - safe_delete_array(query); - if (results.RowCount() == 0) return false; From 56de9072c046662735aedebd863846aa250d74f7 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 20:08:33 -0700 Subject: [PATCH 179/288] GetZoneLongName converted to StringFormat --- common/database.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index a4431790a..36e2ead38 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -975,16 +975,14 @@ bool Database::GetSafePoints(const char* short_name, uint32 version, float* safe } bool Database::GetZoneLongName(const char* short_name, char** long_name, char* file_name, float* safe_x, float* safe_y, float* safe_z, uint32* graveyard_id, uint32* maxclients) { - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT long_name, file_name, safe_x, safe_y, safe_z, graveyard_id, maxclients FROM zone WHERE short_name='%s' AND version=0", short_name)); + + std::string query = StringFormat("SELECT long_name, file_name, safe_x, safe_y, safe_z, graveyard_id, maxclients FROM zone WHERE short_name='%s' AND version=0", short_name); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in GetZoneLongName query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return false; } - safe_delete_array(query); if (results.RowCount() == 0) return false; From c2e5875f02c40bd2070c5216905678686321c72d Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 20:09:15 -0700 Subject: [PATCH 180/288] GetzoneGraveyardID converted to StringFormat --- common/database.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 36e2ead38..0953ee753 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1014,17 +1014,15 @@ bool Database::GetZoneLongName(const char* short_name, char** long_name, char* f } uint32 Database::GetZoneGraveyardID(uint32 zone_id, uint32 version) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT graveyard_id FROM zone WHERE zoneidnumber='%u' AND (version=%i OR version=0) ORDER BY version DESC", zone_id, version)); + std::string query = StringFormat("SELECT graveyard_id FROM zone WHERE zoneidnumber='%u' AND (version=%i OR version=0) ORDER BY version DESC", zone_id, version); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in GetZoneGraveyardID query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return 0; } - safe_delete_array(query); if (results.RowCount() == 0) return 0; From 0850b1edad08e5864830d326bb9a0bf865bd3260 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 20:18:09 -0700 Subject: [PATCH 181/288] LoadZoneNames converted to use string --- common/database.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 0953ee753..2c10a2947 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1061,17 +1061,15 @@ bool Database::GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zon } bool Database::LoadZoneNames() { - char *query = nullptr; + std::string query("SELECT zoneidnumber, short_name FROM zone"); - auto results = QueryDatabase(query,MakeAnyLenString(&query, "SELECT zoneidnumber, short_name FROM zone")); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in LoadZoneNames query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return false; } - safe_delete_array(query); for (auto row= results.begin();row != results.end();++row) { From 4804cca0ab55aad470be455f2b2c1684491d7eb1 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 20:19:33 -0700 Subject: [PATCH 182/288] GetPEQZone converted to StringFormat --- common/database.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 2c10a2947..ad16b6d0a 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1106,17 +1106,15 @@ const char* Database::GetZoneName(uint32 zoneID, bool ErrorUnknown) { } uint8 Database::GetPEQZone(uint32 zoneID, uint32 version){ - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT peqzone from zone where zoneidnumber='%i' AND (version=%i OR version=0) ORDER BY version DESC", zoneID, version)); + + std::string query = StringFormat("SELECT peqzone from zone where zoneidnumber='%i' AND (version=%i OR version=0) ORDER BY version DESC", zoneID, version); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in GetPEQZone query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return 0; } - safe_delete_array(query); if (results.RowCount() == 0) return 0; From d7a98e76551da7cf3e156c47aa7756532b1818fb Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 20:21:15 -0700 Subject: [PATCH 183/288] CheckNameFilter converted to string --- common/database.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index ad16b6d0a..e006ae986 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1127,7 +1127,6 @@ uint8 Database::GetPEQZone(uint32 zoneID, uint32 version){ bool Database::CheckNameFilter(const char* name, bool surname) { std::string str_name = name; - char *query = nullptr; if(surname) { @@ -1178,16 +1177,16 @@ bool Database::CheckNameFilter(const char* name, bool surname) } } - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT name FROM name_filter")); + + std::string query("SELECT name FROM name_filter"); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in CheckNameFilter query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); // false through to true? shouldn't it be falls through to false? return true; } - safe_delete_array(query); for (auto row = results.begin();row != results.end();++row) { From 97588fbcf48c7b6e560fa9cc8fd337356a88b824 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 20:22:40 -0700 Subject: [PATCH 184/288] AddToNameFilter converted to StringFormat --- common/database.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index e006ae986..6bb591700 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1203,17 +1203,15 @@ bool Database::CheckNameFilter(const char* name, bool surname) } bool Database::AddToNameFilter(const char* name) { - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "INSERT INTO name_filter (name) values ('%s')", name)); + + std::string query = StringFormat("INSERT INTO name_filter (name) values ('%s')", name); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in AddToNameFilter query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return false; } - safe_delete_array(query); if (results.RowsAffected() == 0) return false; From 66070e9bf65e9718d7fa904603786963c23b8e91 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 20:24:24 -0700 Subject: [PATCH 185/288] GetAccountIDFromLSID converted to StringFormat --- common/database.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 6bb591700..6749b15f5 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1220,17 +1220,15 @@ bool Database::AddToNameFilter(const char* name) { } uint32 Database::GetAccountIDFromLSID(uint32 iLSID, char* oAccountName, int16* oStatus) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT id, name, status FROM account WHERE lsaccount_id=%i", iLSID)); + std::string query = StringFormat("SELECT id, name, status FROM account WHERE lsaccount_id=%i", iLSID); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in GetAccountIDFromLSID query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return 0; } - safe_delete_array(query); if (results.RowCount() != 1) return 0; From 396eced36ef95ef3d1a164558d276bef6f13b6de Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 20:25:55 -0700 Subject: [PATCH 186/288] GetAccountFromID converted to StringFormat --- common/database.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 6749b15f5..38138923f 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1246,17 +1246,15 @@ uint32 Database::GetAccountIDFromLSID(uint32 iLSID, char* oAccountName, int16* o } void Database::GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus) { - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT name, status FROM account WHERE id=%i", id)); + + std::string query = StringFormat("SELECT name, status FROM account WHERE id=%i", id); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in GetAccountFromID query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return; } - safe_delete_array(query); if (results.RowCount() != 1) return; From 57b11629ce6bf4323379b495d760c926e4528c5e Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 20:26:52 -0700 Subject: [PATCH 187/288] ClearMerchantTemp converted to string --- common/database.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 38138923f..9380a634b 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1268,14 +1268,12 @@ void Database::GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus) { } void Database::ClearMerchantTemp(){ - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from merchantlist_temp")); + std::string query("delete from merchantlist_temp"); + auto results = QueryDatabase(query); if (!results.Success()) std::cerr << "Error in ClearMerchantTemp query '" << query << "' " << results.ErrorMessage() << std::endl; - - safe_delete_array(query); } bool Database::UpdateName(const char* oldname, const char* newname) { From 8b3afbdf10e4acd9758410d6e08a556977da7a4b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 20:28:04 -0700 Subject: [PATCH 188/288] UpdateName converted to StringFormat --- common/database.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 9380a634b..cb7651321 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1277,12 +1277,11 @@ void Database::ClearMerchantTemp(){ } bool Database::UpdateName(const char* oldname, const char* newname) { - char *query = nullptr; - + std::cout << "Renaming " << oldname << " to " << newname << "..." << std::endl; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "UPDATE character_ SET name='%s' WHERE name='%s';", newname, oldname)); - safe_delete_array(query); + std::string query = StringFormat("UPDATE character_ SET name='%s' WHERE name='%s';", newname, oldname); + auto results = QueryDatabase(query); if (!results.Success()) return false; From ec47f8644c218d59e1f6c1aa03b35367ab95dc6f Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 20:34:44 -0700 Subject: [PATCH 189/288] CheckUsedName converted to StringFormat --- common/database.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index cb7651321..5637daa59 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1295,17 +1295,14 @@ bool Database::UpdateName(const char* oldname, const char* newname) { // If the name is used or an error occurs, it returns false, otherwise it returns true bool Database::CheckUsedName(const char* name) { - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT id FROM character_ where name='%s'", name)); + std::string query = StringFormat("SELECT id FROM character_ where name='%s'", name); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in CheckUsedName query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return false; } - safe_delete_array(query); if (results.RowCount() > 0) return false; From 6430a62c865f23c35b82f2a13953afc4e22172e1 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 20:35:41 -0700 Subject: [PATCH 190/288] GetServerType converted to StringFormat --- common/database.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 5637daa59..eeabbde36 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1312,17 +1312,14 @@ bool Database::CheckUsedName(const char* name) uint8 Database::GetServerType() { - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT value FROM variables WHERE varname='ServerType'")); + std::string query("SELECT value FROM variables WHERE varname='ServerType'"); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in GetServerType query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return 0; } - safe_delete_array(query); if (results.RowCount() != 1) return 0; From 2e8ff36ef7b2215d0fe456d97eb66988b0111ab5 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 20:40:50 -0700 Subject: [PATCH 191/288] MoveCharacterToZone converted to StringFormat --- common/database.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index eeabbde36..6b15f5356 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1329,20 +1329,17 @@ uint8 Database::GetServerType() } bool Database::MoveCharacterToZone(const char* charname, const char* zonename,uint32 zoneid) { - char *query = nullptr; - if(zonename == nullptr || strlen(zonename) == 0) return false; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "UPDATE character_ SET zonename = '%s',zoneid=%i,x=-1, y=-1, z=-1 WHERE name='%s'", zonename,zoneid, charname)); + std::string query = StringFormat("UPDATE character_ SET zonename = '%s',zoneid=%i,x=-1, y=-1, z=-1 WHERE name='%s'", zonename,zoneid, charname); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in MoveCharacterToZone(name) query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return false; } - safe_delete_array(query); if (results.RowsAffected() == 0) return false; From 84499e43dd0a1cb08c84ae87f3efae5fae8284d8 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 20:42:10 -0700 Subject: [PATCH 192/288] MoveCharacterToZone converted to StringFormat --- common/database.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 6b15f5356..49d1775d2 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1352,17 +1352,15 @@ bool Database::MoveCharacterToZone(const char* charname, const char* zonename) { } bool Database::MoveCharacterToZone(uint32 iCharID, const char* iZonename) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "UPDATE character_ SET zonename = '%s', zoneid=%i, x=-1, y=-1, z=-1 WHERE id=%i", iZonename, GetZoneID(iZonename), iCharID)); + std::string query = StringFormat("UPDATE character_ SET zonename = '%s', zoneid=%i, x=-1, y=-1, z=-1 WHERE id=%i", iZonename, GetZoneID(iZonename), iCharID); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in MoveCharacterToZone(id) query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return false; } - safe_delete_array(query); return results.RowsAffected() != 0; } From 3a2ceab58a4f38cc88b9c0596f7e222f0474faeb Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Tue, 8 Jul 2014 20:46:41 -0700 Subject: [PATCH 193/288] CopyCharacter converted to StringFormat --- common/database.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 49d1775d2..be87fedf9 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1366,19 +1366,18 @@ bool Database::MoveCharacterToZone(uint32 iCharID, const char* iZonename) { } uint8 Database::CopyCharacter(const char* oldname, const char* newname, uint32 acctid) { - char *query = nullptr; + PlayerProfile_Struct* pp; ExtendedProfile_Struct* ext; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT profile, extprofile FROM character_ WHERE name='%s'", oldname)); + std::string query = StringFormat("SELECT profile, extprofile FROM character_ WHERE name='%s'", oldname); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in CopyCharacter read query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return 0; } - safe_delete_array(query); auto row = results.begin(); @@ -1387,7 +1386,6 @@ uint8 Database::CopyCharacter(const char* oldname, const char* newname, uint32 a ext = (ExtendedProfile_Struct*)row[1]; - char query2[276 + sizeof(PlayerProfile_Struct)*2 + sizeof(ExtendedProfile_Struct)*2 + 1]; char* end=query2; From 1f15f7ff9a08f4648d77454280de1524002e3fa4 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 9 Jul 2014 16:35:30 -0700 Subject: [PATCH 194/288] SetHackerFlag converted to StringFormat --- common/database.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index be87fedf9..40704bdfd 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1410,17 +1410,15 @@ uint8 Database::CopyCharacter(const char* oldname, const char* newname, uint32 a } bool Database::SetHackerFlag(const char* accountname, const char* charactername, const char* hacked) { - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "INSERT INTO hackers(account,name,hacked) values('%s','%s','%s')", accountname, charactername, hacked)); + + std::string query = StringFormat("INSERT INTO hackers(account,name,hacked) values('%s','%s','%s')", accountname, charactername, hacked); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in SetHackerFlag query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return false; } - safe_delete_array(query); return results.RowsAffected() != 0; } From 09ede557b107165bfb6bc2c624a25e39e311dbc8 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 9 Jul 2014 16:37:21 -0700 Subject: [PATCH 195/288] SetMQDetectionFlag converted to StringFormat --- common/database.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 40704bdfd..171074e16 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1424,18 +1424,16 @@ bool Database::SetHackerFlag(const char* accountname, const char* charactername, } bool Database::SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone) { + //Utilize the "hacker" table, but also give zone information. - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "INSERT INTO hackers(account,name,hacked,zone) values('%s','%s','%s','%s')", accountname, charactername, hacked, zone)); + std::string query = StringFormat("INSERT INTO hackers(account,name,hacked,zone) values('%s','%s','%s','%s')", accountname, charactername, hacked, zone); + auto results = QueryDatabase(query); if (!results.Success()) { - safe_delete_array(query); std::cerr << "Error in SetMQDetectionFlag query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } - safe_delete_array(query); return results.RowsAffected() != 0; } From 397e3998ffc52d5a5b435bcf79f0b03a53c383b3 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 14:55:57 -0700 Subject: [PATCH 196/288] GetRaceSkill converted to StringFormat --- common/database.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 171074e16..0c2949ebb 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1441,12 +1441,10 @@ bool Database::SetMQDetectionFlag(const char* accountname, const char* character uint8 Database::GetRaceSkill(uint8 skillid, uint8 in_race) { uint16 race_cap = 0; - char *query = nullptr; - + //Check for a racial cap! - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT skillcap from race_skillcaps where skill = %i && race = %i", skillid, in_race)); - safe_delete_array(query); + std::string query = StringFormat("SELECT skillcap from race_skillcaps where skill = %i && race = %i", skillid, in_race); + auto results = QueryDatabase(query); if (!results.Success()) return 0; From 422f3b1ce91abd67619f63265130cdef669ed2ad Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 14:57:24 -0700 Subject: [PATCH 197/288] GetSkillCap converted to StringFormat --- common/database.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 0c2949ebb..2b7480ac9 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1460,11 +1460,11 @@ uint8 Database::GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 { uint8 skill_level = 0, skill_formula = 0; uint16 base_cap = 0, skill_cap = 0, skill_cap2 = 0, skill_cap3 = 0; - char *query = nullptr; + //Fetch the data from DB. - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT level, formula, pre50cap, post50cap, post60cap from skillcaps where skill = %i && class = %i", skillid, in_class)); - safe_delete_array(query); + std::string query = StringFormat("SELECT level, formula, pre50cap, post50cap, post60cap from skillcaps where skill = %i && class = %i", skillid, in_class); + auto results = QueryDatabase(query); if (results.Success() && results.RowsAffected() != 0) { From 6f8e7fc720b4fa352cac5e307173e32ef4b02cd6 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 14:58:27 -0700 Subject: [PATCH 198/288] GetCharacterInfo converted to StringFormat --- common/database.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 2b7480ac9..eb72aba92 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1507,17 +1507,15 @@ uint8 Database::GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 } uint32 Database::GetCharacterInfo(const char* iName, uint32* oAccID, uint32* oZoneID, uint32* oInstanceID, float* oX, float* oY, float* oZ) { - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT id, account_id, zonename, instanceid, x, y, z FROM character_ WHERE name='%s'", iName)); + + std::string query = StringFormat("SELECT id, account_id, zonename, instanceid, x, y, z FROM character_ WHERE name='%s'", iName); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in GetCharacterInfo query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return 0; } - safe_delete_array(query); if (results.RowCount() != 1) return 0; From 4ce7081ace6b1d5beb0ae306cf5983502a5db0a0 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 14:59:16 -0700 Subject: [PATCH 199/288] UpdateLiveChar converted to StringFormat --- common/database.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index eb72aba92..3292d0fd2 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1540,17 +1540,15 @@ uint32 Database::GetCharacterInfo(const char* iName, uint32* oAccID, uint32* oZo } bool Database::UpdateLiveChar(char* charname,uint32 lsaccount_id) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "UPDATE account SET charname='%s' WHERE id=%i;",charname, lsaccount_id)); + std::string query = StringFormat("UPDATE account SET charname='%s' WHERE id=%i;",charname, lsaccount_id); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in UpdateLiveChar query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return false; } - safe_delete_array(query); return true; } From d4aaa93047005974b620310d450782c3906a0cfd Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 15:00:05 -0700 Subject: [PATCH 200/288] GetLiveChar converted to StringFormat --- common/database.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 3292d0fd2..4d32b9ec3 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1554,17 +1554,15 @@ bool Database::UpdateLiveChar(char* charname,uint32 lsaccount_id) { } bool Database::GetLiveChar(uint32 account_id, char* cname) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT charname FROM account WHERE id=%i", account_id)); + std::string query = StringFormat("SELECT charname FROM account WHERE id=%i", account_id); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in GetLiveChar query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return false; } - safe_delete_array(query); if (results.RowCount() != 1) return false; From bde62709b5635b9c9b56436e4c77cdcd506d7c0b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 15:01:08 -0700 Subject: [PATCH 201/288] SetLFP converted to StringFormat --- common/database.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 4d32b9ec3..d6ded6a5e 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1574,10 +1574,9 @@ bool Database::GetLiveChar(uint32 account_id, char* cname) { } void Database::SetLFP(uint32 CharID, bool LFP) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "update character_ set lfp=%i where id=%i",LFP, CharID)); - safe_delete_array(query); + std::string query = StringFormat("update character_ set lfp=%i where id=%i",LFP, CharID); + auto results = QueryDatabase(query); if (!results.Success()) LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, results.ErrorMessage().c_str()); From fdb4e54ff6ffa1c8118f5e6c6f51d3b8f00aec61 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 15:01:56 -0700 Subject: [PATCH 202/288] SetLoginFlags converted to StringFormat --- common/database.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index d6ded6a5e..850cbe916 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1583,10 +1583,9 @@ void Database::SetLFP(uint32 CharID, bool LFP) { } void Database::SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon) { - char *query = nullptr; - - auto results = QueryDatabase(query,MakeAnyLenString(&query, "update character_ set lfp=%i, lfg=%i, firstlogon=%i where id=%i",LFP, LFG, firstlogon, CharID)); - safe_delete_array(query); + + std::string query = StringFormat("update character_ set lfp=%i, lfg=%i, firstlogon=%i where id=%i",LFP, LFG, firstlogon, CharID); + auto results = QueryDatabase(query); if (!results.Success()) LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, results.ErrorMessage().c_str()); From 474d5d1340c655726b4b81d4f459af4a63863e39 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 15:02:39 -0700 Subject: [PATCH 203/288] SetLFG converted to StringFormat --- common/database.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 850cbe916..83f75974e 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1592,10 +1592,9 @@ void Database::SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon } void Database::SetLFG(uint32 CharID, bool LFG) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "update character_ set lfg=%i where id=%i",LFG, CharID)); - safe_delete_array(query); + std::string query = StringFormat("update character_ set lfg=%i where id=%i",LFG, CharID); + auto results = QueryDatabase(query); if (!results.Success()) LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, results.ErrorMessage().c_str()); From 61732658f20ca4a1b88e25262f89ba79fc30048c Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 15:03:25 -0700 Subject: [PATCH 204/288] SetFirstLogon converted to StringFormat --- common/database.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 83f75974e..13ce2a61b 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1601,10 +1601,9 @@ void Database::SetLFG(uint32 CharID, bool LFG) { } void Database::SetFirstLogon(uint32 CharID, uint8 firstlogon) { - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "update character_ set firstlogon=%i where id=%i",firstlogon, CharID)); - safe_delete_array(query); + + std::string query = StringFormat( "update character_ set firstlogon=%i where id=%i",firstlogon, CharID); + auto results = QueryDatabase(query); if (!results.Success()) LogFile->write(EQEMuLog::Error, "Error updating firstlogon for character %i : %s", CharID, results.ErrorMessage().c_str()); From 1ec7da0f3630353894074ebab9f3744d9c0dac24 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 15:11:44 -0700 Subject: [PATCH 205/288] SetGroupID converted to StringFormat --- common/database.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 13ce2a61b..d95d52862 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1624,13 +1624,13 @@ void Database::AddReport(std::string who, std::string against, std::string lines } void Database::SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ismerc){ - char *query = nullptr; - + + std::string query; if (id == 0) { // removing from group - auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from group_id where charid=%i and name='%s' and ismerc=%i",charid, name, ismerc)); - safe_delete_array(query); + query = StringFormat("delete from group_id where charid=%i and name='%s' and ismerc=%i",charid, name, ismerc); + auto results = QueryDatabase(query); if (!results.Success()) LogFile->write(EQEMuLog::Error, "Error deleting character from group id: %s", results.ErrorMessage().c_str()); @@ -1639,8 +1639,8 @@ void Database::SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ism } // adding to group - auto results = QueryDatabase(query, MakeAnyLenString(&query, "replace into group_id set charid=%i, groupid=%i, name='%s', ismerc='%i'",charid, id, name, ismerc)); - safe_delete_array(query); + query = StringFormat("replace into group_id set charid=%i, groupid=%i, name='%s', ismerc='%i'",charid, id, name, ismerc); + auto results = QueryDatabase(query); if (!results.Success()) LogFile->write(EQEMuLog::Error, "Error adding character to group id: %s", results.ErrorMessage().c_str()); From ed21229bba09aab4616ea1f6de3916d080cd3386 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 15:15:05 -0700 Subject: [PATCH 206/288] ClearAllGroups converted to StringFormat --- common/database.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index d95d52862..8d2a44761 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1648,10 +1648,8 @@ void Database::SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ism void Database::ClearAllGroups(void) { - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from group_id")); - safe_delete_array(query); + std::string query("delete from group_id"); + auto results = QueryDatabase(query); if (!results.Success()) std::cout << "Unable to clear groups: " << results.ErrorMessage() << std::endl; From 538979716dfafcdbf69c7f96966370fa3f4ad648 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 15:16:02 -0700 Subject: [PATCH 207/288] ClearGroup converted to StringFormat --- common/database.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 8d2a44761..b59ab6c29 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1659,8 +1659,7 @@ void Database::ClearAllGroups(void) void Database::ClearGroup(uint32 gid) { ClearGroupLeader(gid); - char *query = nullptr; - + if(gid == 0) { //clear all groups @@ -1669,12 +1668,11 @@ void Database::ClearGroup(uint32 gid) { } //clear a specific group - auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from group_id where groupid = %lu", (unsigned long)gid)); - safe_delete_array(query); + std::string query = StringFormat("delete from group_id where groupid = %lu", (unsigned long)gid); + auto results = QueryDatabase(query); if (!results.Success()) std::cout << "Unable to clear groups: " << results.ErrorMessage() << std::endl; - } uint32 Database::GetGroupID(const char* name){ From 34a7b46163ce7202df9c54ae00b58f98c22798a1 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 15:17:10 -0700 Subject: [PATCH 208/288] GetGroupID converted to StringFormat --- common/database.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index b59ab6c29..9370b444e 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1676,10 +1676,9 @@ void Database::ClearGroup(uint32 gid) { } uint32 Database::GetGroupID(const char* name){ - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT groupid from group_id where name='%s'", name)); - safe_delete_array(query); + std::string query = StringFormat("SELECT groupid from group_id where name='%s'", name); + auto results = QueryDatabase(query); if (!results.Success()) { From 0862feeba8d330436537d1550128400bb982a37a Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 15:19:10 -0700 Subject: [PATCH 209/288] GetGroupLeaderForLogin converted to StringFormat --- common/database.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 9370b444e..4deaff5e2 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1698,12 +1698,11 @@ uint32 Database::GetGroupID(const char* name){ } char* Database::GetGroupLeaderForLogin(const char* name,char* leaderbuf){ - char *query = nullptr; - + PlayerProfile_Struct pp; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT profile from character_ where name='%s'", name)); - safe_delete_array(query); + std::string query = StringFormat("SELECT profile from character_ where name='%s'", name); + auto results = QueryDatabase(query); if (!results.Success()) { From 3b18c4891c3c5ce0188d739914abffeef66a18ad Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 16:17:14 -0700 Subject: [PATCH 210/288] SetGroupLeaderName converted to StringFormat --- common/database.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 4deaff5e2..4184b4d75 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1722,10 +1722,9 @@ char* Database::GetGroupLeaderForLogin(const char* name,char* leaderbuf){ } void Database::SetGroupLeaderName(uint32 gid, const char* name) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "Replace into group_leaders set gid=%lu, leadername='%s'",(unsigned long)gid,name)); - safe_delete_array(query); + std::string query = StringFormat("Replace into group_leaders set gid=%lu, leadername='%s'",(unsigned long)gid,name); + auto results = QueryDatabase(query); if (!results.Success()) std::cout << "Unable to set group leader: " << results.ErrorMessage() << std::endl; From e3d02cdf40142cb7fcc94b16ffc6f141935229f5 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 16:18:31 -0700 Subject: [PATCH 211/288] GetGroupLeadershipInfo converted to StringFormat --- common/database.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 4184b4d75..dc62a2fc8 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1731,10 +1731,9 @@ void Database::SetGroupLeaderName(uint32 gid, const char* name) { } char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank, char* assist, char* puller, char *marknpc, GroupLeadershipAA_Struct* GLAA){ - char* query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT leadername, maintank, assist, puller, marknpc, leadershipaa FROM group_leaders WHERE gid=%lu",(unsigned long)gid)); - safe_delete_array(query); + + std::string query = StringFormat("SELECT leadername, maintank, assist, puller, marknpc, leadershipaa FROM group_leaders WHERE gid=%lu",(unsigned long)gid); + auto results = QueryDatabase(query); if (!results.Success() || results.RowCount() == 0) { From b7fb8fa43445d8b43685870f069a02198c7b017e Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 16:21:46 -0700 Subject: [PATCH 212/288] ClearAllGroupLeaders converted to StringFormat --- common/database.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index dc62a2fc8..26bc170f8 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1781,9 +1781,8 @@ char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* mainta // Clearing all group leaders void Database::ClearAllGroupLeaders(void) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "DELETE from group_leaders")); - safe_delete_array(query); + std::string query("DELETE from group_leaders"); + auto results = QueryDatabase(query); if (!results.Success()) std::cout << "Unable to clear group leaders: " << results.ErrorMessage() << std::endl; From 8e8a21349fcf2de22f569bced750326d46da543b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:05:47 -0700 Subject: [PATCH 213/288] ClearGroupLeader converted to StringFormat --- common/database.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 26bc170f8..1ee5ea2a0 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1791,16 +1791,15 @@ void Database::ClearAllGroupLeaders(void) } void Database::ClearGroupLeader(uint32 gid) { - char *query = nullptr; - + if(gid == 0) { ClearAllGroupLeaders(); return; } - auto results = QueryDatabase(query, MakeAnyLenString(&query, "DELETE from group_leaders where gid = %lu", (unsigned long)gid)); - safe_delete_array(query); + std::string query = StringFormat("DELETE from group_leaders where gid = %lu", (unsigned long)gid); + auto results = QueryDatabase(query); if (!results.Success()) std::cout << "Unable to clear group leader: " << results.ErrorMessage() << std::endl; From c1b69594e55007d8d5c50fd535dfc0bb64210315 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:14:21 -0700 Subject: [PATCH 214/288] GetAgreementFlag converted to StringFormat --- common/database.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 1ee5ea2a0..1c53d13c3 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1807,10 +1807,9 @@ void Database::ClearGroupLeader(uint32 gid) { uint8 Database::GetAgreementFlag(uint32 acctid) { - char* query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT rulesflag FROM account WHERE id=%i",acctid)); - safe_delete_array(query); + std::string query = StringFormat("SELECT rulesflag FROM account WHERE id=%i",acctid); + auto results = QueryDatabase(query); if (!results.Success()) return 0; From 3cf9c71c27872eb6369b9e8cd9afebb6ec45dde0 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:16:16 -0700 Subject: [PATCH 215/288] SetAgreementFlag converted to StringFormat --- common/database.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 1c53d13c3..8eb895f34 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1824,10 +1824,8 @@ uint8 Database::GetAgreementFlag(uint32 acctid) void Database::SetAgreementFlag(uint32 acctid) { - char *query = nullptr; - - QueryDatabase(query, MakeAnyLenString(&query, "UPDATE account SET rulesflag=1 where id=%i", acctid)); - safe_delete_array(query); + std::string query = StringFormat("UPDATE account SET rulesflag=1 where id=%i", acctid); + QueryDatabase(query); } void Database::ClearRaid(uint32 rid) { From 71da40c75761295122889a25ecbe99828d60179e Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:17:06 -0700 Subject: [PATCH 216/288] ClearRaid converted to StringFormat --- common/database.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 8eb895f34..6bdb1eacf 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1829,8 +1829,7 @@ void Database::SetAgreementFlag(uint32 acctid) } void Database::ClearRaid(uint32 rid) { - char *query = nullptr; - + if(rid == 0) { //clear all raids @@ -1839,8 +1838,8 @@ void Database::ClearRaid(uint32 rid) { } //clear a specific group - auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from raid_members where raidid = %lu", (unsigned long)rid)); - safe_delete_array(query); + std::string query = StringFormat("delete from raid_members where raidid = %lu", (unsigned long)rid); + auto results = QueryDatabase(query); if (!results.Success()) std::cout << "Unable to clear raids: " << results.ErrorMessage() << std::endl; From 652b158ca4d600b53e6e4f674ab8d98c9c73b950 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:17:54 -0700 Subject: [PATCH 217/288] ClearAllRaids converted to StringFormat --- common/database.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 6bdb1eacf..71739ce03 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1847,10 +1847,9 @@ void Database::ClearRaid(uint32 rid) { void Database::ClearAllRaids(void) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from raid_members")); - safe_delete_array(query); + std::string query("delete from raid_members"); + auto results = QueryDatabase(query); if (!results.Success()) std::cout << "Unable to clear raids: " << results.ErrorMessage() << std::endl; From d21c4a58b428c47e66bfd072d9068ca224ad4ece Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:18:49 -0700 Subject: [PATCH 218/288] ClearAllRaidDetails converted to StringFormat --- common/database.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 71739ce03..2503c41b7 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1857,15 +1857,12 @@ void Database::ClearAllRaids(void) void Database::ClearAllRaidDetails(void) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from raid_details")); - safe_delete_array(query); + std::string query("delete from raid_details"); + auto results = QueryDatabase(query); if (!results.Success()) std::cout << "Unable to clear raid details: " << results.ErrorMessage() << std::endl; - - return; } void Database::ClearRaidDetails(uint32 rid) { From 12c15c6db0610629c593375a28677d25325641ea Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:19:44 -0700 Subject: [PATCH 219/288] ClearRaidDetails converted to StringFormat --- common/database.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 2503c41b7..da32d3c3b 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1866,7 +1866,7 @@ void Database::ClearAllRaidDetails(void) } void Database::ClearRaidDetails(uint32 rid) { - char *query = nullptr; + if(rid == 0) { @@ -1876,8 +1876,8 @@ void Database::ClearRaidDetails(uint32 rid) { } //clear a specific group - auto results = QueryDatabase(query, MakeAnyLenString(&query, "delete from raid_details where raidid = %lu", (unsigned long)rid)); - safe_delete_array(query); + std::string query = StringFormat("delete from raid_details where raidid = %lu", (unsigned long)rid); + auto results = QueryDatabase(query); if (!results.Success()) std::cout << "Unable to clear raid details: " << results.ErrorMessage() << std::endl; From dc6e5bc48e10884038ff7059643f35f1e33ed74f Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:20:42 -0700 Subject: [PATCH 220/288] GetRaidID converted to StringFormat --- common/database.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index da32d3c3b..f1cd47c50 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1867,7 +1867,6 @@ void Database::ClearAllRaidDetails(void) void Database::ClearRaidDetails(uint32 rid) { - if(rid == 0) { //clear all raids @@ -1886,10 +1885,9 @@ void Database::ClearRaidDetails(uint32 rid) { // returns 0 on error or no raid for that character, or // the raid id that the character is a member of. uint32 Database::GetRaidID(const char* name){ - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT raidid from raid_members where name='%s'", name)); - safe_delete_array(query); + std::string query = StringFormat("SELECT raidid from raid_members where name='%s'", name); + auto results = QueryDatabase(query); if (!results.Success()) { From d68fca8e511d839db41082b3f071eaeb05f71685 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:22:20 -0700 Subject: [PATCH 221/288] GetRaidLeaderName converted to StringFormat --- common/database.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index f1cd47c50..1354651d2 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1917,10 +1917,9 @@ const char* Database::GetRaidLeaderName(uint32 rid) // variable). C++0x standard states this should be thread safe // but may not be fully supported in some compilers. static char name[128]; - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT name FROM raid_members WHERE raidid=%u AND israidleader=1",rid)); - safe_delete_array(query); + + std::string query = StringFormat("SELECT name FROM raid_members WHERE raidid=%u AND israidleader=1",rid); + auto results = QueryDatabase(query); if (!results.Success()) { From b5f5dae9e8b6fc66a07f0bf086664eb5159af953 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:23:11 -0700 Subject: [PATCH 222/288] VerifyZoneInstance converted to StringFormat --- common/database.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 1354651d2..20f8620f1 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1958,10 +1958,9 @@ bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 char_id) bool Database::VerifyZoneInstance(uint32 zone_id, uint16 instance_id) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT id FROM instance_list where id=%u AND zone=%u",instance_id, zone_id)); - safe_delete_array(query); + std::string query = StringFormat("SELECT id FROM instance_list where id=%u AND zone=%u",instance_id, zone_id); + auto results = QueryDatabase(query); if (!results.Success()) return false; From 3581b0bf1a8fe804f471164773c1eaae8ba0cd2f Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:24:01 -0700 Subject: [PATCH 223/288] CharacterInInstanceGroup converted to StringFormat --- common/database.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 20f8620f1..5c087615b 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1973,10 +1973,9 @@ bool Database::VerifyZoneInstance(uint32 zone_id, uint16 instance_id) bool Database::CharacterInInstanceGroup(uint16 instance_id, uint32 char_id) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT charid FROM instance_list_player where id=%u AND charid=%u",instance_id, char_id)); - safe_delete_array(query); + std::string query = StringFormat("SELECT charid FROM instance_list_player where id=%u AND charid=%u",instance_id, char_id); + auto results = QueryDatabase(query); if (!results.Success()) return false; From c6c47aba22ad4d5023e78368967407e5ece224ae Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:25:58 -0700 Subject: [PATCH 224/288] DeleteInstance converted to StringFormat --- common/database.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 5c087615b..35c850277 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1988,19 +1988,18 @@ bool Database::CharacterInInstanceGroup(uint16 instance_id, uint32 char_id) void Database::DeleteInstance(uint16 instance_id) { - char *query = nullptr; - QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM instance_list WHERE id=%u", instance_id)); - safe_delete_array(query); + std::string query = StringFormat("DELETE FROM instance_list WHERE id=%u", instance_id); + QueryDatabase(query); - QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM instance_list_player WHERE id=%u", instance_id)); - safe_delete_array(query); + query = StringFormat("DELETE FROM instance_list_player WHERE id=%u", instance_id); + QueryDatabase(query); - QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM respawn_times WHERE instance_id=%u", instance_id)); - safe_delete_array(query); + query = StringFormat("DELETE FROM respawn_times WHERE instance_id=%u", instance_id); + QueryDatabase(query); - QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM spawn_condition_values WHERE instance_id=%u", instance_id)); - safe_delete_array(query); + query = StringFormat("DELETE FROM spawn_condition_values WHERE instance_id=%u", instance_id); + QueryDatabase(query); BuryCorpsesInInstance(instance_id); } From 784b16bd4331eb401a4b63a900a1fa0039959930 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:26:56 -0700 Subject: [PATCH 225/288] CheckInstanceExpired converted to StringFormat --- common/database.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 35c850277..992b4d86d 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2006,14 +2006,13 @@ void Database::DeleteInstance(uint16 instance_id) bool Database::CheckInstanceExpired(uint16 instance_id) { - char *query = nullptr; - + int32 start_time = 0; int32 duration = 0; uint32 never_expires = 0; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", instance_id)); - safe_delete_array(query); + std::string query = StringFormat("SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", instance_id); + auto results = QueryDatabase(query); if (!results.Success()) return true; From cb510e13d1c2d687e78aa38f69bdc6c8c9eea821 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:27:48 -0700 Subject: [PATCH 226/288] ZoneIDFromInstanceID converted to StringFormat --- common/database.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 992b4d86d..12b7ce3c3 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2040,10 +2040,9 @@ bool Database::CheckInstanceExpired(uint16 instance_id) uint32 Database::ZoneIDFromInstanceID(uint16 instance_id) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT zone FROM instance_list where id=%u", instance_id)); - safe_delete_array(query); + std::string query = StringFormat("SELECT zone FROM instance_list where id=%u", instance_id); + auto results = QueryDatabase(query); if (!results.Success()) return 0; From 11dc235121931f33b58af7076c951324b4c8bbcb Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:28:38 -0700 Subject: [PATCH 227/288] VersionFromInstanceID converted to StringFormat --- common/database.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 12b7ce3c3..6c639af85 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2057,10 +2057,9 @@ uint32 Database::ZoneIDFromInstanceID(uint16 instance_id) uint32 Database::VersionFromInstanceID(uint16 instance_id) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT version FROM instance_list where id=%u", instance_id)); - safe_delete_array(query); + std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id); + auto results = QueryDatabase(query); if (!results.Success()) return 0; From aafc6810345bb00ad9974aa7eaf128bd35ed2f74 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:29:51 -0700 Subject: [PATCH 228/288] GetTimeRemainingInstance converted to StringFormat --- common/database.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 6c639af85..2c668bf71 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2074,14 +2074,12 @@ uint32 Database::VersionFromInstanceID(uint16 instance_id) uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma) { - char *query = nullptr; - uint32 start_time = 0; uint32 duration = 0; uint32 never_expires = 0; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", instance_id)); - safe_delete_array(query); + std::string query = StringFormat("SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", instance_id); + auto results = QueryDatabase(query); if (!results.Success()) { From fb213e6ee58c3f59fb09286401c7382c73b70c15 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:31:30 -0700 Subject: [PATCH 229/288] GetUnusedInstanceID converted to StringFormat --- common/database.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 2c668bf71..78895e9d7 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2114,13 +2114,11 @@ uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma) bool Database::GetUnusedInstanceID(uint16 &instance_id) { - char *query = nullptr; - uint32 count = RuleI(Zone, ReservedInstances); uint32 max = 65535; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT IFNULL(MAX(id),%u)+1 FROM instance_list WHERE id > %u", count, count)); - safe_delete_array(query); + std::string query = StringFormat("SELECT IFNULL(MAX(id),%u)+1 FROM instance_list WHERE id > %u", count, count); + auto results = QueryDatabase(query); if (!results.Success()) { @@ -2142,8 +2140,8 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id) return true; } - results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT id FROM instance_list where id > %u ORDER BY id", count)); - safe_delete_array(query); + query = StringFormat("SELECT id FROM instance_list where id > %u ORDER BY id", count); + results = QueryDatabase(query); if (!results.Success()) { From 9d38c6d44e273a3bc6dea080c7465fab04029478 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:32:48 -0700 Subject: [PATCH 230/288] CreateInstance converted to StringFormat --- common/database.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 78895e9d7..52c3f3fb9 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2180,11 +2180,11 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id) //perhaps purge any expireds too bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "INSERT INTO instance_list (id, zone, version, start_time, duration)" - " values(%lu, %lu, %lu, UNIX_TIMESTAMP(), %lu)", (unsigned long)instance_id, (unsigned long)zone_id, (unsigned long)version, (unsigned long)duration)); - safe_delete_array(query); + std::string query = StringFormat("INSERT INTO instance_list (id, zone, version, start_time, duration)" + " values(%lu, %lu, %lu, UNIX_TIMESTAMP(), %lu)", + (unsigned long)instance_id, (unsigned long)zone_id, (unsigned long)version, (unsigned long)duration); + auto results = QueryDatabase(query); return results.Success(); } From cc9bef9706661e871f77890a1d819b3d7531c328 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:33:44 -0700 Subject: [PATCH 231/288] PurgeExpiredInstances converted to StringFormat --- common/database.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 52c3f3fb9..1a9dabbfb 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2191,10 +2191,9 @@ bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version void Database::PurgeExpiredInstances() { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT id FROM instance_list where (start_time+duration) <= UNIX_TIMESTAMP() and never_expires = 0")); - safe_delete_array(query); + std::string query("SELECT id FROM instance_list where (start_time+duration) <= UNIX_TIMESTAMP() and never_expires = 0"); + auto results = QueryDatabase(query); if (!results.Success()) return; From 39196efcb34ff4c2752150e4033b0e7bef91e35d Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:34:37 -0700 Subject: [PATCH 232/288] AddClientToInstance converted to StringFormat --- common/database.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 1a9dabbfb..b658d78a3 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2207,11 +2207,9 @@ void Database::PurgeExpiredInstances() bool Database::AddClientToInstance(uint16 instance_id, uint32 char_id) { - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "INSERT INTO instance_list_player(id, charid) " - "values(%lu, %lu)", (unsigned long)instance_id, (unsigned long)char_id)); - safe_delete_array(query); + std::string query = StringFormat("INSERT INTO instance_list_player(id, charid) values(%lu, %lu)", + (unsigned long)instance_id, (unsigned long)char_id); + auto results = QueryDatabase(query); return results.Success(); } From e08533c634d74c8dc4eeb83728a35fd36e3f3472 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:43:13 -0700 Subject: [PATCH 233/288] RemoveClientFromInstance converted to StringFormat --- common/database.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index b658d78a3..e19de22f4 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2216,11 +2216,10 @@ bool Database::AddClientToInstance(uint16 instance_id, uint32 char_id) bool Database::RemoveClientFromInstance(uint16 instance_id, uint32 char_id) { - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM instance_list_player WHERE id=%lu AND charid=%lu", - (unsigned long)instance_id, (unsigned long)char_id)); - safe_delete_array(query); + + std::string query = StringFormat("DELETE FROM instance_list_player WHERE id=%lu AND charid=%lu", + (unsigned long)instance_id, (unsigned long)char_id); + auto results = QueryDatabase(query); return results.Success(); } From 77c793166c476ce677f10c517ced2f580c1d01d2 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:44:04 -0700 Subject: [PATCH 234/288] RemoveClientsFromInstance converted to StringFormat --- common/database.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index e19de22f4..32e085bc4 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2226,10 +2226,8 @@ bool Database::RemoveClientFromInstance(uint16 instance_id, uint32 char_id) bool Database::RemoveClientsFromInstance(uint16 instance_id) { - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "DELETE FROM instance_list_player WHERE id=%lu", (unsigned long)instance_id)); - safe_delete_array(query); + std::string query = StringFormat("DELETE FROM instance_list_player WHERE id=%lu", (unsigned long)instance_id); + auto results = QueryDatabase(query); return results.Success(); } From cb5cecd0c25c007990abfa82526224eb50a0a7f2 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:44:58 -0700 Subject: [PATCH 235/288] CheckInstanceExists converted to StringFormat --- common/database.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 32e085bc4..54cc71286 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2234,10 +2234,9 @@ bool Database::RemoveClientsFromInstance(uint16 instance_id) bool Database::CheckInstanceExists(uint16 instance_id) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT * FROM instance_list where id=%u", instance_id)); - safe_delete_array(query); + std::string query = StringFormat("SELECT * FROM instance_list where id=%u", instance_id); + auto results = QueryDatabase(query); if (!results.Success()) return false; From 5104b507bbade95dfd1b041e2a30aba7567c23fc Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:45:49 -0700 Subject: [PATCH 236/288] BuryCorpsesInInstance converted to StringFormat --- common/database.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 54cc71286..45697aca9 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2249,10 +2249,9 @@ bool Database::CheckInstanceExists(uint16 instance_id) void Database::BuryCorpsesInInstance(uint16 instance_id) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "UPDATE player_corpses SET IsBurried=1, instanceid=0 WHERE instanceid=%u", instance_id)); - safe_delete_array(query); + std::string query = StringFormat("UPDATE player_corpses SET IsBurried=1, instanceid=0 WHERE instanceid=%u", instance_id); + auto results = QueryDatabase(query); } uint16 Database::GetInstanceVersion(uint16 instance_id) From c4d9e543e3b04c010abb7ab076977c3d71d7764c Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:46:28 -0700 Subject: [PATCH 237/288] GetInstanceVersion converted to StringFormat --- common/database.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 45697aca9..ed296e34a 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2259,10 +2259,8 @@ uint16 Database::GetInstanceVersion(uint16 instance_id) if(instance_id == 0) return 0; - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT version FROM instance_list where id=%u", instance_id)); - safe_delete_array(query); + std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id); + auto results = QueryDatabase(query); if (!results.Success()) return 0; From a862d9a06d823fd6b79b0b43dd577a7cfeaab1d4 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:47:25 -0700 Subject: [PATCH 238/288] GetInstanceID converted to StringFormat --- common/database.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index ed296e34a..3bce78f13 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2274,12 +2274,11 @@ uint16 Database::GetInstanceVersion(uint16 instance_id) uint16 Database::GetInstanceID(const char* zone, uint32 charid, int16 version) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT instance_list.id FROM instance_list, instance_list_player " - "WHERE instance_list.zone=%u AND instance_list.version=%u AND instance_list.id=instance_list_player.id AND " - "instance_list_player.charid=%u LIMIT 1;", GetZoneID(zone), version, charid, charid)); - safe_delete_array(query); + std::string query = StringFormat("SELECT instance_list.id FROM instance_list, instance_list_player " + "WHERE instance_list.zone=%u AND instance_list.version=%u AND instance_list.id=instance_list_player.id AND " + "instance_list_player.charid=%u LIMIT 1;", GetZoneID(zone), version, charid, charid); + auto results = QueryDatabase(query); if (!results.Success()) return 0; From d606d8f4f27e61b62649daabcbc92569f696a118 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:48:17 -0700 Subject: [PATCH 239/288] GetInstanceID converted to StringFormat --- common/database.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 3bce78f13..9c22e5f61 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2295,12 +2295,10 @@ uint16 Database::GetInstanceID(uint32 zone, uint32 charid, int16 version) if(!zone) return 0; - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT instance_list.id FROM instance_list, instance_list_player " - "WHERE instance_list.zone=%u AND instance_list.version=%u AND instance_list.id=instance_list_player.id AND " - "instance_list_player.charid=%u LIMIT 1;", zone, version, charid)); - safe_delete_array(query); + std::string query = StringFormat("SELECT instance_list.id FROM instance_list, instance_list_player " + "WHERE instance_list.zone=%u AND instance_list.version=%u AND instance_list.id=instance_list_player.id AND " + "instance_list_player.charid=%u LIMIT 1;", zone, version, charid); + auto results = QueryDatabase(query); if (!results.Success()) return 0; From e66b4e4a3d2b00dca08916a3ef56ef19b2d1af22 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:49:13 -0700 Subject: [PATCH 240/288] GetCharactersInInstance converted to StringFormat --- common/database.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 9c22e5f61..609ea231e 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2312,17 +2312,15 @@ uint16 Database::GetInstanceID(uint32 zone, uint32 charid, int16 version) } void Database::GetCharactersInInstance(uint16 instance_id, std::list &charid_list) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT charid FROM instance_list_player WHERE id=%u", instance_id)); + std::string query = StringFormat("SELECT charid FROM instance_list_player WHERE id=%u", instance_id); + auto results = QueryDatabase(query); if (!results.Success()) { - LogFile->write(EQEMuLog::Error, "Error in GetCharactersInInstace query '%s': %s", query, results.ErrorMessage().c_str()); - safe_delete_array(query); + LogFile->write(EQEMuLog::Error, "Error in GetCharactersInInstace query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); return; } - safe_delete_array(query); for(auto row=results.begin();row != results.end();++row) charid_list.push_back(atoi(row[0])); From 79819a85d614ea546c57f44ec243d19f15666d89 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:50:08 -0700 Subject: [PATCH 241/288] AssignGroupToInstance converted to StringFormat --- common/database.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 609ea231e..3afbccb38 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2328,12 +2328,12 @@ void Database::GetCharactersInInstance(uint16 instance_id, std::list &ch void Database::AssignGroupToInstance(uint32 gid, uint32 instance_id) { - char *query = nullptr; + uint32 zone_id = ZoneIDFromInstanceID(instance_id); uint16 version = VersionFromInstanceID(instance_id); - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT charid FROM group_id WHERE groupid=%u", gid)); - safe_delete_array(query); + std::string query = StringFormat("SELECT charid FROM group_id WHERE groupid=%u", gid); + auto results = QueryDatabase(query); if (!results.Success()) return; From 899c34ff63cbf0ddfffec1e900a509579ec72f43 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 17:51:09 -0700 Subject: [PATCH 242/288] AssignRaidToInstance converted to StringFormat --- common/database.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 3afbccb38..020ebd5bc 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2348,12 +2348,12 @@ void Database::AssignGroupToInstance(uint32 gid, uint32 instance_id) void Database::AssignRaidToInstance(uint32 rid, uint32 instance_id) { - char *query = nullptr; + uint32 zone_id = ZoneIDFromInstanceID(instance_id); uint16 version = VersionFromInstanceID(instance_id); - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT charid FROM raid_members WHERE raidid=%u", rid)); - safe_delete_array(query); + std::string query = StringFormat("SELECT charid FROM raid_members WHERE raidid=%u", rid); + auto results = QueryDatabase(query); if (!results.Success()) return; From f2e7f8ec64f8491c332a1c2cde44eabd75a8d42f Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 21:19:57 -0700 Subject: [PATCH 243/288] SetInstanceDuration converted to StringFormat --- common/database.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 020ebd5bc..f4abb5a8c 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2401,11 +2401,10 @@ void Database::FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 chari void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "UPDATE `instance_list` SET start_time=UNIX_TIMESTAMP(), " - "duration=%u WHERE id=%u", new_duration, instance_id)); - safe_delete_array(query); + std::string query = StringFormat("UPDATE `instance_list` SET start_time=UNIX_TIMESTAMP(), " + "duration=%u WHERE id=%u", new_duration, instance_id); + auto results = QueryDatabase(query); } bool Database::GlobalInstance(uint16 instance_id) From 9cd2225f8c888db6bc0d9f20cee107a631a9e08f Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 22:04:58 -0700 Subject: [PATCH 244/288] GlobalInstane converted to StringFormat --- common/database.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index f4abb5a8c..7dcbf5e6b 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2409,10 +2409,9 @@ void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration) bool Database::GlobalInstance(uint16 instance_id) { - char *query = nullptr; - - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT is_global from instance_list where id=%u LIMIT 1", instance_id)); - safe_delete_array(query); + + std::string query = StringFormat("SELECT is_global from instance_list where id=%u LIMIT 1", instance_id); + auto results = QueryDatabase(query); if (!results.Success()) return false; From a7ac4b8debb6f18e8f2f28583a613ab4e60173e3 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 22:06:19 -0700 Subject: [PATCH 245/288] UpdateAdventureStatsEntry converted to StringFormat --- common/database.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 7dcbf5e6b..a2209734b 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2426,8 +2426,7 @@ bool Database::GlobalInstance(uint16 instance_id) void Database::UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win) { - char *query = nullptr; - + std::string field; switch(theme) @@ -2468,16 +2467,14 @@ void Database::UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win) else field += "losses"; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "UPDATE `adventure_stats` SET %s=%s+1 WHERE player_id=%u", - field.c_str(), field.c_str(), char_id)); - safe_delete_array(query); + std::string query = StringFormat("UPDATE `adventure_stats` SET %s=%s+1 WHERE player_id=%u",field.c_str(), field.c_str(), char_id); + auto results = QueryDatabase(query); if (results.RowsAffected() != 0) return; - QueryDatabase(query, MakeAnyLenString(&query, "INSERT INTO `adventure_stats` SET %s=1, player_id=%u", - field.c_str(), char_id)); - safe_delete_array(query); + query = StringFormat("INSERT INTO `adventure_stats` SET %s=1, player_id=%u", field.c_str(), char_id); + QueryDatabase(query); } bool Database::GetAdventureStats(uint32 char_id, uint32 &guk_w, uint32 &mir_w, uint32 &mmc_w, uint32 &ruj_w, From 77a5d82de46029f3a238615cd9c3392cb6541d2b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 22:07:23 -0700 Subject: [PATCH 246/288] GetAdventureStats converted to StringFormat --- common/database.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index a2209734b..842bef0e5 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2480,12 +2480,10 @@ void Database::UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win) bool Database::GetAdventureStats(uint32 char_id, uint32 &guk_w, uint32 &mir_w, uint32 &mmc_w, uint32 &ruj_w, uint32 &tak_w, uint32 &guk_l, uint32 &mir_l, uint32 &mmc_l, uint32 &ruj_l, uint32 &tak_l) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT `guk_wins`, `mir_wins`, `mmc_wins`, `ruj_wins`, `tak_wins`, " - "`guk_losses`, `mir_losses`, `mmc_losses`, `ruj_losses`, `tak_losses` FROM `adventure_stats` WHERE player_id=%u", - char_id)); - safe_delete_array(query); + std::string query = StringFormat("SELECT `guk_wins`, `mir_wins`, `mmc_wins`, `ruj_wins`, `tak_wins`, `guk_losses`, " + "`mir_losses`, `mmc_losses`, `ruj_losses`, `tak_losses` FROM `adventure_stats` WHERE player_id=%u", char_id); + auto results = QueryDatabase(query); if (!results.Success()) return false; From b3895f717ae5b37af0a7cedfd35aae1149f611d5 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 22:08:19 -0700 Subject: [PATCH 247/288] GetGuildIDByCharID converted to StringFormat --- common/database.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 842bef0e5..21506f112 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2509,17 +2509,15 @@ bool Database::GetAdventureStats(uint32 char_id, uint32 &guk_w, uint32 &mir_w, u uint32 Database::GetGuildIDByCharID(uint32 char_id) { - char *query = nullptr; - auto results = QueryDatabase(query, MakeAnyLenString(&query, "SELECT guild_id FROM guild_members WHERE char_id='%i'", char_id)); + std::string query = StringFormat("SELECT guild_id FROM guild_members WHERE char_id='%i'", char_id); + auto results = QueryDatabase(query); if (!results.Success()) { std::cerr << "Error in GetGuildIDByChar query '" << query << "' " << results.ErrorMessage() << std::endl; - safe_delete_array(query); return 0; } - safe_delete_array(query); if (results.RowCount() == 0) return 0; From be90b4e0ccffcc93949dff20470a6d6f0be33490 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 22:53:20 -0700 Subject: [PATCH 248/288] CheckLogin converted to StringFormat --- common/database.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 21506f112..66825f3ab 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -141,8 +141,6 @@ Zero will also be returned if there is a database error. */ uint32 Database::CheckLogin(const char* name, const char* password, int16* oStatus) { - char *query = nullptr; - if(strlen(name) >= 50 || strlen(password) >= 50) return(0); @@ -152,22 +150,17 @@ uint32 Database::CheckLogin(const char* name, const char* password, int16* oStat DoEscapeString(tmpUN, name, strlen(name)); DoEscapeString(tmpPW, password, strlen(password)); - auto results = QueryDatabase(query, MakeAnyLenString(&query, - "SELECT id, status FROM account WHERE name='%s' AND password is not null " + std::string query = StringFormat("SELECT id, status FROM account WHERE name='%s' AND password is not null " "and length(password) > 0 and (password='%s' or password=MD5('%s'))", - tmpUN, tmpPW, tmpPW)); - - + tmpUN, tmpPW, tmpPW); + auto results = QueryDatabase(query); if (!results.Success()) { - safe_delete_array(query); std::cerr << "Error in CheckLogin query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } - safe_delete_array(query); - auto row = results.begin(); uint32 id = atoi(row[0]); From b43ab783b0f0929c5e718d858d620ccc5266169b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 10 Jul 2014 22:55:00 -0700 Subject: [PATCH 249/288] AddReport converted to StringFormat --- common/database.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 66825f3ab..1815b155c 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1604,12 +1604,12 @@ void Database::SetFirstLogon(uint32 CharID, uint8 firstlogon) { void Database::AddReport(std::string who, std::string against, std::string lines) { - char *query = nullptr; + char *escape_str = new char[lines.size()*2+1]; DoEscapeString(escape_str, lines.c_str(), lines.size()); - auto results = QueryDatabase(query, MakeAnyLenString(&query, "INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", who.c_str(), against.c_str(), escape_str)); - safe_delete_array(query); + std::string query = StringFormat("INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", who.c_str(), against.c_str(), escape_str); + auto results = QueryDatabase(query); safe_delete_array(escape_str); if (!results.Success()) From e1e219ae97a044b786217d21465f707cab0ce987 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Fri, 1 Aug 2014 10:41:26 -0700 Subject: [PATCH 250/288] Merge upstream --- common/eq_dictionary.cpp.orig | 1151 +++++++++++++++++++++++++++++++++ 1 file changed, 1151 insertions(+) create mode 100644 common/eq_dictionary.cpp.orig diff --git a/common/eq_dictionary.cpp.orig b/common/eq_dictionary.cpp.orig new file mode 100644 index 000000000..ecedcbb4e --- /dev/null +++ b/common/eq_dictionary.cpp.orig @@ -0,0 +1,1151 @@ +/* +EQEMu: Everquest Server Emulator + +Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net) + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY except by those people which sell it, which +are required to give you total support for your newly bought product; +without even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "eq_dictionary.h" +#include "StringUtil.h" + +// +// class EmuConstants +// +uint16 EmuConstants::InventoryMapSize(int16 map) { + switch (map) { + case MapPossessions: + return MAP_POSSESSIONS_SIZE; + case MapBank: + return MAP_BANK_SIZE; + case MapSharedBank: + return MAP_SHARED_BANK_SIZE; + case MapTrade: + return MAP_TRADE_SIZE; + case MapWorld: + return MAP_WORLD_SIZE; + case MapLimbo: + return MAP_LIMBO_SIZE; + case MapTribute: + return MAP_TRIBUTE_SIZE; + case MapTrophyTribute: + return MAP_TROPHY_TRIBUTE_SIZE; + case MapGuildTribute: + return MAP_GUILD_TRIBUTE_SIZE; + case MapMerchant: + return MAP_MERCHANT_SIZE; + case MapDeleted: + return MAP_DELETED_SIZE; + case MapCorpse: + return MAP_CORPSE_SIZE; + case MapBazaar: + return MAP_BAZAAR_SIZE; + case MapInspect: + return MAP_INSPECT_SIZE; + case MapRealEstate: + return MAP_REAL_ESTATE_SIZE; + case MapViewMODPC: + return MAP_VIEW_MOD_PC_SIZE; + case MapViewMODBank: + return MAP_VIEW_MOD_BANK_SIZE; + case MapViewMODSharedBank: + return MAP_VIEW_MOD_SHARED_BANK_SIZE; + case MapViewMODLimbo: + return MAP_VIEW_MOD_LIMBO_SIZE; + case MapAltStorage: + return MAP_ALT_STORAGE_SIZE; + case MapArchived: + return MAP_ARCHIVED_SIZE; + case MapMail: + return MAP_MAIL_SIZE; + case MapGuildTrophyTribute: + return MAP_GUILD_TROPHY_TRIBUTE_SIZE; + case MapKrono: + return MAP_KRONO_SIZE; + case MapOther: + return MAP_OTHER_SIZE; + default: + return NOT_USED; + } +} + +/* +std::string EmuConstants::InventoryLocationName(Location_Struct location) { + // not ready for implementation... + std::string ret_str; + StringFormat(ret_str, "%s, %s, %s, %s", InventoryMapName(location.map), InventoryMainName(location.main), InventorySubName(location.sub), InventoryAugName(location.aug)); + return ret_str; +} +*/ + +std::string EmuConstants::InventoryMapName(int16 map) { + switch (map) { + case INVALID_INDEX: + return "Invalid Map"; + case MapPossessions: + return "Possessions"; + case MapBank: + return "Bank"; + case MapSharedBank: + return "Shared Bank"; + case MapTrade: + return "Trade"; + case MapWorld: + return "World"; + case MapLimbo: + return "Limbo"; + case MapTribute: + return "Tribute"; + case MapTrophyTribute: + return "Trophy Tribute"; + case MapGuildTribute: + return "Guild Tribute"; + case MapMerchant: + return "Merchant"; + case MapDeleted: + return "Deleted"; + case MapCorpse: + return "Corpse"; + case MapBazaar: + return "Bazaar"; + case MapInspect: + return "Inspect"; + case MapRealEstate: + return "Real Estate"; + case MapViewMODPC: + return "View MOD PC"; + case MapViewMODBank: + return "View MOD Bank"; + case MapViewMODSharedBank: + return "View MOD Shared Bank"; + case MapViewMODLimbo: + return "View MOD Limbo"; + case MapAltStorage: + return "Alt Storage"; + case MapArchived: + return "Archived"; + case MapMail: + return "Mail"; + case MapGuildTrophyTribute: + return "Guild Trophy Tribute"; + case MapKrono: + return "Krono"; + case MapOther: + return "Other"; + default: + return "Unknown Map"; + } +} + +std::string EmuConstants::InventoryMainName(int16 main) { + switch (main) { + case INVALID_INDEX: + return "Invalid Main"; + case MainCharm: + return "Charm"; + case MainEar1: + return "Ear 1"; + case MainHead: + return "Head"; + case MainFace: + return "Face"; + case MainEar2: + return "Ear 2"; + case MainNeck: + return "Neck"; + case MainShoulders: + return "Shoulders"; + case MainArms: + return "Arms"; + case MainBack: + return "Back"; + case MainWrist1: + return "Wrist 1"; + case MainWrist2: + return "Wrist 2"; + case MainRange: + return "Range"; + case MainHands: + return "Hands"; + case MainPrimary: + return "Primary"; + case MainSecondary: + return "Secondary"; + case MainFinger1: + return "Finger 1"; + case MainFinger2: + return "Finger 2"; + case MainChest: + return "Chest"; + case MainLegs: + return "Legs"; + case MainFeet: + return "Feet"; + case MainWaist: + return "Waist"; + case MainPowerSource: + return "Power Source"; + case MainAmmo: + return "Ammo"; + case MainGeneral1: + return "General 1"; + case MainGeneral2: + return "General 2"; + case MainGeneral3: + return "General 3"; + case MainGeneral4: + return "General 4"; + case MainGeneral5: + return "General 5"; + case MainGeneral6: + return "General 6"; + case MainGeneral7: + return "General 7"; + case MainGeneral8: + return "General 8"; + /* + case MainGeneral9: + return "General 9"; + case MainGeneral10: + return "General 10"; + */ + case MainCursor: + return "Cursor"; + default: + return "Unknown Main"; + } +} + +std::string EmuConstants::InventorySubName(int16 sub) { + if (sub == INVALID_INDEX) + return "Invalid Sub"; + + if ((uint16)sub >= ITEM_CONTAINER_SIZE) + return "Unknown Sub"; + + std::string ret_str; + ret_str = StringFormat("Container %i", (sub + 1)); // zero-based index..but, count starts at one + + return ret_str; +} + +std::string EmuConstants::InventoryAugName(int16 aug) { + if (aug == INVALID_INDEX) + return "Invalid Aug"; + + if ((uint16)aug >= ITEM_COMMON_SIZE) + return "Unknown Aug"; + + std::string ret_str; + ret_str = StringFormat("Augment %i", (aug + 1)); // zero-based index..but, count starts at one + + return ret_str; +} + +<<<<<<< HEAD +// +// class ClientLimits +======= +// legacy-related functions +// +// these should work for the first-stage coversions..but, once the new system is up and going..conversions will be incompatible +// without limiting server functions and other aspects, such as augment control, bag size, etc. A complete remapping will be +// required when bag sizes over 10 and direct manipulation of augments are implemented, due to the massive increase in range usage. +// +// (current personal/cursor bag range {251..340}, or 90 slots ... conversion translated range would be {10000..12804}, or 2805 slots... +// these would have to be hard-coded into all perl code to allow access to full range of the new system - actual limits would be +// less, based on bag size..but, the range must be full and consistent to avoid translation issues -- similar changes to other ranges +// (240 versus 6120 slots for bank bags, for example...)) +/* +int EmuConstants::ServerToPerlSlot(int server_slot) { // set r/s + switch (server_slot) { + case legacy::SLOT_CURSOR_END: + return legacy::SLOT_CURSOR_END; + case INVALID_INDEX: + return legacy::SLOT_INVALID; + case MainPowerSource: + return legacy::SLOT_POWER_SOURCE; + case MainAmmo: + return legacy::SLOT_AMMO; + case MainCursor: + return legacy::SLOT_CURSOR; + case legacy::SLOT_TRADESKILL: + return legacy::SLOT_TRADESKILL; + case legacy::SLOT_AUGMENT: + return legacy::SLOT_AUGMENT; + default: + int perl_slot = legacy::SLOT_INVALID; + + // activate the internal checks as needed + if (server_slot >= EmuConstants::EQUIPMENT_BEGIN && server_slot <= MainWaist) { + perl_slot = server_slot; + } + else if (server_slot >= EmuConstants::GENERAL_BEGIN && server_slot <= EmuConstants::GENERAL_END) { + perl_slot = server_slot;// + legacy::SLOT_PERSONAL_BEGIN - EmuConstants::GENERAL_BEGIN; + //if (perl_slot < legacy::SLOT_PERSONAL_BEGIN || perl_slot > legacy::SLOT_PERSONAL_END) + // perl_slot = legacy::SLOT_INVALID; + } + else if (server_slot >= EmuConstants::GENERAL_BAGS_BEGIN && server_slot <= EmuConstants::GENERAL_BAGS_END) { + perl_slot = server_slot;// + legacy::SLOT_PERSONAL_BAGS_BEGIN - EmuConstants::GENERAL_BAGS_BEGIN; + //if (perl_slot < legacy::SLOT_PERSONAL_BAGS_BEGIN || perl_slot > legacy::SLOT_PERSONAL_BAGS_END) + // perl_slot = legacy::SLOT_INVALID; + } + else if (server_slot >= EmuConstants::CURSOR_BAG_BEGIN && server_slot <= EmuConstants::CURSOR_BAG_END) { + perl_slot = server_slot;// + legacy::SLOT_CURSOR_BAG_BEGIN - EmuConstants::CURSOR_BAG_BEGIN; + //if (perl_slot < legacy::SLOT_CURSOR_BAG_BEGIN || perl_slot > legacy::SLOT_CURSOR_BAG_END) + // perl_slot = legacy::SLOT_INVALID; + } + else if (server_slot >= EmuConstants::TRIBUTE_BEGIN && server_slot <= EmuConstants::TRIBUTE_END) { + perl_slot = server_slot;// + legacy::SLOT_TRIBUTE_BEGIN - EmuConstants::TRADE_BEGIN; + //if (perl_slot < legacy::SLOT_TRIBUTE_BEGIN || perl_slot > legacy::SLOT_TRIBUTE_END) + // perl_slot = legacy::SLOT_INVALID; + } + else if (server_slot >= EmuConstants::BANK_BEGIN && server_slot <= EmuConstants::BANK_END) { + perl_slot = server_slot;// + legacy::SLOT_BANK_BEGIN - EmuConstants::BANK_BEGIN; + //if (perl_slot < legacy::SLOT_BANK_BEGIN || perl_slot > legacy::SLOT_BANK_END) + // perl_slot = legacy::SLOT_INVALID; + } + else if (server_slot >= EmuConstants::BANK_BAGS_BEGIN && server_slot <= EmuConstants::BANK_BAGS_END) { + perl_slot = server_slot;// + legacy::SLOT_BANK_BAGS_BEGIN - EmuConstants::BANK_BAGS_BEGIN; + //if (perl_slot < legacy::SLOT_BANK_BAGS_BEGIN || perl_slot > legacy::SLOT_BANK_BAGS_END) + // perl_slot = legacy::SLOT_INVALID; + } + else if (server_slot >= EmuConstants::SHARED_BANK_BEGIN && server_slot <= EmuConstants::SHARED_BANK_END) { + perl_slot = server_slot;// + legacy::SLOT_SHARED_BANK_BEGIN - EmuConstants::SHARED_BANK_BEGIN; + //if (perl_slot < legacy::SLOT_SHARED_BANK_BEGIN || perl_slot > legacy::SLOT_SHARED_BANK_END) + // perl_slot = legacy::SLOT_INVALID; + } + else if (server_slot >= EmuConstants::SHARED_BANK_BAGS_BEGIN && server_slot <= EmuConstants::SHARED_BANK_BAGS_END) { + perl_slot = server_slot;// + legacy::SLOT_SHARED_BANK_BAGS_BEGIN - EmuConstants::SHARED_BANK_BAGS_BEGIN; + //if (perl_slot < legacy::SLOT_SHARED_BANK_BAGS_BEGIN || perl_slot > legacy::SLOT_SHARED_BANK_BAGS_END) + // perl_slot = legacy::SLOT_INVALID; + } + else if (server_slot >= EmuConstants::TRADE_BEGIN && server_slot <= EmuConstants::TRADE_END) { + perl_slot = server_slot;// + legacy::SLOT_TRADE_BEGIN - EmuConstants::TRADE_BEGIN; + //if (perl_slot < legacy::SLOT_TRADE_BEGIN || perl_slot > legacy::SLOT_TRADE_END) + // perl_slot = legacy::SLOT_INVALID; + } + else if (server_slot >= EmuConstants::TRADE_BAGS_BEGIN && server_slot <= EmuConstants::TRADE_BAGS_END) { + perl_slot = server_slot;// + legacy::SLOT_TRADE_BAGS_BEGIN - EmuConstants::TRADE_BAGS_BEGIN; + //if (perl_slot < legacy::SLOT_TRADE_BAGS_BEGIN || perl_slot > legacy::SLOT_TRADE_BAGS_END) + // perl_slot = legacy::SLOT_INVALID; + } + else if (server_slot >= EmuConstants::WORLD_BEGIN && server_slot <= EmuConstants::WORLD_END) { + perl_slot = server_slot;// + legacy::SLOT_WORLD_BEGIN - EmuConstants::WORLD_BEGIN; + //if (perl_slot < legacy::SLOT_WORLD_BEGIN || perl_slot > legacy::SLOT_WORLD_END) + // perl_slot = legacy::SLOT_INVALID; + } + else if (server_slot >= 8000 && server_slot <= 8999) { // this range may be limited to 36 in the future (client size) + perl_slot = server_slot; + } + + return perl_slot; + } +} +*/ +/* +int EmuConstants::PerlToServerSlot(int perl_slot) { // set r/s + switch (perl_slot) { + case legacy::SLOT_CURSOR_END: + return legacy::SLOT_CURSOR_END; + case legacy::SLOT_INVALID: + return INVALID_INDEX; + case legacy::SLOT_POWER_SOURCE: + return MainPowerSource; + case legacy::SLOT_AMMO: + return MainAmmo; + case legacy::SLOT_CURSOR: + return MainCursor; + case legacy::SLOT_TRADESKILL: + return legacy::SLOT_TRADESKILL; + case legacy::SLOT_AUGMENT: + return legacy::SLOT_AUGMENT; + default: + int server_slot = INVALID_INDEX; + + // activate the internal checks as needed + if (perl_slot >= legacy::SLOT_EQUIPMENT_BEGIN && perl_slot <= legacy::SLOT_WAIST) { + server_slot = perl_slot; + } + else if (perl_slot >= legacy::SLOT_PERSONAL_BEGIN && perl_slot <= legacy::SLOT_PERSONAL_END) { + server_slot = perl_slot;// + EmuConstants::GENERAL_BEGIN - legacy::SLOT_PERSONAL_BEGIN; + //if (server_slot < EmuConstants::GENERAL_BEGIN || server_slot > EmuConstants::GENERAL_END) + // server_slot = INVALID_INDEX; + } + else if (perl_slot >= legacy::SLOT_PERSONAL_BAGS_BEGIN && perl_slot <= legacy::SLOT_PERSONAL_BAGS_END) { + server_slot = perl_slot;// + EmuConstants::GENERAL_BAGS_BEGIN - legacy::SLOT_PERSONAL_BAGS_BEGIN; + //if (server_slot < EmuConstants::GENERAL_BAGS_BEGIN || server_slot > EmuConstants::GENERAL_BAGS_END) + // server_slot = INVALID_INDEX; + } + else if (perl_slot >= legacy::SLOT_CURSOR_BAG_BEGIN && perl_slot <= legacy::SLOT_CURSOR_BAG_END) { + server_slot = perl_slot;// + EmuConstants::CURSOR_BAG_BEGIN - legacy::SLOT_CURSOR_BAG_BEGIN; + //if (server_slot < EmuConstants::CURSOR_BAG_BEGIN || server_slot > EmuConstants::CURSOR_BAG_END) + // server_slot = INVALID_INDEX; + } + else if (perl_slot >= legacy::SLOT_TRIBUTE_BEGIN && perl_slot <= legacy::SLOT_TRIBUTE_END) { + server_slot = perl_slot;// + EmuConstants::TRIBUTE_BEGIN - legacy::SLOT_TRIBUTE_BEGIN; + //if (server_slot < EmuConstants::TRIBUTE_BEGIN || server_slot > EmuConstants::TRIBUTE_END) + // server_slot = INVALID_INDEX; + } + else if (perl_slot >= legacy::SLOT_BANK_BEGIN && perl_slot <= legacy::SLOT_BANK_END) { + server_slot = perl_slot;// + EmuConstants::BANK_BEGIN - legacy::SLOT_BANK_BEGIN; + //if (server_slot < EmuConstants::BANK_BEGIN || server_slot > EmuConstants::BANK_END) + // server_slot = INVALID_INDEX; + } + else if (perl_slot >= legacy::SLOT_BANK_BAGS_BEGIN && perl_slot <= legacy::SLOT_BANK_BAGS_END) { + server_slot = perl_slot;// + EmuConstants::BANK_BAGS_BEGIN - legacy::SLOT_BANK_BAGS_BEGIN; + //if (server_slot < EmuConstants::BANK_BAGS_BEGIN || server_slot > EmuConstants::BANK_BAGS_END) + // server_slot = INVALID_INDEX; + } + else if (perl_slot >= legacy::SLOT_SHARED_BANK_BEGIN && perl_slot <= legacy::SLOT_SHARED_BANK_END) { + server_slot = perl_slot;// + EmuConstants::SHARED_BANK_BEGIN - legacy::SLOT_SHARED_BANK_BEGIN; + //if (server_slot < EmuConstants::SHARED_BANK_BEGIN || server_slot > EmuConstants::SHARED_BANK_END) + // server_slot = INVALID_INDEX; + } + else if (perl_slot >= legacy::SLOT_SHARED_BANK_BAGS_BEGIN && perl_slot <= legacy::SLOT_SHARED_BANK_BAGS_END) { + server_slot = perl_slot;// + EmuConstants::SHARED_BANK_BAGS_BEGIN - legacy::SLOT_SHARED_BANK_BAGS_END; + //if (server_slot < EmuConstants::SHARED_BANK_BAGS_BEGIN || server_slot > EmuConstants::SHARED_BANK_BAGS_END) + // server_slot = INVALID_INDEX; + } + else if (perl_slot >= legacy::SLOT_TRADE_BEGIN && perl_slot <= legacy::SLOT_TRADE_END) { + server_slot = perl_slot;// + EmuConstants::TRADE_BEGIN - legacy::SLOT_TRADE_BEGIN; + //if (server_slot < EmuConstants::TRADE_BEGIN || server_slot > EmuConstants::TRADE_END) + // server_slot = INVALID_INDEX; + } + else if (perl_slot >= legacy::SLOT_TRADE_BAGS_BEGIN && perl_slot <= legacy::SLOT_TRADE_BAGS_END) { + server_slot = perl_slot;// + EmuConstants::TRADE_BAGS_BEGIN - legacy::SLOT_TRADE_BAGS_BEGIN; + //if (server_slot < EmuConstants::TRADE_BAGS_BEGIN || server_slot > EmuConstants::TRADE_BAGS_END) + // server_slot = INVALID_INDEX; + } + else if (perl_slot >= legacy::SLOT_WORLD_BEGIN && perl_slot <= legacy::SLOT_WORLD_END) { + server_slot = perl_slot;// + EmuConstants::WORLD_BEGIN - legacy::SLOT_WORLD_BEGIN; + //if (server_slot < EmuConstants::WORLD_BEGIN || server_slot > EmuConstants::WORLD_END) + // server_slot = INVALID_INDEX; + } + else if (perl_slot >= 8000 && perl_slot <= 8999) { // this range may be limited to 36 in the future (client size) + server_slot = perl_slot; + } + + return server_slot; + } +} +*/ + +// +// class EQLimits +>>>>>>> upstream/master +// +// client validation +bool EQLimits::IsValidClientVersion(uint32 version) { + if (version < _EQClientCount) + return true; + + return false; +} + +uint32 EQLimits::ValidateClientVersion(uint32 version) { + if (version < _EQClientCount) + return version; + + return EQClientUnknown; +} + +EQClientVersion EQLimits::ValidateClientVersion(EQClientVersion version) { + if (version >= EQClientUnknown) + if (version < _EQClientCount) + return version; + + return EQClientUnknown; +} + +// npc validation +bool EQLimits::IsValidNPCVersion(uint32 version) { + if (version >= _EQClientCount) + if (version < _EmuClientCount) + return true; + + return false; +} + +uint32 EQLimits::ValidateNPCVersion(uint32 version) { + if (version >= _EQClientCount) + if (version < _EmuClientCount) + return version; + + return EQClientUnknown; +} + +EQClientVersion EQLimits::ValidateNPCVersion(EQClientVersion version) { + if (version >= _EQClientCount) + if (version < _EmuClientCount) + return version; + + return EQClientUnknown; +} + +// mob validation +bool EQLimits::IsValidMobVersion(uint32 version) { + if (version < _EmuClientCount) + return true; + + return false; +} + +uint32 EQLimits::ValidateMobVersion(uint32 version) { + if (version < _EmuClientCount) + return version; + + return EQClientUnknown; +} + +EQClientVersion EQLimits::ValidateMobVersion(EQClientVersion version) { + if (version >= EQClientUnknown) + if (version < _EmuClientCount) + return version; + + return EQClientUnknown; +} + +// inventory +uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { + // not all maps will have an instantiated container..some are references for queue generators (i.e., bazaar, mail, etc...) + // a zero '0' indicates a needed value..otherwise, change to '_NOTUSED' for a null value so indices requiring research can be identified + // ALL of these values need to be verified before pushing to live + // + // make sure that you transcribe the actual value from 'defaults' to here before updating or client crashes will ensue..and/or... + // insert older clients inside of the progression of client order + // + // MAP_POSSESSIONS_SIZE does not reflect all actual _constants size due to bitmask-use compatibility + // + // when setting NPC-based values, try to adhere to an EmuConstants:: or NOT_USED value to avoid unnecessary issues + + static const uint16 local[_MapCount][_EmuClientCount] = { + // server and database are sync'd to current MapPossessions's client as set in 'using namespace RoF::slots;' and + // 'EmuConstants::MAP_POSSESSIONS_SIZE' - use/update EquipmentBitmask(), GeneralBitmask() and CursorBitmask() + // for partial range validation checks and 'EmuConstants::MAP_POSSESSIONS_SIZE' for full range iterations + { // local[MainPossessions] +/*Unknown*/ NOT_USED, +/*62*/ EmuConstants::MAP_POSSESSIONS_SIZE, +/*Titanium*/ EmuConstants::MAP_POSSESSIONS_SIZE, +/*SoF*/ EmuConstants::MAP_POSSESSIONS_SIZE, +/*SoD*/ EmuConstants::MAP_POSSESSIONS_SIZE, +/*Underfoot*/ EmuConstants::MAP_POSSESSIONS_SIZE, +/*RoF*/ EmuConstants::MAP_POSSESSIONS_SIZE, +/*RoF2*/ 0, + +/*NPC*/ EmuConstants::MAP_POSSESSIONS_SIZE, +/*Merc*/ EmuConstants::MAP_POSSESSIONS_SIZE, +/*Bot*/ EmuConstants::MAP_POSSESSIONS_SIZE, +/*Pet*/ EmuConstants::MAP_POSSESSIONS_SIZE + }, + { // local[MapBank] +/*Unknown*/ NOT_USED, +/*62*/ Client62::consts::MAP_BANK_SIZE, +/*Titanium*/ Titanium::consts::MAP_BANK_SIZE, +/*SoF*/ EmuConstants::MAP_BANK_SIZE, +/*SoD*/ EmuConstants::MAP_BANK_SIZE, +/*Underfoot*/ EmuConstants::MAP_BANK_SIZE, +/*RoF*/ EmuConstants::MAP_BANK_SIZE, +/*RoF2*/ 0, + +/*NPC*/ NOT_USED, +/*Merc*/ NOT_USED, +/*Bot*/ NOT_USED, +/*Pet*/ NOT_USED + }, + { // local[MapSharedBank] +/*Unknown*/ NOT_USED, +/*62*/ EmuConstants::MAP_SHARED_BANK_SIZE, +/*Titanium*/ EmuConstants::MAP_SHARED_BANK_SIZE, +/*SoF*/ EmuConstants::MAP_SHARED_BANK_SIZE, +/*SoD*/ EmuConstants::MAP_SHARED_BANK_SIZE, +/*Underfoot*/ EmuConstants::MAP_SHARED_BANK_SIZE, +/*RoF*/ EmuConstants::MAP_SHARED_BANK_SIZE, +/*RoF2*/ 0, + +/*NPC*/ NOT_USED, +/*Merc*/ NOT_USED, +/*Bot*/ NOT_USED, +/*Pet*/ NOT_USED + }, + { // local[MapTrade] +/*Unknown*/ NOT_USED, +/*62*/ EmuConstants::MAP_TRADE_SIZE, +/*Titanium*/ EmuConstants::MAP_TRADE_SIZE, +/*SoF*/ EmuConstants::MAP_TRADE_SIZE, +/*SoD*/ EmuConstants::MAP_TRADE_SIZE, +/*Underfoot*/ EmuConstants::MAP_TRADE_SIZE, +/*RoF*/ EmuConstants::MAP_TRADE_SIZE, +/*RoF2*/ 0, + +/*NPC*/ 4, +/*Merc*/ 4, +/*Bot*/ EmuConstants::MAP_TRADE_SIZE, // client thinks this is another client +/*Pet*/ 4 + }, + { // local[MapWorld] +/*Unknown*/ NOT_USED, +/*62*/ EmuConstants::MAP_WORLD_SIZE, +/*Titanium*/ EmuConstants::MAP_WORLD_SIZE, +/*SoF*/ EmuConstants::MAP_WORLD_SIZE, +/*SoD*/ EmuConstants::MAP_WORLD_SIZE, +/*Underfoot*/ EmuConstants::MAP_WORLD_SIZE, +/*RoF*/ EmuConstants::MAP_WORLD_SIZE, +/*RoF2*/ 0, + +/*NPC*/ NOT_USED, +/*Merc*/ NOT_USED, +/*Bot*/ NOT_USED, +/*Pet*/ NOT_USED + }, + { // local[MapLimbo] +/*Unknown*/ NOT_USED, +/*62*/ EmuConstants::MAP_LIMBO_SIZE, +/*Titanium*/ EmuConstants::MAP_LIMBO_SIZE, +/*SoF*/ EmuConstants::MAP_LIMBO_SIZE, +/*SoD*/ EmuConstants::MAP_LIMBO_SIZE, +/*Underfoot*/ EmuConstants::MAP_LIMBO_SIZE, +/*RoF*/ EmuConstants::MAP_LIMBO_SIZE, +/*RoF2*/ 0, + +/*NPC*/ NOT_USED, +/*Merc*/ NOT_USED, +/*Bot*/ NOT_USED, +/*Pet*/ NOT_USED + }, + { // local[MapTribute] +/*Unknown*/ NOT_USED, +/*62*/ EmuConstants::MAP_TRIBUTE_SIZE, +/*Titanium*/ EmuConstants::MAP_TRIBUTE_SIZE, +/*SoF*/ EmuConstants::MAP_TRIBUTE_SIZE, +/*SoD*/ EmuConstants::MAP_TRIBUTE_SIZE, +/*Underfoot*/ EmuConstants::MAP_TRIBUTE_SIZE, +/*RoF*/ EmuConstants::MAP_TRIBUTE_SIZE, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[MapTrophyTribute] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ EmuConstants::MAP_TROPHY_TRIBUTE_SIZE, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[MapGuildTribute] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ EmuConstants::MAP_GUILD_TRIBUTE_SIZE, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[MapMerchant] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ EmuConstants::MAP_MERCHANT_SIZE, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[MapDeleted] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ EmuConstants::MAP_DELETED_SIZE, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[MapCorpse] +/*Unknown*/ NOT_USED, +/*62*/ Client62::consts::MAP_CORPSE_SIZE, +/*Titanium*/ Titanium::consts::MAP_CORPSE_SIZE, +/*SoF*/ SoF::consts::MAP_CORPSE_SIZE, +/*SoD*/ SoD::consts::MAP_CORPSE_SIZE, +/*Underfoot*/ Underfoot::consts::MAP_CORPSE_SIZE, +/*RoF*/ RoF::consts::MAP_CORPSE_SIZE, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[MapBazaar] +/*Unknown*/ NOT_USED, +/*62*/ EmuConstants::MAP_BAZAAR_SIZE, +/*Titanium*/ EmuConstants::MAP_BAZAAR_SIZE, +/*SoF*/ EmuConstants::MAP_BAZAAR_SIZE, +/*SoD*/ EmuConstants::MAP_BAZAAR_SIZE, +/*Underfoot*/ EmuConstants::MAP_BAZAAR_SIZE, +/*RoF*/ EmuConstants::MAP_BAZAAR_SIZE, +/*RoF2*/ 0, + +/*NPC*/ 0, // this may need to be 'EmuConstants::MAP_BAZAAR_SIZE' if offline client traders respawn as an npc +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[MapInspect] +/*Unknown*/ NOT_USED, +/*62*/ Client62::consts::MAP_INSPECT_SIZE, +/*Titanium*/ Titanium::consts::MAP_INSPECT_SIZE, +/*SoF*/ SoF::consts::MAP_INSPECT_SIZE, +/*SoD*/ SoD::consts::MAP_INSPECT_SIZE, +/*Underfoot*/ Underfoot::consts::MAP_INSPECT_SIZE, +/*RoF*/ RoF::consts::MAP_INSPECT_SIZE, +/*RoF2*/ 0, + +/*NPC*/ NOT_USED, +/*Merc*/ NOT_USED, +/*Bot*/ NOT_USED, +/*Pet*/ NOT_USED + }, + { // local[MapRealEstate] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ EmuConstants::MAP_REAL_ESTATE_SIZE, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[MapViewMODPC] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ EmuConstants::MAP_VIEW_MOD_PC_SIZE, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[MapViewMODBank] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ EmuConstants::MAP_VIEW_MOD_BANK_SIZE, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[MapViewMODSharedBank] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ EmuConstants::MAP_VIEW_MOD_SHARED_BANK_SIZE, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[MapViewMODLimbo] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ EmuConstants::MAP_VIEW_MOD_LIMBO_SIZE, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[MapAltStorage] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ EmuConstants::MAP_ALT_STORAGE_SIZE, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[MapArchived] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ EmuConstants::MAP_ARCHIVED_SIZE, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[MapMail] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ EmuConstants::MAP_MAIL_SIZE, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[MapGuildTrophyTribute] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ EmuConstants::MAP_GUILD_TROPHY_TRIBUTE_SIZE, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[MapKrono] +/*Unknown*/ NOT_USED, +/*62*/ NOT_USED, +/*Titanium*/ NOT_USED, +/*SoF*/ NOT_USED, +/*SoD*/ NOT_USED, +/*Underfoot*/ NOT_USED, +/*RoF*/ EmuConstants::MAP_KRONO_SIZE, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[MapOther] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ EmuConstants::MAP_OTHER_SIZE, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + } + }; + + if ((uint16)map < _MapCount) + return local[map][ValidateMobVersion(version)]; + + return NOT_USED; +} + +uint64 EQLimits::PossessionsBitmask(uint32 version) { + // these are for the new inventory system (RoF)..not the current (Ti) one... + // 0x0000000000200000 is SlotPowerSource (SoF+) + // 0x0000000080000000 is SlotGeneral9 (RoF+) + // 0x0000000100000000 is SlotGeneral10 (RoF+) + + static const uint64 local[_EmuClientCount] = { +/*Unknown*/ NOT_USED, +/*62*/ 0x000000027FDFFFFF, +/*Titanium*/ 0x000000027FDFFFFF, +/*SoF*/ 0x000000027FFFFFFF, +/*SoD*/ 0x000000027FFFFFFF, +/*Underfoot*/ 0x000000027FFFFFFF, +/*RoF*/ 0x00000003FFFFFFFF, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }; + + return NOT_USED; + //return local[ValidateMobVersion(version)]; +} + +uint64 EQLimits::EquipmentBitmask(uint32 version) { + static const uint64 local[_EmuClientCount] = { +/*Unknown*/ NOT_USED, +/*62*/ 0x00000000005FFFFF, +/*Titanium*/ 0x00000000005FFFFF, +/*SoF*/ 0x00000000007FFFFF, +/*SoD*/ 0x00000000007FFFFF, +/*Underfoot*/ 0x00000000007FFFFF, +/*RoF*/ 0x00000000007FFFFF, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }; + + return NOT_USED; + //return local[ValidateMobVersion(version)]; +} + +uint64 EQLimits::GeneralBitmask(uint32 version) { + static const uint64 local[_EmuClientCount] = { +/*Unknown*/ NOT_USED, +/*62*/ 0x000000007F800000, +/*Titanium*/ 0x000000007F800000, +/*SoF*/ 0x000000007F800000, +/*SoD*/ 0x000000007F800000, +/*Underfoot*/ 0x000000007F800000, +/*RoF*/ 0x00000001FF800000, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }; + + return NOT_USED; + //return local[ValidateMobVersion(version)]; +} + +uint64 EQLimits::CursorBitmask(uint32 version) { + static const uint64 local[_EmuClientCount] = { +/*Unknown*/ NOT_USED, +/*62*/ 0x0000000200000000, +/*Titanium*/ 0x0000000200000000, +/*SoF*/ 0x0000000200000000, +/*SoD*/ 0x0000000200000000, +/*Underfoot*/ 0x0000000200000000, +/*RoF*/ 0x0000000200000000, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }; + + return NOT_USED; + //return local[ValidateMobVersion(version)]; +} + +bool EQLimits::AllowsEmptyBagInBag(uint32 version) { + static const bool local[_EmuClientCount] = { +/*Unknown*/ false, +/*62*/ Client62::limits::ALLOWS_EMPTY_BAG_IN_BAG, +/*Titanium*/ Titanium::limits::ALLOWS_EMPTY_BAG_IN_BAG, +/*SoF*/ SoF::limits::ALLOWS_EMPTY_BAG_IN_BAG, +/*SoD*/ SoD::limits::ALLOWS_EMPTY_BAG_IN_BAG, +/*Underfoot*/ Underfoot::limits::ALLOWS_EMPTY_BAG_IN_BAG, +/*RoF*/ RoF::limits::ALLOWS_EMPTY_BAG_IN_BAG, +/*RoF2*/ false, + +/*NPC*/ false, +/*Merc*/ false, +/*Bot*/ false, +/*Pet*/ false + }; + + return false; // not implemented + //return local[ValidateMobVersion(version)]; +} + +// items +uint16 EQLimits::ItemCommonSize(uint32 version) { + static const uint16 local[_EmuClientCount] = { +/*Unknown*/ NOT_USED, +/*62*/ EmuConstants::ITEM_COMMON_SIZE, +/*Titanium*/ EmuConstants::ITEM_COMMON_SIZE, +/*SoF*/ EmuConstants::ITEM_COMMON_SIZE, +/*SoD*/ EmuConstants::ITEM_COMMON_SIZE, +/*Underfoot*/ EmuConstants::ITEM_COMMON_SIZE, +/*RoF*/ EmuConstants::ITEM_COMMON_SIZE, +/*RoF2*/ 0, + +/*NPC*/ EmuConstants::ITEM_COMMON_SIZE, +/*Merc*/ EmuConstants::ITEM_COMMON_SIZE, +/*Bot*/ EmuConstants::ITEM_COMMON_SIZE, +/*Pet*/ EmuConstants::ITEM_COMMON_SIZE + }; + + return local[ValidateMobVersion(version)]; +} + +uint16 EQLimits::ItemContainerSize(uint32 version) { + static const uint16 local[_EmuClientCount] = { +/*Unknown*/ NOT_USED, +/*62*/ EmuConstants::ITEM_CONTAINER_SIZE, +/*Titanium*/ EmuConstants::ITEM_CONTAINER_SIZE, +/*SoF*/ EmuConstants::ITEM_CONTAINER_SIZE, +/*SoD*/ EmuConstants::ITEM_CONTAINER_SIZE, +/*Underfoot*/ EmuConstants::ITEM_CONTAINER_SIZE, +/*RoF*/ EmuConstants::ITEM_CONTAINER_SIZE, +/*RoF2*/ 0, + +/*NPC*/ EmuConstants::ITEM_CONTAINER_SIZE, +/*Merc*/ EmuConstants::ITEM_CONTAINER_SIZE, +/*Bot*/ EmuConstants::ITEM_CONTAINER_SIZE, +/*Pet*/ EmuConstants::ITEM_CONTAINER_SIZE + }; + + return local[ValidateMobVersion(version)]; +} + +bool EQLimits::CoinHasWeight(uint32 version) { + static const bool local[_EmuClientCount] = { +/*Unknown*/ true, +/*62*/ Client62::limits::COIN_HAS_WEIGHT, +/*Titanium*/ Titanium::limits::COIN_HAS_WEIGHT, +/*SoF*/ SoF::limits::COIN_HAS_WEIGHT, +/*SoD*/ SoD::limits::COIN_HAS_WEIGHT, +/*Underfoot*/ Underfoot::limits::COIN_HAS_WEIGHT, +/*RoF*/ RoF::limits::COIN_HAS_WEIGHT, +/*RoF2*/ true, + +/*NPC*/ true, +/*Merc*/ true, +/*Bot*/ true, +/*Pet*/ true + }; + + return local[ValidateMobVersion(version)]; +} + +uint32 EQLimits::BandoliersCount(uint32 version) { + static const uint32 local[_EmuClientCount] = { +/*Unknown*/ NOT_USED, +/*62*/ EmuConstants::BANDOLIERS_COUNT, +/*Titanium*/ EmuConstants::BANDOLIERS_COUNT, +/*SoF*/ EmuConstants::BANDOLIERS_COUNT, +/*SoD*/ EmuConstants::BANDOLIERS_COUNT, +/*Underfoot*/ EmuConstants::BANDOLIERS_COUNT, +/*RoF*/ EmuConstants::BANDOLIERS_COUNT, +/*RoF2*/ 0, + +/*NPC*/ NOT_USED, +/*Merc*/ NOT_USED, +/*Bot*/ NOT_USED, +/*Pet*/ NOT_USED + }; + + return local[ValidateMobVersion(version)]; +} + +uint32 EQLimits::BandolierSize(uint32 version) { + static const uint32 local[_EmuClientCount] = { +/*Unknown*/ NOT_USED, +/*62*/ EmuConstants::BANDOLIER_SIZE, +/*Titanium*/ EmuConstants::BANDOLIER_SIZE, +/*SoF*/ EmuConstants::BANDOLIER_SIZE, +/*SoD*/ EmuConstants::BANDOLIER_SIZE, +/*Underfoot*/ EmuConstants::BANDOLIER_SIZE, +/*RoF*/ EmuConstants::BANDOLIER_SIZE, +/*RoF2*/ 0, + +/*NPC*/ NOT_USED, +/*Merc*/ NOT_USED, +/*Bot*/ NOT_USED, +/*Pet*/ NOT_USED + }; + + return local[ValidateMobVersion(version)]; +} + +uint32 EQLimits::PotionBeltSize(uint32 version) { + static const uint32 local[_EmuClientCount] = { +/*Unknown*/ NOT_USED, +/*62*/ EmuConstants::POTION_BELT_SIZE, +/*Titanium*/ EmuConstants::POTION_BELT_SIZE, +/*SoF*/ EmuConstants::POTION_BELT_SIZE, +/*SoD*/ EmuConstants::POTION_BELT_SIZE, +/*Underfoot*/ EmuConstants::POTION_BELT_SIZE, +/*RoF*/ EmuConstants::POTION_BELT_SIZE, +/*RoF2*/ 0, + +/*NPC*/ NOT_USED, +/*Merc*/ NOT_USED, +/*Bot*/ NOT_USED, +/*Pet*/ NOT_USED + }; + + return local[ValidateMobVersion(version)]; +} From 454f2520c3ff37f9c8448ada1e1db4930dd69eb1 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 1 Aug 2014 23:35:35 -0400 Subject: [PATCH 251/288] Support for spells_new field npc_no_los (simply skips the LOS check for that spell despite name, no reason to hard code it only for NPC). --- common/shareddb.cpp | 3 +++ common/spdat.h | 7 ++++--- zone/spells.cpp | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 7dd4a6fa7..b93b57710 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1720,6 +1720,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { sp[tempid].descnum = atoi(row[155]); sp[tempid].effectdescnum = atoi(row[157]); + sp[tempid].npc_no_los = atoi(row[159]) != 0; sp[tempid].reflectable = atoi(row[161]) != 0; sp[tempid].bonushate=atoi(row[162]); @@ -1750,6 +1751,8 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { sp[tempid].AllowRest = atoi(row[212]) != 0; sp[tempid].NotOutofCombat = atoi(row[213]) != 0; sp[tempid].NotInCombat = atoi(row[214]) != 0; + sp[tempid].aemaxtargets = atoi(row[218]); + sp[tempid].maxtargets = atoi(row[219]); sp[tempid].persistdeath = atoi(row[224]) != 0; sp[tempid].DamageShieldType = 0; } diff --git a/common/spdat.h b/common/spdat.h index 69082d305..927550fc6 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -690,7 +690,7 @@ struct SPDat_Spell_Struct /* 156 */ //int typedescnum; // eqstr of type description /* 157 */ int effectdescnum; // eqstr of effect description /* 158 */ //Category Desc ID 3 -/* 159 */ //bool npc_no_los; +/* 159 */ bool npc_no_los; /* 161 */ bool reflectable; /* 162 */ int bonushate; /* 163 */ @@ -732,8 +732,9 @@ struct SPDat_Spell_Struct /* 212 */ bool AllowRest; /* 213 */ bool NotOutofCombat; //Fail if cast out of combat /* 214 */ bool NotInCombat; //Fail if cast in combat -/* 215 - 218 */ -/* 219 */ //int maxtargets; // is used for beam and ring spells for target # limits (not implemented) +/* 215 - 217 */ +/* 219 */ int aemaxtargets; // +/* 219 */ int maxtargets; // is used for beam and ring spells for target # limits (not implemented) /* 220 - 223 */ /* 224 */ bool persistdeath; // buff doesn't get stripped on death /* 225 - 236 */ // Not in DB diff --git a/zone/spells.cpp b/zone/spells.cpp index fac7e2c59..305156b63 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1833,7 +1833,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 } // check line of sight to target if it's a detrimental spell - if(spell_target && IsDetrimentalSpell(spell_id) && !CheckLosFN(spell_target) && !IsHarmonySpell(spell_id) && spells[spell_id].targettype != ST_TargetOptional) + if(!spells[spell_id].npc_no_los && spell_target && IsDetrimentalSpell(spell_id) && !CheckLosFN(spell_target) && !IsHarmonySpell(spell_id) && spells[spell_id].targettype != ST_TargetOptional) { mlog(SPELLS__CASTING, "Spell %d: cannot see target %s", spell_target->GetName()); Message_StringID(13,CANT_SEE_TARGET); From b65d3c85b668f85370a3db625b8a6a852ecc5f6e Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sat, 2 Aug 2014 10:42:11 -0400 Subject: [PATCH 252/288] Implemented support for spells_new fields InCombat, OutofCombat Required SQL to rename and add new fields to spells_new table. --- changelog.txt | 9 +++++++++ common/shareddb.cpp | 12 ++++++++++-- common/spdat.h | 27 ++++++++++++++++---------- zone/StringIDs.h | 4 ++++ zone/spells.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 86 insertions(+), 12 deletions(-) diff --git a/changelog.txt b/changelog.txt index 464669fd5..2847b92e6 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,14 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 08/02/2014 == +Kayen: Implemented spell_news fields +- npc_no_los (check if LOS is required for spells) +- InCombat, OutofCombat - Used together to restrict spells to only be cast while +in/out of combat (beneficial) or if target is in/out of combat (detrimental). +Many new fields added and defined for future development. + +Required SQL: utils/sql/git/required/2014_08_02_spells_new.sql + == 07/31/2014 == Uleat: More inventory slot constant conversions. This should be the bulk of everything..but, due to the size of the server code, there may be some hidden ones. (client_packet.cpp and the client translators still need a thorough review.) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index b93b57710..585576f17 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1726,6 +1726,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { sp[tempid].EndurCost=atoi(row[166]); sp[tempid].EndurTimerIndex=atoi(row[167]); + sp[tempid].IsDisciplineBuff = atoi(row[168]) != 0; sp[tempid].HateAdded=atoi(row[173]); sp[tempid].EndurUpkeep=atoi(row[174]); sp[tempid].numhitstype = atoi(row[175]); @@ -1745,15 +1746,22 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { sp[tempid].directional_end = (float)atoi(row[195]); sp[tempid].not_extendable = atoi(row[197]) != 0; sp[tempid].suspendable = atoi(row[200]) != 0; + sp[tempid].viral_range = atoi(row[201]); sp[tempid].spellgroup=atoi(row[207]); + sp[tempid].rank = atoi(row[208]); sp[tempid].powerful_flag=atoi(row[209]); sp[tempid].CastRestriction = atoi(row[211]); sp[tempid].AllowRest = atoi(row[212]) != 0; - sp[tempid].NotOutofCombat = atoi(row[213]) != 0; - sp[tempid].NotInCombat = atoi(row[214]) != 0; + sp[tempid].InCombat = atoi(row[213]) != 0; + sp[tempid].OutofCombat = atoi(row[214]) != 0; sp[tempid].aemaxtargets = atoi(row[218]); sp[tempid].maxtargets = atoi(row[219]); sp[tempid].persistdeath = atoi(row[224]) != 0; + sp[tempid].min_dist = atof(row[227]); + sp[tempid].min_dist_mod = atof(row[228]); + sp[tempid].max_dist = atof(row[229]); + sp[tempid].max_dist_mod = atof(row[230]); + sp[tempid].min_range = atoi(row[231]); sp[tempid].DamageShieldType = 0; } mysql_free_result(result); diff --git a/common/spdat.h b/common/spdat.h index 927550fc6..510817121 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -697,8 +697,8 @@ struct SPDat_Spell_Struct /* 164 */ // for most spells this appears to mimic ResistDiff /* 166 */ int EndurCost; /* 167 */ int8 EndurTimerIndex; -/* 168 */ //int IsDisciplineBuff; //Will goto the combat window when cast -/* 169 */ +/* 168 */ bool IsDisciplineBuff; //Will goto the combat window when cast +/* 169 - 172*/ //These are zero for ALL spells /* 173 */ int HateAdded; /* 174 */ int EndurUpkeep; /* 175 */ int numhitstype; // defines which type of behavior will tick down the numhit counter. @@ -721,23 +721,30 @@ struct SPDat_Spell_Struct /* 197 */ bool not_extendable; /* 198- 199 */ /* 200 */ bool suspendable; // buff is suspended in suspended buff zones -/* 201 - 202 */ +/* 201 */ int viral_range; +/* 202 */ /* 203 */ //int songcap; // individual song cap (how live currently does it, not implemented) /* 204 - 206 */ /* 207 */ int spellgroup; -/* 208 */ // int rank - increments AA effects with same name +/* 208 */ int rank; //increments AA effects with same name /* 209 */ int powerful_flag; // Need more investigation to figure out what to call this, for now we know -1 makes charm spells not break before their duration is complete, it does alot more though /* 210 */ // bool DurationFrozen; ??? /* 211 */ int CastRestriction; //Various restriction categories for spells most seem targetable race related but have also seen others for instance only castable if target hp 20% or lower or only if target out of combat /* 212 */ bool AllowRest; -/* 213 */ bool NotOutofCombat; //Fail if cast out of combat -/* 214 */ bool NotInCombat; //Fail if cast in combat +/* 213 */ bool InCombat; //Allow spell if target is in combat +/* 214 */ bool OutofCombat; //Allow spell if target is out of combat /* 215 - 217 */ -/* 219 */ int aemaxtargets; // -/* 219 */ int maxtargets; // is used for beam and ring spells for target # limits (not implemented) -/* 220 - 223 */ +/* 218 */ int aemaxtargets; //Is used for various AE effects +/* 219 */ int maxtargets; //Is used for beam and ring spells for target # limits (not implemented) +/* 220 - 223 */ /* 224 */ bool persistdeath; // buff doesn't get stripped on death -/* 225 - 236 */ // Not in DB +/* 225 - 226 */ +/* 227 */ float min_dist; //spell power modified by distance from caster (Min Distance) +/* 228 */ float min_dist_mod; //spell power modified by distance from caster (Modifier at Min Distance) +/* 229 */ float max_dist; //spell power modified by distance from caster (Max Distance) +/* 230 */ float max_dist_mod; //spell power modified by distance from caster (Modifier at Max Distance) +/* 231 */ int min_range; //Min casting range +/* 232 - 236 */ uint8 DamageShieldType; // This field does not exist in spells_us.txt }; diff --git a/zone/StringIDs.h b/zone/StringIDs.h index 9a222d276..5e5d16bb2 100644 --- a/zone/StringIDs.h +++ b/zone/StringIDs.h @@ -316,6 +316,10 @@ #define PET_NOT_FOCUSING 9263 //No longer focusing on one target, Master. #define PET_NOT_CASTING 9264 //Not casting spells, Master. #define PET_CASTING 9291 //Casting spells normally, Master. +#define NO_CAST_IN_COMBAT 9190 //You can not cast this spell while in combat. +#define NO_CAST_OUT_OF_COMBAT 9191 //You can not cast this spell while out of combat. +#define NO_ABILITY_IN_COMBAT 9192 //You can not use this ability while in combat. +#define NO_ABILITY_OUT_OF_COMBAT 9194 //You can not use this ability while out of combat. #define AE_RAMPAGE 11015 //%1 goes on a WILD RAMPAGE! #define FACE_ACCEPTED 12028 //Facial features accepted. #define SPELL_LEVEL_TO_LOW 12048 //You will have to achieve level %1 before you can scribe the %2. diff --git a/zone/spells.cpp b/zone/spells.cpp index 305156b63..6757a7ba6 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1384,6 +1384,52 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce return false; } + //Must be out of combat. (If Beneficial checks casters combat state, Deterimental checks targets) + if (!spells[spell_id].InCombat && spells[spell_id].OutofCombat){ + if (IsDetrimentalSpell(spell_id)) { + if ( (spell_target->IsNPC() && spell_target->IsEngaged()) || + (spell_target->IsClient() && spell_target->CastToClient()->GetAggroCount())){ + Message_StringID(13,SPELL_NO_EFFECT); //Unsure correct string + return false; + } + } + + else if (IsBeneficialSpell(spell_id)) { + if ( (IsNPC() && IsEngaged()) || + (IsClient() && CastToClient()->GetAggroCount())){ + if (IsDiscipline(spell_id)) + Message_StringID(13,NO_ABILITY_IN_COMBAT); + else + Message_StringID(13,NO_CAST_IN_COMBAT); + + return false; + } + } + } + + //Must be in combat. (If Beneficial checks casters combat state, Deterimental checks targets) + else if (spells[spell_id].InCombat && !spells[spell_id].OutofCombat){ + if (IsDetrimentalSpell(spell_id)) { + if ( (spell_target->IsNPC() && !spell_target->IsEngaged()) || + (spell_target->IsClient() && !spell_target->CastToClient()->GetAggroCount())){ + Message_StringID(13,SPELL_NO_EFFECT); //Unsure correct string + return false; + } + } + + else if (IsBeneficialSpell(spell_id)) { + if ( (IsNPC() && !IsEngaged()) || + (IsClient() && !CastToClient()->GetAggroCount())){ + if (IsDiscipline(spell_id)) + Message_StringID(13,NO_ABILITY_OUT_OF_COMBAT); + else + Message_StringID(13,NO_CAST_OUT_OF_COMBAT); + + return false; + } + } + } + switch (targetType) { // single target spells From 9c92c5dbe4af5a57a7b4af82c8768bcf2a688a5b Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sat, 2 Aug 2014 10:43:48 -0400 Subject: [PATCH 253/288] SQL --- .../sql/git/required/2014_08_02_spells_new.sql | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 utils/sql/git/required/2014_08_02_spells_new.sql diff --git a/utils/sql/git/required/2014_08_02_spells_new.sql b/utils/sql/git/required/2014_08_02_spells_new.sql new file mode 100644 index 000000000..f4e74158a --- /dev/null +++ b/utils/sql/git/required/2014_08_02_spells_new.sql @@ -0,0 +1,18 @@ +-- spells new talbe update +ALTER TABLE `spells_new` CHANGE `NotOutofCombat` `InCombat` INT(11) NOT NULL DEFAULT '0'; +ALTER TABLE `spells_new` CHANGE `NotInCombat` `OutofCombat` INT(11) NOT NULL DEFAULT '0'; +ALTER TABLE `spells_new` CHANGE `field201` `viral_range` INT(11) NOT NULL DEFAULT '0'; +ALTER TABLE `spells_new` CHANGE `field218` `aemaxtargets` INT(11) NOT NULL DEFAULT '0'; +ALTER TABLE `spells_new` ADD `field225` int( 11 ) NOT NULL DEFAULT '0' AFTER `persistdeath`; +ALTER TABLE `spells_new` ADD `field226` int( 11 ) NOT NULL DEFAULT '0' AFTER `field225`; +ALTER TABLE `spells_new` ADD `min_dist` float( 0 ) NOT NULL DEFAULT '0' AFTER `field226`; +ALTER TABLE `spells_new` ADD `min_dist_mod` float( 0 ) NOT NULL DEFAULT '0' AFTER `min_dist`; +ALTER TABLE `spells_new` ADD `max_dist` float( 0 ) NOT NULL DEFAULT '0' AFTER `min_dist_mod`; +ALTER TABLE `spells_new` ADD `max_dist_mod` float( 0 ) NOT NULL DEFAULT '0' AFTER `max_dist`; +ALTER TABLE `spells_new` ADD `min_range` int( 11 ) NOT NULL DEFAULT '0' AFTER `max_dist_mod`; +ALTER TABLE `spells_new` ADD `field232` int( 11 ) NOT NULL DEFAULT '0' AFTER `min_range`; +ALTER TABLE `spells_new` ADD `field233` int( 11 ) NOT NULL DEFAULT '0' AFTER `field232`; +ALTER TABLE `spells_new` ADD `field234` int( 11 ) NOT NULL DEFAULT '0' AFTER `field233`; +ALTER TABLE `spells_new` ADD `field235` int( 11 ) NOT NULL DEFAULT '0' AFTER `field234`; +ALTER TABLE `spells_new` ADD `field236` int( 11 ) NOT NULL DEFAULT '0' AFTER `field235`; + From 52d92b71814e6e364e0d5ada187c71f53238ab9c Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sat, 2 Aug 2014 21:10:44 -0400 Subject: [PATCH 254/288] Implemented broad support for fields min_dist, min_dist_mod, max_dist, max_dist_mod - Scales spell power based on targets distance from caster. This implemented in a broad way to function with spells that would make sense to scale. Some work will still be needed on this. Be aware if making custom spells not everything will work and certain effects just should not be included (use common sense). --- changelog.txt | 4 +++- common/spdat.cpp | 9 +++++++++ common/spdat.h | 1 + zone/effects.cpp | 7 ++++++- zone/groups.cpp | 1 + zone/hate_list.cpp | 6 +++++- zone/mob.cpp | 1 + zone/mob.h | 4 ++++ zone/spell_effects.cpp | 31 ++++++++++++++++++++++++++++++- zone/spells.cpp | 10 ++++++++-- 10 files changed, 68 insertions(+), 6 deletions(-) diff --git a/changelog.txt b/changelog.txt index 2847b92e6..85fa4ecb5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -5,7 +5,9 @@ Kayen: Implemented spell_news fields - npc_no_los (check if LOS is required for spells) - InCombat, OutofCombat - Used together to restrict spells to only be cast while in/out of combat (beneficial) or if target is in/out of combat (detrimental). -Many new fields added and defined for future development. +-min_dist, min_dist_mod, max_dist, max_dist_mod - Scales spell power based on targets distance from caster. +*This will require further work to fully implement but will work with 90% of live spells as is. +*If making custom spells do not include effects that can't be scaled (like a spell trigger) Required SQL: utils/sql/git/required/2014_08_02_spells_new.sql diff --git a/common/spdat.cpp b/common/spdat.cpp index 75f1e9b88..8e93f4e1f 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -1040,6 +1040,15 @@ bool IsCastonFadeDurationSpell(uint16 spell_id) return false; } +bool IsPowerDistModSpell(uint16 spell_id) +{ + if (IsValidSpell(spell_id) && + (spells[spell_id].max_dist_mod || spells[spell_id].min_dist_mod) && spells[spell_id].max_dist > spells[spell_id].min_dist) + return true; + + return false; +} + uint32 GetPartialMeleeRuneReduction(uint32 spell_id) { for (int i = 0; i < EFFECT_COUNT; ++i) diff --git a/common/spdat.h b/common/spdat.h index 510817121..ec068585c 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -845,6 +845,7 @@ bool IsPersistDeathSpell(uint16 spell_id); bool IsSuspendableSpell(uint16 spell_id); uint32 GetMorphTrigger(uint32 spell_id); bool IsCastonFadeDurationSpell(uint16 spell_id); +bool IsPowerDistModSpell(uint16 spell_id); uint32 GetPartialMeleeRuneReduction(uint32 spell_id); uint32 GetPartialMagicRuneReduction(uint32 spell_id); uint32 GetPartialMeleeRuneAmount(uint32 spell_id); diff --git a/zone/effects.cpp b/zone/effects.cpp index c298974db..27cccd0a9 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -740,6 +740,7 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ float dist = caster->GetAOERange(spell_id); float dist2 = dist * dist; + float dist_targ = 0; bool bad = IsDetrimentalSpell(spell_id); bool isnpc = caster->IsNPC(); @@ -755,7 +756,9 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ continue; if (curmob == caster && !affect_caster) //watch for caster too continue; - if (center->DistNoRoot(*curmob) > dist2) //make sure they are in range + + dist_targ = center->DistNoRoot(*curmob); + if (dist_targ > dist2) //make sure they are in range continue; if (isnpc && curmob->IsNPC()) { //check npc->npc casting FACTION_VALUE f = curmob->GetReverseFactionCon(caster); @@ -786,6 +789,8 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ continue; } + curmob->CalcSpellPowerDistanceMod(spell_id, dist_targ); + //if we get here... cast the spell. if (IsTargetableAESpell(spell_id) && bad) { if (iCounter < MAX_TARGETS_ALLOWED) { diff --git a/zone/groups.cpp b/zone/groups.cpp index 6aee5f38b..c9f6e9127 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -674,6 +674,7 @@ void Group::CastGroupSpell(Mob* caster, uint16 spell_id) { { distance = caster->DistNoRoot(*members[z]); if(distance <= range2) { + members[z]->CalcSpellPowerDistanceMod(spell_id, distance); caster->SpellOnTarget(spell_id, members[z]); #ifdef GROUP_BUFF_PETS if(members[z]->GetPet() && members[z]->HasPetAffinity() && !members[z]->GetPet()->IsCharmed()) diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index bb39d224a..f3de52544 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -567,20 +567,24 @@ void HateList::SpellCast(Mob *caster, uint32 spell_id, float range) //So keep a list of entity ids and look up after std::list id_list; range = range * range; + float dist_targ = 0; auto iterator = list.begin(); while (iterator != list.end()) { tHateEntry *h = (*iterator); if(range > 0) { - if(caster->DistNoRoot(*h->ent) <= range) + dist_targ = caster->DistNoRoot(*h->ent); + if(dist_targ <= range) { id_list.push_back(h->ent->GetID()); + h->ent->CalcSpellPowerDistanceMod(spell_id, dist_targ); } } else { id_list.push_back(h->ent->GetID()); + h->ent->CalcSpellPowerDistanceMod(spell_id, 0, caster); } ++iterator; } diff --git a/zone/mob.cpp b/zone/mob.cpp index a55390050..24b691e36 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -182,6 +182,7 @@ Mob::Mob(const char* in_name, has_numhits = false; has_MGB = false; has_ProjectIllusion = false; + SpellPowerDistanceMod = 0; if(in_aa_title>0) aa_title = in_aa_title; diff --git a/zone/mob.h b/zone/mob.h index 1793e0864..15f1728ec 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -615,6 +615,9 @@ public: bool ImprovedTaunt(); bool TryRootFadeByDamage(int buffslot, Mob* attacker); int16 GetSlowMitigation() const {return slow_mitigation;} + void CalcSpellPowerDistanceMod(uint16 spell_id, float range, Mob* caster = nullptr); + inline int16 GetSpellPowerDistanceMod() const { return SpellPowerDistanceMod; }; + inline void SetSpellPowerDistanceMod(int16 value) { SpellPowerDistanceMod = value; }; void ModSkillDmgTaken(SkillUseTypes skill_num, int value); int16 GetModSkillDmgTaken(const SkillUseTypes skill_num); @@ -1114,6 +1117,7 @@ protected: bool has_numhits; bool has_MGB; bool has_ProjectIllusion; + int16 SpellPowerDistanceMod; // Bind wound Timer bindwound_timer; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 0ee88a154..864bf004c 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -186,6 +186,12 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) buffs[buffslot].numhits = numhit; } + bool _IsPowerDistModSpell = false; + if (IsPowerDistModSpell(spell_id)) + _IsPowerDistModSpell = true; + else + SetSpellPowerDistanceMod(0); + // iterate through the effects in the spell for (i = 0; i < EFFECT_COUNT; i++) { @@ -198,6 +204,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) if(spell_id == SPELL_LAY_ON_HANDS && caster && caster->GetAA(aaImprovedLayOnHands)) effect_value = GetMaxHP(); + if (_IsPowerDistModSpell) + effect_value += (effect_value*(GetSpellPowerDistanceMod()/100)/100); + #ifdef SPELL_EFFECT_SPAM effect_desc[0] = 0; #endif @@ -6444,4 +6453,24 @@ bool Mob::CheckSpellCategory(uint16 spell_id, int category_id, int effect_id){ return false; } - \ No newline at end of file + +void Mob::CalcSpellPowerDistanceMod(uint16 spell_id, float range, Mob* caster) +{ + if (IsPowerDistModSpell(spell_id)){ + + float distance = 0; + + if (caster && !range) + distance = caster->CalculateDistance(GetX(), GetY(), GetZ()); + else + distance = sqrt(range); + + float dm_range = spells[spell_id].max_dist - spells[spell_id].min_dist; + float dm_mod_interval = spells[spell_id].max_dist_mod - spells[spell_id].min_dist_mod; + float dist_from_min = distance - spells[spell_id].min_dist; + float mod = spells[spell_id].min_dist_mod + (dist_from_min * (dm_mod_interval/dm_range)); + mod *= 100.0f; + + SetSpellPowerDistanceMod(static_cast(mod)); + } +} \ No newline at end of file diff --git a/zone/spells.cpp b/zone/spells.cpp index 6757a7ba6..f5bd8f09d 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1915,6 +1915,8 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 Message_StringID(13, TARGET_OUT_OF_RANGE); return(false); } + + spell_target->CalcSpellPowerDistanceMod(spell_id, dist2); } // @@ -2114,16 +2116,20 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 if((heading_to_target >= angle_start && heading_to_target <= 360.0f) || (heading_to_target >= 0.0f && heading_to_target <= angle_end)) { - if(CheckLosFN(spell_target)) + if(CheckLosFN((*iter)) || spells[spell_id].npc_no_los){ + (*iter)->CalcSpellPowerDistanceMod(spell_id, 0, this); SpellOnTarget(spell_id, spell_target, false, true, resist_adjust); + } } } else { if(heading_to_target >= angle_start && heading_to_target <= angle_end) { - if(CheckLosFN((*iter))) + if(CheckLosFN((*iter)) || spells[spell_id].npc_no_los){ + (*iter)->CalcSpellPowerDistanceMod(spell_id, 0, this); SpellOnTarget(spell_id, (*iter), false, true, resist_adjust); + } } } ++iter; From ef982b9ce236d83ebe5a5e576e2eadbd9ddb3d85 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 3 Aug 2014 08:21:47 -0400 Subject: [PATCH 255/288] Implemented 'min_range' field, sets a min range that you must be away from target for spell to land. --- changelog.txt | 1 + common/shareddb.cpp | 6 +++--- common/spdat.h | 2 +- zone/StringIDs.h | 1 + 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/changelog.txt b/changelog.txt index 85fa4ecb5..16d63a05e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -8,6 +8,7 @@ in/out of combat (beneficial) or if target is in/out of combat (detrimental). -min_dist, min_dist_mod, max_dist, max_dist_mod - Scales spell power based on targets distance from caster. *This will require further work to fully implement but will work with 90% of live spells as is. *If making custom spells do not include effects that can't be scaled (like a spell trigger) +- min_rage sets minimum distance range that must be away from target. Required SQL: utils/sql/git/required/2014_08_02_spells_new.sql diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 585576f17..a64fef404 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1742,8 +1742,8 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { sp[tempid].viral_targets = atoi(row[191]); sp[tempid].viral_timer = atoi(row[192]); sp[tempid].NimbusEffect = atoi(row[193]); - sp[tempid].directional_start = (float)atoi(row[194]); - sp[tempid].directional_end = (float)atoi(row[195]); + sp[tempid].directional_start = static_cast(atoi(row[194])); + sp[tempid].directional_end = static_cast(atoi(row[195])); sp[tempid].not_extendable = atoi(row[197]) != 0; sp[tempid].suspendable = atoi(row[200]) != 0; sp[tempid].viral_range = atoi(row[201]); @@ -1761,7 +1761,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { sp[tempid].min_dist_mod = atof(row[228]); sp[tempid].max_dist = atof(row[229]); sp[tempid].max_dist_mod = atof(row[230]); - sp[tempid].min_range = atoi(row[231]); + sp[tempid].min_range = static_cast(atoi(row[231])); sp[tempid].DamageShieldType = 0; } mysql_free_result(result); diff --git a/common/spdat.h b/common/spdat.h index ec068585c..aaf29e61a 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -743,7 +743,7 @@ struct SPDat_Spell_Struct /* 228 */ float min_dist_mod; //spell power modified by distance from caster (Modifier at Min Distance) /* 229 */ float max_dist; //spell power modified by distance from caster (Max Distance) /* 230 */ float max_dist_mod; //spell power modified by distance from caster (Modifier at Max Distance) -/* 231 */ int min_range; //Min casting range +/* 231 */ float min_range; //Min casting range /* 232 - 236 */ uint8 DamageShieldType; // This field does not exist in spells_us.txt }; diff --git a/zone/StringIDs.h b/zone/StringIDs.h index 5e5d16bb2..b1e13edca 100644 --- a/zone/StringIDs.h +++ b/zone/StringIDs.h @@ -249,6 +249,7 @@ #define CORPSEDRAG_BEGIN 4064 //You begin to drag %1. #define CORPSEDRAG_STOPALL 4065 //You stop dragging the corpses. #define CORPSEDRAG_STOP 4066 //You stop dragging the corpse. +#define TARGET_TOO_CLOSE 4602 //You are too close to your target. Get farther away. #define WHOALL_NO_RESULTS 5029 //There are no players in EverQuest that match those who filters. #define PETITION_NO_DELETE 5053 //You do not have a petition in the queue. #define PETITION_DELETED 5054 //Your petition was successfully deleted. From f3710856ad59e6e3c456a5d4429119b9f1f64fad Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 3 Aug 2014 16:04:55 -0400 Subject: [PATCH 256/288] min_range field --- zone/effects.cpp | 3 +++ zone/entity.cpp | 10 +++++----- zone/entity.h | 2 +- zone/groups.cpp | 3 ++- zone/hate_list.cpp | 3 ++- zone/spell_effects.cpp | 4 ++-- zone/spells.cpp | 9 ++++++++- 7 files changed, 23 insertions(+), 11 deletions(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index 27cccd0a9..1b1eeb2ea 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -740,6 +740,7 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ float dist = caster->GetAOERange(spell_id); float dist2 = dist * dist; + float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range; float dist_targ = 0; bool bad = IsDetrimentalSpell(spell_id); @@ -760,6 +761,8 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ dist_targ = center->DistNoRoot(*curmob); if (dist_targ > dist2) //make sure they are in range continue; + if (dist_targ < min_range2) //make sure they are in range + continue; if (isnpc && curmob->IsNPC()) { //check npc->npc casting FACTION_VALUE f = curmob->GetReverseFactionCon(caster); if (bad) { diff --git a/zone/entity.cpp b/zone/entity.cpp index 3d316585d..5ff19847f 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -4538,7 +4538,7 @@ Mob *EntityList::GetClosestMobByBodyType(Mob *sender, bodyType BodyType) return ClosestMob; } -void EntityList::GetTargetsForConeArea(Mob *start, uint32 radius, uint32 height, std::list &m_list) +void EntityList::GetTargetsForConeArea(Mob *start, float min_radius, float radius, float height, std::list &m_list) { auto it = mob_list.begin(); while (it != mob_list.end()) { @@ -4547,15 +4547,15 @@ void EntityList::GetTargetsForConeArea(Mob *start, uint32 radius, uint32 height, ++it; continue; } - int32 x_diff = ptr->GetX() - start->GetX(); - int32 y_diff = ptr->GetY() - start->GetY(); - int32 z_diff = ptr->GetZ() - start->GetZ(); + float x_diff = ptr->GetX() - start->GetX(); + float y_diff = ptr->GetY() - start->GetY(); + float z_diff = ptr->GetZ() - start->GetZ(); x_diff *= x_diff; y_diff *= y_diff; z_diff *= z_diff; - if ((x_diff + y_diff) <= (radius * radius)) + if ((x_diff + y_diff) <= (radius * radius) && (x_diff + y_diff) >= (min_radius * min_radius)) if(z_diff <= (height * height)) m_list.push_back(ptr); diff --git a/zone/entity.h b/zone/entity.h index 8b94b0e0a..c1ba0936c 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -406,7 +406,7 @@ public: void GetObjectList(std::list &o_list); void GetDoorsList(std::list &d_list); void GetSpawnList(std::list &d_list); - void GetTargetsForConeArea(Mob *start, uint32 radius, uint32 height, std::list &m_list); + void GetTargetsForConeArea(Mob *start, float min_radius, float radius, float height, std::list &m_list); void DepopAll(int NPCTypeID, bool StartSpawnTimer = true); diff --git a/zone/groups.cpp b/zone/groups.cpp index c9f6e9127..d948eb476 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -658,6 +658,7 @@ void Group::CastGroupSpell(Mob* caster, uint16 spell_id) { range = caster->GetAOERange(spell_id); float range2 = range*range; + float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range; // caster->SpellOnTarget(spell_id, caster); @@ -673,7 +674,7 @@ void Group::CastGroupSpell(Mob* caster, uint16 spell_id) { else if(members[z] != nullptr) { distance = caster->DistNoRoot(*members[z]); - if(distance <= range2) { + if(distance <= range2 && distance >= min_range2) { members[z]->CalcSpellPowerDistanceMod(spell_id, distance); caster->SpellOnTarget(spell_id, members[z]); #ifdef GROUP_BUFF_PETS diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index f3de52544..1b585ca32 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -567,6 +567,7 @@ void HateList::SpellCast(Mob *caster, uint32 spell_id, float range) //So keep a list of entity ids and look up after std::list id_list; range = range * range; + float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range; float dist_targ = 0; auto iterator = list.begin(); while (iterator != list.end()) @@ -575,7 +576,7 @@ void HateList::SpellCast(Mob *caster, uint32 spell_id, float range) if(range > 0) { dist_targ = caster->DistNoRoot(*h->ent); - if(dist_targ <= range) + if(dist_targ <= range && dist_targ >= min_range2) { id_list.push_back(h->ent->GetID()); h->ent->CalcSpellPowerDistanceMod(spell_id, dist_targ); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 864bf004c..2312614bc 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -205,7 +205,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) effect_value = GetMaxHP(); if (_IsPowerDistModSpell) - effect_value += (effect_value*(GetSpellPowerDistanceMod()/100)/100); + effect_value = effect_value*(GetSpellPowerDistanceMod()/100); #ifdef SPELL_EFFECT_SPAM effect_desc[0] = 0; @@ -6471,6 +6471,6 @@ void Mob::CalcSpellPowerDistanceMod(uint16 spell_id, float range, Mob* caster) float mod = spells[spell_id].min_dist_mod + (dist_from_min * (dm_mod_interval/dm_range)); mod *= 100.0f; - SetSpellPowerDistanceMod(static_cast(mod)); + SetSpellPSetSpellPowerDistanceMod(static_cast(mod)); } } \ No newline at end of file diff --git a/zone/spells.cpp b/zone/spells.cpp index f5bd8f09d..ca6d80f6f 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1909,12 +1909,19 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 //casting a spell on somebody but ourself, make sure they are in range float dist2 = DistNoRoot(*spell_target); float range2 = range * range; + float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range; if(dist2 > range2) { //target is out of range. mlog(SPELLS__CASTING, "Spell %d: Spell target is out of range (squared: %f > %f)", spell_id, dist2, range2); Message_StringID(13, TARGET_OUT_OF_RANGE); return(false); } + else if (dist2 < min_range2){ + //target is too close range. + mlog(SPELLS__CASTING, "Spell %d: Spell target is too close (squared: %f < %f)", spell_id, dist2, min_range2); + Message_StringID(13, TARGET_TOO_CLOSE); + return(false); + } spell_target->CalcSpellPowerDistanceMod(spell_id, dist2); } @@ -2100,7 +2107,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 std::list targets_in_range; std::list::iterator iter; - entity_list.GetTargetsForConeArea(this, spells[spell_id].aoerange, spells[spell_id].aoerange / 2, targets_in_range); + entity_list.GetTargetsForConeArea(this, spells[spell_id].min_range, spells[spell_id].aoerange, spells[spell_id].aoerange / 2, targets_in_range); iter = targets_in_range.begin(); while(iter != targets_in_range.end()) { From 4b7fa0654c00b0fd4d30d182ca752db82ca20908 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 3 Aug 2014 16:32:36 -0400 Subject: [PATCH 257/288] fix --- zone/spell_effects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 2312614bc..dc4de2409 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -204,7 +204,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) if(spell_id == SPELL_LAY_ON_HANDS && caster && caster->GetAA(aaImprovedLayOnHands)) effect_value = GetMaxHP(); - if (_IsPowerDistModSpell) + if (_IsPowerDistModSpell && GetSpellPowerDistanceMod()) effect_value = effect_value*(GetSpellPowerDistanceMod()/100); #ifdef SPELL_EFFECT_SPAM From 92a1abbbee67ce6507c27be147edbcd821db3bdc Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 3 Aug 2014 16:36:44 -0400 Subject: [PATCH 258/288] fix --- zone/spell_effects.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index dc4de2409..078827b78 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -186,10 +186,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) buffs[buffslot].numhits = numhit; } - bool _IsPowerDistModSpell = false; - if (IsPowerDistModSpell(spell_id)) - _IsPowerDistModSpell = true; - else + if (!IsPowerDistModSpell(spell_id)) SetSpellPowerDistanceMod(0); // iterate through the effects in the spell @@ -204,7 +201,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) if(spell_id == SPELL_LAY_ON_HANDS && caster && caster->GetAA(aaImprovedLayOnHands)) effect_value = GetMaxHP(); - if (_IsPowerDistModSpell && GetSpellPowerDistanceMod()) + if (GetSpellPowerDistanceMod()) effect_value = effect_value*(GetSpellPowerDistanceMod()/100); #ifdef SPELL_EFFECT_SPAM From 13f3c13c0ed3b00ef071c5aa2b6be05ba92cf4b3 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 4 Aug 2014 21:28:56 -0400 Subject: [PATCH 259/288] Added a dev script for cross-referencing server-to-client opcodes --- utils/scripts/.gitignore | 1 + utils/scripts/opcode_handlers.py | 475 +++++++++++++++++++++++++++++++ 2 files changed, 476 insertions(+) create mode 100644 utils/scripts/.gitignore create mode 100644 utils/scripts/opcode_handlers.py diff --git a/utils/scripts/.gitignore b/utils/scripts/.gitignore new file mode 100644 index 000000000..eba9f59cb --- /dev/null +++ b/utils/scripts/.gitignore @@ -0,0 +1 @@ +opcode_handlers_output \ No newline at end of file diff --git a/utils/scripts/opcode_handlers.py b/utils/scripts/opcode_handlers.py new file mode 100644 index 000000000..cae5fdc5c --- /dev/null +++ b/utils/scripts/opcode_handlers.py @@ -0,0 +1,475 @@ +#! /usr/bin/env python +# untested on Linux + +# This script generates cross-references to show associated (handled) opcodes between the server and client. +# It will generate files for each client found and provide some basic information..such as opcode names and +# values, server handler and whether opcodes are translated on tx/rx. +# +# It's currently limited to the 'Zone' server..but, can be expounded upon to include other servers, clients +# and other criteria and features. + + +import os +#import pickle + +from time import time, ctime + + +VERBOSE = True # pipes relativistic information to the console window +DEBUG = False # setting this to 'True' will pipe more information to the console window than you would ever want! + +repopath = os.getcwd() +repopath = repopath[:-14] # '\utils\scripts' - because I'm lazy and don't want to do it the right way... + +clients = [ '6.2', 'Titanium', 'SoF', 'SoD', 'Underfoot', 'RoF' ] +servers = [ 'Login', 'World', 'Zone' ] + +clientops = {} +serverops = {} + +encodes = [] +decodes = [] + +handlers = {} +outstreams = {} + + +def main() : + print('Loading source data...') + + if not LoadServerOpcodes() : + print('Error! Could not load server opcodes') + return + + if not LoadClientOpcodes() : + print('Error! Could not load client opcodes') + return + + if not LoadClientTranslators() : + print('Error! Could not load client translators') + return + + if not LoadServerHandlers() : + print('Error! Could not load server handlers') + return + + print('Creating output streams...') + + if not CreateOutputDirectory() : + print('Output directory already exists or could not be created...') + #return # existing directory returns a failure..don't exit here..CreateOutputStreams() will catch makdir() problems + + if not CreateOutputStreams() : + print('Error! Could not open output files') + return + + print('Parsing opcode data...') + + if not ParseOpcodeData() : + print('Error! Could not parse opcode data') + return + + print('Destroying output streams...') + + if not DestroyOutputStreams() : + print('Error! Could not close output files') + return + + +def LoadServerOpcodes() : + # Server opcodes are auto-enumerated with a starting reference of '1' + try : + filename = '{0}{1}{2}'.format(repopath, '\common', '\emu_oplist.h') + + if VERBOSE or DEBUG : print(filename) + + with open(filename, 'r') as datafile : + value = 0 + serverops['Null'] = value + + while True : + begin = 0 + end = 0 + + dataline = datafile.readline() + + if not dataline : break + if not dataline[:1] == 'N' : continue + + while not dataline[begin:(begin + 1)] == '(' : + if begin >= len(dataline) : break + else : begin = begin + 1 + + end = begin + 1 + + while not dataline[(end - 1):end] == ')' : + if end >= len(dataline) : break + else : end = end + 1 + + begin = begin + 1 # adjust out the '(' + end = end - 1 # adjust out the ')' + + if begin >= end or begin >= len(dataline) : continue + if end >= len(dataline) : continue + + value = value + 1 + + serverops[dataline[begin:end]] = value + + if DEBUG : print('({0}, {1}) = {2}'.format('Server', dataline[begin:end], serverops[dataline[begin:end]])) + + datafile.close() + + except : return False + + return True + + +def LoadClientOpcodes() : + badclients = [] + + for client in clients : + try : + filename = '{0}{1}{2}{3}{4}'.format(repopath, '\utils\patches', '\patch_', client, '.conf') + + if VERBOSE or DEBUG : print(filename) + + with open(filename, 'r') as datafile : + while True : + kbegin = 0 + vbegin = 0 + kend = 0 + vend = 0 + + dataline = datafile.readline() + + if not dataline : break + if not dataline[0:3] == 'OP_' : continue + + kend = kbegin + 3 + + while not dataline[(kend - 1):kend] == '=' : + if kend >= len(dataline) : break + else : kend = kend + 1 + + kend = kend - 1 # adjust out the '=' + vbegin = kend + 1 + vend = vbegin + 6 + + if dataline[vbegin:vend] == '0x0000' : continue + + clientops[client, dataline[kbegin:kend]] = dataline[vbegin:vend] + + if DEBUG : print('({0}, {1}) = {2}'.format(client, dataline[kbegin:kend], clientops[client, dataline[kbegin:kend]])) + + datafile.close() + + except : badclients.append(client) + + if len(badclients) > 0 : + badentries = [] + + for badclient in badclients : + if VERBOSE or DEBUG : print('Deleting client {0} from search criteria...'.format(badclient)) + + clients.remove(badclient) + + if VERBOSE or DEBUG : print('Deleting any partial entries for client {0}...'.format(badclient)) + + for entry in clientops.keys() : + if entry[0] == client : + badentries.append(entry) + + for badentry in badentries : + del clientops[badentry] + + if len(clients) == 0 : + return False + + return True + + +def LoadClientTranslators() : + for client in clients : + try : + if client == '6.2' : shortname = '{0}'.format('\Client62_ops.h') + else : shortname = '{0}{1}{2}'.format(chr(92), client, '_ops.h') + + filename = '{0}{1}{2}'.format(repopath, '\common\patches', shortname) + + if VERBOSE or DEBUG : print(filename) + + with open(filename, 'r') as datafile : + while True: + begin = 0 + end = 0 + + dataline = datafile.readline() + + if not dataline : break + if not dataline[:1] == 'E' and not dataline[0:1] == 'D' : continue + + while not dataline[begin:(begin + 1)] == '(' : + if begin >= len(dataline) : break + else : begin = begin + 1 + + end = begin + 1 + + while not dataline[(end - 1):end] == ')' : + if end >= len(dataline) : break + else : end = end + 1 + + begin = begin + 1 # adjust out the '(' + end = end - 1 # adjust out the ')' + + if begin >= end or begin >= len(dataline) : continue + if end >= len(dataline) : continue + + if dataline[:1] == 'E' : + encodes.append((client, dataline[begin:end])) + + if DEBUG : print('ENCODE({0}, {1}) [floating index: {2}]'.format(client, dataline[begin:end], encodes.index((client, dataline[begin:end])))) + elif dataline[:1] == 'D' : + decodes.append((client, dataline[begin:end])) + + if DEBUG : print('DECODE({0}, {1}) [floating index: {2}]'.format(client, dataline[begin:end], decodes.index((client, dataline[begin:end])))) + + datafile.close() + + except : return False # TODO: need to handle + + if len(encodes) == 0 and len(decodes) == 0 : + return False + + return True + + +def LoadServerHandlers() : + # TODO: handle remarked out definitions; add other servers, if possible + try : + filename = '{0}{1}{2}'.format(repopath, '\zone', '\client_packet.cpp') + + if VERBOSE or DEBUG : print(filename) + + with open(filename, 'r') as datafile : + dataline = datafile.readline() + + while not dataline[:19] == 'void MapOpcodes() {' : + dataline = datafile.readline() + + if not dataline : break + + while True : + kbegin = 0 + vbegin = 0 + kend = 0 + vend = 0 + + dataline = datafile.readline() + + if not dataline : break + if dataline[0:1] == '}' : break + + kbegin = dataline.find('OP_') + + if kbegin == -1 : continue + + kend = kbegin + 1 + + while not dataline[kend:(kend + 1)] == ']' : + if kend >= len(dataline) : break + else : kend = kend + 1 + + vbegin = dataline.find('&Client::') + + if vbegin == -1 : continue + + vbegin = vbegin + 1 + vend = vbegin + 9 + + while not dataline[vend:(vend + 1)] == ';' : + if vend >= len(dataline) : break + else : vend = vend + 1 + + handlers['Zone', dataline[kbegin:kend]] = dataline[vbegin:vend] + + if DEBUG : print('({0}, {1}) = {2}'.format('Zone', dataline[kbegin:kend], handlers['Zone', dataline[kbegin:kend]])) + + datafile.close() + + except : return False # should probably do the same for this (badservers) as done for badclients above + + return True + + +def CreateOutputDirectory() : + try : + outputpath = '{0}{1}'.format(repopath, '\utils\scripts\opcode_handlers_output') + + if VERBOSE or DEBUG : print(outputpath) + + os.mkdir(outputpath) + + return True + + except : return False + + +def CreateOutputStreams() : + try : + for client in clients : + filename = '{0}{1}{2}{3}{4}'.format(repopath, '\utils\scripts\opcode_handlers_output', chr(92), client, '_opcode_handlers.txt') + + if VERBOSE or DEBUG : print(filename) + + outstreams[client] = open(filename, 'w') + + outstreams[client].write('******************************************************\n') + outstreams[client].write('** Opcode-Handler analysis for \'{0}\' client\n'.format(client)) + outstreams[client].write('** script-generated file @ {0}\n'.format(ctime(time()))) + outstreams[client].write('**\n') + outstreams[client].write('** (only cross-linked (active) opcodes are listed)\n') + outstreams[client].write('******************************************************\n\n') + + except : + for client in clients : + if client in outstreams.keys() : + outstreams[client].close() + del outstreams[client] + + return False + + return True + + +def ParseOpcodeData() : + serveropnames = [] + + for serveropkey in serverops.keys() : + if serveropkey == 'Null' : continue + + if DEBUG : print('->ServerOpKey: {0}'.format(serveropkey)) + + serveropnames.append(serveropkey) + + if len(serveropnames) == 0 : return False + + for server in servers : + if server == 'Login' or server == 'World' : continue # Login, World not implemented yet + + handleropnames = [] + + for handlerkey in handlers.keys() : + if handlerkey[0] == server : + if DEBUG : print('->HandlerKey: {0}'.format(handlerkey[1])) + + handleropnames.append(handlerkey[1]) + + if len(handleropnames) == 0 : return False + else : handleropnames.sort() # sort to process opcode names in ascending order + + for client in clients : + clientopnames = [] + clientencodes = [] + clientdecodes = [] + + notranslation = 0 + encodeonly = 0 + decodeonly = 0 + encodedecode = 0 + totalopcodes = 0 + + for clientopkey in clientops.keys() : + if clientopkey[0] == client : + if DEBUG : print('->ClientOpKey: {0}'.format(clientopkey[1])) + + clientopnames.append(clientopkey[1]) + + if len(clientopnames) == 0 : return False + + for encodeentry in encodes : + if encodeentry[0] == client : + if DEBUG : print('->EncodeEntry: {0}'.format(encodeentry[1])) + + clientencodes.append(encodeentry[1]) + + if len(clientencodes) == 0 : return False + + for decodeentry in decodes : + if decodeentry[0] == client : + if DEBUG : print('->DecodeEntry: {0}'.format(decodeentry[1])) + + clientdecodes.append(decodeentry[1]) + + if len(clientdecodes) == 0 : return False + + for handleropentry in handleropnames : + try : clientopindex = clientopnames.index(handleropentry) + except : clientopindex = -1 + + if clientopindex > -1 : + val0 = clientopnames[clientopindex] + val1 = serverops[val0] + val2 = clientops[(client, val0)] + + if DEBUG : print('->Opcode: {0} ({1}: {2} | {3}: {4})'.format(val0, server, val1, client, val2)) + + outstreams[client].write('Opcode: {0} | {1}: {2} | {3}: {4}\n'.format(val0, server, val1, client, val2)) + + val3 = handlers[(server, val0)] + + if DEBUG : print('->{0} Handler: {1}'.format(server, val3)) + + outstreams[client].write(' {0} Handler: {1}\n'.format(server, val3)) + + try : val4 = clientencodes.index(val0) > -1 + except : val4 = False + try : val5 = clientdecodes.index(val0) > -1 + except : val5 = False + + if DEBUG : print('Encoded: {0} | Decoded: {1}'.format(val4, val5)) + + outstreams[client].write(' Encoded: {0} | Decoded: {1}\n\n'.format(val4, val5)) + + totalopcodes = totalopcodes + 1 + + if val4 and val5 : encodedecode = encodedecode + 1 + elif val4 and not val5 : encodeonly = encodeonly + 1 + elif not val4 and val5 : decodeonly = decodeonly + 1 + elif not val4 and not val5 : notranslation = notranslation + 1 + + if DEBUG : print('->EndOfOpcodeLoop: {0}'.format(val0)) + + if DEBUG : print('->OpcodeCount: {0}'.format(totalopcodes)) + if DEBUG : print('->Translations: (Bi-directional: {0}, EncodeOnly: {1}, DecodeOnly: {2}, NoTranslation: {3})'.format(encodedecode, encodeonly, decodeonly, notranslation)) + + outstreams[client].write('Statistics *******************************************\n') + outstreams[client].write('** Handled Opcodes: {0}\n'.format(totalopcodes)) + outstreams[client].write('** Bi-directional Translations: {0}\n'.format(encodeonly)) + outstreams[client].write('** Encodes Only: {0}\n'.format(encodeonly)) + outstreams[client].write('** Decodes Only: {0}\n'.format(decodeonly)) + outstreams[client].write('** No Translations: {0}\n'.format(notranslation)) + outstreams[client].write('Notes ************************************************\n') + outstreams[client].write('** \'Bi-directional\' indicates translations are performed on tx/rx packets\n') + outstreams[client].write('** \'Encodes Only\' indicates translations only on tx packets - does not exclude direct packet rx\n') + outstreams[client].write('** \'Decodes Only\' indicates translations only on rx packets - does not exclude direct packet tx\n') + outstreams[client].write('** \'No Translations\' indicates no translations on tx/rx of packets\n') + + if DEBUG : print('->EndOfClientLoop: {0}'.format(client)) + + if DEBUG : print('->EndOfServerLoop: {0}'.format(server)) + + return True + + +def DestroyOutputStreams() : + for client in clients : + if client in outstreams.keys() : + outstreams[client].close() + del outstreams[client] + + return True + + +if __name__ == '__main__': + main() From 32243aa3837b1e5c9e732450a8d738a7a347e3a4 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 4 Aug 2014 23:12:28 -0400 Subject: [PATCH 260/288] Unix fix... Thanks Demonstar!! --- utils/scripts/opcode_handlers.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/utils/scripts/opcode_handlers.py b/utils/scripts/opcode_handlers.py index cae5fdc5c..0a9c63bd0 100644 --- a/utils/scripts/opcode_handlers.py +++ b/utils/scripts/opcode_handlers.py @@ -79,7 +79,7 @@ def main() : def LoadServerOpcodes() : # Server opcodes are auto-enumerated with a starting reference of '1' try : - filename = '{0}{1}{2}'.format(repopath, '\common', '\emu_oplist.h') + filename = '{0}{1}{2}'.format(repopath, '/common', '/emu_oplist.h') if VERBOSE or DEBUG : print(filename) @@ -130,7 +130,7 @@ def LoadClientOpcodes() : for client in clients : try : - filename = '{0}{1}{2}{3}{4}'.format(repopath, '\utils\patches', '\patch_', client, '.conf') + filename = '{0}{1}{2}{3}{4}'.format(repopath, '/utils/patches', '/patch_', client, '.conf') if VERBOSE or DEBUG : print(filename) @@ -192,10 +192,10 @@ def LoadClientOpcodes() : def LoadClientTranslators() : for client in clients : try : - if client == '6.2' : shortname = '{0}'.format('\Client62_ops.h') - else : shortname = '{0}{1}{2}'.format(chr(92), client, '_ops.h') + if client == '6.2' : shortname = '{0}'.format('/Client62_ops.h') + else : shortname = '{0}{1}{2}'.format('/', client, '_ops.h') - filename = '{0}{1}{2}'.format(repopath, '\common\patches', shortname) + filename = '{0}{1}{2}'.format(repopath, '/common/patches', shortname) if VERBOSE or DEBUG : print(filename) @@ -247,7 +247,7 @@ def LoadClientTranslators() : def LoadServerHandlers() : # TODO: handle remarked out definitions; add other servers, if possible try : - filename = '{0}{1}{2}'.format(repopath, '\zone', '\client_packet.cpp') + filename = '{0}{1}{2}'.format(repopath, '/zone', '/client_packet.cpp') if VERBOSE or DEBUG : print(filename) @@ -304,7 +304,7 @@ def LoadServerHandlers() : def CreateOutputDirectory() : try : - outputpath = '{0}{1}'.format(repopath, '\utils\scripts\opcode_handlers_output') + outputpath = '{0}{1}'.format(repopath, '/utils/scripts/opcode_handlers_output') if VERBOSE or DEBUG : print(outputpath) @@ -318,7 +318,7 @@ def CreateOutputDirectory() : def CreateOutputStreams() : try : for client in clients : - filename = '{0}{1}{2}{3}{4}'.format(repopath, '\utils\scripts\opcode_handlers_output', chr(92), client, '_opcode_handlers.txt') + filename = '{0}{1}{2}{3}'.format(repopath, '/utils/scripts/opcode_handlers_output/', client, '_opcode_handlers.txt') if VERBOSE or DEBUG : print(filename) From 9561f841c4fb0b67fb7fa6129d767bacd70b14b1 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 5 Aug 2014 16:34:57 -0400 Subject: [PATCH 261/288] Tweaked some procedural code and re-worked client opcode reader to standardize hex format (i.e., {0x0abc, 0x0ABC, 0xabc} = 0x0abc) --- utils/scripts/opcode_handlers.py | 706 +++++++++++++++++++------------ 1 file changed, 429 insertions(+), 277 deletions(-) diff --git a/utils/scripts/opcode_handlers.py b/utils/scripts/opcode_handlers.py index 0a9c63bd0..a677142fa 100644 --- a/utils/scripts/opcode_handlers.py +++ b/utils/scripts/opcode_handlers.py @@ -1,12 +1,12 @@ #! /usr/bin/env python -# untested on Linux - -# This script generates cross-references to show associated (handled) opcodes between the server and client. -# It will generate files for each client found and provide some basic information..such as opcode names and -# values, server handler and whether opcodes are translated on tx/rx. # -# It's currently limited to the 'Zone' server..but, can be expounded upon to include other servers, clients -# and other criteria and features. +# This script generates cross-references to show associated (handled) opcodes +# between the server and client. It will generate files for each client found +# and provide some basic information..such as opcode names and values, server +# handler and whether opcodes are translated on tx/rx. +# +# It's currently limited to the 'Zone' server..but, can be expounded upon to +# include other servers, clients and other criteria and features. import os @@ -15,14 +15,16 @@ import os from time import time, ctime -VERBOSE = True # pipes relativistic information to the console window -DEBUG = False # setting this to 'True' will pipe more information to the console window than you would ever want! +# pipes relativistic information to the console window +VERBOSE = True -repopath = os.getcwd() -repopath = repopath[:-14] # '\utils\scripts' - because I'm lazy and don't want to do it the right way... +# setting this to 'True' will pipe more information than you would ever want! +DEBUG = False -clients = [ '6.2', 'Titanium', 'SoF', 'SoD', 'Underfoot', 'RoF' ] -servers = [ 'Login', 'World', 'Zone' ] +repopath = os.getcwd()[:-14] # '/utils/scripts' + +clients = ['6.2', 'Titanium', 'SoF', 'SoD', 'Underfoot', 'RoF'] +servers = ['Login', 'World', 'Zone', 'UCS'] clientops = {} serverops = {} @@ -34,439 +36,589 @@ handlers = {} outstreams = {} -def main() : +def main(): print('Loading source data...') - if not LoadServerOpcodes() : + if not loadserveropcodes(): print('Error! Could not load server opcodes') return - if not LoadClientOpcodes() : + if not loadclientopcodes(): print('Error! Could not load client opcodes') return - if not LoadClientTranslators() : + if not loadclienttranslators(): print('Error! Could not load client translators') return - if not LoadServerHandlers() : + if not loadserverhandlers(): print('Error! Could not load server handlers') return print('Creating output streams...') - if not CreateOutputDirectory() : - print('Output directory already exists or could not be created...') - #return # existing directory returns a failure..don't exit here..CreateOutputStreams() will catch makdir() problems + if not createoutputdirectory(): + print('Output directory could not be created...') + return - if not CreateOutputStreams() : + if not createoutputstreams(): print('Error! Could not open output files') return print('Parsing opcode data...') - if not ParseOpcodeData() : + if not parseopcodedata(): print('Error! Could not parse opcode data') return print('Destroying output streams...') - if not DestroyOutputStreams() : + if not destroyoutputstreams(): print('Error! Could not close output files') return -def LoadServerOpcodes() : +def loadserveropcodes(): # Server opcodes are auto-enumerated with a starting reference of '1' - try : - filename = '{0}{1}{2}'.format(repopath, '/common', '/emu_oplist.h') + try: + value = 0 + + filename = '{0}{1}{2}'.format( + repopath, + '/common', + '/emu_oplist.h') - if VERBOSE or DEBUG : print(filename) - - with open(filename, 'r') as datafile : - value = 0 - serverops['Null'] = value - - while True : - begin = 0 - end = 0 - + if VERBOSE or DEBUG: + print(filename) + + with open(filename, 'r') as datafile: + while True: dataline = datafile.readline() - if not dataline : break - if not dataline[:1] == 'N' : continue - - while not dataline[begin:(begin + 1)] == '(' : - if begin >= len(dataline) : break - else : begin = begin + 1 + if not dataline: + break - end = begin + 1 + vbegin = dataline.find('OP_', 2) + vend = dataline.find(')', vbegin) + + if vbegin == -1: + continue + if vend == -1: + continue + + value += 1 - while not dataline[(end - 1):end] == ')' : - if end >= len(dataline) : break - else : end = end + 1 + if dataline[:1] == 'N': + serverops[dataline[vbegin:vend]] = value - begin = begin + 1 # adjust out the '(' - end = end - 1 # adjust out the ')' - - if begin >= end or begin >= len(dataline) : continue - if end >= len(dataline) : continue - - value = value + 1 - - serverops[dataline[begin:end]] = value - - if DEBUG : print('({0}, {1}) = {2}'.format('Server', dataline[begin:end], serverops[dataline[begin:end]])) + if DEBUG: + print('({0}, {1}) = {2}'.format( + 'Server', + dataline[vbegin:vend], + serverops[dataline[vbegin:vend]])) datafile.close() + + filename = '{0}{1}{2}'.format( + repopath, + '/common', + '/mail_oplist.h') + + if VERBOSE or DEBUG: + print(filename) + + with open(filename, 'r') as datafile: + while True: + dataline = datafile.readline() - except : return False + if not dataline: + break + + vbegin = dataline.find('OP_', 2) + vend = dataline.find(')', vbegin) + + if vbegin == -1: + continue + if vend == -1: + continue + + value += 1 + + if dataline[:1] == 'N': + serverops[dataline[vbegin:vend]] = value + + if DEBUG: + print('({0}, {1}) = {2}'.format( + 'Server', + dataline[vbegin:vend], + serverops[dataline[vbegin:vend]])) + + datafile.close() + except: + return False return True -def LoadClientOpcodes() : +def loadclientopcodes(): badclients = [] - for client in clients : - try : - filename = '{0}{1}{2}{3}{4}'.format(repopath, '/utils/patches', '/patch_', client, '.conf') + for client in clients: + try: + filename = '{0}{1}{2}{3}{4}'.format( + repopath, + '/utils/patches', + '/patch_', + client, + '.conf') - if VERBOSE or DEBUG : print(filename) + if VERBOSE or DEBUG: + print(filename) - with open(filename, 'r') as datafile : - while True : - kbegin = 0 - vbegin = 0 - kend = 0 - vend = 0 - + with open(filename, 'r') as datafile: + while True: dataline = datafile.readline() - if not dataline : break - if not dataline[0:3] == 'OP_' : continue + if not dataline: + break - kend = kbegin + 3 + kbegin = dataline.find('OP_') + kend = dataline.find('=', kbegin) - while not dataline[(kend - 1):kend] == '=' : - if kend >= len(dataline) : break - else : kend = kend + 1 - - kend = kend - 1 # adjust out the '=' - vbegin = kend + 1 + if not kbegin == 0: + continue + if kend == -1: + continue + + vbegin = dataline.find('0x', kend) vend = vbegin + 6 - if dataline[vbegin:vend] == '0x0000' : continue + if vbegin == -1: + continue + + value = int(dataline[(vbegin + 2):vend].lower(), 16) + + if value == 0: + continue + + clientops[client, dataline[kbegin:kend]] = '0x{0}'.format( + hex(value)[2:].zfill(4)) - clientops[client, dataline[kbegin:kend]] = dataline[vbegin:vend] - - if DEBUG : print('({0}, {1}) = {2}'.format(client, dataline[kbegin:kend], clientops[client, dataline[kbegin:kend]])) + if DEBUG: + print('({0}, {1}) = {2} (int: {3})'.format( + client, + dataline[kbegin:kend], + clientops[client, dataline[kbegin:kend]], + value)) datafile.close() + except: + badclients.append(client) - except : badclients.append(client) - - if len(badclients) > 0 : + if len(badclients) > 0: badentries = [] - for badclient in badclients : - if VERBOSE or DEBUG : print('Deleting client {0} from search criteria...'.format(badclient)) + for badclient in badclients: + if VERBOSE or DEBUG: + print('Deleting client {0} from search criteria...'.format( + badclient)) clients.remove(badclient) - if VERBOSE or DEBUG : print('Deleting any partial entries for client {0}...'.format(badclient)) + if VERBOSE or DEBUG: + print('Deleting any partial entries for client {0}...'.format( + badclient)) - for entry in clientops.keys() : - if entry[0] == client : + for entry in clientops.keys(): + if entry[0] == badclient: badentries.append(entry) - for badentry in badentries : + for badentry in badentries: del clientops[badentry] - if len(clients) == 0 : + if len(clients) == 0: return False return True -def LoadClientTranslators() : - for client in clients : - try : - if client == '6.2' : shortname = '{0}'.format('/Client62_ops.h') - else : shortname = '{0}{1}{2}'.format('/', client, '_ops.h') - - filename = '{0}{1}{2}'.format(repopath, '/common/patches', shortname) +def loadclienttranslators(): + for client in clients: + if client == '6.2': + shortname = '{0}'.format( + '/Client62_ops.h') + else: + shortname = '{0}{1}{2}'.format( + '/', + client, + '_ops.h') + + try: + filename = '{0}{1}{2}'.format( + repopath, + '/common/patches', + shortname) - if VERBOSE or DEBUG : print(filename) + if VERBOSE or DEBUG: + print(filename) - with open(filename, 'r') as datafile : + with open(filename, 'r') as datafile: while True: - begin = 0 - end = 0 - dataline = datafile.readline() - if not dataline : break - if not dataline[:1] == 'E' and not dataline[0:1] == 'D' : continue - - while not dataline[begin:(begin + 1)] == '(' : - if begin >= len(dataline) : break - else : begin = begin + 1 + if not dataline: + break - end = begin + 1 - - while not dataline[(end - 1):end] == ')' : - if end >= len(dataline) : break - else : end = end + 1 - - begin = begin + 1 # adjust out the '(' - end = end - 1 # adjust out the ')' - - if begin >= end or begin >= len(dataline) : continue - if end >= len(dataline) : continue + vbegin = dataline.find('OP_', 2) + vend = dataline.find(')', vbegin) + + if vbegin == -1: + continue + if vend == -1: + continue - if dataline[:1] == 'E' : - encodes.append((client, dataline[begin:end])) + if dataline[:1] == 'E': + encodes.append((client, dataline[vbegin:vend])) - if DEBUG : print('ENCODE({0}, {1}) [floating index: {2}]'.format(client, dataline[begin:end], encodes.index((client, dataline[begin:end])))) - elif dataline[:1] == 'D' : - decodes.append((client, dataline[begin:end])) + if DEBUG: + print('ENCODE({0}, {1}) [floating index: {2}]'.format( + client, + dataline[vbegin:vend], + encodes.index((client, dataline[vbegin:vend])))) + elif dataline[:1] == 'D': + decodes.append((client, dataline[vbegin:vend])) - if DEBUG : print('DECODE({0}, {1}) [floating index: {2}]'.format(client, dataline[begin:end], decodes.index((client, dataline[begin:end])))) + if DEBUG: + print('DECODE({0}, {1}) [floating index: {2}]'.format( + client, + dataline[vbegin:vend], + decodes.index((client, dataline[vbegin:vend])))) datafile.close() + except: + # TODO: need to handle + return False - except : return False # TODO: need to handle - - if len(encodes) == 0 and len(decodes) == 0 : + # this will need to change if we ever have a client with 100% support + if len(encodes) == 0 and len(decodes) == 0: return False return True -def LoadServerHandlers() : +def loadserverhandlers(): # TODO: handle remarked out definitions; add other servers, if possible - try : - filename = '{0}{1}{2}'.format(repopath, '/zone', '/client_packet.cpp') + try: + filename = '{0}{1}{2}'.format( + repopath, + '/zone', + '/client_packet.cpp') - if VERBOSE or DEBUG : print(filename) + if VERBOSE or DEBUG: + print(filename) - with open(filename, 'r') as datafile : + with open(filename, 'r') as datafile: dataline = datafile.readline() - while not dataline[:19] == 'void MapOpcodes() {' : + while not dataline[:19] == 'void MapOpcodes() {': dataline = datafile.readline() - if not dataline : break + if not dataline: + break - while True : - kbegin = 0 - vbegin = 0 - kend = 0 - vend = 0 - + while True: dataline = datafile.readline() - if not dataline : break - if dataline[0:1] == '}' : break + if not dataline: + break + if dataline[0:1] == '}': + break kbegin = dataline.find('OP_') + kend = dataline.find(']', kbegin) - if kbegin == -1 : continue + if kbegin == -1: + continue + if kend == -1: + continue - kend = kbegin + 1 - - while not dataline[kend:(kend + 1)] == ']' : - if kend >= len(dataline) : break - else : kend = kend + 1 + vbegin = dataline.find('Client::', kend) + vend = dataline.find(';', vbegin) - vbegin = dataline.find('&Client::') - - if vbegin == -1 : continue - - vbegin = vbegin + 1 - vend = vbegin + 9 - - while not dataline[vend:(vend + 1)] == ';' : - if vend >= len(dataline) : break - else : vend = vend + 1 + if vbegin == -1: + continue + if vend == -1: + continue handlers['Zone', dataline[kbegin:kend]] = dataline[vbegin:vend] - if DEBUG : print('({0}, {1}) = {2}'.format('Zone', dataline[kbegin:kend], handlers['Zone', dataline[kbegin:kend]])) + if DEBUG: + print('({0}, {1}) = {2}'.format( + 'Zone', + dataline[kbegin:kend], + handlers['Zone', dataline[kbegin:kend]])) datafile.close() - - except : return False # should probably do the same for this (badservers) as done for badclients above + except: + # should probably do the same for this (badservers) + # as done for badclients in the above function + return False return True -def CreateOutputDirectory() : - try : - outputpath = '{0}{1}'.format(repopath, '/utils/scripts/opcode_handlers_output') +def createoutputdirectory(): + outputpath = '' + + try: + outputpath = '{0}{1}'.format( + repopath, + '/utils/scripts/opcode_handlers_output') - if VERBOSE or DEBUG : print(outputpath) - - os.mkdir(outputpath) + if VERBOSE or DEBUG: + print(outputpath) + + if not os.path.exists(outputpath): + os.mkdir(outputpath) return True + except: + return False + + +def createoutputstreams(): + filename = '' - except : return False - - -def CreateOutputStreams() : - try : - for client in clients : - filename = '{0}{1}{2}{3}'.format(repopath, '/utils/scripts/opcode_handlers_output/', client, '_opcode_handlers.txt') + try: + for client in clients: + filename = '{0}{1}{2}{3}'.format( + repopath, + '/utils/scripts/opcode_handlers_output/', + client, + '_opcode_handlers.txt') - if VERBOSE or DEBUG : print(filename) + if VERBOSE or DEBUG: + print(filename) outstreams[client] = open(filename, 'w') - - outstreams[client].write('******************************************************\n') - outstreams[client].write('** Opcode-Handler analysis for \'{0}\' client\n'.format(client)) - outstreams[client].write('** script-generated file @ {0}\n'.format(ctime(time()))) - outstreams[client].write('**\n') - outstreams[client].write('** (only cross-linked (active) opcodes are listed)\n') - outstreams[client].write('******************************************************\n\n') - - except : - for client in clients : - if client in outstreams.keys() : + + message = \ + '------------------------------------------------------\n' \ + '|| Opcode-Handler analysis for \'{0}\' client\n' \ + '|| script-generated file @ {1}\n' \ + '||\n' \ + '|| (only cross-linked (active) opcodes are listed)\n' \ + '------------------------------------------------------\n' \ + '\n'.format( + client, + ctime(time())) + + outstreams[client].write(message) + + if DEBUG: + print(message[:-2]) + except: + for client in clients: + if client in outstreams.keys(): outstreams[client].close() del outstreams[client] + + if DEBUG: + print('->CreatingClientStream(exception): {0}'.format( + client)) return False return True -def ParseOpcodeData() : +def parseopcodedata(): serveropnames = [] - for serveropkey in serverops.keys() : - if serveropkey == 'Null' : continue - - if DEBUG : print('->ServerOpKey: {0}'.format(serveropkey)) - + for serveropkey in serverops.keys(): serveropnames.append(serveropkey) - if len(serveropnames) == 0 : return False + if DEBUG: + print('->ServerOpKey: {0}'.format( + serveropkey)) + + if len(serveropnames) == 0: + return False - for server in servers : - if server == 'Login' or server == 'World' : continue # Login, World not implemented yet + for server in servers: + # Login, World, UCS not implemented yet + if not server == 'Zone': + if DEBUG: + print('->SkippingServerOpcodeParse: {0}'.format( + server)) + + continue handleropnames = [] - for handlerkey in handlers.keys() : - if handlerkey[0] == server : - if DEBUG : print('->HandlerKey: {0}'.format(handlerkey[1])) - + for handlerkey in handlers.keys(): + if handlerkey[0] == server: handleropnames.append(handlerkey[1]) + + if DEBUG: + print('->HandlerKey: {0}'.format( + handlerkey[1])) - if len(handleropnames) == 0 : return False - else : handleropnames.sort() # sort to process opcode names in ascending order + if len(handleropnames) == 0: + return False + else: + # sort to process opcode names in ascending order + handleropnames.sort() - for client in clients : + for client in clients: clientopnames = [] clientencodes = [] clientdecodes = [] - notranslation = 0 + totalopcodes = 0 + encodedecode = 0 encodeonly = 0 decodeonly = 0 - encodedecode = 0 - totalopcodes = 0 + notranslation = 0 - for clientopkey in clientops.keys() : - if clientopkey[0] == client : - if DEBUG : print('->ClientOpKey: {0}'.format(clientopkey[1])) - + for clientopkey in clientops.keys(): + if clientopkey[0] == client: clientopnames.append(clientopkey[1]) - - if len(clientopnames) == 0 : return False - - for encodeentry in encodes : - if encodeentry[0] == client : - if DEBUG : print('->EncodeEntry: {0}'.format(encodeentry[1])) + if DEBUG: + print('->ClientOpKey: {0}'.format( + clientopkey[1])) + + if len(clientopnames) == 0: + return False + + for encodeentry in encodes: + if encodeentry[0] == client: clientencodes.append(encodeentry[1]) - - if len(clientencodes) == 0 : return False - - for decodeentry in decodes : - if decodeentry[0] == client : - if DEBUG : print('->DecodeEntry: {0}'.format(decodeentry[1])) - clientdecodes.append(decodeentry[1]) + if DEBUG: + print('->EncodeEntry: {0}'.format( + encodeentry[1])) - if len(clientdecodes) == 0 : return False + if len(clientencodes) == 0: + return False + + for decodeentry in decodes: + if decodeentry[0] == client: + clientdecodes.append(decodeentry[1]) + + if DEBUG: + print('->DecodeEntry: {0}'.format( + decodeentry[1])) + + if len(clientdecodes) == 0: + return False - for handleropentry in handleropnames : - try : clientopindex = clientopnames.index(handleropentry) - except : clientopindex = -1 + for handleropentry in handleropnames: + try: + clientopindex = clientopnames.index(handleropentry) + except: + clientopindex = -1 - if clientopindex > -1 : + if clientopindex > -1: val0 = clientopnames[clientopindex] val1 = serverops[val0] val2 = clientops[(client, val0)] - - if DEBUG : print('->Opcode: {0} ({1}: {2} | {3}: {4})'.format(val0, server, val1, client, val2)) - - outstreams[client].write('Opcode: {0} | {1}: {2} | {3}: {4}\n'.format(val0, server, val1, client, val2)) - val3 = handlers[(server, val0)] - if DEBUG : print('->{0} Handler: {1}'.format(server, val3)) + try: + val4 = clientencodes.index(val0) > -1 + except: + val4 = False + try: + val5 = clientdecodes.index(val0) > -1 + except: + val5 = False - outstreams[client].write(' {0} Handler: {1}\n'.format(server, val3)) + message = \ + 'Opcode: {0} | {1}: {2} | {3}: {4}\n' \ + ' {5} Handler: \'{6}\'\n' \ + ' Encoded: {7} | Decoded: {8}\n\n'.format( + val0, + server, + val1, + client, + val2, + server, + val3, + val4, + val5) + + outstreams[client].write(message) + + if DEBUG: + print(message[:-2]) + + totalopcodes += 1 + + if val4 and val5: + encodedecode += 1 + elif val4 and not val5: + encodeonly += 1 + elif not val4 and val5: + decodeonly += 1 + elif not val4 and not val5: + notranslation += 1 - try : val4 = clientencodes.index(val0) > -1 - except : val4 = False - try : val5 = clientdecodes.index(val0) > -1 - except : val5 = False + if DEBUG: + print('->EndOfOpcodeLoop: {0}'.format( + val0)) + + message = \ + 'Statistics -------------------------------------------\n' \ + '|| Server Opcode Type: {0}\n' \ + '|| Handled Opcodes: {1}\n' \ + '|| Bi-directional: {2}\n' \ + '|| Encodes Only: {3}\n' \ + '|| Decodes Only: {4}\n' \ + '|| No Translations: {5}\n' \ + '\n' \ + 'Notes ------------------------------------------------\n' \ + '|| Encodes are Server-to-Client and Decodes are' \ + ' Server-from-Client in context\n' \ + '|| \'Bi-directional\' indicates translations are performed on' \ + ' tx/rx packets\n' \ + '|| \'Encodes Only\' indicates translations only on tx packets' \ + ' - does not exclude direct packet rx\n' \ + '|| \'Decodes Only\' indicates translations only on rx packets' \ + ' - does not exclude direct packet tx\n' \ + '|| \'No Translations\' indicates no translations of tx/rx' \ + ' packets\n'.format( + server, + totalopcodes, + encodedecode, + encodeonly, + decodeonly, + notranslation) + + outstreams[client].write(message) + + if DEBUG: + print(message[:-1]) + print('->EndOfClientLoop: {0}'.format( + client)) - if DEBUG : print('Encoded: {0} | Decoded: {1}'.format(val4, val5)) - - outstreams[client].write(' Encoded: {0} | Decoded: {1}\n\n'.format(val4, val5)) - - totalopcodes = totalopcodes + 1 - - if val4 and val5 : encodedecode = encodedecode + 1 - elif val4 and not val5 : encodeonly = encodeonly + 1 - elif not val4 and val5 : decodeonly = decodeonly + 1 - elif not val4 and not val5 : notranslation = notranslation + 1 - - if DEBUG : print('->EndOfOpcodeLoop: {0}'.format(val0)) - - if DEBUG : print('->OpcodeCount: {0}'.format(totalopcodes)) - if DEBUG : print('->Translations: (Bi-directional: {0}, EncodeOnly: {1}, DecodeOnly: {2}, NoTranslation: {3})'.format(encodedecode, encodeonly, decodeonly, notranslation)) - - outstreams[client].write('Statistics *******************************************\n') - outstreams[client].write('** Handled Opcodes: {0}\n'.format(totalopcodes)) - outstreams[client].write('** Bi-directional Translations: {0}\n'.format(encodeonly)) - outstreams[client].write('** Encodes Only: {0}\n'.format(encodeonly)) - outstreams[client].write('** Decodes Only: {0}\n'.format(decodeonly)) - outstreams[client].write('** No Translations: {0}\n'.format(notranslation)) - outstreams[client].write('Notes ************************************************\n') - outstreams[client].write('** \'Bi-directional\' indicates translations are performed on tx/rx packets\n') - outstreams[client].write('** \'Encodes Only\' indicates translations only on tx packets - does not exclude direct packet rx\n') - outstreams[client].write('** \'Decodes Only\' indicates translations only on rx packets - does not exclude direct packet tx\n') - outstreams[client].write('** \'No Translations\' indicates no translations on tx/rx of packets\n') - - if DEBUG : print('->EndOfClientLoop: {0}'.format(client)) - - if DEBUG : print('->EndOfServerLoop: {0}'.format(server)) + if DEBUG: + print('->EndOfServerLoop: {0}'.format( + server)) return True -def DestroyOutputStreams() : - for client in clients : - if client in outstreams.keys() : +def destroyoutputstreams(): + for client in clients: + if client in outstreams.keys(): outstreams[client].close() del outstreams[client] + + if DEBUG: + print('->DestroyingClientStream: {0}'.format( + client)) return True From aab3cac29c493ee7f831f89a7da27a0219fc0011 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Wed, 6 Aug 2014 06:49:29 -0400 Subject: [PATCH 262/288] fix --- zone/spell_effects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 078827b78..9f6a3866b 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -6468,6 +6468,6 @@ void Mob::CalcSpellPowerDistanceMod(uint16 spell_id, float range, Mob* caster) float mod = spells[spell_id].min_dist_mod + (dist_from_min * (dm_mod_interval/dm_range)); mod *= 100.0f; - SetSpellPSetSpellPowerDistanceMod(static_cast(mod)); + SetSpellPowerDistanceMod(static_cast(mod)); } } \ No newline at end of file From f0496a6f59f5dbf58ae210a1c455c0580ddf2575 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 7 Aug 2014 15:27:30 -0400 Subject: [PATCH 263/288] Total re-work..not much more can be done until more server handlers are added... --- utils/scripts/opcode_handlers.py | 978 ++++++++++++++++--------------- 1 file changed, 505 insertions(+), 473 deletions(-) diff --git a/utils/scripts/opcode_handlers.py b/utils/scripts/opcode_handlers.py index a677142fa..ca4a00d3d 100644 --- a/utils/scripts/opcode_handlers.py +++ b/utils/scripts/opcode_handlers.py @@ -1,625 +1,657 @@ #! /usr/bin/env python # # This script generates cross-references to show associated (handled) opcodes -# between the server and client. It will generate files for each client found -# and provide some basic information..such as opcode names and values, server -# handler and whether opcodes are translated on tx/rx. +# between the server and client. It will generate files for each client and +# server found, and provide some basic information..such as opcode names and +# values, server handler and whether opcodes are translated on tx/rx, etc... # # It's currently limited to the 'Zone' server..but, can be expounded upon to -# include other servers, clients and other criteria and features. +# include other servers and clients, and other criteria and features. import os -#import pickle +# import pickle from time import time, ctime -# pipes relativistic information to the console window -VERBOSE = True +DEBUG = 1 # {0 - normal, 1 - verbose, 2 - in-depth} -# setting this to 'True' will pipe more information than you would ever want! -DEBUG = False +base_path = os.getcwd()[:-14] # '/utils/scripts' -repopath = os.getcwd()[:-14] # '/utils/scripts' +client_list = ['6.2', 'Titanium', 'SoF', 'SoD', 'Underfoot', 'RoF'] +server_list = ['Login', 'World', 'Zone', 'UCS'] -clients = ['6.2', 'Titanium', 'SoF', 'SoD', 'Underfoot', 'RoF'] -servers = ['Login', 'World', 'Zone', 'UCS'] +client_opcodes = {} +server_opcodes = {} -clientops = {} -serverops = {} +client_encodes = {} +client_decodes = {} -encodes = [] -decodes = [] +server_handlers = {} -handlers = {} -outstreams = {} +out_files = {} def main(): print('Loading source data...') - if not loadserveropcodes(): - print('Error! Could not load server opcodes') - return - if not loadclientopcodes(): - print('Error! Could not load client opcodes') + print('Could not load client opcodes...') return - + + if not loadserveropcodes(): + print('Could not load server opcodes...') + return + if not loadclienttranslators(): - print('Error! Could not load client translators') + print('Could not load client translators...') return if not loadserverhandlers(): - print('Error! Could not load server handlers') + print('Could not load server handlers...') return print('Creating output streams...') if not createoutputdirectory(): - print('Output directory could not be created...') + print('Could not create output directory...') return - if not createoutputstreams(): - print('Error! Could not open output files') + if not openoutputfiles(): + print('Could not open output files...') return print('Parsing opcode data...') - if not parseopcodedata(): - print('Error! Could not parse opcode data') + if not parseclientopcodedata(): + print('Could not parse client opcode data...') + return + + if not parseserveropcodedata(): + print('Could not parse server opcode data...') return print('Destroying output streams...') - if not destroyoutputstreams(): - print('Error! Could not close output files') + if not closeoutputfiles(): + print('Could not close output files...') return -def loadserveropcodes(): - # Server opcodes are auto-enumerated with a starting reference of '1' - try: - value = 0 - - filename = '{0}{1}{2}'.format( - repopath, - '/common', - '/emu_oplist.h') - - if VERBOSE or DEBUG: - print(filename) - - with open(filename, 'r') as datafile: - while True: - dataline = datafile.readline() - - if not dataline: - break - - vbegin = dataline.find('OP_', 2) - vend = dataline.find(')', vbegin) - - if vbegin == -1: - continue - if vend == -1: - continue - - value += 1 - - if dataline[:1] == 'N': - serverops[dataline[vbegin:vend]] = value - - if DEBUG: - print('({0}, {1}) = {2}'.format( - 'Server', - dataline[vbegin:vend], - serverops[dataline[vbegin:vend]])) - - datafile.close() - - filename = '{0}{1}{2}'.format( - repopath, - '/common', - '/mail_oplist.h') - - if VERBOSE or DEBUG: - print(filename) - - with open(filename, 'r') as datafile: - while True: - dataline = datafile.readline() - - if not dataline: - break - - vbegin = dataline.find('OP_', 2) - vend = dataline.find(')', vbegin) - - if vbegin == -1: - continue - if vend == -1: - continue - - value += 1 - - if dataline[:1] == 'N': - serverops[dataline[vbegin:vend]] = value - - if DEBUG: - print('({0}, {1}) = {2}'.format( - 'Server', - dataline[vbegin:vend], - serverops[dataline[vbegin:vend]])) - - datafile.close() - except: - return False - - return True - - def loadclientopcodes(): - badclients = [] + bad_clients = [] - for client in clients: + for client in client_list: try: - filename = '{0}{1}{2}{3}{4}'.format( - repopath, - '/utils/patches', + short_name = '{0}{1}{2}'.format( '/patch_', client, '.conf') - - if VERBOSE or DEBUG: - print(filename) - with open(filename, 'r') as datafile: + file_name = '{0}{1}{2}'.format( + base_path, + '/utils/patches', + short_name) + + if DEBUG >= 1: + print(file_name) + + with open(file_name, 'r') as data_file: + client_opcodes[client] = {} # force empty dictionary to avoid collisions + while True: - dataline = datafile.readline() - - if not dataline: + data_line = data_file.readline() + + if not data_line: break - kbegin = dataline.find('OP_') - kend = dataline.find('=', kbegin) + key_begin = data_line.find('OP_') + key_end = data_line.find('=', key_begin) - if not kbegin == 0: - continue - if kend == -1: - continue - - vbegin = dataline.find('0x', kend) - vend = vbegin + 6 - - if vbegin == -1: + if not key_begin == 0 or key_end < 0: continue - value = int(dataline[(vbegin + 2):vend].lower(), 16) + val_begin = data_line.find('0x', key_end) + val_end = val_begin + 6 # max size is always 6 bytes + + if val_begin < 0: + continue + + value = int(data_line[(val_begin + 2):val_end].lower(), 16) if value == 0: continue - clientops[client, dataline[kbegin:kend]] = '0x{0}'.format( - hex(value)[2:].zfill(4)) - - if DEBUG: - print('({0}, {1}) = {2} (int: {3})'.format( + client_opcodes[client][data_line[key_begin:key_end]] = '0x{0}'.format(hex(value)[2:].zfill(4)) + + if DEBUG >= 2: + print('[{0}][{1}] = {2} (int: {3})'.format( client, - dataline[kbegin:kend], - clientops[client, dataline[kbegin:kend]], + data_line[key_begin:key_end], + client_opcodes[client][data_line[key_begin:key_end]], value)) - datafile.close() - except: - badclients.append(client) + data_file.close() + except: # StandardError as se: + #print(se.message) - if len(badclients) > 0: - badentries = [] - - for badclient in badclients: - if VERBOSE or DEBUG: - print('Deleting client {0} from search criteria...'.format( - badclient)) - - clients.remove(badclient) + #if DEBUG >= 2: + # print(pickle.dumps(se.args)) - if VERBOSE or DEBUG: - print('Deleting any partial entries for client {0}...'.format( - badclient)) + bad_clients.append(client) + + if len(bad_clients) > 0: + for bad_client in bad_clients: + if DEBUG >= 1: + print('Deleting \'{0}\' client from search criteria...'.format(bad_client)) - for entry in clientops.keys(): - if entry[0] == badclient: - badentries.append(entry) - - for badentry in badentries: - del clientops[badentry] + client_list.remove(bad_client) + + if DEBUG >= 1: + print('Deleting stale entries for \'{0}\' client...'.format(bad_client)) + + if bad_client in client_opcodes: + del client_opcodes[bad_client] - if len(clients) == 0: + if not len(client_list) > 0: + return False + + return True + + +def loadserveropcodes(): + try: + value = 1 # Server opcodes are auto-enumerated with a starting reference of '1' + + file_name = '{0}{1}{2}'.format( + base_path, + '/common', + '/emu_oplist.h') + + if DEBUG >= 1: + print(file_name) + + with open(file_name, 'r') as data_file: + while True: + data_line = data_file.readline() + + if not data_line: + break + + val_begin = data_line.find('OP_', 2) + val_end = data_line.find(')', val_begin) + + if val_begin < 0 or val_end < 0: + continue + + if data_line[:1] == 'N': + server_opcodes[data_line[val_begin:val_end]] = value + value += 1 + + if DEBUG >= 2: + print('N[{0}]({1}) = {2}'.format( + 'Server', + data_line[val_begin:val_end], + server_opcodes[data_line[val_begin:val_end]])) + + data_file.close() + + file_name = '{0}{1}{2}'.format( + base_path, + '/common', + '/mail_oplist.h') + + if DEBUG >= 1: + print(file_name) + + with open(file_name, 'r') as data_file: + while True: + data_line = data_file.readline() + + if not data_line: + break + + val_begin = data_line.find('OP_', 2) + val_end = data_line.find(')', val_begin) + + if val_begin < 0 or val_end < 0: + continue + + if data_line[:1] == 'N': + server_opcodes[data_line[val_begin:val_end]] = value + value += 1 + + if DEBUG >= 2: + print('N[{0}]({1}) = {2}'.format( + 'Server', + data_line[val_begin:val_end], + server_opcodes[data_line[val_begin:val_end]])) + + data_file.close() + except: # StandardError as se: + #print(se.message) + + #if DEBUG >= 2: + # print(pickle.dumps(se.args)) + return False return True def loadclienttranslators(): - for client in clients: + for client in client_list: if client == '6.2': - shortname = '{0}'.format( - '/Client62_ops.h') + short_name = '{0}'.format('/Client62_ops.h') else: - shortname = '{0}{1}{2}'.format( + short_name = '{0}{1}{2}'.format( '/', client, '_ops.h') try: - filename = '{0}{1}{2}'.format( - repopath, + file_name = '{0}{1}{2}'.format( + base_path, '/common/patches', - shortname) + short_name) - if VERBOSE or DEBUG: - print(filename) + if DEBUG >= 1: + print(file_name) + + with open(file_name, 'r') as data_file: + client_encodes[client] = [] + client_decodes[client] = [] - with open(filename, 'r') as datafile: while True: - dataline = datafile.readline() + data_line = data_file.readline() - if not dataline: + if not data_line: break - vbegin = dataline.find('OP_', 2) - vend = dataline.find(')', vbegin) + val_begin = data_line.find('OP_', 2) + val_end = data_line.find(')', val_begin) - if vbegin == -1: - continue - if vend == -1: + if val_begin < 0 or val_end < 0: continue - if dataline[:1] == 'E': - encodes.append((client, dataline[vbegin:vend])) + if data_line[:1] == 'E': + client_encodes[client].append(data_line[val_begin:val_end]) - if DEBUG: - print('ENCODE({0}, {1}) [floating index: {2}]'.format( + if DEBUG >= 2: + print('E[{0}]({1}) (listed: {2})'.format( client, - dataline[vbegin:vend], - encodes.index((client, dataline[vbegin:vend])))) - elif dataline[:1] == 'D': - decodes.append((client, dataline[vbegin:vend])) + data_line[val_begin:val_end], + data_line[val_begin:val_end] in client_encodes[client])) + elif data_line[:1] == 'D': + client_decodes[client].append(data_line[val_begin:val_end]) - if DEBUG: - print('DECODE({0}, {1}) [floating index: {2}]'.format( + if DEBUG >= 2: + print('D[{0}]({1}) (listed: {2})'.format( client, - dataline[vbegin:vend], - decodes.index((client, dataline[vbegin:vend])))) + data_line[val_begin:val_end], + data_line[val_begin:val_end] in client_decodes[client])) + + data_file.close() + except: # StandardError as se: + #print(se.message) + + #if DEBUG >= 2: + # print(pickle.dumps(se.args)) - datafile.close() - except: - # TODO: need to handle return False - # this will need to change if we ever have a client with 100% support - if len(encodes) == 0 and len(decodes) == 0: + # there's always going to be at least one client with one encode or decode + if not len(client_encodes) > 0 and not len(client_decodes) > 0: return False return True def loadserverhandlers(): - # TODO: handle remarked out definitions; add other servers, if possible - try: - filename = '{0}{1}{2}'.format( - repopath, - '/zone', - '/client_packet.cpp') - - if VERBOSE or DEBUG: - print(filename) - - with open(filename, 'r') as datafile: - dataline = datafile.readline() - - while not dataline[:19] == 'void MapOpcodes() {': - dataline = datafile.readline() - - if not dataline: - break - - while True: - dataline = datafile.readline() - - if not dataline: - break - if dataline[0:1] == '}': - break - - kbegin = dataline.find('OP_') - kend = dataline.find(']', kbegin) - - if kbegin == -1: - continue - if kend == -1: - continue - - vbegin = dataline.find('Client::', kend) - vend = dataline.find(';', vbegin) - - if vbegin == -1: - continue - if vend == -1: - continue - - handlers['Zone', dataline[kbegin:kend]] = dataline[vbegin:vend] - - if DEBUG: - print('({0}, {1}) = {2}'.format( - 'Zone', - dataline[kbegin:kend], - handlers['Zone', dataline[kbegin:kend]])) + # TODO: handle remarked out definitions in file (i.e., // and /**/); + # TODO: out-going-only handlers need to be added..more research... + bad_servers = [] - datafile.close() - except: - # should probably do the same for this (badservers) - # as done for badclients in the above function - return False + for server in server_list: + try: + if server == 'Login': + raise + elif server == 'World': + raise + elif server == 'Zone': + file_name = '{0}{1}{2}'.format( + base_path, + '/zone', + '/client_packet.cpp') + + if DEBUG >= 1: + print(file_name) + + with open(file_name, 'r') as data_file: + server_handlers[server] = {} + + data_line = data_file.readline() + + while not data_line[:19] == 'void MapOpcodes() {': + data_line = data_file.readline() + + if not data_line: + break + + while True: + data_line = data_file.readline() + + if not data_line or data_line[0:1] == '}': + break + + key_begin = data_line.find('OP_') + key_end = data_line.find(']', key_begin) + + if key_begin < 0 or key_end < 0: + continue + + val_begin = data_line.find('Client::', key_end) + val_end = data_line.find(';', val_begin) + + if val_begin < 0 or val_end < 0: + continue + + server_handlers[server][data_line[key_begin:key_end]] = data_line[val_begin:val_end] + + if DEBUG >= 2: + print('[{0}][{1}] = {2}'.format( + server, + data_line[key_begin:key_end], + server_handlers[server][data_line[key_begin:key_end]])) + + data_file.close() + elif server == 'UCS': + raise + else: + if DEBUG >= 2: + print('->LoadServerHandlers(Someone added a new server and forgot to code for the data load...)') + + return False + except: # StandardError as se: + #print(se.message) + + #if DEBUG >= 2: + # print(pickle.dumps(se.args)) + + bad_servers.append(server) + + if len(bad_servers) > 0: + for bad_server in bad_servers: + if DEBUG >= 1: + print('Deleting \'{0}\' server from search criteria...'.format(bad_server)) + + server_list.remove(bad_server) + + if DEBUG >= 1: + print('Deleting stale entries for \'{0}\' server...'.format(bad_server)) + + if bad_server in server_handlers: + del server_handlers[bad_server] + + if not len(server_list) > 0: + return False return True def createoutputdirectory(): - outputpath = '' - try: - outputpath = '{0}{1}'.format( - repopath, + output_path = '{0}{1}'.format( + base_path, '/utils/scripts/opcode_handlers_output') - if VERBOSE or DEBUG: - print(outputpath) + if DEBUG >= 1: + print(output_path) - if not os.path.exists(outputpath): - os.mkdir(outputpath) + if not os.path.exists(output_path): + os.mkdir(output_path) return True - except: + except: # StandardError as se: + #print(se.message) + + #if DEBUG >= 2: + # print(pickle.dumps(se.args)) + return False -def createoutputstreams(): - filename = '' - +def openoutputfiles(): try: - for client in clients: - filename = '{0}{1}{2}{3}'.format( - repopath, + #file_name = '{0}{1}{2}'.format( + # base_path, + # '/utils/scripts/opcode_handlers_output/', + # 'Report.txt') + + #if DEBUG >= 1: + # print(file_name) + + #out_files['Report'] = open(file_name, 'w') + + for client in client_list: + file_name = '{0}{1}{2}{3}'.format( + base_path, '/utils/scripts/opcode_handlers_output/', client, '_opcode_handlers.txt') - if VERBOSE or DEBUG: - print(filename) + if DEBUG >= 1: + print(file_name) - outstreams[client] = open(filename, 'w') + out_files[client] = open(file_name, 'w') message = \ - '------------------------------------------------------\n' \ - '|| Opcode-Handler analysis for \'{0}\' client\n' \ - '|| script-generated file @ {1}\n' \ - '||\n' \ - '|| (only cross-linked (active) opcodes are listed)\n' \ - '------------------------------------------------------\n' \ + '>> \'Opcode-Handler\' analysis for \'{0}\' client\n' \ + '>> file generated @ {1}\n' \ '\n'.format( client, ctime(time())) - outstreams[client].write(message) + out_files[client].write(message) - if DEBUG: + if DEBUG >= 2: print(message[:-2]) - except: - for client in clients: - if client in outstreams.keys(): - outstreams[client].close() - del outstreams[client] - if DEBUG: - print('->CreatingClientStream(exception): {0}'.format( - client)) - - return False + for server in server_list: + file_name = '{0}{1}{2}{3}'.format( + base_path, + '/utils/scripts/opcode_handlers_output/', + server, + '_opcode_handlers.txt') - return True + if DEBUG >= 1: + print(file_name) - -def parseopcodedata(): - serveropnames = [] - - for serveropkey in serverops.keys(): - serveropnames.append(serveropkey) - - if DEBUG: - print('->ServerOpKey: {0}'.format( - serveropkey)) - - if len(serveropnames) == 0: - return False - - for server in servers: - # Login, World, UCS not implemented yet - if not server == 'Zone': - if DEBUG: - print('->SkippingServerOpcodeParse: {0}'.format( - server)) - - continue - - handleropnames = [] - - for handlerkey in handlers.keys(): - if handlerkey[0] == server: - handleropnames.append(handlerkey[1]) - - if DEBUG: - print('->HandlerKey: {0}'.format( - handlerkey[1])) - - if len(handleropnames) == 0: - return False - else: - # sort to process opcode names in ascending order - handleropnames.sort() - - for client in clients: - clientopnames = [] - clientencodes = [] - clientdecodes = [] - - totalopcodes = 0 - encodedecode = 0 - encodeonly = 0 - decodeonly = 0 - notranslation = 0 - - for clientopkey in clientops.keys(): - if clientopkey[0] == client: - clientopnames.append(clientopkey[1]) - - if DEBUG: - print('->ClientOpKey: {0}'.format( - clientopkey[1])) - - if len(clientopnames) == 0: - return False - - for encodeentry in encodes: - if encodeentry[0] == client: - clientencodes.append(encodeentry[1]) - - if DEBUG: - print('->EncodeEntry: {0}'.format( - encodeentry[1])) - - if len(clientencodes) == 0: - return False - - for decodeentry in decodes: - if decodeentry[0] == client: - clientdecodes.append(decodeentry[1]) - - if DEBUG: - print('->DecodeEntry: {0}'.format( - decodeentry[1])) - - if len(clientdecodes) == 0: - return False - - for handleropentry in handleropnames: - try: - clientopindex = clientopnames.index(handleropentry) - except: - clientopindex = -1 - - if clientopindex > -1: - val0 = clientopnames[clientopindex] - val1 = serverops[val0] - val2 = clientops[(client, val0)] - val3 = handlers[(server, val0)] - - try: - val4 = clientencodes.index(val0) > -1 - except: - val4 = False - try: - val5 = clientdecodes.index(val0) > -1 - except: - val5 = False - - message = \ - 'Opcode: {0} | {1}: {2} | {3}: {4}\n' \ - ' {5} Handler: \'{6}\'\n' \ - ' Encoded: {7} | Decoded: {8}\n\n'.format( - val0, - server, - val1, - client, - val2, - server, - val3, - val4, - val5) - - outstreams[client].write(message) - - if DEBUG: - print(message[:-2]) - - totalopcodes += 1 - - if val4 and val5: - encodedecode += 1 - elif val4 and not val5: - encodeonly += 1 - elif not val4 and val5: - decodeonly += 1 - elif not val4 and not val5: - notranslation += 1 - - if DEBUG: - print('->EndOfOpcodeLoop: {0}'.format( - val0)) + out_files[server] = open(file_name, 'w') message = \ - 'Statistics -------------------------------------------\n' \ - '|| Server Opcode Type: {0}\n' \ - '|| Handled Opcodes: {1}\n' \ - '|| Bi-directional: {2}\n' \ - '|| Encodes Only: {3}\n' \ - '|| Decodes Only: {4}\n' \ - '|| No Translations: {5}\n' \ - '\n' \ - 'Notes ------------------------------------------------\n' \ - '|| Encodes are Server-to-Client and Decodes are' \ - ' Server-from-Client in context\n' \ - '|| \'Bi-directional\' indicates translations are performed on' \ - ' tx/rx packets\n' \ - '|| \'Encodes Only\' indicates translations only on tx packets' \ - ' - does not exclude direct packet rx\n' \ - '|| \'Decodes Only\' indicates translations only on rx packets' \ - ' - does not exclude direct packet tx\n' \ - '|| \'No Translations\' indicates no translations of tx/rx' \ - ' packets\n'.format( + '>> \'Opcode-Handler\' analysis for \'{0}\' server\n' \ + '>> file generated @ {1}\n' \ + '\n'.format( server, - totalopcodes, - encodedecode, - encodeonly, - decodeonly, - notranslation) + ctime(time())) - outstreams[client].write(message) + out_files[server].write(message) - if DEBUG: - print(message[:-1]) - print('->EndOfClientLoop: {0}'.format( - client)) - - if DEBUG: - print('->EndOfServerLoop: {0}'.format( - server)) + if DEBUG >= 2: + print(message[:-2]) + except: # StandardError as se: + #print(se.message) + + #if DEBUG >= 2: + # print(pickle.dumps(se.args)) + + for client in client_list: + if client in out_files: + out_files[client].close() + del out_files[client] + + if DEBUG >= 2: + print('->OpeningClientStream(exception): {0}'.format(client)) + + for server in server_list: + if server in out_files: + out_files[server].close() + del out_files[server] + + if DEBUG >= 2: + print('->OpeningServerStream(exception): {0}'.format(server)) + + #if 'Report' in out_files: + # out_files['Report'].close() + # del out_files['Report'] + + # if DEBUG >= 2: + # print('->OpeningReportStream(exception)') + + return False return True -def destroyoutputstreams(): - for client in clients: - if client in outstreams.keys(): - outstreams[client].close() - del outstreams[client] +def parseclientopcodedata(): + # TODO: add metrics + for client in client_list: + server_max_len = 0 + + for server in server_list: + if len(server) > server_max_len: + server_max_len = len(server) + + client_keys = client_opcodes[client].keys() + client_keys.sort() + + for client_opcode in client_keys: + handled = client_opcode in server_opcodes + + if handled is True: + encoded = client_opcode in client_encodes[client] + decoded = client_opcode in client_decodes[client] + else: + encoded = 'n/a' + decoded = 'n/a' + + message = 'Opcode: {0} ({1}) | Handled: {2} | Encoded: {3} | Decoded: {4}\n'.format( + client_opcode, + client_opcodes[client][client_opcode], + handled, + encoded, + decoded) + + for server in server_list: + if client_opcode in server_handlers[server]: + val1 = '{0}'.format(server_opcodes[client_opcode]).zfill(4) + val2 = server_handlers[server][client_opcode] + else: + val1 = '0000' + val2 = 'n/a' + + message += ' Server: {0} ({1}) | Handler: \'{2}\'\n'.format( + server.ljust(len(server) + (server_max_len - len(server)), ' '), + val1, + val2) + + if DEBUG >= 2: + print('->EndOfServerLoop: {0}'.format(server)) + + message += '\n' + + out_files[client].write(message) + + if DEBUG >= 2: + print(message[:-2]) + print('->EndOfOpcodeLoop: {0}'.format(client_opcode)) + + if DEBUG >= 2: + print('->EndOfClientLoop: {0}'.format(client)) + + return True + + +def parseserveropcodedata(): + # TODO: add metrics + for server in server_list: + client_max_len = 0 + + for client in client_list: + if len(client) > client_max_len: + client_max_len = len(client) + + handler_keys = server_handlers[server].keys() + handler_keys.sort() + + for handler_opcode in handler_keys: + message = 'Opcode: {0} ({1}) | Handler: \'{2}\'\n'.format( + handler_opcode, + server_opcodes[handler_opcode], + server_handlers[server][handler_opcode]) + + for client in client_list: + if handler_opcode in client_opcodes[client]: + val1 = client_opcodes[client][handler_opcode] + val2 = 'True' + val3 = '{0}'.format(handler_opcode in client_encodes[client]) + val4 = '{0}'.format(handler_opcode in client_decodes[client]) + else: + val1 = '0x0000' + val2 = 'False' + val3 = 'n/a' + val4 = 'n/a' + + message += ' Client: {0} ({1}) | Handled: {2} | Encoded: {3} | Decoded: {4}\n'.format( + client.ljust(len(client) + (client_max_len - len(client)), ' '), + val1, + val2.ljust(len(val2) + (len('False') - len(val2)), ' '), + val3.ljust(len(val3) + (len('False') - len(val3)), ' '), + val4.ljust(len(val4) + (len('False') - len(val4)), ' ')) + + if DEBUG >= 2: + print('->EndOfClientLoop: {0}'.format(client)) + + message += '\n' + + out_files[server].write(message) + + if DEBUG >= 2: + print(message[:-2]) + print('->EndOfOpcodeLoop: {0}'.format(handler_opcode)) + + if DEBUG >= 2: + print('->EndOfServerLoop: {0}'.format(server)) + + return True + + +def closeoutputfiles(): + for client in client_list: + if client in out_files: + out_files[client].close() + del out_files[client] + + if DEBUG >= 2: + print('->ClosingClientStream: {0}'.format(client)) + + for server in server_list: + if server in out_files: + out_files[server].close() + del out_files[server] + + if DEBUG >= 2: + print('->ClosingServerStream: {0}'.format(server)) + + #if 'Report' in out_files: + # out_files['Report'].close() + # del out_files['Report'] + + # if DEBUG >= 2: + # print('->ClosingReportStream') - if DEBUG: - print('->DestroyingClientStream: {0}'.format( - client)) - return True From 2aec190afc0dd714f5120727d4f82de1ca6baa8f Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 8 Aug 2014 13:42:14 -0400 Subject: [PATCH 264/288] Support for spells_new field 'uninterruptable' --- common/shareddb.cpp | 2 +- zone/spell_effects.cpp | 2 +- zone/spells.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index a64fef404..7c7a99efa 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1710,7 +1710,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { for (y = 0; y < 16; y++) sp[tempid].deities[y]=atoi(row[126+y]); - sp[tempid].uninterruptable=atoi(row[146]); + sp[tempid].uninterruptable=atoi(row[146]) != 0; sp[tempid].ResistDiff=atoi(row[147]); sp[tempid].dot_stacking_exempt=atoi(row[148]); sp[tempid].RecourseLink = atoi(row[150]); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 9f6a3866b..8a45cf391 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2711,7 +2711,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) if (buffslot >= 0) break; - if(IsCasting() && MakeRandomInt(0, 100) <= spells[spell_id].base[i]) + if(!spells[spell_id].uninterruptable && IsCasting() && MakeRandomInt(0, 100) <= spells[spell_id].base[i]) InterruptSpell(); break; diff --git a/zone/spells.cpp b/zone/spells.cpp index ca6d80f6f..e9d3eb55a 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1034,7 +1034,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, mlog(SPELLS__CASTING, "Checking Interruption: spell x: %f spell y: %f cur x: %f cur y: %f channelchance %f channeling skill %d\n", GetSpellX(), GetSpellY(), GetX(), GetY(), channelchance, GetSkill(SkillChanneling)); - if(MakeRandomFloat(0, 100) > channelchance) { + if(!spells[spell_id].uninterruptable && MakeRandomFloat(0, 100) > channelchance) { mlog(SPELLS__CASTING_ERR, "Casting of %d canceled: interrupted.", spell_id); InterruptSpell(); return; @@ -4684,7 +4684,7 @@ void Mob::Stun(int duration) if(stunned && stunned_timer.GetRemainingTime() > uint32(duration)) return; - if(casting_spell_id) { + if(IsValidSpell(casting_spell_id) && !spells[casting_spell_id].uninterruptable) { int persistent_casting = spellbonuses.PersistantCasting + itembonuses.PersistantCasting; if(IsClient()) persistent_casting += aabonuses.PersistantCasting; From b7be8fb6257500dd3f5c5ee42ae1a71bca33d2e2 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 8 Aug 2014 15:53:53 -0400 Subject: [PATCH 265/288] fix --- zone/spells.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index e9d3eb55a..b7b5dd169 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -4685,11 +4685,9 @@ void Mob::Stun(int duration) return; if(IsValidSpell(casting_spell_id) && !spells[casting_spell_id].uninterruptable) { - int persistent_casting = spellbonuses.PersistantCasting + itembonuses.PersistantCasting; - if(IsClient()) - persistent_casting += aabonuses.PersistantCasting; + int persistent_casting = spellbonuses.PersistantCasting + itembonuses.PersistantCasting + aabonuses.PersistantCasting; - if(MakeRandomInt(1,99) > persistent_casting) + if(MakeRandomInt(0,99) > persistent_casting) InterruptSpell(); } From e1996e62b0a5a14dfc45522b44dc97ed32d23aee Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 9 Aug 2014 20:59:08 -0400 Subject: [PATCH 266/288] Added 'discovery' code for server handlers - still needs some debug/messaging work --- utils/scripts/opcode_handlers.py | 629 ++++++++++++++++++++++--------- 1 file changed, 445 insertions(+), 184 deletions(-) diff --git a/utils/scripts/opcode_handlers.py b/utils/scripts/opcode_handlers.py index ca4a00d3d..2a1921d5d 100644 --- a/utils/scripts/opcode_handlers.py +++ b/utils/scripts/opcode_handlers.py @@ -9,8 +9,8 @@ # include other servers and clients, and other criteria and features. +import sys import os -# import pickle from time import time, ctime @@ -19,8 +19,8 @@ DEBUG = 1 # {0 - normal, 1 - verbose, 2 - in-depth} base_path = os.getcwd()[:-14] # '/utils/scripts' -client_list = ['6.2', 'Titanium', 'SoF', 'SoD', 'Underfoot', 'RoF'] -server_list = ['Login', 'World', 'Zone', 'UCS'] +client_list = ['6.2', 'Titanium', 'SoF', 'SoD', 'Underfoot', 'RoF', 'RoF2', 'ClientTest'] +server_list = ['Login', 'World', 'Zone', 'UCS', 'ServerTest'] client_opcodes = {} server_opcodes = {} @@ -34,49 +34,138 @@ out_files = {} def main(): - print('Loading source data...') + """ Call each method independently and track success """ - if not loadclientopcodes(): - print('Could not load client opcodes...') - return + fault = False + faults = [] - if not loadserveropcodes(): - print('Could not load server opcodes...') - return + print('') - if not loadclienttranslators(): - print('Could not load client translators...') - return - - if not loadserverhandlers(): - print('Could not load server handlers...') - return + if fault is False: + fault = not createoutputdirectory() - print('Creating output streams...') + if fault is True: + faults.append('createoutputdirectory()') - if not createoutputdirectory(): - print('Could not create output directory...') - return - - if not openoutputfiles(): - print('Could not open output files...') - return + if fault is False: + fault = not opendebugfile() - print('Parsing opcode data...') + if fault is True: + faults.append('opendebugfile()') - if not parseclientopcodedata(): - print('Could not parse client opcode data...') - return + if fault is False: + print('Loading source data...') - if not parseserveropcodedata(): - print('Could not parse server opcode data...') - return + if fault is False: + fault = not loadclientopcodes() - print('Destroying output streams...') + if fault is True: + faults.append('loadclientopcodes()') + if fault is False: + fault = not loadserveropcodes() + + if fault is True: + faults.append('loadserveropcodes()') + + if fault is False: + fault = not loadclienttranslators() + + if fault is True: + faults.append('loadclienttranslators()') + + if fault is False: + fault = not loadserverhandlers() + + if fault is True: + faults.append('loadserverhandlers()') + + if fault is False: + fault = not discoverserverhandlers() + + if fault is True: + faults.append('discoverserverhandlers()') + + if fault is False: + fault = not clearemptyserverentries() + + if fault is True: + faults.append('clearemptyserverentries()') + + if fault is False: + print('Creating output streams...') + + if fault is False: + fault = not openoutputfiles() + + if fault is True: + faults.append('openoutputfiles()') + + if fault is False: + print('Parsing opcode data...') + + if fault is False: + fault = not parseclientopcodedata() + + if fault is True: + faults.append('parseclientopcodedata()') + + if fault is False: + fault = not parseserveropcodedata() + + if fault is True: + faults.append('parseserveropcodedata()') + + if fault is False: + print('Destroying output streams...') + + # these should always be processed..verbose or silent if not closeoutputfiles(): - print('Could not close output files...') - return + faults.append('closeoutputfiles()') + + if not closedebugfile(): + faults.append('closedebugfile()') + + if len(faults) > 0: + message = 'Script failed due to errors in:\n' + + for entry in faults: + message += ' {0}'.format(entry) + + print(message) + + return + + +def createoutputdirectory(): + """ Check for output directory - create if does not exist """ + + try: + output_path = '{0}/utils/scripts/opcode_handlers_output'.format(base_path) + + if DEBUG >= 1: + print(output_path) + + if not os.path.exists(output_path): + os.mkdir(output_path) + + return True + except: + if DEBUG >= 2: + print('EXCEPTION ERROR->createoutputdirectory({0})'.format(sys.exc_info()[0])) + + return False + + +def opendebugfile(): + file_name = '{0}/utils/scripts/opcode_handlers_output/DEBUG.txt'.format(base_path) + + if DEBUG >= 1: + print(file_name) + + out_files['DEBUG'] = open(file_name, 'w') + + return True def loadclientopcodes(): @@ -100,12 +189,7 @@ def loadclientopcodes(): with open(file_name, 'r') as data_file: client_opcodes[client] = {} # force empty dictionary to avoid collisions - while True: - data_line = data_file.readline() - - if not data_line: - break - + for data_line in data_file: key_begin = data_line.find('OP_') key_end = data_line.find('=', key_begin) @@ -133,26 +217,23 @@ def loadclientopcodes(): value)) data_file.close() - except: # StandardError as se: - #print(se.message) - - #if DEBUG >= 2: - # print(pickle.dumps(se.args)) + except: + if DEBUG >= 2: + print('EXCEPTION ERROR->loadclientopcodes({0})'.format(sys.exc_info()[0])) bad_clients.append(client) - if len(bad_clients) > 0: - for bad_client in bad_clients: - if DEBUG >= 1: - print('Deleting \'{0}\' client from search criteria...'.format(bad_client)) + for bad_client in bad_clients: + if DEBUG >= 1: + print('Deleting \'{0}\' client from search criteria...'.format(bad_client)) - client_list.remove(bad_client) + client_list.remove(bad_client) - if DEBUG >= 1: - print('Deleting stale entries for \'{0}\' client...'.format(bad_client)) + if DEBUG >= 1: + print('Deleting stale entries for \'{0}\' client...'.format(bad_client)) - if bad_client in client_opcodes: - del client_opcodes[bad_client] + if bad_client in client_opcodes: + del client_opcodes[bad_client] if not len(client_list) > 0: return False @@ -162,23 +243,23 @@ def loadclientopcodes(): def loadserveropcodes(): try: - value = 1 # Server opcodes are auto-enumerated with a starting reference of '1' + value = 0 - file_name = '{0}{1}{2}'.format( + server_opcodes['OP_Unknown'] = value + value += 1 + + if DEBUG >= 2: + print('N[Server](OP_Unknown) = {0}'.format(server_opcodes['OP_Unknown'])) + + file_name = '{0}{1}'.format( base_path, - '/common', - '/emu_oplist.h') + '/common/emu_oplist.h') if DEBUG >= 1: print(file_name) with open(file_name, 'r') as data_file: - while True: - data_line = data_file.readline() - - if not data_line: - break - + for data_line in data_file: val_begin = data_line.find('OP_', 2) val_end = data_line.find(')', val_begin) @@ -197,21 +278,15 @@ def loadserveropcodes(): data_file.close() - file_name = '{0}{1}{2}'.format( + file_name = '{0}{1}'.format( base_path, - '/common', - '/mail_oplist.h') + '/common/mail_oplist.h') if DEBUG >= 1: print(file_name) with open(file_name, 'r') as data_file: - while True: - data_line = data_file.readline() - - if not data_line: - break - + for data_line in data_file: val_begin = data_line.find('OP_', 2) val_end = data_line.find(')', val_begin) @@ -229,11 +304,9 @@ def loadserveropcodes(): server_opcodes[data_line[val_begin:val_end]])) data_file.close() - except: # StandardError as se: - #print(se.message) - - #if DEBUG >= 2: - # print(pickle.dumps(se.args)) + except: + if DEBUG >= 2: + print('EXCEPTION ERROR->loadserveropcodes({0})'.format(sys.exc_info()[0])) return False @@ -263,12 +336,7 @@ def loadclienttranslators(): client_encodes[client] = [] client_decodes[client] = [] - while True: - data_line = data_file.readline() - - if not data_line: - break - + for data_line in data_file: val_begin = data_line.find('OP_', 2) val_end = data_line.find(')', val_begin) @@ -293,11 +361,9 @@ def loadclienttranslators(): data_line[val_begin:val_end] in client_decodes[client])) data_file.close() - except: # StandardError as se: - #print(se.message) - - #if DEBUG >= 2: - # print(pickle.dumps(se.args)) + except: + if DEBUG >= 2: + print('EXCEPTION ERROR->loadclienttranslators({0})'.format(sys.exc_info()[0])) return False @@ -309,40 +375,46 @@ def loadclienttranslators(): def loadserverhandlers(): + """ Load pre-designated SERVER opcode handlers """ + # TODO: handle remarked out definitions in file (i.e., // and /**/); - # TODO: out-going-only handlers need to be added..more research... bad_servers = [] for server in server_list: try: if server == 'Login': - raise + if DEBUG >= 1: + print('No pre-designated server opcode handlers for \'{0}\''.format(server)) + + continue elif server == 'World': - raise + if DEBUG >= 1: + print('No pre-designated server opcode handlers for \'{0}\''.format(server)) + + continue elif server == 'Zone': - file_name = '{0}{1}{2}'.format( + file_name = '{0}{1}'.format( base_path, - '/zone', - '/client_packet.cpp') + '/zone/client_packet.cpp') if DEBUG >= 1: print(file_name) with open(file_name, 'r') as data_file: server_handlers[server] = {} + can_run = False + line_no = 0 - data_line = data_file.readline() - - while not data_line[:19] == 'void MapOpcodes() {': - data_line = data_file.readline() - - if not data_line: - break - - while True: - data_line = data_file.readline() - - if not data_line or data_line[0:1] == '}': + for data_line in data_file: + line_no += 1 + + if can_run is False: + if data_line[:19] == 'void MapOpcodes() {': + can_run = True + + continue + + if data_line[0:1] == '}': break key_begin = data_line.find('OP_') @@ -357,42 +429,55 @@ def loadserverhandlers(): if val_begin < 0 or val_end < 0: continue - server_handlers[server][data_line[key_begin:key_end]] = data_line[val_begin:val_end] + # TODO: add continue on 'in server_opcodes' failure + + if not data_line[key_begin:key_end] in server_handlers[server]: + server_handlers[server][data_line[key_begin:key_end]] = [] + + server_handlers[server][data_line[key_begin:key_end]].append( + '../zone/client_packet.cpp({0}:{1}) \'{2}\''.format( + line_no, + key_begin, + data_line[val_begin:val_end])) if DEBUG >= 2: - print('[{0}][{1}] = {2}'.format( + print('[{0}][{1}]({2}) [{3}]'.format( server, data_line[key_begin:key_end], - server_handlers[server][data_line[key_begin:key_end]])) + data_line[val_begin:val_end], + data_line[val_begin:val_end] in server_handlers[server][data_line[key_begin:key_end]])) data_file.close() elif server == 'UCS': - raise + if DEBUG >= 1: + print('No pre-designated server opcode handlers for \'{0}\''.format(server)) + + continue else: + if DEBUG >= 1: + print('No pre-designated server opcode handlers for \'{0}\''.format(server)) + if DEBUG >= 2: print('->LoadServerHandlers(Someone added a new server and forgot to code for the data load...)') - return False - except: # StandardError as se: - #print(se.message) - - #if DEBUG >= 2: - # print(pickle.dumps(se.args)) + continue + except: + if DEBUG >= 2: + print('EXCEPTION ERROR->loadserverhandlers({0})'.format(sys.exc_info()[0])) bad_servers.append(server) - if len(bad_servers) > 0: - for bad_server in bad_servers: - if DEBUG >= 1: - print('Deleting \'{0}\' server from search criteria...'.format(bad_server)) + for bad_server in bad_servers: + if DEBUG >= 1: + print('Deleting \'{0}\' server from search criteria...'.format(bad_server)) - server_list.remove(bad_server) + server_list.remove(bad_server) - if DEBUG >= 1: - print('Deleting stale entries for \'{0}\' server...'.format(bad_server)) + if DEBUG >= 1: + print('Deleting stale entries for \'{0}\' server...'.format(bad_server)) - if bad_server in server_handlers: - del server_handlers[bad_server] + if bad_server in server_handlers: + del server_handlers[bad_server] if not len(server_list) > 0: return False @@ -400,39 +485,199 @@ def loadserverhandlers(): return True -def createoutputdirectory(): - try: - output_path = '{0}{1}'.format( - base_path, - '/utils/scripts/opcode_handlers_output') - +def discoverserverhandlers(): + """ Load undefined SERVER opcode handlers using 'discovery' method """ + + locations = {} + + for server in server_list: # initialize lists for any remaining servers + locations[server] = [] + + # manually enter search locations + #if 'Server' in locations: + # locations['Server'].append('//.') + + # TODO: if/how to include perl/lua handlers... + + if 'Login' in locations: + locations['Login'].append('/loginserver/Client.cpp') + locations['Login'].append('/loginserver/ServerManager.cpp') + locations['Login'].append('/loginserver/WorldServer.cpp') + + if 'World' in locations: + locations['World'].append('/world/client.cpp') + + # the bulk of opcodes are handled in 'Zone' - if processing occurs on a different + # server, you will need to manually trace 'ServerPacket' to the deferred location + if 'Zone' in locations: + locations['Zone'].append('/zone/AA.cpp') + locations['Zone'].append('/zone/attack.cpp') + locations['Zone'].append('/zone/bot.cpp') + locations['Zone'].append('/zone/client.cpp') + locations['Zone'].append('/zone/client_packet.cpp') + locations['Zone'].append('/zone/client_process.cpp') + locations['Zone'].append('/zone/command.cpp') + locations['Zone'].append('/zone/corpse.cpp') + locations['Zone'].append('/zone/doors.cpp') + locations['Zone'].append('/zone/effects.cpp') + locations['Zone'].append('/zone/entity.cpp') + locations['Zone'].append('/zone/exp.cpp') + locations['Zone'].append('/zone/groups.cpp') + locations['Zone'].append('/zone/guild.cpp') + locations['Zone'].append('/zone/guild_mgr.cpp') + locations['Zone'].append('/zone/horse.cpp') + locations['Zone'].append('/zone/inventory.cpp') + locations['Zone'].append('/zone/loottables.cpp') + locations['Zone'].append('/zone/merc.cpp') + locations['Zone'].append('/zone/mob.cpp') + locations['Zone'].append('/zone/MobAI.cpp') + locations['Zone'].append('/zone/Object.cpp') + locations['Zone'].append('/zone/pathing.cpp') + locations['Zone'].append('/zone/petitions.cpp') + locations['Zone'].append('/zone/questmgr.cpp') + locations['Zone'].append('/zone/raids.cpp') + locations['Zone'].append('/zone/special_attacks.cpp') + locations['Zone'].append('/zone/spells.cpp') + locations['Zone'].append('/zone/spell_effects.cpp') + locations['Zone'].append('/zone/tasks.cpp') + locations['Zone'].append('/zone/titles.cpp') + locations['Zone'].append('/zone/tradeskills.cpp') + locations['Zone'].append('/zone/trading.cpp') + locations['Zone'].append('/zone/trap.cpp') + locations['Zone'].append('/zone/tribute.cpp') + locations['Zone'].append('/zone/worldserver.cpp') + locations['Zone'].append('/zone/zone.cpp') + locations['Zone'].append('/zone/zonedb.cpp') + locations['Zone'].append('/zone/zoning.cpp') + + if 'UCS' in locations: + locations['UCS'].append('/ucs/clientlist.cpp') + locations['UCS'].append('/ucs/database.cpp') + + for server in server_list: + if not server in server_handlers: + server_handlers[server] = {} + + for location in locations[server]: + try: + file_name = '{0}{1}'.format( + base_path, + location) + + if DEBUG >= 1: + print(file_name) + + with open(file_name, 'r') as data_file: + line_no = 0 + hint = 'Near beginning of file' + + for data_line in data_file: + line_no += 1 + + if data_line[:1].isalpha(): + hint_end = data_line.find('(') + + if not hint_end < 0: + hint_begin = hint_end - 1 + + while not hint_begin < 0: + if data_line[(hint_begin - 1):hint_begin].isspace(): + if not data_line[hint_begin:(hint_begin + 1)].isalpha(): + hint_begin += 1 + + hint = 'Near {0}'.format(data_line[hint_begin:hint_end]) + + break + + hint_begin -= 1 + + op_begin = data_line.find('OP_') + + if op_begin < 0: + continue + + if data_line[(op_begin - 20):op_begin] == 'EQApplicationPacket(': + key_begin = op_begin + key_end = data_line.find(',', key_begin) + elif data_line[(op_begin - 12):op_begin] == '->SetOpcode(': + key_begin = op_begin + key_end = data_line.find(')', key_begin) + elif data_line[(op_begin - 5):op_begin] == 'case ': + key_begin = op_begin + key_end = data_line.find(':', key_begin) + else: + continue + + if key_end < 0: + continue + + if not data_line[key_begin:key_end] in server_opcodes: + out_files['DEBUG'].write('Illegal Opcode Found: ..{0} ({1}:{2}) \'{3}\'\n'.format( + location, + line_no, + key_begin, + data_line[key_begin:key_end] + )) + + continue + + if not data_line[key_begin:key_end] in server_handlers[server]: + server_handlers[server][data_line[key_begin:key_end]] = [] + + if not data_line in server_handlers[server][data_line[key_begin:key_end]]: + server_handlers[server][data_line[key_begin:key_end]].append( + '..{0}({1}:{2}) \'{3}\''.format( + location, + line_no, + key_begin, + hint)) + except: + if DEBUG >= 2: + print('EXCEPTION ERROR->discoverserverhandlers({0})'.format(sys.exc_info()[0])) + + return True + + +def clearemptyserverentries(): + bad_servers = [] + + for server in server_list: + if len(server_handlers[server]) == 0: + bad_servers.append(server) + else: + bad_opcodes = [] + + for opcode in server_handlers[server]: + if len(server_handlers[server][opcode]) == 0: + bad_opcodes.append(opcodes) + + for bad_opcode in bad_opcodes: + del server_handlers[server][bad_opcode] + + if len(server_handlers[server]) == 0: + bad_servers.append(server) + + for bad_server in bad_servers: if DEBUG >= 1: - print(output_path) - - if not os.path.exists(output_path): - os.mkdir(output_path) - - return True - except: # StandardError as se: - #print(se.message) + print('Deleting \'{0}\' server from search criteria...'.format(bad_server)) + print('Deleting stale entries for \'{0}\' server...'.format(bad_server)) - #if DEBUG >= 2: - # print(pickle.dumps(se.args)) + del server_handlers[bad_server] + server_list.remove(bad_server) - return False + return True def openoutputfiles(): + """ Open output files in 'w' mode - create/overwrite mode """ + try: - #file_name = '{0}{1}{2}'.format( - # base_path, - # '/utils/scripts/opcode_handlers_output/', - # 'Report.txt') + file_name = '{0}/utils/scripts/opcode_handlers_output/Report.txt'.format(base_path) - #if DEBUG >= 1: - # print(file_name) + if DEBUG >= 1: + print(file_name) - #out_files['Report'] = open(file_name, 'w') + out_files['Report'] = open(file_name, 'w') for client in client_list: file_name = '{0}{1}{2}{3}'.format( @@ -481,11 +726,9 @@ def openoutputfiles(): if DEBUG >= 2: print(message[:-2]) - except: # StandardError as se: - #print(se.message) - - #if DEBUG >= 2: - # print(pickle.dumps(se.args)) + except: + if DEBUG >= 2: + print('EXCEPTION ERROR->openoutputfiles({0})'.format(sys.exc_info()[0])) for client in client_list: if client in out_files: @@ -503,12 +746,12 @@ def openoutputfiles(): if DEBUG >= 2: print('->OpeningServerStream(exception): {0}'.format(server)) - #if 'Report' in out_files: - # out_files['Report'].close() - # del out_files['Report'] + if 'Report' in out_files: + out_files['Report'].close() + del out_files['Report'] - # if DEBUG >= 2: - # print('->OpeningReportStream(exception)') + if DEBUG >= 2: + print('->OpeningReportStream(exception)') return False @@ -534,8 +777,8 @@ def parseclientopcodedata(): encoded = client_opcode in client_encodes[client] decoded = client_opcode in client_decodes[client] else: - encoded = 'n/a' - decoded = 'n/a' + encoded = 'N/A' + decoded = 'N/A' message = 'Opcode: {0} ({1}) | Handled: {2} | Encoded: {3} | Decoded: {4}\n'.format( client_opcode, @@ -545,17 +788,18 @@ def parseclientopcodedata(): decoded) for server in server_list: - if client_opcode in server_handlers[server]: - val1 = '{0}'.format(server_opcodes[client_opcode]).zfill(4) - val2 = server_handlers[server][client_opcode] - else: - val1 = '0000' - val2 = 'n/a' + if client_opcode in server_handlers[server] and len(server_handlers[server][client_opcode]) > 0: + handler_list = server_handlers[server][client_opcode] + handler_list.sort() - message += ' Server: {0} ({1}) | Handler: \'{2}\'\n'.format( - server.ljust(len(server) + (server_max_len - len(server)), ' '), - val1, - val2) + for handler_entry in handler_list: + message += ' Server: {0} ({1}) | Handler: {2}\n'.format( + server.ljust(len(server) + (server_max_len - len(server)), ' '), + '{0}'.format(server_opcodes[client_opcode]).zfill(4), + handler_entry) + else: + message += ' Server: {0} (0000) | Handler: N/A\n'.format( + server.ljust(len(server) + (server_max_len - len(server)), ' ')) if DEBUG >= 2: print('->EndOfServerLoop: {0}'.format(server)) @@ -587,10 +831,16 @@ def parseserveropcodedata(): handler_keys.sort() for handler_opcode in handler_keys: - message = 'Opcode: {0} ({1}) | Handler: \'{2}\'\n'.format( - handler_opcode, - server_opcodes[handler_opcode], - server_handlers[server][handler_opcode]) + handler_list = server_handlers[server][handler_opcode] + handler_list.sort() + + message = '' + + for handler_entry in handler_list: + message += 'Opcode: {0} ({1}) | Handler: {2}\n'.format( + handler_opcode, + server_opcodes[handler_opcode], + handler_entry) for client in client_list: if handler_opcode in client_opcodes[client]: @@ -601,8 +851,8 @@ def parseserveropcodedata(): else: val1 = '0x0000' val2 = 'False' - val3 = 'n/a' - val4 = 'n/a' + val3 = 'N/A' + val4 = 'N/A' message += ' Client: {0} ({1}) | Handled: {2} | Encoded: {3} | Decoded: {4}\n'.format( client.ljust(len(client) + (client_max_len - len(client)), ' '), @@ -645,12 +895,23 @@ def closeoutputfiles(): if DEBUG >= 2: print('->ClosingServerStream: {0}'.format(server)) - #if 'Report' in out_files: - # out_files['Report'].close() - # del out_files['Report'] + if 'Report' in out_files: + out_files['Report'].close() + del out_files['Report'] - # if DEBUG >= 2: - # print('->ClosingReportStream') + if DEBUG >= 2: + print('->ClosingReportStream') + + return True + + +def closedebugfile(): + if 'DEBUG' in out_files: + out_files['DEBUG'].close() + del out_files['DEBUG'] + + if DEBUG >= 2: + print('->ClosingDEBUGStream') return True From d7eb28c7f82dc94b7202b17928f839f2b542f22d Mon Sep 17 00:00:00 2001 From: KimLS Date: Sun, 10 Aug 2014 02:45:21 -0700 Subject: [PATCH 267/288] Travis CI file --- .travis.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..5bdd64324 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,16 @@ +language: cpp +compiler: gcc +before_install: + - sudo apt-get update -qq + - sudo apt-get install -y libmysqlclient-dev libperl-dev libboost-dev liblua5.1-0-dev zlib1g-dev +script: + - cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON + - make + - ./bin/tests +branches: + only: master +notifications: + email: false + irc: + channels: "irc.eqemulator.net#eqemucoders" +os: linux \ No newline at end of file From 478eb35a3bbb58f673a615010a805388f99c3f18 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 10 Aug 2014 08:37:30 -0400 Subject: [PATCH 268/288] Rule ArcheryHitPenalty fix for calc mistake from prior update. --- zone/attack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 2403293e6..3195b4234 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -311,7 +311,7 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c hitBonus += (attacker->CastToNPC()->GetAccuracyRating() / 10.0f); //Modifier from database if(skillinuse == SkillArchery) - hitBonus -= hitBonus*(RuleR(Combat, ArcheryHitPenalty)*100.0f); + hitBonus -= hitBonus*RuleR(Combat, ArcheryHitPenalty); //Calculate final chance to hit chancetohit += ((chancetohit * (hitBonus - avoidanceBonus)) / 100.0f); From 99b25f42e4a52e4dbc61b25b3802c6ff10652f9f Mon Sep 17 00:00:00 2001 From: Michael Cook Date: Sun, 10 Aug 2014 12:42:43 -0400 Subject: [PATCH 269/288] Add Travis-CI bling --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index edee03cca..bee563054 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ EQEmu - Custom Game Implementation for EverQuest +[![Build Status](https://api.travis-ci.org/EQEmu/Server.svg)](https://travis-ci.org/EQEmu/Server) + Dependencies can be obtained at http://eqemu.github.io More Information: https://github.com/EQEmu/Server/wiki From c02cb2c343d352fbf74420fee588be42807de940 Mon Sep 17 00:00:00 2001 From: Michael Cook Date: Sun, 10 Aug 2014 13:08:50 -0400 Subject: [PATCH 270/288] Proper bling instead of copy paste for another [skip ci] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bee563054..d7ca01121 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ EQEmu - Custom Game Implementation for EverQuest -[![Build Status](https://api.travis-ci.org/EQEmu/Server.svg)](https://travis-ci.org/EQEmu/Server) +[![Build Status](https://travis-ci.org/EQEmu/Server.svg?branch=master)](https://travis-ci.org/EQEmu/Server) Dependencies can be obtained at http://eqemu.github.io From 8940e987c1d7fba36a1f939997590d904ee494b7 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 10 Aug 2014 15:56:58 -0400 Subject: [PATCH 271/288] Fix some compiler warnings --- client_files/export/main.cpp | 4 ++-- client_files/import/main.cpp | 4 ++-- common/shareddb.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client_files/export/main.cpp b/client_files/export/main.cpp index 8aa29bea6..d89976b88 100644 --- a/client_files/export/main.cpp +++ b/client_files/export/main.cpp @@ -70,7 +70,7 @@ void ExportSpells(SharedDatabase *db) { } char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = "SELECT * FROM spells_new ORDER BY id"; + const char *query = "SELECT * FROM spells_new ORDER BY id"; MYSQL_RES *result; MYSQL_ROW row; if(db->RunQuery(query, strlen(query), errbuf, &result)) { @@ -176,7 +176,7 @@ void ExportBaseData(SharedDatabase *db) { } char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = "SELECT * FROM base_data ORDER BY level, class"; + const char *query = "SELECT * FROM base_data ORDER BY level, class"; MYSQL_RES *result; MYSQL_ROW row; if(db->RunQuery(query, strlen(query), errbuf, &result)) { diff --git a/client_files/import/main.cpp b/client_files/import/main.cpp index 8115600bf..d902bc98e 100644 --- a/client_files/import/main.cpp +++ b/client_files/import/main.cpp @@ -61,7 +61,7 @@ int main(int argc, char **argv) { int GetSpellColumns(SharedDatabase *db) { char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = "DESCRIBE spells_new"; + const char *query = "DESCRIBE spells_new"; MYSQL_RES *result; MYSQL_ROW row; int res = 0; @@ -234,4 +234,4 @@ void ImportBaseData(SharedDatabase *db) { } fclose(f); -} \ No newline at end of file +} diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 7c7a99efa..7a9858789 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1775,7 +1775,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { int SharedDatabase::GetMaxBaseDataLevel() { char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = "SELECT MAX(level) FROM base_data"; + const char *query = "SELECT MAX(level) FROM base_data"; MYSQL_RES *result; MYSQL_ROW row; int32 ret = 0; @@ -1826,7 +1826,7 @@ bool SharedDatabase::LoadBaseData() { void SharedDatabase::LoadBaseData(void *data, int max_level) { char *base_ptr = reinterpret_cast(data); char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = "SELECT * FROM base_data ORDER BY level, class ASC"; + const char *query = "SELECT * FROM base_data ORDER BY level, class ASC"; MYSQL_RES *result; MYSQL_ROW row; From 12ded4b5062344629aaf044de6d419ccfb7872c7 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 10 Aug 2014 14:19:35 -0700 Subject: [PATCH 272/288] Fixed bug with non row returning queries crashing. --- common/dbcore.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/common/dbcore.cpp b/common/dbcore.cpp index 9b6236e5a..2435621eb 100644 --- a/common/dbcore.cpp +++ b/common/dbcore.cpp @@ -80,10 +80,10 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo pStatus = Error; // error appears to be a disconnect error, may need to try again. - if (errorNumber == CR_SERVER_LOST || errorNumber == CR_SERVER_GONE_ERROR) + if (errorNumber == CR_SERVER_LOST || errorNumber == CR_SERVER_GONE_ERROR) { - if (retryOnFailureOnce) + if (retryOnFailureOnce) { std::cout << "Database Error: Lost connection, attempting to recover...." << std::endl; MySQLRequestResult requestResult = QueryDatabase(query, querylen, false); @@ -95,18 +95,18 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo } } - + pStatus = Error; - + char *errorBuffer = new char[MYSQL_ERRMSG_SIZE]; snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql)); - + std::cout << "DB Query Error #" << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << std::endl; return MySQLRequestResult(nullptr, 0, 0, 0, 0, (uint32)mysql_errno(&mysql), errorBuffer); - } - + } + char *errorBuffer = new char[MYSQL_ERRMSG_SIZE]; snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql)); @@ -114,21 +114,24 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo std::cout << "DB Query Error #" << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << std::endl; #endif return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(&mysql),errorBuffer); - + } // successful query. get results. MYSQL_RES* res = mysql_store_result(&mysql); - MySQLRequestResult requestResult(res, (uint32)mysql_affected_rows(&mysql), (uint32)mysql_num_rows(res), (uint32)mysql_field_count(&mysql), (uint32)mysql_insert_id(&mysql)); + uint32 rowCount = 0; + if (res != nullptr) + rowCount = (uint32)mysql_num_rows(res); + MySQLRequestResult requestResult(res, (uint32)mysql_affected_rows(&mysql), rowCount, (uint32)mysql_field_count(&mysql), (uint32)mysql_insert_id(&mysql)); #if DEBUG_MYSQL_QUERIES >= 1 - if (requestResult.Success()) + if (requestResult.Success()) { std::cout << "query successful"; if (requestResult.Result()) std::cout << ", " << (int) mysql_num_rows(requestResult.Result()) << " rows returned"; - + std::cout << ", " << requestResult.RowCount() << " rows affected"; std::cout<< std::endl; } From 8b2dba97159cff2d382952dd1c7b3492f84e9b91 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 10 Aug 2014 20:13:01 -0400 Subject: [PATCH 273/288] ST_PetMaster target type support added Targets pets master. (Works for regular and swarm pets) --- common/spdat.h | 4 ++-- zone/spells.cpp | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/common/spdat.h b/common/spdat.h index aaf29e61a..40f5e658f 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -131,10 +131,10 @@ typedef enum { /* 41 */ ST_Group = 0x29, /* 42 */ ST_Directional = 0x2a, //ae around this target between two angles /* 43 */ ST_GroupClientAndPet = 0x2b, -/* 44 */ ST_Beam = 0x2c, //like directional but facing in front of you always +/* 44 */ //ST_Beam = 0x2c, //like directional but facing in front of you always /* 45 */ //ST_Ring = 0x2d, // Like a mix of PB ae + rain spell(has ae duration) /* 46 */ ST_TargetsTarget = 0x2e, // uses the target of your target -/* 47 */ //ST_PetMaster = 0x2e, // uses the master as target +/* 47 */ ST_PetMaster = 0x2f, // uses the master as target } SpellTargetType; typedef enum { diff --git a/zone/spells.cpp b/zone/spells.cpp index b7b5dd169..5d891629e 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1780,6 +1780,24 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce break; } + case ST_PetMaster: + { + + Mob *owner = nullptr; + + if (IsPet()) + owner = GetOwner(); + else if ((IsNPC() && CastToNPC()->GetSwarmOwner())) + owner = entity_list.GetMobID(CastToNPC()->GetSwarmOwner()); + + if (!owner) + return false; + + spell_target = owner; + CastAction = SingleTarget; + break; + } + default: { mlog(SPELLS__CASTING_ERR, "I dont know Target Type: %d Spell: (%d) %s", spells[spell_id].targettype, spell_id, spells[spell_id].name); From 091047d08be6a11caf1018b44da2e3496a6fee51 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 10 Aug 2014 23:07:05 -0400 Subject: [PATCH 274/288] Pretty up the read me [skip ci] --- README.md | 52 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d7ca01121..f2245dcf4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,53 @@ -EQEmu - Custom Game Implementation for EverQuest +EQEmu +=== [![Build Status](https://travis-ci.org/EQEmu/Server.svg?branch=master)](https://travis-ci.org/EQEmu/Server) -Dependencies can be obtained at http://eqemu.github.io +Overview +--- + +EQEmu is a custom server implementation for EverQuest + +Dependencies +--- + +For Windows: http://eqemu.github.io + +Login Server dependencies for Windows/Linux/OSX: http://eqemu.github.io + +For Debian based distros (adjust to your local flavor): + +- libmysqlclient-dev +- libperl-dev +- liblua5.1-0-dev (5.2 should work as well) +- libboost-dev + +Further instructions on building the source can be found on the +[wiki](http://wiki.eqemulator.org/i?M=Wiki). + +Bug reports +--- + +Please use the [issue tracker](issue-tracker) provided by GitHub to send us bug +reports or feature requests. + +The [EQEmu Forums](http://www.eqemulator.org/forums/) also have forums to submit +bugs/get help with bugs. + +Contributions +--- + +The preferred way to contribute is to fork the repo and submit a pull request on +GitHub. If you need help with your changes, you can always post on the forums or +try IRC. You can also post unified diffs (`git diff` should do the trick) on the +[Server Code Submissions](http://www.eqemulator.org/forums/forumdisplay.php?f=669) +forum, although pull requests will be much quicker and easier on all parties. + +Contact +--- + - **User IRC Channel**: `#eqemu` on `irc.eqemulator.net` + - **Developer IRC Channel**: `#eqemucoders` on `irc.eqemulator.net` + +- [EQEmulator Forums](http://www.eqemulator.org/forums) +- [EQEmulator Wiki](http://wiki.eqemulator.org/i?M=Wiki) -More Information: https://github.com/EQEmu/Server/wiki From 321cf17eac088a90eb9eb2d95c0a62f7272aa1c9 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 10 Aug 2014 22:27:25 -0700 Subject: [PATCH 275/288] fixed issue with row request on null result --- common/MySQLRequestRow.cpp | 20 ++++++++++++-------- common/dbcore.cpp | 2 ++ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/common/MySQLRequestRow.cpp b/common/MySQLRequestRow.cpp index 46bdaffd9..f8c2b4c06 100644 --- a/common/MySQLRequestRow.cpp +++ b/common/MySQLRequestRow.cpp @@ -1,6 +1,6 @@ #include "MySQLRequestRow.h" -MySQLRequestRow::MySQLRequestRow(const MySQLRequestRow& row) +MySQLRequestRow::MySQLRequestRow(const MySQLRequestRow& row) : m_Result(row.m_Result), m_MySQLRow(row.m_MySQLRow) { } @@ -26,13 +26,17 @@ MySQLRequestRow& MySQLRequestRow::operator=(MySQLRequestRow& moveItem) moveItem.m_Result = nullptr; moveItem.m_MySQLRow = nullptr; - + return *this; } MySQLRequestRow::MySQLRequestRow(MYSQL_RES *result) - : m_Result(result), m_MySQLRow(mysql_fetch_row(m_Result)) + : m_Result(result) { + if (result != nullptr) + m_MySQLRow = mysql_fetch_row(result); + else + m_MySQLRow = nullptr; } MySQLRequestRow& MySQLRequestRow::operator++() @@ -41,19 +45,19 @@ MySQLRequestRow& MySQLRequestRow::operator++() return *this; } -MySQLRequestRow MySQLRequestRow::operator++(int) +MySQLRequestRow MySQLRequestRow::operator++(int) { - MySQLRequestRow tmp(*this); - operator++(); + MySQLRequestRow tmp(*this); + operator++(); return tmp; } -bool MySQLRequestRow::operator==(const MySQLRequestRow& rhs) +bool MySQLRequestRow::operator==(const MySQLRequestRow& rhs) { return m_MySQLRow == rhs.m_MySQLRow; } -bool MySQLRequestRow::operator!=(const MySQLRequestRow& rhs) +bool MySQLRequestRow::operator!=(const MySQLRequestRow& rhs) { return m_MySQLRow != rhs.m_MySQLRow; } diff --git a/common/dbcore.cpp b/common/dbcore.cpp index 2435621eb..3d25236c7 100644 --- a/common/dbcore.cpp +++ b/common/dbcore.cpp @@ -120,8 +120,10 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo // successful query. get results. MYSQL_RES* res = mysql_store_result(&mysql); uint32 rowCount = 0; + if (res != nullptr) rowCount = (uint32)mysql_num_rows(res); + MySQLRequestResult requestResult(res, (uint32)mysql_affected_rows(&mysql), rowCount, (uint32)mysql_field_count(&mysql), (uint32)mysql_insert_id(&mysql)); From f1b8908c9a04c227036c2ba4920e93fbd4a14e4d Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Mon, 11 Aug 2014 13:55:25 -0700 Subject: [PATCH 276/288] Fixed bug with ErrorBuffer being overwritten on non query requests --- common/MySQLRequestResult.cpp | 45 +++++++++++++---------------------- 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/common/MySQLRequestResult.cpp b/common/MySQLRequestResult.cpp index 56e62ae37..f364bf9b2 100644 --- a/common/MySQLRequestResult.cpp +++ b/common/MySQLRequestResult.cpp @@ -10,35 +10,24 @@ MySQLRequestResult::MySQLRequestResult() MySQLRequestResult::MySQLRequestResult(MYSQL_RES* result, uint32 rowsAffected, uint32 rowCount, uint32 columnCount, uint32 lastInsertedID, uint32 errorNumber, char *errorBuffer) : m_CurrentRow(result), m_OneBeyondRow() { - if (errorBuffer != nullptr) - m_Success = false; - else if (errorBuffer == nullptr && result == nullptr) - { - m_Success = false; - -#ifdef _EQDEBUG - std::cout << "DB Query Error: No Result" << std::endl; -#endif - m_ErrorNumber = UINT_MAX; - m_ErrorBuffer = new char[MYSQL_ERRMSG_SIZE]; - - strcpy(m_ErrorBuffer, "DBcore::RunQuery: No Result"); - } - else - m_Success = true; - - m_Result = result; - m_ErrorBuffer = errorBuffer; + m_Result = result; m_RowsAffected = rowsAffected; m_RowCount = rowCount; m_ColumnCount = columnCount; - // If we actually need the column length / fields it will be - // requested at that time, no need to pull it in just to cache it. - // Normal usage would have it as nullptr most likely anyways. - m_ColumnLengths = nullptr; - m_Fields = nullptr; m_LastInsertedID = lastInsertedID; - m_ErrorNumber = errorNumber; + + // If we actually need the column length / fields it will be + // requested at that time, no need to pull it in just to cache it. + // Normal usage would have it as nullptr most likely anyways. + m_ColumnLengths = nullptr; + m_Fields = nullptr; + + if (errorBuffer != nullptr) + m_Success = false; + + m_Success = true; + m_ErrorNumber = errorNumber; + m_ErrorBuffer = errorBuffer; } void MySQLRequestResult::FreeInternals() @@ -113,7 +102,7 @@ MySQLRequestResult::MySQLRequestResult(MySQLRequestResult&& moveItem) m_ColumnLengths = moveItem.m_ColumnLengths; m_Fields = moveItem.m_Fields; - // Keeps deconstructor from double freeing + // Keeps deconstructor from double freeing // pre move instance. moveItem.ZeroOut(); } @@ -140,8 +129,8 @@ MySQLRequestResult& MySQLRequestResult::operator=(MySQLRequestResult&& other) m_ColumnLengths = other.m_ColumnLengths; m_Fields = other.m_Fields; - // Keeps deconstructor from double freeing + // Keeps deconstructor from double freeing // pre move instance. other.ZeroOut(); return *this; -} \ No newline at end of file +} From cfd636499908ece72ec76ee7c9aaa842479be7dd Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 11 Aug 2014 18:55:00 -0400 Subject: [PATCH 277/288] Re-worked server 'discovery' code to better handle inclusions and exclusions. --- utils/scripts/opcode_handlers.py | 1178 ++++++++++++++++++++++-------- 1 file changed, 868 insertions(+), 310 deletions(-) diff --git a/utils/scripts/opcode_handlers.py b/utils/scripts/opcode_handlers.py index 2a1921d5d..ddad43eda 100644 --- a/utils/scripts/opcode_handlers.py +++ b/utils/scripts/opcode_handlers.py @@ -1,12 +1,15 @@ #! /usr/bin/env python # -# This script generates cross-references to show associated (handled) opcodes -# between the server and client. It will generate files for each client and -# server found, and provide some basic information..such as opcode names and -# values, server handler and whether opcodes are translated on tx/rx, etc... -# -# It's currently limited to the 'Zone' server..but, can be expounded upon to -# include other servers and clients, and other criteria and features. + +""" +'Opcode-Handlers' for EQEmulator + +This script generates cross-references to show associated (handled) opcodes +between the server and client. It will generate files for each client and +server found, and provide some basic information..such as opcode names and +values, server handler and whether opcodes are translated on tx/rx, etc... + +""" import sys @@ -15,122 +18,137 @@ import os from time import time, ctime -DEBUG = 1 # {0 - normal, 1 - verbose, 2 - in-depth} +VERBOSE = False # messaging: {False - minimal, True - robust} base_path = os.getcwd()[:-14] # '/utils/scripts' +base_path = base_path.replace('\\', '/') client_list = ['6.2', 'Titanium', 'SoF', 'SoD', 'Underfoot', 'RoF', 'RoF2', 'ClientTest'] server_list = ['Login', 'World', 'Zone', 'UCS', 'ServerTest'] -client_opcodes = {} -server_opcodes = {} +client_opcodes = {} # x[key='Client'][key='OP_CodeName'](value='0x####') +server_opcodes = {} # x[key='OP_CodeName'](value=) - opcodes apply to all servers -client_encodes = {} -client_decodes = {} +client_encodes = {} # x[key='Client'](value='OP_CodeName') +client_decodes = {} # x[key='Client'](value='OP_CodeName') -server_handlers = {} +server_handlers = {} # x[key='Server'][key='OP_CodeName'](value='[%X] Near Handler::ReferenceFunction') -out_files = {} +out_files = {} # x[key='Server'](value=) + +#statistics = {} +#report_entries = {} def main(): - """ Call each method independently and track success """ + """ Call TASK METHODS independently and track success """ fault = False faults = [] - print('') + print('Initializing...') - if fault is False: + if not fault: fault = not createoutputdirectory() - if fault is True: + if fault: faults.append('createoutputdirectory()') - if fault is False: + if not fault: fault = not opendebugfile() - if fault is True: + if fault: faults.append('opendebugfile()') - if fault is False: + if not fault: + fault = not openundefinedfile() + + if fault: + faults.append('openundefinedfile()') + + if not fault: print('Loading source data...') - if fault is False: + if not fault: fault = not loadclientopcodes() - if fault is True: + if fault: faults.append('loadclientopcodes()') - if fault is False: + if not fault: fault = not loadserveropcodes() - if fault is True: + if fault: faults.append('loadserveropcodes()') - if fault is False: + if not fault: fault = not loadclienttranslators() - if fault is True: + if fault: faults.append('loadclienttranslators()') - if fault is False: + if not fault: fault = not loadserverhandlers() - if fault is True: + if fault: faults.append('loadserverhandlers()') - if fault is False: + if not fault: fault = not discoverserverhandlers() - if fault is True: + if fault: faults.append('discoverserverhandlers()') - if fault is False: + if not fault: fault = not clearemptyserverentries() - if fault is True: + if fault: faults.append('clearemptyserverentries()') - if fault is False: + if not fault: print('Creating output streams...') - if fault is False: + if not fault: fault = not openoutputfiles() - if fault is True: + if fault: faults.append('openoutputfiles()') - if fault is False: + if not fault: print('Parsing opcode data...') - if fault is False: + if not fault: fault = not parseclientopcodedata() - if fault is True: + if fault: faults.append('parseclientopcodedata()') - if fault is False: + if not fault: fault = not parseserveropcodedata() - if fault is True: + if fault: faults.append('parseserveropcodedata()') - if fault is False: + if not fault: print('Destroying output streams...') - # these should always be processed..verbose or silent if not closeoutputfiles(): + fault = True faults.append('closeoutputfiles()') + if not closeundefinedfile(): + fault = True + faults.append('closeundefinedfile()') + if not closedebugfile(): + fault = True faults.append('closedebugfile()') - if len(faults) > 0: + if fault and len(faults) > 0: message = 'Script failed due to errors in:\n' for entry in faults: - message += ' {0}'.format(entry) + message += ' {0}\n'.format(entry) print(message) @@ -138,58 +156,105 @@ def main(): def createoutputdirectory(): - """ Check for output directory - create if does not exist """ + """ Check for OUTPUT DIRECTORY - create if does not exist """ try: output_path = '{0}/utils/scripts/opcode_handlers_output'.format(base_path) - if DEBUG >= 1: - print(output_path) + vprint(output_path) if not os.path.exists(output_path): os.mkdir(output_path) return True except: - if DEBUG >= 2: - print('EXCEPTION ERROR->createoutputdirectory({0})'.format(sys.exc_info()[0])) + print('(Exception Error: {0}) createoutputdirectory()'.format(sys.exc_info()[0])) return False def opendebugfile(): - file_name = '{0}/utils/scripts/opcode_handlers_output/DEBUG.txt'.format(base_path) + """ DEBUG FILE should always open """ - if DEBUG >= 1: - print(file_name) + try: + file_name = '{0}/utils/scripts/opcode_handlers_output/DEBUG.txt'.format(base_path) - out_files['DEBUG'] = open(file_name, 'w') + vprint(file_name) - return True + out_files['DEBUG'] = open(file_name, 'w') + + dprint( + '>> \'Opcode-Handler\' DEBUG dump file\n' + '>> file generated @ {0}\n\n' + '->open: \'{1}\' in \'w\' mode\n' + 'leaving \'opendebugfile()\'\n\n'.format( + ctime(time()), + file_name + ) + ) + + return True + except: + print('(Exception Error: {0}) opendebugfile()'.format(sys.exc_info()[0])) + + return False + + +def openundefinedfile(): + """ UNDEFINED FILE should always open """ + + dprint('entering \'openundefinedfile()\'\n') + + try: + file_name = '{0}/utils/scripts/opcode_handlers_output/Undefined.txt'.format(base_path) + + vprint(file_name) + + out_files['Undefined'] = open(file_name, 'w') + + uprint( + '>> \'Opcode-Handler\' Undefined dump file\n' + '>> file generated @ {0}\n\n'.format(ctime(time())) + ) + + dprint( + '->open: \'{0}\' in \'w\' mode\n' + 'leaving \'openundefinedfile()\'\n\n'.format(file_name) + ) + + return True + except: + print('(Exception Error: {0}) openundefinedfile()'.format(sys.exc_info()[0])) + + return False def loadclientopcodes(): + """ Load CLIENT OPCODES into memory """ + + dprint('entering \'loadclientopcodes()\'\n') + bad_clients = [] for client in client_list: try: - short_name = '{0}{1}{2}'.format( - '/patch_', - client, - '.conf') + short_name = '/patch_{0}.conf'.format(client) - file_name = '{0}{1}{2}'.format( + file_name = '{0}/utils/patches{1}'.format( base_path, - '/utils/patches', - short_name) + short_name + ) - if DEBUG >= 1: - print(file_name) + vprint(file_name) with open(file_name, 'r') as data_file: - client_opcodes[client] = {} # force empty dictionary to avoid collisions + dprint('->open: \'{0}\' in \'r\' mode\n'.format(file_name)) + + client_opcodes[client] = {} + line_no = 0 for data_line in data_file: + line_no += 1 key_begin = data_line.find('OP_') key_end = data_line.find('=', key_begin) @@ -197,7 +262,7 @@ def loadclientopcodes(): continue val_begin = data_line.find('0x', key_end) - val_end = val_begin + 6 # max size is always 6 bytes + val_end = val_begin + 6 if val_begin < 0: continue @@ -209,57 +274,89 @@ def loadclientopcodes(): client_opcodes[client][data_line[key_begin:key_end]] = '0x{0}'.format(hex(value)[2:].zfill(4)) - if DEBUG >= 2: - print('[{0}][{1}] = {2} (int: {3})'.format( - client, - data_line[key_begin:key_end], - client_opcodes[client][data_line[key_begin:key_end]], - value)) + dprint('../utils/patches{0}({1}:{2}) [{3}][{4}] = {5}\n'.format( + short_name, + line_no, + key_begin, + client, + data_line[key_begin:key_end], + client_opcodes[client][data_line[key_begin:key_end]] + )) data_file.close() + + dprint('->close: \'{0}\'\n'.format(file_name)) + + if not len(client_opcodes[client]) > 0: + bad_clients.append(client) except: - if DEBUG >= 2: - print('EXCEPTION ERROR->loadclientopcodes({0})'.format(sys.exc_info()[0])) + print('(Exception Error: {0}) loadclientopcodes() [{1}]'.format( + sys.exc_info()[0], + client + )) + + dprint('<-except: \'{0} [{1}]\'\n'.format( + sys.exc_info()[0], + client + )) bad_clients.append(client) for bad_client in bad_clients: - if DEBUG >= 1: - print('Deleting \'{0}\' client from search criteria...'.format(bad_client)) + vprint('Deleting \'{0}\' client from search criteria...'.format(bad_client)) client_list.remove(bad_client) - if DEBUG >= 1: - print('Deleting stale entries for \'{0}\' client...'.format(bad_client)) + dprint('->delete: \'{0}\' client\n'.format(bad_client)) if bad_client in client_opcodes: + vprint('Deleting stale entries for \'{0}\' client...'.format(bad_client)) + del client_opcodes[bad_client] - + + dprint('->delete: \'{0}\' client opcode entries\n'.format(bad_client)) + if not len(client_list) > 0: + print('Could not locate valid clients...') + + dprint('leaving \'loadclientopcodes(): NO VALID CLIENTS EXIST\'\n\n') + return False + if not len(client_opcodes) > 0: + print('Could not locate client opcode lists...') + + dprint('leaving \'loadclientopcodes(): CLIENT OPCODES NOT FOUND\'\n\n') + + return False + + dprint('leaving \'loadclientopcodes()\'\n\n') + return True def loadserveropcodes(): + """ Load SERVER OPCODES into memory """ + + dprint('entering \'loadserveropcodes()\'\n') + try: - value = 0 + server_opcodes['OP_Unknown'] = 0 + value = 1 - server_opcodes['OP_Unknown'] = value - value += 1 + dprint('(manual) \'Servers\' [OP_Unknown] = {0}\n'.format(server_opcodes['OP_Unknown'])) - if DEBUG >= 2: - print('N[Server](OP_Unknown) = {0}'.format(server_opcodes['OP_Unknown'])) + file_name = '{0}/common/emu_oplist.h'.format(base_path) - file_name = '{0}{1}'.format( - base_path, - '/common/emu_oplist.h') - - if DEBUG >= 1: - print(file_name) + vprint(file_name) with open(file_name, 'r') as data_file: + dprint('->open: \'{0}\' in \'r\' mode\n'.format(file_name)) + + line_no = 0 + for data_line in data_file: + line_no += 1 val_begin = data_line.find('OP_', 2) val_end = data_line.find(')', val_begin) @@ -270,23 +367,28 @@ def loadserveropcodes(): server_opcodes[data_line[val_begin:val_end]] = value value += 1 - if DEBUG >= 2: - print('N[{0}]({1}) = {2}'.format( - 'Server', - data_line[val_begin:val_end], - server_opcodes[data_line[val_begin:val_end]])) + dprint('../common/emu_oplist.h({0}:{1}) \'Servers\' [{2}] = {3}\n'.format( + line_no, + val_begin, + data_line[val_begin:val_end], + server_opcodes[data_line[val_begin:val_end]] + )) data_file.close() - file_name = '{0}{1}'.format( - base_path, - '/common/mail_oplist.h') + dprint('->close: \'{0}\'\n'.format(file_name)) - if DEBUG >= 1: - print(file_name) + file_name = '{0}/common/mail_oplist.h'.format(base_path) + + vprint(file_name) with open(file_name, 'r') as data_file: + dprint('->open: \'{0}\' in \'r\' mode\n'.format(file_name)) + + line_no = 0 + for data_line in data_file: + line_no += 1 val_begin = data_line.find('OP_', 2) val_end = data_line.find(')', val_begin) @@ -297,46 +399,72 @@ def loadserveropcodes(): server_opcodes[data_line[val_begin:val_end]] = value value += 1 - if DEBUG >= 2: - print('N[{0}]({1}) = {2}'.format( - 'Server', - data_line[val_begin:val_end], - server_opcodes[data_line[val_begin:val_end]])) + dprint('../common/mail_oplist.h({0}:{1}) \'Servers\' [{2}] = {3}\n'.format( + line_no, + val_begin, + data_line[val_begin:val_end], + server_opcodes[data_line[val_begin:val_end]] + )) data_file.close() + + dprint('->close: \'{0}\'\n'.format(file_name)) except: - if DEBUG >= 2: - print('EXCEPTION ERROR->loadserveropcodes({0})'.format(sys.exc_info()[0])) + print('(Exception Error: {0}) loadserveropcodes()'.format(sys.exc_info()[0])) + + dprint('leaving \'loadserveropcodes(): EXCEPTION ERROR\'\n\n') return False + if not len(server_opcodes) > 0: + print('Could not locate server opcode list...') + + dprint('leaving \'loadserveropcodes(): SERVER OPCODES NOT FOUND\'\n\n') + + return False + + dprint('leaving \'loadserveropcodes()\'\n\n') + return True def loadclienttranslators(): + """ + Load CLIENT ENCODES and CLIENT DECODES OPCODES into memory + + The CLIENT LIST should be clean of any invalid entries by the time this + function is called. Client translator load failures are only commented + upon in output streams and do not trigger a removal of the client. + + """ + + dprint('entering \'loadclienttranslators()\'\n') + + bad_clients = [] + for client in client_list: - if client == '6.2': - short_name = '{0}'.format('/Client62_ops.h') - else: - short_name = '{0}{1}{2}'.format( - '/', - client, - '_ops.h') - try: - file_name = '{0}{1}{2}'.format( + if client == '6.2': + short_name = '/Client62_ops.h' + else: + short_name = '/{0}_ops.h'.format(client) + + file_name = '{0}/common/patches{1}'.format( base_path, - '/common/patches', - short_name) + short_name + ) - if DEBUG >= 1: - print(file_name) + vprint(file_name) with open(file_name, 'r') as data_file: + dprint('->open: \'{0}\' in \'r\' mode\n'.format(file_name)) + client_encodes[client] = [] client_decodes[client] = [] + line_no = 0 for data_line in data_file: + line_no += 1 val_begin = data_line.find('OP_', 2) val_end = data_line.find(')', val_begin) @@ -345,159 +473,254 @@ def loadclienttranslators(): if data_line[:1] == 'E': client_encodes[client].append(data_line[val_begin:val_end]) - - if DEBUG >= 2: - print('E[{0}]({1}) (listed: {2})'.format( - client, - data_line[val_begin:val_end], - data_line[val_begin:val_end] in client_encodes[client])) + + dprint('..{0}({1}:{2}) \'ENCODE\' [{3}] = {4}\n'.format( + short_name, + line_no, + val_begin, + client, + data_line[val_begin:val_end] + )) elif data_line[:1] == 'D': client_decodes[client].append(data_line[val_begin:val_end]) - if DEBUG >= 2: - print('D[{0}]({1}) (listed: {2})'.format( - client, - data_line[val_begin:val_end], - data_line[val_begin:val_end] in client_decodes[client])) + dprint('..{0}({1}:{2}) \'DECODE\' [{3}] = {4}\n'.format( + short_name, + line_no, + val_begin, + client, + data_line[val_begin:val_end] + )) data_file.close() + + dprint('->close: \'{0}\'\n'.format(file_name)) except: - if DEBUG >= 2: - print('EXCEPTION ERROR->loadclienttranslators({0})'.format(sys.exc_info()[0])) + print('(Exception Error: {0}) loadclienttranslators() [{1}]'.format( + sys.exc_info()[0], + client + )) - return False + dprint('<-except: \'{0} [{1}]\'\n'.format( + sys.exc_info()[0], + client + )) + + bad_clients.append(client) + + for bad_client in bad_clients: + if bad_client in client_encodes or bad_client in client_decodes: + vprint('Deleting stale entries for \'{0}\' client...'.format(bad_client)) + + if bad_client in client_encodes: + del client_encodes[bad_client] + + dprint('->delete: \'{0}\' client encode entries\n'.format(bad_client)) + + if bad_client in client_decodes: + del client_decodes[bad_client] + + dprint('->delete: \'{0}\' client decode entries\n'.format(bad_client)) - # there's always going to be at least one client with one encode or decode if not len(client_encodes) > 0 and not len(client_decodes) > 0: + dprint('leaving \'loadclienttranslators(): NO CLIENT ENCODES OR DECODES FOUND\'\n\n') + return False + dprint('leaving \'loadclienttranslators()\'\n\n') + return True def loadserverhandlers(): - """ Load pre-designated SERVER opcode handlers """ + """ Load pre-designated SERVER OPCODE HANDLERS """ + + # TODO: handle remarked out definitions in file (i.e., // and /**/) + + dprint('entering \'loadserverhandlers()\'\n') - # TODO: handle remarked out definitions in file (i.e., // and /**/); bad_servers = [] for server in server_list: try: if server == 'Login': - if DEBUG >= 1: - print('No pre-designated server opcode handlers for \'{0}\''.format(server)) + vprint('No pre-designated server opcode handlers for \'Login\'') + dprint('->pass: \'Login\' server\n') continue elif server == 'World': - if DEBUG >= 1: - print('No pre-designated server opcode handlers for \'{0}\''.format(server)) + vprint('No pre-designated server opcode handlers for \'World\'') + dprint('->pass: \'World\' server\n') continue elif server == 'Zone': - file_name = '{0}{1}'.format( - base_path, - '/zone/client_packet.cpp') + file_name = '{0}/zone/client_packet.cpp'.format(base_path) - if DEBUG >= 1: - print(file_name) + vprint(file_name) with open(file_name, 'r') as data_file: + dprint('->open: \'{0}\' in \'r\' mode\n'.format(file_name)) + server_handlers[server] = {} - can_run = False + handler_assigns = {} + step_1 = False + step_2 = False line_no = 0 + hint = 'Near beginning of file' for data_line in data_file: line_no += 1 - if can_run is False: + if step_1 is False: if data_line[:19] == 'void MapOpcodes() {': - can_run = True + step_1 = True continue - if data_line[0:1] == '}': - break + if step_2 is False: + if data_line[0:1] == '}': + step_2 = True + + continue + + val_begin = data_line.find('OP_') + val_end = data_line.find(']', val_begin) - key_begin = data_line.find('OP_') - key_end = data_line.find(']', key_begin) + if val_begin < 0 or val_end < 0: + continue + + if not data_line[val_begin:val_end] in server_opcodes: + dprint('\nILLEGAL OPCODE FOUND: ../zone/client_packet.cpp({0}:{1}) \'{2}\'\n'.format( + line_no, + val_begin, + data_line[val_begin:val_end] + )) + + continue + + key_begin = data_line.find('Client::', val_end) + key_end = data_line.find(';', key_begin) - if key_begin < 0 or key_end < 0: - continue - - val_begin = data_line.find('Client::', key_end) - val_end = data_line.find(';', val_begin) - - if val_begin < 0 or val_end < 0: + if key_begin < 0 or key_end < 0: + continue + + if not data_line[key_begin:key_end] in handler_assigns: + handler_assigns[data_line[key_begin:key_end]] = data_line[val_begin:val_end] + continue - # TODO: add continue on 'in server_opcodes' failure + if data_line[:1].isalpha(): + hint_begin = 0 + hint_end = data_line.find('(') - if not data_line[key_begin:key_end] in server_handlers[server]: - server_handlers[server][data_line[key_begin:key_end]] = [] + if not hint_end < 0: + hint_begin = hint_end - 1 - server_handlers[server][data_line[key_begin:key_end]].append( - '../zone/client_packet.cpp({0}:{1}) \'{2}\''.format( + while not hint_begin < 0: + if data_line[(hint_begin - 1):hint_begin].isspace(): + if not data_line[hint_begin:(hint_begin + 1)].isalpha(): + hint_begin += 1 + + hint = '[RX] Near {0}'.format(data_line[hint_begin:hint_end]) + + break + + hint_begin -= 1 + else: + continue + + if hint[10:] in handler_assigns: + if not handler_assigns[hint[10:]] in server_handlers[server]: + server_handlers[server][handler_assigns[hint[10:]]] = [] + + server_handlers[server][handler_assigns[hint[10:]]].append( + '../zone/client_packet.cpp({0}:{1}) \'{2}\''.format( + line_no, + hint_begin, + hint + ) + ) + + dprint('../zone/client_packet.cpp({0}:{1}) [{2}][{3}] = \'{4}\'\n'.format( line_no, - key_begin, - data_line[val_begin:val_end])) - - if DEBUG >= 2: - print('[{0}][{1}]({2}) [{3}]'.format( + hint_begin, server, - data_line[key_begin:key_end], - data_line[val_begin:val_end], - data_line[val_begin:val_end] in server_handlers[server][data_line[key_begin:key_end]])) + handler_assigns[hint[10:]], + hint + )) + + del handler_assigns[hint[10:]] + + if len(handler_assigns) > 0: + for unhandled in handler_assigns: + dprint('\nUNMATCHED DESIGNATED HANDLER FOUND: ../zone/client_packet.cpp \'{0}\'\n'.format( + unhandled + )) data_file.close() + + dprint('->close: \'{0}\'\n'.format(file_name)) elif server == 'UCS': - if DEBUG >= 1: - print('No pre-designated server opcode handlers for \'{0}\''.format(server)) + vprint('No pre-designated server opcode handlers for \'UCS\'') + dprint('->pass: \'UCS\' server\n') continue else: - if DEBUG >= 1: - print('No pre-designated server opcode handlers for \'{0}\''.format(server)) - - if DEBUG >= 2: - print('->LoadServerHandlers(Someone added a new server and forgot to code for the data load...)') + vprint('No pre-designated server opcode handlers for \'{0}\''.format(server)) + dprint('->pass: \'{0}\' server\n'.format(server)) continue except: - if DEBUG >= 2: - print('EXCEPTION ERROR->loadserverhandlers({0})'.format(sys.exc_info()[0])) + print('(Exception Error: {0}) loadserverhandlers() [{1}]'.format( + sys.exc_info()[0], + server + )) + + dprint('<-except: \'{0} [{1}]\'\n'.format( + sys.exc_info()[0], + server + )) bad_servers.append(server) for bad_server in bad_servers: - if DEBUG >= 1: - print('Deleting \'{0}\' server from search criteria...'.format(bad_server)) - - server_list.remove(bad_server) - - if DEBUG >= 1: - print('Deleting stale entries for \'{0}\' server...'.format(bad_server)) - if bad_server in server_handlers: + vprint('Deleting stale entries for \'{0}\' server...'.format(bad_server)) + del server_handlers[bad_server] - if not len(server_list) > 0: - return False + dprint('->delete: \'{0}\' server designated handler entries\n'.format(bad_server)) + + dprint('leaving \'loadserverhandlers()\'\n\n') return True def discoverserverhandlers(): - """ Load undefined SERVER opcode handlers using 'discovery' method """ + """ + Load undefined SERVER OPCODE HANDLERS using 'discovery' method + When adding new servers and/or search locations, use the following format: + + if 'Server' in locations: + locations['Server'].append('//.') + + Lists are instantiated for all SERVERS in SERVER LIST. The lists are then appended + with location data based on the presence of the list in the parent dictionary. + + """ + + # TODO: handle remarked out definitions in file (i.e., // and /**/) + # TODO: if/how to include perl/lua handlers... + + dprint('entering \'discoverserverhandlers()\'\n') + + bad_servers = [] locations = {} - for server in server_list: # initialize lists for any remaining servers - locations[server] = [] - - # manually enter search locations - #if 'Server' in locations: - # locations['Server'].append('//.') - - # TODO: if/how to include perl/lua handlers... + for server in server_list: + if not server in locations: + locations[server] = [] if 'Login' in locations: locations['Login'].append('/loginserver/Client.cpp') @@ -507,8 +730,6 @@ def discoverserverhandlers(): if 'World' in locations: locations['World'].append('/world/client.cpp') - # the bulk of opcodes are handled in 'Zone' - if processing occurs on a different - # server, you will need to manually trace 'ServerPacket' to the deferred location if 'Zone' in locations: locations['Zone'].append('/zone/AA.cpp') locations['Zone'].append('/zone/attack.cpp') @@ -564,10 +785,11 @@ def discoverserverhandlers(): base_path, location) - if DEBUG >= 1: - print(file_name) + vprint(file_name) with open(file_name, 'r') as data_file: + dprint('->open: \'{0}\' in \'r\' mode\n'.format(file_name)) + line_no = 0 hint = 'Near beginning of file' @@ -598,21 +820,192 @@ def discoverserverhandlers(): if data_line[(op_begin - 20):op_begin] == 'EQApplicationPacket(': key_begin = op_begin - key_end = data_line.find(',', key_begin) + key_end = key_begin + 3 + direction = '[TX]' + + while data_line[key_end:(key_end + 1)].isalnum(): + key_end += 1 elif data_line[(op_begin - 12):op_begin] == '->SetOpcode(': key_begin = op_begin - key_end = data_line.find(')', key_begin) + key_end = key_begin + 3 + direction = '[TX]' + + while data_line[key_end:(key_end + 1)].isalnum(): + key_end += 1 elif data_line[(op_begin - 5):op_begin] == 'case ': key_begin = op_begin - key_end = data_line.find(':', key_begin) + key_end = key_begin + 3 + direction = '[RX]' + + while data_line[key_end:(key_end + 1)].isalnum(): + key_end += 1 + elif data_line[(op_begin - 3):op_begin] == '== ': + key_begin = op_begin + key_end = key_begin + 3 + direction = '[RX]' + + while data_line[key_end:(key_end + 1)].isalnum(): + key_end += 1 + elif data_line[(op_begin - 2):op_begin] == '==': + key_begin = op_begin + key_end = key_begin + 3 + direction = '[RX]' + + while data_line[key_end:(key_end + 1)].isalnum(): + key_end += 1 + elif data_line[(op_begin - 3):op_begin] == '!= ': + key_begin = op_begin + key_end = key_begin + 3 + + while data_line[key_end:(key_end + 1)].isalnum(): + key_end += 1 + + dprint( + '\nILL-DEFINED OPCODE CONDITIONAL FOUND: ..{0}({1}:{2}) \'{3}\'\n' + '->line: \'{4}\'\n'.format( + location, + line_no, + key_begin, + data_line[key_begin:key_end], + data_line[:-1] + ) + ) + + continue + elif data_line[(op_begin - 2):op_begin] == '!=': + key_begin = op_begin + key_end = key_begin + 3 + + while data_line[key_end:(key_end + 1)].isalnum(): + key_end += 1 + + dprint( + '\nILL-DEFINED OPCODE CONDITIONAL FOUND: ..{0}({1}:{2}) \'{3}\'\n' + '->line: \'{4}\'\n'.format( + location, + line_no, + key_begin, + data_line[key_begin:key_end], + data_line[:-1] + ) + ) + + continue + elif data_line[(op_begin - 3):op_begin] == '>= ': + key_begin = op_begin + key_end = key_begin + 3 + + while data_line[key_end:(key_end + 1)].isalnum(): + key_end += 1 + + dprint( + '\nILL-DEFINED OPCODE CONDITIONAL FOUND: ..{0}({1}:{2}) \'{3}\'\n' + '->line: \'{4}\'\n'.format( + location, + line_no, + key_begin, + data_line[key_begin:key_end], + data_line[:-1] + ) + ) + + continue + elif data_line[(op_begin - 2):op_begin] == '>=': + key_begin = op_begin + key_end = key_begin + 3 + + while data_line[key_end:(key_end + 1)].isalnum(): + key_end += 1 + + dprint( + '\nILL-DEFINED OPCODE CONDITIONAL FOUND: ..{0}({1}:{2}) \'{3}\'\n' + '->line: \'{4}\'\n'.format( + location, + line_no, + key_begin, + data_line[key_begin:key_end], + data_line[:-1] + ) + ) + + continue + elif data_line[(op_begin - 3):op_begin] == '<= ': + key_begin = op_begin + key_end = key_begin + 3 + + while data_line[key_end:(key_end + 1)].isalnum(): + key_end += 1 + + dprint( + '\nILL-DEFINED OPCODE CONDITIONAL FOUND: ..{0}({1}:{2}) \'{3}\'\n' + '->line: \'{4}\'\n'.format( + location, + line_no, + key_begin, + data_line[key_begin:key_end], + data_line[:-1] + ) + ) + + continue + elif data_line[(op_begin - 2):op_begin] == '<=': + key_begin = op_begin + key_end = key_begin + 3 + + while data_line[key_end:(key_end + 1)].isalnum(): + key_end += 1 + + dprint( + '\nILL-DEFINED OPCODE CONDITIONAL FOUND: ..{0}({1}:{2}) \'{3}\'\n' + '->line: \'{4}\'\n'.format( + location, + line_no, + key_begin, + data_line[key_begin:key_end], + data_line[:-1] + ) + ) + + continue + elif data_line[(op_begin - 2):op_begin] == '= ': + key_begin = op_begin + key_end = key_begin + 3 + direction = '[TX]' + + while data_line[key_end:(key_end + 1)].isalnum(): + key_end += 1 + elif data_line[(op_begin - 1):op_begin] == '=': + key_begin = op_begin + key_end = key_begin + 3 + direction = '[TX]' + + while data_line[key_end:(key_end + 1)].isalnum(): + key_end += 1 else: + key_begin = op_begin + key_end = key_begin + 3 + + while data_line[key_end:(key_end + 1)].isalnum(): + key_end += 1 + + uprint( + '\nUNDEFINED OPCODE CONDITIONAL FOUND: ..{0}({1}:{2}) \'{3}\'\n' + '->line: \'{4}\'\n'.format( + location, + line_no, + key_begin, + data_line[key_begin:key_end], + data_line[:-1] + ) + ) + continue if key_end < 0: continue if not data_line[key_begin:key_end] in server_opcodes: - out_files['DEBUG'].write('Illegal Opcode Found: ..{0} ({1}:{2}) \'{3}\'\n'.format( + dprint('\nILLEGAL OPCODE FOUND: ..{0}({1}:{2}) \'{3}\'\n'.format( location, line_no, key_begin, @@ -624,25 +1017,77 @@ def discoverserverhandlers(): if not data_line[key_begin:key_end] in server_handlers[server]: server_handlers[server][data_line[key_begin:key_end]] = [] - if not data_line in server_handlers[server][data_line[key_begin:key_end]]: - server_handlers[server][data_line[key_begin:key_end]].append( - '..{0}({1}:{2}) \'{3}\''.format( - location, - line_no, - key_begin, - hint)) + server_handlers[server][data_line[key_begin:key_end]].append( + '..{0}({1}:{2}) \'{3}\''.format( + location, + line_no, + key_begin, + '{0} {1}'.format( + direction, + hint + ) + ) + ) + + dprint('..{0}({1}:{2}) [{3}][{4}] = \'{5} {6}\'\n'.format( + location, + line_no, + key_begin, + server, + data_line[key_begin:key_end], + direction, + hint + )) + + data_file.close() + + dprint('->close: \'{0}\'\n'.format(file_name)) except: - if DEBUG >= 2: - print('EXCEPTION ERROR->discoverserverhandlers({0})'.format(sys.exc_info()[0])) + print('(Exception Error: {0}) discoverserverhandlers() [{1}]'.format( + sys.exc_info()[0], + server + )) + + dprint('<-except: \'{0} [{1}]\'\n'.format( + sys.exc_info()[0], + server + )) + + if not server in bad_servers: + bad_servers.append(server) + + for bad_server in bad_servers: + if bad_server in server_handlers: + vprint('Deleting stale entries for \'{0}\' server...'.format(bad_server)) + + del server_handlers[bad_server] + + dprint('->delete: \'{0}\' server discovered handler entries\n'.format(bad_server)) + + dprint('leaving \'discoverserverhandlers()\'\n\n') return True def clearemptyserverentries(): + """ + Delete SERVER OPCODE HANDLERS with no references + + Server methods are treated a little differently than client ones. Because of multiple + search functions, we do not want to invalidate a server until all data-load processes + are performed. + + This function cleans up and removes unused server references after all relevant + processing is complete. + + """ + + dprint('entering \'clearemptyserverentries()\'\n') + bad_servers = [] for server in server_list: - if len(server_handlers[server]) == 0: + if not server in server_handlers or not len(server_handlers[server]) > 0: bad_servers.append(server) else: bad_opcodes = [] @@ -658,108 +1103,138 @@ def clearemptyserverentries(): bad_servers.append(server) for bad_server in bad_servers: - if DEBUG >= 1: - print('Deleting \'{0}\' server from search criteria...'.format(bad_server)) - print('Deleting stale entries for \'{0}\' server...'.format(bad_server)) + vprint('Deleting \'{0}\' server from search criteria...'.format(bad_server)) - del server_handlers[bad_server] server_list.remove(bad_server) + dprint('->delete: \'{0}\' server\n'.format(bad_server)) + + if bad_server in server_handlers: + vprint('Deleting stale entries for \'{0}\' server...'.format(bad_server)) + + del server_handlers[bad_server] + + dprint('->delete: \'{0}\' server handler entries\n'.format(bad_server)) + + if not len(server_list) > 0: + print('Could not locate valid servers...') + + dprint('leaving \'clearemptyserverentries(): NO VALID SERVERS EXIST\'\n\n') + + return False + + if not len(server_handlers) > 0: + print('Could not locate server handlers...') + + dprint('leaving \'clearemptyserverentries(): SERVER HANDLERS NOT FOUND\'\n\n') + + return False + + dprint('leaving \'clearemptyserverentries()\'\n\n') + return True def openoutputfiles(): - """ Open output files in 'w' mode - create/overwrite mode """ + """ Open OUTPUT FILES in 'w' mode - create/overwrite mode """ + + dprint('entering \'openoutputfiles()\'\n') try: file_name = '{0}/utils/scripts/opcode_handlers_output/Report.txt'.format(base_path) - if DEBUG >= 1: - print(file_name) + vprint(file_name) out_files['Report'] = open(file_name, 'w') + dprint('->open: \'{0}\' in \'w\' mode\n'.format(file_name)) + + rprint( + '>> \'Opcode-Handler\' Report file\n' + '>> file generated @ {0}\n\n'.format(ctime(time())) + ) + for client in client_list: - file_name = '{0}{1}{2}{3}'.format( + file_name = '{0}/utils/scripts/opcode_handlers_output/{1}_opcode_handlers.txt'.format( base_path, - '/utils/scripts/opcode_handlers_output/', - client, - '_opcode_handlers.txt') + client + ) - if DEBUG >= 1: - print(file_name) + vprint(file_name) out_files[client] = open(file_name, 'w') - message = \ - '>> \'Opcode-Handler\' analysis for \'{0}\' client\n' \ - '>> file generated @ {1}\n' \ - '\n'.format( + dprint('->open: \'{0}\' in \'w\' mode\n'.format(file_name)) + + cprint( + client, + '>> \'Opcode-Handler\' analysis for \'{0}\' client\n' + '>> file generated @ {1}\n\n'.format( client, - ctime(time())) - - out_files[client].write(message) - - if DEBUG >= 2: - print(message[:-2]) + ctime(time()) + ) + ) for server in server_list: - file_name = '{0}{1}{2}{3}'.format( + file_name = '{0}/utils/scripts/opcode_handlers_output/{1}_opcode_handlers.txt'.format( base_path, - '/utils/scripts/opcode_handlers_output/', - server, - '_opcode_handlers.txt') + server + ) - if DEBUG >= 1: - print(file_name) + vprint(file_name) out_files[server] = open(file_name, 'w') - message = \ - '>> \'Opcode-Handler\' analysis for \'{0}\' server\n' \ - '>> file generated @ {1}\n' \ - '\n'.format( + dprint('->open: \'{0}\' in \'w\' mode\n'.format(file_name)) + + sprint( + server, + '>> \'Opcode-Handler\' analysis for \'{0}\' server\n' + '>> file generated @ {1}\n\n'.format( server, - ctime(time())) + ctime(time()) + ) + ) - out_files[server].write(message) + dprint('leaving \'openoutputfiles()\'\n\n') - if DEBUG >= 2: - print(message[:-2]) + return True except: - if DEBUG >= 2: - print('EXCEPTION ERROR->openoutputfiles({0})'.format(sys.exc_info()[0])) + print('(Exception Error: {0}) openoutputfiles()'.format(sys.exc_info()[0])) + + if 'Report' in out_files: + vprint('Closing Report output file...') + + out_files['Report'].close() + + del out_files['Report'] for client in client_list: if client in out_files: + vprint('Closing {0} client output file...'.format(client)) + out_files[client].close() + del out_files[client] - if DEBUG >= 2: - print('->OpeningClientStream(exception): {0}'.format(client)) - for server in server_list: if server in out_files: + vprint('Closing {0} server output file...'.format(server)) + out_files[server].close() + del out_files[server] - if DEBUG >= 2: - print('->OpeningServerStream(exception): {0}'.format(server)) - - if 'Report' in out_files: - out_files['Report'].close() - del out_files['Report'] - - if DEBUG >= 2: - print('->OpeningReportStream(exception)') + dprint('leaving \'openoutputfiles(): EXCEPTION ERROR\'\n\n') return False - return True - def parseclientopcodedata(): - # TODO: add metrics + """ Process CLIENT OPCODE cross-link references """ + + dprint('entering \'parseclientopcodedata()\'\n') + for client in client_list: server_max_len = 0 @@ -785,7 +1260,8 @@ def parseclientopcodedata(): client_opcodes[client][client_opcode], handled, encoded, - decoded) + decoded + ) for server in server_list: if client_opcode in server_handlers[server] and len(server_handlers[server][client_opcode]) > 0: @@ -796,30 +1272,29 @@ def parseclientopcodedata(): message += ' Server: {0} ({1}) | Handler: {2}\n'.format( server.ljust(len(server) + (server_max_len - len(server)), ' '), '{0}'.format(server_opcodes[client_opcode]).zfill(4), - handler_entry) + handler_entry + ) else: message += ' Server: {0} (0000) | Handler: N/A\n'.format( - server.ljust(len(server) + (server_max_len - len(server)), ' ')) - - if DEBUG >= 2: - print('->EndOfServerLoop: {0}'.format(server)) + server.ljust(len(server) + (server_max_len - len(server)), ' ') + ) message += '\n' - out_files[client].write(message) + cprint(client, message) - if DEBUG >= 2: - print(message[:-2]) - print('->EndOfOpcodeLoop: {0}'.format(client_opcode)) + dprint('->parse: \'{0}\' client\n'.format(client)) - if DEBUG >= 2: - print('->EndOfClientLoop: {0}'.format(client)) + dprint('leaving \'parseclientopcodedata()\'\n\n') return True def parseserveropcodedata(): - # TODO: add metrics + """ Process SERVER OPCODE cross-link references """ + + dprint('entering \'parseserveropcodedata()\'\n') + for server in server_list: client_max_len = 0 @@ -859,62 +1334,145 @@ def parseserveropcodedata(): val1, val2.ljust(len(val2) + (len('False') - len(val2)), ' '), val3.ljust(len(val3) + (len('False') - len(val3)), ' '), - val4.ljust(len(val4) + (len('False') - len(val4)), ' ')) - - if DEBUG >= 2: - print('->EndOfClientLoop: {0}'.format(client)) + val4.ljust(len(val4) + (len('False') - len(val4)), ' ') + ) message += '\n' - out_files[server].write(message) + sprint(server, message) - if DEBUG >= 2: - print(message[:-2]) - print('->EndOfOpcodeLoop: {0}'.format(handler_opcode)) + dprint('->parse: \'{0}\' server\n'.format(server)) - if DEBUG >= 2: - print('->EndOfServerLoop: {0}'.format(server)) + dprint('leaving \'parseserveropcodedata()\'\n\n') return True def closeoutputfiles(): + """ Close OUTPUT FILES - excluding DEBUG FILE """ + + dprint('entering \'closeoutputfiles()\'\n') + + if 'Report' in out_files: + file_name = out_files['Report'].name + + out_files['Report'].close() + + del out_files['Report'] + + dprint('->close: \'{0}\'\n'.format(file_name)) + + if 'Undefined' in out_files: + file_name = out_files['Undefined'].name + + out_files['Undefined'].close() + + del out_files['Undefined'] + + dprint('->close: \'{0}\'\n'.format(file_name)) + for client in client_list: if client in out_files: + file_name = out_files[client].name + out_files[client].close() + del out_files[client] - if DEBUG >= 2: - print('->ClosingClientStream: {0}'.format(client)) + dprint('->close: \'{0}\'\n'.format(file_name)) for server in server_list: if server in out_files: + file_name = out_files[server].name + out_files[server].close() + del out_files[server] - if DEBUG >= 2: - print('->ClosingServerStream: {0}'.format(server)) + dprint('->close: \'{0}\'\n'.format(file_name)) - if 'Report' in out_files: - out_files['Report'].close() - del out_files['Report'] + dprint('leaving \'closeoutputfiles()\'\n\n') - if DEBUG >= 2: - print('->ClosingReportStream') + return True + + +def closeundefinedfile(): + """ Close UNDEFINED FILE """ + + dprint('entering \'closeundefinedfile()\'\n') + + if 'Undefined' in out_files: + file_name = out_files['Undefined'].name + + dprint('closing \'{0}\'\n'.format(file_name)) + + out_files['Undefined'].close() + + del out_files['Undefined'] + + dprint('leaving \'closeundefinedfile()\'\n\n') return True def closedebugfile(): - if 'DEBUG' in out_files: - out_files['DEBUG'].close() - del out_files['DEBUG'] + """ Close DEBUG FILE - last performed action to catch late messages """ - if DEBUG >= 2: - print('->ClosingDEBUGStream') + dprint('entering \'closedebugfile()\'\n') + + if 'DEBUG' in out_files: + file_name = out_files['DEBUG'].name + + dprint('closing \'{0}\'\n'.format(file_name)) + + out_files['DEBUG'].close() + + del out_files['DEBUG'] return True +def cprint(client, message): + """ CLIENT PRINT helper function """ + + if client in out_files: + out_files[client].write(message) + + +def dprint(message): + """ DEBUG PRINT helper function """ + + if 'DEBUG' in out_files: + out_files['DEBUG'].write(message) + + +def rprint(message): + """ REPORT PRINT helper function """ + + if 'Report' in out_files: + out_files['Report'].write(message) + + +def sprint(server, message): + """ SERVER PRINT helper function """ + + if server in out_files: + out_files[server].write(message) + + +def uprint(message): + """ UNDEFINED PRINT helper function """ + + if 'Undefined' in out_files: + out_files['Undefined'].write(message) + + +def vprint(message): + """ VERBOSE PRINT helper function """ + + if VERBOSE: + print(message) + + if __name__ == '__main__': main() From 1ba4b6fc3124bf3a4376b1f18564ecd576dabc5a Mon Sep 17 00:00:00 2001 From: Russell Kinasz Date: Tue, 12 Aug 2014 15:18:11 -0700 Subject: [PATCH 278/288] Implemented Raid OOC Regen --- common/ruletypes.h | 1 + zone/client.cpp | 28 ++++++++++++++++++++++++---- zone/client.h | 6 ++++++ zone/client_packet.cpp | 3 ++- zone/hate_list.cpp | 5 ++++- zone/mob.h | 1 + zone/npc.cpp | 1 + zone/npc.h | 4 ++++ zone/zonedb.cpp | 4 +++- zone/zonedump.h | 1 + 10 files changed, 47 insertions(+), 7 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 0fd413e5a..91ade257b 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -76,6 +76,7 @@ RULE_BOOL ( Character, SharedBankPlat, false) //off by default to prevent duping RULE_BOOL ( Character, BindAnywhere, false) RULE_INT ( Character, RestRegenPercent, 0) // Set to >0 to enable rest state bonus HP and mana regen. RULE_INT ( Character, RestRegenTimeToActivate, 30) // Time in seconds for rest state regen to kick in. +RULE_INT ( Character, RestRegenRaidTimeToActivate, 300) // Time in seconds for rest state regen to kick in with a raid target. RULE_BOOL ( Character, RestRegenEndurance, false) // Whether rest regen will work for endurance or not. RULE_INT ( Character, KillsPerGroupLeadershipAA, 250) // Number of dark blues or above per Group Leadership AA RULE_INT ( Character, KillsPerRaidLeadershipAA, 250) // Number of dark blues or above per Raid Leadership AA diff --git a/zone/client.cpp b/zone/client.cpp index 6b7828f1d..aa93478ba 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -324,6 +324,9 @@ Client::Client(EQStreamInterface* ieqs) initial_respawn_selection = 0; alternate_currency_loaded = false; + + EngagedRaidTarget = false; + SavedRaidRestTimer = 0; } Client::~Client() { @@ -4330,12 +4333,16 @@ void Client::IncrementAggroCount() { if(!RuleI(Character, RestRegenPercent)) return; - + // If we already had aggro before this method was called, the combat indicator should already be up for SoF clients, // so we don't need to send it again. // if(AggroCount > 1) return; + + // Pause the rest timer + if (AggroCount == 1) + SavedRaidRestTimer = rest_timer.GetRemainingTime(); if(GetClientVersion() >= EQClientSoF) { @@ -4367,14 +4374,27 @@ void Client::DecrementAggroCount() { // Something else is still aggro on us, can't rest yet. if(AggroCount) return; - rest_timer.Start(RuleI(Character, RestRegenTimeToActivate) * 1000); - + uint32 time_until_rest; + if (GetEngagedRaidTarget()) { + time_until_rest = RuleI(Character, RestRegenRaidTimeToActivate) * 1000; + SetEngagedRaidTarget(false); + } else { + if (SavedRaidRestTimer > (RuleI(Character, RestRegenTimeToActivate) * 1000)) { + time_until_rest = SavedRaidRestTimer; + SavedRaidRestTimer = 0; + } else { + time_until_rest = RuleI(Character, RestRegenTimeToActivate) * 1000; + } + } + + rest_timer.Start(time_until_rest); + if(GetClientVersion() >= EQClientSoF) { EQApplicationPacket *outapp = new EQApplicationPacket(OP_RestState, 5); char *Buffer = (char *)outapp->pBuffer; VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0x00); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, RuleI(Character, RestRegenTimeToActivate)); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, (uint32)(time_until_rest / 1000)); QueuePacket(outapp); safe_delete(outapp); } diff --git a/zone/client.h b/zone/client.h index cce84673c..cadf9b583 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1198,6 +1198,9 @@ public: int mod_food_value(const Item_Struct *item, int change); int mod_drink_value(const Item_Struct *item, int change); + void SetEngagedRaidTarget(bool value) { EngagedRaidTarget = value; } + bool GetEngagedRaidTarget() const { return EngagedRaidTarget; } + protected: friend class Mob; void CalcItemBonuses(StatBonuses* newbon); @@ -1442,6 +1445,9 @@ private: unsigned int RestRegenHP; unsigned int RestRegenMana; unsigned int RestRegenEndurance; + + bool EngagedRaidTarget; + uint32 SavedRaidRestTimer; std::set zone_flags; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 01e768c1f..0d44bfa93 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -9140,7 +9140,8 @@ bool Client::FinishConnState2(DBAsyncWork* dbaw) { m_pp.timeentitledonaccount = database.GetTotalTimeEntitledOnAccount(AccountID()) / 1440; - if(m_pp.RestTimer > RuleI(Character, RestRegenTimeToActivate)) + // Reset rest timer if the durations have been lowered in the database + if ((m_pp.RestTimer > RuleI(Character, RestRegenTimeToActivate)) && (m_pp.RestTimer > RuleI(Character, RestRegenRaidTimeToActivate))) m_pp.RestTimer = 0; //This checksum should disappear once dynamic structs are in... each struct strategy will do it diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index 1b585ca32..2d7bd3ea6 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -198,8 +198,11 @@ void HateList::Add(Mob *ent, int32 in_hate, int32 in_dam, bool bFrenzy, bool iAd list.push_back(p); parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), ent, "1", 0); - if(ent->IsClient()) + if (ent->IsClient()) { + if (owner->CastToNPC()->IsRaidTarget()) + ent->CastToClient()->SetEngagedRaidTarget(true); ent->CastToClient()->IncrementAggroCount(); + } } } diff --git a/zone/mob.h b/zone/mob.h index 15f1728ec..a0c8dbdc4 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -524,6 +524,7 @@ public: //More stuff to sort: + virtual bool IsRaidTarget() { return false; }; virtual bool IsAttackAllowed(Mob *target, bool isSpellAttack = false); bool IsTargeted() const { return (targeted > 0); } inline void IsTargeted(int in_tar) { targeted += in_tar; if(targeted < 0) targeted = 0;} diff --git a/zone/npc.cpp b/zone/npc.cpp index 565a89598..f4e307bbc 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -358,6 +358,7 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float SetEmoteID(d->emoteid); InitializeBuffSlots(); CalcBonuses(); + raid_target = d->raid_target; } NPC::~NPC() diff --git a/zone/npc.h b/zone/npc.h index 6bc9813fe..5c8fd43bb 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -395,6 +395,8 @@ public: void mod_npc_killed_merit(Mob* c); void mod_npc_killed(Mob* oos); void AISpellsList(Client *c); + + bool IsRaidTarget() const { return raid_target; }; protected: @@ -500,6 +502,8 @@ protected: //mercenary stuff std::list mercTypeList; std::list mercDataList; + + bool raid_target; private: uint32 loottable_id; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index b14e63f26..0d1653453 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1115,7 +1115,8 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { "npc_types.emoteid," "npc_types.spellscale," "npc_types.healscale," - "npc_types.no_target_hotkey"; + "npc_types.no_target_hotkey," + "npc_types.raid_target"; MakeAnyLenString(&query, "%s FROM npc_types WHERE id=%d", basic_query, id); @@ -1302,6 +1303,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { tmpNPCType->spellscale = atoi(row[r++]); tmpNPCType->healscale = atoi(row[r++]); tmpNPCType->no_target_hotkey = atoi(row[r++]) == 1 ? true : false; + tmpNPCType->raid_target = atoi(row[r++]) == 0 ? false : true; // If NPC with duplicate NPC id already in table, // free item we attempted to add. diff --git a/zone/zonedump.h b/zone/zonedump.h index 3b5b91577..98841630a 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -125,6 +125,7 @@ struct NPCType float spellscale; float healscale; bool no_target_hotkey; + bool raid_target; }; /* From 6badd7e00e7e5aeeea5955061b1b2b3d0fac84ca Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 12 Aug 2014 22:51:36 -0400 Subject: [PATCH 279/288] Added SQLs from previous commit [skip ci] --- utils/sql/git/optional/2014_08_12_raid_timer_rule.sql | 1 + utils/sql/git/required/2014_08_12_NPC_raid_targets.sql | 1 + 2 files changed, 2 insertions(+) create mode 100644 utils/sql/git/optional/2014_08_12_raid_timer_rule.sql create mode 100644 utils/sql/git/required/2014_08_12_NPC_raid_targets.sql diff --git a/utils/sql/git/optional/2014_08_12_raid_timer_rule.sql b/utils/sql/git/optional/2014_08_12_raid_timer_rule.sql new file mode 100644 index 000000000..46f5acb37 --- /dev/null +++ b/utils/sql/git/optional/2014_08_12_raid_timer_rule.sql @@ -0,0 +1 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Character:RestRegenRaidTimeToActivate', 300, 'Time in seconds for rest state regen to kick in with a raid target.'); diff --git a/utils/sql/git/required/2014_08_12_NPC_raid_targets.sql b/utils/sql/git/required/2014_08_12_NPC_raid_targets.sql new file mode 100644 index 000000000..c045b18e3 --- /dev/null +++ b/utils/sql/git/required/2014_08_12_NPC_raid_targets.sql @@ -0,0 +1 @@ +ALTER TABLE `npc_types` ADD `raid_target` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `fixed`; From c2282ced0e97f16f19fd2f7b519b4da51a852544 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 13 Aug 2014 13:20:10 -0400 Subject: [PATCH 280/288] Some people were having issues with the other one [skip ci] --- utils/sql/git/required/2014_08_12_NPC_raid_targets.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/sql/git/required/2014_08_12_NPC_raid_targets.sql b/utils/sql/git/required/2014_08_12_NPC_raid_targets.sql index c045b18e3..a91a02815 100644 --- a/utils/sql/git/required/2014_08_12_NPC_raid_targets.sql +++ b/utils/sql/git/required/2014_08_12_NPC_raid_targets.sql @@ -1 +1 @@ -ALTER TABLE `npc_types` ADD `raid_target` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `fixed`; +ALTER TABLE `npc_types` ADD `raid_target` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `no_target_hotkey`; From dc6e6fd05f4e5a1b3914bef66777078948205565 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 13 Aug 2014 14:24:42 -0400 Subject: [PATCH 281/288] Fix for bot chest armor display glitch in SoF+ clients --- changelog.txt | 3 +++ zone/bot.cpp | 9 +++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/changelog.txt b/changelog.txt index 16d63a05e..32b1a105c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 08/13/2014 == +Uleat (Kingly_Krab): Fix for bot chest armor graphic glitch. (fix also caused RoF #wc to work properly) + == 08/02/2014 == Kayen: Implemented spell_news fields - npc_no_los (check if LOS is required for spells) diff --git a/zone/bot.cpp b/zone/bot.cpp index eef5f803f..283f482de 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -4303,8 +4303,9 @@ void Bot::Spawn(Client* botCharacterOwner, std::string* errorMessage) { // Get the zone id this bot spawned in _lastZoneId = GetZoneID(); - this->helmtexture = 0xFF; - this->texture = 0xFF; + // this change propagates to Bot::FillSpawnStruct() + this->helmtexture = 0; //0xFF; + this->texture = 0; //0xFF; if(this->Save()) this->GetBotOwner()->CastToClient()->Message(0, "%s saved.", this->GetCleanName()); @@ -4586,8 +4587,8 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { ns->spawn.size = 0; ns->spawn.NPC = 0; // 0=player,1=npc,2=pc corpse,3=npc corpse - ns->spawn.helm = 0xFF; - ns->spawn.equip_chest2 = 0xFF; + ns->spawn.helm = helmtexture; //0xFF; + ns->spawn.equip_chest2 = texture; //0xFF; const Item_Struct* item = 0; const ItemInst* inst = 0; From e2874b2cc6cb44ff59cb1c0ee97acfadea22d715 Mon Sep 17 00:00:00 2001 From: Michael Cook Date: Thu, 14 Aug 2014 15:05:44 -0400 Subject: [PATCH 282/288] Update README.md [skip ci] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f2245dcf4..0c973ed43 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Further instructions on building the source can be found on the Bug reports --- -Please use the [issue tracker](issue-tracker) provided by GitHub to send us bug +Please use the [issue tracker](https://github.com/EQEmu/Server/issues) provided by GitHub to send us bug reports or feature requests. The [EQEmu Forums](http://www.eqemulator.org/forums/) also have forums to submit From bce3b1b9617543cbad615659a65e1386b52c9cf3 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Fri, 15 Aug 2014 04:15:37 -0400 Subject: [PATCH 283/288] Edit some uint32 to int32: GetAugmentIDAt, GetItemIDAt, GetItemStat --- zone/client.h | 4 ++-- zone/inventory.cpp | 4 ++-- zone/mob.cpp | 2 +- zone/mob.h | 2 +- zone/perl_client.cpp | 8 ++++---- zone/perl_mob.cpp | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/zone/client.h b/zone/client.h index cadf9b583..718efbb6e 100644 --- a/zone/client.h +++ b/zone/client.h @@ -789,8 +789,8 @@ public: void SetTint(int16 slot_id, Color_Struct& color); void SetMaterial(int16 slot_id, uint32 item_id); void Undye(); - uint32 GetItemIDAt(int16 slot_id); - uint32 GetAugmentIDAt(int16 slot_id, uint8 augslot); + int32 GetItemIDAt(int16 slot_id); + int32 GetAugmentIDAt(int16 slot_id, uint8 augslot); bool PutItemInInventory(int16 slot_id, const ItemInst& inst, bool client_update = false); bool PushItemOnCursor(const ItemInst& inst, bool client_update = false); void DeleteItemInInventory(int16 slot_id, int8 quantity = 0, bool client_update = false, bool update_db = true); diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 969065fdb..9a815c6ca 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -659,7 +659,7 @@ void Client::DropInst(const ItemInst* inst) } // Returns a slot's item ID (returns INVALID_ID if not found) -uint32 Client::GetItemIDAt(int16 slot_id) { +int32 Client::GetItemIDAt(int16 slot_id) { const ItemInst* inst = m_inv[slot_id]; if (inst) return inst->GetItem()->ID; @@ -670,7 +670,7 @@ uint32 Client::GetItemIDAt(int16 slot_id) { // Returns an augment's ID that's in an item (returns INVALID_ID if not found) // Pass in the slot ID of the item and which augslot you want to check (0-4) -uint32 Client::GetAugmentIDAt(int16 slot_id, uint8 augslot) { +int32 Client::GetAugmentIDAt(int16 slot_id, uint8 augslot) { const ItemInst* inst = m_inv[slot_id]; if (inst) if (inst->GetAugmentItemID(augslot)) diff --git a/zone/mob.cpp b/zone/mob.cpp index 24b691e36..03e7bbdaa 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3537,7 +3537,7 @@ void Mob::TrySympatheticProc(Mob *target, uint32 spell_id) } } -uint32 Mob::GetItemStat(uint32 itemid, const char *identifier) +int32 Mob::GetItemStat(uint32 itemid, const char *identifier) { const ItemInst* inst = database.CreateItem(itemid); if (!inst) diff --git a/zone/mob.h b/zone/mob.h index a0c8dbdc4..fe0919f7e 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -553,7 +553,7 @@ public: void Shout(const char *format, ...); void Emote(const char *format, ...); void QuestJournalledSay(Client *QuestInitiator, const char *str); - uint32 GetItemStat(uint32 itemid, const char *identifier); + int32 GetItemStat(uint32 itemid, const char *identifier); int16 CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, bool best_focus=false); uint8 IsFocusEffect(uint16 spellid, int effect_index, bool AA=false,uint32 aa_effect=0); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 0bab3cfb0..816956d86 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -2955,7 +2955,7 @@ XS(XS_Client_GetItemIDAt) Perl_croak(aTHX_ "Usage: Client::GetItemIDAt(THIS, slot_id)"); { Client * THIS; - uint32 RETVAL; + int32 RETVAL; dXSTARG; int16 slot_id = (int16)SvIV(ST(1)); @@ -2969,7 +2969,7 @@ XS(XS_Client_GetItemIDAt) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); RETVAL = THIS->GetItemIDAt(slot_id); - XSprePUSH; PUSHu((UV)RETVAL); + XSprePUSH; PUSHi((IV)RETVAL); } XSRETURN(1); } @@ -2982,7 +2982,7 @@ XS(XS_Client_GetAugmentIDAt) Perl_croak(aTHX_ "Usage: Client::GetAugmentIDAt(THIS, slot_id, augslot)"); { Client * THIS; - uint32 RETVAL; + int32 RETVAL; dXSTARG; int16 slot_id = (int16)SvIV(ST(1)); int16 augslot = (uint8)SvIV(ST(2)); @@ -2997,7 +2997,7 @@ XS(XS_Client_GetAugmentIDAt) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); RETVAL = THIS->GetAugmentIDAt(slot_id, augslot); - XSprePUSH; PUSHu((UV)RETVAL); + XSprePUSH; PUSHi((IV)RETVAL); } XSRETURN(1); } diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 86cf58981..14d84a70e 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -7298,7 +7298,7 @@ XS(XS_Mob_GetItemStat) Perl_croak(aTHX_ "Usage: Mob::GetItemStat(THIS, itemid, stat)"); { Mob * THIS; - uint32 RETVAL; + int32 RETVAL; uint32 itemid = (uint32)SvUV(ST(1)); Const_char * stat = (Const_char *)SvPV_nolen(ST(2)); dXSTARG; @@ -7313,7 +7313,7 @@ XS(XS_Mob_GetItemStat) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); RETVAL = THIS->GetItemStat(itemid, stat); - XSprePUSH; PUSHu((UV)RETVAL); + XSprePUSH; PUSHi((IV)RETVAL); } XSRETURN(1); } From f7bb763aaca6dd55bb591ab20ba280b3b5adca1c Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 15 Aug 2014 16:28:16 -0400 Subject: [PATCH 284/288] Reactivation of wear change updates in Bot::Spawn() until fix can be found. --- changelog.txt | 3 +++ zone/bot.cpp | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/changelog.txt b/changelog.txt index 32b1a105c..1f43ed0d9 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 08/15/2014 == +Uleat: Reactivated the Bot::Spawn() code for sending post-spawn wear change updates..temporary until I can sort out the proper usage. + == 08/13/2014 == Uleat (Kingly_Krab): Fix for bot chest armor graphic glitch. (fix also caused RoF #wc to work properly) diff --git a/zone/bot.cpp b/zone/bot.cpp index 283f482de..aa5ab33f0 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -4330,18 +4330,18 @@ void Bot::Spawn(Client* botCharacterOwner, std::string* errorMessage) { this->SendPosition(); - /* // fillspawnstruct now properly handles this -U + // there is something askew with spawn struct appearance fields... + // I re-enabled this until I can sort it out -U uint32 itemID = 0; uint8 materialFromSlot = 0xFF; - for(int i=EmuConstants::EQUIPMENT_BEGIN; i<=EmuConstants::EQUIPMENT_END; ++i) { + for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { itemID = GetBotItemBySlot(i); if(itemID != 0) { materialFromSlot = Inventory::CalcMaterialFromSlot(i); - if(materialFromSlot != 0xFF) { + if(materialFromSlot != 0xFF) this->SendWearChange(materialFromSlot); - } } - }*/ + } } } From a3069b63df95ad3d0dbf8f47ec0e8746e470dd6a Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 16 Aug 2014 00:18:19 -0400 Subject: [PATCH 285/288] Minor tweaks... --- utils/scripts/opcode_handlers.py | 93 +++++++++++++++----------------- 1 file changed, 43 insertions(+), 50 deletions(-) diff --git a/utils/scripts/opcode_handlers.py b/utils/scripts/opcode_handlers.py index ddad43eda..6cad4ade0 100644 --- a/utils/scripts/opcode_handlers.py +++ b/utils/scripts/opcode_handlers.py @@ -136,10 +136,6 @@ def main(): fault = True faults.append('closeoutputfiles()') - if not closeundefinedfile(): - fault = True - faults.append('closeundefinedfile()') - if not closedebugfile(): fault = True faults.append('closedebugfile()') @@ -197,6 +193,13 @@ def opendebugfile(): except: print('(Exception Error: {0}) opendebugfile()'.format(sys.exc_info()[0])) + if 'DEBUG' in out_files: + vprint('Closing DEBUG output file...') + + out_files['DEBUG'].close() + + del out_files['DEBUG'] + return False @@ -206,14 +209,14 @@ def openundefinedfile(): dprint('entering \'openundefinedfile()\'\n') try: - file_name = '{0}/utils/scripts/opcode_handlers_output/Undefined.txt'.format(base_path) + file_name = '{0}/utils/scripts/opcode_handlers_output/UNDEFINED.txt'.format(base_path) vprint(file_name) - out_files['Undefined'] = open(file_name, 'w') + out_files['UNDEFINED'] = open(file_name, 'w') uprint( - '>> \'Opcode-Handler\' Undefined dump file\n' + '>> \'Opcode-Handler\' UNDEFINED dump file\n' '>> file generated @ {0}\n\n'.format(ctime(time())) ) @@ -226,6 +229,13 @@ def openundefinedfile(): except: print('(Exception Error: {0}) openundefinedfile()'.format(sys.exc_info()[0])) + if 'UNDEFINED' in out_files: + vprint('Closing UNDEFINED output file...') + + out_files['UNDEFINED'].close() + + del out_files['UNDEFINED'] + return False @@ -570,6 +580,7 @@ def loadserverhandlers(): for data_line in data_file: line_no += 1 + read_begin = 0 if step_1 is False: if data_line[:19] == 'void MapOpcodes() {': @@ -583,7 +594,7 @@ def loadserverhandlers(): continue - val_begin = data_line.find('OP_') + val_begin = data_line.find('OP_', read_begin) val_end = data_line.find(']', val_begin) if val_begin < 0 or val_end < 0: @@ -706,12 +717,12 @@ def discoverserverhandlers(): locations['Server'].append('//.') Lists are instantiated for all SERVERS in SERVER LIST. The lists are then appended - with location data based on the presence of the list in the parent dictionary. + with location data based on the presence of the SERVER in the parent dictionary. """ # TODO: handle remarked out definitions in file (i.e., // and /**/) - # TODO: if/how to include perl/lua handlers... + # TODO: if/how to include perl, lua and non-'..//' location handlers... dprint('entering \'discoverserverhandlers()\'\n') @@ -795,6 +806,7 @@ def discoverserverhandlers(): for data_line in data_file: line_no += 1 + read_begin = 0 if data_line[:1].isalpha(): hint_end = data_line.find('(') @@ -813,7 +825,7 @@ def discoverserverhandlers(): hint_begin -= 1 - op_begin = data_line.find('OP_') + op_begin = data_line.find('OP_', read_begin) if op_begin < 0: continue @@ -1141,16 +1153,16 @@ def openoutputfiles(): dprint('entering \'openoutputfiles()\'\n') try: - file_name = '{0}/utils/scripts/opcode_handlers_output/Report.txt'.format(base_path) + file_name = '{0}/utils/scripts/opcode_handlers_output/REPORT.txt'.format(base_path) vprint(file_name) - out_files['Report'] = open(file_name, 'w') + out_files['REPORT'] = open(file_name, 'w') dprint('->open: \'{0}\' in \'w\' mode\n'.format(file_name)) rprint( - '>> \'Opcode-Handler\' Report file\n' + '>> \'Opcode-Handler\' REPORT file\n' '>> file generated @ {0}\n\n'.format(ctime(time())) ) @@ -1202,12 +1214,12 @@ def openoutputfiles(): except: print('(Exception Error: {0}) openoutputfiles()'.format(sys.exc_info()[0])) - if 'Report' in out_files: - vprint('Closing Report output file...') + if 'REPORT' in out_files: + vprint('Closing REPORT output file...') - out_files['Report'].close() + out_files['REPORT'].close() - del out_files['Report'] + del out_files['REPORT'] for client in client_list: if client in out_files: @@ -1314,7 +1326,7 @@ def parseserveropcodedata(): for handler_entry in handler_list: message += 'Opcode: {0} ({1}) | Handler: {2}\n'.format( handler_opcode, - server_opcodes[handler_opcode], + '{0}'.format(server_opcodes[handler_opcode]).zfill(4), handler_entry) for client in client_list: @@ -1353,21 +1365,21 @@ def closeoutputfiles(): dprint('entering \'closeoutputfiles()\'\n') - if 'Report' in out_files: - file_name = out_files['Report'].name + if 'REPORT' in out_files: + file_name = out_files['REPORT'].name - out_files['Report'].close() + out_files['REPORT'].close() - del out_files['Report'] + del out_files['REPORT'] dprint('->close: \'{0}\'\n'.format(file_name)) - if 'Undefined' in out_files: - file_name = out_files['Undefined'].name + if 'UNDEFINED' in out_files: + file_name = out_files['UNDEFINED'].name - out_files['Undefined'].close() + out_files['UNDEFINED'].close() - del out_files['Undefined'] + del out_files['UNDEFINED'] dprint('->close: \'{0}\'\n'.format(file_name)) @@ -1396,25 +1408,6 @@ def closeoutputfiles(): return True -def closeundefinedfile(): - """ Close UNDEFINED FILE """ - - dprint('entering \'closeundefinedfile()\'\n') - - if 'Undefined' in out_files: - file_name = out_files['Undefined'].name - - dprint('closing \'{0}\'\n'.format(file_name)) - - out_files['Undefined'].close() - - del out_files['Undefined'] - - dprint('leaving \'closeundefinedfile()\'\n\n') - - return True - - def closedebugfile(): """ Close DEBUG FILE - last performed action to catch late messages """ @@ -1449,8 +1442,8 @@ def dprint(message): def rprint(message): """ REPORT PRINT helper function """ - if 'Report' in out_files: - out_files['Report'].write(message) + if 'REPORT' in out_files: + out_files['REPORT'].write(message) def sprint(server, message): @@ -1463,8 +1456,8 @@ def sprint(server, message): def uprint(message): """ UNDEFINED PRINT helper function """ - if 'Undefined' in out_files: - out_files['Undefined'].write(message) + if 'UNDEFINED' in out_files: + out_files['UNDEFINED'].write(message) def vprint(message): From 0f5214f4818a9751e52288424db25d362a70e39a Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Sat, 16 Aug 2014 01:13:15 -0400 Subject: [PATCH 286/288] Fixed GetItemStat making all information it pulls default it uint32. --- zone/mob.cpp | 314 ++++++++++++++++++++++++++------------------------- 1 file changed, 158 insertions(+), 156 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index 03e7bbdaa..a6baabd1a 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3550,7 +3550,7 @@ int32 Mob::GetItemStat(uint32 itemid, const char *identifier) if (!identifier) return 0; - uint32 stat = 0; + int32 stat = 0; std::string id = identifier; for(int i = 0; i < id.length(); ++i) @@ -3559,316 +3559,318 @@ int32 Mob::GetItemStat(uint32 itemid, const char *identifier) } if (id == "itemclass") - stat = uint32(item->ItemClass); + stat = int32(item->ItemClass); if (id == "id") - stat = uint32(item->ID); + stat = int32(item->ID); + if (id == "idfile") + stat = atoi(&item->IDFile[2]); if (id == "weight") - stat = uint32(item->Weight); + stat = int32(item->Weight); if (id == "norent") - stat = uint32(item->NoRent); + stat = int32(item->NoRent); if (id == "nodrop") - stat = uint32(item->NoDrop); + stat = int32(item->NoDrop); if (id == "size") - stat = uint32(item->Size); + stat = int32(item->Size); if (id == "slots") - stat = uint32(item->Slots); + stat = int32(item->Slots); if (id == "price") - stat = uint32(item->Price); + stat = int32(item->Price); if (id == "icon") - stat = uint32(item->Icon); + stat = int32(item->Icon); if (id == "loregroup") - stat = uint32(item->LoreGroup); + stat = int32(item->LoreGroup); if (id == "loreflag") - stat = uint32(item->LoreFlag); + stat = int32(item->LoreFlag); if (id == "pendingloreflag") - stat = uint32(item->PendingLoreFlag); + stat = int32(item->PendingLoreFlag); if (id == "artifactflag") - stat = uint32(item->ArtifactFlag); + stat = int32(item->ArtifactFlag); if (id == "summonedflag") - stat = uint32(item->SummonedFlag); + stat = int32(item->SummonedFlag); if (id == "fvnodrop") - stat = uint32(item->FVNoDrop); + stat = int32(item->FVNoDrop); if (id == "favor") - stat = uint32(item->Favor); + stat = int32(item->Favor); if (id == "guildfavor") - stat = uint32(item->GuildFavor); + stat = int32(item->GuildFavor); if (id == "pointtype") - stat = uint32(item->PointType); + stat = int32(item->PointType); if (id == "bagtype") - stat = uint32(item->BagType); + stat = int32(item->BagType); if (id == "bagslots") - stat = uint32(item->BagSlots); + stat = int32(item->BagSlots); if (id == "bagsize") - stat = uint32(item->BagSize); + stat = int32(item->BagSize); if (id == "bagwr") - stat = uint32(item->BagWR); + stat = int32(item->BagWR); if (id == "benefitflag") - stat = uint32(item->BenefitFlag); + stat = int32(item->BenefitFlag); if (id == "tradeskills") - stat = uint32(item->Tradeskills); + stat = int32(item->Tradeskills); if (id == "cr") - stat = uint32(item->CR); + stat = int32(item->CR); if (id == "dr") - stat = uint32(item->DR); + stat = int32(item->DR); if (id == "pr") - stat = uint32(item->PR); + stat = int32(item->PR); if (id == "mr") - stat = uint32(item->MR); + stat = int32(item->MR); if (id == "fr") - stat = uint32(item->FR); + stat = int32(item->FR); if (id == "astr") - stat = uint32(item->AStr); + stat = int32(item->AStr); if (id == "asta") - stat = uint32(item->ASta); + stat = int32(item->ASta); if (id == "aagi") - stat = uint32(item->AAgi); + stat = int32(item->AAgi); if (id == "adex") - stat = uint32(item->ADex); + stat = int32(item->ADex); if (id == "acha") - stat = uint32(item->ACha); + stat = int32(item->ACha); if (id == "aint") - stat = uint32(item->AInt); + stat = int32(item->AInt); if (id == "awis") - stat = uint32(item->AWis); + stat = int32(item->AWis); if (id == "hp") - stat = uint32(item->HP); + stat = int32(item->HP); if (id == "mana") - stat = uint32(item->Mana); + stat = int32(item->Mana); if (id == "ac") - stat = uint32(item->AC); + stat = int32(item->AC); if (id == "deity") - stat = uint32(item->Deity); + stat = int32(item->Deity); if (id == "skillmodvalue") - stat = uint32(item->SkillModValue); + stat = int32(item->SkillModValue); if (id == "skillmodtype") - stat = uint32(item->SkillModType); + stat = int32(item->SkillModType); if (id == "banedmgrace") - stat = uint32(item->BaneDmgRace); + stat = int32(item->BaneDmgRace); if (id == "banedmgamt") - stat = uint32(item->BaneDmgAmt); + stat = int32(item->BaneDmgAmt); if (id == "banedmgbody") - stat = uint32(item->BaneDmgBody); + stat = int32(item->BaneDmgBody); if (id == "magic") - stat = uint32(item->Magic); + stat = int32(item->Magic); if (id == "casttime_") - stat = uint32(item->CastTime_); + stat = int32(item->CastTime_); if (id == "reqlevel") - stat = uint32(item->ReqLevel); + stat = int32(item->ReqLevel); if (id == "bardtype") - stat = uint32(item->BardType); + stat = int32(item->BardType); if (id == "bardvalue") - stat = uint32(item->BardValue); + stat = int32(item->BardValue); if (id == "light") - stat = uint32(item->Light); + stat = int32(item->Light); if (id == "delay") - stat = uint32(item->Delay); + stat = int32(item->Delay); if (id == "reclevel") - stat = uint32(item->RecLevel); + stat = int32(item->RecLevel); if (id == "recskill") - stat = uint32(item->RecSkill); + stat = int32(item->RecSkill); if (id == "elemdmgtype") - stat = uint32(item->ElemDmgType); + stat = int32(item->ElemDmgType); if (id == "elemdmgamt") - stat = uint32(item->ElemDmgAmt); + stat = int32(item->ElemDmgAmt); if (id == "range") - stat = uint32(item->Range); + stat = int32(item->Range); if (id == "damage") - stat = uint32(item->Damage); + stat = int32(item->Damage); if (id == "color") - stat = uint32(item->Color); + stat = int32(item->Color); if (id == "classes") - stat = uint32(item->Classes); + stat = int32(item->Classes); if (id == "races") - stat = uint32(item->Races); + stat = int32(item->Races); if (id == "maxcharges") - stat = uint32(item->MaxCharges); + stat = int32(item->MaxCharges); if (id == "itemtype") - stat = uint32(item->ItemType); + stat = int32(item->ItemType); if (id == "material") - stat = uint32(item->Material); + stat = int32(item->Material); if (id == "casttime") - stat = uint32(item->CastTime); + stat = int32(item->CastTime); if (id == "elitematerial") - stat = uint32(item->EliteMaterial); + stat = int32(item->EliteMaterial); if (id == "procrate") - stat = uint32(item->ProcRate); + stat = int32(item->ProcRate); if (id == "combateffects") - stat = uint32(item->CombatEffects); + stat = int32(item->CombatEffects); if (id == "shielding") - stat = uint32(item->Shielding); + stat = int32(item->Shielding); if (id == "stunresist") - stat = uint32(item->StunResist); + stat = int32(item->StunResist); if (id == "strikethrough") - stat = uint32(item->StrikeThrough); + stat = int32(item->StrikeThrough); if (id == "extradmgskill") - stat = uint32(item->ExtraDmgSkill); + stat = int32(item->ExtraDmgSkill); if (id == "extradmgamt") - stat = uint32(item->ExtraDmgAmt); + stat = int32(item->ExtraDmgAmt); if (id == "spellshield") - stat = uint32(item->SpellShield); + stat = int32(item->SpellShield); if (id == "avoidance") - stat = uint32(item->Avoidance); + stat = int32(item->Avoidance); if (id == "accuracy") - stat = uint32(item->Accuracy); + stat = int32(item->Accuracy); if (id == "charmfileid") - stat = uint32(item->CharmFileID); + stat = int32(item->CharmFileID); if (id == "factionmod1") - stat = uint32(item->FactionMod1); + stat = int32(item->FactionMod1); if (id == "factionmod2") - stat = uint32(item->FactionMod2); + stat = int32(item->FactionMod2); if (id == "factionmod3") - stat = uint32(item->FactionMod3); + stat = int32(item->FactionMod3); if (id == "factionmod4") - stat = uint32(item->FactionMod4); + stat = int32(item->FactionMod4); if (id == "factionamt1") - stat = uint32(item->FactionAmt1); + stat = int32(item->FactionAmt1); if (id == "factionamt2") - stat = uint32(item->FactionAmt2); + stat = int32(item->FactionAmt2); if (id == "factionamt3") - stat = uint32(item->FactionAmt3); + stat = int32(item->FactionAmt3); if (id == "factionamt4") - stat = uint32(item->FactionAmt4); + stat = int32(item->FactionAmt4); if (id == "augtype") - stat = uint32(item->AugType); + stat = int32(item->AugType); if (id == "ldontheme") - stat = uint32(item->LDoNTheme); + stat = int32(item->LDoNTheme); if (id == "ldonprice") - stat = uint32(item->LDoNPrice); + stat = int32(item->LDoNPrice); if (id == "ldonsold") - stat = uint32(item->LDoNSold); + stat = int32(item->LDoNSold); if (id == "banedmgraceamt") - stat = uint32(item->BaneDmgRaceAmt); + stat = int32(item->BaneDmgRaceAmt); if (id == "augrestrict") - stat = uint32(item->AugRestrict); + stat = int32(item->AugRestrict); if (id == "endur") - stat = uint32(item->Endur); + stat = int32(item->Endur); if (id == "dotshielding") - stat = uint32(item->DotShielding); + stat = int32(item->DotShielding); if (id == "attack") - stat = uint32(item->Attack); + stat = int32(item->Attack); if (id == "regen") - stat = uint32(item->Regen); + stat = int32(item->Regen); if (id == "manaregen") - stat = uint32(item->ManaRegen); + stat = int32(item->ManaRegen); if (id == "enduranceregen") - stat = uint32(item->EnduranceRegen); + stat = int32(item->EnduranceRegen); if (id == "haste") - stat = uint32(item->Haste); + stat = int32(item->Haste); if (id == "damageshield") - stat = uint32(item->DamageShield); + stat = int32(item->DamageShield); if (id == "recastdelay") - stat = uint32(item->RecastDelay); + stat = int32(item->RecastDelay); if (id == "recasttype") - stat = uint32(item->RecastType); + stat = int32(item->RecastType); if (id == "augdistiller") - stat = uint32(item->AugDistiller); + stat = int32(item->AugDistiller); if (id == "attuneable") - stat = uint32(item->Attuneable); + stat = int32(item->Attuneable); if (id == "nopet") - stat = uint32(item->NoPet); + stat = int32(item->NoPet); if (id == "potionbelt") - stat = uint32(item->PotionBelt); + stat = int32(item->PotionBelt); if (id == "stackable") - stat = uint32(item->Stackable); + stat = int32(item->Stackable); if (id == "notransfer") - stat = uint32(item->NoTransfer); + stat = int32(item->NoTransfer); if (id == "questitemflag") - stat = uint32(item->QuestItemFlag); + stat = int32(item->QuestItemFlag); if (id == "stacksize") - stat = uint32(item->StackSize); + stat = int32(item->StackSize); if (id == "potionbeltslots") - stat = uint32(item->PotionBeltSlots); + stat = int32(item->PotionBeltSlots); if (id == "book") - stat = uint32(item->Book); + stat = int32(item->Book); if (id == "booktype") - stat = uint32(item->BookType); + stat = int32(item->BookType); if (id == "svcorruption") - stat = uint32(item->SVCorruption); + stat = int32(item->SVCorruption); if (id == "purity") - stat = uint32(item->Purity); + stat = int32(item->Purity); if (id == "backstabdmg") - stat = uint32(item->BackstabDmg); + stat = int32(item->BackstabDmg); if (id == "dsmitigation") - stat = uint32(item->DSMitigation); + stat = int32(item->DSMitigation); if (id == "heroicstr") - stat = uint32(item->HeroicStr); + stat = int32(item->HeroicStr); if (id == "heroicint") - stat = uint32(item->HeroicInt); + stat = int32(item->HeroicInt); if (id == "heroicwis") - stat = uint32(item->HeroicWis); + stat = int32(item->HeroicWis); if (id == "heroicagi") - stat = uint32(item->HeroicAgi); + stat = int32(item->HeroicAgi); if (id == "heroicdex") - stat = uint32(item->HeroicDex); + stat = int32(item->HeroicDex); if (id == "heroicsta") - stat = uint32(item->HeroicSta); + stat = int32(item->HeroicSta); if (id == "heroiccha") - stat = uint32(item->HeroicCha); + stat = int32(item->HeroicCha); if (id == "heroicmr") - stat = uint32(item->HeroicMR); + stat = int32(item->HeroicMR); if (id == "heroicfr") - stat = uint32(item->HeroicFR); + stat = int32(item->HeroicFR); if (id == "heroiccr") - stat = uint32(item->HeroicCR); + stat = int32(item->HeroicCR); if (id == "heroicdr") - stat = uint32(item->HeroicDR); + stat = int32(item->HeroicDR); if (id == "heroicpr") - stat = uint32(item->HeroicPR); + stat = int32(item->HeroicPR); if (id == "heroicsvcorrup") - stat = uint32(item->HeroicSVCorrup); + stat = int32(item->HeroicSVCorrup); if (id == "healamt") - stat = uint32(item->HealAmt); + stat = int32(item->HealAmt); if (id == "spelldmg") - stat = uint32(item->SpellDmg); + stat = int32(item->SpellDmg); if (id == "ldonsellbackrate") - stat = uint32(item->LDoNSellBackRate); + stat = int32(item->LDoNSellBackRate); if (id == "scriptfileid") - stat = uint32(item->ScriptFileID); + stat = int32(item->ScriptFileID); if (id == "expendablearrow") - stat = uint32(item->ExpendableArrow); + stat = int32(item->ExpendableArrow); if (id == "clairvoyance") - stat = uint32(item->Clairvoyance); + stat = int32(item->Clairvoyance); // Begin Effects if (id == "clickeffect") - stat = uint32(item->Click.Effect); + stat = int32(item->Click.Effect); if (id == "clicktype") - stat = uint32(item->Click.Type); + stat = int32(item->Click.Type); if (id == "clicklevel") - stat = uint32(item->Click.Level); + stat = int32(item->Click.Level); if (id == "clicklevel2") - stat = uint32(item->Click.Level2); + stat = int32(item->Click.Level2); if (id == "proceffect") - stat = uint32(item->Proc.Effect); + stat = int32(item->Proc.Effect); if (id == "proctype") - stat = uint32(item->Proc.Type); + stat = int32(item->Proc.Type); if (id == "proclevel") - stat = uint32(item->Proc.Level); + stat = int32(item->Proc.Level); if (id == "proclevel2") - stat = uint32(item->Proc.Level2); + stat = int32(item->Proc.Level2); if (id == "worneffect") - stat = uint32(item->Worn.Effect); + stat = int32(item->Worn.Effect); if (id == "worntype") - stat = uint32(item->Worn.Type); + stat = int32(item->Worn.Type); if (id == "wornlevel") - stat = uint32(item->Worn.Level); + stat = int32(item->Worn.Level); if (id == "wornlevel2") - stat = uint32(item->Worn.Level2); + stat = int32(item->Worn.Level2); if (id == "focuseffect") - stat = uint32(item->Focus.Effect); + stat = int32(item->Focus.Effect); if (id == "focustype") - stat = uint32(item->Focus.Type); + stat = int32(item->Focus.Type); if (id == "focuslevel") - stat = uint32(item->Focus.Level); + stat = int32(item->Focus.Level); if (id == "focuslevel2") - stat = uint32(item->Focus.Level2); + stat = int32(item->Focus.Level2); if (id == "scrolleffect") - stat = uint32(item->Scroll.Effect); + stat = int32(item->Scroll.Effect); if (id == "scrolltype") - stat = uint32(item->Scroll.Type); + stat = int32(item->Scroll.Type); if (id == "scrolllevel") - stat = uint32(item->Scroll.Level); + stat = int32(item->Scroll.Level); if (id == "scrolllevel2") - stat = uint32(item->Scroll.Level2); + stat = int32(item->Scroll.Level2); safe_delete(inst); return stat; From a85bb6aca6a14b0941e1c4f9b4d6c92598de63bd Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 16 Aug 2014 15:03:01 -0700 Subject: [PATCH 287/288] Cleanup before push --- changelog.txt | 3 + common/eq_dictionary.cpp.orig | 1151 --------------------------------- 2 files changed, 3 insertions(+), 1151 deletions(-) delete mode 100644 common/eq_dictionary.cpp.orig diff --git a/changelog.txt b/changelog.txt index 1f43ed0d9..c674316a8 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 08/16/2014 == +KLS: (addmoreice) Trying out some unstable DB changes. Do backup your database before trying them as master will be considered unstable for a few days at least. + == 08/15/2014 == Uleat: Reactivated the Bot::Spawn() code for sending post-spawn wear change updates..temporary until I can sort out the proper usage. diff --git a/common/eq_dictionary.cpp.orig b/common/eq_dictionary.cpp.orig deleted file mode 100644 index ecedcbb4e..000000000 --- a/common/eq_dictionary.cpp.orig +++ /dev/null @@ -1,1151 +0,0 @@ -/* -EQEMu: Everquest Server Emulator - -Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net) - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY except by those people which sell it, which -are required to give you total support for your newly bought product; -without even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "eq_dictionary.h" -#include "StringUtil.h" - -// -// class EmuConstants -// -uint16 EmuConstants::InventoryMapSize(int16 map) { - switch (map) { - case MapPossessions: - return MAP_POSSESSIONS_SIZE; - case MapBank: - return MAP_BANK_SIZE; - case MapSharedBank: - return MAP_SHARED_BANK_SIZE; - case MapTrade: - return MAP_TRADE_SIZE; - case MapWorld: - return MAP_WORLD_SIZE; - case MapLimbo: - return MAP_LIMBO_SIZE; - case MapTribute: - return MAP_TRIBUTE_SIZE; - case MapTrophyTribute: - return MAP_TROPHY_TRIBUTE_SIZE; - case MapGuildTribute: - return MAP_GUILD_TRIBUTE_SIZE; - case MapMerchant: - return MAP_MERCHANT_SIZE; - case MapDeleted: - return MAP_DELETED_SIZE; - case MapCorpse: - return MAP_CORPSE_SIZE; - case MapBazaar: - return MAP_BAZAAR_SIZE; - case MapInspect: - return MAP_INSPECT_SIZE; - case MapRealEstate: - return MAP_REAL_ESTATE_SIZE; - case MapViewMODPC: - return MAP_VIEW_MOD_PC_SIZE; - case MapViewMODBank: - return MAP_VIEW_MOD_BANK_SIZE; - case MapViewMODSharedBank: - return MAP_VIEW_MOD_SHARED_BANK_SIZE; - case MapViewMODLimbo: - return MAP_VIEW_MOD_LIMBO_SIZE; - case MapAltStorage: - return MAP_ALT_STORAGE_SIZE; - case MapArchived: - return MAP_ARCHIVED_SIZE; - case MapMail: - return MAP_MAIL_SIZE; - case MapGuildTrophyTribute: - return MAP_GUILD_TROPHY_TRIBUTE_SIZE; - case MapKrono: - return MAP_KRONO_SIZE; - case MapOther: - return MAP_OTHER_SIZE; - default: - return NOT_USED; - } -} - -/* -std::string EmuConstants::InventoryLocationName(Location_Struct location) { - // not ready for implementation... - std::string ret_str; - StringFormat(ret_str, "%s, %s, %s, %s", InventoryMapName(location.map), InventoryMainName(location.main), InventorySubName(location.sub), InventoryAugName(location.aug)); - return ret_str; -} -*/ - -std::string EmuConstants::InventoryMapName(int16 map) { - switch (map) { - case INVALID_INDEX: - return "Invalid Map"; - case MapPossessions: - return "Possessions"; - case MapBank: - return "Bank"; - case MapSharedBank: - return "Shared Bank"; - case MapTrade: - return "Trade"; - case MapWorld: - return "World"; - case MapLimbo: - return "Limbo"; - case MapTribute: - return "Tribute"; - case MapTrophyTribute: - return "Trophy Tribute"; - case MapGuildTribute: - return "Guild Tribute"; - case MapMerchant: - return "Merchant"; - case MapDeleted: - return "Deleted"; - case MapCorpse: - return "Corpse"; - case MapBazaar: - return "Bazaar"; - case MapInspect: - return "Inspect"; - case MapRealEstate: - return "Real Estate"; - case MapViewMODPC: - return "View MOD PC"; - case MapViewMODBank: - return "View MOD Bank"; - case MapViewMODSharedBank: - return "View MOD Shared Bank"; - case MapViewMODLimbo: - return "View MOD Limbo"; - case MapAltStorage: - return "Alt Storage"; - case MapArchived: - return "Archived"; - case MapMail: - return "Mail"; - case MapGuildTrophyTribute: - return "Guild Trophy Tribute"; - case MapKrono: - return "Krono"; - case MapOther: - return "Other"; - default: - return "Unknown Map"; - } -} - -std::string EmuConstants::InventoryMainName(int16 main) { - switch (main) { - case INVALID_INDEX: - return "Invalid Main"; - case MainCharm: - return "Charm"; - case MainEar1: - return "Ear 1"; - case MainHead: - return "Head"; - case MainFace: - return "Face"; - case MainEar2: - return "Ear 2"; - case MainNeck: - return "Neck"; - case MainShoulders: - return "Shoulders"; - case MainArms: - return "Arms"; - case MainBack: - return "Back"; - case MainWrist1: - return "Wrist 1"; - case MainWrist2: - return "Wrist 2"; - case MainRange: - return "Range"; - case MainHands: - return "Hands"; - case MainPrimary: - return "Primary"; - case MainSecondary: - return "Secondary"; - case MainFinger1: - return "Finger 1"; - case MainFinger2: - return "Finger 2"; - case MainChest: - return "Chest"; - case MainLegs: - return "Legs"; - case MainFeet: - return "Feet"; - case MainWaist: - return "Waist"; - case MainPowerSource: - return "Power Source"; - case MainAmmo: - return "Ammo"; - case MainGeneral1: - return "General 1"; - case MainGeneral2: - return "General 2"; - case MainGeneral3: - return "General 3"; - case MainGeneral4: - return "General 4"; - case MainGeneral5: - return "General 5"; - case MainGeneral6: - return "General 6"; - case MainGeneral7: - return "General 7"; - case MainGeneral8: - return "General 8"; - /* - case MainGeneral9: - return "General 9"; - case MainGeneral10: - return "General 10"; - */ - case MainCursor: - return "Cursor"; - default: - return "Unknown Main"; - } -} - -std::string EmuConstants::InventorySubName(int16 sub) { - if (sub == INVALID_INDEX) - return "Invalid Sub"; - - if ((uint16)sub >= ITEM_CONTAINER_SIZE) - return "Unknown Sub"; - - std::string ret_str; - ret_str = StringFormat("Container %i", (sub + 1)); // zero-based index..but, count starts at one - - return ret_str; -} - -std::string EmuConstants::InventoryAugName(int16 aug) { - if (aug == INVALID_INDEX) - return "Invalid Aug"; - - if ((uint16)aug >= ITEM_COMMON_SIZE) - return "Unknown Aug"; - - std::string ret_str; - ret_str = StringFormat("Augment %i", (aug + 1)); // zero-based index..but, count starts at one - - return ret_str; -} - -<<<<<<< HEAD -// -// class ClientLimits -======= -// legacy-related functions -// -// these should work for the first-stage coversions..but, once the new system is up and going..conversions will be incompatible -// without limiting server functions and other aspects, such as augment control, bag size, etc. A complete remapping will be -// required when bag sizes over 10 and direct manipulation of augments are implemented, due to the massive increase in range usage. -// -// (current personal/cursor bag range {251..340}, or 90 slots ... conversion translated range would be {10000..12804}, or 2805 slots... -// these would have to be hard-coded into all perl code to allow access to full range of the new system - actual limits would be -// less, based on bag size..but, the range must be full and consistent to avoid translation issues -- similar changes to other ranges -// (240 versus 6120 slots for bank bags, for example...)) -/* -int EmuConstants::ServerToPerlSlot(int server_slot) { // set r/s - switch (server_slot) { - case legacy::SLOT_CURSOR_END: - return legacy::SLOT_CURSOR_END; - case INVALID_INDEX: - return legacy::SLOT_INVALID; - case MainPowerSource: - return legacy::SLOT_POWER_SOURCE; - case MainAmmo: - return legacy::SLOT_AMMO; - case MainCursor: - return legacy::SLOT_CURSOR; - case legacy::SLOT_TRADESKILL: - return legacy::SLOT_TRADESKILL; - case legacy::SLOT_AUGMENT: - return legacy::SLOT_AUGMENT; - default: - int perl_slot = legacy::SLOT_INVALID; - - // activate the internal checks as needed - if (server_slot >= EmuConstants::EQUIPMENT_BEGIN && server_slot <= MainWaist) { - perl_slot = server_slot; - } - else if (server_slot >= EmuConstants::GENERAL_BEGIN && server_slot <= EmuConstants::GENERAL_END) { - perl_slot = server_slot;// + legacy::SLOT_PERSONAL_BEGIN - EmuConstants::GENERAL_BEGIN; - //if (perl_slot < legacy::SLOT_PERSONAL_BEGIN || perl_slot > legacy::SLOT_PERSONAL_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= EmuConstants::GENERAL_BAGS_BEGIN && server_slot <= EmuConstants::GENERAL_BAGS_END) { - perl_slot = server_slot;// + legacy::SLOT_PERSONAL_BAGS_BEGIN - EmuConstants::GENERAL_BAGS_BEGIN; - //if (perl_slot < legacy::SLOT_PERSONAL_BAGS_BEGIN || perl_slot > legacy::SLOT_PERSONAL_BAGS_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= EmuConstants::CURSOR_BAG_BEGIN && server_slot <= EmuConstants::CURSOR_BAG_END) { - perl_slot = server_slot;// + legacy::SLOT_CURSOR_BAG_BEGIN - EmuConstants::CURSOR_BAG_BEGIN; - //if (perl_slot < legacy::SLOT_CURSOR_BAG_BEGIN || perl_slot > legacy::SLOT_CURSOR_BAG_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= EmuConstants::TRIBUTE_BEGIN && server_slot <= EmuConstants::TRIBUTE_END) { - perl_slot = server_slot;// + legacy::SLOT_TRIBUTE_BEGIN - EmuConstants::TRADE_BEGIN; - //if (perl_slot < legacy::SLOT_TRIBUTE_BEGIN || perl_slot > legacy::SLOT_TRIBUTE_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= EmuConstants::BANK_BEGIN && server_slot <= EmuConstants::BANK_END) { - perl_slot = server_slot;// + legacy::SLOT_BANK_BEGIN - EmuConstants::BANK_BEGIN; - //if (perl_slot < legacy::SLOT_BANK_BEGIN || perl_slot > legacy::SLOT_BANK_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= EmuConstants::BANK_BAGS_BEGIN && server_slot <= EmuConstants::BANK_BAGS_END) { - perl_slot = server_slot;// + legacy::SLOT_BANK_BAGS_BEGIN - EmuConstants::BANK_BAGS_BEGIN; - //if (perl_slot < legacy::SLOT_BANK_BAGS_BEGIN || perl_slot > legacy::SLOT_BANK_BAGS_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= EmuConstants::SHARED_BANK_BEGIN && server_slot <= EmuConstants::SHARED_BANK_END) { - perl_slot = server_slot;// + legacy::SLOT_SHARED_BANK_BEGIN - EmuConstants::SHARED_BANK_BEGIN; - //if (perl_slot < legacy::SLOT_SHARED_BANK_BEGIN || perl_slot > legacy::SLOT_SHARED_BANK_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= EmuConstants::SHARED_BANK_BAGS_BEGIN && server_slot <= EmuConstants::SHARED_BANK_BAGS_END) { - perl_slot = server_slot;// + legacy::SLOT_SHARED_BANK_BAGS_BEGIN - EmuConstants::SHARED_BANK_BAGS_BEGIN; - //if (perl_slot < legacy::SLOT_SHARED_BANK_BAGS_BEGIN || perl_slot > legacy::SLOT_SHARED_BANK_BAGS_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= EmuConstants::TRADE_BEGIN && server_slot <= EmuConstants::TRADE_END) { - perl_slot = server_slot;// + legacy::SLOT_TRADE_BEGIN - EmuConstants::TRADE_BEGIN; - //if (perl_slot < legacy::SLOT_TRADE_BEGIN || perl_slot > legacy::SLOT_TRADE_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= EmuConstants::TRADE_BAGS_BEGIN && server_slot <= EmuConstants::TRADE_BAGS_END) { - perl_slot = server_slot;// + legacy::SLOT_TRADE_BAGS_BEGIN - EmuConstants::TRADE_BAGS_BEGIN; - //if (perl_slot < legacy::SLOT_TRADE_BAGS_BEGIN || perl_slot > legacy::SLOT_TRADE_BAGS_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= EmuConstants::WORLD_BEGIN && server_slot <= EmuConstants::WORLD_END) { - perl_slot = server_slot;// + legacy::SLOT_WORLD_BEGIN - EmuConstants::WORLD_BEGIN; - //if (perl_slot < legacy::SLOT_WORLD_BEGIN || perl_slot > legacy::SLOT_WORLD_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= 8000 && server_slot <= 8999) { // this range may be limited to 36 in the future (client size) - perl_slot = server_slot; - } - - return perl_slot; - } -} -*/ -/* -int EmuConstants::PerlToServerSlot(int perl_slot) { // set r/s - switch (perl_slot) { - case legacy::SLOT_CURSOR_END: - return legacy::SLOT_CURSOR_END; - case legacy::SLOT_INVALID: - return INVALID_INDEX; - case legacy::SLOT_POWER_SOURCE: - return MainPowerSource; - case legacy::SLOT_AMMO: - return MainAmmo; - case legacy::SLOT_CURSOR: - return MainCursor; - case legacy::SLOT_TRADESKILL: - return legacy::SLOT_TRADESKILL; - case legacy::SLOT_AUGMENT: - return legacy::SLOT_AUGMENT; - default: - int server_slot = INVALID_INDEX; - - // activate the internal checks as needed - if (perl_slot >= legacy::SLOT_EQUIPMENT_BEGIN && perl_slot <= legacy::SLOT_WAIST) { - server_slot = perl_slot; - } - else if (perl_slot >= legacy::SLOT_PERSONAL_BEGIN && perl_slot <= legacy::SLOT_PERSONAL_END) { - server_slot = perl_slot;// + EmuConstants::GENERAL_BEGIN - legacy::SLOT_PERSONAL_BEGIN; - //if (server_slot < EmuConstants::GENERAL_BEGIN || server_slot > EmuConstants::GENERAL_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= legacy::SLOT_PERSONAL_BAGS_BEGIN && perl_slot <= legacy::SLOT_PERSONAL_BAGS_END) { - server_slot = perl_slot;// + EmuConstants::GENERAL_BAGS_BEGIN - legacy::SLOT_PERSONAL_BAGS_BEGIN; - //if (server_slot < EmuConstants::GENERAL_BAGS_BEGIN || server_slot > EmuConstants::GENERAL_BAGS_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= legacy::SLOT_CURSOR_BAG_BEGIN && perl_slot <= legacy::SLOT_CURSOR_BAG_END) { - server_slot = perl_slot;// + EmuConstants::CURSOR_BAG_BEGIN - legacy::SLOT_CURSOR_BAG_BEGIN; - //if (server_slot < EmuConstants::CURSOR_BAG_BEGIN || server_slot > EmuConstants::CURSOR_BAG_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= legacy::SLOT_TRIBUTE_BEGIN && perl_slot <= legacy::SLOT_TRIBUTE_END) { - server_slot = perl_slot;// + EmuConstants::TRIBUTE_BEGIN - legacy::SLOT_TRIBUTE_BEGIN; - //if (server_slot < EmuConstants::TRIBUTE_BEGIN || server_slot > EmuConstants::TRIBUTE_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= legacy::SLOT_BANK_BEGIN && perl_slot <= legacy::SLOT_BANK_END) { - server_slot = perl_slot;// + EmuConstants::BANK_BEGIN - legacy::SLOT_BANK_BEGIN; - //if (server_slot < EmuConstants::BANK_BEGIN || server_slot > EmuConstants::BANK_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= legacy::SLOT_BANK_BAGS_BEGIN && perl_slot <= legacy::SLOT_BANK_BAGS_END) { - server_slot = perl_slot;// + EmuConstants::BANK_BAGS_BEGIN - legacy::SLOT_BANK_BAGS_BEGIN; - //if (server_slot < EmuConstants::BANK_BAGS_BEGIN || server_slot > EmuConstants::BANK_BAGS_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= legacy::SLOT_SHARED_BANK_BEGIN && perl_slot <= legacy::SLOT_SHARED_BANK_END) { - server_slot = perl_slot;// + EmuConstants::SHARED_BANK_BEGIN - legacy::SLOT_SHARED_BANK_BEGIN; - //if (server_slot < EmuConstants::SHARED_BANK_BEGIN || server_slot > EmuConstants::SHARED_BANK_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= legacy::SLOT_SHARED_BANK_BAGS_BEGIN && perl_slot <= legacy::SLOT_SHARED_BANK_BAGS_END) { - server_slot = perl_slot;// + EmuConstants::SHARED_BANK_BAGS_BEGIN - legacy::SLOT_SHARED_BANK_BAGS_END; - //if (server_slot < EmuConstants::SHARED_BANK_BAGS_BEGIN || server_slot > EmuConstants::SHARED_BANK_BAGS_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= legacy::SLOT_TRADE_BEGIN && perl_slot <= legacy::SLOT_TRADE_END) { - server_slot = perl_slot;// + EmuConstants::TRADE_BEGIN - legacy::SLOT_TRADE_BEGIN; - //if (server_slot < EmuConstants::TRADE_BEGIN || server_slot > EmuConstants::TRADE_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= legacy::SLOT_TRADE_BAGS_BEGIN && perl_slot <= legacy::SLOT_TRADE_BAGS_END) { - server_slot = perl_slot;// + EmuConstants::TRADE_BAGS_BEGIN - legacy::SLOT_TRADE_BAGS_BEGIN; - //if (server_slot < EmuConstants::TRADE_BAGS_BEGIN || server_slot > EmuConstants::TRADE_BAGS_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= legacy::SLOT_WORLD_BEGIN && perl_slot <= legacy::SLOT_WORLD_END) { - server_slot = perl_slot;// + EmuConstants::WORLD_BEGIN - legacy::SLOT_WORLD_BEGIN; - //if (server_slot < EmuConstants::WORLD_BEGIN || server_slot > EmuConstants::WORLD_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= 8000 && perl_slot <= 8999) { // this range may be limited to 36 in the future (client size) - server_slot = perl_slot; - } - - return server_slot; - } -} -*/ - -// -// class EQLimits ->>>>>>> upstream/master -// -// client validation -bool EQLimits::IsValidClientVersion(uint32 version) { - if (version < _EQClientCount) - return true; - - return false; -} - -uint32 EQLimits::ValidateClientVersion(uint32 version) { - if (version < _EQClientCount) - return version; - - return EQClientUnknown; -} - -EQClientVersion EQLimits::ValidateClientVersion(EQClientVersion version) { - if (version >= EQClientUnknown) - if (version < _EQClientCount) - return version; - - return EQClientUnknown; -} - -// npc validation -bool EQLimits::IsValidNPCVersion(uint32 version) { - if (version >= _EQClientCount) - if (version < _EmuClientCount) - return true; - - return false; -} - -uint32 EQLimits::ValidateNPCVersion(uint32 version) { - if (version >= _EQClientCount) - if (version < _EmuClientCount) - return version; - - return EQClientUnknown; -} - -EQClientVersion EQLimits::ValidateNPCVersion(EQClientVersion version) { - if (version >= _EQClientCount) - if (version < _EmuClientCount) - return version; - - return EQClientUnknown; -} - -// mob validation -bool EQLimits::IsValidMobVersion(uint32 version) { - if (version < _EmuClientCount) - return true; - - return false; -} - -uint32 EQLimits::ValidateMobVersion(uint32 version) { - if (version < _EmuClientCount) - return version; - - return EQClientUnknown; -} - -EQClientVersion EQLimits::ValidateMobVersion(EQClientVersion version) { - if (version >= EQClientUnknown) - if (version < _EmuClientCount) - return version; - - return EQClientUnknown; -} - -// inventory -uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { - // not all maps will have an instantiated container..some are references for queue generators (i.e., bazaar, mail, etc...) - // a zero '0' indicates a needed value..otherwise, change to '_NOTUSED' for a null value so indices requiring research can be identified - // ALL of these values need to be verified before pushing to live - // - // make sure that you transcribe the actual value from 'defaults' to here before updating or client crashes will ensue..and/or... - // insert older clients inside of the progression of client order - // - // MAP_POSSESSIONS_SIZE does not reflect all actual _constants size due to bitmask-use compatibility - // - // when setting NPC-based values, try to adhere to an EmuConstants:: or NOT_USED value to avoid unnecessary issues - - static const uint16 local[_MapCount][_EmuClientCount] = { - // server and database are sync'd to current MapPossessions's client as set in 'using namespace RoF::slots;' and - // 'EmuConstants::MAP_POSSESSIONS_SIZE' - use/update EquipmentBitmask(), GeneralBitmask() and CursorBitmask() - // for partial range validation checks and 'EmuConstants::MAP_POSSESSIONS_SIZE' for full range iterations - { // local[MainPossessions] -/*Unknown*/ NOT_USED, -/*62*/ EmuConstants::MAP_POSSESSIONS_SIZE, -/*Titanium*/ EmuConstants::MAP_POSSESSIONS_SIZE, -/*SoF*/ EmuConstants::MAP_POSSESSIONS_SIZE, -/*SoD*/ EmuConstants::MAP_POSSESSIONS_SIZE, -/*Underfoot*/ EmuConstants::MAP_POSSESSIONS_SIZE, -/*RoF*/ EmuConstants::MAP_POSSESSIONS_SIZE, -/*RoF2*/ 0, - -/*NPC*/ EmuConstants::MAP_POSSESSIONS_SIZE, -/*Merc*/ EmuConstants::MAP_POSSESSIONS_SIZE, -/*Bot*/ EmuConstants::MAP_POSSESSIONS_SIZE, -/*Pet*/ EmuConstants::MAP_POSSESSIONS_SIZE - }, - { // local[MapBank] -/*Unknown*/ NOT_USED, -/*62*/ Client62::consts::MAP_BANK_SIZE, -/*Titanium*/ Titanium::consts::MAP_BANK_SIZE, -/*SoF*/ EmuConstants::MAP_BANK_SIZE, -/*SoD*/ EmuConstants::MAP_BANK_SIZE, -/*Underfoot*/ EmuConstants::MAP_BANK_SIZE, -/*RoF*/ EmuConstants::MAP_BANK_SIZE, -/*RoF2*/ 0, - -/*NPC*/ NOT_USED, -/*Merc*/ NOT_USED, -/*Bot*/ NOT_USED, -/*Pet*/ NOT_USED - }, - { // local[MapSharedBank] -/*Unknown*/ NOT_USED, -/*62*/ EmuConstants::MAP_SHARED_BANK_SIZE, -/*Titanium*/ EmuConstants::MAP_SHARED_BANK_SIZE, -/*SoF*/ EmuConstants::MAP_SHARED_BANK_SIZE, -/*SoD*/ EmuConstants::MAP_SHARED_BANK_SIZE, -/*Underfoot*/ EmuConstants::MAP_SHARED_BANK_SIZE, -/*RoF*/ EmuConstants::MAP_SHARED_BANK_SIZE, -/*RoF2*/ 0, - -/*NPC*/ NOT_USED, -/*Merc*/ NOT_USED, -/*Bot*/ NOT_USED, -/*Pet*/ NOT_USED - }, - { // local[MapTrade] -/*Unknown*/ NOT_USED, -/*62*/ EmuConstants::MAP_TRADE_SIZE, -/*Titanium*/ EmuConstants::MAP_TRADE_SIZE, -/*SoF*/ EmuConstants::MAP_TRADE_SIZE, -/*SoD*/ EmuConstants::MAP_TRADE_SIZE, -/*Underfoot*/ EmuConstants::MAP_TRADE_SIZE, -/*RoF*/ EmuConstants::MAP_TRADE_SIZE, -/*RoF2*/ 0, - -/*NPC*/ 4, -/*Merc*/ 4, -/*Bot*/ EmuConstants::MAP_TRADE_SIZE, // client thinks this is another client -/*Pet*/ 4 - }, - { // local[MapWorld] -/*Unknown*/ NOT_USED, -/*62*/ EmuConstants::MAP_WORLD_SIZE, -/*Titanium*/ EmuConstants::MAP_WORLD_SIZE, -/*SoF*/ EmuConstants::MAP_WORLD_SIZE, -/*SoD*/ EmuConstants::MAP_WORLD_SIZE, -/*Underfoot*/ EmuConstants::MAP_WORLD_SIZE, -/*RoF*/ EmuConstants::MAP_WORLD_SIZE, -/*RoF2*/ 0, - -/*NPC*/ NOT_USED, -/*Merc*/ NOT_USED, -/*Bot*/ NOT_USED, -/*Pet*/ NOT_USED - }, - { // local[MapLimbo] -/*Unknown*/ NOT_USED, -/*62*/ EmuConstants::MAP_LIMBO_SIZE, -/*Titanium*/ EmuConstants::MAP_LIMBO_SIZE, -/*SoF*/ EmuConstants::MAP_LIMBO_SIZE, -/*SoD*/ EmuConstants::MAP_LIMBO_SIZE, -/*Underfoot*/ EmuConstants::MAP_LIMBO_SIZE, -/*RoF*/ EmuConstants::MAP_LIMBO_SIZE, -/*RoF2*/ 0, - -/*NPC*/ NOT_USED, -/*Merc*/ NOT_USED, -/*Bot*/ NOT_USED, -/*Pet*/ NOT_USED - }, - { // local[MapTribute] -/*Unknown*/ NOT_USED, -/*62*/ EmuConstants::MAP_TRIBUTE_SIZE, -/*Titanium*/ EmuConstants::MAP_TRIBUTE_SIZE, -/*SoF*/ EmuConstants::MAP_TRIBUTE_SIZE, -/*SoD*/ EmuConstants::MAP_TRIBUTE_SIZE, -/*Underfoot*/ EmuConstants::MAP_TRIBUTE_SIZE, -/*RoF*/ EmuConstants::MAP_TRIBUTE_SIZE, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[MapTrophyTribute] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_TROPHY_TRIBUTE_SIZE, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[MapGuildTribute] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_GUILD_TRIBUTE_SIZE, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[MapMerchant] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_MERCHANT_SIZE, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[MapDeleted] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_DELETED_SIZE, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[MapCorpse] -/*Unknown*/ NOT_USED, -/*62*/ Client62::consts::MAP_CORPSE_SIZE, -/*Titanium*/ Titanium::consts::MAP_CORPSE_SIZE, -/*SoF*/ SoF::consts::MAP_CORPSE_SIZE, -/*SoD*/ SoD::consts::MAP_CORPSE_SIZE, -/*Underfoot*/ Underfoot::consts::MAP_CORPSE_SIZE, -/*RoF*/ RoF::consts::MAP_CORPSE_SIZE, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[MapBazaar] -/*Unknown*/ NOT_USED, -/*62*/ EmuConstants::MAP_BAZAAR_SIZE, -/*Titanium*/ EmuConstants::MAP_BAZAAR_SIZE, -/*SoF*/ EmuConstants::MAP_BAZAAR_SIZE, -/*SoD*/ EmuConstants::MAP_BAZAAR_SIZE, -/*Underfoot*/ EmuConstants::MAP_BAZAAR_SIZE, -/*RoF*/ EmuConstants::MAP_BAZAAR_SIZE, -/*RoF2*/ 0, - -/*NPC*/ 0, // this may need to be 'EmuConstants::MAP_BAZAAR_SIZE' if offline client traders respawn as an npc -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[MapInspect] -/*Unknown*/ NOT_USED, -/*62*/ Client62::consts::MAP_INSPECT_SIZE, -/*Titanium*/ Titanium::consts::MAP_INSPECT_SIZE, -/*SoF*/ SoF::consts::MAP_INSPECT_SIZE, -/*SoD*/ SoD::consts::MAP_INSPECT_SIZE, -/*Underfoot*/ Underfoot::consts::MAP_INSPECT_SIZE, -/*RoF*/ RoF::consts::MAP_INSPECT_SIZE, -/*RoF2*/ 0, - -/*NPC*/ NOT_USED, -/*Merc*/ NOT_USED, -/*Bot*/ NOT_USED, -/*Pet*/ NOT_USED - }, - { // local[MapRealEstate] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_REAL_ESTATE_SIZE, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[MapViewMODPC] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_VIEW_MOD_PC_SIZE, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[MapViewMODBank] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_VIEW_MOD_BANK_SIZE, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[MapViewMODSharedBank] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_VIEW_MOD_SHARED_BANK_SIZE, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[MapViewMODLimbo] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_VIEW_MOD_LIMBO_SIZE, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[MapAltStorage] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_ALT_STORAGE_SIZE, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[MapArchived] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_ARCHIVED_SIZE, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[MapMail] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_MAIL_SIZE, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[MapGuildTrophyTribute] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_GUILD_TROPHY_TRIBUTE_SIZE, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[MapKrono] -/*Unknown*/ NOT_USED, -/*62*/ NOT_USED, -/*Titanium*/ NOT_USED, -/*SoF*/ NOT_USED, -/*SoD*/ NOT_USED, -/*Underfoot*/ NOT_USED, -/*RoF*/ EmuConstants::MAP_KRONO_SIZE, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[MapOther] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_OTHER_SIZE, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - } - }; - - if ((uint16)map < _MapCount) - return local[map][ValidateMobVersion(version)]; - - return NOT_USED; -} - -uint64 EQLimits::PossessionsBitmask(uint32 version) { - // these are for the new inventory system (RoF)..not the current (Ti) one... - // 0x0000000000200000 is SlotPowerSource (SoF+) - // 0x0000000080000000 is SlotGeneral9 (RoF+) - // 0x0000000100000000 is SlotGeneral10 (RoF+) - - static const uint64 local[_EmuClientCount] = { -/*Unknown*/ NOT_USED, -/*62*/ 0x000000027FDFFFFF, -/*Titanium*/ 0x000000027FDFFFFF, -/*SoF*/ 0x000000027FFFFFFF, -/*SoD*/ 0x000000027FFFFFFF, -/*Underfoot*/ 0x000000027FFFFFFF, -/*RoF*/ 0x00000003FFFFFFFF, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }; - - return NOT_USED; - //return local[ValidateMobVersion(version)]; -} - -uint64 EQLimits::EquipmentBitmask(uint32 version) { - static const uint64 local[_EmuClientCount] = { -/*Unknown*/ NOT_USED, -/*62*/ 0x00000000005FFFFF, -/*Titanium*/ 0x00000000005FFFFF, -/*SoF*/ 0x00000000007FFFFF, -/*SoD*/ 0x00000000007FFFFF, -/*Underfoot*/ 0x00000000007FFFFF, -/*RoF*/ 0x00000000007FFFFF, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }; - - return NOT_USED; - //return local[ValidateMobVersion(version)]; -} - -uint64 EQLimits::GeneralBitmask(uint32 version) { - static const uint64 local[_EmuClientCount] = { -/*Unknown*/ NOT_USED, -/*62*/ 0x000000007F800000, -/*Titanium*/ 0x000000007F800000, -/*SoF*/ 0x000000007F800000, -/*SoD*/ 0x000000007F800000, -/*Underfoot*/ 0x000000007F800000, -/*RoF*/ 0x00000001FF800000, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }; - - return NOT_USED; - //return local[ValidateMobVersion(version)]; -} - -uint64 EQLimits::CursorBitmask(uint32 version) { - static const uint64 local[_EmuClientCount] = { -/*Unknown*/ NOT_USED, -/*62*/ 0x0000000200000000, -/*Titanium*/ 0x0000000200000000, -/*SoF*/ 0x0000000200000000, -/*SoD*/ 0x0000000200000000, -/*Underfoot*/ 0x0000000200000000, -/*RoF*/ 0x0000000200000000, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }; - - return NOT_USED; - //return local[ValidateMobVersion(version)]; -} - -bool EQLimits::AllowsEmptyBagInBag(uint32 version) { - static const bool local[_EmuClientCount] = { -/*Unknown*/ false, -/*62*/ Client62::limits::ALLOWS_EMPTY_BAG_IN_BAG, -/*Titanium*/ Titanium::limits::ALLOWS_EMPTY_BAG_IN_BAG, -/*SoF*/ SoF::limits::ALLOWS_EMPTY_BAG_IN_BAG, -/*SoD*/ SoD::limits::ALLOWS_EMPTY_BAG_IN_BAG, -/*Underfoot*/ Underfoot::limits::ALLOWS_EMPTY_BAG_IN_BAG, -/*RoF*/ RoF::limits::ALLOWS_EMPTY_BAG_IN_BAG, -/*RoF2*/ false, - -/*NPC*/ false, -/*Merc*/ false, -/*Bot*/ false, -/*Pet*/ false - }; - - return false; // not implemented - //return local[ValidateMobVersion(version)]; -} - -// items -uint16 EQLimits::ItemCommonSize(uint32 version) { - static const uint16 local[_EmuClientCount] = { -/*Unknown*/ NOT_USED, -/*62*/ EmuConstants::ITEM_COMMON_SIZE, -/*Titanium*/ EmuConstants::ITEM_COMMON_SIZE, -/*SoF*/ EmuConstants::ITEM_COMMON_SIZE, -/*SoD*/ EmuConstants::ITEM_COMMON_SIZE, -/*Underfoot*/ EmuConstants::ITEM_COMMON_SIZE, -/*RoF*/ EmuConstants::ITEM_COMMON_SIZE, -/*RoF2*/ 0, - -/*NPC*/ EmuConstants::ITEM_COMMON_SIZE, -/*Merc*/ EmuConstants::ITEM_COMMON_SIZE, -/*Bot*/ EmuConstants::ITEM_COMMON_SIZE, -/*Pet*/ EmuConstants::ITEM_COMMON_SIZE - }; - - return local[ValidateMobVersion(version)]; -} - -uint16 EQLimits::ItemContainerSize(uint32 version) { - static const uint16 local[_EmuClientCount] = { -/*Unknown*/ NOT_USED, -/*62*/ EmuConstants::ITEM_CONTAINER_SIZE, -/*Titanium*/ EmuConstants::ITEM_CONTAINER_SIZE, -/*SoF*/ EmuConstants::ITEM_CONTAINER_SIZE, -/*SoD*/ EmuConstants::ITEM_CONTAINER_SIZE, -/*Underfoot*/ EmuConstants::ITEM_CONTAINER_SIZE, -/*RoF*/ EmuConstants::ITEM_CONTAINER_SIZE, -/*RoF2*/ 0, - -/*NPC*/ EmuConstants::ITEM_CONTAINER_SIZE, -/*Merc*/ EmuConstants::ITEM_CONTAINER_SIZE, -/*Bot*/ EmuConstants::ITEM_CONTAINER_SIZE, -/*Pet*/ EmuConstants::ITEM_CONTAINER_SIZE - }; - - return local[ValidateMobVersion(version)]; -} - -bool EQLimits::CoinHasWeight(uint32 version) { - static const bool local[_EmuClientCount] = { -/*Unknown*/ true, -/*62*/ Client62::limits::COIN_HAS_WEIGHT, -/*Titanium*/ Titanium::limits::COIN_HAS_WEIGHT, -/*SoF*/ SoF::limits::COIN_HAS_WEIGHT, -/*SoD*/ SoD::limits::COIN_HAS_WEIGHT, -/*Underfoot*/ Underfoot::limits::COIN_HAS_WEIGHT, -/*RoF*/ RoF::limits::COIN_HAS_WEIGHT, -/*RoF2*/ true, - -/*NPC*/ true, -/*Merc*/ true, -/*Bot*/ true, -/*Pet*/ true - }; - - return local[ValidateMobVersion(version)]; -} - -uint32 EQLimits::BandoliersCount(uint32 version) { - static const uint32 local[_EmuClientCount] = { -/*Unknown*/ NOT_USED, -/*62*/ EmuConstants::BANDOLIERS_COUNT, -/*Titanium*/ EmuConstants::BANDOLIERS_COUNT, -/*SoF*/ EmuConstants::BANDOLIERS_COUNT, -/*SoD*/ EmuConstants::BANDOLIERS_COUNT, -/*Underfoot*/ EmuConstants::BANDOLIERS_COUNT, -/*RoF*/ EmuConstants::BANDOLIERS_COUNT, -/*RoF2*/ 0, - -/*NPC*/ NOT_USED, -/*Merc*/ NOT_USED, -/*Bot*/ NOT_USED, -/*Pet*/ NOT_USED - }; - - return local[ValidateMobVersion(version)]; -} - -uint32 EQLimits::BandolierSize(uint32 version) { - static const uint32 local[_EmuClientCount] = { -/*Unknown*/ NOT_USED, -/*62*/ EmuConstants::BANDOLIER_SIZE, -/*Titanium*/ EmuConstants::BANDOLIER_SIZE, -/*SoF*/ EmuConstants::BANDOLIER_SIZE, -/*SoD*/ EmuConstants::BANDOLIER_SIZE, -/*Underfoot*/ EmuConstants::BANDOLIER_SIZE, -/*RoF*/ EmuConstants::BANDOLIER_SIZE, -/*RoF2*/ 0, - -/*NPC*/ NOT_USED, -/*Merc*/ NOT_USED, -/*Bot*/ NOT_USED, -/*Pet*/ NOT_USED - }; - - return local[ValidateMobVersion(version)]; -} - -uint32 EQLimits::PotionBeltSize(uint32 version) { - static const uint32 local[_EmuClientCount] = { -/*Unknown*/ NOT_USED, -/*62*/ EmuConstants::POTION_BELT_SIZE, -/*Titanium*/ EmuConstants::POTION_BELT_SIZE, -/*SoF*/ EmuConstants::POTION_BELT_SIZE, -/*SoD*/ EmuConstants::POTION_BELT_SIZE, -/*Underfoot*/ EmuConstants::POTION_BELT_SIZE, -/*RoF*/ EmuConstants::POTION_BELT_SIZE, -/*RoF2*/ 0, - -/*NPC*/ NOT_USED, -/*Merc*/ NOT_USED, -/*Bot*/ NOT_USED, -/*Pet*/ NOT_USED - }; - - return local[ValidateMobVersion(version)]; -} From 9e1549b61b4a7fa493d2f6a77452cff4624650e4 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 16 Aug 2014 18:12:21 -0400 Subject: [PATCH 288/288] Fix for invalid handling of heading criteria in Client::Handle_OP_ClientUpdate() --- changelog.txt | 9 +++++++++ common/MiscFunctions.h | 3 ++- zone/client_packet.cpp | 6 ++++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/changelog.txt b/changelog.txt index 1f43ed0d9..6e1240815 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,14 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 08/16/2014 == +Uleat (Noudness): Fixed a floating-point comparison error that led to the notorious 'client bounce' (this is not related to the +'mob falling' due to not having maps installed.) This fix also eliminates a sizeable amount of unnecessary out-going packets due +to invalid orientation corrections. + +Note: This patch is probably of significant enough importance that admins may wish to manually apply this to older server builds. +The number of packets reduced per second should be approximately (num_stationary_close_clients * (num_close_clients - 1)). This will +likely have the most effect in zones like: Nexus, Bazaar, Guilds (Halls) and RAID INSTANCES - where players don't move around a lot. + == 08/15/2014 == Uleat: Reactivated the Bot::Spawn() code for sending post-spawn wear change updates..temporary until I can sort out the proper usage. diff --git a/common/MiscFunctions.h b/common/MiscFunctions.h index 2117773f6..c057af8d8 100644 --- a/common/MiscFunctions.h +++ b/common/MiscFunctions.h @@ -103,7 +103,8 @@ int NewFloatToEQ13(float d); int FloatToEQ19(float d); int FloatToEQH(float d); - +// macro to catch fp errors (provided by noudness) +#define FCMP(a,b) (fabs(a-b) < FLT_EPSILON) #define _ITOA_BUFLEN 25 const char *itoa(int num); //not thread safe diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 0d44bfa93..ff8b9e717 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1231,7 +1231,6 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) delta_y = ppu->delta_y; delta_z = ppu->delta_z; delta_heading = ppu->delta_heading; - heading = EQ19toFloat(ppu->heading); if(IsTracking() && ((x_pos!=ppu->x_pos) || (y_pos!=ppu->y_pos))){ if(MakeRandomFloat(0, 100) < 70)//should be good @@ -1257,12 +1256,15 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) } // Outgoing client packet - if (ppu->y_pos != y_pos || ppu->x_pos != x_pos || ppu->heading != heading || ppu->animation != animation) + float tmpheading = EQ19toFloat(ppu->heading); + + if (!FCMP(ppu->y_pos, y_pos) || !FCMP(ppu->x_pos, x_pos) || !FCMP(tmpheading, heading) || ppu->animation != animation) { x_pos = ppu->x_pos; y_pos = ppu->y_pos; z_pos = ppu->z_pos; animation = ppu->animation; + heading = tmpheading; EQApplicationPacket* outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); PlayerPositionUpdateServer_Struct* ppu = (PlayerPositionUpdateServer_Struct*)outapp->pBuffer;