mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 21:01:29 +00:00
This commit is contained in:
commit
87efd22394
16
.travis.yml
Normal file
16
.travis.yml
Normal file
@ -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
|
||||
54
README.md
54
README.md
@ -1,5 +1,53 @@
|
||||
EQEmu - Custom Game Implementation for EverQuest
|
||||
EQEmu
|
||||
===
|
||||
|
||||
Dependencies can be obtained at http://eqemu.github.io
|
||||
[](https://travis-ci.org/EQEmu/Server)
|
||||
|
||||
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](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
|
||||
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
|
||||
|
||||
@ -1,5 +1,32 @@
|
||||
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.
|
||||
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.
|
||||
|
||||
== 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)
|
||||
- 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).
|
||||
-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
|
||||
|
||||
== 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.)
|
||||
|
||||
@ -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)) {
|
||||
|
||||
@ -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;
|
||||
@ -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);
|
||||
|
||||
@ -234,4 +234,4 @@ void ImportBaseData(SharedDatabase *db) {
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
@ -916,8 +916,7 @@ void Inventory::dumpItemCollection(const std::map<int16, ItemInst*> &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);
|
||||
@ -936,8 +935,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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
@ -384,3 +379,15 @@ std::string EscapeString(const std::string &s) {
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool isAlphaNumeric(const char *text)
|
||||
{
|
||||
for (unsigned int charIndex=0; charIndex<strlen(text); charIndex++) {
|
||||
if ((text[charIndex] < 'a' || text[charIndex] > 'z') &&
|
||||
(text[charIndex] < 'A' || text[charIndex] > 'Z') &&
|
||||
(text[charIndex] < '0' || text[charIndex] > '9'))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -19,11 +19,12 @@
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <cstdarg>
|
||||
#include <string.h>
|
||||
#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);
|
||||
@ -51,4 +52,6 @@ char *RemoveApostrophes(const char *s);
|
||||
|
||||
std::vector<std::string> SplitString(const std::string &s, char delim);
|
||||
|
||||
bool isAlphaNumeric(const char *text);
|
||||
|
||||
#endif
|
||||
|
||||
3381
common/database.cpp
3381
common/database.cpp
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
@ -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
|
||||
@ -223,7 +224,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
|
||||
@ -262,7 +263,20 @@ private:
|
||||
uint32 varcache_max;
|
||||
VarCache_Struct** varcache_array;
|
||||
uint32 varcache_lastupdate;
|
||||
|
||||
|
||||
/*
|
||||
* Groups, utility methods.
|
||||
*/
|
||||
void ClearAllGroupLeaders();
|
||||
void ClearAllGroups();
|
||||
|
||||
|
||||
/*
|
||||
* Raid, utility methods.
|
||||
*/
|
||||
void ClearAllRaids();
|
||||
void ClearAllRaidDetails();
|
||||
};
|
||||
|
||||
bool FetchRowMap(MYSQL_RES *result, std::map<std::string,std::string> &rowmap);
|
||||
#endif
|
||||
|
||||
@ -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,26 @@ 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;
|
||||
}
|
||||
|
||||
@ -237,7 +237,7 @@ std::string EmuConstants::InventorySubName(int16 sub) {
|
||||
return "Unknown Sub";
|
||||
|
||||
std::string ret_str;
|
||||
StringFormat(ret_str, "Container %i", (sub + 1)); // zero-based index..but, count starts at one
|
||||
ret_str = StringFormat("Container %i", (sub + 1)); // zero-based index..but, count starts at one
|
||||
|
||||
return ret_str;
|
||||
}
|
||||
@ -250,7 +250,7 @@ std::string EmuConstants::InventoryAugName(int16 aug) {
|
||||
return "Unknown Aug";
|
||||
|
||||
std::string ret_str;
|
||||
StringFormat(ret_str, "Augment %i", (aug + 1)); // zero-based index..but, count starts at one
|
||||
ret_str = StringFormat("Augment %i", (aug + 1)); // zero-based index..but, count starts at one
|
||||
|
||||
return ret_str;
|
||||
}
|
||||
@ -929,7 +929,7 @@ uint64 EQLimits::PossessionsBitmask(uint32 version) {
|
||||
/*Underfoot*/ 0x000000027FFFFFFF,
|
||||
/*RoF*/ 0x00000003FFFFFFFF,
|
||||
/*RoF2*/ 0,
|
||||
|
||||
|
||||
/*NPC*/ 0,
|
||||
/*Merc*/ 0,
|
||||
/*Bot*/ 0,
|
||||
@ -950,7 +950,7 @@ uint64 EQLimits::EquipmentBitmask(uint32 version) {
|
||||
/*Underfoot*/ 0x00000000007FFFFF,
|
||||
/*RoF*/ 0x00000000007FFFFF,
|
||||
/*RoF2*/ 0,
|
||||
|
||||
|
||||
/*NPC*/ 0,
|
||||
/*Merc*/ 0,
|
||||
/*Bot*/ 0,
|
||||
@ -971,7 +971,7 @@ uint64 EQLimits::GeneralBitmask(uint32 version) {
|
||||
/*Underfoot*/ 0x000000007F800000,
|
||||
/*RoF*/ 0x00000001FF800000,
|
||||
/*RoF2*/ 0,
|
||||
|
||||
|
||||
/*NPC*/ 0,
|
||||
/*Merc*/ 0,
|
||||
/*Bot*/ 0,
|
||||
@ -992,7 +992,7 @@ uint64 EQLimits::CursorBitmask(uint32 version) {
|
||||
/*Underfoot*/ 0x0000000200000000,
|
||||
/*RoF*/ 0x0000000200000000,
|
||||
/*RoF2*/ 0,
|
||||
|
||||
|
||||
/*NPC*/ 0,
|
||||
/*Merc*/ 0,
|
||||
/*Bot*/ 0,
|
||||
@ -1013,13 +1013,13 @@ bool EQLimits::AllowsEmptyBagInBag(uint32 version) {
|
||||
/*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)];
|
||||
}
|
||||
@ -1035,7 +1035,7 @@ uint16 EQLimits::ItemCommonSize(uint32 version) {
|
||||
/*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,
|
||||
@ -1055,7 +1055,7 @@ uint16 EQLimits::ItemContainerSize(uint32 version) {
|
||||
/*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,
|
||||
@ -1075,7 +1075,7 @@ bool EQLimits::CoinHasWeight(uint32 version) {
|
||||
/*Underfoot*/ Underfoot::limits::COIN_HAS_WEIGHT,
|
||||
/*RoF*/ RoF::limits::COIN_HAS_WEIGHT,
|
||||
/*RoF2*/ true,
|
||||
|
||||
|
||||
/*NPC*/ true,
|
||||
/*Merc*/ true,
|
||||
/*Bot*/ true,
|
||||
@ -1095,7 +1095,7 @@ uint32 EQLimits::BandoliersCount(uint32 version) {
|
||||
/*Underfoot*/ EmuConstants::BANDOLIERS_COUNT,
|
||||
/*RoF*/ EmuConstants::BANDOLIERS_COUNT,
|
||||
/*RoF2*/ 0,
|
||||
|
||||
|
||||
/*NPC*/ NOT_USED,
|
||||
/*Merc*/ NOT_USED,
|
||||
/*Bot*/ NOT_USED,
|
||||
@ -1115,7 +1115,7 @@ uint32 EQLimits::BandolierSize(uint32 version) {
|
||||
/*Underfoot*/ EmuConstants::BANDOLIER_SIZE,
|
||||
/*RoF*/ EmuConstants::BANDOLIER_SIZE,
|
||||
/*RoF2*/ 0,
|
||||
|
||||
|
||||
/*NPC*/ NOT_USED,
|
||||
/*Merc*/ NOT_USED,
|
||||
/*Bot*/ NOT_USED,
|
||||
@ -1135,7 +1135,7 @@ uint32 EQLimits::PotionBeltSize(uint32 version) {
|
||||
/*Underfoot*/ EmuConstants::POTION_BELT_SIZE,
|
||||
/*RoF*/ EmuConstants::POTION_BELT_SIZE,
|
||||
/*RoF2*/ 0,
|
||||
|
||||
|
||||
/*NPC*/ NOT_USED,
|
||||
/*Merc*/ NOT_USED,
|
||||
/*Bot*/ NOT_USED,
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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]);
|
||||
@ -1720,11 +1720,13 @@ 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]);
|
||||
|
||||
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]);
|
||||
@ -1740,17 +1742,26 @@ 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<float>(atoi(row[194]));
|
||||
sp[tempid].directional_end = static_cast<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 = static_cast<float>(atoi(row[231]));
|
||||
sp[tempid].DamageShieldType = 0;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
@ -1764,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;
|
||||
@ -1815,7 +1826,7 @@ bool SharedDatabase::LoadBaseData() {
|
||||
void SharedDatabase::LoadBaseData(void *data, int max_level) {
|
||||
char *base_ptr = reinterpret_cast<char*>(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;
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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 {
|
||||
@ -690,15 +690,15 @@ 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 */
|
||||
/* 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,22 +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
|
||||
/* 215 - 218 */
|
||||
/* 219 */ //int maxtargets; // is used for beam and ring spells for target # limits (not implemented)
|
||||
/* 220 - 223 */
|
||||
/* 213 */ bool InCombat; //Allow spell if target is in combat
|
||||
/* 214 */ bool OutofCombat; //Allow spell if target is out of combat
|
||||
/* 215 - 217 */
|
||||
/* 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 */ float min_range; //Min casting range
|
||||
/* 232 - 236 */
|
||||
uint8 DamageShieldType; // This field does not exist in spells_us.txt
|
||||
};
|
||||
|
||||
@ -837,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);
|
||||
|
||||
1
utils/scripts/.gitignore
vendored
Normal file
1
utils/scripts/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
opcode_handlers_output
|
||||
1471
utils/scripts/opcode_handlers.py
Normal file
1471
utils/scripts/opcode_handlers.py
Normal file
File diff suppressed because it is too large
Load Diff
1
utils/sql/git/optional/2014_08_12_raid_timer_rule.sql
Normal file
1
utils/sql/git/optional/2014_08_12_raid_timer_rule.sql
Normal file
@ -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.');
|
||||
34
utils/sql/git/required/2014_06_25_AA_Updates..sql
Normal file
34
utils/sql/git/required/2014_06_25_AA_Updates..sql
Normal file
@ -0,0 +1,34 @@
|
||||
-- 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;
|
||||
|
||||
-- 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');
|
||||
|
||||
-- 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');
|
||||
|
||||
-- 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');
|
||||
18
utils/sql/git/required/2014_08_02_spells_new.sql
Normal file
18
utils/sql/git/required/2014_08_02_spells_new.sql
Normal file
@ -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`;
|
||||
|
||||
1
utils/sql/git/required/2014_08_12_NPC_raid_targets.sql
Normal file
1
utils/sql/git/required/2014_08_12_NPC_raid_targets.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE `npc_types` ADD `raid_target` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `no_target_hotkey`;
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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.
|
||||
@ -316,6 +317,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.
|
||||
|
||||
@ -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);
|
||||
|
||||
19
zone/bot.cpp
19
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());
|
||||
@ -4329,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);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
@ -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<uint32> zone_flags;
|
||||
|
||||
|
||||
@ -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;
|
||||
@ -9140,7 +9142,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
|
||||
|
||||
@ -740,6 +740,8 @@ 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);
|
||||
bool isnpc = caster->IsNPC();
|
||||
@ -755,7 +757,11 @@ 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 (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);
|
||||
@ -786,6 +792,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) {
|
||||
|
||||
@ -4538,7 +4538,7 @@ Mob *EntityList::GetClosestMobByBodyType(Mob *sender, bodyType BodyType)
|
||||
return ClosestMob;
|
||||
}
|
||||
|
||||
void EntityList::GetTargetsForConeArea(Mob *start, uint32 radius, uint32 height, std::list<Mob*> &m_list)
|
||||
void EntityList::GetTargetsForConeArea(Mob *start, float min_radius, float radius, float height, std::list<Mob*> &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);
|
||||
|
||||
|
||||
@ -406,7 +406,7 @@ public:
|
||||
void GetObjectList(std::list<Object*> &o_list);
|
||||
void GetDoorsList(std::list<Doors*> &d_list);
|
||||
void GetSpawnList(std::list<Spawn2*> &d_list);
|
||||
void GetTargetsForConeArea(Mob *start, uint32 radius, uint32 height, std::list<Mob*> &m_list);
|
||||
void GetTargetsForConeArea(Mob *start, float min_radius, float radius, float height, std::list<Mob*> &m_list);
|
||||
|
||||
void DepopAll(int NPCTypeID, bool StartSpawnTimer = true);
|
||||
|
||||
|
||||
@ -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,8 @@ 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
|
||||
if(members[z]->GetPet() && members[z]->HasPetAffinity() && !members[z]->GetPet()->IsCharmed())
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -567,20 +570,25 @@ void HateList::SpellCast(Mob *caster, uint32 spell_id, float range)
|
||||
//So keep a list of entity ids and look up after
|
||||
std::list<uint32> 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())
|
||||
{
|
||||
tHateEntry *h = (*iterator);
|
||||
if(range > 0)
|
||||
{
|
||||
if(caster->DistNoRoot(*h->ent) <= range)
|
||||
dist_targ = caster->DistNoRoot(*h->ent);
|
||||
if(dist_targ <= range && dist_targ >= min_range2)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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))
|
||||
|
||||
317
zone/mob.cpp
317
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;
|
||||
@ -3536,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)
|
||||
@ -3549,7 +3550,7 @@ uint32 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)
|
||||
@ -3558,316 +3559,318 @@ uint32 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;
|
||||
|
||||
@ -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;}
|
||||
@ -552,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);
|
||||
@ -615,6 +616,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 +1118,7 @@ protected:
|
||||
bool has_numhits;
|
||||
bool has_MGB;
|
||||
bool has_ProjectIllusion;
|
||||
int16 SpellPowerDistanceMod;
|
||||
|
||||
// Bind wound
|
||||
Timer bindwound_timer;
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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<MercType> mercTypeList;
|
||||
std::list<MercData> mercDataList;
|
||||
|
||||
bool raid_target;
|
||||
|
||||
private:
|
||||
uint32 loottable_id;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -2015,7 +2015,7 @@ float Mob::GetSpecialProcChances(uint16 hand)
|
||||
ProcBonus += static_cast<float>(mydex/35) + static_cast<float>(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.”
|
||||
/*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<float>(mydex/35) + static_cast<float>(itembonuses.HeroicDEX / 25))/100.0f;
|
||||
|
||||
@ -186,6 +186,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
buffs[buffslot].numhits = numhit;
|
||||
}
|
||||
|
||||
if (!IsPowerDistModSpell(spell_id))
|
||||
SetSpellPowerDistanceMod(0);
|
||||
|
||||
// iterate through the effects in the spell
|
||||
for (i = 0; i < EFFECT_COUNT; i++)
|
||||
{
|
||||
@ -198,6 +201,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 (GetSpellPowerDistanceMod())
|
||||
effect_value = effect_value*(GetSpellPowerDistanceMod()/100);
|
||||
|
||||
#ifdef SPELL_EFFECT_SPAM
|
||||
effect_desc[0] = 0;
|
||||
#endif
|
||||
@ -2705,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;
|
||||
@ -6444,4 +6450,24 @@ bool Mob::CheckSpellCategory(uint16 spell_id, int category_id, int effect_id){
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
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<int>(mod));
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
@ -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
|
||||
@ -1734,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);
|
||||
@ -1833,7 +1897,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);
|
||||
@ -1863,12 +1927,21 @@ 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);
|
||||
}
|
||||
|
||||
//
|
||||
@ -2052,7 +2125,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16
|
||||
std::list<Mob*> targets_in_range;
|
||||
std::list<Mob*>::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())
|
||||
{
|
||||
@ -2068,16 +2141,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;
|
||||
@ -4625,12 +4702,10 @@ void Mob::Stun(int duration)
|
||||
if(stunned && stunned_timer.GetRemainingTime() > uint32(duration))
|
||||
return;
|
||||
|
||||
if(casting_spell_id) {
|
||||
int persistent_casting = spellbonuses.PersistantCasting + itembonuses.PersistantCasting;
|
||||
if(IsClient())
|
||||
persistent_casting += aabonuses.PersistantCasting;
|
||||
if(IsValidSpell(casting_spell_id) && !spells[casting_spell_id].uninterruptable) {
|
||||
int persistent_casting = spellbonuses.PersistantCasting + itembonuses.PersistantCasting + aabonuses.PersistantCasting;
|
||||
|
||||
if(MakeRandomInt(1,99) > persistent_casting)
|
||||
if(MakeRandomInt(0,99) > persistent_casting)
|
||||
InterruptSpell();
|
||||
}
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -125,6 +125,7 @@ struct NPCType
|
||||
float spellscale;
|
||||
float healscale;
|
||||
bool no_target_hotkey;
|
||||
bool raid_target;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user