mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-23 21:32:28 +00:00
Compare commits
297 Commits
profiler
...
data_verify
| Author | SHA1 | Date | |
|---|---|---|---|
| a6675a483d | |||
| 923252dbcc | |||
| c3a805923c | |||
| 32e880f571 | |||
| 5481847987 | |||
| 6503e6371a | |||
| ca311c8990 | |||
| c5609db8d1 | |||
| 6ffe7a9563 | |||
| 0dcf34d62b | |||
| 08f8e2e55c | |||
| 34655e7753 | |||
| 56e064751b | |||
| a583391319 | |||
| de81850dd9 | |||
| b1829e929e | |||
| 8dccc8bf90 | |||
| 8174428189 | |||
| 5186d3a2ef | |||
| 226bb4f3b2 | |||
| 6229b90451 | |||
| db307d865b | |||
| 4bb2bb1438 | |||
| f198ab714f | |||
| c2e4365214 | |||
| 4a036bede2 | |||
| f35594947c | |||
| f57734e591 | |||
| 42a5ddcf77 | |||
| 03bc245318 | |||
| a9b98ed057 | |||
| b45f0f9dbc | |||
| 6cb1861c91 | |||
| 0b17dc73f1 | |||
| fafbecb055 | |||
| a5d9faf8ea | |||
| 00d258a952 | |||
| 64caf298fb | |||
| 7f30950fdb | |||
| dbd07106d7 | |||
| 328b7bb93c | |||
| c351a9b54f | |||
| 6ff06ded43 | |||
| 2c6fd44811 | |||
| 66d37cabe4 | |||
| 9a5ff58213 | |||
| c3c6d18979 | |||
| aacd288ad7 | |||
| 46dd1511af | |||
| 7011395d4c | |||
| 03c006bef5 | |||
| bfb40f6c5f | |||
| 38cdea7d7e | |||
| d9cab4820a | |||
| 96264cb688 | |||
| b0d85e3558 | |||
| 0348c0817d | |||
| a41fd122bc | |||
| 8646791d1d | |||
| 070183789b | |||
| 36de3879f8 | |||
| e588af2e79 | |||
| 2416960818 | |||
| be210950d7 | |||
| 5917052a6d | |||
| d7b9d7c990 | |||
| 235d6b6c48 | |||
| 95243fd6ce | |||
| e5f979665d | |||
| 22ef16947c | |||
| dbbae0e735 | |||
| 24917257e6 | |||
| dbd615572c | |||
| 92c756c820 | |||
| 76d7fe1586 | |||
| 4424afac94 | |||
| 2b495cea5a | |||
| e7902342dd | |||
| 5c194c7087 | |||
| b6091c1960 | |||
| d2a1fb7acf | |||
| ee136881c8 | |||
| b06e1c2041 | |||
| 41ca23eb7c | |||
| 5c4389effb | |||
| 788959a5e2 | |||
| aaca6fd2d9 | |||
| 1bcb5c72a5 | |||
| 249d67a1c3 | |||
| 85bdcf413b | |||
| 93942fa82b | |||
| 8922c72452 | |||
| ec8e7139ec | |||
| a882397eb6 | |||
| 7d61934ce6 | |||
| 7041db7480 | |||
| 70048eb6e1 | |||
| a46b1ac18b | |||
| 00721f4a96 | |||
| 8aadc36320 | |||
| 351e63ae72 | |||
| 9cbda0f81b | |||
| ea44b4b3b1 | |||
| ea5a1dd6f1 | |||
| 2ef0fc9342 | |||
| 02c3fd0905 | |||
| 4266f45295 | |||
| 553b7c9f8c | |||
| 79a87fac1d | |||
| 2308d3e880 | |||
| cbcaead8df | |||
| 4b7871a665 | |||
| 052f343e4d | |||
| e6f6da7845 | |||
| cc2a60feb2 | |||
| d5eeaf4f47 | |||
| 6fad93aeee | |||
| d1fbd086d7 | |||
| c360aa9b0f | |||
| f68952c168 | |||
| bf4ff03641 | |||
| 103d808925 | |||
| 53a139256d | |||
| 7bcfaf60ab | |||
| ebe2ea697e | |||
| 8224a9e776 | |||
| be0507c4d3 | |||
| cfedf53dc0 | |||
| 4a4a0c5e8b | |||
| 77dca484fe | |||
| 690274338d | |||
| 59ab7071b7 | |||
| 1438c1a9c3 | |||
| 72702be820 | |||
| 1ab3cf53e2 | |||
| 79928c190b | |||
| 6c8dfbdc4d | |||
| 1f56c7476e | |||
| eda74e66e0 | |||
| 80fd71a406 | |||
| 399942f6f4 | |||
| 3846dc2bbc | |||
| 06f4fd49ef | |||
| eea667e22d | |||
| 8b4d601027 | |||
| a1960d4a4a | |||
| d7c556c672 | |||
| 2c4ca77ffc | |||
| 7bde00c63b | |||
| 46d7019909 | |||
| 41f3b721d6 | |||
| cafac36bed | |||
| 0d84ede3d6 | |||
| d7e3a33179 | |||
| c84f56f1f5 | |||
| 47c9690a32 | |||
| de57c94d3e | |||
| c974b30192 | |||
| 23dd560a72 | |||
| 0eda3efe6a | |||
| a4ac2b3831 | |||
| ea240f7814 | |||
| 0d4775a9df | |||
| 0321bf72a5 | |||
| 739a7b6f75 | |||
| 979590db9f | |||
| 7bd185b7b7 | |||
| 7662eaf983 | |||
| 78eb8747aa | |||
| fc1d6c0676 | |||
| 7e1c296ecf | |||
| 51a314fa31 | |||
| b3efd8a817 | |||
| bf93d72a43 | |||
| 026278504f | |||
| a5872b165f | |||
| 8bd22e8c38 | |||
| e304e67cf1 | |||
| b6a01871d8 | |||
| a569e20110 | |||
| 75146350fc | |||
| 2635d37095 | |||
| a75f4e70a1 | |||
| b6cc070633 | |||
| 94d118fdf8 | |||
| 4dcb679c53 | |||
| ad9e9ba2d6 | |||
| c4a7acb6d1 | |||
| e6835804af | |||
| 9598ce45c9 | |||
| 9ef4825a72 | |||
| eed57ddf97 | |||
| 202c59eb48 | |||
| f86c6d9c5e | |||
| 340ed6c59d | |||
| 0cf5cca415 | |||
| f021ee5491 | |||
| 6c26bc9c8f | |||
| 93eb727ade | |||
| 1c454d9569 | |||
| 3b9f62f0a1 | |||
| cd82aae183 | |||
| d08d50f4b5 | |||
| c5fb9ba6dd | |||
| 2bcb964326 | |||
| b3a0370e71 | |||
| 9344cfb4e3 | |||
| bcf8b1af8e | |||
| 2003efb5ab | |||
| 13743caf19 | |||
| 6a241d44cc | |||
| b36d9fe115 | |||
| c313bd8d07 | |||
| be9066235b | |||
| 1f540666f8 | |||
| 2cf2ef4fac | |||
| c305582c77 | |||
| 69d02b7e72 | |||
| c96ee79b1e | |||
| bd9665e35b | |||
| 0210d6f6bf | |||
| fe294e60b5 | |||
| f95806b47b | |||
| 10f1e69ad8 | |||
| d3249397f3 | |||
| 69e9adf796 | |||
| 4835b7063c | |||
| 8dfa0a7220 | |||
| 2b8bdb9158 | |||
| 7851f272e5 | |||
| e15ee6e320 | |||
| 1f0b86a0d5 | |||
| e47f9d95b0 | |||
| 0b6d71181f | |||
| 318a664b09 | |||
| 180c4c3286 | |||
| 221c1f17c7 | |||
| d601a70546 | |||
| ba49e5f696 | |||
| 19fc02c284 | |||
| b05581499a | |||
| 9d866c1889 | |||
| a567812f35 | |||
| 167b6f5ebf | |||
| 2bed129037 | |||
| a0ea6066ed | |||
| c8c2209617 | |||
| eff818ca42 | |||
| a537981ad0 | |||
| 32cb219e64 | |||
| 4f3360aa49 | |||
| e61f647bf2 | |||
| 7afb29cf02 | |||
| 0a351bf6e1 | |||
| 9a19d59cf7 | |||
| c5a217842f | |||
| 921a292f5b | |||
| 3b45a66498 | |||
| 414db873b7 | |||
| 7deb4d5e78 | |||
| fe77c6fb3f | |||
| aaa9595b59 | |||
| 2d40adcf66 | |||
| 57ccddbb36 | |||
| b6dd604de2 | |||
| 911a515923 | |||
| ea38fd2421 | |||
| e7fc6420f2 | |||
| 766641cd15 | |||
| e4be4d6895 | |||
| 53a1faa36f | |||
| 20249cec67 | |||
| dedbb3f6c8 | |||
| 5a3b10a11c | |||
| f1a25da065 | |||
| f9dbea531c | |||
| b48a712887 | |||
| 28be3b87b7 | |||
| db3feafe48 | |||
| 9a78bac0d0 | |||
| f95e211d9b | |||
| 75809fc3bb | |||
| 811e8809cc | |||
| eaf5cea908 | |||
| 7ac7914f33 | |||
| da425195f9 | |||
| a544c681c7 | |||
| fd45e8d21d | |||
| 1966324112 | |||
| d1be53bef2 | |||
| 16002eb62e | |||
| 2774d8e761 | |||
| e07704e36b | |||
| 9f400c8d14 | |||
| 2c31b348c3 | |||
| cefff6506f | |||
| 8cde649e39 |
+323
-207
File diff suppressed because it is too large
Load Diff
@@ -32,6 +32,7 @@ EQEmuLogSys Log;
|
||||
void ExportSpells(SharedDatabase *db);
|
||||
void ExportSkillCaps(SharedDatabase *db);
|
||||
void ExportBaseData(SharedDatabase *db);
|
||||
void ExportDBStrings(SharedDatabase *db);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
RegisterExecutablePlatform(ExePlatformClientExport);
|
||||
@@ -62,6 +63,7 @@ int main(int argc, char **argv) {
|
||||
ExportSpells(&database);
|
||||
ExportSkillCaps(&database);
|
||||
ExportBaseData(&database);
|
||||
ExportDBStrings(&database);
|
||||
|
||||
Log.CloseFileLogs();
|
||||
|
||||
@@ -194,7 +196,38 @@ void ExportBaseData(SharedDatabase *db) {
|
||||
|
||||
fprintf(f, "%s\n", line.c_str());
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void ExportDBStrings(SharedDatabase *db) {
|
||||
Log.Out(Logs::General, Logs::Status, "Exporting DB Strings...");
|
||||
|
||||
FILE *f = fopen("export/dbstr_us.txt", "w");
|
||||
if(!f) {
|
||||
Log.Out(Logs::General, Logs::Error, "Unable to open export/dbstr_us.txt to write, skipping.");
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(f, "Major^Minor^String(New)\n");
|
||||
const std::string query = "SELECT * FROM db_str ORDER BY id, type";
|
||||
auto results = db->QueryDatabase(query);
|
||||
if(results.Success()) {
|
||||
for(auto row = results.begin(); row != results.end(); ++row) {
|
||||
std::string line;
|
||||
unsigned int fields = results.ColumnCount();
|
||||
for(unsigned int rowIndex = 0; rowIndex < fields; ++rowIndex) {
|
||||
if(rowIndex != 0)
|
||||
line.push_back('^');
|
||||
|
||||
if(row[rowIndex] != nullptr) {
|
||||
line += row[rowIndex];
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(f, "%s\n", line.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
@@ -30,6 +30,7 @@ EQEmuLogSys Log;
|
||||
void ImportSpells(SharedDatabase *db);
|
||||
void ImportSkillCaps(SharedDatabase *db);
|
||||
void ImportBaseData(SharedDatabase *db);
|
||||
void ImportDBStrings(SharedDatabase *db);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
RegisterExecutablePlatform(ExePlatformClientImport);
|
||||
@@ -59,6 +60,7 @@ int main(int argc, char **argv) {
|
||||
ImportSpells(&database);
|
||||
ImportSkillCaps(&database);
|
||||
ImportBaseData(&database);
|
||||
ImportDBStrings(&database);
|
||||
|
||||
Log.CloseFileLogs();
|
||||
|
||||
@@ -202,7 +204,6 @@ void ImportSkillCaps(SharedDatabase *db) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
int class_id, skill_id, level, cap;
|
||||
class_id = atoi(split[0].c_str());
|
||||
skill_id = atoi(split[1].c_str());
|
||||
@@ -262,3 +263,56 @@ void ImportBaseData(SharedDatabase *db) {
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void ImportDBStrings(SharedDatabase *db) {
|
||||
Log.Out(Logs::General, Logs::Status, "Importing DB Strings...");
|
||||
|
||||
FILE *f = fopen("import/dbstr_us.txt", "r");
|
||||
if(!f) {
|
||||
Log.Out(Logs::General, Logs::Error, "Unable to open import/dbstr_us.txt to read, skipping.");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string delete_sql = "DELETE FROM db_str";
|
||||
db->QueryDatabase(delete_sql);
|
||||
|
||||
char buffer[2048];
|
||||
bool first = true;
|
||||
while(fgets(buffer, 2048, f)) {
|
||||
if(first) {
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
for(int i = 0; i < 2048; ++i) {
|
||||
if(buffer[i] == '\n') {
|
||||
buffer[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto split = SplitString(buffer, '^');
|
||||
|
||||
if(split.size() < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string sql;
|
||||
int id, type;
|
||||
std::string value;
|
||||
|
||||
id = atoi(split[0].c_str());
|
||||
type = atoi(split[1].c_str());
|
||||
|
||||
if(split.size() >= 3) {
|
||||
value = ::EscapeString(split[2]);
|
||||
}
|
||||
|
||||
sql = StringFormat("INSERT INTO db_str(id, type, value) VALUES(%u, %u, '%s')",
|
||||
id, type, value.c_str());
|
||||
|
||||
db->QueryDatabase(sql);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ SET(common_sources
|
||||
eqtime.cpp
|
||||
extprofile.cpp
|
||||
faction.cpp
|
||||
file_verify.cpp
|
||||
file_verify_manager.cpp
|
||||
guild_base.cpp
|
||||
guilds.cpp
|
||||
ipc_mutex.cpp
|
||||
@@ -130,6 +132,8 @@ SET(common_headers
|
||||
extprofile.h
|
||||
faction.h
|
||||
features.h
|
||||
file_verify.h
|
||||
file_verify_manager.h
|
||||
fixed_memory_hash_set.h
|
||||
fixed_memory_variable_hash_set.h
|
||||
global_define.h
|
||||
|
||||
@@ -63,6 +63,7 @@ public:
|
||||
void WriteFloat(float value) { *(float *)(pBuffer + _wpos) = value; _wpos += sizeof(float); }
|
||||
void WriteDouble(double value) { *(double *)(pBuffer + _wpos) = value; _wpos += sizeof(double); }
|
||||
void WriteString(const char * str) { uint32 len = static_cast<uint32>(strlen(str)) + 1; memcpy(pBuffer + _wpos, str, len); _wpos += len; }
|
||||
void WriteData(const void *ptr, size_t n) { memcpy(pBuffer + _wpos, ptr, n); _wpos += n; }
|
||||
|
||||
uint8 ReadUInt8() { uint8 value = *(uint8 *)(pBuffer + _rpos); _rpos += sizeof(uint8); return value; }
|
||||
uint8 ReadUInt8(uint32 Offset) const { uint8 value = *(uint8 *)(pBuffer + Offset); return value; }
|
||||
|
||||
+90
-12
@@ -1,3 +1,24 @@
|
||||
/*
|
||||
EQEMu: Everquest Server Emulator
|
||||
|
||||
Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef CLIENTVERSIONS_H
|
||||
#define CLIENTVERSIONS_H
|
||||
|
||||
@@ -34,6 +55,8 @@ enum class ClientVersion
|
||||
MobMerc,
|
||||
MobBot,
|
||||
MobPet,
|
||||
|
||||
MaxClientVersions
|
||||
};
|
||||
|
||||
#define CLIENT_VERSION_COUNT 12
|
||||
@@ -46,32 +69,87 @@ static const char* ClientVersionName(ClientVersion version)
|
||||
switch (version)
|
||||
{
|
||||
case ClientVersion::Unknown:
|
||||
return "ClientVersion::Unknown";
|
||||
return "Unknown";
|
||||
case ClientVersion::Client62:
|
||||
return "ClientVersion::Client62";
|
||||
return "Client62";
|
||||
case ClientVersion::Titanium:
|
||||
return "ClientVersion::Titanium";
|
||||
return "Titanium";
|
||||
case ClientVersion::SoF:
|
||||
return "ClientVersion::SoF";
|
||||
return "SoF";
|
||||
case ClientVersion::SoD:
|
||||
return "ClientVersion::SoD";
|
||||
return "SoD";
|
||||
case ClientVersion::UF:
|
||||
return "ClientVersion::UF";
|
||||
return "UF";
|
||||
case ClientVersion::RoF:
|
||||
return "ClientVersion::RoF";
|
||||
return "RoF";
|
||||
case ClientVersion::RoF2:
|
||||
return "ClientVersion::RoF2";
|
||||
return "RoF2";
|
||||
case ClientVersion::MobNPC:
|
||||
return "ClientVersion::MobNPC";
|
||||
return "MobNPC";
|
||||
case ClientVersion::MobMerc:
|
||||
return "ClientVersion::MobMerc";
|
||||
return "MobMerc";
|
||||
case ClientVersion::MobBot:
|
||||
return "ClientVersion::MobBot";
|
||||
return "MobBot";
|
||||
case ClientVersion::MobPet:
|
||||
return "ClientVersion::MobPet";
|
||||
return "MobPet";
|
||||
default:
|
||||
return "<ERROR> Invalid ClientVersion";
|
||||
};
|
||||
}
|
||||
|
||||
static uint32 ClientBitFromVersion(ClientVersion clientVersion)
|
||||
{
|
||||
switch (clientVersion)
|
||||
{
|
||||
case ClientVersion::Unknown:
|
||||
case ClientVersion::Client62:
|
||||
return 0;
|
||||
case ClientVersion::Titanium:
|
||||
case ClientVersion::SoF:
|
||||
case ClientVersion::SoD:
|
||||
case ClientVersion::UF:
|
||||
case ClientVersion::RoF:
|
||||
case ClientVersion::RoF2:
|
||||
case ClientVersion::MobNPC:
|
||||
case ClientVersion::MobMerc:
|
||||
case ClientVersion::MobBot:
|
||||
case ClientVersion::MobPet:
|
||||
return ((uint32)1 << (static_cast<unsigned int>(clientVersion) - 1));
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static ClientVersion ClientVersionFromBit(uint32 clientVersionBit)
|
||||
{
|
||||
switch (clientVersionBit)
|
||||
{
|
||||
case (uint32)static_cast<unsigned int>(ClientVersion::Unknown):
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::Client62) - 1)):
|
||||
return ClientVersion::Unknown;
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::Titanium) - 1)):
|
||||
return ClientVersion::Titanium;
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::SoF) - 1)):
|
||||
return ClientVersion::SoF;
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::SoD) - 1)):
|
||||
return ClientVersion::SoD;
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::UF) - 1)):
|
||||
return ClientVersion::UF;
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::RoF) - 1)):
|
||||
return ClientVersion::RoF;
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::RoF2) - 1)):
|
||||
return ClientVersion::RoF2;
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::MobNPC) - 1)):
|
||||
return ClientVersion::MobNPC;
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::MobMerc) - 1)):
|
||||
return ClientVersion::MobMerc;
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::MobBot) - 1)):
|
||||
return ClientVersion::MobBot;
|
||||
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::MobPet) - 1)):
|
||||
return ClientVersion::MobPet;
|
||||
default:
|
||||
return ClientVersion::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CLIENTVERSIONS_H */
|
||||
|
||||
@@ -157,18 +157,29 @@ namespace Convert {
|
||||
/*84*/ uint32 Points;
|
||||
/*88*/
|
||||
} PVPStatsEntry_Struct;
|
||||
|
||||
static const size_t BANDOLIERS_SIZE = 4;
|
||||
static const size_t BANDOLIER_ITEM_COUNT = 4;
|
||||
struct BandolierItem_Struct {
|
||||
uint32 item_id;
|
||||
uint32 icon;
|
||||
char item_name[64];
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
struct Bandolier_Struct {
|
||||
char name[32];
|
||||
Convert::BandolierItem_Struct items[EmuConstants::BANDOLIER_SIZE];
|
||||
char Name[32];
|
||||
Convert::BandolierItem_Struct Items[Convert::BANDOLIER_ITEM_COUNT];
|
||||
};
|
||||
|
||||
static const size_t POTION_BELT_ITEM_COUNT = 4;
|
||||
struct PotionBeltItem_Struct {
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
struct PotionBelt_Struct {
|
||||
Convert::BandolierItem_Struct items[EmuConstants::POTION_BELT_SIZE];
|
||||
Convert::PotionBeltItem_Struct Items[Convert::POTION_BELT_ITEM_COUNT];
|
||||
};
|
||||
|
||||
struct SuspendedMinion_Struct
|
||||
{
|
||||
/*000*/ uint16 SpellID;
|
||||
@@ -346,7 +357,7 @@ namespace Convert {
|
||||
/*12800*/ uint32 expAA;
|
||||
/*12804*/ uint32 aapoints; //avaliable, unspent
|
||||
/*12808*/ uint8 unknown12844[36];
|
||||
/*12844*/ Convert::Bandolier_Struct bandoliers[EmuConstants::BANDOLIERS_COUNT];
|
||||
/*12844*/ Convert::Bandolier_Struct bandoliers[Convert::BANDOLIERS_SIZE];
|
||||
/*14124*/ uint8 unknown14160[4506];
|
||||
/*18630*/ Convert::SuspendedMinion_Struct SuspendedMinion; // No longer in use
|
||||
/*19240*/ uint32 timeentitledonaccount;
|
||||
@@ -483,7 +494,7 @@ bool Database::CheckDatabaseConversions() {
|
||||
/* Check for a new version of this script, the arg passed
|
||||
would have to be higher than the copy they have downloaded
|
||||
locally and they will re fetch */
|
||||
system("perl eqemu_update.pl V 2");
|
||||
system("perl eqemu_update.pl V 7");
|
||||
|
||||
/* Run Automatic Database Upgrade Script */
|
||||
system("perl eqemu_update.pl ran_from_world");
|
||||
@@ -1430,15 +1441,15 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
/* Run Bandolier Convert */
|
||||
first_entry = 0; rquery = "";
|
||||
for (i = 0; i < EmuConstants::BANDOLIERS_COUNT; i++){
|
||||
if (strlen(pp->bandoliers[i].name) < 32) {
|
||||
for (int si = 0; si < EmuConstants::BANDOLIER_SIZE; si++){
|
||||
if (pp->bandoliers[i].items[si].item_id > 0){
|
||||
for (i = 0; i < Convert::BANDOLIERS_SIZE; i++){
|
||||
if (strlen(pp->bandoliers[i].Name) < 32) {
|
||||
for (int si = 0; si < Convert::BANDOLIER_ITEM_COUNT; si++){
|
||||
if (pp->bandoliers[i].Items[si].ID > 0){
|
||||
if (first_entry != 1) {
|
||||
rquery = StringFormat("REPLACE INTO `character_bandolier` (id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name) VALUES (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name);
|
||||
rquery = StringFormat("REPLACE INTO `character_bandolier` (id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name) VALUES (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].Items[si].ID, pp->bandoliers[i].Items[si].Icon, pp->bandoliers[i].Name);
|
||||
first_entry = 1;
|
||||
}
|
||||
rquery = rquery + StringFormat(", (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name);
|
||||
rquery = rquery + StringFormat(", (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].Items[si].ID, pp->bandoliers[i].Items[si].Icon, pp->bandoliers[i].Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1446,13 +1457,13 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
/* Run Potion Belt Convert */
|
||||
first_entry = 0; rquery = "";
|
||||
for (i = 0; i < EmuConstants::POTION_BELT_SIZE; i++){
|
||||
if (pp->potionbelt.items[i].item_id > 0){
|
||||
for (i = 0; i < Convert::POTION_BELT_ITEM_COUNT; i++){
|
||||
if (pp->potionbelt.Items[i].ID > 0){
|
||||
if (first_entry != 1){
|
||||
rquery = StringFormat("REPLACE INTO `character_potionbelt` (id, potion_id, item_id, icon) VALUES (%i, %u, %u, %u)", character_id, i, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].icon);
|
||||
rquery = StringFormat("REPLACE INTO `character_potionbelt` (id, potion_id, item_id, icon) VALUES (%i, %u, %u, %u)", character_id, i, pp->potionbelt.Items[i].ID, pp->potionbelt.Items[i].Icon);
|
||||
first_entry = 1;
|
||||
}
|
||||
rquery = rquery + StringFormat(", (%i, %u, %u, %u)", character_id, i, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].icon);
|
||||
rquery = rquery + StringFormat(", (%i, %u, %u, %u)", character_id, i, pp->potionbelt.Items[i].ID, pp->potionbelt.Items[i].Icon);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+7
-6
@@ -292,8 +292,6 @@ N(OP_LockoutTimerInfo),
|
||||
N(OP_Login),
|
||||
N(OP_LoginAccepted),
|
||||
N(OP_LoginComplete),
|
||||
N(OP_LoginUnknown1),
|
||||
N(OP_LoginUnknown2),
|
||||
N(OP_Logout),
|
||||
N(OP_LogoutReply),
|
||||
N(OP_LogServer),
|
||||
@@ -348,6 +346,7 @@ N(OP_OpenTributeMaster),
|
||||
N(OP_PDeletePetition),
|
||||
N(OP_PetBuffWindow),
|
||||
N(OP_PetCommands),
|
||||
N(OP_PetHoTT),
|
||||
N(OP_Petition),
|
||||
N(OP_PetitionBug),
|
||||
N(OP_PetitionCheckIn),
|
||||
@@ -364,6 +363,8 @@ N(OP_PetitionUnCheckout),
|
||||
N(OP_PetitionUpdate),
|
||||
N(OP_PickPocket),
|
||||
N(OP_PlayerProfile),
|
||||
N(OP_PlayerStateAdd),
|
||||
N(OP_PlayerStateRemove),
|
||||
N(OP_PlayEverquestRequest),
|
||||
N(OP_PlayEverquestResponse),
|
||||
N(OP_PlayMP3),
|
||||
@@ -519,15 +520,15 @@ N(OP_VetRewardsAvaliable),
|
||||
N(OP_VoiceMacroIn),
|
||||
N(OP_VoiceMacroOut),
|
||||
N(OP_WeaponEquip1),
|
||||
N(OP_WeaponEquip2),
|
||||
N(OP_WeaponUnequip2),
|
||||
N(OP_WearChange),
|
||||
N(OP_Weather),
|
||||
N(OP_Weblink),
|
||||
N(OP_WhoAllRequest),
|
||||
N(OP_WhoAllResponse),
|
||||
N(OP_World_Client_CRC1),
|
||||
N(OP_World_Client_CRC2),
|
||||
N(OP_World_SpellFileCheck),
|
||||
N(OP_World_SkillFileCheck),
|
||||
N(OP_World_BaseDataFileCheck),
|
||||
N(OP_World_ExeFileCheck),
|
||||
N(OP_WorldClientReady),
|
||||
N(OP_WorldComplete),
|
||||
N(OP_WorldLogout),
|
||||
|
||||
+48
-1
@@ -21,6 +21,53 @@
|
||||
#include "skills.h"
|
||||
#include "types.h"
|
||||
|
||||
/*
|
||||
** Light Types
|
||||
**
|
||||
*/
|
||||
enum LightTypes
|
||||
{
|
||||
lightTypeNone = 0,
|
||||
lightTypeCandle,
|
||||
lightTypeTorch,
|
||||
lightTypeTinyGlowingSkull,
|
||||
lightTypeSmallLantern,
|
||||
lightTypeSteinOfMoggok,
|
||||
lightTypeLargeLantern,
|
||||
lightTypeFlamelessLantern,
|
||||
lightTypeGlobeOfStars,
|
||||
lightTypeLightGlobe,
|
||||
lightTypeLightstone,
|
||||
lightTypeGreaterLightstone,
|
||||
lightTypeFireBeetleEye,
|
||||
lightTypeColdlight,
|
||||
lightTypeUnknown1,
|
||||
lightTypeUnknown2
|
||||
};
|
||||
|
||||
#define LIGHT_TYPES_COUNT 16
|
||||
|
||||
/*
|
||||
** Light Levels
|
||||
**
|
||||
*/
|
||||
enum LightLevels
|
||||
{
|
||||
lightLevelUnlit = 0,
|
||||
lightLevelCandle,
|
||||
lightLevelTorch,
|
||||
lightLevelSmallMagic,
|
||||
lightLevelRedLight,
|
||||
lightLevelBlueLight,
|
||||
lightLevelSmallLantern,
|
||||
lightLevelMagicLantern,
|
||||
lightLevelLargeLantern,
|
||||
lightLevelLargeMagic,
|
||||
lightLevelBrilliant
|
||||
};
|
||||
|
||||
#define LIGHT_LEVELS_COUNT 11
|
||||
|
||||
/*
|
||||
** Item attributes
|
||||
**
|
||||
@@ -55,7 +102,7 @@ enum ItemClassTypes
|
||||
**
|
||||
** (ref: database and eqstr_us.txt)
|
||||
**
|
||||
** (Looking at a recent database, it's possible that some of the item values may be off [10-27-2013] -U)
|
||||
** (Looking at a recent database, it's possible that some of the item values may be off [10-27-2013])
|
||||
*/
|
||||
enum ItemUseTypes : uint8
|
||||
{
|
||||
|
||||
+102
-115
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
EQEMu: Everquest Server Emulator
|
||||
|
||||
Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net)
|
||||
Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -25,8 +25,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// class EmuConstants
|
||||
//
|
||||
uint16 EmuConstants::InventoryMapSize(int16 indexMap) {
|
||||
switch (indexMap) {
|
||||
uint16 EmuConstants::InventoryMapSize(int16 indexMap)
|
||||
{
|
||||
switch (indexMap)
|
||||
{
|
||||
case MapPossessions:
|
||||
return MAP_POSSESSIONS_SIZE;
|
||||
case MapBank:
|
||||
@@ -83,7 +85,8 @@ uint16 EmuConstants::InventoryMapSize(int16 indexMap) {
|
||||
}
|
||||
|
||||
/*
|
||||
std::string EmuConstants::InventoryLocationName(Location_Struct location) {
|
||||
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));
|
||||
@@ -91,8 +94,10 @@ std::string EmuConstants::InventoryLocationName(Location_Struct location) {
|
||||
}
|
||||
*/
|
||||
|
||||
std::string EmuConstants::InventoryMapName(int16 indexMap) {
|
||||
switch (indexMap) {
|
||||
std::string EmuConstants::InventoryMapName(int16 indexMap)
|
||||
{
|
||||
switch (indexMap)
|
||||
{
|
||||
case INVALID_INDEX:
|
||||
return "Invalid Map";
|
||||
case MapPossessions:
|
||||
@@ -100,7 +105,7 @@ std::string EmuConstants::InventoryMapName(int16 indexMap) {
|
||||
case MapBank:
|
||||
return "Bank";
|
||||
case MapSharedBank:
|
||||
return "Shared Bank";
|
||||
return "SharedBank";
|
||||
case MapTrade:
|
||||
return "Trade";
|
||||
case MapWorld:
|
||||
@@ -110,9 +115,9 @@ std::string EmuConstants::InventoryMapName(int16 indexMap) {
|
||||
case MapTribute:
|
||||
return "Tribute";
|
||||
case MapTrophyTribute:
|
||||
return "Trophy Tribute";
|
||||
return "TrophyTribute";
|
||||
case MapGuildTribute:
|
||||
return "Guild Tribute";
|
||||
return "GuildTribute";
|
||||
case MapMerchant:
|
||||
return "Merchant";
|
||||
case MapDeleted:
|
||||
@@ -124,23 +129,23 @@ std::string EmuConstants::InventoryMapName(int16 indexMap) {
|
||||
case MapInspect:
|
||||
return "Inspect";
|
||||
case MapRealEstate:
|
||||
return "Real Estate";
|
||||
return "RealEstate";
|
||||
case MapViewMODPC:
|
||||
return "View MOD PC";
|
||||
return "ViewMODPC";
|
||||
case MapViewMODBank:
|
||||
return "View MOD Bank";
|
||||
return "ViewMODBank";
|
||||
case MapViewMODSharedBank:
|
||||
return "View MOD Shared Bank";
|
||||
return "ViewMODSharedBank";
|
||||
case MapViewMODLimbo:
|
||||
return "View MOD Limbo";
|
||||
return "ViewMODLimbo";
|
||||
case MapAltStorage:
|
||||
return "Alt Storage";
|
||||
return "AltStorage";
|
||||
case MapArchived:
|
||||
return "Archived";
|
||||
case MapMail:
|
||||
return "Mail";
|
||||
case MapGuildTrophyTribute:
|
||||
return "Guild Trophy Tribute";
|
||||
return "GuildTrophyTribute";
|
||||
case MapKrono:
|
||||
return "Krono";
|
||||
case MapOther:
|
||||
@@ -150,20 +155,22 @@ std::string EmuConstants::InventoryMapName(int16 indexMap) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string EmuConstants::InventoryMainName(int16 indexMain) {
|
||||
switch (indexMain) {
|
||||
std::string EmuConstants::InventoryMainName(int16 indexMain)
|
||||
{
|
||||
switch (indexMain)
|
||||
{
|
||||
case INVALID_INDEX:
|
||||
return "Invalid Main";
|
||||
case MainCharm:
|
||||
return "Charm";
|
||||
case MainEar1:
|
||||
return "Ear 1";
|
||||
return "Ear1";
|
||||
case MainHead:
|
||||
return "Head";
|
||||
case MainFace:
|
||||
return "Face";
|
||||
case MainEar2:
|
||||
return "Ear 2";
|
||||
return "Ear2";
|
||||
case MainNeck:
|
||||
return "Neck";
|
||||
case MainShoulders:
|
||||
@@ -173,9 +180,9 @@ std::string EmuConstants::InventoryMainName(int16 indexMain) {
|
||||
case MainBack:
|
||||
return "Back";
|
||||
case MainWrist1:
|
||||
return "Wrist 1";
|
||||
return "Wrist1";
|
||||
case MainWrist2:
|
||||
return "Wrist 2";
|
||||
return "Wrist2";
|
||||
case MainRange:
|
||||
return "Range";
|
||||
case MainHands:
|
||||
@@ -185,9 +192,9 @@ std::string EmuConstants::InventoryMainName(int16 indexMain) {
|
||||
case MainSecondary:
|
||||
return "Secondary";
|
||||
case MainFinger1:
|
||||
return "Finger 1";
|
||||
return "Finger1";
|
||||
case MainFinger2:
|
||||
return "Finger 2";
|
||||
return "Finger2";
|
||||
case MainChest:
|
||||
return "Chest";
|
||||
case MainLegs:
|
||||
@@ -197,30 +204,30 @@ std::string EmuConstants::InventoryMainName(int16 indexMain) {
|
||||
case MainWaist:
|
||||
return "Waist";
|
||||
case MainPowerSource:
|
||||
return "Power Source";
|
||||
return "PowerSource";
|
||||
case MainAmmo:
|
||||
return "Ammo";
|
||||
case MainGeneral1:
|
||||
return "General 1";
|
||||
return "General1";
|
||||
case MainGeneral2:
|
||||
return "General 2";
|
||||
return "General2";
|
||||
case MainGeneral3:
|
||||
return "General 3";
|
||||
return "General3";
|
||||
case MainGeneral4:
|
||||
return "General 4";
|
||||
return "General4";
|
||||
case MainGeneral5:
|
||||
return "General 5";
|
||||
return "General5";
|
||||
case MainGeneral6:
|
||||
return "General 6";
|
||||
return "General6";
|
||||
case MainGeneral7:
|
||||
return "General 7";
|
||||
return "General7";
|
||||
case MainGeneral8:
|
||||
return "General 8";
|
||||
return "General8";
|
||||
/*
|
||||
case MainGeneral9:
|
||||
return "General 9";
|
||||
return "General9";
|
||||
case MainGeneral10:
|
||||
return "General 10";
|
||||
return "General10";
|
||||
*/
|
||||
case MainCursor:
|
||||
return "Cursor";
|
||||
@@ -229,7 +236,8 @@ std::string EmuConstants::InventoryMainName(int16 indexMain) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string EmuConstants::InventorySubName(int16 indexSub) {
|
||||
std::string EmuConstants::InventorySubName(int16 indexSub)
|
||||
{
|
||||
if (indexSub == INVALID_INDEX)
|
||||
return "Invalid Sub";
|
||||
|
||||
@@ -237,12 +245,13 @@ std::string EmuConstants::InventorySubName(int16 indexSub) {
|
||||
return "Unknown Sub";
|
||||
|
||||
std::string ret_str;
|
||||
ret_str = StringFormat("Container %i", (indexSub + 1)); // zero-based index..but, count starts at one
|
||||
ret_str = StringFormat("Container%i", (indexSub + 1)); // zero-based index..but, count starts at one
|
||||
|
||||
return ret_str;
|
||||
}
|
||||
|
||||
std::string EmuConstants::InventoryAugName(int16 indexAug) {
|
||||
std::string EmuConstants::InventoryAugName(int16 indexAug)
|
||||
{
|
||||
if (indexAug == INVALID_INDEX)
|
||||
return "Invalid Aug";
|
||||
|
||||
@@ -250,7 +259,7 @@ std::string EmuConstants::InventoryAugName(int16 indexAug) {
|
||||
return "Unknown Aug";
|
||||
|
||||
std::string ret_str;
|
||||
ret_str = StringFormat("Augment %i", (indexAug + 1)); // zero-based index..but, count starts at one
|
||||
ret_str = StringFormat("Augment%i", (indexAug + 1)); // zero-based index..but, count starts at one
|
||||
|
||||
return ret_str;
|
||||
}
|
||||
@@ -260,14 +269,16 @@ std::string EmuConstants::InventoryAugName(int16 indexAug) {
|
||||
// class EQLimits
|
||||
//
|
||||
// client validation
|
||||
bool EQLimits::IsValidPCClientVersion(ClientVersion clientVersion) {
|
||||
bool EQLimits::IsValidPCClientVersion(ClientVersion clientVersion)
|
||||
{
|
||||
if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_PC_CLIENT)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ClientVersion EQLimits::ValidatePCClientVersion(ClientVersion clientVersion) {
|
||||
ClientVersion EQLimits::ValidatePCClientVersion(ClientVersion clientVersion)
|
||||
{
|
||||
if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_PC_CLIENT)
|
||||
return clientVersion;
|
||||
|
||||
@@ -275,14 +286,16 @@ ClientVersion EQLimits::ValidatePCClientVersion(ClientVersion clientVersion) {
|
||||
}
|
||||
|
||||
// npc validation
|
||||
bool EQLimits::IsValidNPCClientVersion(ClientVersion clientVersion) {
|
||||
bool EQLimits::IsValidNPCClientVersion(ClientVersion clientVersion)
|
||||
{
|
||||
if (clientVersion > LAST_PC_CLIENT && clientVersion <= LAST_NPC_CLIENT)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ClientVersion EQLimits::ValidateNPCClientVersion(ClientVersion clientVersion) {
|
||||
ClientVersion EQLimits::ValidateNPCClientVersion(ClientVersion clientVersion)
|
||||
{
|
||||
if (clientVersion > LAST_PC_CLIENT && clientVersion <= LAST_NPC_CLIENT)
|
||||
return clientVersion;
|
||||
|
||||
@@ -290,22 +303,47 @@ ClientVersion EQLimits::ValidateNPCClientVersion(ClientVersion clientVersion) {
|
||||
}
|
||||
|
||||
// mob validation
|
||||
bool EQLimits::IsValidMobClientVersion(ClientVersion clientVersion) {
|
||||
bool EQLimits::IsValidMobClientVersion(ClientVersion clientVersion)
|
||||
{
|
||||
if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_NPC_CLIENT)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ClientVersion EQLimits::ValidateMobClientVersion(ClientVersion clientVersion) {
|
||||
ClientVersion EQLimits::ValidateMobClientVersion(ClientVersion clientVersion)
|
||||
{
|
||||
if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_NPC_CLIENT)
|
||||
return clientVersion;
|
||||
|
||||
return ClientVersion::Unknown;
|
||||
}
|
||||
|
||||
// database
|
||||
size_t EQLimits::CharacterCreationLimit(ClientVersion clientVersion)
|
||||
{
|
||||
static const size_t local[CLIENT_VERSION_COUNT] = {
|
||||
/*Unknown*/ NOT_USED,
|
||||
/*Client62*/ NOT_USED,
|
||||
/*Titanium*/ Titanium::consts::CHARACTER_CREATION_LIMIT,
|
||||
/*SoF*/ SoF::consts::CHARACTER_CREATION_LIMIT,
|
||||
/*SoD*/ SoD::consts::CHARACTER_CREATION_LIMIT,
|
||||
/*UF*/ UF::consts::CHARACTER_CREATION_LIMIT,
|
||||
/*RoF*/ RoF::consts::CHARACTER_CREATION_LIMIT,
|
||||
/*RoF2*/ RoF2::consts::CHARACTER_CREATION_LIMIT,
|
||||
|
||||
/*MobNPC*/ NOT_USED,
|
||||
/*MobMerc*/ NOT_USED,
|
||||
/*MobBot*/ NOT_USED,
|
||||
/*MobPet*/ NOT_USED
|
||||
};
|
||||
|
||||
return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
// inventory
|
||||
uint16 EQLimits::InventoryMapSize(int16 indexMap, ClientVersion clientVersion) {
|
||||
uint16 EQLimits::InventoryMapSize(int16 indexMap, ClientVersion clientVersion)
|
||||
{
|
||||
// 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
|
||||
@@ -704,7 +742,8 @@ uint16 EQLimits::InventoryMapSize(int16 indexMap, ClientVersion clientVersion) {
|
||||
return NOT_USED;
|
||||
}
|
||||
|
||||
uint64 EQLimits::PossessionsBitmask(ClientVersion clientVersion) {
|
||||
uint64 EQLimits::PossessionsBitmask(ClientVersion clientVersion)
|
||||
{
|
||||
// these are for the new inventory system (RoF)..not the current (Ti) one...
|
||||
// 0x0000000000200000 is SlotPowerSource (SoF+)
|
||||
// 0x0000000080000000 is SlotGeneral9 (RoF+)
|
||||
@@ -730,7 +769,8 @@ uint64 EQLimits::PossessionsBitmask(ClientVersion clientVersion) {
|
||||
//return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
uint64 EQLimits::EquipmentBitmask(ClientVersion clientVersion) {
|
||||
uint64 EQLimits::EquipmentBitmask(ClientVersion clientVersion)
|
||||
{
|
||||
static const uint64 local[CLIENT_VERSION_COUNT] = {
|
||||
/*Unknown*/ NOT_USED,
|
||||
/*62*/ 0x00000000005FFFFF,
|
||||
@@ -751,7 +791,8 @@ uint64 EQLimits::EquipmentBitmask(ClientVersion clientVersion) {
|
||||
//return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
uint64 EQLimits::GeneralBitmask(ClientVersion clientVersion) {
|
||||
uint64 EQLimits::GeneralBitmask(ClientVersion clientVersion)
|
||||
{
|
||||
static const uint64 local[CLIENT_VERSION_COUNT] = {
|
||||
/*Unknown*/ NOT_USED,
|
||||
/*62*/ 0x000000007F800000,
|
||||
@@ -772,7 +813,8 @@ uint64 EQLimits::GeneralBitmask(ClientVersion clientVersion) {
|
||||
//return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
uint64 EQLimits::CursorBitmask(ClientVersion clientVersion) {
|
||||
uint64 EQLimits::CursorBitmask(ClientVersion clientVersion)
|
||||
{
|
||||
static const uint64 local[CLIENT_VERSION_COUNT] = {
|
||||
/*Unknown*/ NOT_USED,
|
||||
/*62*/ 0x0000000200000000,
|
||||
@@ -793,7 +835,8 @@ uint64 EQLimits::CursorBitmask(ClientVersion clientVersion) {
|
||||
//return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
bool EQLimits::AllowsEmptyBagInBag(ClientVersion clientVersion) {
|
||||
bool EQLimits::AllowsEmptyBagInBag(ClientVersion clientVersion)
|
||||
{
|
||||
static const bool local[CLIENT_VERSION_COUNT] = {
|
||||
/*Unknown*/ false,
|
||||
/*62*/ false,
|
||||
@@ -814,7 +857,8 @@ bool EQLimits::AllowsEmptyBagInBag(ClientVersion clientVersion) {
|
||||
//return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
bool EQLimits::AllowsClickCastFromBag(ClientVersion clientVersion) {
|
||||
bool EQLimits::AllowsClickCastFromBag(ClientVersion clientVersion)
|
||||
{
|
||||
static const bool local[CLIENT_VERSION_COUNT] = {
|
||||
/*Unknown*/ false,
|
||||
/*62*/ false,
|
||||
@@ -835,7 +879,8 @@ bool EQLimits::AllowsClickCastFromBag(ClientVersion clientVersion) {
|
||||
}
|
||||
|
||||
// items
|
||||
uint16 EQLimits::ItemCommonSize(ClientVersion clientVersion) {
|
||||
uint16 EQLimits::ItemCommonSize(ClientVersion clientVersion)
|
||||
{
|
||||
static const uint16 local[CLIENT_VERSION_COUNT] = {
|
||||
/*Unknown*/ NOT_USED,
|
||||
/*62*/ EmuConstants::ITEM_COMMON_SIZE,
|
||||
@@ -855,7 +900,8 @@ uint16 EQLimits::ItemCommonSize(ClientVersion clientVersion) {
|
||||
return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
uint16 EQLimits::ItemContainerSize(ClientVersion clientVersion) {
|
||||
uint16 EQLimits::ItemContainerSize(ClientVersion clientVersion)
|
||||
{
|
||||
static const uint16 local[CLIENT_VERSION_COUNT] = {
|
||||
/*Unknown*/ NOT_USED,
|
||||
/*62*/ EmuConstants::ITEM_CONTAINER_SIZE,
|
||||
@@ -875,7 +921,8 @@ uint16 EQLimits::ItemContainerSize(ClientVersion clientVersion) {
|
||||
return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
bool EQLimits::CoinHasWeight(ClientVersion clientVersion) {
|
||||
bool EQLimits::CoinHasWeight(ClientVersion clientVersion)
|
||||
{
|
||||
static const bool local[CLIENT_VERSION_COUNT] = {
|
||||
/*Unknown*/ true,
|
||||
/*62*/ true,
|
||||
@@ -894,63 +941,3 @@ bool EQLimits::CoinHasWeight(ClientVersion clientVersion) {
|
||||
|
||||
return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
uint32 EQLimits::BandoliersCount(ClientVersion clientVersion) {
|
||||
static const uint32 local[CLIENT_VERSION_COUNT] = {
|
||||
/*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*/ EmuConstants::BANDOLIERS_COUNT,
|
||||
|
||||
/*NPC*/ NOT_USED,
|
||||
/*Merc*/ NOT_USED,
|
||||
/*Bot*/ NOT_USED,
|
||||
/*Pet*/ NOT_USED
|
||||
};
|
||||
|
||||
return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
uint32 EQLimits::BandolierSize(ClientVersion clientVersion) {
|
||||
static const uint32 local[CLIENT_VERSION_COUNT] = {
|
||||
/*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*/ EmuConstants::BANDOLIER_SIZE,
|
||||
|
||||
/*NPC*/ NOT_USED,
|
||||
/*Merc*/ NOT_USED,
|
||||
/*Bot*/ NOT_USED,
|
||||
/*Pet*/ NOT_USED
|
||||
};
|
||||
|
||||
return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
uint32 EQLimits::PotionBeltSize(ClientVersion clientVersion) {
|
||||
static const uint32 local[CLIENT_VERSION_COUNT] = {
|
||||
/*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*/ EmuConstants::POTION_BELT_SIZE,
|
||||
|
||||
/*NPC*/ NOT_USED,
|
||||
/*Merc*/ NOT_USED,
|
||||
/*Bot*/ NOT_USED,
|
||||
/*Pet*/ NOT_USED
|
||||
};
|
||||
|
||||
return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
|
||||
}
|
||||
|
||||
+16
-20
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
EQEMu: Everquest Server Emulator
|
||||
|
||||
Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net)
|
||||
Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -42,12 +42,15 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//using namespace RoF2::maps; // server inventory maps enumeration (code and database sync'd to reference)
|
||||
//using namespace RoF::slots; // server possessions slots enumeration (code and database sync'd to reference)
|
||||
|
||||
class EmuConstants {
|
||||
class EmuConstants
|
||||
{
|
||||
// an immutable value is required to initialize arrays, etc... use this class as a repository for those
|
||||
public:
|
||||
// database
|
||||
static const ClientVersion CHARACTER_CREATION_CLIENT = ClientVersion::RoF2; // adjust according to starting item placement and target client
|
||||
|
||||
static const size_t CHARACTER_CREATION_LIMIT = RoF2::consts::CHARACTER_CREATION_LIMIT;
|
||||
|
||||
// inventory
|
||||
static uint16 InventoryMapSize(int16 indexMap);
|
||||
//static std::string InventoryLocationName(Location_Struct location);
|
||||
@@ -140,23 +143,18 @@ public:
|
||||
static const uint16 ITEM_COMMON_SIZE = RoF::consts::ITEM_COMMON_SIZE;
|
||||
static const uint16 ITEM_CONTAINER_SIZE = Titanium::consts::ITEM_CONTAINER_SIZE;
|
||||
|
||||
// player profile
|
||||
//static const uint32 CLASS_BITMASK = 0; // needs value
|
||||
//static const uint32 RACE_BITMASK = 0; // needs value
|
||||
// BANDOLIERS_SIZE sets maximum limit..active limit will need to be handled by the appropriate AA or spell (or item?)
|
||||
static const size_t BANDOLIERS_SIZE = RoF2::consts::BANDOLIERS_SIZE; // number of bandolier instances
|
||||
static const size_t BANDOLIER_ITEM_COUNT = RoF2::consts::BANDOLIER_ITEM_COUNT; // number of equipment slots in bandolier instance
|
||||
|
||||
// BANDOLIERS_COUNT sets maximum limit..active limit will need to be handled by the appropriate AA
|
||||
static const uint32 BANDOLIERS_COUNT = Titanium::consts::BANDOLIERS_COUNT; // count = number of bandolier instances
|
||||
static const uint32 BANDOLIER_SIZE = Titanium::consts::BANDOLIER_SIZE; // size = number of equipment slots in bandolier instance
|
||||
static const uint32 POTION_BELT_SIZE = Titanium::consts::POTION_BELT_SIZE;
|
||||
// POTION_BELT_SIZE sets maximum limit..active limit will need to be handled by the appropriate AA or spell (or item?)
|
||||
static const size_t POTION_BELT_ITEM_COUNT = RoF2::consts::POTION_BELT_ITEM_COUNT;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 56;
|
||||
|
||||
// legacy-related functions
|
||||
//static int ServerToPerlSlot(int slot); // encode
|
||||
//static int PerlToServerSlot(int slot); // decode
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = RoF2::consts::TEXT_LINK_BODY_LENGTH;
|
||||
};
|
||||
|
||||
class EQLimits {
|
||||
class EQLimits
|
||||
{
|
||||
// values should default to a non-beneficial value..unless value conflicts with intended operation
|
||||
//
|
||||
// EmuConstants may be used as references..but, not every reference needs to be in EmuConstants (i.e., AllowsEmptyBagInBag(), CoinHasWeight(), etc...)
|
||||
@@ -174,6 +172,9 @@ public:
|
||||
static bool IsValidMobClientVersion(ClientVersion clientVersion);
|
||||
static ClientVersion ValidateMobClientVersion(ClientVersion clientVersion);
|
||||
|
||||
// database
|
||||
static size_t CharacterCreationLimit(ClientVersion clientVersion);
|
||||
|
||||
// inventory
|
||||
static uint16 InventoryMapSize(int16 indexMap, ClientVersion clientVersion);
|
||||
static uint64 PossessionsBitmask(ClientVersion clientVersion);
|
||||
@@ -190,11 +191,6 @@ public:
|
||||
|
||||
// player profile
|
||||
static bool CoinHasWeight(ClientVersion clientVersion);
|
||||
|
||||
static uint32 BandoliersCount(ClientVersion clientVersion);
|
||||
static uint32 BandolierSize(ClientVersion clientVersion);
|
||||
|
||||
static uint32 PotionBeltSize(ClientVersion clientVersion);
|
||||
};
|
||||
|
||||
#endif /* EQ_DICTIONARY_H */
|
||||
|
||||
+184
-173
@@ -15,6 +15,7 @@
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef EQ_PACKET_STRUCTS_H
|
||||
#define EQ_PACKET_STRUCTS_H
|
||||
|
||||
@@ -123,83 +124,81 @@ struct LDoNTrapTemplate
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/*
|
||||
** Color_Struct
|
||||
** Size: 4 bytes
|
||||
** Used for convenience
|
||||
** Merth: Gave struct a name so gcc 2.96 would compile
|
||||
**
|
||||
*/
|
||||
// All clients translate the character select information to some degree
|
||||
|
||||
struct Color_Struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8 blue;
|
||||
uint8 green;
|
||||
uint8 red;
|
||||
uint8 use_tint; // if there's a tint this is FF
|
||||
} rgb;
|
||||
uint32 color;
|
||||
union {
|
||||
struct {
|
||||
uint8 Blue;
|
||||
uint8 Green;
|
||||
uint8 Red;
|
||||
uint8 UseTint; // if there's a tint this is FF
|
||||
} RGB;
|
||||
uint32 Color;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Visible equiptment.
|
||||
* Size: 20 Octets
|
||||
*/
|
||||
struct EquipStruct {
|
||||
/*00*/ uint32 material;
|
||||
/*04*/ uint32 unknown1;
|
||||
/*08*/ uint32 elitematerial;
|
||||
/*12*/ uint32 heroforgemodel;
|
||||
/*16*/ uint32 material2; // Same as material?
|
||||
/*20*/
|
||||
struct EquipStruct
|
||||
{
|
||||
uint32 Material;
|
||||
uint32 Unknown1;
|
||||
uint32 EliteMaterial;
|
||||
uint32 HeroForgeModel;
|
||||
uint32 Material2; // Same as material?
|
||||
};
|
||||
|
||||
struct CharSelectEquip {
|
||||
uint32 material;
|
||||
uint32 unknown1;
|
||||
uint32 elitematerial;
|
||||
uint32 heroforgemodel;
|
||||
uint32 material2;
|
||||
Color_Struct color;
|
||||
struct CharSelectEquip
|
||||
{
|
||||
uint32 Material;
|
||||
uint32 Unknown1;
|
||||
uint32 EliteMaterial;
|
||||
uint32 HeroForgeModel;
|
||||
uint32 Material2;
|
||||
Color_Struct Color;
|
||||
};
|
||||
|
||||
/*
|
||||
** Character Selection Struct
|
||||
** Length: 1704 Bytes
|
||||
**
|
||||
*/
|
||||
struct CharacterSelect_Struct {
|
||||
/*0000*/ uint32 race[10]; // Characters Race
|
||||
/*0040*/ //Color_Struct cs_colors[10][9]; // Characters Equipment Colors
|
||||
/*0400*/ uint8 beardcolor[10]; // Characters beard Color
|
||||
/*0410*/ uint8 hairstyle[10]; // Characters hair style
|
||||
/*0420*/ //uint32 equip[10][9]; // 0=helm, 1=chest, 2=arm, 3=bracer, 4=hand, 5=leg, 6=boot, 7=melee1, 8=melee2 (Might not be)
|
||||
/*0000*/ CharSelectEquip equip[10][9];
|
||||
/*0780*/ uint32 secondary[10]; // Characters secondary IDFile number
|
||||
/*0820*/ uint32 drakkin_heritage[10]; // added for SoF
|
||||
/*0860*/ uint32 drakkin_tattoo[10]; // added for SoF
|
||||
/*0900*/ uint32 drakkin_details[10]; // added for SoF
|
||||
/*0940*/ uint32 deity[10]; // Characters Deity
|
||||
/*0980*/ uint8 gohome[10]; // 1=Go Home available, 0=not
|
||||
/*0990*/ uint8 tutorial[10]; // 1=Tutorial available, 0=not
|
||||
/*1000*/ uint8 beard[10]; // Characters Beard Type
|
||||
/*1010*/ uint8 unknown902[10]; // 10x ff
|
||||
/*1020*/ uint32 primary[10]; // Characters primary IDFile number
|
||||
/*1060*/ uint8 haircolor[10]; // Characters Hair Color
|
||||
/*1070*/ uint8 unknown0962[2]; // 2x 00
|
||||
/*1072*/ uint32 zone[10]; // Characters Current Zone
|
||||
/*1112*/ uint8 class_[10]; // Characters Classes
|
||||
/*1022*/ uint8 face[10]; // Characters Face Type
|
||||
/*1032*/ char name[10][64]; // Characters Names
|
||||
/*1672*/ uint8 gender[10]; // Characters Gender
|
||||
/*1682*/ uint8 eyecolor1[10]; // Characters Eye Color
|
||||
/*1692*/ uint8 eyecolor2[10]; // Characters Eye 2 Color
|
||||
/*1702*/ uint8 level[10]; // Characters Levels
|
||||
/*1712*/
|
||||
// RoF2-based hybrid struct
|
||||
struct CharacterSelectEntry_Struct
|
||||
{
|
||||
char Name[64];
|
||||
uint8 Class;
|
||||
uint32 Race;
|
||||
uint8 Level;
|
||||
uint8 ShroudClass;
|
||||
uint32 ShroudRace;
|
||||
uint16 Zone;
|
||||
uint16 Instance;
|
||||
uint8 Gender;
|
||||
uint8 Face;
|
||||
CharSelectEquip Equip[9];
|
||||
uint8 Unknown15; // Seen FF
|
||||
uint8 Unknown19; // Seen FF
|
||||
uint32 DrakkinTattoo;
|
||||
uint32 DrakkinDetails;
|
||||
uint32 Deity;
|
||||
uint32 PrimaryIDFile;
|
||||
uint32 SecondaryIDFile;
|
||||
uint8 HairColor;
|
||||
uint8 BeardColor;
|
||||
uint8 EyeColor1;
|
||||
uint8 EyeColor2;
|
||||
uint8 HairStyle;
|
||||
uint8 Beard;
|
||||
uint8 GoHome; // Seen 0 for new char and 1 for existing
|
||||
uint8 Tutorial; // Seen 1 for new char or 0 for existing
|
||||
uint32 DrakkinHeritage;
|
||||
uint8 Unknown1; // Seen 0
|
||||
uint8 Enabled; // Originally labeled as 'CharEnabled' - unknown purpose and setting
|
||||
uint32 LastLogin;
|
||||
uint8 Unknown2; // Seen 0
|
||||
};
|
||||
|
||||
struct CharacterSelect_Struct
|
||||
{
|
||||
uint32 CharCount; //number of chars in this packet
|
||||
uint32 TotalChars; //total number of chars allowed?
|
||||
CharacterSelectEntry_Struct Entries[0];
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -274,7 +273,8 @@ struct Spawn_Struct {
|
||||
/*0146*/ uint8 beard; // Beard style (not totally, sure but maybe!)
|
||||
/*0147*/ uint8 unknown0147[4];
|
||||
/*0151*/ uint8 level; // Spawn Level
|
||||
/*0152*/ uint8 unknown0259[4]; // ***Placeholder
|
||||
// None = 0, Open = 1, WeaponSheathed = 2, Aggressive = 4, ForcedAggressive = 8, InstrumentEquipped = 16, Stunned = 32, PrimaryWeaponEquipped = 64, SecondaryWeaponEquipped = 128
|
||||
/*0152*/ uint32 PlayerState; // Controls animation stuff
|
||||
/*0156*/ uint8 beardcolor; // Beard color
|
||||
/*0157*/ char suffix[32]; // Player's suffix (of Veeshan, etc.)
|
||||
/*0189*/ uint32 petOwnerId; // If this is a pet, the spawn id of owner
|
||||
@@ -367,6 +367,11 @@ union
|
||||
|
||||
};
|
||||
|
||||
struct PlayerState_Struct {
|
||||
/*00*/ uint32 spawn_id;
|
||||
/*04*/ uint32 state;
|
||||
};
|
||||
|
||||
/*
|
||||
** New Spawn
|
||||
** Length: 176 Bytes
|
||||
@@ -548,7 +553,7 @@ struct SpellBuff_Struct
|
||||
/*002*/ uint8 bard_modifier;
|
||||
/*003*/ uint8 effect; //not real
|
||||
/*004*/ uint32 spellid;
|
||||
/*008*/ uint32 duration;
|
||||
/*008*/ int32 duration;
|
||||
/*012*/ uint32 counters;
|
||||
/*016*/ uint32 player_id; //'global' ID of the caster, for wearoff messages
|
||||
/*020*/
|
||||
@@ -561,7 +566,7 @@ struct SpellBuffFade_Struct {
|
||||
/*006*/ uint8 effect;
|
||||
/*007*/ uint8 unknown7;
|
||||
/*008*/ uint32 spellid;
|
||||
/*012*/ uint32 duration;
|
||||
/*012*/ int32 duration;
|
||||
/*016*/ uint32 num_hits;
|
||||
/*020*/ uint32 unknown020; //prolly global player ID
|
||||
/*024*/ uint32 slotid;
|
||||
@@ -579,14 +584,8 @@ struct BuffRemoveRequest_Struct
|
||||
|
||||
struct PetBuff_Struct {
|
||||
/*000*/ uint32 petid;
|
||||
/*004*/ uint32 spellid[BUFF_COUNT];
|
||||
/*104*/ uint32 unknown700;
|
||||
/*108*/ uint32 unknown701;
|
||||
/*112*/ uint32 unknown702;
|
||||
/*116*/ uint32 unknown703;
|
||||
/*120*/ uint32 unknown704;
|
||||
/*124*/ uint32 ticsremaining[BUFF_COUNT];
|
||||
/*224*/ uchar unknown705[20];
|
||||
/*004*/ uint32 spellid[BUFF_COUNT+5];
|
||||
/*124*/ int32 ticsremaining[BUFF_COUNT+5];
|
||||
/*244*/ uint32 buffcount;
|
||||
};
|
||||
|
||||
@@ -727,6 +726,7 @@ struct AA_Array
|
||||
{
|
||||
uint32 AA;
|
||||
uint32 value;
|
||||
uint32 charges;
|
||||
};
|
||||
|
||||
|
||||
@@ -756,29 +756,46 @@ struct Tribute_Struct {
|
||||
uint32 tier;
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct {
|
||||
uint32 item_id;
|
||||
uint32 icon;
|
||||
char item_name[64];
|
||||
};
|
||||
|
||||
//len = 320
|
||||
enum { //bandolier item positions
|
||||
bandolierMainHand = 0,
|
||||
bandolierOffHand,
|
||||
// Bandolier item positions
|
||||
enum
|
||||
{
|
||||
bandolierPrimary = 0,
|
||||
bandolierSecondary,
|
||||
bandolierRange,
|
||||
bandolierAmmo
|
||||
};
|
||||
struct Bandolier_Struct {
|
||||
char name[32];
|
||||
BandolierItem_Struct items[EmuConstants::BANDOLIER_SIZE];
|
||||
};
|
||||
struct PotionBelt_Struct {
|
||||
BandolierItem_Struct items[EmuConstants::POTION_BELT_SIZE];
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
struct MovePotionToBelt_Struct {
|
||||
//len = 320
|
||||
struct Bandolier_Struct
|
||||
{
|
||||
char Name[32];
|
||||
BandolierItem_Struct Items[EmuConstants::BANDOLIER_ITEM_COUNT];
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct PotionBeltItem_Struct
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
//len = 288
|
||||
struct PotionBelt_Struct
|
||||
{
|
||||
PotionBeltItem_Struct Items[EmuConstants::POTION_BELT_ITEM_COUNT];
|
||||
};
|
||||
|
||||
struct MovePotionToBelt_Struct
|
||||
{
|
||||
uint32 Action;
|
||||
uint32 SlotNumber;
|
||||
uint32 ItemID;
|
||||
@@ -1103,7 +1120,7 @@ struct PlayerProfile_Struct
|
||||
/*12800*/ uint32 expAA;
|
||||
/*12804*/ uint32 aapoints; //avaliable, unspent
|
||||
/*12808*/ uint8 unknown12844[36];
|
||||
/*12844*/ Bandolier_Struct bandoliers[EmuConstants::BANDOLIERS_COUNT];
|
||||
/*12844*/ Bandolier_Struct bandoliers[EmuConstants::BANDOLIERS_SIZE];
|
||||
/*14124*/ uint8 unknown14160[4506];
|
||||
/*18630*/ SuspendedMinion_Struct SuspendedMinion; // No longer in use
|
||||
/*19240*/ uint32 timeentitledonaccount;
|
||||
@@ -1144,7 +1161,7 @@ struct TargetReject_Struct {
|
||||
|
||||
struct PetCommand_Struct {
|
||||
/*000*/ uint32 command;
|
||||
/*004*/ uint32 unknown;
|
||||
/*004*/ uint32 target;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1249,7 +1266,7 @@ struct ZoneChange_Struct {
|
||||
|
||||
// Whatever you send to the client in RequestClientZoneChange_Struct.type, the client will send back
|
||||
// to the server in ZoneChange_Struct.zone_reason. My guess is this is a memo field of sorts.
|
||||
// WildcardX 27 January 2008
|
||||
// 27 January 2008
|
||||
|
||||
struct RequestClientZoneChange_Struct {
|
||||
/*00*/ uint16 zone_id;
|
||||
@@ -1263,8 +1280,8 @@ struct RequestClientZoneChange_Struct {
|
||||
|
||||
struct Animation_Struct {
|
||||
/*00*/ uint16 spawnid;
|
||||
/*02*/ uint8 action;
|
||||
/*03*/ uint8 value;
|
||||
/*02*/ uint8 speed;
|
||||
/*03*/ uint8 action;
|
||||
/*04*/
|
||||
};
|
||||
|
||||
@@ -1302,9 +1319,9 @@ struct CombatDamage_Struct
|
||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||
/* 05 */ uint16 spellid;
|
||||
/* 07 */ uint32 damage;
|
||||
/* 11 */ uint32 unknown11;
|
||||
/* 15 */ uint32 sequence; // see above notes in Action_Struct
|
||||
/* 19 */ uint32 unknown19;
|
||||
/* 11 */ float force;
|
||||
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
|
||||
/* 19 */ float meleepush_z;
|
||||
/* 23 */
|
||||
};
|
||||
|
||||
@@ -2132,24 +2149,24 @@ struct Illusion_Struct_Old {
|
||||
// OP_Sound - Size: 68
|
||||
struct QuestReward_Struct
|
||||
{
|
||||
/*000*/ uint32 from_mob; // ID of mob awarding the client
|
||||
/*004*/ uint32 unknown004;
|
||||
/*008*/ uint32 unknown008;
|
||||
/*012*/ uint32 unknown012;
|
||||
/*016*/ uint32 unknown016;
|
||||
/*020*/ uint32 unknown020;
|
||||
/*024*/ uint32 silver; // Gives silver to the client
|
||||
/*028*/ uint32 gold; // Gives gold to the client
|
||||
/*032*/ uint32 platinum; // Gives platinum to the client
|
||||
/*036*/ uint32 unknown036;
|
||||
/*040*/ uint32 unknown040;
|
||||
/*044*/ uint32 unknown044;
|
||||
/*048*/ uint32 unknown048;
|
||||
/*052*/ uint32 unknown052;
|
||||
/*056*/ uint32 unknown056;
|
||||
/*060*/ uint32 unknown060;
|
||||
/*064*/ uint32 unknown064;
|
||||
/*068*/
|
||||
/*000*/ uint32 mob_id; // ID of mob awarding the client
|
||||
/*004*/ uint32 target_id;
|
||||
/*008*/ uint32 exp_reward;
|
||||
/*012*/ uint32 faction;
|
||||
/*016*/ int32 faction_mod;
|
||||
/*020*/ uint32 copper; // Gives copper to the client
|
||||
/*024*/ uint32 silver; // Gives silver to the client
|
||||
/*028*/ uint32 gold; // Gives gold to the client
|
||||
/*032*/ uint32 platinum; // Gives platinum to the client
|
||||
/*036*/ uint32 item_id;
|
||||
/*040*/ uint32 unknown040;
|
||||
/*044*/ uint32 unknown044;
|
||||
/*048*/ uint32 unknown048;
|
||||
/*052*/ uint32 unknown052;
|
||||
/*056*/ uint32 unknown056;
|
||||
/*060*/ uint32 unknown060;
|
||||
/*064*/ uint32 unknown064;
|
||||
/*068*/
|
||||
};
|
||||
|
||||
// Size: 8
|
||||
@@ -2405,11 +2422,11 @@ struct InspectResponse_Struct {
|
||||
/*004*/ uint32 playerid;
|
||||
/*008*/ char itemnames[23][64];
|
||||
/*1480*/uint32 itemicons[23];
|
||||
/*1572*/char text[288]; // Max number of chars in Inspect Window appears to be 254 // Msg struct property is 256 (254 + '\0' is my guess) -U
|
||||
/*1572*/char text[288]; // Max number of chars in Inspect Window appears to be 254 // Msg struct property is 256 (254 + '\0' is my guess)
|
||||
/*1860*/
|
||||
};
|
||||
|
||||
//OP_InspectMessageUpdate - Size: 256 (SoF+ clients after self-inspect window is closed) -U
|
||||
//OP_InspectMessageUpdate - Size: 256 (SoF+ clients after self-inspect window is closed)
|
||||
struct InspectMessage_Struct {
|
||||
/*000*/ char text[256];
|
||||
/*256*/
|
||||
@@ -2518,9 +2535,9 @@ struct BookRequest_Struct {
|
||||
**
|
||||
*/
|
||||
struct Object_Struct {
|
||||
/*00*/ uint32 linked_list_addr[2];// <Zaphod> They are, get this, prev and next, ala linked list
|
||||
/*08*/ uint16 unknown008; //
|
||||
/*10*/ uint16 unknown010; //
|
||||
/*00*/ uint32 linked_list_addr[2];// They are, get this, prev and next, ala linked list
|
||||
/*08*/ uint16 size; //
|
||||
/*10*/ uint16 solidtype; //
|
||||
/*12*/ uint32 drop_id; // Unique object id for zone
|
||||
/*16*/ uint16 zone_id; // Redudant, but: Zone the object appears in
|
||||
/*18*/ uint16 zone_instance; //
|
||||
@@ -2537,8 +2554,8 @@ struct Object_Struct {
|
||||
/*88*/ uint32 spawn_id; // Spawn Id of client interacting with object
|
||||
/*92*/
|
||||
};
|
||||
//<Zaphod> 01 = generic drop, 02 = armor, 19 = weapon
|
||||
//[13:40] <Zaphod> and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject
|
||||
// 01 = generic drop, 02 = armor, 19 = weapon
|
||||
//[13:40] and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject
|
||||
|
||||
/*
|
||||
** Click Object Struct
|
||||
@@ -2595,7 +2612,7 @@ struct CloseContainer_Struct {
|
||||
*/
|
||||
struct Door_Struct
|
||||
{
|
||||
/*0000*/ char name[32]; // Filename of Door // Was 10char long before... added the 6 in the next unknown to it: Daeken M. BlackBlade //changed both to 32: Trevius
|
||||
/*0000*/ char name[32]; // Filename of Door // Was 10char long before... added the 6 in the next unknown to it //changed both to 32
|
||||
/*0032*/ float yPos; // y loc
|
||||
/*0036*/ float xPos; // x loc
|
||||
/*0040*/ float zPos; // z loc
|
||||
@@ -2761,7 +2778,8 @@ struct BazaarWelcome_Struct {
|
||||
BazaarWindowStart_Struct Beginning;
|
||||
uint32 Traders;
|
||||
uint32 Items;
|
||||
uint8 Unknown012[8];
|
||||
uint32 Unknown012;
|
||||
uint32 Unknown016;
|
||||
};
|
||||
|
||||
struct BazaarSearch_Struct {
|
||||
@@ -3146,6 +3164,7 @@ struct Trader_ShowItems_Struct{
|
||||
/*000*/ uint32 Code;
|
||||
/*004*/ uint32 TraderID;
|
||||
/*008*/ uint32 Unknown08[3];
|
||||
/*020*/
|
||||
};
|
||||
|
||||
struct TraderBuy_Struct{
|
||||
@@ -3191,9 +3210,10 @@ struct TraderDelItem_Struct{
|
||||
|
||||
struct TraderClick_Struct{
|
||||
/*000*/ uint32 TraderID;
|
||||
/*004*/ uint32 Unknown004;
|
||||
/*004*/ uint32 Code;
|
||||
/*008*/ uint32 Unknown008;
|
||||
/*012*/ uint32 Approval;
|
||||
/*016*/
|
||||
};
|
||||
|
||||
struct FormattedMessage_Struct{
|
||||
@@ -4011,7 +4031,7 @@ struct MarkNPC_Struct
|
||||
|
||||
struct InspectBuffs_Struct {
|
||||
/*000*/ uint32 spell_id[BUFF_COUNT];
|
||||
/*100*/ uint32 tics_remaining[BUFF_COUNT];
|
||||
/*100*/ int32 tics_remaining[BUFF_COUNT];
|
||||
};
|
||||
|
||||
struct RaidGeneral_Struct {
|
||||
@@ -4104,30 +4124,35 @@ struct DynamicWall_Struct {
|
||||
/*80*/
|
||||
};
|
||||
|
||||
enum { //bandolier actions
|
||||
BandolierCreate = 0,
|
||||
BandolierRemove = 1,
|
||||
BandolierSet = 2
|
||||
// Bandolier actions
|
||||
enum
|
||||
{
|
||||
bandolierCreate = 0,
|
||||
bandolierRemove,
|
||||
bandolierSet
|
||||
};
|
||||
|
||||
struct BandolierCreate_Struct {
|
||||
/*00*/ uint32 action; //0 for create
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ char name[32];
|
||||
/*37*/ uint16 unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 unknown39; //0
|
||||
struct BandolierCreate_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; //0 for create
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ char Name[32];
|
||||
/*37*/ uint16 Unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 Unknown39; //0
|
||||
};
|
||||
|
||||
struct BandolierDelete_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierDelete_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct BandolierSet_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierSet_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct Arrow_Struct {
|
||||
@@ -4252,14 +4277,6 @@ struct AA_Action {
|
||||
/*12*/ uint32 exp_value;
|
||||
};
|
||||
|
||||
|
||||
struct AA_Skills { //this should be removed and changed to AA_Array
|
||||
/*00*/ uint32 aa_skill; // Total AAs Spent
|
||||
/*04*/ uint32 aa_value;
|
||||
/*08*/ uint32 unknown08;
|
||||
/*12*/
|
||||
};
|
||||
|
||||
struct AAExpUpdate_Struct {
|
||||
/*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability
|
||||
/*04*/ uint32 aapoints_unspent;
|
||||
@@ -4277,12 +4294,12 @@ struct AltAdvStats_Struct {
|
||||
};
|
||||
|
||||
struct PlayerAA_Struct { // Is this still used?
|
||||
AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct AATable_Struct {
|
||||
/*00*/ int32 aa_spent; // Total AAs Spent
|
||||
/*04*/ AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
/*04*/ AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct Weather_Struct {
|
||||
@@ -4530,19 +4547,12 @@ struct InternalVeteranReward
|
||||
/*012*/ InternalVeteranRewardItem items[8];
|
||||
};
|
||||
|
||||
struct VeteranClaimReply
|
||||
struct VeteranClaim
|
||||
{
|
||||
/*000*/ char name[64];
|
||||
/*064*/ uint32 claim_id;
|
||||
/*068*/ uint32 reject_field;
|
||||
/*072*/ uint32 unknown072;
|
||||
};
|
||||
|
||||
struct VeteranClaimRequest
|
||||
{
|
||||
/*000*/ char name_data[64]; //name + other data
|
||||
/*000*/ char name[64]; //name + other data
|
||||
/*064*/ uint32 claim_id;
|
||||
/*068*/ uint32 unknown068;
|
||||
/*072*/ uint32 action;
|
||||
};
|
||||
|
||||
struct GMSearchCorpse_Struct
|
||||
@@ -4714,7 +4724,7 @@ struct BuffIconEntry_Struct
|
||||
{
|
||||
uint32 buff_slot;
|
||||
uint32 spell_id;
|
||||
uint32 tics_remaining;
|
||||
int32 tics_remaining;
|
||||
uint32 num_hits;
|
||||
};
|
||||
|
||||
@@ -4723,6 +4733,7 @@ struct BuffIcon_Struct
|
||||
uint32 entity_id;
|
||||
uint8 all_buffs;
|
||||
uint16 count;
|
||||
uint8 type; // 0 = self buff window, 1 = self target window, 4 = group, 5 = PC, 7 = NPC
|
||||
BuffIconEntry_Struct entries[0];
|
||||
};
|
||||
|
||||
|
||||
+32
-20
@@ -72,6 +72,8 @@ void EQStream::init(bool resetSession) {
|
||||
RateThreshold=RATEBASE/250;
|
||||
DecayRate=DECAYBASE/250;
|
||||
BytesWritten=0;
|
||||
sent_packet_count = 0;
|
||||
received_packet_count = 0;
|
||||
SequencedBase = 0;
|
||||
NextSequencedSend = 0;
|
||||
|
||||
@@ -464,37 +466,45 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
||||
}
|
||||
break;
|
||||
case OP_SessionStatRequest: {
|
||||
if(p->Size() < sizeof(SessionStats))
|
||||
if(p->Size() < sizeof(ClientSessionStats))
|
||||
{
|
||||
Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_SessionStatRequest that was of malformed size" __L);
|
||||
break;
|
||||
}
|
||||
#ifndef COLLECTOR
|
||||
SessionStats *Stats=(SessionStats *)p->pBuffer;
|
||||
ClientSessionStats *ClientStats=(ClientSessionStats *)p->pBuffer;
|
||||
Log.Out(Logs::Detail, Logs::Netcode, _L "Received Stats: %lu packets received, %lu packets sent, Deltas: local %lu, (%lu <- %lu -> %lu) remote %lu" __L,
|
||||
(unsigned long)ntohl(Stats->packets_received), (unsigned long)ntohl(Stats->packets_sent), (unsigned long)ntohl(Stats->last_local_delta),
|
||||
(unsigned long)ntohl(Stats->low_delta), (unsigned long)ntohl(Stats->average_delta),
|
||||
(unsigned long)ntohl(Stats->high_delta), (unsigned long)ntohl(Stats->last_remote_delta));
|
||||
uint64 x=Stats->packets_received;
|
||||
Stats->packets_received=Stats->packets_sent;
|
||||
Stats->packets_sent=x;
|
||||
NonSequencedPush(new EQProtocolPacket(OP_SessionStatResponse,p->pBuffer,p->size));
|
||||
AdjustRates(ntohl(Stats->average_delta));
|
||||
(unsigned long)ntohl(ClientStats->packets_received), (unsigned long)ntohl(ClientStats->packets_sent), (unsigned long)ntohl(ClientStats->last_local_delta),
|
||||
(unsigned long)ntohl(ClientStats->low_delta), (unsigned long)ntohl(ClientStats->average_delta),
|
||||
(unsigned long)ntohl(ClientStats->high_delta), (unsigned long)ntohl(ClientStats->last_remote_delta));
|
||||
|
||||
AdjustRates(ntohl(ClientStats->average_delta));
|
||||
|
||||
if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) {
|
||||
if(RETRANSMIT_TIMEOUT_MULT && ntohl(Stats->average_delta)) {
|
||||
if (RETRANSMIT_TIMEOUT_MULT && ntohl(ClientStats->average_delta)) {
|
||||
//recalculate retransmittimeout using the larger of the last rtt or average rtt, which is multiplied by the rule value
|
||||
if((ntohl(Stats->last_local_delta) + ntohl(Stats->last_remote_delta)) > (ntohl(Stats->average_delta) * 2)) {
|
||||
retransmittimeout = (ntohl(Stats->last_local_delta) + ntohl(Stats->last_remote_delta))
|
||||
if ((ntohl(ClientStats->last_local_delta) + ntohl(ClientStats->last_remote_delta)) > (ntohl(ClientStats->average_delta) * 2)) {
|
||||
retransmittimeout = (ntohl(ClientStats->last_local_delta) + ntohl(ClientStats->last_remote_delta))
|
||||
* RETRANSMIT_TIMEOUT_MULT;
|
||||
} else {
|
||||
retransmittimeout = ntohl(Stats->average_delta) * 2 * RETRANSMIT_TIMEOUT_MULT;
|
||||
retransmittimeout = ntohl(ClientStats->average_delta) * 2 * RETRANSMIT_TIMEOUT_MULT;
|
||||
}
|
||||
if(retransmittimeout > RETRANSMIT_TIMEOUT_MAX)
|
||||
retransmittimeout = RETRANSMIT_TIMEOUT_MAX;
|
||||
Log.Out(Logs::Detail, Logs::Netcode, _L "Retransmit timeout recalculated to %dms" __L, retransmittimeout);
|
||||
}
|
||||
}
|
||||
|
||||
ServerSessionStats *ServerStats = (ServerSessionStats *)p->pBuffer;
|
||||
|
||||
//ServerStats->RequestID = ClientStats->RequestID; // no change
|
||||
ServerStats->ServerTime = htonl(Timer::GetCurrentTime());
|
||||
ServerStats->packets_sent_echo = ClientStats->packets_sent; // still in htonll format
|
||||
ServerStats->packets_received_echo = ClientStats->packets_received; // still in htonll format
|
||||
ServerStats->packets_sent = htonll(GetPacketsSent());
|
||||
ServerStats->packets_received = htonll(GetPacketsReceived());
|
||||
|
||||
NonSequencedPush(new EQProtocolPacket(OP_SessionStatResponse, p->pBuffer, p->size));
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
@@ -573,16 +583,18 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p)
|
||||
|
||||
// Convert the EQApplicationPacket to 1 or more EQProtocolPackets
|
||||
if (p->size>(MaxLen-8)) { // proto-op(2), seq(2), app-op(2) ... data ... crc(2)
|
||||
Log.Out(Logs::Detail, Logs::Netcode, _L "Making oversized packet, len %d" __L, p->size);
|
||||
Log.Out(Logs::Detail, Logs::Netcode, _L "Making oversized packet, len %d" __L, p->Size());
|
||||
|
||||
unsigned char *tmpbuff=new unsigned char[p->size+3];
|
||||
length=p->serialize(opcode, tmpbuff);
|
||||
if (length != p->Size())
|
||||
Log.Out(Logs::Detail, Logs::Netcode, _L "Packet adjustment, len %d to %d" __L, p->Size(), length);
|
||||
|
||||
EQProtocolPacket *out=new EQProtocolPacket(OP_Fragment,nullptr,MaxLen-4);
|
||||
*(uint32 *)(out->pBuffer+2)=htonl(p->Size());
|
||||
*(uint32 *)(out->pBuffer+2)=htonl(length);
|
||||
used=MaxLen-10;
|
||||
memcpy(out->pBuffer+6,tmpbuff,used);
|
||||
Log.Out(Logs::Detail, Logs::Netcode, _L "First fragment: used %d/%d. Put size %d in the packet" __L, used, p->size, p->Size());
|
||||
Log.Out(Logs::Detail, Logs::Netcode, _L "First fragment: used %d/%d. Payload size %d in the packet" __L, used, length, p->size);
|
||||
SequencedPush(out);
|
||||
|
||||
|
||||
@@ -593,7 +605,7 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p)
|
||||
out->size=chunksize+2;
|
||||
SequencedPush(out);
|
||||
used+=chunksize;
|
||||
Log.Out(Logs::Detail, Logs::Netcode, _L "Subsequent fragment: len %d, used %d/%d." __L, chunksize, used, p->size);
|
||||
Log.Out(Logs::Detail, Logs::Netcode, _L "Subsequent fragment: len %d, used %d/%d." __L, chunksize, used, length);
|
||||
}
|
||||
delete p;
|
||||
delete[] tmpbuff;
|
||||
@@ -1101,8 +1113,8 @@ EQProtocolPacket *p=nullptr;
|
||||
|
||||
void EQStream::Process(const unsigned char *buffer, const uint32 length)
|
||||
{
|
||||
static unsigned char newbuffer[2048];
|
||||
uint32 newlength=0;
|
||||
static unsigned char newbuffer[2048];
|
||||
uint32 newlength=0;
|
||||
if (EQProtocolPacket::ValidateCRC(buffer,length,Key)) {
|
||||
if (compressed) {
|
||||
newlength=EQProtocolPacket::Decompress(buffer,length,newbuffer,2048);
|
||||
|
||||
+19
-1
@@ -71,7 +71,7 @@ struct SessionResponse {
|
||||
};
|
||||
|
||||
//Deltas are in ms, representing round trip times
|
||||
struct SessionStats {
|
||||
struct ClientSessionStats {
|
||||
/*000*/ uint16 RequestID;
|
||||
/*002*/ uint32 last_local_delta;
|
||||
/*006*/ uint32 average_delta;
|
||||
@@ -83,6 +83,16 @@ struct SessionStats {
|
||||
/*038*/
|
||||
};
|
||||
|
||||
struct ServerSessionStats {
|
||||
/*000*/ uint16 RequestID;
|
||||
/*002*/ uint32 ServerTime;
|
||||
/*006*/ uint64 packets_sent_echo;
|
||||
/*014*/ uint64 packets_received_echo;
|
||||
/*022*/ uint64 packets_sent;
|
||||
/*030*/ uint64 packets_received;
|
||||
/*038*/
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
class OpcodeManager;
|
||||
@@ -158,6 +168,9 @@ class EQStream : public EQStreamInterface {
|
||||
|
||||
int32 BytesWritten;
|
||||
|
||||
uint64 sent_packet_count;
|
||||
uint64 received_packet_count;
|
||||
|
||||
Mutex MRate;
|
||||
int32 RateThreshold;
|
||||
int32 DecayRate;
|
||||
@@ -265,11 +278,13 @@ class EQStream : public EQStreamInterface {
|
||||
void AddBytesSent(uint32 bytes)
|
||||
{
|
||||
bytes_sent += bytes;
|
||||
++sent_packet_count;
|
||||
}
|
||||
|
||||
void AddBytesRecv(uint32 bytes)
|
||||
{
|
||||
bytes_recv += bytes;
|
||||
++received_packet_count;
|
||||
}
|
||||
|
||||
virtual const uint32 GetBytesSent() const { return bytes_sent; }
|
||||
@@ -288,6 +303,9 @@ class EQStream : public EQStreamInterface {
|
||||
return bytes_recv / (Timer::GetTimeSeconds() - create_time);
|
||||
}
|
||||
|
||||
const uint64 GetPacketsSent() { return sent_packet_count; }
|
||||
const uint64 GetPacketsReceived() { return received_packet_count; }
|
||||
|
||||
//used for dynamic stream identification
|
||||
class Signature {
|
||||
public:
|
||||
|
||||
+41
-42
@@ -43,19 +43,19 @@ EQTime::EQTime(TimeOfDay_Struct start_eq, time_t start_real)
|
||||
|
||||
EQTime::EQTime()
|
||||
{
|
||||
timezone=0;
|
||||
timezone = 0;
|
||||
memset(&eqTime, 0, sizeof(eqTime));
|
||||
//Defaults for time
|
||||
TimeOfDay_Struct start;
|
||||
start.day=1;
|
||||
start.hour=9;
|
||||
start.minute=0;
|
||||
start.month=1;
|
||||
start.year=3100;
|
||||
start.day = 1;
|
||||
start.hour = 9;
|
||||
start.minute = 0;
|
||||
start.month = 1;
|
||||
start.year = 3100;
|
||||
//Set default time zone
|
||||
timezone=0;
|
||||
timezone = 0;
|
||||
//Start EQTimer
|
||||
setEQTimeOfDay(start, time(0));
|
||||
SetCurrentEQTimeOfDay(start, time(0));
|
||||
}
|
||||
|
||||
EQTime::~EQTime()
|
||||
@@ -67,10 +67,10 @@ EQTime::~EQTime()
|
||||
//Input: Current Time (as a time_t), a pointer to the TimeOfDay_Struct that will be written to.
|
||||
//Output: 0=Error, 1=Sucess
|
||||
|
||||
int EQTime::getEQTimeOfDay( time_t timeConvert, struct TimeOfDay_Struct *eqTimeOfDay )
|
||||
int EQTime::GetCurrentEQTimeOfDay(time_t timeConvert, struct TimeOfDay_Struct *eqTimeOfDay)
|
||||
{
|
||||
/* check to see if we have a reference time to go by. */
|
||||
if( eqTime.start_realtime == 0 )
|
||||
if (eqTime.start_realtime == 0)
|
||||
return 0;
|
||||
|
||||
unsigned long diff = timeConvert - eqTime.start_realtime;
|
||||
@@ -83,7 +83,7 @@ int EQTime::getEQTimeOfDay( time_t timeConvert, struct TimeOfDay_Struct *eqTimeO
|
||||
int32 ntz = timezone;
|
||||
|
||||
/* The minutes range from 0 - 59 */
|
||||
diff += eqTime.start_eqtime.minute + (ntz%60);
|
||||
diff += eqTime.start_eqtime.minute + (ntz % 60);
|
||||
eqTimeOfDay->minute = diff % 60;
|
||||
diff /= 60;
|
||||
ntz /= 60;
|
||||
@@ -97,24 +97,24 @@ int EQTime::getEQTimeOfDay( time_t timeConvert, struct TimeOfDay_Struct *eqTimeO
|
||||
//
|
||||
// Modify it so that it works from
|
||||
// 0-23 for our calculations
|
||||
diff += ( eqTime.start_eqtime.hour - 1) + (ntz%24);
|
||||
eqTimeOfDay->hour = (diff%24) + 1;
|
||||
diff += (eqTime.start_eqtime.hour - 1) + (ntz % 24);
|
||||
eqTimeOfDay->hour = (diff % 24) + 1;
|
||||
diff /= 24;
|
||||
ntz /= 24;
|
||||
|
||||
// The days range from 1-28
|
||||
// Modify it so that it works from
|
||||
// 0-27 for our calculations
|
||||
diff += ( eqTime.start_eqtime.day - 1 ) + (ntz%28);
|
||||
eqTimeOfDay->day = (diff%28) + 1;
|
||||
diff += (eqTime.start_eqtime.day - 1) + (ntz % 28);
|
||||
eqTimeOfDay->day = (diff % 28) + 1;
|
||||
diff /= 28;
|
||||
ntz /= 28;
|
||||
|
||||
// The months range from 1-12
|
||||
// Modify it so that it works from
|
||||
// 0-11 for our calculations
|
||||
diff += ( eqTime.start_eqtime.month - 1 ) + (ntz%12);
|
||||
eqTimeOfDay->month = (diff%12) + 1;
|
||||
diff += (eqTime.start_eqtime.month - 1) + (ntz % 12);
|
||||
eqTimeOfDay->month = (diff % 12) + 1;
|
||||
diff /= 12;
|
||||
ntz /= 12;
|
||||
|
||||
@@ -124,12 +124,12 @@ int EQTime::getEQTimeOfDay( time_t timeConvert, struct TimeOfDay_Struct *eqTimeO
|
||||
}
|
||||
|
||||
//setEQTimeOfDay
|
||||
int EQTime::setEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real)
|
||||
int EQTime::SetCurrentEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real)
|
||||
{
|
||||
if(start_real==0)
|
||||
if (start_real == 0)
|
||||
return 0;
|
||||
eqTime.start_eqtime=start_eq;
|
||||
eqTime.start_realtime=start_real;
|
||||
eqTime.start_eqtime = start_eq;
|
||||
eqTime.start_realtime = start_real;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ bool EQTime::saveFile(const char *filename)
|
||||
{
|
||||
std::ofstream of;
|
||||
of.open(filename);
|
||||
if(!of)
|
||||
if (!of)
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Error, "EQTime::saveFile failed: Unable to open file '%s'", filename);
|
||||
return false;
|
||||
@@ -200,24 +200,24 @@ bool EQTime::loadFile(const char *filename)
|
||||
|
||||
|
||||
bool EQTime::IsTimeBefore(TimeOfDay_Struct *base, TimeOfDay_Struct *test) {
|
||||
if(base->year > test->year)
|
||||
if (base->year > test->year)
|
||||
return(true);
|
||||
if(base->year < test->year)
|
||||
if (base->year < test->year)
|
||||
return(false);
|
||||
//same years
|
||||
if(base->month > test->month)
|
||||
if (base->month > test->month)
|
||||
return(true);
|
||||
if(base->month < test->month)
|
||||
if (base->month < test->month)
|
||||
return(false);
|
||||
//same month
|
||||
if(base->day > test->day)
|
||||
if (base->day > test->day)
|
||||
return(true);
|
||||
if(base->day < test->day)
|
||||
if (base->day < test->day)
|
||||
return(false);
|
||||
//same day
|
||||
if(base->hour > test->hour)
|
||||
if (base->hour > test->hour)
|
||||
return(true);
|
||||
if(base->hour < test->hour)
|
||||
if (base->hour < test->hour)
|
||||
return(false);
|
||||
//same hour...
|
||||
return(base->minute > test->minute);
|
||||
@@ -230,7 +230,7 @@ void EQTime::AddMinutes(uint32 minutes, TimeOfDay_Struct *to) {
|
||||
//minutes start at 0, everything else starts at 1
|
||||
cur = to->minute;
|
||||
cur += minutes;
|
||||
if(cur < 60) {
|
||||
if (cur < 60) {
|
||||
to->minute = cur;
|
||||
return;
|
||||
}
|
||||
@@ -238,29 +238,29 @@ void EQTime::AddMinutes(uint32 minutes, TimeOfDay_Struct *to) {
|
||||
//carry hours
|
||||
cur /= 60;
|
||||
cur += to->hour;
|
||||
if(cur <= 24) {
|
||||
if (cur <= 24) {
|
||||
to->hour = cur;
|
||||
return;
|
||||
}
|
||||
to->hour = ((cur-1) % 24) + 1;
|
||||
to->hour = ((cur - 1) % 24) + 1;
|
||||
//carry days
|
||||
cur = (cur-1) / 24;
|
||||
cur = (cur - 1) / 24;
|
||||
cur += to->day;
|
||||
if(cur <= 28) {
|
||||
if (cur <= 28) {
|
||||
to->day = cur;
|
||||
return;
|
||||
}
|
||||
to->day = ((cur-1) % 28) + 1;
|
||||
to->day = ((cur - 1) % 28) + 1;
|
||||
//carry months
|
||||
cur = (cur-1) / 28;
|
||||
cur = (cur - 1) / 28;
|
||||
cur += to->month;
|
||||
if(cur <= 12) {
|
||||
if (cur <= 12) {
|
||||
to->month = cur;
|
||||
return;
|
||||
}
|
||||
to->month = ((cur-1) % 12) + 1;
|
||||
to->month = ((cur - 1) % 12) + 1;
|
||||
//carry years
|
||||
to->year += (cur-1) / 12;
|
||||
to->year += (cur - 1) / 12;
|
||||
}
|
||||
|
||||
void EQTime::ToString(TimeOfDay_Struct *t, std::string &str) {
|
||||
@@ -269,5 +269,4 @@ void EQTime::ToString(TimeOfDay_Struct *t, std::string &str) {
|
||||
t->month, t->day, t->year, t->hour, t->minute);
|
||||
buf[127] = '\0';
|
||||
str = buf;
|
||||
}
|
||||
|
||||
}
|
||||
+3
-3
@@ -21,8 +21,8 @@ public:
|
||||
~EQTime();
|
||||
|
||||
//Get functions
|
||||
int getEQTimeOfDay( TimeOfDay_Struct *eqTimeOfDay ) { return(getEQTimeOfDay(time(nullptr), eqTimeOfDay)); }
|
||||
int getEQTimeOfDay( time_t timeConvert, TimeOfDay_Struct *eqTimeOfDay );
|
||||
int GetCurrentEQTimeOfDay( TimeOfDay_Struct *eqTimeOfDay ) { return(GetCurrentEQTimeOfDay(time(nullptr), eqTimeOfDay)); }
|
||||
int GetCurrentEQTimeOfDay( time_t timeConvert, TimeOfDay_Struct *eqTimeOfDay );
|
||||
TimeOfDay_Struct getStartEQTime() { return eqTime.start_eqtime; }
|
||||
time_t getStartRealTime() { return eqTime.start_realtime; }
|
||||
uint32 getEQTimeZone() { return timezone; }
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
uint32 getEQTimeZoneMin() { return timezone%60; }
|
||||
|
||||
//Set functions
|
||||
int setEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real);
|
||||
int SetCurrentEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real);
|
||||
void setEQTimeZone(int32 in_timezone) { timezone=in_timezone; }
|
||||
|
||||
//Time math/logic functions
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
#include "global_define.h"
|
||||
#include "types.h"
|
||||
#include "clientversions.h"
|
||||
#include "file_verify.h"
|
||||
#include "crc32.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#pragma pack(1)
|
||||
struct VerifyFileStruct
|
||||
{
|
||||
uint32 crc;
|
||||
uint32 file_size;
|
||||
uint32 offset[256];
|
||||
uint32 data[256];
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
EQEmu::FileVerify::FileVerify() {
|
||||
buffer = nullptr;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
EQEmu::FileVerify::~FileVerify() {
|
||||
safe_delete_array(buffer);
|
||||
}
|
||||
|
||||
bool EQEmu::FileVerify::Load(const char *file_name) {
|
||||
safe_delete_array(buffer);
|
||||
size = 0;
|
||||
|
||||
FILE *f = fopen(file_name, "rb");
|
||||
if(!f) {
|
||||
buffer = nullptr;
|
||||
size = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
fseek(f, 0U, SEEK_END);
|
||||
size = ftell(f);
|
||||
rewind(f);
|
||||
|
||||
buffer = new char[size];
|
||||
auto result = fread(buffer, 1, size, f);
|
||||
fclose(f);
|
||||
|
||||
if(result != size) {
|
||||
safe_delete_array(buffer);
|
||||
size = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EQEmu::FileVerify::Verify(const char *data, uint32 size, ClientVersion version) {
|
||||
if(!buffer) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(size != sizeof(VerifyFileStruct)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VerifyFileStruct *vs = (VerifyFileStruct*)data;
|
||||
if(this->size != vs->file_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 crc = CRC32::GenerateNoFlip((uchar*)buffer, this->size);
|
||||
if(vs->crc != crc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(int i = 0; i < 256; ++i) {
|
||||
uint32 offset = vs->offset[i] * 4;
|
||||
|
||||
if((offset - 4) > this->size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 check = *(uint32*)(buffer + offset);
|
||||
if(check != vs->data[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef EQEMU_COMMON_FILE_VERIFY_H
|
||||
#define EQEMU_COMMON_FILE_VERIFY_H
|
||||
|
||||
namespace EQEmu
|
||||
{
|
||||
class FileVerify
|
||||
{
|
||||
public:
|
||||
FileVerify();
|
||||
~FileVerify();
|
||||
|
||||
bool Load(const char *file_name);
|
||||
bool Verify(const char *data, uint32 size, ClientVersion version);
|
||||
|
||||
private:
|
||||
char *buffer;
|
||||
uint32 size;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,87 @@
|
||||
#include "global_define.h"
|
||||
#include "types.h"
|
||||
#include "clientversions.h"
|
||||
#include "eq_packet.h"
|
||||
#include "file_verify_manager.h"
|
||||
#include "string_util.h"
|
||||
#include <memory>
|
||||
|
||||
struct EQEmu::FileVerifyManager::impl {
|
||||
std::unique_ptr<FileVerify> spell_data;
|
||||
std::unique_ptr<FileVerify> skill_data;
|
||||
std::unique_ptr<FileVerify> base_data;
|
||||
std::unique_ptr<FileVerify> eqgames[(int)ClientVersion::MaxClientVersions];
|
||||
};
|
||||
|
||||
EQEmu::FileVerifyManager::FileVerifyManager() {
|
||||
impl_ = new impl;
|
||||
impl_->spell_data.reset(new FileVerify());
|
||||
impl_->spell_data->Load("verify/spells_us.txt");
|
||||
|
||||
impl_->skill_data.reset(new FileVerify());
|
||||
impl_->skill_data->Load("verify/SkillCaps.txt");
|
||||
|
||||
impl_->base_data.reset(new FileVerify());
|
||||
impl_->base_data->Load("verify/BaseData.txt");
|
||||
|
||||
for(int i = 0; i < (int)ClientVersion::MaxClientVersions; ++i) {
|
||||
impl_->eqgames[i].reset(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
EQEmu::FileVerifyManager::~FileVerifyManager() {
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
bool EQEmu::FileVerifyManager::VerifySpellFile(const EQApplicationPacket *app, ClientVersion version) {
|
||||
if(!impl_->spell_data) {
|
||||
impl_->spell_data.reset(new FileVerify());
|
||||
|
||||
if(!impl_->spell_data->Load("verify/spells_us.txt")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return impl_->spell_data->Verify((char*)app->pBuffer, app->size, version);
|
||||
}
|
||||
|
||||
bool EQEmu::FileVerifyManager::VerifySkillFile(const EQApplicationPacket *app, ClientVersion version) {
|
||||
if(!impl_->skill_data) {
|
||||
impl_->skill_data.reset(new FileVerify());
|
||||
|
||||
if(!impl_->skill_data->Load("verify/SkillCaps.txt")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return impl_->skill_data->Verify((char*)app->pBuffer, app->size, version);
|
||||
}
|
||||
|
||||
bool EQEmu::FileVerifyManager::VerifyBaseDataFile(const EQApplicationPacket *app, ClientVersion version) {
|
||||
if(!impl_->base_data) {
|
||||
impl_->base_data.reset(new FileVerify());
|
||||
|
||||
if(!impl_->base_data->Load("verify/BaseData.txt")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return impl_->base_data->Verify((char*)app->pBuffer, app->size, version);
|
||||
}
|
||||
|
||||
bool EQEmu::FileVerifyManager::VerifyEQGame(const EQApplicationPacket *app, ClientVersion version) {
|
||||
int v = (int)version;
|
||||
if(v >= (int)ClientVersion::MaxClientVersions) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!impl_->eqgames[v]) {
|
||||
impl_->eqgames[v].reset(new FileVerify());
|
||||
|
||||
if(!impl_->eqgames[v]->Load(StringFormat("verify/%s/eqgame.exe", ClientVersionName(version)).c_str())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return impl_->eqgames[v]->Verify((char*)app->pBuffer, app->size, version);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef EQEMU_COMMON_FILE_VERIFY_MANAGER_H
|
||||
#define EQEMU_COMMON_FILE_VERIFY_MANAGER_H
|
||||
|
||||
#include "file_verify.h"
|
||||
|
||||
namespace EQEmu
|
||||
{
|
||||
class FileVerifyManager
|
||||
{
|
||||
public:
|
||||
~FileVerifyManager();
|
||||
|
||||
static FileVerifyManager& Get()
|
||||
{
|
||||
static FileVerifyManager instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
bool VerifySpellFile(const EQApplicationPacket *app, ClientVersion version);
|
||||
bool VerifySkillFile(const EQApplicationPacket *app, ClientVersion version);
|
||||
bool VerifyBaseDataFile(const EQApplicationPacket *app, ClientVersion version);
|
||||
bool VerifyEQGame(const EQApplicationPacket *app, ClientVersion version);
|
||||
private:
|
||||
FileVerifyManager();
|
||||
FileVerifyManager(FileVerifyManager const&);
|
||||
void operator=(FileVerifyManager const&);
|
||||
|
||||
struct impl;
|
||||
impl *impl_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
+85
-13
@@ -660,7 +660,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) {
|
||||
// Do not arbitrarily use this function..it is designed for use with Client::ResetTrade() and Client::FinishTrade().
|
||||
// If you have a need, use it..but, understand it is not a compatible replacement for Inventory::FindFreeSlot().
|
||||
//
|
||||
// I'll probably implement a bitmask in the new inventory system to avoid having to adjust stack bias -U
|
||||
// I'll probably implement a bitmask in the new inventory system to avoid having to adjust stack bias
|
||||
|
||||
if (!inst || !inst->GetID())
|
||||
return INVALID_INDEX;
|
||||
@@ -993,34 +993,43 @@ int Inventory::GetSlotByItemInst(ItemInst *inst) {
|
||||
return INVALID_INDEX;
|
||||
}
|
||||
|
||||
uint8 Inventory::FindHighestLightValue()
|
||||
uint8 Inventory::FindBrightestLightType()
|
||||
{
|
||||
uint8 light_value = NOT_USED;
|
||||
uint8 brightest_light_type = 0;
|
||||
|
||||
// NOTE: The client does not recognize augment light sources, applied or otherwise, and should not be parsed
|
||||
for (auto iter = m_worn.begin(); iter != m_worn.end(); ++iter) {
|
||||
if ((iter->first < EmuConstants::EQUIPMENT_BEGIN || iter->first > EmuConstants::EQUIPMENT_END) && iter->first != MainPowerSource) { continue; }
|
||||
if (iter->first == MainAmmo) { continue; }
|
||||
|
||||
auto inst = iter->second;
|
||||
if (inst == nullptr) { continue; }
|
||||
auto item = inst->GetItem();
|
||||
if (item == nullptr) { continue; }
|
||||
if (item->Light & 0xF0) { continue; }
|
||||
if (item->Light > light_value) { light_value = item->Light; }
|
||||
|
||||
if (LightProfile_Struct::IsLevelGreater(item->Light, brightest_light_type))
|
||||
brightest_light_type = item->Light;
|
||||
}
|
||||
|
||||
uint8 general_light_type = 0;
|
||||
for (auto iter = m_inv.begin(); iter != m_inv.end(); ++iter) {
|
||||
if (iter->first < EmuConstants::GENERAL_BEGIN || iter->first > EmuConstants::GENERAL_END) { continue; }
|
||||
|
||||
auto inst = iter->second;
|
||||
if (inst == nullptr) { continue; }
|
||||
auto item = inst->GetItem();
|
||||
if (item == nullptr) { continue; }
|
||||
// 'Gloomingdeep lantern' is ItemTypeArmor in the database..there may be others instances and/or types that need to be handled
|
||||
if (item->ItemType != ItemTypeMisc && item->ItemType != ItemTypeLight && item->ItemType != ItemTypeArmor) { continue; }
|
||||
if (item->Light & 0xF0) { continue; }
|
||||
if (item->Light > light_value) { light_value = item->Light; }
|
||||
|
||||
if (item->ItemClass != ItemClassCommon) { continue; }
|
||||
if (item->Light < 9 || item->Light > 13) { continue; }
|
||||
|
||||
if (LightProfile_Struct::TypeToLevel(item->Light))
|
||||
general_light_type = item->Light;
|
||||
}
|
||||
|
||||
return light_value;
|
||||
if (LightProfile_Struct::IsLevelGreater(general_light_type, brightest_light_type))
|
||||
brightest_light_type = general_light_type;
|
||||
|
||||
return brightest_light_type;
|
||||
}
|
||||
|
||||
void Inventory::dumpEntireInventory() {
|
||||
@@ -1232,7 +1241,7 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity)
|
||||
// found, it is presented as being available on the cursor. In cases of a parity check, this
|
||||
// is sufficient. However, in cases where referential criteria is considered, this can lead
|
||||
// to unintended results. Funtionality should be observed when referencing the return value
|
||||
// of this query -U
|
||||
// of this query
|
||||
|
||||
uint8 quantity_found = 0;
|
||||
|
||||
@@ -2148,7 +2157,7 @@ ItemInst* ItemInst::Clone() const
|
||||
}
|
||||
|
||||
bool ItemInst::IsSlotAllowed(int16 slot_id) const {
|
||||
// 'SupportsContainers' and 'slot_id > 21' previously saw the reassigned PowerSource slot (9999 to 22) as valid -U
|
||||
// 'SupportsContainers' and 'slot_id > 21' previously saw the reassigned PowerSource slot (9999 to 22) as valid
|
||||
if (!m_item) { return false; }
|
||||
else if (Inventory::SupportsContainers(slot_id)) { return true; }
|
||||
else if (m_item->Slots & (1 << slot_id)) { return true; }
|
||||
@@ -2361,3 +2370,66 @@ bool Item_Struct::IsEquipable(uint16 Race, uint16 Class_) const
|
||||
|
||||
return (IsRace && IsClass);
|
||||
}
|
||||
|
||||
//
|
||||
// struct LightProfile_Struct
|
||||
//
|
||||
uint8 LightProfile_Struct::TypeToLevel(uint8 lightType)
|
||||
{
|
||||
switch (lightType) {
|
||||
case lightTypeGlobeOfStars:
|
||||
return lightLevelBrilliant; // 10
|
||||
case lightTypeFlamelessLantern:
|
||||
case lightTypeGreaterLightstone:
|
||||
return lightLevelLargeMagic; // 9
|
||||
case lightTypeLargeLantern:
|
||||
return lightLevelLargeLantern; // 8
|
||||
case lightTypeSteinOfMoggok:
|
||||
case lightTypeLightstone:
|
||||
return lightLevelMagicLantern; // 7
|
||||
case lightTypeSmallLantern:
|
||||
return lightLevelSmallLantern; // 6
|
||||
case lightTypeColdlight:
|
||||
case lightTypeUnknown2:
|
||||
return lightLevelBlueLight; // 5
|
||||
case lightTypeFireBeetleEye:
|
||||
case lightTypeUnknown1:
|
||||
return lightLevelRedLight; // 4
|
||||
case lightTypeTinyGlowingSkull:
|
||||
case lightTypeLightGlobe:
|
||||
return lightLevelSmallMagic; // 3
|
||||
case lightTypeTorch:
|
||||
return lightLevelTorch; // 2
|
||||
case lightLevelCandle:
|
||||
return lightLevelCandle; // 1
|
||||
default:
|
||||
return lightLevelUnlit; // 0
|
||||
}
|
||||
}
|
||||
|
||||
bool LightProfile_Struct::IsLevelGreater(uint8 leftType, uint8 rightType)
|
||||
{
|
||||
static const uint8 light_levels[LIGHT_TYPES_COUNT] = {
|
||||
lightLevelUnlit, /* lightTypeNone */
|
||||
lightLevelCandle, /* lightTypeCandle */
|
||||
lightLevelTorch, /* lightTypeTorch */
|
||||
lightLevelSmallMagic, /* lightTypeTinyGlowingSkull */
|
||||
lightLevelSmallLantern, /* lightTypeSmallLantern */
|
||||
lightLevelMagicLantern, /* lightTypeSteinOfMoggok */
|
||||
lightLevelLargeLantern, /* lightTypeLargeLantern */
|
||||
lightLevelLargeMagic, /* lightTypeFlamelessLantern */
|
||||
lightLevelBrilliant, /* lightTypeGlobeOfStars */
|
||||
lightLevelSmallMagic, /* lightTypeLightGlobe */
|
||||
lightLevelMagicLantern, /* lightTypeLightstone */
|
||||
lightLevelLargeMagic, /* lightTypeGreaterLightstone */
|
||||
lightLevelRedLight, /* lightTypeFireBeetleEye */
|
||||
lightLevelBlueLight, /* lightTypeColdlight */
|
||||
lightLevelRedLight, /* lightTypeUnknown1 */
|
||||
lightLevelBlueLight /* lightTypeUnknown2 */
|
||||
};
|
||||
|
||||
if (leftType >= LIGHT_TYPES_COUNT) { leftType = lightTypeNone; }
|
||||
if (rightType >= LIGHT_TYPES_COUNT) { rightType = lightTypeNone; }
|
||||
|
||||
return (light_levels[leftType] > light_levels[rightType]);
|
||||
}
|
||||
|
||||
+40
-1
@@ -204,7 +204,7 @@ public:
|
||||
|
||||
int GetSlotByItemInst(ItemInst *inst);
|
||||
|
||||
uint8 FindHighestLightValue();
|
||||
uint8 FindBrightestLightType();
|
||||
|
||||
void dumpEntireInventory();
|
||||
void dumpWornItems();
|
||||
@@ -472,4 +472,43 @@ public:
|
||||
~EvolveInfo();
|
||||
};
|
||||
|
||||
struct LightProfile_Struct
|
||||
{
|
||||
/*
|
||||
Current criteria (light types):
|
||||
Equipment: { 0 .. 15 }
|
||||
General: { 9 .. 13 }
|
||||
|
||||
Notes:
|
||||
- Initial character load and item movement updates use different light source update behaviors
|
||||
-- Server procedure matches the item movement behavior since most updates occur post-character load
|
||||
- MainAmmo is not considered when determining light sources
|
||||
- No 'Sub' or 'Aug' items are recognized as light sources
|
||||
- Light types '< 9' and '> 13' are not considered for general (carried) light sources
|
||||
- If values > 0x0F are valid, then assignment limiters will need to be removed
|
||||
- MainCursor 'appears' to be a valid light source update slot..but, have not experienced updates during debug sessions
|
||||
- All clients have a bug regarding stackable items (light and sound updates are not processed when picking up an item)
|
||||
-- The timer-based update cancels out the invalid light source
|
||||
*/
|
||||
|
||||
static uint8 TypeToLevel(uint8 lightType);
|
||||
static bool IsLevelGreater(uint8 leftType, uint8 rightType);
|
||||
|
||||
// Light types (classifications)
|
||||
struct {
|
||||
uint8 Innate; // Defined by db field `npc_types`.`light` - where appropriate
|
||||
uint8 Equipment; // Item_Struct::light value of worn/carried equipment
|
||||
uint8 Spell; // Set value of any light-producing spell (can be modded to mimic equip_light behavior)
|
||||
uint8 Active; // Highest value of all light sources
|
||||
} Type;
|
||||
|
||||
// Light levels (intensities) - used to determine which light source should be active
|
||||
struct {
|
||||
uint8 Innate;
|
||||
uint8 Equipment;
|
||||
uint8 Spell;
|
||||
uint8 Active;
|
||||
} Level;
|
||||
};
|
||||
|
||||
#endif // #define __ITEM_H
|
||||
|
||||
@@ -185,7 +185,7 @@ struct Item_Struct {
|
||||
uint32 AugType;
|
||||
uint8 AugSlotType[EmuConstants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Type
|
||||
uint8 AugSlotVisible[EmuConstants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Visible
|
||||
uint8 AugSlotUnk2[EmuConstants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Unknown
|
||||
uint8 AugSlotUnk2[EmuConstants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Unknown Most likely Powersource related
|
||||
uint32 LDoNTheme;
|
||||
uint32 LDoNPrice;
|
||||
uint32 LDoNSold;
|
||||
|
||||
@@ -180,7 +180,7 @@ IN(OP_GMLastName, GMLastName_Struct);
|
||||
IN(OP_GMToggle, GMToggle_Struct);
|
||||
IN(OP_LFGCommand, LFG_Struct);
|
||||
IN(OP_GMGoto, GMSummon_Struct);
|
||||
IN(OP_TraderShop, TraderClick_Struct);
|
||||
INv(OP_TraderShop, TraderClick_Struct);
|
||||
IN(OP_ShopRequest, Merchant_Click_Struct);
|
||||
IN(OP_Bazaar, BazaarSearch_Struct);
|
||||
//alt:IN(OP_Bazaar, BazaarWelcome_Struct); //alternate structure for OP_Bazaar
|
||||
@@ -399,7 +399,7 @@ OUT(OP_Weather, Weather_Struct);
|
||||
OUT(OP_ZoneChange, ZoneChange_Struct);
|
||||
OUT(OP_ZoneInUnknown, ZoneInUnknown_Struct);
|
||||
|
||||
//this is the set of opcodes which are allready listed
|
||||
//this is the set of opcodes which are already listed
|
||||
//in the IN section above, but are also sent OUT
|
||||
#ifdef DISJOINT_DIRECTIONS
|
||||
OUTz(OP_ClientReady); //follows OP_SetServerFilter
|
||||
@@ -449,7 +449,7 @@ OUT(OP_Trader, TraderBuy_Struct); //3 possible lengths
|
||||
//alt:OUT(OP_Trader, Trader_ShowItems_Struct);
|
||||
//alt:OUT(OP_Trader, Trader_Struct);
|
||||
OUT(OP_TraderBuy, TraderBuy_Struct);
|
||||
OUT(OP_TraderShop, TraderClick_Struct);
|
||||
OUTv(OP_TraderShop, TraderClick_Struct);
|
||||
OUT(OP_WearChange, WearChange_Struct);
|
||||
OUT(OP_ZoneEntry, ServerZoneEntry_Struct);
|
||||
#endif
|
||||
|
||||
+258
-191
@@ -15,6 +15,8 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <numeric>
|
||||
#include <cassert>
|
||||
|
||||
namespace RoF
|
||||
{
|
||||
@@ -225,8 +227,8 @@ namespace RoF
|
||||
SETUP_DIRECT_ENCODE(Animation_Struct, structs::Animation_Struct);
|
||||
|
||||
OUT(spawnid);
|
||||
OUT(value);
|
||||
OUT(action);
|
||||
OUT(speed);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@@ -415,7 +417,7 @@ namespace RoF
|
||||
outapp->WriteUInt32(0); // Duration
|
||||
outapp->WriteUInt32(0); // ?
|
||||
outapp->WriteUInt8(0); // Caster name
|
||||
outapp->WriteUInt8(0); // Terminating byte
|
||||
outapp->WriteUInt8(0); // Type
|
||||
}
|
||||
FINISH_ENCODE();
|
||||
|
||||
@@ -452,7 +454,7 @@ namespace RoF
|
||||
__packet->WriteUInt32(emu->entries[i].num_hits); // Unknown
|
||||
__packet->WriteString("");
|
||||
}
|
||||
__packet->WriteUInt8(!emu->all_buffs); // Unknown
|
||||
__packet->WriteUInt8(emu->type); // Unknown
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@@ -477,7 +479,7 @@ namespace RoF
|
||||
eq->slot = 13;
|
||||
else
|
||||
OUT(slot);
|
||||
|
||||
|
||||
OUT(spell_id);
|
||||
eq->inventoryslot = ServerToRoFSlot(emu->inventoryslot);
|
||||
//OUT(inventoryslot);
|
||||
@@ -656,7 +658,9 @@ namespace RoF
|
||||
OUT(type);
|
||||
OUT(spellid);
|
||||
OUT(damage);
|
||||
eq->sequence = emu->sequence;
|
||||
OUT(force)
|
||||
OUT(meleepush_xy);
|
||||
OUT(meleepush_z)
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@@ -700,7 +704,7 @@ namespace RoF
|
||||
{
|
||||
SETUP_VAR_ENCODE(ExpeditionCompass_Struct);
|
||||
ALLOC_VAR_ENCODE(structs::ExpeditionCompass_Struct, sizeof(structs::ExpeditionInfo_Struct) + sizeof(structs::ExpeditionCompassEntry_Struct) * emu->count);
|
||||
|
||||
|
||||
OUT(count);
|
||||
|
||||
for (uint32 i = 0; i < emu->count; ++i)
|
||||
@@ -971,8 +975,8 @@ namespace RoF
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Same for all objects in the zone
|
||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->heading);
|
||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Normally 0, but seen (float)255.0 as well
|
||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Unknown
|
||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 1); // Need to add emu->size to struct
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->solidtype); // Unknown
|
||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->size != 0 && (float)emu->size < 5000.f ? (float)((float)emu->size / 100.0f) : 1.f ); // This appears to be the size field. Hackish logic because some PEQ DB items were corrupt.
|
||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y);
|
||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x);
|
||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->z);
|
||||
@@ -1247,7 +1251,7 @@ namespace RoF
|
||||
switch (emu_e->rank) {
|
||||
case 0: { e->rank = htonl(5); break; } // GUILD_MEMBER 0
|
||||
case 1: { e->rank = htonl(3); break; } // GUILD_OFFICER 1
|
||||
case 2: { e->rank = htonl(1); break; } // GUILD_LEADER 2
|
||||
case 2: { e->rank = htonl(1); break; } // GUILD_LEADER 2
|
||||
default: { e->rank = htonl(emu_e->rank); break; } // GUILD_NONE
|
||||
}
|
||||
|
||||
@@ -2043,7 +2047,7 @@ namespace RoF
|
||||
|
||||
for (int r = 0; r < 7; r++)
|
||||
{
|
||||
outapp->WriteUInt32(emu->item_tint[r].color);
|
||||
outapp->WriteUInt32(emu->item_tint[r].Color);
|
||||
}
|
||||
// Write zeroes for extra two tint values
|
||||
outapp->WriteUInt32(0);
|
||||
@@ -2053,7 +2057,7 @@ namespace RoF
|
||||
|
||||
for (int r = 0; r < 7; r++)
|
||||
{
|
||||
outapp->WriteUInt32(emu->item_tint[r].color);
|
||||
outapp->WriteUInt32(emu->item_tint[r].Color);
|
||||
}
|
||||
// Write zeroes for extra two tint values
|
||||
outapp->WriteUInt32(0);
|
||||
@@ -2116,7 +2120,7 @@ namespace RoF
|
||||
{
|
||||
outapp->WriteUInt32(emu->aa_array[r].AA);
|
||||
outapp->WriteUInt32(emu->aa_array[r].value);
|
||||
outapp->WriteUInt32(0);
|
||||
outapp->WriteUInt32(emu->aa_array[r].charges);
|
||||
}
|
||||
|
||||
// Fill the other 60 AAs with zeroes
|
||||
@@ -2286,46 +2290,52 @@ namespace RoF
|
||||
outapp->WriteUInt8(0); // Unknown
|
||||
outapp->WriteUInt8(0); // Unknown
|
||||
|
||||
outapp->WriteUInt32(structs::MAX_PLAYER_BANDOLIER);
|
||||
outapp->WriteUInt32(consts::BANDOLIERS_SIZE);
|
||||
|
||||
for (uint32 r = 0; r < EmuConstants::BANDOLIERS_COUNT; r++)
|
||||
{
|
||||
outapp->WriteString(emu->bandoliers[r].name);
|
||||
|
||||
for (uint32 j = 0; j < EmuConstants::BANDOLIER_SIZE; ++j)
|
||||
{
|
||||
outapp->WriteString(emu->bandoliers[r].items[j].item_name);
|
||||
outapp->WriteUInt32(emu->bandoliers[r].items[j].item_id);
|
||||
outapp->WriteUInt32(emu->bandoliers[r].items[j].icon);
|
||||
// Copy bandoliers where server and client indexes converge
|
||||
for (uint32 r = 0; r < EmuConstants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) {
|
||||
outapp->WriteString(emu->bandoliers[r].Name);
|
||||
for (uint32 j = 0; j < consts::BANDOLIER_ITEM_COUNT; ++j) { // Will need adjusting if 'server != client' is ever true
|
||||
outapp->WriteString(emu->bandoliers[r].Items[j].Name);
|
||||
outapp->WriteUInt32(emu->bandoliers[r].Items[j].ID);
|
||||
if (emu->bandoliers[r].Items[j].Icon) {
|
||||
outapp->WriteSInt32(emu->bandoliers[r].Items[j].Icon);
|
||||
}
|
||||
else {
|
||||
// If no icon, it must send -1 or Treasure Chest Icon (836) is displayed
|
||||
outapp->WriteSInt32(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32 r = 0; r < structs::MAX_PLAYER_BANDOLIER - EmuConstants::BANDOLIERS_COUNT; r++)
|
||||
{
|
||||
// Nullify bandoliers where server and client indexes diverge, with a client bias
|
||||
for (uint32 r = EmuConstants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) {
|
||||
outapp->WriteString("");
|
||||
|
||||
for (uint32 j = 0; j < EmuConstants::BANDOLIER_SIZE; ++j)
|
||||
{
|
||||
for (uint32 j = 0; j < consts::BANDOLIER_ITEM_COUNT; ++j) { // Will need adjusting if 'server != client' is ever true
|
||||
outapp->WriteString("");
|
||||
outapp->WriteUInt32(0);
|
||||
outapp->WriteUInt32(0);
|
||||
outapp->WriteSInt32(-1);
|
||||
}
|
||||
}
|
||||
|
||||
outapp->WriteUInt32(structs::MAX_POTIONS_IN_BELT);
|
||||
outapp->WriteUInt32(consts::POTION_BELT_ITEM_COUNT);
|
||||
|
||||
for (uint32 r = 0; r < EmuConstants::POTION_BELT_SIZE; r++)
|
||||
{
|
||||
outapp->WriteString(emu->potionbelt.items[r].item_name);
|
||||
outapp->WriteUInt32(emu->potionbelt.items[r].item_id);
|
||||
outapp->WriteUInt32(emu->potionbelt.items[r].icon);
|
||||
// Copy potion belt where server and client indexes converge
|
||||
for (uint32 r = 0; r < EmuConstants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) {
|
||||
outapp->WriteString(emu->potionbelt.Items[r].Name);
|
||||
outapp->WriteUInt32(emu->potionbelt.Items[r].ID);
|
||||
if (emu->potionbelt.Items[r].Icon) {
|
||||
outapp->WriteSInt32(emu->potionbelt.Items[r].Icon);
|
||||
}
|
||||
else {
|
||||
// If no icon, it must send -1 or Treasure Chest Icon (836) is displayed
|
||||
outapp->WriteSInt32(-1);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32 r = 0; r < structs::MAX_POTIONS_IN_BELT - EmuConstants::POTION_BELT_SIZE; r++)
|
||||
{
|
||||
// Nullify potion belt where server and client indexes diverge, with a client bias
|
||||
for (uint32 r = EmuConstants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) {
|
||||
outapp->WriteString("");
|
||||
outapp->WriteUInt32(0);
|
||||
outapp->WriteUInt32(0);
|
||||
outapp->WriteSInt32(-1);
|
||||
}
|
||||
|
||||
outapp->WriteSInt32(-1); // Unknown;
|
||||
@@ -2418,7 +2428,7 @@ namespace RoF
|
||||
outapp->WriteUInt32(emu->silver_bank);
|
||||
outapp->WriteUInt32(emu->copper_bank);
|
||||
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt32(emu->platinum_shared);
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
@@ -2808,9 +2818,9 @@ namespace RoF
|
||||
|
||||
for (uint32 i = 0; i < MAX_PP_AA_ARRAY; ++i)
|
||||
{
|
||||
eq->aa_list[i].aa_skill = emu->aa_list[i].aa_skill;
|
||||
eq->aa_list[i].aa_value = emu->aa_list[i].aa_value;
|
||||
eq->aa_list[i].unknown08 = emu->aa_list[i].unknown08;
|
||||
eq->aa_list[i].AA = emu->aa_list[i].AA;
|
||||
eq->aa_list[i].value = emu->aa_list[i].value;
|
||||
eq->aa_list[i].charges = emu->aa_list[i].charges;
|
||||
}
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -2842,7 +2852,7 @@ namespace RoF
|
||||
|
||||
// Check clientver field to verify this AA should be sent for SoF
|
||||
// clientver 1 is for all clients and 5 is for Live
|
||||
if (emu->clientver <= 5)
|
||||
if (emu->clientver <= 7)
|
||||
{
|
||||
OUT(id);
|
||||
eq->unknown004 = 1;
|
||||
@@ -2858,9 +2868,9 @@ namespace RoF
|
||||
OUT(cost);
|
||||
OUT(seq);
|
||||
OUT(current_level);
|
||||
eq->unknown037 = 1; // Introduced during HoT
|
||||
eq->prereq_skill_count = 1; // min 1
|
||||
OUT(prereq_skill);
|
||||
eq->unknown045 = 1; // New Mar 21 2012 - Seen 1
|
||||
eq->prereq_minpoints_count = 1; // min 1
|
||||
OUT(prereq_minpoints);
|
||||
eq->type = emu->sof_type;
|
||||
OUT(spellid);
|
||||
@@ -2876,6 +2886,7 @@ namespace RoF
|
||||
OUT(cost2);
|
||||
eq->aa_expansion = emu->aa_expansion;
|
||||
eq->special_category = emu->special_category;
|
||||
eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number
|
||||
OUT(total_abilities);
|
||||
unsigned int r;
|
||||
for (r = 0; r < emu->total_abilities; r++) {
|
||||
@@ -2891,85 +2902,100 @@ namespace RoF
|
||||
|
||||
ENCODE(OP_SendCharInfo)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(CharacterSelect_Struct);
|
||||
ENCODE_LENGTH_ATLEAST(CharacterSelect_Struct);
|
||||
SETUP_VAR_ENCODE(CharacterSelect_Struct);
|
||||
|
||||
//EQApplicationPacket *packet = *p;
|
||||
//const CharacterSelect_Struct *emu = (CharacterSelect_Struct *) packet->pBuffer;
|
||||
// Zero-character count shunt
|
||||
if (emu->CharCount == 0) {
|
||||
ALLOC_VAR_ENCODE(structs::CharacterSelect_Struct, sizeof(structs::CharacterSelect_Struct));
|
||||
eq->CharCount = emu->CharCount;
|
||||
|
||||
int char_count;
|
||||
int namelen = 0;
|
||||
for (char_count = 0; char_count < 10; char_count++) {
|
||||
if (emu->name[char_count][0] == '\0')
|
||||
break;
|
||||
if (strcmp(emu->name[char_count], "<none>") == 0)
|
||||
break;
|
||||
namelen += strlen(emu->name[char_count]);
|
||||
FINISH_ENCODE();
|
||||
return;
|
||||
}
|
||||
|
||||
int total_length = sizeof(structs::CharacterSelect_Struct)
|
||||
+ char_count * sizeof(structs::CharacterSelectEntry_Struct)
|
||||
+ namelen;
|
||||
unsigned char *emu_ptr = __emu_buffer;
|
||||
emu_ptr += sizeof(CharacterSelect_Struct);
|
||||
CharacterSelectEntry_Struct *emu_cse = (CharacterSelectEntry_Struct *)nullptr;
|
||||
|
||||
size_t names_length = 0;
|
||||
size_t character_count = 0;
|
||||
for (; character_count < emu->CharCount && character_count < consts::CHARACTER_CREATION_LIMIT; ++character_count) {
|
||||
emu_cse = (CharacterSelectEntry_Struct *)emu_ptr;
|
||||
names_length += strlen(emu_cse->Name);
|
||||
emu_ptr += sizeof(CharacterSelectEntry_Struct);
|
||||
}
|
||||
|
||||
size_t total_length = sizeof(structs::CharacterSelect_Struct)
|
||||
+ character_count * sizeof(structs::CharacterSelectEntry_Struct)
|
||||
+ names_length;
|
||||
|
||||
ALLOC_VAR_ENCODE(structs::CharacterSelect_Struct, total_length);
|
||||
structs::CharacterSelectEntry_Struct *eq_cse = (structs::CharacterSelectEntry_Struct *)nullptr;
|
||||
|
||||
//unsigned char *eq_buffer = new unsigned char[total_length];
|
||||
//structs::CharacterSelect_Struct *eq_head = (structs::CharacterSelect_Struct *) eq_buffer;
|
||||
eq->CharCount = character_count;
|
||||
//eq->TotalChars = emu->TotalChars;
|
||||
|
||||
eq->char_count = char_count;
|
||||
//eq->total_chars = 10;
|
||||
//if (eq->TotalChars > consts::CHARACTER_CREATION_LIMIT)
|
||||
// eq->TotalChars = consts::CHARACTER_CREATION_LIMIT;
|
||||
|
||||
unsigned char *bufptr = (unsigned char *)eq->entries;
|
||||
int r;
|
||||
for (r = 0; r < char_count; r++) {
|
||||
{ //pre-name section...
|
||||
structs::CharacterSelectEntry_Struct *eq2 = (structs::CharacterSelectEntry_Struct *) bufptr;
|
||||
memcpy(eq2->name, emu->name[r], strlen(emu->name[r]) + 1);
|
||||
emu_ptr = __emu_buffer;
|
||||
emu_ptr += sizeof(CharacterSelect_Struct);
|
||||
|
||||
unsigned char *eq_ptr = __packet->pBuffer;
|
||||
eq_ptr += sizeof(structs::CharacterSelect_Struct);
|
||||
|
||||
for (int counter = 0; counter < character_count; ++counter) {
|
||||
emu_cse = (CharacterSelectEntry_Struct *)emu_ptr;
|
||||
eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // base address
|
||||
|
||||
strcpy(eq_cse->Name, emu_cse->Name);
|
||||
eq_ptr += strlen(emu_cse->Name);
|
||||
eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // offset address (base + name length offset)
|
||||
eq_cse->Name[0] = '\0'; // (offset)eq_cse->Name[0] = (base)eq_cse->Name[strlen(emu_cse->Name)]
|
||||
|
||||
eq_cse->Class = emu_cse->Class;
|
||||
eq_cse->Race = emu_cse->Race;
|
||||
eq_cse->Level = emu_cse->Level;
|
||||
eq_cse->ShroudClass = emu_cse->ShroudClass;
|
||||
eq_cse->ShroudRace = emu_cse->ShroudRace;
|
||||
eq_cse->Zone = emu_cse->Zone;
|
||||
eq_cse->Instance = emu_cse->Instance;
|
||||
eq_cse->Gender = emu_cse->Gender;
|
||||
eq_cse->Face = emu_cse->Face;
|
||||
|
||||
for (int equip_index = 0; equip_index < _MaterialCount; equip_index++) {
|
||||
eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material;
|
||||
eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1;
|
||||
eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial;
|
||||
eq_cse->Equip[equip_index].HeroForgeModel = emu_cse->Equip[equip_index].HeroForgeModel;
|
||||
eq_cse->Equip[equip_index].Material2 = emu_cse->Equip[equip_index].Material2;
|
||||
eq_cse->Equip[equip_index].Color.Color = emu_cse->Equip[equip_index].Color.Color;
|
||||
}
|
||||
//adjust for name.
|
||||
bufptr += strlen(emu->name[r]);
|
||||
{ //post-name section...
|
||||
structs::CharacterSelectEntry_Struct *eq2 = (structs::CharacterSelectEntry_Struct *) bufptr;
|
||||
eq2->class_ = emu->class_[r];
|
||||
eq2->race = emu->race[r];
|
||||
eq2->level = emu->level[r];
|
||||
eq2->class_2 = emu->class_[r];
|
||||
eq2->race2 = emu->race[r];
|
||||
eq2->zone = emu->zone[r];
|
||||
eq2->instance = 0;
|
||||
eq2->gender = emu->gender[r];
|
||||
eq2->face = emu->face[r];
|
||||
int k;
|
||||
for (k = 0; k < _MaterialCount; k++) {
|
||||
eq2->equip[k].material = emu->equip[r][k].material;
|
||||
eq2->equip[k].unknown1 = emu->equip[r][k].unknown1;
|
||||
eq2->equip[k].elitematerial = emu->equip[r][k].elitematerial;
|
||||
eq2->equip[k].heroforgemodel = emu->equip[r][k].heroforgemodel;
|
||||
eq2->equip[k].material2 = emu->equip[r][k].material2;
|
||||
eq2->equip[k].color.color = emu->equip[r][k].color.color;
|
||||
}
|
||||
eq2->u15 = 0xff;
|
||||
eq2->u19 = 0xFF;
|
||||
eq2->drakkin_tattoo = emu->drakkin_tattoo[r];
|
||||
eq2->drakkin_details = emu->drakkin_details[r];
|
||||
eq2->deity = emu->deity[r];
|
||||
eq2->primary = emu->primary[r];
|
||||
eq2->secondary = emu->secondary[r];
|
||||
eq2->haircolor = emu->haircolor[r];
|
||||
eq2->beardcolor = emu->beardcolor[r];
|
||||
eq2->eyecolor1 = emu->eyecolor1[r];
|
||||
eq2->eyecolor2 = emu->eyecolor2[r];
|
||||
eq2->hairstyle = emu->hairstyle[r];
|
||||
eq2->beard = emu->beard[r];
|
||||
eq2->char_enabled = 1;
|
||||
eq2->tutorial = emu->tutorial[r];
|
||||
eq2->drakkin_heritage = emu->drakkin_heritage[r];
|
||||
eq2->unknown1 = 0;
|
||||
eq2->gohome = emu->gohome[r];
|
||||
eq2->LastLogin = 1212696584;
|
||||
eq2->unknown2 = 0;
|
||||
}
|
||||
bufptr += sizeof(structs::CharacterSelectEntry_Struct);
|
||||
|
||||
eq_cse->Unknown15 = emu_cse->Unknown15;
|
||||
eq_cse->Unknown19 = emu_cse->Unknown19;
|
||||
eq_cse->DrakkinTattoo = emu_cse->DrakkinTattoo;
|
||||
eq_cse->DrakkinDetails = emu_cse->DrakkinDetails;
|
||||
eq_cse->Deity = emu_cse->Deity;
|
||||
eq_cse->PrimaryIDFile = emu_cse->PrimaryIDFile;
|
||||
eq_cse->SecondaryIDFile = emu_cse->SecondaryIDFile;
|
||||
eq_cse->HairColor = emu_cse->HairColor;
|
||||
eq_cse->BeardColor = emu_cse->BeardColor;
|
||||
eq_cse->EyeColor1 = emu_cse->EyeColor1;
|
||||
eq_cse->EyeColor2 = emu_cse->EyeColor2;
|
||||
eq_cse->HairStyle = emu_cse->HairStyle;
|
||||
eq_cse->Beard = emu_cse->Beard;
|
||||
eq_cse->GoHome = emu_cse->GoHome;
|
||||
eq_cse->Tutorial = emu_cse->Tutorial;
|
||||
eq_cse->DrakkinHeritage = emu_cse->DrakkinHeritage;
|
||||
eq_cse->Unknown1 = emu_cse->Unknown1;
|
||||
eq_cse->Enabled = emu_cse->Enabled;
|
||||
eq_cse->LastLogin = emu_cse->LastLogin;
|
||||
eq_cse->Unknown2 = emu_cse->Unknown2;
|
||||
|
||||
emu_ptr += sizeof(CharacterSelectEntry_Struct);
|
||||
eq_ptr += sizeof(structs::CharacterSelectEntry_Struct);
|
||||
}
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -3024,7 +3050,7 @@ namespace RoF
|
||||
switch (emu->Rank) {
|
||||
case 0: { eq->Rank = 5; break; } // GUILD_MEMBER 0
|
||||
case 1: { eq->Rank = 3; break; } // GUILD_OFFICER 1
|
||||
case 2: { eq->Rank = 1; break; } // GUILD_LEADER 2
|
||||
case 2: { eq->Rank = 1; break; } // GUILD_LEADER 2
|
||||
default: { eq->Rank = emu->Rank; break; }
|
||||
}
|
||||
|
||||
@@ -3291,7 +3317,7 @@ namespace RoF
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
|
||||
|
||||
#if 0 // original code
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
@@ -3588,37 +3614,71 @@ namespace RoF
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_VetClaimReply)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(VeteranClaim);
|
||||
SETUP_DIRECT_ENCODE(VeteranClaim, structs::VeteranClaim);
|
||||
|
||||
memcpy(eq->name, emu->name, sizeof(emu->name));
|
||||
OUT(claim_id);
|
||||
OUT(action);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_VetRewardsAvaliable)
|
||||
{
|
||||
EQApplicationPacket *inapp = *p;
|
||||
unsigned char * __emu_buffer = inapp->pBuffer;
|
||||
auto __emu_buffer = inapp->pBuffer;
|
||||
|
||||
uint32 count = ((*p)->Size() / sizeof(InternalVeteranReward));
|
||||
*p = nullptr;
|
||||
|
||||
EQApplicationPacket *outapp_create = new EQApplicationPacket(OP_VetRewardsAvaliable, (sizeof(structs::VeteranReward)*count));
|
||||
uchar *old_data = __emu_buffer;
|
||||
uchar *data = outapp_create->pBuffer;
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
{
|
||||
structs::VeteranReward *vr = (structs::VeteranReward*)data;
|
||||
InternalVeteranReward *ivr = (InternalVeteranReward*)old_data;
|
||||
// calculate size of names, note the packet DOES NOT have null termed c-strings
|
||||
std::vector<uint32> name_lengths;
|
||||
for (int i = 0; i < count; ++i) {
|
||||
InternalVeteranReward *ivr = (InternalVeteranReward *)__emu_buffer;
|
||||
|
||||
vr->claim_count = ivr->claim_count;
|
||||
vr->claim_id = ivr->claim_id;
|
||||
vr->number_available = ivr->number_available;
|
||||
for (int x = 0; x < 8; ++x)
|
||||
{
|
||||
vr->items[x].item_id = ivr->items[x].item_id;
|
||||
strncpy(vr->items[x].item_name, ivr->items[x].item_name, sizeof(vr->items[x].item_name));
|
||||
vr->items[x].charges = ivr->items[x].charges;
|
||||
for (int i = 0; i < ivr->claim_count; i++) {
|
||||
uint32 length = strnlen(ivr->items[i].item_name, 63);
|
||||
if (length)
|
||||
name_lengths.push_back(length);
|
||||
}
|
||||
|
||||
old_data += sizeof(InternalVeteranReward);
|
||||
data += sizeof(structs::VeteranReward);
|
||||
__emu_buffer += sizeof(InternalVeteranReward);
|
||||
}
|
||||
|
||||
dest->FastQueuePacket(&outapp_create);
|
||||
uint32 packet_size = std::accumulate(name_lengths.begin(), name_lengths.end(), 0) +
|
||||
sizeof(structs::VeteranReward) + (sizeof(structs::VeteranRewardEntry) * count) +
|
||||
// size of name_lengths is the same as item count
|
||||
(sizeof(structs::VeteranRewardItem) * name_lengths.size());
|
||||
|
||||
// build packet now!
|
||||
auto outapp = new EQApplicationPacket(OP_VetRewardsAvaliable, packet_size);
|
||||
__emu_buffer = inapp->pBuffer;
|
||||
|
||||
outapp->WriteUInt32(count);
|
||||
auto name_itr = name_lengths.begin();
|
||||
for (int i = 0; i < count; i++) {
|
||||
InternalVeteranReward *ivr = (InternalVeteranReward *)__emu_buffer;
|
||||
|
||||
outapp->WriteUInt32(ivr->claim_id);
|
||||
outapp->WriteUInt32(ivr->number_available);
|
||||
outapp->WriteUInt32(ivr->claim_count);
|
||||
outapp->WriteUInt8(1); // enabled
|
||||
|
||||
for (int j = 0; j < ivr->claim_count; j++) {
|
||||
assert(name_itr != name_lengths.end()); // the way it's written, it should never happen, so just assert
|
||||
outapp->WriteUInt32(*name_itr);
|
||||
outapp->WriteData(ivr->items[j].item_name, *name_itr);
|
||||
outapp->WriteUInt32(ivr->items[j].item_id);
|
||||
outapp->WriteUInt32(ivr->items[j].charges);
|
||||
++name_itr;
|
||||
}
|
||||
|
||||
__emu_buffer += sizeof(InternalVeteranReward);
|
||||
}
|
||||
|
||||
dest->FastQueuePacket(&outapp);
|
||||
delete inapp;
|
||||
}
|
||||
|
||||
@@ -3633,7 +3693,7 @@ namespace RoF
|
||||
OUT(elite_material);
|
||||
OUT(hero_forge_model);
|
||||
OUT(unknown18);
|
||||
OUT(color.color);
|
||||
OUT(color.Color);
|
||||
OUT(wear_slot_id);
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -3721,45 +3781,26 @@ namespace RoF
|
||||
}
|
||||
|
||||
ENCODE(OP_ZoneEntry) { ENCODE_FORWARD(OP_ZoneSpawns); }
|
||||
|
||||
|
||||
ENCODE(OP_ZonePlayerToBind)
|
||||
{
|
||||
ENCODE_LENGTH_ATLEAST(ZonePlayerToBind_Struct);
|
||||
SETUP_VAR_ENCODE(ZonePlayerToBind_Struct);
|
||||
ALLOC_LEN_ENCODE(sizeof(structs::ZonePlayerToBind_Struct) + strlen(emu->zone_name));
|
||||
|
||||
ZonePlayerToBind_Struct *zps = (ZonePlayerToBind_Struct*)(*p)->pBuffer;
|
||||
__packet->SetWritePosition(0);
|
||||
__packet->WriteUInt16(emu->bind_zone_id);
|
||||
__packet->WriteUInt16(emu->bind_instance_id);
|
||||
__packet->WriteFloat(emu->x);
|
||||
__packet->WriteFloat(emu->y);
|
||||
__packet->WriteFloat(emu->z);
|
||||
__packet->WriteFloat(emu->heading);
|
||||
__packet->WriteString(emu->zone_name);
|
||||
__packet->WriteUInt8(1); // save items
|
||||
__packet->WriteUInt32(0); // hp
|
||||
__packet->WriteUInt32(0); // mana
|
||||
__packet->WriteUInt32(0); // endurance
|
||||
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
||||
|
||||
unsigned char *buffer1 = new unsigned char[sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name)];
|
||||
structs::ZonePlayerToBindHeader_Struct *zph = (structs::ZonePlayerToBindHeader_Struct*)buffer1;
|
||||
unsigned char *buffer2 = new unsigned char[sizeof(structs::ZonePlayerToBindFooter_Struct)];
|
||||
structs::ZonePlayerToBindFooter_Struct *zpf = (structs::ZonePlayerToBindFooter_Struct*)buffer2;
|
||||
|
||||
zph->x = zps->x;
|
||||
zph->y = zps->y;
|
||||
zph->z = zps->z;
|
||||
zph->heading = zps->heading;
|
||||
zph->bind_zone_id = 0;
|
||||
zph->bind_instance_id = zps->bind_instance_id;
|
||||
strncpy(zph->zone_name, zps->zone_name, sizeof(zph->zone_name));
|
||||
|
||||
zpf->unknown021 = 1;
|
||||
zpf->unknown022 = 0;
|
||||
zpf->unknown023 = 0;
|
||||
zpf->unknown024 = 0;
|
||||
|
||||
ss.write((const char*)buffer1, (sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name)));
|
||||
ss.write((const char*)buffer2, sizeof(structs::ZonePlayerToBindFooter_Struct));
|
||||
|
||||
delete[] buffer1;
|
||||
delete[] buffer2;
|
||||
delete[](*p)->pBuffer;
|
||||
|
||||
(*p)->pBuffer = new unsigned char[ss.str().size()];
|
||||
(*p)->size = ss.str().size();
|
||||
|
||||
memcpy((*p)->pBuffer, ss.str().c_str(), ss.str().size());
|
||||
dest->FastQueuePacket(&(*p));
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ZoneServerInfo)
|
||||
@@ -3807,8 +3848,8 @@ namespace RoF
|
||||
PacketSize += strlen(emu->name);
|
||||
PacketSize += strlen(emu->lastName);
|
||||
|
||||
emu->title[0] = 0;
|
||||
emu->suffix[0] = 0;
|
||||
emu->title[31] = 0;
|
||||
emu->suffix[31] = 0;
|
||||
|
||||
if (strlen(emu->title))
|
||||
PacketSize += strlen(emu->title) + 1;
|
||||
@@ -3931,8 +3972,8 @@ namespace RoF
|
||||
switch (emu->guildrank) {
|
||||
case 0: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 5); break; } // GUILD_MEMBER 0
|
||||
case 1: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 3); break; } // GUILD_OFFICER 1
|
||||
case 2: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); break; } // GUILD_LEADER 2
|
||||
default: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildrank); break; } //
|
||||
case 2: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); break; } // GUILD_LEADER 2
|
||||
default: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildrank); break; } //
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3951,7 +3992,7 @@ namespace RoF
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->petOwnerId);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown13
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown14 - Stance 64 = normal 4 = aggressive 40 = stun/mezzed
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->PlayerState);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown15
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown16
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown17
|
||||
@@ -3963,18 +4004,18 @@ namespace RoF
|
||||
for (k = 0; k < 9; ++k)
|
||||
{
|
||||
{
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->colors[k].color);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->colors[k].Color);
|
||||
}
|
||||
}
|
||||
|
||||
structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer;
|
||||
|
||||
for (k = 0; k < 9; k++) {
|
||||
Equipment[k].material = emu->equipment[k].material;
|
||||
Equipment[k].unknown1 = emu->equipment[k].unknown1;
|
||||
Equipment[k].elitematerial = emu->equipment[k].elitematerial;
|
||||
Equipment[k].heroforgemodel = emu->equipment[k].heroforgemodel;
|
||||
Equipment[k].material2 = emu->equipment[k].material2;
|
||||
Equipment[k].Material = emu->equipment[k].Material;
|
||||
Equipment[k].Unknown1 = emu->equipment[k].Unknown1;
|
||||
Equipment[k].EliteMaterial = emu->equipment[k].EliteMaterial;
|
||||
Equipment[k].HeroForgeModel = emu->equipment[k].HeroForgeModel;
|
||||
Equipment[k].Material2 = emu->equipment[k].Material2;
|
||||
}
|
||||
|
||||
Buffer += (sizeof(structs::EquipStruct) * 9);
|
||||
@@ -3987,13 +4028,13 @@ namespace RoF
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].material);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].Material);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].material);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].Material);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
@@ -4081,6 +4122,18 @@ namespace RoF
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_Animation)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::Animation_Struct);
|
||||
SETUP_DIRECT_DECODE(Animation_Struct, structs::Animation_Struct);
|
||||
|
||||
IN(spawnid);
|
||||
IN(action);
|
||||
IN(speed);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_ApplyPoison)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::ApplyPoison_Struct);
|
||||
@@ -4193,12 +4246,16 @@ namespace RoF
|
||||
emu->slot = 10;
|
||||
else
|
||||
IN(slot);
|
||||
|
||||
|
||||
IN(spell_id);
|
||||
emu->inventoryslot = RoFToServerSlot(eq->inventoryslot);
|
||||
//IN(inventoryslot);
|
||||
IN(target_id);
|
||||
|
||||
IN(y_pos);
|
||||
IN(x_pos);
|
||||
IN(z_pos);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
@@ -4336,7 +4393,7 @@ namespace RoF
|
||||
IN(type);
|
||||
IN(spellid);
|
||||
IN(damage);
|
||||
emu->sequence = eq->sequence;
|
||||
IN(meleepush_xy);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@@ -4664,7 +4721,7 @@ namespace RoF
|
||||
SETUP_DIRECT_DECODE(PetCommand_Struct, structs::PetCommand_Struct);
|
||||
|
||||
IN(command);
|
||||
emu->unknown = eq->unknown04;
|
||||
IN(target);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@@ -4888,7 +4945,7 @@ namespace RoF
|
||||
slot_id = legacy::SLOT_TRADESKILL; // 1000
|
||||
}
|
||||
emu->container_slot = slot_id;
|
||||
emu->guildtribute_slot = RoFToServerSlot(eq->guildtribute_slot); // this should only return INVALID_INDEX until implemented -U
|
||||
emu->guildtribute_slot = RoFToServerSlot(eq->guildtribute_slot); // this should only return INVALID_INDEX until implemented
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@@ -4923,6 +4980,16 @@ namespace RoF
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_VetClaimRequest)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::VeteranClaim);
|
||||
SETUP_DIRECT_DECODE(VeteranClaim, structs::VeteranClaim);
|
||||
|
||||
IN(claim_id);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_ZoneChange)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::ZoneChange_Struct);
|
||||
@@ -4983,7 +5050,7 @@ namespace RoF
|
||||
|
||||
//sprintf(hdr.unknown000, "06e0002Y1W00");
|
||||
|
||||
snprintf(hdr.unknown000, sizeof(hdr.unknown000), "%012d", item->ID);
|
||||
snprintf(hdr.unknown000, sizeof(hdr.unknown000), "%016d", item->ID);
|
||||
|
||||
hdr.stacksize = stackable ? charges : 1;
|
||||
hdr.unknown004 = 0;
|
||||
@@ -5054,7 +5121,7 @@ namespace RoF
|
||||
hdrf.ItemClass = item->ItemClass;
|
||||
|
||||
ss.write((const char*)&hdrf, sizeof(RoF::structs::ItemSerializationHeaderFinish));
|
||||
|
||||
|
||||
if (strlen(item->Name) > 0)
|
||||
{
|
||||
ss.write(item->Name, strlen(item->Name));
|
||||
|
||||
+418
-219
File diff suppressed because it is too large
Load Diff
@@ -103,6 +103,8 @@ namespace RoF2 {
|
||||
}
|
||||
|
||||
namespace consts {
|
||||
static const size_t CHARACTER_CREATION_LIMIT = 12;
|
||||
|
||||
static const uint16 MAP_POSSESSIONS_SIZE = slots::_MainCount;
|
||||
static const uint16 MAP_BANK_SIZE = 24;
|
||||
static const uint16 MAP_SHARED_BANK_SIZE = 2;
|
||||
@@ -178,9 +180,10 @@ namespace RoF2 {
|
||||
static const uint16 ITEM_COMMON_SIZE = 6;
|
||||
static const uint16 ITEM_CONTAINER_SIZE = 255; // 255; (server max will be 255..unsure what actual client is - test)
|
||||
|
||||
static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances
|
||||
static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance
|
||||
static const uint32 POTION_BELT_SIZE = 5;
|
||||
static const size_t BANDOLIERS_SIZE = 20; // number of bandolier instances
|
||||
static const size_t BANDOLIER_ITEM_COUNT = 4; // number of equipment slots in bandolier instance
|
||||
|
||||
static const size_t POTION_BELT_ITEM_COUNT = 5;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 56;
|
||||
}
|
||||
|
||||
@@ -2,10 +2,14 @@
|
||||
// Begin RoF2 Encodes
|
||||
|
||||
E(OP_SendMembershipDetails)
|
||||
E(OP_TraderShop)
|
||||
E(OP_TraderDelItem)
|
||||
|
||||
// incoming packets that require a DECODE translation:
|
||||
// Begin RoF2 Decodes
|
||||
|
||||
D(OP_TraderShop)
|
||||
|
||||
// End RoF2 Encodes/Decodes
|
||||
|
||||
// These require Encodes/Decodes for RoF, so they do for RoF2 as well
|
||||
@@ -107,6 +111,7 @@ E(OP_Trader)
|
||||
E(OP_TraderBuy)
|
||||
E(OP_TributeInfo)
|
||||
E(OP_TributeItem)
|
||||
E(OP_VetClaimReply)
|
||||
E(OP_VetRewardsAvaliable)
|
||||
E(OP_WearChange)
|
||||
E(OP_WhoAllResponse)
|
||||
@@ -119,6 +124,7 @@ E(OP_ZoneSpawns)
|
||||
D(OP_AdventureMerchantSell)
|
||||
D(OP_AltCurrencySell)
|
||||
D(OP_AltCurrencySellSelection)
|
||||
D(OP_Animation)
|
||||
D(OP_ApplyPoison)
|
||||
D(OP_AugmentInfo)
|
||||
D(OP_AugmentItem)
|
||||
@@ -170,6 +176,7 @@ D(OP_Trader)
|
||||
D(OP_TraderBuy)
|
||||
D(OP_TradeSkillCombine)
|
||||
D(OP_TributeItem)
|
||||
D(OP_VetClaimRequest)
|
||||
D(OP_WhoAllRequest)
|
||||
D(OP_ZoneChange)
|
||||
D(OP_ZoneEntry)
|
||||
|
||||
+247
-178
@@ -97,11 +97,6 @@ static const uint32 MAX_PLAYER_TRIBUTES = 5;
|
||||
static const uint32 MAX_TRIBUTE_TIERS = 10;
|
||||
static const uint32 TRIBUTE_NONE = 0xFFFFFFFF;
|
||||
|
||||
static const uint32 MAX_PLAYER_BANDOLIER = 20;
|
||||
static const uint32 MAX_PLAYER_BANDOLIER_ITEMS = 4;
|
||||
|
||||
static const uint32 MAX_POTIONS_IN_BELT = 5;
|
||||
|
||||
static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16;
|
||||
static const uint32 MAX_RAID_LEADERSHIP_AA_ARRAY = 16;
|
||||
static const uint32 MAX_LEADERSHIP_AA_ARRAY = (MAX_GROUP_LEADERSHIP_AA_ARRAY+MAX_RAID_LEADERSHIP_AA_ARRAY);
|
||||
@@ -114,7 +109,7 @@ static const uint32 MAX_PP_SPELLBOOK = 720; // was 480
|
||||
static const uint32 MAX_PP_MEMSPELL = 16; // was 12
|
||||
static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size
|
||||
static const uint32 MAX_PP_AA_ARRAY = 300;
|
||||
static const uint32 MAX_PP_DISCIPLINES = 200; // was 100
|
||||
static const uint32 MAX_PP_DISCIPLINES = 300; // was 200
|
||||
static const uint32 MAX_GROUP_MEMBERS = 6;
|
||||
static const uint32 MAX_RECAST_TYPES = 20;
|
||||
|
||||
@@ -147,84 +142,87 @@ struct AdventureInfo {
|
||||
*/
|
||||
struct Color_Struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8 blue;
|
||||
uint8 green;
|
||||
uint8 red;
|
||||
uint8 use_tint; // if there's a tint this is FF
|
||||
} rgb;
|
||||
uint32 color;
|
||||
union {
|
||||
struct {
|
||||
uint8 Blue;
|
||||
uint8 Green;
|
||||
uint8 Red;
|
||||
uint8 UseTint; // if there's a tint this is FF
|
||||
} RGB;
|
||||
uint32 Color;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Visible equiptment.
|
||||
* Size: 20 Octets
|
||||
*/
|
||||
struct EquipStruct {
|
||||
/*00*/ uint32 material;
|
||||
/*04*/ uint32 unknown1;
|
||||
/*08*/ uint32 elitematerial;
|
||||
/*12*/ uint32 heroforgemodel;
|
||||
/*16*/ uint32 material2; // Same as material?
|
||||
/*20*/
|
||||
struct CharSelectEquip
|
||||
{
|
||||
uint32 Material;
|
||||
uint32 Unknown1;
|
||||
uint32 EliteMaterial;
|
||||
uint32 HeroForgeModel;
|
||||
uint32 Material2;
|
||||
Color_Struct Color;
|
||||
};
|
||||
|
||||
struct CharSelectEquip {
|
||||
uint32 material;
|
||||
uint32 unknown1;
|
||||
uint32 elitematerial;
|
||||
uint32 heroforgemodel;
|
||||
uint32 material2;
|
||||
Color_Struct color;
|
||||
};
|
||||
|
||||
struct CharacterSelectEntry_Struct {
|
||||
/*0000*/ char name[1]; // Name null terminated
|
||||
/*0000*/ uint8 class_;
|
||||
/*0000*/ uint32 race;
|
||||
/*0000*/ uint8 level;
|
||||
/*0000*/ uint8 class_2;
|
||||
/*0000*/ uint32 race2;
|
||||
/*0000*/ uint16 zone;
|
||||
/*0000*/ uint16 instance;
|
||||
/*0000*/ uint8 gender;
|
||||
/*0000*/ uint8 face;
|
||||
/*0000*/ CharSelectEquip equip[9];
|
||||
/*0000*/ uint8 u15; // Seen FF
|
||||
/*0000*/ uint8 u19; // Seen FF
|
||||
/*0000*/ uint32 drakkin_tattoo;
|
||||
/*0000*/ uint32 drakkin_details;
|
||||
/*0000*/ uint32 deity;
|
||||
/*0000*/ uint32 primary;
|
||||
/*0000*/ uint32 secondary;
|
||||
/*0000*/ uint8 haircolor;
|
||||
/*0000*/ uint8 beardcolor;
|
||||
/*0000*/ uint8 eyecolor1;
|
||||
/*0000*/ uint8 eyecolor2;
|
||||
/*0000*/ uint8 hairstyle;
|
||||
/*0000*/ uint8 beard;
|
||||
/*0000*/ uint8 char_enabled;
|
||||
/*0000*/ uint8 tutorial; // Seen 1 for new char or 0 for existing
|
||||
/*0000*/ uint32 drakkin_heritage;
|
||||
/*0000*/ uint8 unknown1; // Seen 0
|
||||
/*0000*/ uint8 gohome; // Seen 0 for new char and 1 for existing
|
||||
struct CharacterSelectEntry_Struct
|
||||
{
|
||||
/*0000*/ char Name[1]; // Name null terminated
|
||||
/*0000*/ uint8 Class;
|
||||
/*0000*/ uint32 Race;
|
||||
/*0000*/ uint8 Level;
|
||||
/*0000*/ uint8 ShroudClass;
|
||||
/*0000*/ uint32 ShroudRace;
|
||||
/*0000*/ uint16 Zone;
|
||||
/*0000*/ uint16 Instance;
|
||||
/*0000*/ uint8 Gender;
|
||||
/*0000*/ uint8 Face;
|
||||
/*0000*/ CharSelectEquip Equip[9];
|
||||
/*0000*/ uint8 Unknown15; // Seen FF
|
||||
/*0000*/ uint8 Unknown19; // Seen FF
|
||||
/*0000*/ uint32 DrakkinTattoo;
|
||||
/*0000*/ uint32 DrakkinDetails;
|
||||
/*0000*/ uint32 Deity;
|
||||
/*0000*/ uint32 PrimaryIDFile;
|
||||
/*0000*/ uint32 SecondaryIDFile;
|
||||
/*0000*/ uint8 HairColor;
|
||||
/*0000*/ uint8 BeardColor;
|
||||
/*0000*/ uint8 EyeColor1;
|
||||
/*0000*/ uint8 EyeColor2;
|
||||
/*0000*/ uint8 HairStyle;
|
||||
/*0000*/ uint8 Beard;
|
||||
/*0000*/ uint8 GoHome; // Seen 0 for new char and 1 for existing
|
||||
/*0000*/ uint8 Tutorial; // Seen 1 for new char or 0 for existing
|
||||
/*0000*/ uint32 DrakkinHeritage;
|
||||
/*0000*/ uint8 Unknown1; // Seen 0
|
||||
/*0000*/ uint8 Enabled; // Swapped position with 'GoHome' 02/23/2015
|
||||
/*0000*/ uint32 LastLogin;
|
||||
/*0000*/ uint8 unknown2; // Seen 0
|
||||
/*0000*/ uint8 Unknown2; // Seen 0
|
||||
};
|
||||
|
||||
/*
|
||||
** Character Selection Struct
|
||||
**
|
||||
*/
|
||||
struct CharacterSelect_Struct {
|
||||
/*000*/ uint32 char_count; //number of chars in this packet
|
||||
/*004*/ CharacterSelectEntry_Struct entries[0];
|
||||
struct CharacterSelect_Struct
|
||||
{
|
||||
/*000*/ uint32 CharCount; //number of chars in this packet
|
||||
/*004*/ CharacterSelectEntry_Struct Entries[0];
|
||||
};
|
||||
|
||||
/*
|
||||
* Visible equiptment.
|
||||
* Size: 20 Octets
|
||||
*/
|
||||
struct EquipStruct
|
||||
{
|
||||
/*00*/ uint32 Material;
|
||||
/*04*/ uint32 Unknown1;
|
||||
/*08*/ uint32 EliteMaterial;
|
||||
/*12*/ uint32 HeroForgeModel;
|
||||
/*16*/ uint32 Material2; // Same as material?
|
||||
/*20*/
|
||||
};
|
||||
|
||||
|
||||
struct Membership_Entry_Struct
|
||||
{
|
||||
/*000*/ uint32 purchase_id; // Seen 1, then increments 90287 to 90300
|
||||
@@ -418,7 +416,7 @@ struct Spawn_Struct
|
||||
/*0000*/ uint8 unknown12;
|
||||
/*0000*/ uint32 petOwnerId;
|
||||
/*0000*/ uint8 unknown13;
|
||||
/*0000*/ uint32 unknown14; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed
|
||||
/*0000*/ uint32 PlayerState; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed
|
||||
/*0000*/ uint32 unknown15;
|
||||
/*0000*/ uint32 unknown16;
|
||||
/*0000*/ uint32 unknown17;
|
||||
@@ -660,7 +658,10 @@ struct CastSpell_Struct
|
||||
/*04*/ uint32 spell_id;
|
||||
/*08*/ ItemSlotStruct inventoryslot; // slot for clicky item, Seen unknown of 131 = normal cast
|
||||
/*20*/ uint32 target_id;
|
||||
/*24*/ uint32 cs_unknown[5];
|
||||
/*24*/ uint32 cs_unknown[2];
|
||||
/*32*/ float y_pos;
|
||||
/*36*/ float x_pos;
|
||||
/*40*/ float z_pos;
|
||||
/*44*/
|
||||
};
|
||||
|
||||
@@ -686,7 +687,7 @@ struct SpellBuff_Struct
|
||||
/*005*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages
|
||||
/*009*/ uint32 unknown016;
|
||||
/*013*/ uint8 bard_modifier;
|
||||
/*014*/ uint32 duration;
|
||||
/*014*/ int32 duration;
|
||||
/*018*/ uint8 level;
|
||||
/*019*/ uint32 spellid;
|
||||
/*023*/ uint32 counters;
|
||||
@@ -702,7 +703,7 @@ struct SpellBuff_Struct_Old
|
||||
/*003*/ uint8 effect; // not real
|
||||
/*004*/ float unknown004; // Seen 1 for no buff
|
||||
/*008*/ uint32 spellid;
|
||||
/*012*/ uint32 duration;
|
||||
/*012*/ int32 duration;
|
||||
/*016*/ uint32 unknown016;
|
||||
/*020*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages
|
||||
/*024*/ uint32 counters;
|
||||
@@ -719,7 +720,7 @@ struct SpellBuffFade_Struct_Live {
|
||||
/*007*/ uint8 unknown007;
|
||||
/*008*/ float unknown008;
|
||||
/*012*/ uint32 spellid;
|
||||
/*016*/ uint32 duration;
|
||||
/*016*/ int32 duration;
|
||||
/*020*/ uint32 playerId; // Global player ID?
|
||||
/*024*/ uint32 num_hits;
|
||||
/*028*/ uint8 unknown0028[64];
|
||||
@@ -735,7 +736,7 @@ struct SpellBuffFade_Struct {
|
||||
/*006*/ uint8 effect;
|
||||
/*007*/ uint8 unknown7;
|
||||
/*008*/ uint32 spellid;
|
||||
/*012*/ uint32 duration;
|
||||
/*012*/ int32 duration;
|
||||
/*016*/ uint32 num_hits;
|
||||
/*020*/ uint32 unknown020; // Global player ID?
|
||||
/*024*/ uint32 playerId; // Player id who cast the buff
|
||||
@@ -876,7 +877,7 @@ struct AA_Array
|
||||
{
|
||||
uint32 AA;
|
||||
uint32 value;
|
||||
uint32 unknown08; // Looks like AA_Array is now 12 bytes in Live
|
||||
uint32 charges; // expendable charges
|
||||
};
|
||||
|
||||
struct Disciplines_Struct {
|
||||
@@ -896,38 +897,66 @@ struct Tribute_Struct {
|
||||
uint32 tier;
|
||||
};
|
||||
|
||||
struct BandolierItem_Struct {
|
||||
char item_name[1]; // Variable Length
|
||||
uint32 item_id;
|
||||
uint32 icon;
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct_Old {
|
||||
uint32 item_id;
|
||||
uint32 icon;
|
||||
char item_name[64];
|
||||
};
|
||||
|
||||
//len = 320
|
||||
enum { //bandolier item positions
|
||||
bandolierMainHand = 0,
|
||||
bandolierOffHand,
|
||||
// Bandolier item positions
|
||||
enum
|
||||
{
|
||||
bandolierPrimary = 0,
|
||||
bandolierSecondary,
|
||||
bandolierRange,
|
||||
bandolierAmmo
|
||||
};
|
||||
struct Bandolier_Struct {
|
||||
char name[1]; // Variable Length
|
||||
BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS];
|
||||
|
||||
struct BandolierItem_Struct
|
||||
{
|
||||
char Name[1]; // Variable Length
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
};
|
||||
|
||||
struct Bandolier_Struct_Old {
|
||||
char name[32];
|
||||
BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS];
|
||||
//len = 72
|
||||
struct BandolierItem_Struct_Old
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
struct PotionBelt_Struct {
|
||||
BandolierItem_Struct items[MAX_POTIONS_IN_BELT];
|
||||
//len = 320
|
||||
struct Bandolier_Struct
|
||||
{
|
||||
char Name[1]; // Variable Length
|
||||
BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT];
|
||||
};
|
||||
|
||||
struct Bandolier_Struct_Old
|
||||
{
|
||||
char Name[32];
|
||||
BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT];
|
||||
};
|
||||
|
||||
struct PotionBeltItem_Struct
|
||||
{
|
||||
char Name[1]; // Variable Length
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct PotionBeltItem_Struct_Old
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
struct PotionBelt_Struct
|
||||
{
|
||||
PotionBeltItem_Struct Items[consts::POTION_BELT_ITEM_COUNT];
|
||||
};
|
||||
|
||||
struct PotionBelt_Struct_Old
|
||||
{
|
||||
PotionBeltItem_Struct_Old Items[consts::POTION_BELT_ITEM_COUNT];
|
||||
};
|
||||
|
||||
struct GroupLeadershipAA_Struct {
|
||||
@@ -1137,7 +1166,7 @@ union
|
||||
/*12949*/ uint32 aapoints; // Unspent AA points - Seen 1
|
||||
/*12953*/ uint16 unknown_rof20; //
|
||||
/*12955*/ uint32 bandolier_count; // Seen 20
|
||||
/*12959*/ Bandolier_Struct bandoliers[MAX_PLAYER_BANDOLIER]; // [20] 740 bytes (Variable Name Sizes) - bandolier contents
|
||||
/*12959*/ Bandolier_Struct bandoliers[consts::BANDOLIERS_SIZE]; // [20] 740 bytes (Variable Name Sizes) - bandolier contents
|
||||
/*13699*/ uint32 potionbelt_count; // Seen 5
|
||||
/*13703*/ PotionBelt_Struct potionbelt; // [5] 45 bytes potion belt - (Variable Name Sizes)
|
||||
/*13748*/ int32 unknown_rof21; // Seen -1
|
||||
@@ -1264,7 +1293,7 @@ struct TargetReject_Struct {
|
||||
|
||||
struct PetCommand_Struct {
|
||||
/*00*/ uint32 command;
|
||||
/*04*/ uint32 unknown04;
|
||||
/*04*/ uint32 target;
|
||||
/*08*/ uint32 unknown08;
|
||||
};
|
||||
|
||||
@@ -1389,8 +1418,8 @@ struct RequestClientZoneChange_Struct {
|
||||
|
||||
struct Animation_Struct {
|
||||
/*00*/ uint16 spawnid;
|
||||
/*02*/ uint8 value;
|
||||
/*03*/ uint8 action;
|
||||
/*02*/ uint8 action;
|
||||
/*03*/ uint8 speed;
|
||||
/*04*/
|
||||
};
|
||||
|
||||
@@ -1455,9 +1484,10 @@ struct CombatDamage_Struct
|
||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||
/* 05 */ uint32 spellid;
|
||||
/* 09 */ int32 damage;
|
||||
/* 13 */ float unknown11; // cd cc cc 3d
|
||||
/* 17 */ float sequence; // see above notes in Action_Struct
|
||||
/* 21 */ uint8 unknown19[9]; // was [9]
|
||||
/* 13 */ float force; // cd cc cc 3d
|
||||
/* 17 */ float meleepush_xy; // see above notes in Action_Struct
|
||||
/* 21 */ float meleepush_z;
|
||||
/* 25 */ uint8 unknown25[5]; // was [9]
|
||||
/* 30 */
|
||||
};
|
||||
|
||||
@@ -2443,7 +2473,7 @@ struct GroupFollow_Struct { // Live Follow Struct
|
||||
|
||||
struct InspectBuffs_Struct {
|
||||
/*000*/ uint32 spell_id[BUFF_COUNT];
|
||||
/*168*/ uint32 tics_remaining[BUFF_COUNT];
|
||||
/*168*/ int32 tics_remaining[BUFF_COUNT];
|
||||
};
|
||||
|
||||
struct LFG_Struct {
|
||||
@@ -2914,10 +2944,12 @@ struct BazaarWindowStart_Struct {
|
||||
|
||||
|
||||
struct BazaarWelcome_Struct {
|
||||
BazaarWindowStart_Struct Beginning;
|
||||
uint32 Traders;
|
||||
uint32 Items;
|
||||
uint8 Unknown012[8];
|
||||
uint32 Code;
|
||||
uint32 EntityID;
|
||||
uint32 Traders;
|
||||
uint32 Items;
|
||||
uint32 Traders2;
|
||||
uint32 Items2;
|
||||
};
|
||||
|
||||
struct BazaarSearch_Struct {
|
||||
@@ -3200,6 +3232,13 @@ struct BecomeTrader_Struct {
|
||||
};
|
||||
|
||||
struct Trader_ShowItems_Struct {
|
||||
/*000*/ uint32 Code;
|
||||
/*004*/ uint16 TraderID;
|
||||
/*008*/ uint32 Unknown08;
|
||||
/*012*/
|
||||
};
|
||||
|
||||
struct Trader_ShowItems_Struct_WIP {
|
||||
/*000*/ uint32 Code;
|
||||
/*004*/ char SerialNumber[17];
|
||||
/*021*/ uint8 Unknown21;
|
||||
@@ -3217,6 +3256,26 @@ struct TraderStatus_Struct {
|
||||
};
|
||||
|
||||
struct TraderBuy_Struct {
|
||||
/*000*/ uint32 Action;
|
||||
/*004*/ uint32 Unknown004;
|
||||
/*008*/ uint32 Unknown008;
|
||||
/*012*/ uint32 Unknown012;
|
||||
/*016*/ uint32 TraderID;
|
||||
/*020*/ char BuyerName[64];
|
||||
/*084*/ char SellerName[64];
|
||||
/*148*/ char Unknown148[32];
|
||||
/*180*/ char ItemName[64];
|
||||
/*244*/ char SerialNumber[16];
|
||||
/*260*/ uint32 Unknown076;
|
||||
/*264*/ uint32 ItemID;
|
||||
/*268*/ uint32 Price;
|
||||
/*272*/ uint32 AlreadySold;
|
||||
/*276*/ uint32 Unknown276;
|
||||
/*280*/ uint32 Quantity;
|
||||
/*284*/
|
||||
};
|
||||
|
||||
struct TraderBuy_Struct_OLD {
|
||||
/*000*/ uint32 Action;
|
||||
/*004*/ uint32 Unknown004;
|
||||
/*008*/ uint32 Price;
|
||||
@@ -3246,25 +3305,19 @@ struct MoneyUpdate_Struct{
|
||||
int32 copper;
|
||||
};
|
||||
|
||||
//struct MoneyUpdate_Struct
|
||||
//{
|
||||
//*0000*/ uint32 spawn_id; // ***Placeholder
|
||||
//*0004*/ uint32 cointype; // Coin Type
|
||||
//*0008*/ uint32 amount; // Amount
|
||||
//*0012*/
|
||||
//};
|
||||
|
||||
|
||||
struct TraderDelItem_Struct{
|
||||
uint32 slotid;
|
||||
uint32 quantity;
|
||||
uint32 unknown;
|
||||
/*000*/ uint32 Unknown000;
|
||||
/*004*/ uint32 TraderID;
|
||||
/*008*/ char SerialNumber[16];
|
||||
/*024*/ uint32 Unknown012;
|
||||
/*028*/
|
||||
};
|
||||
|
||||
struct TraderClick_Struct{
|
||||
uint32 traderid;
|
||||
uint32 unknown4[2];
|
||||
uint32 approval;
|
||||
/*000*/ uint32 Code;
|
||||
/*004*/ uint32 TraderID;
|
||||
/*008*/ uint32 Approval;
|
||||
/*012*/
|
||||
};
|
||||
|
||||
struct FormattedMessage_Struct{
|
||||
@@ -3567,7 +3620,7 @@ struct Split_Struct
|
||||
*/
|
||||
struct NewCombine_Struct {
|
||||
/*00*/ ItemSlotStruct container_slot;
|
||||
/*12*/ ItemSlotStruct guildtribute_slot; // Slot type is 8? (MapGuildTribute = 8 -U)
|
||||
/*12*/ ItemSlotStruct guildtribute_slot; // Slot type is 8? (MapGuildTribute = 8)
|
||||
/*24*/
|
||||
};
|
||||
|
||||
@@ -4088,30 +4141,35 @@ struct DynamicWall_Struct {
|
||||
/*80*/
|
||||
};
|
||||
|
||||
enum { //bandolier actions
|
||||
BandolierCreate = 0,
|
||||
BandolierRemove = 1,
|
||||
BandolierSet = 2
|
||||
// Bandolier actions
|
||||
enum
|
||||
{
|
||||
bandolierCreate = 0,
|
||||
bandolierRemove,
|
||||
bandolierSet
|
||||
};
|
||||
|
||||
struct BandolierCreate_Struct {
|
||||
/*00*/ uint32 action; //0 for create
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ char name[32];
|
||||
/*37*/ uint16 unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 unknown39; //0
|
||||
struct BandolierCreate_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; //0 for create
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ char Name[32];
|
||||
/*37*/ uint16 Unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 Unknown39; //0
|
||||
};
|
||||
|
||||
struct BandolierDelete_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierDelete_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct BandolierSet_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierSet_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct Arrow_Struct {
|
||||
@@ -4132,9 +4190,11 @@ struct Arrow_Struct {
|
||||
/*068*/ uint8 unknown068;
|
||||
/*069*/ uint8 unknown069;
|
||||
/*070*/ uint8 unknown070;
|
||||
/*071*/ uint8 item_type;
|
||||
/*072*/ uint8 skill;
|
||||
/*073*/ uint8 unknown073[16];
|
||||
/*071*/ uint8 unknown071;
|
||||
/*072*/ uint8 unknown072;
|
||||
/*073*/ uint8 skill;
|
||||
/*074*/ uint8 item_type;
|
||||
/*075*/ uint8 unknown075[14];
|
||||
/*089*/ char model_name[27];
|
||||
/*116*/
|
||||
};
|
||||
@@ -4193,9 +4253,9 @@ struct SendAA_Struct {
|
||||
/*0025*/ uint32 cost;
|
||||
/*0029*/ uint32 seq;
|
||||
/*0033*/ uint32 current_level; //1s, MQ2 calls this AARankRequired
|
||||
/*0037*/ uint32 unknown037; // Introduced during HoT
|
||||
/*0037*/ uint32 prereq_skill_count; // mutliple prereqs at least 1, even no prereqs
|
||||
/*0041*/ uint32 prereq_skill; //is < 0, abs() is category #
|
||||
/*0045*/ uint32 unknown045; // New Mar 21 2012 - Seen 1
|
||||
/*0045*/ uint32 prereq_minpoints_count; // mutliple prereqs at least 1, even no prereqs
|
||||
/*0049*/ uint32 prereq_minpoints; //min points in the prereq
|
||||
/*0053*/ uint32 type;
|
||||
/*0057*/ uint32 spellid;
|
||||
@@ -4208,10 +4268,16 @@ struct SendAA_Struct {
|
||||
/*0081*/ uint32 last_id;
|
||||
/*0085*/ uint32 next_id;
|
||||
/*0089*/ uint32 cost2;
|
||||
/*0093*/ uint8 unknown80[7];
|
||||
/*0093*/ uint8 unknown93;
|
||||
/*0094*/ uint8 grant_only; // VetAAs, progression, etc
|
||||
/*0095*/ uint8 unknown95; // 1 for skill cap increase AAs, Mystical Attuning, and RNG attack inc, doesn't seem to matter though
|
||||
/*0096*/ uint32 expendable_charges; // max charges of the AA
|
||||
/*0100*/ uint32 aa_expansion;
|
||||
/*0104*/ uint32 special_category;
|
||||
/*0108*/ uint32 unknown0096;
|
||||
/*0108*/ uint8 shroud;
|
||||
/*0109*/ uint8 unknown109;
|
||||
/*0110*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter?
|
||||
/*0111*/ uint8 unknown111;
|
||||
/*0112*/ uint32 total_abilities;
|
||||
/*0116*/ AA_Ability abilities[0];
|
||||
};
|
||||
@@ -4228,12 +4294,6 @@ struct AA_Action {
|
||||
/*16*/
|
||||
};
|
||||
|
||||
struct AA_Skills { //this should be removed and changed to AA_Array
|
||||
/*00*/ uint32 aa_skill; // Total AAs Spent
|
||||
/*04*/ uint32 aa_value;
|
||||
/*08*/ uint32 unknown08;
|
||||
/*12*/
|
||||
};
|
||||
|
||||
struct AAExpUpdate_Struct {
|
||||
/*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability
|
||||
@@ -4253,14 +4313,7 @@ struct AltAdvStats_Struct {
|
||||
};
|
||||
|
||||
struct PlayerAA_Struct { // Is this still used?
|
||||
AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct AA_Values {
|
||||
/*00*/ uint32 aa_skill;
|
||||
/*04*/ uint32 aa_value;
|
||||
/*08*/ uint32 unknown08;
|
||||
/*12*/
|
||||
AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct AATable_Struct {
|
||||
@@ -4270,7 +4323,7 @@ struct AATable_Struct {
|
||||
/*12*/ uint32 aa_spent_archetype; // Seen 40
|
||||
/*16*/ uint32 aa_spent_class; // Seen 103
|
||||
/*20*/ uint32 aa_spent_special; // Seen 0
|
||||
/*24*/ AA_Values aa_list[MAX_PP_AA_ARRAY];
|
||||
/*24*/ AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct Weather_Struct {
|
||||
@@ -4498,7 +4551,7 @@ struct ItemSecondaryBodyStruct
|
||||
uint32 augtype;
|
||||
// swapped augrestrict and augdistiller positions
|
||||
// (this swap does show the proper augment restrictions in Item Information window now)
|
||||
// unsure what the purpose of augdistiller is at this time -U 3/17/2014
|
||||
// unsure what the purpose of augdistiller is at this time 3/17/2014
|
||||
int32 augrestrict2; // New to December 10th 2012 client - Hidden Aug Restriction
|
||||
uint32 augrestrict;
|
||||
AugSlotStruct augslots[6];
|
||||
@@ -4673,17 +4726,33 @@ struct AugmentInfo_Struct
|
||||
|
||||
struct VeteranRewardItem
|
||||
{
|
||||
/*000*/ uint32 item_id;
|
||||
/*004*/ uint32 charges;
|
||||
/*008*/ char item_name[64];
|
||||
/*000*/ uint32 name_length;
|
||||
/*004*/ //char item_name[0]; // THIS IS NOT NULL TERMED
|
||||
/*???*/ uint32 item_id;
|
||||
/*???*/ uint32 charges;
|
||||
};
|
||||
|
||||
struct VeteranRewardEntry
|
||||
{
|
||||
/*000*/ uint32 claim_id; // guessed
|
||||
/*004*/ uint32 avaliable_count;
|
||||
/*008*/ uint32 claim_count;
|
||||
/*012*/ char enabled;
|
||||
/*013*/ //VeteranRewardItem items[0];
|
||||
};
|
||||
|
||||
struct VeteranReward
|
||||
{
|
||||
/*000*/ uint32 claim_id;
|
||||
/*004*/ uint32 number_available;
|
||||
/*008*/ uint32 claim_count;
|
||||
/*012*/ VeteranRewardItem items[8];
|
||||
/*000*/ uint32 claim_count;
|
||||
/*004*/ //VeteranRewardEntry entries[0];
|
||||
};
|
||||
|
||||
struct VeteranClaim
|
||||
{
|
||||
/*000*/ char name[68]; //name + other data
|
||||
/*068*/ uint32 claim_id;
|
||||
/*072*/ uint32 unknown072;
|
||||
/*076*/ uint32 action;
|
||||
};
|
||||
|
||||
struct ExpeditionEntryHeader_Struct
|
||||
|
||||
@@ -102,6 +102,8 @@ namespace RoF {
|
||||
}
|
||||
|
||||
namespace consts {
|
||||
static const size_t CHARACTER_CREATION_LIMIT = 12;
|
||||
|
||||
static const uint16 MAP_POSSESSIONS_SIZE = slots::_MainCount;
|
||||
static const uint16 MAP_BANK_SIZE = 24;
|
||||
static const uint16 MAP_SHARED_BANK_SIZE = 2;
|
||||
@@ -177,9 +179,10 @@ namespace RoF {
|
||||
static const uint16 ITEM_COMMON_SIZE = 6;
|
||||
static const uint16 ITEM_CONTAINER_SIZE = 255; // 255; (server max will be 255..unsure what actual client is - test)
|
||||
|
||||
static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances
|
||||
static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance
|
||||
static const uint32 POTION_BELT_SIZE = 5;
|
||||
static const size_t BANDOLIERS_SIZE = 20; // number of bandolier instances
|
||||
static const size_t BANDOLIER_ITEM_COUNT = 4; // number of equipment slots in bandolier instance
|
||||
|
||||
static const size_t POTION_BELT_ITEM_COUNT = 5;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 55;
|
||||
}
|
||||
|
||||
@@ -96,6 +96,7 @@ E(OP_Trader)
|
||||
E(OP_TraderBuy)
|
||||
E(OP_TributeInfo)
|
||||
E(OP_TributeItem)
|
||||
E(OP_VetClaimReply)
|
||||
E(OP_VetRewardsAvaliable)
|
||||
E(OP_WearChange)
|
||||
E(OP_WhoAllResponse)
|
||||
@@ -108,6 +109,7 @@ E(OP_ZoneSpawns)
|
||||
D(OP_AdventureMerchantSell)
|
||||
D(OP_AltCurrencySell)
|
||||
D(OP_AltCurrencySellSelection)
|
||||
D(OP_Animation)
|
||||
D(OP_ApplyPoison)
|
||||
D(OP_AugmentInfo)
|
||||
D(OP_AugmentItem)
|
||||
@@ -159,6 +161,7 @@ D(OP_Trader)
|
||||
D(OP_TraderBuy)
|
||||
D(OP_TradeSkillCombine)
|
||||
D(OP_TributeItem)
|
||||
D(OP_VetClaimRequest)
|
||||
D(OP_WhoAllRequest)
|
||||
D(OP_ZoneChange)
|
||||
D(OP_ZoneEntry)
|
||||
|
||||
+200
-158
@@ -97,11 +97,6 @@ static const uint32 MAX_PLAYER_TRIBUTES = 5;
|
||||
static const uint32 MAX_TRIBUTE_TIERS = 10;
|
||||
static const uint32 TRIBUTE_NONE = 0xFFFFFFFF;
|
||||
|
||||
static const uint32 MAX_PLAYER_BANDOLIER = 20;
|
||||
static const uint32 MAX_PLAYER_BANDOLIER_ITEMS = 4;
|
||||
|
||||
static const uint32 MAX_POTIONS_IN_BELT = 5;
|
||||
|
||||
static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16;
|
||||
static const uint32 MAX_RAID_LEADERSHIP_AA_ARRAY = 16;
|
||||
static const uint32 MAX_LEADERSHIP_AA_ARRAY = (MAX_GROUP_LEADERSHIP_AA_ARRAY+MAX_RAID_LEADERSHIP_AA_ARRAY);
|
||||
@@ -147,71 +142,87 @@ struct AdventureInfo {
|
||||
*/
|
||||
struct Color_Struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8 blue;
|
||||
uint8 green;
|
||||
uint8 red;
|
||||
uint8 use_tint; // if there's a tint this is FF
|
||||
} rgb;
|
||||
uint32 color;
|
||||
union {
|
||||
struct {
|
||||
uint8 Blue;
|
||||
uint8 Green;
|
||||
uint8 Red;
|
||||
uint8 UseTint; // if there's a tint this is FF
|
||||
} RGB;
|
||||
uint32 Color;
|
||||
};
|
||||
};
|
||||
|
||||
struct CharSelectEquip {
|
||||
uint32 material;
|
||||
uint32 unknown1;
|
||||
uint32 elitematerial;
|
||||
uint32 heroforgemodel;
|
||||
uint32 material2;
|
||||
Color_Struct color;
|
||||
struct CharSelectEquip
|
||||
{
|
||||
uint32 Material;
|
||||
uint32 Unknown1;
|
||||
uint32 EliteMaterial;
|
||||
uint32 HeroForgeModel;
|
||||
uint32 Material2;
|
||||
Color_Struct Color;
|
||||
};
|
||||
|
||||
struct CharacterSelectEntry_Struct {
|
||||
/*0000*/ char name[1]; // Name null terminated
|
||||
/*0000*/ uint8 class_;
|
||||
/*0000*/ uint32 race;
|
||||
/*0000*/ uint8 level;
|
||||
/*0000*/ uint8 class_2;
|
||||
/*0000*/ uint32 race2;
|
||||
/*0000*/ uint16 zone;
|
||||
/*0000*/ uint16 instance;
|
||||
/*0000*/ uint8 gender;
|
||||
/*0000*/ uint8 face;
|
||||
/*0000*/ CharSelectEquip equip[9];
|
||||
/*0000*/ uint8 u15; // Seen FF
|
||||
/*0000*/ uint8 u19; // Seen FF
|
||||
/*0000*/ uint32 drakkin_tattoo;
|
||||
/*0000*/ uint32 drakkin_details;
|
||||
/*0000*/ uint32 deity;
|
||||
/*0000*/ uint32 primary;
|
||||
/*0000*/ uint32 secondary;
|
||||
/*0000*/ uint8 haircolor;
|
||||
/*0000*/ uint8 beardcolor;
|
||||
/*0000*/ uint8 eyecolor1;
|
||||
/*0000*/ uint8 eyecolor2;
|
||||
/*0000*/ uint8 hairstyle;
|
||||
/*0000*/ uint8 beard;
|
||||
/*0000*/ uint8 char_enabled;
|
||||
/*0000*/ uint8 tutorial; // Seen 1 for new char or 0 for existing
|
||||
/*0000*/ uint32 drakkin_heritage;
|
||||
/*0000*/ uint8 unknown1; // Seen 0
|
||||
/*0000*/ uint8 gohome; // Seen 0 for new char and 1 for existing
|
||||
struct CharacterSelectEntry_Struct
|
||||
{
|
||||
/*0000*/ char Name[1]; // Name null terminated
|
||||
/*0000*/ uint8 Class;
|
||||
/*0000*/ uint32 Race;
|
||||
/*0000*/ uint8 Level;
|
||||
/*0000*/ uint8 ShroudClass;
|
||||
/*0000*/ uint32 ShroudRace;
|
||||
/*0000*/ uint16 Zone;
|
||||
/*0000*/ uint16 Instance;
|
||||
/*0000*/ uint8 Gender;
|
||||
/*0000*/ uint8 Face;
|
||||
/*0000*/ CharSelectEquip Equip[9];
|
||||
/*0000*/ uint8 Unknown15; // Seen FF
|
||||
/*0000*/ uint8 Unknown19; // Seen FF
|
||||
/*0000*/ uint32 DrakkinTattoo;
|
||||
/*0000*/ uint32 DrakkinDetails;
|
||||
/*0000*/ uint32 Deity;
|
||||
/*0000*/ uint32 PrimaryIDFile;
|
||||
/*0000*/ uint32 SecondaryIDFile;
|
||||
/*0000*/ uint8 HairColor;
|
||||
/*0000*/ uint8 BeardColor;
|
||||
/*0000*/ uint8 EyeColor1;
|
||||
/*0000*/ uint8 EyeColor2;
|
||||
/*0000*/ uint8 HairStyle;
|
||||
/*0000*/ uint8 Beard;
|
||||
/*0000*/ uint8 GoHome; // Seen 0 for new char and 1 for existing
|
||||
/*0000*/ uint8 Tutorial; // Seen 1 for new char or 0 for existing
|
||||
/*0000*/ uint32 DrakkinHeritage;
|
||||
/*0000*/ uint8 Unknown1; // Seen 0
|
||||
/*0000*/ uint8 Enabled; // Swapped position with 'GoHome' 02/23/2015
|
||||
/*0000*/ uint32 LastLogin;
|
||||
/*0000*/ uint8 unknown2; // Seen 0
|
||||
/*0000*/ uint8 Unknown2; // Seen 0
|
||||
};
|
||||
|
||||
/*
|
||||
** Character Selection Struct
|
||||
**
|
||||
*/
|
||||
struct CharacterSelect_Struct {
|
||||
/*000*/ uint32 char_count; //number of chars in this packet
|
||||
/*004*/ CharacterSelectEntry_Struct entries[0];
|
||||
struct CharacterSelect_Struct
|
||||
{
|
||||
/*000*/ uint32 CharCount; //number of chars in this packet
|
||||
/*004*/ CharacterSelectEntry_Struct Entries[0];
|
||||
};
|
||||
|
||||
/*
|
||||
* Visible equiptment.
|
||||
* Size: 20 Octets
|
||||
*/
|
||||
struct EquipStruct
|
||||
{
|
||||
/*00*/ uint32 Material;
|
||||
/*04*/ uint32 Unknown1;
|
||||
/*08*/ uint32 EliteMaterial;
|
||||
/*12*/ uint32 HeroForgeModel;
|
||||
/*16*/ uint32 Material2; // Same as material?
|
||||
/*20*/
|
||||
};
|
||||
|
||||
|
||||
struct Membership_Entry_Struct
|
||||
{
|
||||
/*000*/ uint32 purchase_id; // Seen 1, then increments 90287 to 90300
|
||||
@@ -252,20 +263,6 @@ struct Membership_Struct
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Visible equiptment.
|
||||
* Size: 20 Octets
|
||||
*/
|
||||
struct EquipStruct {
|
||||
/*00*/ uint32 material;
|
||||
/*04*/ uint32 unknown1;
|
||||
/*08*/ uint32 elitematerial;
|
||||
/*12*/ uint32 heroforgemodel;
|
||||
/*16*/ uint32 material2; // Same as material?
|
||||
/*20*/
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** Generic Spawn Struct
|
||||
** Length: 897 Octets
|
||||
@@ -413,7 +410,7 @@ struct Spawn_Struct
|
||||
/*0000*/ uint8 unknown12;
|
||||
/*0000*/ uint32 petOwnerId;
|
||||
/*0000*/ uint8 unknown13;
|
||||
/*0000*/ uint32 unknown14; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed
|
||||
/*0000*/ uint32 PlayerState; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed
|
||||
/*0000*/ uint32 unknown15;
|
||||
/*0000*/ uint32 unknown16;
|
||||
/*0000*/ uint32 unknown17;
|
||||
@@ -650,7 +647,10 @@ struct CastSpell_Struct
|
||||
/*04*/ uint32 spell_id;
|
||||
/*08*/ ItemSlotStruct inventoryslot; // slot for clicky item, Seen unknown of 131 = normal cast
|
||||
/*20*/ uint32 target_id;
|
||||
/*24*/ uint32 cs_unknown[5];
|
||||
/*24*/ uint32 cs_unknown[2];
|
||||
/*32*/ float y_pos;
|
||||
/*36*/ float x_pos;
|
||||
/*40*/ float z_pos;
|
||||
/*44*/
|
||||
};
|
||||
|
||||
@@ -676,7 +676,7 @@ struct SpellBuff_Struct
|
||||
/*005*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages
|
||||
/*009*/ uint32 unknown016;
|
||||
/*013*/ uint8 bard_modifier;
|
||||
/*014*/ uint32 duration;
|
||||
/*014*/ int32 duration;
|
||||
/*018*/ uint8 level;
|
||||
/*019*/ uint32 spellid;
|
||||
/*023*/ uint32 counters;
|
||||
@@ -692,7 +692,7 @@ struct SpellBuff_Struct_Old
|
||||
/*003*/ uint8 effect; // not real
|
||||
/*004*/ float unknown004; // Seen 1 for no buff
|
||||
/*008*/ uint32 spellid;
|
||||
/*012*/ uint32 duration;
|
||||
/*012*/ int32 duration;
|
||||
/*016*/ uint32 unknown016;
|
||||
/*020*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages
|
||||
/*024*/ uint32 counters;
|
||||
@@ -709,7 +709,7 @@ struct SpellBuffFade_Struct_Live {
|
||||
/*007*/ uint8 unknown007;
|
||||
/*008*/ float unknown008;
|
||||
/*012*/ uint32 spellid;
|
||||
/*016*/ uint32 duration;
|
||||
/*016*/ int32 duration;
|
||||
/*020*/ uint32 playerId; // Global player ID?
|
||||
/*024*/ uint32 num_hits;
|
||||
/*028*/ uint8 unknown0028[64];
|
||||
@@ -725,7 +725,7 @@ struct SpellBuffFade_Struct {
|
||||
/*006*/ uint8 effect;
|
||||
/*007*/ uint8 unknown7;
|
||||
/*008*/ uint32 spellid;
|
||||
/*012*/ uint32 duration;
|
||||
/*012*/ int32 duration;
|
||||
/*016*/ uint32 num_hits;
|
||||
/*020*/ uint32 unknown020; // Global player ID?
|
||||
/*024*/ uint32 playerId; // Player id who cast the buff
|
||||
@@ -866,7 +866,7 @@ struct AA_Array
|
||||
{
|
||||
uint32 AA;
|
||||
uint32 value;
|
||||
uint32 unknown08; // Looks like AA_Array is now 12 bytes in Live
|
||||
uint32 charges; // expendable charges
|
||||
};
|
||||
|
||||
struct Disciplines_Struct {
|
||||
@@ -880,38 +880,66 @@ struct Tribute_Struct {
|
||||
uint32 tier;
|
||||
};
|
||||
|
||||
struct BandolierItem_Struct {
|
||||
char item_name[1]; // Variable Length
|
||||
uint32 item_id;
|
||||
uint32 icon;
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct_Old {
|
||||
uint32 item_id;
|
||||
uint32 icon;
|
||||
char item_name[64];
|
||||
};
|
||||
|
||||
//len = 320
|
||||
enum { //bandolier item positions
|
||||
bandolierMainHand = 0,
|
||||
bandolierOffHand,
|
||||
// Bandolier item positions
|
||||
enum
|
||||
{
|
||||
bandolierPrimary = 0,
|
||||
bandolierSecondary,
|
||||
bandolierRange,
|
||||
bandolierAmmo
|
||||
};
|
||||
struct Bandolier_Struct {
|
||||
char name[1]; // Variable Length
|
||||
BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS];
|
||||
|
||||
struct BandolierItem_Struct
|
||||
{
|
||||
char Name[1]; // Variable Length
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
};
|
||||
|
||||
struct Bandolier_Struct_Old {
|
||||
char name[32];
|
||||
BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS];
|
||||
//len = 72
|
||||
struct BandolierItem_Struct_Old
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
struct PotionBelt_Struct {
|
||||
BandolierItem_Struct items[MAX_POTIONS_IN_BELT];
|
||||
//len = 320
|
||||
struct Bandolier_Struct
|
||||
{
|
||||
char Name[1]; // Variable Length
|
||||
BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT];
|
||||
};
|
||||
|
||||
struct Bandolier_Struct_Old
|
||||
{
|
||||
char Name[32];
|
||||
BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT];
|
||||
};
|
||||
|
||||
struct PotionBeltItem_Struct
|
||||
{
|
||||
char Name[1]; // Variable Length
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct PotionBeltItem_Struct_Old
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
struct PotionBelt_Struct
|
||||
{
|
||||
PotionBeltItem_Struct Items[consts::POTION_BELT_ITEM_COUNT];
|
||||
};
|
||||
|
||||
struct PotionBelt_Struct_Old
|
||||
{
|
||||
PotionBeltItem_Struct_Old Items[consts::POTION_BELT_ITEM_COUNT];
|
||||
};
|
||||
|
||||
struct GroupLeadershipAA_Struct {
|
||||
@@ -1121,7 +1149,7 @@ union
|
||||
/*12949*/ uint32 aapoints; // Unspent AA points - Seen 1
|
||||
/*12953*/ uint16 unknown_rof20; //
|
||||
/*12955*/ uint32 bandolier_count; // Seen 20
|
||||
/*12959*/ Bandolier_Struct bandoliers[MAX_PLAYER_BANDOLIER]; // [20] 740 bytes (Variable Name Sizes) - bandolier contents
|
||||
/*12959*/ Bandolier_Struct bandoliers[consts::BANDOLIERS_SIZE]; // [20] 740 bytes (Variable Name Sizes) - bandolier contents
|
||||
/*13699*/ uint32 potionbelt_count; // Seen 5
|
||||
/*13703*/ PotionBelt_Struct potionbelt; // [5] 45 bytes potion belt - (Variable Name Sizes)
|
||||
/*13748*/ int32 unknown_rof21; // Seen -1
|
||||
@@ -1295,7 +1323,7 @@ struct TargetReject_Struct {
|
||||
|
||||
struct PetCommand_Struct {
|
||||
/*00*/ uint32 command;
|
||||
/*04*/ uint32 unknown04;
|
||||
/*04*/ uint32 target;
|
||||
/*08*/ uint32 unknown08;
|
||||
};
|
||||
|
||||
@@ -1420,8 +1448,8 @@ struct RequestClientZoneChange_Struct {
|
||||
|
||||
struct Animation_Struct {
|
||||
/*00*/ uint16 spawnid;
|
||||
/*02*/ uint8 value;
|
||||
/*03*/ uint8 action;
|
||||
/*02*/ uint8 action;
|
||||
/*03*/ uint8 speed;
|
||||
/*04*/
|
||||
};
|
||||
|
||||
@@ -1486,9 +1514,10 @@ struct CombatDamage_Struct
|
||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||
/* 05 */ uint32 spellid;
|
||||
/* 09 */ int32 damage;
|
||||
/* 13 */ float unknown11; // cd cc cc 3d
|
||||
/* 17 */ float sequence; // see above notes in Action_Struct
|
||||
/* 21 */ uint8 unknown19[9]; // was [9]
|
||||
/* 13 */ float force; // cd cc cc 3d
|
||||
/* 17 */ float meleepush_xy; // see above notes in Action_Struct
|
||||
/* 21 */ float meleepush_z;
|
||||
/* 25 */ uint8 unknown25[5]; // was [9]
|
||||
/* 30 */
|
||||
};
|
||||
|
||||
@@ -2472,7 +2501,7 @@ struct GroupFollow_Struct { // Live Follow Struct
|
||||
|
||||
struct InspectBuffs_Struct {
|
||||
/*000*/ uint32 spell_id[BUFF_COUNT];
|
||||
/*168*/ uint32 tics_remaining[BUFF_COUNT];
|
||||
/*168*/ int32 tics_remaining[BUFF_COUNT];
|
||||
};
|
||||
|
||||
struct LFG_Struct {
|
||||
@@ -3592,7 +3621,7 @@ struct Split_Struct
|
||||
*/
|
||||
struct NewCombine_Struct {
|
||||
/*00*/ ItemSlotStruct container_slot;
|
||||
/*12*/ ItemSlotStruct guildtribute_slot; // Slot type is 8? (MapGuildTribute = 8 -U)
|
||||
/*12*/ ItemSlotStruct guildtribute_slot; // Slot type is 8? (MapGuildTribute = 8)
|
||||
/*24*/
|
||||
};
|
||||
|
||||
@@ -4113,30 +4142,35 @@ struct DynamicWall_Struct {
|
||||
/*80*/
|
||||
};
|
||||
|
||||
enum { //bandolier actions
|
||||
BandolierCreate = 0,
|
||||
BandolierRemove = 1,
|
||||
BandolierSet = 2
|
||||
// Bandolier actions
|
||||
enum
|
||||
{
|
||||
bandolierCreate = 0,
|
||||
bandolierRemove,
|
||||
bandolierSet
|
||||
};
|
||||
|
||||
struct BandolierCreate_Struct {
|
||||
/*00*/ uint32 action; //0 for create
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ char name[32];
|
||||
/*37*/ uint16 unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 unknown39; //0
|
||||
struct BandolierCreate_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; //0 for create
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ char Name[32];
|
||||
/*37*/ uint16 Unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 Unknown39; //0
|
||||
};
|
||||
|
||||
struct BandolierDelete_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierDelete_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct BandolierSet_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierSet_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct Arrow_Struct {
|
||||
@@ -4218,9 +4252,9 @@ struct SendAA_Struct {
|
||||
/*0025*/ uint32 cost;
|
||||
/*0029*/ uint32 seq;
|
||||
/*0033*/ uint32 current_level; //1s, MQ2 calls this AARankRequired
|
||||
/*0037*/ uint32 unknown037; // Introduced during HoT
|
||||
/*0037*/ uint32 prereq_skill_count; // mutliple prereqs at least 1, even no prereqs
|
||||
/*0041*/ uint32 prereq_skill; //is < 0, abs() is category #
|
||||
/*0045*/ uint32 unknown045; // New Mar 21 2012 - Seen 1
|
||||
/*0045*/ uint32 prereq_minpoints_count; // mutliple prereqs at least 1, even no prereqs
|
||||
/*0049*/ uint32 prereq_minpoints; //min points in the prereq
|
||||
/*0053*/ uint32 type;
|
||||
/*0057*/ uint32 spellid;
|
||||
@@ -4233,10 +4267,16 @@ struct SendAA_Struct {
|
||||
/*0081*/ uint32 last_id;
|
||||
/*0085*/ uint32 next_id;
|
||||
/*0089*/ uint32 cost2;
|
||||
/*0093*/ uint8 unknown80[7];
|
||||
/*0093*/ uint8 unknown93;
|
||||
/*0094*/ uint8 grant_only; // VetAAs, progression, etc
|
||||
/*0095*/ uint8 unknown95; // 1 for skill cap increase AAs, Mystical Attuning, and RNG attack inc, doesn't seem to matter though
|
||||
/*0096*/ uint32 expendable_charges; // max charges of the AA
|
||||
/*0100*/ uint32 aa_expansion;
|
||||
/*0104*/ uint32 special_category;
|
||||
/*0108*/ uint32 unknown0096;
|
||||
/*0108*/ uint8 shroud;
|
||||
/*0109*/ uint8 unknown109;
|
||||
/*0110*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter?
|
||||
/*0111*/ uint8 unknown111;
|
||||
/*0112*/ uint32 total_abilities;
|
||||
/*0116*/ AA_Ability abilities[0];
|
||||
};
|
||||
@@ -4253,13 +4293,6 @@ struct AA_Action {
|
||||
/*16*/
|
||||
};
|
||||
|
||||
struct AA_Skills { //this should be removed and changed to AA_Array
|
||||
/*00*/ uint32 aa_skill; // Total AAs Spent
|
||||
/*04*/ uint32 aa_value;
|
||||
/*08*/ uint32 unknown08;
|
||||
/*12*/
|
||||
};
|
||||
|
||||
struct AAExpUpdate_Struct {
|
||||
/*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability
|
||||
/*04*/ uint32 aapoints_unspent;
|
||||
@@ -4278,14 +4311,7 @@ struct AltAdvStats_Struct {
|
||||
};
|
||||
|
||||
struct PlayerAA_Struct { // Is this still used?
|
||||
AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct AA_Values {
|
||||
/*00*/ uint32 aa_skill;
|
||||
/*04*/ uint32 aa_value;
|
||||
/*08*/ uint32 unknown08;
|
||||
/*12*/
|
||||
AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct AATable_Struct {
|
||||
@@ -4295,7 +4321,7 @@ struct AATable_Struct {
|
||||
/*12*/ uint32 aa_spent_archetype; // Seen 40
|
||||
/*16*/ uint32 aa_spent_class; // Seen 103
|
||||
/*20*/ uint32 aa_spent_special; // Seen 0
|
||||
/*24*/ AA_Values aa_list[MAX_PP_AA_ARRAY];
|
||||
/*24*/ AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct Weather_Struct {
|
||||
@@ -4378,7 +4404,7 @@ struct RoFSlotStruct
|
||||
|
||||
struct ItemSerializationHeader
|
||||
{
|
||||
/*000*/ char unknown000[13]; // New for HoT. Looks like a string.
|
||||
/*000*/ char unknown000[17]; // New for HoT. Looks like a string.
|
||||
/*017*/ uint32 stacksize;
|
||||
/*021*/ uint32 unknown004;
|
||||
/*025*/ uint8 slot_type; // 0 = normal, 1 = bank, 2 = shared bank, 9 = merchant, 20 = ?
|
||||
@@ -4524,7 +4550,7 @@ struct ItemSecondaryBodyStruct
|
||||
uint32 augtype;
|
||||
// swapped augrestrict and augdistiller positions
|
||||
// (this swap does show the proper augment restrictions in Item Information window now)
|
||||
// unsure what the purpose of augdistiller is at this time -U 3/17/2014
|
||||
// unsure what the purpose of augdistiller is at this time 3/17/2014
|
||||
uint32 augdistiller; // New to December 10th 2012 client - NEW
|
||||
uint32 augrestrict;
|
||||
AugSlotStruct augslots[6];
|
||||
@@ -4688,17 +4714,33 @@ struct AugmentInfo_Struct
|
||||
|
||||
struct VeteranRewardItem
|
||||
{
|
||||
/*000*/ uint32 item_id;
|
||||
/*004*/ uint32 charges;
|
||||
/*008*/ char item_name[64];
|
||||
/*000*/ uint32 name_length;
|
||||
/*004*/ //char item_name[0]; // THIS IS NOT NULL TERMED
|
||||
/*???*/ uint32 item_id;
|
||||
/*???*/ uint32 charges;
|
||||
};
|
||||
|
||||
struct VeteranRewardEntry
|
||||
{
|
||||
/*000*/ uint32 claim_id; // guessed
|
||||
/*004*/ uint32 avaliable_count;
|
||||
/*008*/ uint32 claim_count;
|
||||
/*012*/ char enabled;
|
||||
/*013*/ //VeteranRewardItem items[0];
|
||||
};
|
||||
|
||||
struct VeteranReward
|
||||
{
|
||||
/*000*/ uint32 claim_id;
|
||||
/*004*/ uint32 number_available;
|
||||
/*008*/ uint32 claim_count;
|
||||
/*012*/ VeteranRewardItem items[8];
|
||||
/*000*/ uint32 claim_count;
|
||||
/*004*/ //VeteranRewardEntry entries[0];
|
||||
};
|
||||
|
||||
struct VeteranClaim
|
||||
{
|
||||
/*000*/ char name[68]; //name + other data
|
||||
/*068*/ uint32 claim_id;
|
||||
/*072*/ uint32 unknown072;
|
||||
/*076*/ uint32 action;
|
||||
};
|
||||
|
||||
struct ExpeditionEntryHeader_Struct
|
||||
|
||||
+147
-122
@@ -446,7 +446,9 @@ namespace SoD
|
||||
OUT(type);
|
||||
OUT(spellid);
|
||||
OUT(damage);
|
||||
eq->sequence = emu->sequence;
|
||||
OUT(force)
|
||||
OUT(meleepush_xy);
|
||||
OUT(meleepush_z)
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@@ -1542,13 +1544,13 @@ namespace SoD
|
||||
OUT(beard);
|
||||
// OUT(unknown00178[10]);
|
||||
for (r = 0; r < 9; r++) {
|
||||
eq->equipment[r].material = emu->item_material[r];
|
||||
eq->equipment[r].unknown1 = 0;
|
||||
eq->equipment[r].elitematerial = 0;
|
||||
eq->equipment[r].Material = emu->item_material[r];
|
||||
eq->equipment[r].Unknown1 = 0;
|
||||
eq->equipment[r].EliteMaterial = 0;
|
||||
//eq->colors[r].color = emu->colors[r].color;
|
||||
}
|
||||
for (r = 0; r < 7; r++) {
|
||||
OUT(item_tint[r].color);
|
||||
OUT(item_tint[r].Color);
|
||||
}
|
||||
// OUT(unknown00224[48]);
|
||||
//NOTE: new client supports 300 AAs, our internal rep/PP
|
||||
@@ -1556,6 +1558,7 @@ namespace SoD
|
||||
for (r = 0; r < MAX_PP_AA_ARRAY; r++) {
|
||||
OUT(aa_array[r].AA);
|
||||
OUT(aa_array[r].value);
|
||||
OUT(aa_array[r].charges);
|
||||
}
|
||||
// OUT(unknown02220[4]);
|
||||
OUT(mana);
|
||||
@@ -1606,26 +1609,46 @@ namespace SoD
|
||||
OUT(endurance);
|
||||
OUT(aapoints_spent);
|
||||
OUT(aapoints);
|
||||
|
||||
// OUT(unknown06160[4]);
|
||||
//NOTE: new client supports 20 bandoliers, our internal rep
|
||||
//only supports 4..
|
||||
for (r = 0; r < 4; r++) {
|
||||
OUT_str(bandoliers[r].name);
|
||||
uint32 k;
|
||||
for (k = 0; k < structs::MAX_PLAYER_BANDOLIER_ITEMS; k++) {
|
||||
OUT(bandoliers[r].items[k].item_id);
|
||||
OUT(bandoliers[r].items[k].icon);
|
||||
OUT_str(bandoliers[r].items[k].item_name);
|
||||
|
||||
// Copy bandoliers where server and client indexes converge
|
||||
for (r = 0; r < EmuConstants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) {
|
||||
OUT_str(bandoliers[r].Name);
|
||||
for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true
|
||||
OUT(bandoliers[r].Items[k].ID);
|
||||
OUT(bandoliers[r].Items[k].Icon);
|
||||
OUT_str(bandoliers[r].Items[k].Name);
|
||||
}
|
||||
}
|
||||
// OUT(unknown07444[5120]);
|
||||
for (r = 0; r < structs::MAX_POTIONS_IN_BELT; r++) {
|
||||
OUT(potionbelt.items[r].item_id);
|
||||
OUT(potionbelt.items[r].icon);
|
||||
OUT_str(potionbelt.items[r].item_name);
|
||||
// Nullify bandoliers where server and client indexes diverge, with a client bias
|
||||
for (r = EmuConstants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) {
|
||||
eq->bandoliers[r].Name[0] = '\0';
|
||||
for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true
|
||||
eq->bandoliers[r].Items[k].ID = 0;
|
||||
eq->bandoliers[r].Items[k].Icon = 0;
|
||||
eq->bandoliers[r].Items[k].Name[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
// OUT(unknown07444[5120]);
|
||||
|
||||
// Copy potion belt where server and client indexes converge
|
||||
for (r = 0; r < EmuConstants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) {
|
||||
OUT(potionbelt.Items[r].ID);
|
||||
OUT(potionbelt.Items[r].Icon);
|
||||
OUT_str(potionbelt.Items[r].Name);
|
||||
}
|
||||
// Nullify potion belt where server and client indexes diverge, with a client bias
|
||||
for (r = EmuConstants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) {
|
||||
eq->potionbelt.Items[r].ID = 0;
|
||||
eq->potionbelt.Items[r].Icon = 0;
|
||||
eq->potionbelt.Items[r].Name[0] = '\0';
|
||||
}
|
||||
|
||||
// OUT(unknown12852[8]);
|
||||
// OUT(unknown12864[76]);
|
||||
|
||||
OUT_str(name);
|
||||
OUT_str(last_name);
|
||||
OUT(guild_id);
|
||||
@@ -1876,6 +1899,7 @@ namespace SoD
|
||||
OUT(cost2);
|
||||
eq->aa_expansion = emu->aa_expansion;
|
||||
eq->special_category = emu->special_category;
|
||||
eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number
|
||||
OUT(total_abilities);
|
||||
unsigned int r;
|
||||
for (r = 0; r < emu->total_abilities; r++) {
|
||||
@@ -1891,76 +1915,96 @@ namespace SoD
|
||||
|
||||
ENCODE(OP_SendCharInfo)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(CharacterSelect_Struct);
|
||||
ENCODE_LENGTH_ATLEAST(CharacterSelect_Struct);
|
||||
SETUP_VAR_ENCODE(CharacterSelect_Struct);
|
||||
|
||||
//EQApplicationPacket *packet = *p;
|
||||
//const CharacterSelect_Struct *emu = (CharacterSelect_Struct *) packet->pBuffer;
|
||||
// Zero-character count shunt
|
||||
if (emu->CharCount == 0) {
|
||||
ALLOC_VAR_ENCODE(structs::CharacterSelect_Struct, sizeof(structs::CharacterSelect_Struct));
|
||||
eq->CharCount = emu->CharCount;
|
||||
eq->TotalChars = emu->TotalChars;
|
||||
|
||||
int char_count;
|
||||
int namelen = 0;
|
||||
for (char_count = 0; char_count < 10; char_count++) {
|
||||
if (emu->name[char_count][0] == '\0')
|
||||
break;
|
||||
if (strcmp(emu->name[char_count], "<none>") == 0)
|
||||
break;
|
||||
namelen += strlen(emu->name[char_count]);
|
||||
if (eq->TotalChars > consts::CHARACTER_CREATION_LIMIT)
|
||||
eq->TotalChars = consts::CHARACTER_CREATION_LIMIT;
|
||||
|
||||
FINISH_ENCODE();
|
||||
return;
|
||||
}
|
||||
|
||||
int total_length = sizeof(structs::CharacterSelect_Struct)
|
||||
+ char_count * sizeof(structs::CharacterSelectEntry_Struct)
|
||||
+ namelen;
|
||||
unsigned char *emu_ptr = __emu_buffer;
|
||||
emu_ptr += sizeof(CharacterSelect_Struct);
|
||||
CharacterSelectEntry_Struct *emu_cse = (CharacterSelectEntry_Struct *)nullptr;
|
||||
|
||||
size_t names_length = 0;
|
||||
size_t character_count = 0;
|
||||
for (; character_count < emu->CharCount && character_count < consts::CHARACTER_CREATION_LIMIT; ++character_count) {
|
||||
emu_cse = (CharacterSelectEntry_Struct *)emu_ptr;
|
||||
names_length += strlen(emu_cse->Name);
|
||||
emu_ptr += sizeof(CharacterSelectEntry_Struct);
|
||||
}
|
||||
|
||||
size_t total_length = sizeof(structs::CharacterSelect_Struct)
|
||||
+ character_count * sizeof(structs::CharacterSelectEntry_Struct)
|
||||
+ names_length;
|
||||
|
||||
ALLOC_VAR_ENCODE(structs::CharacterSelect_Struct, total_length);
|
||||
structs::CharacterSelectEntry_Struct *eq_cse = (structs::CharacterSelectEntry_Struct *)nullptr;
|
||||
|
||||
//unsigned char *eq_buffer = new unsigned char[total_length];
|
||||
//structs::CharacterSelect_Struct *eq_head = (structs::CharacterSelect_Struct *) eq_buffer;
|
||||
eq->CharCount = character_count;
|
||||
eq->TotalChars = emu->TotalChars;
|
||||
|
||||
eq->char_count = char_count;
|
||||
eq->total_chars = 10;
|
||||
if (eq->TotalChars > consts::CHARACTER_CREATION_LIMIT)
|
||||
eq->TotalChars = consts::CHARACTER_CREATION_LIMIT;
|
||||
|
||||
unsigned char *bufptr = (unsigned char *)eq->entries;
|
||||
int r;
|
||||
for (r = 0; r < char_count; r++) {
|
||||
{ //pre-name section...
|
||||
structs::CharacterSelectEntry_Struct *eq2 = (structs::CharacterSelectEntry_Struct *) bufptr;
|
||||
eq2->level = emu->level[r];
|
||||
eq2->hairstyle = emu->hairstyle[r];
|
||||
eq2->gender = emu->gender[r];
|
||||
memcpy(eq2->name, emu->name[r], strlen(emu->name[r]) + 1);
|
||||
emu_ptr = __emu_buffer;
|
||||
emu_ptr += sizeof(CharacterSelect_Struct);
|
||||
|
||||
unsigned char *eq_ptr = __packet->pBuffer;
|
||||
eq_ptr += sizeof(structs::CharacterSelect_Struct);
|
||||
|
||||
for (int counter = 0; counter < character_count; ++counter) {
|
||||
emu_cse = (CharacterSelectEntry_Struct *)emu_ptr;
|
||||
eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // base address
|
||||
|
||||
eq_cse->Level = emu_cse->Level;
|
||||
eq_cse->HairStyle = emu_cse->HairStyle;
|
||||
eq_cse->Gender = emu_cse->Gender;
|
||||
|
||||
strcpy(eq_cse->Name, emu_cse->Name);
|
||||
eq_ptr += strlen(emu_cse->Name);
|
||||
eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // offset address (base + name length offset)
|
||||
eq_cse->Name[0] = '\0'; // (offset)eq_cse->Name[0] = (base)eq_cse->Name[strlen(emu_cse->Name)]
|
||||
|
||||
eq_cse->Beard = emu_cse->Beard;
|
||||
eq_cse->HairColor = emu_cse->HairColor;
|
||||
eq_cse->Face = emu_cse->Face;
|
||||
|
||||
for (int equip_index = 0; equip_index < _MaterialCount; equip_index++) {
|
||||
eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material;
|
||||
eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1;
|
||||
eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial;
|
||||
eq_cse->Equip[equip_index].Color.Color = emu_cse->Equip[equip_index].Color.Color;
|
||||
}
|
||||
//adjust for name.
|
||||
bufptr += strlen(emu->name[r]);
|
||||
{ //post-name section...
|
||||
structs::CharacterSelectEntry_Struct *eq2 = (structs::CharacterSelectEntry_Struct *) bufptr;
|
||||
eq2->beard = emu->beard[r];
|
||||
eq2->haircolor = emu->haircolor[r];
|
||||
eq2->face = emu->face[r];
|
||||
int k;
|
||||
for (k = 0; k < _MaterialCount; k++) {
|
||||
eq2->equip[k].material = emu->equip[r][k].material;
|
||||
eq2->equip[k].unknown1 = emu->equip[r][k].unknown1;
|
||||
eq2->equip[k].elitematerial = emu->equip[r][k].elitematerial;
|
||||
eq2->equip[k].color.color = emu->equip[r][k].color.color;
|
||||
}
|
||||
eq2->primary = emu->primary[r];
|
||||
eq2->secondary = emu->secondary[r];
|
||||
eq2->tutorial = emu->tutorial[r]; // was u15
|
||||
eq2->u15 = 0xff;
|
||||
eq2->deity = emu->deity[r];
|
||||
eq2->zone = emu->zone[r];
|
||||
eq2->u19 = 0xFF;
|
||||
eq2->race = emu->race[r];
|
||||
eq2->gohome = emu->gohome[r];
|
||||
eq2->class_ = emu->class_[r];
|
||||
eq2->eyecolor1 = emu->eyecolor1[r];
|
||||
eq2->beardcolor = emu->beardcolor[r];
|
||||
eq2->eyecolor2 = emu->eyecolor2[r];
|
||||
eq2->drakkin_heritage = emu->drakkin_heritage[r];
|
||||
eq2->drakkin_tattoo = emu->drakkin_tattoo[r];
|
||||
eq2->drakkin_details = emu->drakkin_details[r];
|
||||
}
|
||||
bufptr += sizeof(structs::CharacterSelectEntry_Struct);
|
||||
|
||||
eq_cse->PrimaryIDFile = emu_cse->PrimaryIDFile;
|
||||
eq_cse->SecondaryIDFile = emu_cse->SecondaryIDFile;
|
||||
eq_cse->Tutorial = emu_cse->Tutorial;
|
||||
eq_cse->Unknown15 = emu_cse->Unknown15;
|
||||
eq_cse->Deity = emu_cse->Deity;
|
||||
eq_cse->Zone = emu_cse->Zone;
|
||||
eq_cse->Unknown19 = emu_cse->Unknown19;
|
||||
eq_cse->Race = emu_cse->Race;
|
||||
eq_cse->GoHome = emu_cse->GoHome;
|
||||
eq_cse->Class = emu_cse->Class;
|
||||
eq_cse->EyeColor1 = emu_cse->EyeColor1;
|
||||
eq_cse->BeardColor = emu_cse->BeardColor;
|
||||
eq_cse->EyeColor2 = emu_cse->EyeColor2;
|
||||
eq_cse->DrakkinHeritage = emu_cse->DrakkinHeritage;
|
||||
eq_cse->DrakkinTattoo = emu_cse->DrakkinTattoo;
|
||||
eq_cse->DrakkinDetails = emu_cse->DrakkinDetails;
|
||||
|
||||
emu_ptr += sizeof(CharacterSelectEntry_Struct);
|
||||
eq_ptr += sizeof(structs::CharacterSelectEntry_Struct);
|
||||
}
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -2355,7 +2399,7 @@ namespace SoD
|
||||
OUT(material);
|
||||
OUT(unknown06);
|
||||
OUT(elite_material);
|
||||
OUT(color.color);
|
||||
OUT(color.Color);
|
||||
OUT(wear_slot_id);
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -2427,42 +2471,23 @@ namespace SoD
|
||||
|
||||
ENCODE(OP_ZonePlayerToBind)
|
||||
{
|
||||
ENCODE_LENGTH_ATLEAST(ZonePlayerToBind_Struct);
|
||||
SETUP_VAR_ENCODE(ZonePlayerToBind_Struct);
|
||||
ALLOC_LEN_ENCODE(sizeof(structs::ZonePlayerToBind_Struct) + strlen(emu->zone_name));
|
||||
|
||||
ZonePlayerToBind_Struct *zps = (ZonePlayerToBind_Struct*)(*p)->pBuffer;
|
||||
__packet->SetWritePosition(0);
|
||||
__packet->WriteUInt16(emu->bind_zone_id);
|
||||
__packet->WriteUInt16(emu->bind_instance_id);
|
||||
__packet->WriteFloat(emu->x);
|
||||
__packet->WriteFloat(emu->y);
|
||||
__packet->WriteFloat(emu->z);
|
||||
__packet->WriteFloat(emu->heading);
|
||||
__packet->WriteString(emu->zone_name);
|
||||
__packet->WriteUInt8(1); // save items
|
||||
__packet->WriteUInt32(0); // hp
|
||||
__packet->WriteUInt32(0); // mana
|
||||
__packet->WriteUInt32(0); // endurance
|
||||
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
||||
|
||||
unsigned char *buffer1 = new unsigned char[sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name)];
|
||||
structs::ZonePlayerToBindHeader_Struct *zph = (structs::ZonePlayerToBindHeader_Struct*)buffer1;
|
||||
unsigned char *buffer2 = new unsigned char[sizeof(structs::ZonePlayerToBindFooter_Struct)];
|
||||
structs::ZonePlayerToBindFooter_Struct *zpf = (structs::ZonePlayerToBindFooter_Struct*)buffer2;
|
||||
|
||||
zph->x = zps->x;
|
||||
zph->y = zps->y;
|
||||
zph->z = zps->z;
|
||||
zph->heading = zps->heading;
|
||||
zph->bind_zone_id = zps->bind_zone_id;
|
||||
zph->bind_instance_id = zps->bind_instance_id;
|
||||
strcpy(zph->zone_name, zps->zone_name);
|
||||
|
||||
zpf->unknown021 = 1;
|
||||
zpf->unknown022 = 0;
|
||||
zpf->unknown023 = 0;
|
||||
zpf->unknown024 = 0;
|
||||
|
||||
ss.write((const char*)buffer1, (sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name)));
|
||||
ss.write((const char*)buffer2, sizeof(structs::ZonePlayerToBindFooter_Struct));
|
||||
|
||||
delete[] buffer1;
|
||||
delete[] buffer2;
|
||||
delete[](*p)->pBuffer;
|
||||
|
||||
(*p)->pBuffer = new unsigned char[ss.str().size()];
|
||||
(*p)->size = ss.str().size();
|
||||
|
||||
memcpy((*p)->pBuffer, ss.str().c_str(), ss.str().size());
|
||||
dest->FastQueuePacket(&(*p));
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ZoneServerInfo)
|
||||
@@ -2715,7 +2740,7 @@ namespace SoD
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown12
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->petOwnerId);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown13
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown14 - Stance 64 = normal 4 = aggressive 40 = stun/mezzed
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->PlayerState);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown15
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown16
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown17
|
||||
@@ -2742,7 +2767,7 @@ namespace SoD
|
||||
for (k = 0; k < 9; ++k)
|
||||
{
|
||||
{
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->colors[k].color);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->colors[k].Color);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2752,11 +2777,11 @@ namespace SoD
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].material);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].Material);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].material);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].Material);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
}
|
||||
@@ -2767,9 +2792,9 @@ namespace SoD
|
||||
structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer;
|
||||
|
||||
for (k = 0; k < 9; k++) {
|
||||
Equipment[k].material = emu->equipment[k].material;
|
||||
Equipment[k].unknown1 = emu->equipment[k].unknown1;
|
||||
Equipment[k].elitematerial = emu->equipment[k].elitematerial;
|
||||
Equipment[k].Material = emu->equipment[k].Material;
|
||||
Equipment[k].Unknown1 = emu->equipment[k].Unknown1;
|
||||
Equipment[k].EliteMaterial = emu->equipment[k].EliteMaterial;
|
||||
}
|
||||
|
||||
Buffer += (sizeof(structs::EquipStruct) * 9);
|
||||
@@ -3329,7 +3354,7 @@ namespace SoD
|
||||
default:
|
||||
emu->command = eq->command;
|
||||
}
|
||||
OUT(unknown);
|
||||
IN(target);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@@ -3484,7 +3509,7 @@ namespace SoD
|
||||
IN(material);
|
||||
IN(unknown06);
|
||||
IN(elite_material);
|
||||
IN(color.color);
|
||||
IN(color.Color);
|
||||
IN(wear_slot_id);
|
||||
emu->hero_forge_model = 0;
|
||||
emu->unknown18 = 0;
|
||||
|
||||
@@ -101,6 +101,8 @@ namespace SoD {
|
||||
}
|
||||
|
||||
namespace consts {
|
||||
static const size_t CHARACTER_CREATION_LIMIT = 12;
|
||||
|
||||
static const uint16 MAP_POSSESSIONS_SIZE = slots::_MainCount;
|
||||
static const uint16 MAP_BANK_SIZE = 24;
|
||||
static const uint16 MAP_SHARED_BANK_SIZE = 2;
|
||||
@@ -174,9 +176,10 @@ namespace SoD {
|
||||
static const uint16 ITEM_COMMON_SIZE = 5;
|
||||
static const uint16 ITEM_CONTAINER_SIZE = 10;
|
||||
|
||||
static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances
|
||||
static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance
|
||||
static const uint32 POTION_BELT_SIZE = 5;
|
||||
static const size_t BANDOLIERS_SIZE = 20; // number of bandolier instances
|
||||
static const size_t BANDOLIER_ITEM_COUNT = 4; // number of equipment slots in bandolier instance
|
||||
|
||||
static const size_t POTION_BELT_ITEM_COUNT = 5;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 50;
|
||||
}
|
||||
|
||||
+132
-112
@@ -103,54 +103,53 @@ struct AdventureInfo {
|
||||
*/
|
||||
struct Color_Struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8 blue;
|
||||
uint8 green;
|
||||
uint8 red;
|
||||
uint8 use_tint; // if there's a tint this is FF
|
||||
} rgb;
|
||||
uint32 color;
|
||||
union {
|
||||
struct {
|
||||
uint8 Blue;
|
||||
uint8 Green;
|
||||
uint8 Red;
|
||||
uint8 UseTint; // if there's a tint this is FF
|
||||
} RGB;
|
||||
uint32 Color;
|
||||
};
|
||||
};
|
||||
|
||||
struct CharSelectEquip {
|
||||
//totally guessed;
|
||||
uint32 material;
|
||||
uint32 unknown1;
|
||||
uint32 elitematerial;
|
||||
Color_Struct color;
|
||||
struct CharSelectEquip
|
||||
{
|
||||
uint32 Material;
|
||||
uint32 Unknown1;
|
||||
uint32 EliteMaterial;
|
||||
Color_Struct Color;
|
||||
};
|
||||
|
||||
struct CharacterSelectEntry_Struct {
|
||||
/*0000*/ uint8 level; //
|
||||
/*0000*/ uint8 hairstyle; //
|
||||
/*0002*/ uint8 gender; //
|
||||
/*0003*/ char name[1]; //variable length, edi+0
|
||||
/*0000*/ uint8 beard; //
|
||||
/*0001*/ uint8 haircolor; //
|
||||
/*0000*/ uint8 face; //
|
||||
/*0000*/ CharSelectEquip equip[9];
|
||||
/*0000*/ uint32 primary; //
|
||||
/*0000*/ uint32 secondary; //
|
||||
/*0000*/ uint8 u15; // 0xff
|
||||
/*0000*/ uint32 deity; //
|
||||
/*0000*/ uint16 zone; //
|
||||
/*0000*/ uint16 instance;
|
||||
/*0000*/ uint8 gohome; //
|
||||
/*0000*/ uint8 u19; // 0xff
|
||||
/*0000*/ uint32 race; //
|
||||
/*0000*/ uint8 tutorial; //
|
||||
/*0000*/ uint8 class_; //
|
||||
/*0000*/ uint8 eyecolor1; //
|
||||
/*0000*/ uint8 beardcolor; //
|
||||
/*0000*/ uint8 eyecolor2; //
|
||||
/*0000*/ uint32 drakkin_heritage; // Drakkin Heritage
|
||||
/*0000*/ uint32 drakkin_tattoo; // Drakkin Tattoo
|
||||
/*0000*/ uint32 drakkin_details; // Drakkin Details (Facial Spikes)
|
||||
/*0000*/ uint8 unknown; // New field to SoD
|
||||
struct CharacterSelectEntry_Struct
|
||||
{
|
||||
/*0000*/ uint8 Level; //
|
||||
/*0000*/ uint8 HairStyle; //
|
||||
/*0002*/ uint8 Gender; //
|
||||
/*0003*/ char Name[1]; // variable length, edi+0
|
||||
/*0000*/ uint8 Beard; //
|
||||
/*0001*/ uint8 HairColor; //
|
||||
/*0000*/ uint8 Face; //
|
||||
/*0000*/ CharSelectEquip Equip[9];
|
||||
/*0000*/ uint32 PrimaryIDFile; //
|
||||
/*0000*/ uint32 SecondaryIDFile; //
|
||||
/*0000*/ uint8 Unknown15; // 0xff
|
||||
/*0000*/ uint32 Deity; //
|
||||
/*0000*/ uint16 Zone; //
|
||||
/*0000*/ uint16 Instance;
|
||||
/*0000*/ uint8 GoHome; //
|
||||
/*0000*/ uint8 Unknown19; // 0xff
|
||||
/*0000*/ uint32 Race; //
|
||||
/*0000*/ uint8 Tutorial; //
|
||||
/*0000*/ uint8 Class; //
|
||||
/*0000*/ uint8 EyeColor1; //
|
||||
/*0000*/ uint8 BeardColor; //
|
||||
/*0000*/ uint8 EyeColor2; //
|
||||
/*0000*/ uint32 DrakkinHeritage; // Drakkin Heritage
|
||||
/*0000*/ uint32 DrakkinTattoo; // Drakkin Tattoo
|
||||
/*0000*/ uint32 DrakkinDetails; // Drakkin Details (Facial Spikes)
|
||||
/*0000*/ uint8 Unknown; // New field to SoD
|
||||
|
||||
};
|
||||
|
||||
@@ -158,20 +157,22 @@ struct CharacterSelectEntry_Struct {
|
||||
** Character Selection Struct
|
||||
**
|
||||
*/
|
||||
struct CharacterSelect_Struct {
|
||||
/*0000*/ uint32 char_count; //number of chars in this packet
|
||||
/*0004*/ uint32 total_chars; //total number of chars allowed?
|
||||
/*0008*/ CharacterSelectEntry_Struct entries[0];
|
||||
struct CharacterSelect_Struct
|
||||
{
|
||||
/*0000*/ uint32 CharCount; //number of chars in this packet
|
||||
/*0004*/ uint32 TotalChars; //total number of chars allowed?
|
||||
/*0008*/ CharacterSelectEntry_Struct Entries[0];
|
||||
};
|
||||
|
||||
/*
|
||||
* Visible equiptment.
|
||||
* Size: 12 Octets
|
||||
*/
|
||||
struct EquipStruct {
|
||||
/*00*/ uint32 material;
|
||||
/*04*/ uint32 unknown1;
|
||||
/*08*/ uint32 elitematerial;
|
||||
struct EquipStruct
|
||||
{
|
||||
/*00*/ uint32 Material;
|
||||
/*04*/ uint32 Unknown1;
|
||||
/*08*/ uint32 EliteMaterial;
|
||||
/*12*/
|
||||
};
|
||||
|
||||
@@ -285,7 +286,7 @@ struct Spawn_Struct
|
||||
/*0000*/ uint8 unknown12;
|
||||
/*0000*/ uint32 petOwnerId;
|
||||
/*0000*/ uint8 unknown13;
|
||||
/*0000*/ uint32 unknown14; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed
|
||||
/*0000*/ uint32 PlayerState; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed
|
||||
/*0000*/ uint32 unknown15;
|
||||
/*0000*/ uint32 unknown16;
|
||||
/*0000*/ uint32 unknown17;
|
||||
@@ -546,7 +547,7 @@ struct SpellBuff_Struct
|
||||
/*002*/ uint8 bard_modifier;
|
||||
/*003*/ uint8 effect; //not real
|
||||
/*004*/ uint32 spellid;
|
||||
/*008*/ uint32 duration;
|
||||
/*008*/ int32 duration;
|
||||
/*012*/ uint32 counters;
|
||||
/*016*/ uint32 unknown004; //Might need to be swapped with player_id
|
||||
/*020*/ uint32 player_id; //'global' ID of the caster, for wearoff messages
|
||||
@@ -563,7 +564,7 @@ struct SpellBuffFade_Struct {
|
||||
/*006*/ uint8 effect;
|
||||
/*007*/ uint8 unknown7;
|
||||
/*008*/ uint32 spellid;
|
||||
/*012*/ uint32 duration;
|
||||
/*012*/ int32 duration;
|
||||
/*016*/ uint32 unknown016;
|
||||
/*020*/ uint32 unknown020; //prolly global player ID
|
||||
/*024*/ uint32 playerId; // Player id who cast the buff
|
||||
@@ -665,7 +666,7 @@ struct AA_Array
|
||||
{
|
||||
uint32 AA;
|
||||
uint32 value;
|
||||
uint32 unknown08; // Looks like AA_Array is now 12 bytes in Live
|
||||
uint32 charges; // expendable
|
||||
};
|
||||
|
||||
|
||||
@@ -676,9 +677,6 @@ struct Disciplines_Struct {
|
||||
};
|
||||
|
||||
static const uint32 MAX_PLAYER_TRIBUTES = 5;
|
||||
static const uint32 MAX_PLAYER_BANDOLIER = 20;
|
||||
static const uint32 MAX_PLAYER_BANDOLIER_ITEMS = 4;
|
||||
static const uint32 MAX_POTIONS_IN_BELT = 5;
|
||||
static const uint32 TRIBUTE_NONE = 0xFFFFFFFF;
|
||||
|
||||
struct Tribute_Struct {
|
||||
@@ -686,26 +684,42 @@ struct Tribute_Struct {
|
||||
uint32 tier;
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct {
|
||||
uint32 item_id;
|
||||
uint32 icon;
|
||||
char item_name[64];
|
||||
};
|
||||
|
||||
//len = 320
|
||||
enum { //bandolier item positions
|
||||
bandolierMainHand = 0,
|
||||
bandolierOffHand,
|
||||
// Bandolier item positions
|
||||
enum
|
||||
{
|
||||
bandolierPrimary = 0,
|
||||
bandolierSecondary,
|
||||
bandolierRange,
|
||||
bandolierAmmo
|
||||
};
|
||||
struct Bandolier_Struct {
|
||||
char name[32];
|
||||
BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS];
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
struct PotionBelt_Struct {
|
||||
BandolierItem_Struct items[MAX_POTIONS_IN_BELT];
|
||||
|
||||
//len = 320
|
||||
struct Bandolier_Struct
|
||||
{
|
||||
char Name[32];
|
||||
BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT];
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct PotionBeltItem_Struct
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
//len = 288
|
||||
struct PotionBelt_Struct
|
||||
{
|
||||
PotionBeltItem_Struct Items[consts::POTION_BELT_ITEM_COUNT];
|
||||
};
|
||||
|
||||
static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16;
|
||||
@@ -925,7 +939,7 @@ struct PlayerProfile_Struct
|
||||
/*08288*/ uint32 aapoints_spent; // Number of spent AA points
|
||||
/*08292*/ uint32 aapoints; // Unspent AA points
|
||||
/*08296*/ uint8 unknown06160[4];
|
||||
/*08300*/ Bandolier_Struct bandoliers[MAX_PLAYER_BANDOLIER]; // [6400] bandolier contents
|
||||
/*08300*/ Bandolier_Struct bandoliers[consts::BANDOLIERS_SIZE]; // [6400] bandolier contents
|
||||
/*14700*/ PotionBelt_Struct potionbelt; // [360] potion belt 72 extra octets by adding 1 more belt slot
|
||||
/*15060*/ uint8 unknown12852[8];
|
||||
/*15068*/ uint32 available_slots;
|
||||
@@ -1077,7 +1091,7 @@ struct TargetReject_Struct {
|
||||
|
||||
struct PetCommand_Struct {
|
||||
/*000*/ uint32 command;
|
||||
/*004*/ uint32 unknown;
|
||||
/*004*/ uint32 target;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1191,8 +1205,8 @@ struct RequestClientZoneChange_Struct {
|
||||
|
||||
struct Animation_Struct {
|
||||
/*00*/ uint16 spawnid;
|
||||
/*02*/ uint8 action;
|
||||
/*03*/ uint8 value;
|
||||
/*02*/ uint8 speed;
|
||||
/*03*/ uint8 action;
|
||||
/*04*/
|
||||
};
|
||||
|
||||
@@ -1258,9 +1272,10 @@ struct CombatDamage_Struct
|
||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||
/* 05 */ uint16 spellid;
|
||||
/* 07 */ int32 damage;
|
||||
/* 11 */ float unknown11; // cd cc cc 3d
|
||||
/* 15 */ float sequence; // see above notes in Action_Struct
|
||||
/* 19 */ uint8 unknown19[9]; // was [9]
|
||||
/* 11 */ float force; // cd cc cc 3d
|
||||
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
|
||||
/* 19 */ float meleepush_z;
|
||||
/* 23 */ uint8 unknown23[5]; // was [9]
|
||||
/* 28 */
|
||||
};
|
||||
|
||||
@@ -2357,7 +2372,7 @@ struct BookRequest_Struct {
|
||||
**
|
||||
*/
|
||||
struct Object_Struct {
|
||||
/*00*/ uint32 linked_list_addr[2];// <Zaphod> They are, get this, prev and next, ala linked list
|
||||
/*00*/ uint32 linked_list_addr[2];// They are, get this, prev and next, ala linked list
|
||||
/*08*/ uint32 unknown008; // Something related to the linked list?
|
||||
/*12*/ uint32 drop_id; // Unique object id for zone
|
||||
/*16*/ uint16 zone_id; // Redudant, but: Zone the object appears in
|
||||
@@ -2377,8 +2392,8 @@ struct Object_Struct {
|
||||
/*100*/ uint32 spawn_id; // Spawn Id of client interacting with object
|
||||
/*104*/
|
||||
};
|
||||
//<Zaphod> 01 = generic drop, 02 = armor, 19 = weapon
|
||||
//[13:40] <Zaphod> and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject
|
||||
//01 = generic drop, 02 = armor, 19 = weapon
|
||||
//[13:40] and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject
|
||||
|
||||
/*
|
||||
** Click Object Struct
|
||||
@@ -3686,30 +3701,35 @@ struct DynamicWall_Struct {
|
||||
/*80*/
|
||||
};
|
||||
|
||||
enum { //bandolier actions
|
||||
BandolierCreate = 0,
|
||||
BandolierRemove = 1,
|
||||
BandolierSet = 2
|
||||
// Bandolier actions
|
||||
enum
|
||||
{
|
||||
bandolierCreate = 0,
|
||||
bandolierRemove,
|
||||
bandolierSet
|
||||
};
|
||||
|
||||
struct BandolierCreate_Struct {
|
||||
/*00*/ uint32 action; //0 for create
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ char name[32];
|
||||
/*37*/ uint16 unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 unknown39; //0
|
||||
struct BandolierCreate_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; //0 for create
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ char Name[32];
|
||||
/*37*/ uint16 Unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 Unknown39; //0
|
||||
};
|
||||
|
||||
struct BandolierDelete_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierDelete_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct BandolierSet_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierSet_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct Arrow_Struct {
|
||||
@@ -3799,10 +3819,16 @@ struct SendAA_Struct {
|
||||
/*0069*/ uint32 last_id;
|
||||
/*0073*/ uint32 next_id;
|
||||
/*0077*/ uint32 cost2;
|
||||
/*0081*/ uint8 unknown80[7];
|
||||
/*0081*/ uint8 unknown81;
|
||||
/*0082*/ uint8 grant_only; // VetAAs, progression, etc
|
||||
/*0083*/ uint8 unknown83; // 1 for skill cap increase AAs, Mystical Attuning, and RNG attack inc, doesn't seem to matter though
|
||||
/*0084*/ uint32 expendable_charges; // max charges of the AA
|
||||
/*0088*/ uint32 aa_expansion;
|
||||
/*0092*/ uint32 special_category;
|
||||
/*0096*/ uint32 unknown0096;
|
||||
/*0096*/ uint8 shroud;
|
||||
/*0097*/ uint8 unknown97;
|
||||
/*0098*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter?
|
||||
/*0099*/ uint8 unknown99;
|
||||
/*0100*/ uint32 total_abilities;
|
||||
/*0104*/ AA_Ability abilities[0];
|
||||
};
|
||||
@@ -3818,12 +3844,6 @@ struct AA_Action {
|
||||
/*12*/ uint32 exp_value;
|
||||
};
|
||||
|
||||
struct AA_Skills { //this should be removed and changed to AA_Array
|
||||
/*00*/ uint32 aa_skill; // Total AAs Spent
|
||||
/*04*/ uint32 aa_value;
|
||||
/*08*/ uint32 unknown08;
|
||||
};
|
||||
|
||||
struct AAExpUpdate_Struct {
|
||||
/*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability
|
||||
/*04*/ uint32 aapoints_unspent;
|
||||
@@ -3841,12 +3861,12 @@ struct AltAdvStats_Struct {
|
||||
};
|
||||
|
||||
struct PlayerAA_Struct { // Is this still used?
|
||||
AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct AATable_Struct {
|
||||
/*00*/ int32 aa_spent; // Total AAs Spent
|
||||
/*04*/ AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
/*04*/ AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct Weather_Struct {
|
||||
|
||||
+146
-120
@@ -426,7 +426,9 @@ namespace SoF
|
||||
OUT(type);
|
||||
OUT(spellid);
|
||||
OUT(damage);
|
||||
eq->sequence = emu->sequence;
|
||||
OUT(force)
|
||||
OUT(meleepush_xy);
|
||||
OUT(meleepush_z)
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@@ -1200,13 +1202,13 @@ namespace SoF
|
||||
OUT(beard);
|
||||
// OUT(unknown00178[10]);
|
||||
for (r = 0; r < 9; r++) {
|
||||
eq->equipment[r].material = emu->item_material[r];
|
||||
eq->equipment[r].unknown1 = 0;
|
||||
eq->equipment[r].elitematerial = 0;
|
||||
eq->equipment[r].Material = emu->item_material[r];
|
||||
eq->equipment[r].Unknown1 = 0;
|
||||
eq->equipment[r].EliteMaterial = 0;
|
||||
//eq->colors[r].color = emu->colors[r].color;
|
||||
}
|
||||
for (r = 0; r < 7; r++) {
|
||||
OUT(item_tint[r].color);
|
||||
OUT(item_tint[r].Color);
|
||||
}
|
||||
// OUT(unknown00224[48]);
|
||||
//NOTE: new client supports 300 AAs, our internal rep/PP
|
||||
@@ -1214,6 +1216,7 @@ namespace SoF
|
||||
for (r = 0; r < MAX_PP_AA_ARRAY; r++) {
|
||||
OUT(aa_array[r].AA);
|
||||
OUT(aa_array[r].value);
|
||||
OUT(aa_array[r].charges);
|
||||
}
|
||||
// OUT(unknown02220[4]);
|
||||
OUT(mana);
|
||||
@@ -1264,26 +1267,46 @@ namespace SoF
|
||||
OUT(endurance);
|
||||
OUT(aapoints_spent);
|
||||
OUT(aapoints);
|
||||
|
||||
// OUT(unknown06160[4]);
|
||||
//NOTE: new client supports 20 bandoliers, our internal rep
|
||||
//only supports 4..
|
||||
for (r = 0; r < 4; r++) {
|
||||
OUT_str(bandoliers[r].name);
|
||||
uint32 k;
|
||||
for (k = 0; k < structs::MAX_PLAYER_BANDOLIER_ITEMS; k++) {
|
||||
OUT(bandoliers[r].items[k].item_id);
|
||||
OUT(bandoliers[r].items[k].icon);
|
||||
OUT_str(bandoliers[r].items[k].item_name);
|
||||
|
||||
// Copy bandoliers where server and client indexes converge
|
||||
for (r = 0; r < EmuConstants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) {
|
||||
OUT_str(bandoliers[r].Name);
|
||||
for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true
|
||||
OUT(bandoliers[r].Items[k].ID);
|
||||
OUT(bandoliers[r].Items[k].Icon);
|
||||
OUT_str(bandoliers[r].Items[k].Name);
|
||||
}
|
||||
}
|
||||
// OUT(unknown07444[5120]);
|
||||
for (r = 0; r < structs::MAX_POTIONS_IN_BELT; r++) {
|
||||
OUT(potionbelt.items[r].item_id);
|
||||
OUT(potionbelt.items[r].icon);
|
||||
OUT_str(potionbelt.items[r].item_name);
|
||||
// Nullify bandoliers where server and client indexes diverge, with a client bias
|
||||
for (r = EmuConstants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) {
|
||||
eq->bandoliers[r].Name[0] = '\0';
|
||||
for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true
|
||||
eq->bandoliers[r].Items[k].ID = 0;
|
||||
eq->bandoliers[r].Items[k].Icon = 0;
|
||||
eq->bandoliers[r].Items[k].Name[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
// OUT(unknown07444[5120]);
|
||||
|
||||
// Copy potion belt where server and client indexes converge
|
||||
for (r = 0; r < EmuConstants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) {
|
||||
OUT(potionbelt.Items[r].ID);
|
||||
OUT(potionbelt.Items[r].Icon);
|
||||
OUT_str(potionbelt.Items[r].Name);
|
||||
}
|
||||
// Nullify potion belt where server and client indexes diverge, with a client bias
|
||||
for (r = EmuConstants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) {
|
||||
eq->potionbelt.Items[r].ID = 0;
|
||||
eq->potionbelt.Items[r].Icon = 0;
|
||||
eq->potionbelt.Items[r].Name[0] = '\0';
|
||||
}
|
||||
|
||||
// OUT(unknown12852[8]);
|
||||
// OUT(unknown12864[76]);
|
||||
|
||||
OUT_str(name);
|
||||
OUT_str(last_name);
|
||||
OUT(guild_id);
|
||||
@@ -1535,6 +1558,7 @@ namespace SoF
|
||||
OUT(cost2);
|
||||
eq->aa_expansion = emu->aa_expansion;
|
||||
eq->special_category = emu->special_category;
|
||||
eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number
|
||||
OUT(total_abilities);
|
||||
unsigned int r;
|
||||
for (r = 0; r < emu->total_abilities; r++) {
|
||||
@@ -1550,76 +1574,96 @@ namespace SoF
|
||||
|
||||
ENCODE(OP_SendCharInfo)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(CharacterSelect_Struct);
|
||||
ENCODE_LENGTH_ATLEAST(CharacterSelect_Struct);
|
||||
SETUP_VAR_ENCODE(CharacterSelect_Struct);
|
||||
|
||||
//EQApplicationPacket *packet = *p;
|
||||
//const CharacterSelect_Struct *emu = (CharacterSelect_Struct *) packet->pBuffer;
|
||||
// Zero-character count shunt
|
||||
if (emu->CharCount == 0) {
|
||||
ALLOC_VAR_ENCODE(structs::CharacterSelect_Struct, sizeof(structs::CharacterSelect_Struct));
|
||||
eq->CharCount = emu->CharCount;
|
||||
eq->TotalChars = emu->TotalChars;
|
||||
|
||||
int char_count;
|
||||
int namelen = 0;
|
||||
for (char_count = 0; char_count < 10; char_count++) {
|
||||
if (emu->name[char_count][0] == '\0')
|
||||
break;
|
||||
if (strcmp(emu->name[char_count], "<none>") == 0)
|
||||
break;
|
||||
namelen += strlen(emu->name[char_count]);
|
||||
if (eq->TotalChars > consts::CHARACTER_CREATION_LIMIT)
|
||||
eq->TotalChars = consts::CHARACTER_CREATION_LIMIT;
|
||||
|
||||
FINISH_ENCODE();
|
||||
return;
|
||||
}
|
||||
|
||||
int total_length = sizeof(structs::CharacterSelect_Struct)
|
||||
+ char_count * sizeof(structs::CharacterSelectEntry_Struct)
|
||||
+ namelen;
|
||||
unsigned char *emu_ptr = __emu_buffer;
|
||||
emu_ptr += sizeof(CharacterSelect_Struct);
|
||||
CharacterSelectEntry_Struct *emu_cse = (CharacterSelectEntry_Struct *)nullptr;
|
||||
|
||||
size_t names_length = 0;
|
||||
size_t character_count = 0;
|
||||
for (; character_count < emu->CharCount && character_count < consts::CHARACTER_CREATION_LIMIT; ++character_count) {
|
||||
emu_cse = (CharacterSelectEntry_Struct *)emu_ptr;
|
||||
names_length += strlen(emu_cse->Name);
|
||||
emu_ptr += sizeof(CharacterSelectEntry_Struct);
|
||||
}
|
||||
|
||||
size_t total_length = sizeof(structs::CharacterSelect_Struct)
|
||||
+ character_count * sizeof(structs::CharacterSelectEntry_Struct)
|
||||
+ names_length;
|
||||
|
||||
ALLOC_VAR_ENCODE(structs::CharacterSelect_Struct, total_length);
|
||||
structs::CharacterSelectEntry_Struct *eq_cse = (structs::CharacterSelectEntry_Struct *)nullptr;
|
||||
|
||||
//unsigned char *eq_buffer = new unsigned char[total_length];
|
||||
//structs::CharacterSelect_Struct *eq_head = (structs::CharacterSelect_Struct *) eq_buffer;
|
||||
eq->CharCount = character_count;
|
||||
eq->TotalChars = emu->TotalChars;
|
||||
|
||||
eq->char_count = char_count;
|
||||
eq->total_chars = 10;
|
||||
if (eq->TotalChars > consts::CHARACTER_CREATION_LIMIT)
|
||||
eq->TotalChars = consts::CHARACTER_CREATION_LIMIT;
|
||||
|
||||
unsigned char *bufptr = (unsigned char *)eq->entries;
|
||||
int r;
|
||||
for (r = 0; r < char_count; r++) {
|
||||
{ //pre-name section...
|
||||
structs::CharacterSelectEntry_Struct *eq2 = (structs::CharacterSelectEntry_Struct *) bufptr;
|
||||
eq2->level = emu->level[r];
|
||||
eq2->hairstyle = emu->hairstyle[r];
|
||||
eq2->gender = emu->gender[r];
|
||||
memcpy(eq2->name, emu->name[r], strlen(emu->name[r]) + 1);
|
||||
emu_ptr = __emu_buffer;
|
||||
emu_ptr += sizeof(CharacterSelect_Struct);
|
||||
|
||||
unsigned char *eq_ptr = __packet->pBuffer;
|
||||
eq_ptr += sizeof(structs::CharacterSelect_Struct);
|
||||
|
||||
for (int counter = 0; counter < character_count; ++counter) {
|
||||
emu_cse = (CharacterSelectEntry_Struct *)emu_ptr;
|
||||
eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // base address
|
||||
|
||||
eq_cse->Level = emu_cse->Level;
|
||||
eq_cse->HairStyle = emu_cse->HairStyle;
|
||||
eq_cse->Gender = emu_cse->Gender;
|
||||
|
||||
strcpy(eq_cse->Name, emu_cse->Name);
|
||||
eq_ptr += strlen(emu_cse->Name);
|
||||
eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // offset address (base + name length offset)
|
||||
eq_cse->Name[0] = '\0'; // (offset)eq_cse->Name[0] = (base)eq_cse->Name[strlen(emu_cse->Name)]
|
||||
|
||||
eq_cse->Beard = emu_cse->Beard;
|
||||
eq_cse->HairColor = emu_cse->HairColor;
|
||||
eq_cse->Face = emu_cse->Face;
|
||||
|
||||
for (int equip_index = 0; equip_index < _MaterialCount; equip_index++) {
|
||||
eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material;
|
||||
eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1;
|
||||
eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial;
|
||||
eq_cse->Equip[equip_index].Color.Color = emu_cse->Equip[equip_index].Color.Color;
|
||||
}
|
||||
//adjust for name.
|
||||
bufptr += strlen(emu->name[r]);
|
||||
{ //post-name section...
|
||||
structs::CharacterSelectEntry_Struct *eq2 = (structs::CharacterSelectEntry_Struct *) bufptr;
|
||||
eq2->beard = emu->beard[r];
|
||||
eq2->haircolor = emu->haircolor[r];
|
||||
eq2->face = emu->face[r];
|
||||
int k;
|
||||
for (k = 0; k < _MaterialCount; k++) {
|
||||
eq2->equip[k].material = emu->equip[r][k].material;
|
||||
eq2->equip[k].unknown1 = emu->equip[r][k].unknown1;
|
||||
eq2->equip[k].elitematerial = emu->equip[r][k].elitematerial;
|
||||
eq2->equip[k].color.color = emu->equip[r][k].color.color;
|
||||
}
|
||||
eq2->primary = emu->primary[r];
|
||||
eq2->secondary = emu->secondary[r];
|
||||
eq2->tutorial = emu->tutorial[r]; // was u15
|
||||
eq2->u15 = 0xff;
|
||||
eq2->deity = emu->deity[r];
|
||||
eq2->zone = emu->zone[r];
|
||||
eq2->u19 = 0xFF;
|
||||
eq2->race = emu->race[r];
|
||||
eq2->gohome = emu->gohome[r];
|
||||
eq2->class_ = emu->class_[r];
|
||||
eq2->eyecolor1 = emu->eyecolor1[r];
|
||||
eq2->beardcolor = emu->beardcolor[r];
|
||||
eq2->eyecolor2 = emu->eyecolor2[r];
|
||||
eq2->drakkin_heritage = emu->drakkin_heritage[r];
|
||||
eq2->drakkin_tattoo = emu->drakkin_tattoo[r];
|
||||
eq2->drakkin_details = emu->drakkin_details[r];
|
||||
}
|
||||
bufptr += sizeof(structs::CharacterSelectEntry_Struct);
|
||||
|
||||
eq_cse->PrimaryIDFile = emu_cse->PrimaryIDFile;
|
||||
eq_cse->SecondaryIDFile = emu_cse->SecondaryIDFile;
|
||||
eq_cse->Tutorial = emu_cse->Tutorial;
|
||||
eq_cse->Unknown15 = emu_cse->Unknown15;
|
||||
eq_cse->Deity = emu_cse->Deity;
|
||||
eq_cse->Zone = emu_cse->Zone;
|
||||
eq_cse->Unknown19 = emu_cse->Unknown19;
|
||||
eq_cse->Race = emu_cse->Race;
|
||||
eq_cse->GoHome = emu_cse->GoHome;
|
||||
eq_cse->Class = emu_cse->Class;
|
||||
eq_cse->EyeColor1 = emu_cse->EyeColor1;
|
||||
eq_cse->BeardColor = emu_cse->BeardColor;
|
||||
eq_cse->EyeColor2 = emu_cse->EyeColor2;
|
||||
eq_cse->DrakkinHeritage = emu_cse->DrakkinHeritage;
|
||||
eq_cse->DrakkinTattoo = emu_cse->DrakkinTattoo;
|
||||
eq_cse->DrakkinDetails = emu_cse->DrakkinDetails;
|
||||
|
||||
emu_ptr += sizeof(CharacterSelectEntry_Struct);
|
||||
eq_ptr += sizeof(structs::CharacterSelectEntry_Struct);
|
||||
}
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -1941,7 +1985,7 @@ namespace SoF
|
||||
OUT(material);
|
||||
OUT(unknown06);
|
||||
OUT(elite_material);
|
||||
OUT(color.color);
|
||||
OUT(color.Color);
|
||||
OUT(wear_slot_id);
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -1951,42 +1995,23 @@ namespace SoF
|
||||
|
||||
ENCODE(OP_ZonePlayerToBind)
|
||||
{
|
||||
ENCODE_LENGTH_ATLEAST(ZonePlayerToBind_Struct);
|
||||
SETUP_VAR_ENCODE(ZonePlayerToBind_Struct);
|
||||
ALLOC_LEN_ENCODE(sizeof(structs::ZonePlayerToBind_Struct) + strlen(emu->zone_name));
|
||||
|
||||
ZonePlayerToBind_Struct *zps = (ZonePlayerToBind_Struct*)(*p)->pBuffer;
|
||||
__packet->SetWritePosition(0);
|
||||
__packet->WriteUInt16(emu->bind_zone_id);
|
||||
__packet->WriteUInt16(emu->bind_instance_id);
|
||||
__packet->WriteFloat(emu->x);
|
||||
__packet->WriteFloat(emu->y);
|
||||
__packet->WriteFloat(emu->z);
|
||||
__packet->WriteFloat(emu->heading);
|
||||
__packet->WriteString(emu->zone_name);
|
||||
__packet->WriteUInt8(1); // save items
|
||||
__packet->WriteUInt32(0); // hp
|
||||
__packet->WriteUInt32(0); // mana
|
||||
__packet->WriteUInt32(0); // endurance
|
||||
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
||||
|
||||
unsigned char *buffer1 = new unsigned char[sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name)];
|
||||
structs::ZonePlayerToBindHeader_Struct *zph = (structs::ZonePlayerToBindHeader_Struct*)buffer1;
|
||||
unsigned char *buffer2 = new unsigned char[sizeof(structs::ZonePlayerToBindFooter_Struct)];
|
||||
structs::ZonePlayerToBindFooter_Struct *zpf = (structs::ZonePlayerToBindFooter_Struct*)buffer2;
|
||||
|
||||
zph->x = zps->x;
|
||||
zph->y = zps->y;
|
||||
zph->z = zps->z;
|
||||
zph->heading = zps->heading;
|
||||
zph->bind_zone_id = zps->bind_zone_id;
|
||||
zph->bind_instance_id = zps->bind_instance_id;
|
||||
strcpy(zph->zone_name, zps->zone_name);
|
||||
|
||||
zpf->unknown021 = 1;
|
||||
zpf->unknown022 = 0;
|
||||
zpf->unknown023 = 0;
|
||||
zpf->unknown024 = 0;
|
||||
|
||||
ss.write((const char*)buffer1, (sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name)));
|
||||
ss.write((const char*)buffer2, sizeof(structs::ZonePlayerToBindFooter_Struct));
|
||||
|
||||
delete[] buffer1;
|
||||
delete[] buffer2;
|
||||
delete[](*p)->pBuffer;
|
||||
|
||||
(*p)->pBuffer = new unsigned char[ss.str().size()];
|
||||
(*p)->size = ss.str().size();
|
||||
|
||||
memcpy((*p)->pBuffer, ss.str().c_str(), ss.str().size());
|
||||
dest->FastQueuePacket(&(*p));
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ZoneServerInfo)
|
||||
@@ -2044,10 +2069,10 @@ namespace SoF
|
||||
eq->drakkin_heritage = emu->drakkin_heritage;
|
||||
eq->gender = emu->gender;
|
||||
for (k = 0; k < 9; k++) {
|
||||
eq->equipment[k].material = emu->equipment[k].material;
|
||||
eq->equipment[k].unknown1 = emu->equipment[k].unknown1;
|
||||
eq->equipment[k].elitematerial = emu->equipment[k].elitematerial;
|
||||
eq->colors[k].color = emu->colors[k].color;
|
||||
eq->equipment[k].Material = emu->equipment[k].Material;
|
||||
eq->equipment[k].Unknown1 = emu->equipment[k].Unknown1;
|
||||
eq->equipment[k].EliteMaterial = emu->equipment[k].EliteMaterial;
|
||||
eq->colors[k].Color = emu->colors[k].Color;
|
||||
}
|
||||
eq->StandState = emu->StandState;
|
||||
eq->guildID = emu->guildID;
|
||||
@@ -2066,6 +2091,7 @@ namespace SoF
|
||||
eq->runspeed = emu->runspeed;
|
||||
eq->light = emu->light;
|
||||
eq->level = emu->level;
|
||||
eq->PlayerState = emu->PlayerState;
|
||||
eq->lfg = emu->lfg;
|
||||
eq->hairstyle = emu->hairstyle;
|
||||
eq->haircolor = emu->haircolor;
|
||||
@@ -2109,7 +2135,7 @@ namespace SoF
|
||||
eq->petOwnerId = emu->petOwnerId;
|
||||
eq->pvp = 0; // 0 = non-pvp colored name, 1 = red pvp name
|
||||
for (k = 0; k < 9; k++) {
|
||||
eq->colors[k].color = emu->colors[k].color;
|
||||
eq->colors[k].Color = emu->colors[k].Color;
|
||||
}
|
||||
eq->anon = emu->anon;
|
||||
eq->face = emu->face;
|
||||
@@ -2667,7 +2693,7 @@ namespace SoF
|
||||
default:
|
||||
emu->command = eq->command;
|
||||
}
|
||||
OUT(unknown);
|
||||
IN(target);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@@ -2808,7 +2834,7 @@ namespace SoF
|
||||
IN(material);
|
||||
IN(unknown06);
|
||||
IN(elite_material);
|
||||
IN(color.color);
|
||||
IN(color.Color);
|
||||
IN(wear_slot_id);
|
||||
emu->hero_forge_model = 0;
|
||||
emu->unknown18 = 0;
|
||||
|
||||
@@ -101,6 +101,8 @@ namespace SoF {
|
||||
}
|
||||
|
||||
namespace consts {
|
||||
static const size_t CHARACTER_CREATION_LIMIT = 12;
|
||||
|
||||
static const uint16 MAP_POSSESSIONS_SIZE = slots::_MainCount;
|
||||
static const uint16 MAP_BANK_SIZE = 24;
|
||||
static const uint16 MAP_SHARED_BANK_SIZE = 2;
|
||||
@@ -174,9 +176,10 @@ namespace SoF {
|
||||
static const uint16 ITEM_COMMON_SIZE = 5;
|
||||
static const uint16 ITEM_CONTAINER_SIZE = 10;
|
||||
|
||||
static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances
|
||||
static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance
|
||||
static const uint32 POTION_BELT_SIZE = 5;
|
||||
static const size_t BANDOLIERS_SIZE = 20; // number of bandolier instances
|
||||
static const size_t BANDOLIER_ITEM_COUNT = 4; // number of equipment slots in bandolier instance
|
||||
|
||||
static const size_t POTION_BELT_ITEM_COUNT = 5;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 50;
|
||||
}
|
||||
|
||||
+130
-110
@@ -103,72 +103,74 @@ struct AdventureInfo {
|
||||
*/
|
||||
struct Color_Struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8 blue;
|
||||
uint8 green;
|
||||
uint8 red;
|
||||
uint8 use_tint; // if there's a tint this is FF
|
||||
} rgb;
|
||||
uint32 color;
|
||||
union {
|
||||
struct {
|
||||
uint8 Blue;
|
||||
uint8 Green;
|
||||
uint8 Red;
|
||||
uint8 UseTint; // if there's a tint this is FF
|
||||
} RGB;
|
||||
uint32 Color;
|
||||
};
|
||||
};
|
||||
|
||||
struct CharSelectEquip {
|
||||
uint32 material;
|
||||
uint32 unknown1;
|
||||
uint32 elitematerial;
|
||||
Color_Struct color;
|
||||
struct CharSelectEquip
|
||||
{
|
||||
uint32 Material;
|
||||
uint32 Unknown1;
|
||||
uint32 EliteMaterial;
|
||||
Color_Struct Color;
|
||||
};
|
||||
|
||||
struct CharacterSelectEntry_Struct {
|
||||
/*0000*/ uint8 level; //
|
||||
/*0000*/ uint8 hairstyle; //
|
||||
/*0002*/ uint8 gender; //
|
||||
/*0003*/ char name[1]; //variable length, edi+0
|
||||
/*0000*/ uint8 beard; //
|
||||
/*0001*/ uint8 haircolor; //
|
||||
/*0000*/ uint8 face; //
|
||||
/*0000*/ CharSelectEquip equip[9];
|
||||
/*0000*/ uint32 primary; //
|
||||
/*0000*/ uint32 secondary; //
|
||||
/*0000*/ uint8 u15; // 0xff
|
||||
/*0000*/ uint32 deity; //
|
||||
/*0000*/ uint16 zone; //
|
||||
/*0000*/ uint16 instance;
|
||||
/*0000*/ uint8 gohome; //
|
||||
/*0000*/ uint8 u19; // 0xff
|
||||
/*0000*/ uint32 race; //
|
||||
/*0000*/ uint8 tutorial; //
|
||||
/*0000*/ uint8 class_; //
|
||||
/*0000*/ uint8 eyecolor1; //
|
||||
/*0000*/ uint8 beardcolor; //
|
||||
/*0000*/ uint8 eyecolor2; //
|
||||
/*0000*/ uint32 drakkin_heritage; // Drakkin Heritage
|
||||
/*0000*/ uint32 drakkin_tattoo; // Drakkin Tattoo
|
||||
/*0000*/ uint32 drakkin_details; // Drakkin Details (Facial Spikes)
|
||||
struct CharacterSelectEntry_Struct
|
||||
{
|
||||
/*0000*/ uint8 Level; //
|
||||
/*0000*/ uint8 HairStyle; //
|
||||
/*0002*/ uint8 Gender; //
|
||||
/*0003*/ char Name[1]; // variable length, edi+0
|
||||
/*0000*/ uint8 Beard; //
|
||||
/*0001*/ uint8 HairColor; //
|
||||
/*0000*/ uint8 Face; //
|
||||
/*0000*/ CharSelectEquip Equip[9];
|
||||
/*0000*/ uint32 PrimaryIDFile; //
|
||||
/*0000*/ uint32 SecondaryIDFile; //
|
||||
/*0000*/ uint8 Unknown15; // 0xff
|
||||
/*0000*/ uint32 Deity; //
|
||||
/*0000*/ uint16 Zone; //
|
||||
/*0000*/ uint16 Instance;
|
||||
/*0000*/ uint8 GoHome; //
|
||||
/*0000*/ uint8 Unknown19; // 0xff
|
||||
/*0000*/ uint32 Race; //
|
||||
/*0000*/ uint8 Tutorial; //
|
||||
/*0000*/ uint8 Class; //
|
||||
/*0000*/ uint8 EyeColor1; //
|
||||
/*0000*/ uint8 BeardColor; //
|
||||
/*0000*/ uint8 EyeColor2; //
|
||||
/*0000*/ uint32 DrakkinHeritage; // Drakkin Heritage
|
||||
/*0000*/ uint32 DrakkinTattoo; // Drakkin Tattoo
|
||||
/*0000*/ uint32 DrakkinDetails; // Drakkin Details (Facial Spikes)
|
||||
};
|
||||
|
||||
/*
|
||||
** Character Selection Struct
|
||||
**
|
||||
*/
|
||||
struct CharacterSelect_Struct {
|
||||
/*0000*/ uint32 char_count; //number of chars in this packet
|
||||
/*0004*/ uint32 total_chars; //total number of chars allowed?
|
||||
/*0008*/ CharacterSelectEntry_Struct entries[0];
|
||||
struct CharacterSelect_Struct
|
||||
{
|
||||
/*0000*/ uint32 CharCount; //number of chars in this packet
|
||||
/*0004*/ uint32 TotalChars; //total number of chars allowed?
|
||||
/*0008*/ CharacterSelectEntry_Struct Entries[0];
|
||||
};
|
||||
|
||||
/*
|
||||
* Visible equiptment.
|
||||
* Size: 12 Octets
|
||||
*/
|
||||
struct EquipStruct {
|
||||
/*00*/ uint32 material;
|
||||
/*04*/ uint32 unknown1;
|
||||
/*08*/ uint32 elitematerial;
|
||||
struct EquipStruct
|
||||
{
|
||||
/*00*/ uint32 Material;
|
||||
/*04*/ uint32 Unknown1;
|
||||
/*08*/ uint32 EliteMaterial;
|
||||
/*12*/
|
||||
};
|
||||
|
||||
@@ -239,7 +241,8 @@ struct Spawn_Struct {
|
||||
/*0506*/ uint8 light; // Spawn's lightsource
|
||||
/*0507*/ uint8 unknown0507[4];
|
||||
/*0511*/ uint8 level; // Spawn Level
|
||||
/*0512*/ uint8 unknown0512[16];
|
||||
/*0512*/ uint32 PlayerState;
|
||||
/*0516*/ uint8 unknown0516[12];
|
||||
/*0528*/ uint8 lfg;
|
||||
/*0529*/ uint8 unknown0529[4];
|
||||
/*0533*/ uint8 hairstyle; // Sets the style of hair
|
||||
@@ -523,7 +526,7 @@ struct SpellBuff_Struct
|
||||
/*002*/ uint8 bard_modifier;
|
||||
/*003*/ uint8 effect; //not real
|
||||
/*004*/ uint32 spellid;
|
||||
/*008*/ uint32 duration;
|
||||
/*008*/ int32 duration;
|
||||
/*012*/ uint32 counters;
|
||||
/*016*/ uint32 unknown004; //Might need to be swapped with player_id
|
||||
/*020*/ uint32 player_id; //'global' ID of the caster, for wearoff messages
|
||||
@@ -540,7 +543,7 @@ struct SpellBuffFade_Struct {
|
||||
/*006*/ uint8 effect;
|
||||
/*007*/ uint8 unknown7;
|
||||
/*008*/ uint32 spellid;
|
||||
/*012*/ uint32 duration;
|
||||
/*012*/ int32 duration;
|
||||
/*016*/ uint32 unknown016;
|
||||
/*020*/ uint32 unknown020; //prolly global player ID
|
||||
/*024*/ uint32 playerId; // Player id who cast the buff
|
||||
@@ -642,7 +645,7 @@ struct AA_Array
|
||||
{
|
||||
uint32 AA;
|
||||
uint32 value;
|
||||
uint32 unknown08; // Looks like AA_Array is now 12 bytes in Live
|
||||
uint32 charges; // expendable charges
|
||||
};
|
||||
|
||||
|
||||
@@ -653,9 +656,6 @@ struct Disciplines_Struct {
|
||||
};
|
||||
|
||||
static const uint32 MAX_PLAYER_TRIBUTES = 5;
|
||||
static const uint32 MAX_PLAYER_BANDOLIER = 20;
|
||||
static const uint32 MAX_PLAYER_BANDOLIER_ITEMS = 4;
|
||||
static const uint32 MAX_POTIONS_IN_BELT = 5;
|
||||
static const uint32 TRIBUTE_NONE = 0xFFFFFFFF;
|
||||
|
||||
struct Tribute_Struct {
|
||||
@@ -663,26 +663,42 @@ struct Tribute_Struct {
|
||||
uint32 tier;
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct {
|
||||
uint32 item_id;
|
||||
uint32 icon;
|
||||
char item_name[64];
|
||||
};
|
||||
|
||||
//len = 320
|
||||
enum { //bandolier item positions
|
||||
bandolierMainHand = 0,
|
||||
bandolierOffHand,
|
||||
// Bandolier item positions
|
||||
enum
|
||||
{
|
||||
bandolierPrimary = 0,
|
||||
bandolierSecondary,
|
||||
bandolierRange,
|
||||
bandolierAmmo
|
||||
};
|
||||
struct Bandolier_Struct {
|
||||
char name[32];
|
||||
BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS];
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
struct PotionBelt_Struct {
|
||||
BandolierItem_Struct items[MAX_POTIONS_IN_BELT];
|
||||
|
||||
//len = 320
|
||||
struct Bandolier_Struct
|
||||
{
|
||||
char Name[32];
|
||||
BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT];
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct PotionBeltItem_Struct
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
//len = 288
|
||||
struct PotionBelt_Struct
|
||||
{
|
||||
PotionBeltItem_Struct Items[consts::POTION_BELT_ITEM_COUNT];
|
||||
};
|
||||
|
||||
static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16;
|
||||
@@ -901,7 +917,7 @@ struct PlayerProfile_Struct //23576 Octets
|
||||
/*08288*/ uint32 aapoints_spent; // Number of spent AA points
|
||||
/*08292*/ uint32 aapoints; // Unspent AA points
|
||||
/*08296*/ uint8 unknown06160[4];
|
||||
/*08300*/ Bandolier_Struct bandoliers[MAX_PLAYER_BANDOLIER]; // [6400] bandolier contents
|
||||
/*08300*/ Bandolier_Struct bandoliers[consts::BANDOLIERS_SIZE]; // [6400] bandolier contents
|
||||
/*14700*/ PotionBelt_Struct potionbelt; // [360] potion belt 72 extra octets by adding 1 more belt slot
|
||||
/*15060*/ uint8 unknown12852[8];
|
||||
/*15068*/ uint32 available_slots;
|
||||
@@ -1053,7 +1069,7 @@ struct TargetReject_Struct {
|
||||
|
||||
struct PetCommand_Struct {
|
||||
/*000*/ uint32 command;
|
||||
/*004*/ uint32 unknown;
|
||||
/*004*/ uint32 target;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1167,8 +1183,8 @@ struct RequestClientZoneChange_Struct {
|
||||
|
||||
struct Animation_Struct {
|
||||
/*00*/ uint16 spawnid;
|
||||
/*02*/ uint8 action;
|
||||
/*03*/ uint8 value;
|
||||
/*02*/ uint8 speed;
|
||||
/*03*/ uint8 action;
|
||||
/*04*/
|
||||
};
|
||||
|
||||
@@ -1234,9 +1250,10 @@ struct CombatDamage_Struct
|
||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||
/* 05 */ uint16 spellid;
|
||||
/* 07 */ int32 damage;
|
||||
/* 11 */ float unknown11; // cd cc cc 3d
|
||||
/* 15 */ float sequence; // see above notes in Action_Struct
|
||||
/* 19 */ uint8 unknown19[9]; // was [9]
|
||||
/* 11 */ float force; // cd cc cc 3d
|
||||
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
|
||||
/* 19 */ float meleepush_z;
|
||||
/* 23 */ uint8 unknown23[5]; // was [9]
|
||||
/* 28 */
|
||||
};
|
||||
|
||||
@@ -2290,7 +2307,7 @@ struct BookRequest_Struct {
|
||||
**
|
||||
*/
|
||||
struct Object_Struct {
|
||||
/*00*/ uint32 linked_list_addr[2];// <Zaphod> They are, get this, prev and next, ala linked list
|
||||
/*00*/ uint32 linked_list_addr[2];// They are, get this, prev and next, ala linked list
|
||||
/*08*/ uint32 unknown008; // Something related to the linked list?
|
||||
/*12*/ uint32 drop_id; // Unique object id for zone
|
||||
/*16*/ uint16 zone_id; // Redudant, but: Zone the object appears in
|
||||
@@ -2310,8 +2327,8 @@ struct Object_Struct {
|
||||
/*100*/ uint32 spawn_id; // Spawn Id of client interacting with object
|
||||
/*104*/
|
||||
};
|
||||
//<Zaphod> 01 = generic drop, 02 = armor, 19 = weapon
|
||||
//[13:40] <Zaphod> and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject
|
||||
//01 = generic drop, 02 = armor, 19 = weapon
|
||||
//[13:40] and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject
|
||||
|
||||
/*
|
||||
** Click Object Struct
|
||||
@@ -3548,30 +3565,35 @@ struct DynamicWall_Struct {
|
||||
/*80*/
|
||||
};
|
||||
|
||||
enum { //bandolier actions
|
||||
BandolierCreate = 0,
|
||||
BandolierRemove = 1,
|
||||
BandolierSet = 2
|
||||
// Bandolier actions
|
||||
enum
|
||||
{
|
||||
bandolierCreate = 0,
|
||||
bandolierRemove,
|
||||
bandolierSet
|
||||
};
|
||||
|
||||
struct BandolierCreate_Struct {
|
||||
/*00*/ uint32 action; //0 for create
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ char name[32];
|
||||
/*37*/ uint16 unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 unknown39; //0
|
||||
struct BandolierCreate_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; //0 for create
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ char Name[32];
|
||||
/*37*/ uint16 Unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 Unknown39; //0
|
||||
};
|
||||
|
||||
struct BandolierDelete_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierDelete_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct BandolierSet_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierSet_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct Arrow_Struct {
|
||||
@@ -3661,10 +3683,14 @@ struct SendAA_Struct {
|
||||
/*0069*/ uint32 last_id;
|
||||
/*0073*/ uint32 next_id;
|
||||
/*0077*/ uint32 cost2;
|
||||
/*0081*/ uint8 unknown80[7];
|
||||
/*0081*/ uint8 unknown81;
|
||||
/*0082*/ uint8 grant_only; // VetAAs, progression, etc
|
||||
/*0083*/ uint8 unknown83; // 1 for skill cap increase AAs, Mystical Attuning, and RNG attack inc, doesn't seem to matter though
|
||||
/*0084*/ uint32 expendable_charges; // max charges of the AA
|
||||
/*0088*/ uint32 aa_expansion;
|
||||
/*0092*/ uint32 special_category;
|
||||
/*0096*/ uint16 unknown0096;
|
||||
/*0096*/ uint8 shroud;
|
||||
/*0097*/ uint8 unknown97;
|
||||
/*0098*/ uint32 total_abilities;
|
||||
/*0102*/ AA_Ability abilities[0];
|
||||
};
|
||||
@@ -3680,12 +3706,6 @@ struct AA_Action {
|
||||
/*12*/ uint32 exp_value;
|
||||
};
|
||||
|
||||
struct AA_Skills { //this should be removed and changed to AA_Array
|
||||
/*00*/ uint32 aa_skill; // Total AAs Spent
|
||||
/*04*/ uint32 aa_value;
|
||||
/*08*/ uint32 unknown08;
|
||||
};
|
||||
|
||||
struct AAExpUpdate_Struct {
|
||||
/*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability
|
||||
/*04*/ uint32 aapoints_unspent;
|
||||
@@ -3703,12 +3723,12 @@ struct AltAdvStats_Struct {
|
||||
};
|
||||
|
||||
struct PlayerAA_Struct {
|
||||
AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct AATable_Struct {
|
||||
/*00*/ int32 aa_spent; // Total AAs Spent
|
||||
/*04*/ AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
/*04*/ AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct Weather_Struct {
|
||||
|
||||
@@ -41,6 +41,11 @@
|
||||
memset(__packet->pBuffer, 0, len); \
|
||||
eq_struct *eq = (eq_struct *) __packet->pBuffer; \
|
||||
|
||||
#define ALLOC_LEN_ENCODE(len) \
|
||||
__packet->pBuffer = new unsigned char[len]; \
|
||||
__packet->size = len; \
|
||||
memset(__packet->pBuffer, 0, len); \
|
||||
|
||||
//a shorter assignment for direct mode
|
||||
#undef OUT
|
||||
#define OUT(x) eq->x = emu->x;
|
||||
@@ -124,14 +129,14 @@
|
||||
//check length of packet before decoding. Call before setup.
|
||||
#define DECODE_LENGTH_EXACT(struct_) \
|
||||
if(__packet->size != sizeof(struct_)) { \
|
||||
__packet->SetOpcode(OP_Unknown); /* invalidate the packet */ \
|
||||
Log.Out(Logs::Detail, Logs::Netcode, "Wrong size on incoming %s (" #struct_ "): Got %d, expected %d", opcodes->EmuToName(__packet->GetOpcode()), __packet->size, sizeof(struct_)); \
|
||||
__packet->SetOpcode(OP_Unknown); /* invalidate the packet */ \
|
||||
return; \
|
||||
}
|
||||
#define DECODE_LENGTH_ATLEAST(struct_) \
|
||||
if(__packet->size < sizeof(struct_)) { \
|
||||
__packet->SetOpcode(OP_Unknown); /* invalidate the packet */ \
|
||||
Log.Out(Logs::Detail, Logs::Netcode, "Wrong size on incoming %s (" #struct_ "): Got %d, expected at least %d", opcodes->EmuToName(__packet->GetOpcode()), __packet->size, sizeof(struct_)); \
|
||||
__packet->SetOpcode(OP_Unknown); /* invalidate the packet */ \
|
||||
return; \
|
||||
}
|
||||
|
||||
|
||||
+141
-60
@@ -122,7 +122,7 @@ namespace Titanium
|
||||
EAT_ENCODE(OP_GuildMemberLevelUpdate); // added ;
|
||||
|
||||
EAT_ENCODE(OP_ZoneServerReady); // added ;
|
||||
|
||||
|
||||
ENCODE(OP_Action)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(Action_Struct);
|
||||
@@ -326,7 +326,7 @@ namespace Titanium
|
||||
{
|
||||
SETUP_VAR_ENCODE(ExpeditionCompass_Struct);
|
||||
ALLOC_VAR_ENCODE(structs::ExpeditionCompass_Struct, sizeof(structs::ExpeditionInfo_Struct) + sizeof(structs::ExpeditionCompassEntry_Struct) * emu->count);
|
||||
|
||||
|
||||
OUT(count);
|
||||
|
||||
for (uint32 i = 0; i < emu->count; ++i)
|
||||
@@ -865,7 +865,7 @@ namespace Titanium
|
||||
// OUT(unknown00178[10]);
|
||||
for (r = 0; r < 9; r++) {
|
||||
OUT(item_material[r]);
|
||||
OUT(item_tint[r].color);
|
||||
OUT(item_tint[r].Color);
|
||||
}
|
||||
// OUT(unknown00224[48]);
|
||||
for (r = 0; r < structs::MAX_PP_AA_ARRAY; r++) {
|
||||
@@ -922,24 +922,46 @@ namespace Titanium
|
||||
OUT(endurance);
|
||||
OUT(aapoints_spent);
|
||||
OUT(aapoints);
|
||||
|
||||
// OUT(unknown06160[4]);
|
||||
for (r = 0; r < structs::MAX_PLAYER_BANDOLIER; r++) {
|
||||
OUT_str(bandoliers[r].name);
|
||||
uint32 k;
|
||||
for (k = 0; k < structs::MAX_PLAYER_BANDOLIER_ITEMS; k++) {
|
||||
OUT(bandoliers[r].items[k].item_id);
|
||||
OUT(bandoliers[r].items[k].icon);
|
||||
OUT_str(bandoliers[r].items[k].item_name);
|
||||
|
||||
// Copy bandoliers where server and client indexes converge
|
||||
for (r = 0; r < EmuConstants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) {
|
||||
OUT_str(bandoliers[r].Name);
|
||||
for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true
|
||||
OUT(bandoliers[r].Items[k].ID);
|
||||
OUT(bandoliers[r].Items[k].Icon);
|
||||
OUT_str(bandoliers[r].Items[k].Name);
|
||||
}
|
||||
}
|
||||
// OUT(unknown07444[5120]);
|
||||
for (r = 0; r < structs::MAX_PLAYER_BANDOLIER_ITEMS; r++) {
|
||||
OUT(potionbelt.items[r].item_id);
|
||||
OUT(potionbelt.items[r].icon);
|
||||
OUT_str(potionbelt.items[r].item_name);
|
||||
// Nullify bandoliers where server and client indexes diverge, with a client bias
|
||||
for (r = EmuConstants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) {
|
||||
eq->bandoliers[r].Name[0] = '\0';
|
||||
for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true
|
||||
eq->bandoliers[r].Items[k].ID = 0;
|
||||
eq->bandoliers[r].Items[k].Icon = 0;
|
||||
eq->bandoliers[r].Items[k].Name[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
// OUT(unknown07444[5120]);
|
||||
|
||||
// Copy potion belt where server and client indexes converge
|
||||
for (r = 0; r < EmuConstants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) {
|
||||
OUT(potionbelt.Items[r].ID);
|
||||
OUT(potionbelt.Items[r].Icon);
|
||||
OUT_str(potionbelt.Items[r].Name);
|
||||
}
|
||||
// Nullify potion belt where server and client indexes diverge, with a client bias
|
||||
for (r = EmuConstants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) {
|
||||
eq->potionbelt.Items[r].ID = 0;
|
||||
eq->potionbelt.Items[r].Icon = 0;
|
||||
eq->potionbelt.Items[r].Name[0] = '\0';
|
||||
}
|
||||
|
||||
// OUT(unknown12852[8]);
|
||||
// OUT(unknown12864[76]);
|
||||
|
||||
OUT_str(name);
|
||||
OUT_str(last_name);
|
||||
OUT(guild_id);
|
||||
@@ -1048,7 +1070,7 @@ namespace Titanium
|
||||
|
||||
ENCODE(OP_ReadBook)
|
||||
{
|
||||
// no apparent slot translation needed -U
|
||||
// no apparent slot translation needed
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
@@ -1076,8 +1098,8 @@ namespace Titanium
|
||||
|
||||
unsigned int r;
|
||||
for (r = 0; r < structs::MAX_PP_AA_ARRAY; r++) {
|
||||
OUT(aa_list[r].aa_skill);
|
||||
OUT(aa_list[r].aa_value);
|
||||
OUT(aa_list[r].AA);
|
||||
OUT(aa_list[r].value);
|
||||
}
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -1133,39 +1155,98 @@ namespace Titanium
|
||||
|
||||
ENCODE(OP_SendCharInfo)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(CharacterSelect_Struct);
|
||||
ENCODE_LENGTH_ATLEAST(CharacterSelect_Struct);
|
||||
SETUP_DIRECT_ENCODE(CharacterSelect_Struct, structs::CharacterSelect_Struct);
|
||||
|
||||
int r;
|
||||
for (r = 0; r < 10; r++) {
|
||||
OUT(zone[r]);
|
||||
OUT(eyecolor1[r]);
|
||||
OUT(eyecolor2[r]);
|
||||
OUT(hairstyle[r]);
|
||||
OUT(primary[r]);
|
||||
if (emu->race[r] > 473)
|
||||
eq->race[r] = 1;
|
||||
else
|
||||
eq->race[r] = emu->race[r];
|
||||
OUT(class_[r]);
|
||||
OUT_str(name[r]);
|
||||
OUT(gender[r]);
|
||||
OUT(level[r]);
|
||||
OUT(secondary[r]);
|
||||
OUT(face[r]);
|
||||
OUT(beard[r]);
|
||||
int k;
|
||||
for (k = 0; k < 9; k++) {
|
||||
eq->equip[r][k] = emu->equip[r][k].material;
|
||||
eq->cs_colors[r][k].color = emu->equip[r][k].color.color;
|
||||
unsigned char *emu_ptr = __emu_buffer;
|
||||
emu_ptr += sizeof(CharacterSelect_Struct);
|
||||
CharacterSelectEntry_Struct *emu_cse = (CharacterSelectEntry_Struct *)nullptr;
|
||||
|
||||
for (size_t index = 0; index < 10; ++index) {
|
||||
memset(eq->Name[index], 0, 64);
|
||||
}
|
||||
|
||||
// Non character-indexed packet fields
|
||||
eq->Unknown830[0] = 0;
|
||||
eq->Unknown830[1] = 0;
|
||||
eq->Unknown0962[0] = 0;
|
||||
eq->Unknown0962[1] = 0;
|
||||
|
||||
size_t char_index = 0;
|
||||
for (; char_index < emu->CharCount && char_index < 8; ++char_index) {
|
||||
emu_cse = (CharacterSelectEntry_Struct *)emu_ptr;
|
||||
|
||||
eq->Race[char_index] = emu_cse->Race;
|
||||
if (eq->Race[char_index] > 473)
|
||||
eq->Race[char_index] = 1;
|
||||
|
||||
for (int index = 0; index < _MaterialCount; ++index) {
|
||||
eq->CS_Colors[char_index][index].Color = emu_cse->Equip[index].Color.Color;
|
||||
}
|
||||
OUT(haircolor[r]);
|
||||
OUT(gohome[r]);
|
||||
OUT(tutorial[r]);
|
||||
OUT(deity[r]);
|
||||
OUT(beardcolor[r]);
|
||||
eq->unknown820[r] = 0xFF;
|
||||
eq->unknown902[r] = 0xFF;
|
||||
|
||||
eq->BeardColor[char_index] = emu_cse->BeardColor;
|
||||
eq->HairStyle[char_index] = emu_cse->HairStyle;
|
||||
|
||||
for (int index = 0; index < _MaterialCount; ++index) {
|
||||
eq->Equip[char_index][index] = emu_cse->Equip[index].Material;
|
||||
}
|
||||
|
||||
eq->SecondaryIDFile[char_index] = emu_cse->SecondaryIDFile;
|
||||
eq->Unknown820[char_index] = (uint8)0xFF;
|
||||
eq->Deity[char_index] = emu_cse->Deity;
|
||||
eq->GoHome[char_index] = emu_cse->GoHome;
|
||||
eq->Tutorial[char_index] = emu_cse->Tutorial;
|
||||
eq->Beard[char_index] = emu_cse->Beard;
|
||||
eq->Unknown902[char_index] = (uint8)0xFF;
|
||||
eq->PrimaryIDFile[char_index] = emu_cse->PrimaryIDFile;
|
||||
eq->HairColor[char_index] = emu_cse->HairColor;
|
||||
eq->Zone[char_index] = emu_cse->Zone;
|
||||
eq->Class[char_index] = emu_cse->Class;
|
||||
eq->Face[char_index] = emu_cse->Face;
|
||||
|
||||
memcpy(eq->Name[char_index], emu_cse->Name, 64);
|
||||
|
||||
eq->Gender[char_index] = emu_cse->Gender;
|
||||
eq->EyeColor1[char_index] = emu_cse->EyeColor1;
|
||||
eq->EyeColor2[char_index] = emu_cse->EyeColor2;
|
||||
eq->Level[char_index] = emu_cse->Level;
|
||||
|
||||
emu_ptr += sizeof(CharacterSelectEntry_Struct);
|
||||
}
|
||||
|
||||
for (; char_index < 10; ++char_index) {
|
||||
eq->Race[char_index] = 0;
|
||||
|
||||
for (int index = 0; index < _MaterialCount; ++index) {
|
||||
eq->CS_Colors[char_index][index].Color = 0;
|
||||
}
|
||||
|
||||
eq->BeardColor[char_index] = 0;
|
||||
eq->HairStyle[char_index] = 0;
|
||||
|
||||
for (int index = 0; index < _MaterialCount; ++index) {
|
||||
eq->Equip[char_index][index] = 0;
|
||||
}
|
||||
|
||||
eq->SecondaryIDFile[char_index] = 0;
|
||||
eq->Unknown820[char_index] = (uint8)0xFF;
|
||||
eq->Deity[char_index] = 0;
|
||||
eq->GoHome[char_index] = 0;
|
||||
eq->Tutorial[char_index] = 0;
|
||||
eq->Beard[char_index] = 0;
|
||||
eq->Unknown902[char_index] = (uint8)0xFF;
|
||||
eq->PrimaryIDFile[char_index] = 0;
|
||||
eq->HairColor[char_index] = 0;
|
||||
eq->Zone[char_index] = 0;
|
||||
eq->Class[char_index] = 0;
|
||||
eq->Face[char_index] = 0;
|
||||
|
||||
strncpy(eq->Name[char_index], "<none>", 6);
|
||||
|
||||
eq->Gender[char_index] = 0;
|
||||
eq->EyeColor1[char_index] = 0;
|
||||
eq->EyeColor2[char_index] = 0;
|
||||
eq->Level[char_index] = 0;
|
||||
}
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -1227,7 +1308,7 @@ namespace Titanium
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[11]);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
@@ -1270,7 +1351,7 @@ namespace Titanium
|
||||
InBuffer += strlen(InBuffer) + 1;
|
||||
|
||||
memcpy(OutBuffer, InBuffer, sizeof(TaskDescriptionTrailer_Struct));
|
||||
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
@@ -1383,7 +1464,7 @@ namespace Titanium
|
||||
|
||||
OUT(spawn_id);
|
||||
OUT(material);
|
||||
OUT(color.color);
|
||||
OUT(color.Color);
|
||||
OUT(wear_slot_id);
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -1468,15 +1549,15 @@ namespace Titanium
|
||||
eq->beardcolor = emu->beardcolor;
|
||||
// eq->unknown0147[4] = emu->unknown0147[4];
|
||||
eq->level = emu->level;
|
||||
// eq->unknown0259[4] = emu->unknown0259[4];
|
||||
eq->PlayerState = emu->PlayerState;
|
||||
eq->beard = emu->beard;
|
||||
strcpy(eq->suffix, emu->suffix);
|
||||
eq->petOwnerId = emu->petOwnerId;
|
||||
eq->guildrank = emu->guildrank;
|
||||
// eq->unknown0194[3] = emu->unknown0194[3];
|
||||
for (k = 0; k < 9; k++) {
|
||||
eq->equipment[k] = emu->equipment[k].material;
|
||||
eq->colors[k].color = emu->colors[k].color;
|
||||
eq->equipment[k] = emu->equipment[k].Material;
|
||||
eq->colors[k].Color = emu->colors[k].Color;
|
||||
}
|
||||
for (k = 0; k < 8; k++) {
|
||||
eq->set_to_0xFF[k] = 0xFF;
|
||||
@@ -1540,7 +1621,7 @@ namespace Titanium
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
|
||||
DECODE(OP_ApplyPoison)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::ApplyPoison_Struct);
|
||||
@@ -1861,14 +1942,14 @@ namespace Titanium
|
||||
default:
|
||||
emu->command = eq->command;
|
||||
}
|
||||
OUT(unknown);
|
||||
IN(target);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_ReadBook)
|
||||
{
|
||||
// no apparent slot translation needed -U
|
||||
// no apparent slot translation needed
|
||||
DECODE_LENGTH_ATLEAST(structs::BookRequest_Struct);
|
||||
SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct);
|
||||
|
||||
@@ -1952,7 +2033,7 @@ namespace Titanium
|
||||
|
||||
IN(spawn_id);
|
||||
IN(material);
|
||||
IN(color.color);
|
||||
IN(color.Color);
|
||||
IN(wear_slot_id);
|
||||
emu->unknown06 = 0;
|
||||
emu->elite_material = 0;
|
||||
@@ -2070,7 +2151,7 @@ namespace Titanium
|
||||
|
||||
return serverSlot; // deprecated
|
||||
}
|
||||
|
||||
|
||||
static inline int16 ServerToTitaniumCorpseSlot(uint32 serverCorpseSlot)
|
||||
{
|
||||
//int16 TitaniumCorpse;
|
||||
@@ -2085,7 +2166,7 @@ namespace Titanium
|
||||
|
||||
return titaniumSlot; // deprecated
|
||||
}
|
||||
|
||||
|
||||
static inline uint32 TitaniumToServerCorpseSlot(int16 titaniumCorpseSlot)
|
||||
{
|
||||
//uint32 ServerCorpse;
|
||||
|
||||
@@ -100,6 +100,8 @@ namespace Titanium {
|
||||
}
|
||||
|
||||
namespace consts {
|
||||
static const size_t CHARACTER_CREATION_LIMIT = 8; // Hard-coded in client - DO NOT ALTER
|
||||
|
||||
static const uint16 MAP_POSSESSIONS_SIZE = slots::_MainCount;
|
||||
static const uint16 MAP_BANK_SIZE = 16;
|
||||
static const uint16 MAP_SHARED_BANK_SIZE = 2;
|
||||
@@ -173,9 +175,10 @@ namespace Titanium {
|
||||
static const uint16 ITEM_COMMON_SIZE = 5;
|
||||
static const uint16 ITEM_CONTAINER_SIZE = 10;
|
||||
|
||||
static const uint32 BANDOLIERS_COUNT = 4; // count = number of bandolier instances
|
||||
static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance
|
||||
static const uint32 POTION_BELT_SIZE = 4;
|
||||
static const size_t BANDOLIERS_SIZE = 4; // number of bandolier instances
|
||||
static const size_t BANDOLIER_ITEM_COUNT = 4; // number of equipment slots in bandolier instance
|
||||
|
||||
static const size_t POTION_BELT_ITEM_COUNT = 4;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 45;
|
||||
}
|
||||
|
||||
@@ -99,16 +99,14 @@ struct AdventureInfo {
|
||||
*/
|
||||
struct Color_Struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8 blue;
|
||||
uint8 green;
|
||||
uint8 red;
|
||||
uint8 use_tint; // if there's a tint this is FF
|
||||
} rgb;
|
||||
uint32 color;
|
||||
union {
|
||||
struct {
|
||||
uint8 Blue;
|
||||
uint8 Green;
|
||||
uint8 Red;
|
||||
uint8 UseTint; // if there's a tint this is FF
|
||||
} RGB;
|
||||
uint32 Color;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -117,31 +115,32 @@ struct Color_Struct
|
||||
** Length: 1704 Bytes
|
||||
**
|
||||
*/
|
||||
struct CharacterSelect_Struct {
|
||||
/*0000*/ uint32 race[10]; // Characters Race
|
||||
/*0040*/ Color_Struct cs_colors[10][9]; // Characters Equipment Colors
|
||||
/*0400*/ uint8 beardcolor[10]; // Characters beard Color
|
||||
/*0410*/ uint8 hairstyle[10]; // Characters hair style
|
||||
/*0420*/ uint32 equip[10][9]; // 0=helm, 1=chest, 2=arm, 3=bracer, 4=hand, 5=leg, 6=boot, 7=melee1, 8=melee2 (Might not be)
|
||||
/*0780*/ uint32 secondary[10]; // Characters secondary IDFile number
|
||||
/*0820*/ uint8 unknown820[10]; // 10x ff
|
||||
/*0830*/ uint8 unknown830[2]; // 2x 00
|
||||
/*0832*/ uint32 deity[10]; // Characters Deity
|
||||
/*0872*/ uint8 gohome[10]; // 1=Go Home available, 0=not
|
||||
/*0882*/ uint8 tutorial[10]; // 1=Tutorial available, 0=not
|
||||
/*0892*/ uint8 beard[10]; // Characters Beard Type
|
||||
/*0902*/ uint8 unknown902[10]; // 10x ff
|
||||
/*0912*/ uint32 primary[10]; // Characters primary IDFile number
|
||||
/*0952*/ uint8 haircolor[10]; // Characters Hair Color
|
||||
/*0962*/ uint8 unknown0962[2]; // 2x 00
|
||||
/*0964*/ uint32 zone[10]; // Characters Current Zone
|
||||
/*1004*/ uint8 class_[10]; // Characters Classes
|
||||
/*1014*/ uint8 face[10]; // Characters Face Type
|
||||
/*1024*/ char name[10][64]; // Characters Names
|
||||
/*1664*/ uint8 gender[10]; // Characters Gender
|
||||
/*1674*/ uint8 eyecolor1[10]; // Characters Eye Color
|
||||
/*1684*/ uint8 eyecolor2[10]; // Characters Eye 2 Color
|
||||
/*1694*/ uint8 level[10]; // Characters Levels
|
||||
struct CharacterSelect_Struct
|
||||
{
|
||||
/*0000*/ uint32 Race[10]; // Characters Race
|
||||
/*0040*/ Color_Struct CS_Colors[10][9]; // Characters Equipment Colors
|
||||
/*0400*/ uint8 BeardColor[10]; // Characters beard Color
|
||||
/*0410*/ uint8 HairStyle[10]; // Characters hair style
|
||||
/*0420*/ uint32 Equip[10][9]; // 0=helm, 1=chest, 2=arm, 3=bracer, 4=hand, 5=leg, 6=boot, 7=melee1, 8=melee2 (Might not be)
|
||||
/*0780*/ uint32 SecondaryIDFile[10]; // Characters secondary IDFile number
|
||||
/*0820*/ uint8 Unknown820[10]; // 10x ff
|
||||
/*0830*/ uint8 Unknown830[2]; // 2x 00
|
||||
/*0832*/ uint32 Deity[10]; // Characters Deity
|
||||
/*0872*/ uint8 GoHome[10]; // 1=Go Home available, 0=not
|
||||
/*0882*/ uint8 Tutorial[10]; // 1=Tutorial available, 0=not
|
||||
/*0892*/ uint8 Beard[10]; // Characters Beard Type
|
||||
/*0902*/ uint8 Unknown902[10]; // 10x ff
|
||||
/*0912*/ uint32 PrimaryIDFile[10]; // Characters primary IDFile number
|
||||
/*0952*/ uint8 HairColor[10]; // Characters Hair Color
|
||||
/*0962*/ uint8 Unknown0962[2]; // 2x 00
|
||||
/*0964*/ uint32 Zone[10]; // Characters Current Zone
|
||||
/*1004*/ uint8 Class[10]; // Characters Classes
|
||||
/*1014*/ uint8 Face[10]; // Characters Face Type
|
||||
/*1024*/ char Name[10][64]; // Characters Names
|
||||
/*1664*/ uint8 Gender[10]; // Characters Gender
|
||||
/*1674*/ uint8 EyeColor1[10]; // Characters Eye Color
|
||||
/*1684*/ uint8 EyeColor2[10]; // Characters Eye 2 Color
|
||||
/*1694*/ uint8 Level[10]; // Characters Levels
|
||||
/*1704*/
|
||||
};
|
||||
|
||||
@@ -213,7 +212,7 @@ struct Spawn_Struct {
|
||||
/*0146*/ uint8 beardcolor; // Beard color
|
||||
/*0147*/ uint8 unknown0147[4];
|
||||
/*0151*/ uint8 level; // Spawn Level
|
||||
/*0152*/ uint8 unknown0259[4]; // ***Placeholder
|
||||
/*0152*/ uint32 PlayerState; // PlayerState controls some animation stuff
|
||||
/*0156*/ uint8 beard; // Beard style
|
||||
/*0157*/ char suffix[32]; // Player's suffix (of Veeshan, etc.)
|
||||
/*0189*/ uint32 petOwnerId; // If this is a pet, the spawn id of owner
|
||||
@@ -446,7 +445,7 @@ struct SpellBuff_Struct
|
||||
/*002*/ uint8 bard_modifier;
|
||||
/*003*/ uint8 effect; //not real
|
||||
/*004*/ uint32 spellid;
|
||||
/*008*/ uint32 duration;
|
||||
/*008*/ int32 duration;
|
||||
/*012*/ uint32 counters;
|
||||
/*016*/ uint32 player_id; //'global' ID of the caster, for wearoff messages
|
||||
};
|
||||
@@ -458,7 +457,7 @@ struct SpellBuffFade_Struct {
|
||||
/*006*/ uint8 effect;
|
||||
/*007*/ uint8 unknown7;
|
||||
/*008*/ uint32 spellid;
|
||||
/*012*/ uint32 duration;
|
||||
/*012*/ int32 duration;
|
||||
/*016*/ uint32 unknown016;
|
||||
/*020*/ uint32 unknown020; //prolly global player ID
|
||||
/*024*/ uint32 slotid;
|
||||
@@ -586,34 +585,48 @@ struct Disciplines_Struct {
|
||||
};
|
||||
|
||||
static const uint32 MAX_PLAYER_TRIBUTES = 5;
|
||||
static const uint32 MAX_PLAYER_BANDOLIER = 4;
|
||||
static const uint32 MAX_PLAYER_BANDOLIER_ITEMS = 4;
|
||||
static const uint32 TRIBUTE_NONE = 0xFFFFFFFF;
|
||||
struct Tribute_Struct {
|
||||
uint32 tribute;
|
||||
uint32 tier;
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct {
|
||||
uint32 item_id;
|
||||
uint32 icon;
|
||||
char item_name[64];
|
||||
};
|
||||
|
||||
//len = 320
|
||||
enum { //bandolier item positions
|
||||
bandolierMainHand = 0,
|
||||
bandolierOffHand,
|
||||
// Bandolier item positions
|
||||
enum
|
||||
{
|
||||
bandolierPrimary = 0,
|
||||
bandolierSecondary,
|
||||
bandolierRange,
|
||||
bandolierAmmo
|
||||
};
|
||||
struct Bandolier_Struct {
|
||||
char name[32];
|
||||
BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS];
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
struct PotionBelt_Struct {
|
||||
BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS];
|
||||
|
||||
//len = 320
|
||||
struct Bandolier_Struct
|
||||
{
|
||||
char Name[32];
|
||||
BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT];
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct PotionBeltItem_Struct
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
//len = 288
|
||||
struct PotionBelt_Struct
|
||||
{
|
||||
PotionBeltItem_Struct Items[consts::POTION_BELT_ITEM_COUNT];
|
||||
};
|
||||
|
||||
static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16;
|
||||
@@ -817,7 +830,7 @@ struct PlayerProfile_Struct
|
||||
/*06152*/ uint32 aapoints_spent; // Number of spent AA points
|
||||
/*06156*/ uint32 aapoints; // Unspent AA points
|
||||
/*06160*/ uint8 unknown06160[4];
|
||||
/*06164*/ Bandolier_Struct bandoliers[MAX_PLAYER_BANDOLIER]; // bandolier contents
|
||||
/*06164*/ Bandolier_Struct bandoliers[consts::BANDOLIERS_SIZE]; // bandolier contents
|
||||
/*07444*/ uint8 unknown07444[5120];
|
||||
/*12564*/ PotionBelt_Struct potionbelt; // potion belt
|
||||
/*12852*/ uint8 unknown12852[8];
|
||||
@@ -937,7 +950,7 @@ struct TargetReject_Struct {
|
||||
|
||||
struct PetCommand_Struct {
|
||||
/*000*/ uint32 command;
|
||||
/*004*/ uint32 unknown;
|
||||
/*004*/ uint32 target;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1049,8 +1062,8 @@ struct RequestClientZoneChange_Struct {
|
||||
|
||||
struct Animation_Struct {
|
||||
/*00*/ uint16 spawnid;
|
||||
/*02*/ uint8 action;
|
||||
/*03*/ uint8 value;
|
||||
/*02*/ uint8 speed;
|
||||
/*03*/ uint8 action;
|
||||
/*04*/
|
||||
};
|
||||
|
||||
@@ -1088,9 +1101,9 @@ struct CombatDamage_Struct
|
||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||
/* 05 */ uint16 spellid;
|
||||
/* 07 */ uint32 damage;
|
||||
/* 11 */ uint32 unknown11;
|
||||
/* 15 */ uint32 sequence; // see above notes in Action_Struct
|
||||
/* 19 */ uint32 unknown19;
|
||||
/* 11 */ float force;
|
||||
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
|
||||
/* 19 */ float meleepush_z;
|
||||
/* 23 */
|
||||
};
|
||||
|
||||
@@ -1997,7 +2010,7 @@ struct BookRequest_Struct {
|
||||
**
|
||||
*/
|
||||
struct Object_Struct {
|
||||
/*00*/ uint32 linked_list_addr[2];// <Zaphod> They are, get this, prev and next, ala linked list
|
||||
/*00*/ uint32 linked_list_addr[2];// They are, get this, prev and next, ala linked list
|
||||
/*08*/ uint16 unknown008[2]; //
|
||||
/*12*/ uint32 drop_id; // Unique object id for zone
|
||||
/*16*/ uint16 zone_id; // Redudant, but: Zone the object appears in
|
||||
@@ -2016,8 +2029,8 @@ struct Object_Struct {
|
||||
/*88*/ uint32 spawn_id; // Spawn Id of client interacting with object
|
||||
/*92*/
|
||||
};
|
||||
//<Zaphod> 01 = generic drop, 02 = armor, 19 = weapon
|
||||
//[13:40] <Zaphod> and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject
|
||||
//01 = generic drop, 02 = armor, 19 = weapon
|
||||
//[13:40] and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject
|
||||
|
||||
/*
|
||||
** Click Object Struct
|
||||
@@ -3030,30 +3043,35 @@ struct DynamicWall_Struct {
|
||||
/*80*/
|
||||
};
|
||||
|
||||
enum { //bandolier actions
|
||||
BandolierCreate = 0,
|
||||
BandolierRemove = 1,
|
||||
BandolierSet = 2
|
||||
// Bandolier actions
|
||||
enum
|
||||
{
|
||||
bandolierCreate = 0,
|
||||
bandolierRemove,
|
||||
bandolierSet
|
||||
};
|
||||
|
||||
struct BandolierCreate_Struct {
|
||||
/*00*/ uint32 action; //0 for create
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ char name[32];
|
||||
/*37*/ uint16 unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 unknown39; //0
|
||||
struct BandolierCreate_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; //0 for create
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ char Name[32];
|
||||
/*37*/ uint16 Unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 Unknown39; //0
|
||||
};
|
||||
|
||||
struct BandolierDelete_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierDelete_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct BandolierSet_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierSet_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct Arrow_Struct {
|
||||
@@ -3161,11 +3179,6 @@ struct AA_Action {
|
||||
/*12*/ uint32 exp_value;
|
||||
};
|
||||
|
||||
struct AA_Skills { //this should be removed and changed to AA_Array
|
||||
/*00*/ uint32 aa_skill;
|
||||
/*04*/ uint32 aa_value;
|
||||
};
|
||||
|
||||
struct AAExpUpdate_Struct {
|
||||
/*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability
|
||||
/*04*/ uint32 aapoints_unspent;
|
||||
@@ -3183,11 +3196,11 @@ struct AltAdvStats_Struct {
|
||||
};
|
||||
|
||||
struct PlayerAA_Struct {
|
||||
AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct AATable_Struct {
|
||||
AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct Weather_Struct {
|
||||
|
||||
+162
-130
@@ -387,7 +387,7 @@ namespace UF
|
||||
__packet->WriteUInt32(emu->entries[i].num_hits);
|
||||
__packet->WriteString("");
|
||||
}
|
||||
__packet->WriteUInt8(!emu->all_buffs);
|
||||
__packet->WriteUInt8(emu->type);
|
||||
|
||||
FINISH_ENCODE();
|
||||
/*
|
||||
@@ -581,7 +581,9 @@ namespace UF
|
||||
OUT(type);
|
||||
OUT(spellid);
|
||||
OUT(damage);
|
||||
eq->sequence = emu->sequence;
|
||||
OUT(force)
|
||||
OUT(meleepush_xy);
|
||||
OUT(meleepush_z)
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@@ -855,8 +857,8 @@ namespace UF
|
||||
// field to be set to (float)255.0 to appear at all, and also the size field below to be 5, to be the correct size. I think SoD has the same
|
||||
// issue.
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown, observed 0
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // This appears to be the size field.
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->solidtype); // Unknown, observed 0
|
||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->size != 0 && (float)emu->size < 5000.f ? (float)((float)emu->size / 100.0f) : 1.f ); // This appears to be the size field. Hackish logic because some PEQ DB items were corrupt.
|
||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y);
|
||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x);
|
||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->z);
|
||||
@@ -1791,13 +1793,13 @@ namespace UF
|
||||
OUT(beard);
|
||||
// OUT(unknown00178[10]);
|
||||
for (r = 0; r < 9; r++) {
|
||||
eq->equipment[r].material = emu->item_material[r];
|
||||
eq->equipment[r].unknown1 = 0;
|
||||
eq->equipment[r].elitematerial = 0;
|
||||
eq->equipment[r].Material = emu->item_material[r];
|
||||
eq->equipment[r].Unknown1 = 0;
|
||||
eq->equipment[r].EliteMaterial = 0;
|
||||
//eq->colors[r].color = emu->colors[r].color;
|
||||
}
|
||||
for (r = 0; r < 7; r++) {
|
||||
OUT(item_tint[r].color);
|
||||
OUT(item_tint[r].Color);
|
||||
}
|
||||
// OUT(unknown00224[48]);
|
||||
//NOTE: new client supports 300 AAs, our internal rep/PP
|
||||
@@ -1805,6 +1807,7 @@ namespace UF
|
||||
for (r = 0; r < MAX_PP_AA_ARRAY; r++) {
|
||||
OUT(aa_array[r].AA);
|
||||
OUT(aa_array[r].value);
|
||||
OUT(aa_array[r].charges);
|
||||
}
|
||||
// OUT(unknown02220[4]);
|
||||
OUT(mana);
|
||||
@@ -1868,26 +1871,46 @@ namespace UF
|
||||
OUT(endurance);
|
||||
OUT(aapoints_spent);
|
||||
OUT(aapoints);
|
||||
|
||||
// OUT(unknown06160[4]);
|
||||
//NOTE: new client supports 20 bandoliers, our internal rep
|
||||
//only supports 4..
|
||||
for (r = 0; r < 4; r++) {
|
||||
OUT_str(bandoliers[r].name);
|
||||
uint32 k;
|
||||
for (k = 0; k < structs::MAX_PLAYER_BANDOLIER_ITEMS; k++) {
|
||||
OUT(bandoliers[r].items[k].item_id);
|
||||
OUT(bandoliers[r].items[k].icon);
|
||||
OUT_str(bandoliers[r].items[k].item_name);
|
||||
|
||||
// Copy bandoliers where server and client indexes converge
|
||||
for (r = 0; r < EmuConstants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) {
|
||||
OUT_str(bandoliers[r].Name);
|
||||
for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true
|
||||
OUT(bandoliers[r].Items[k].ID);
|
||||
OUT(bandoliers[r].Items[k].Icon);
|
||||
OUT_str(bandoliers[r].Items[k].Name);
|
||||
}
|
||||
}
|
||||
// OUT(unknown07444[5120]);
|
||||
for (r = 0; r < structs::MAX_POTIONS_IN_BELT; r++) {
|
||||
OUT(potionbelt.items[r].item_id);
|
||||
OUT(potionbelt.items[r].icon);
|
||||
OUT_str(potionbelt.items[r].item_name);
|
||||
// Nullify bandoliers where server and client indexes diverge, with a client bias
|
||||
for (r = EmuConstants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) {
|
||||
eq->bandoliers[r].Name[0] = '\0';
|
||||
for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true
|
||||
eq->bandoliers[r].Items[k].ID = 0;
|
||||
eq->bandoliers[r].Items[k].Icon = 0;
|
||||
eq->bandoliers[r].Items[k].Name[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
// OUT(unknown07444[5120]);
|
||||
|
||||
// Copy potion belt where server and client indexes converge
|
||||
for (r = 0; r < EmuConstants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) {
|
||||
OUT(potionbelt.Items[r].ID);
|
||||
OUT(potionbelt.Items[r].Icon);
|
||||
OUT_str(potionbelt.Items[r].Name);
|
||||
}
|
||||
// Nullify potion belt where server and client indexes diverge, with a client bias
|
||||
for (r = EmuConstants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) {
|
||||
eq->potionbelt.Items[r].ID = 0;
|
||||
eq->potionbelt.Items[r].Icon = 0;
|
||||
eq->potionbelt.Items[r].Name[0] = '\0';
|
||||
}
|
||||
|
||||
// OUT(unknown12852[8]);
|
||||
// OUT(unknown12864[76]);
|
||||
|
||||
OUT_str(name);
|
||||
OUT_str(last_name);
|
||||
OUT(guild_id);
|
||||
@@ -2112,9 +2135,9 @@ namespace UF
|
||||
|
||||
for (uint32 i = 0; i < MAX_PP_AA_ARRAY; ++i)
|
||||
{
|
||||
eq->aa_list[i].aa_skill = emu->aa_list[i].aa_skill;
|
||||
eq->aa_list[i].aa_value = emu->aa_list[i].aa_value;
|
||||
eq->aa_list[i].unknown08 = emu->aa_list[i].unknown08;
|
||||
eq->aa_list[i].AA = emu->aa_list[i].AA;
|
||||
eq->aa_list[i].value = emu->aa_list[i].value;
|
||||
eq->aa_list[i].charges = emu->aa_list[i].charges;
|
||||
}
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -2159,6 +2182,7 @@ namespace UF
|
||||
OUT(cost2);
|
||||
eq->aa_expansion = emu->aa_expansion;
|
||||
eq->special_category = emu->special_category;
|
||||
eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number
|
||||
OUT(total_abilities);
|
||||
unsigned int r;
|
||||
for (r = 0; r < emu->total_abilities; r++) {
|
||||
@@ -2174,77 +2198,104 @@ namespace UF
|
||||
|
||||
ENCODE(OP_SendCharInfo)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(CharacterSelect_Struct);
|
||||
ENCODE_LENGTH_ATLEAST(CharacterSelect_Struct);
|
||||
SETUP_VAR_ENCODE(CharacterSelect_Struct);
|
||||
|
||||
//EQApplicationPacket *packet = *p;
|
||||
//const CharacterSelect_Struct *emu = (CharacterSelect_Struct *) packet->pBuffer;
|
||||
// Zero-character count shunt
|
||||
if (emu->CharCount == 0) {
|
||||
ALLOC_VAR_ENCODE(structs::CharacterSelect_Struct, sizeof(structs::CharacterSelect_Struct));
|
||||
eq->CharCount = emu->CharCount;
|
||||
eq->TotalChars = emu->TotalChars;
|
||||
|
||||
int char_count;
|
||||
int namelen = 0;
|
||||
for (char_count = 0; char_count < 10; char_count++) {
|
||||
if (emu->name[char_count][0] == '\0')
|
||||
break;
|
||||
if (strcmp(emu->name[char_count], "<none>") == 0)
|
||||
break;
|
||||
namelen += strlen(emu->name[char_count]);
|
||||
if (eq->TotalChars > consts::CHARACTER_CREATION_LIMIT)
|
||||
eq->TotalChars = consts::CHARACTER_CREATION_LIMIT;
|
||||
|
||||
// Special Underfoot adjustment - field should really be 'AdditionalChars' or 'BonusChars'
|
||||
uint32 adjusted_total = eq->TotalChars - 8; // Yes, it rolls under for '< 8' - probably an int32 field
|
||||
eq->TotalChars = adjusted_total;
|
||||
|
||||
FINISH_ENCODE();
|
||||
return;
|
||||
}
|
||||
|
||||
int total_length = sizeof(structs::CharacterSelect_Struct)
|
||||
+ char_count * sizeof(structs::CharacterSelectEntry_Struct)
|
||||
+ namelen;
|
||||
unsigned char *emu_ptr = __emu_buffer;
|
||||
emu_ptr += sizeof(CharacterSelect_Struct);
|
||||
CharacterSelectEntry_Struct *emu_cse = (CharacterSelectEntry_Struct *)nullptr;
|
||||
|
||||
size_t names_length = 0;
|
||||
size_t character_count = 0;
|
||||
for (; character_count < emu->CharCount && character_count < consts::CHARACTER_CREATION_LIMIT; ++character_count) {
|
||||
emu_cse = (CharacterSelectEntry_Struct *)emu_ptr;
|
||||
names_length += strlen(emu_cse->Name);
|
||||
emu_ptr += sizeof(CharacterSelectEntry_Struct);
|
||||
}
|
||||
|
||||
size_t total_length = sizeof(structs::CharacterSelect_Struct)
|
||||
+ character_count * sizeof(structs::CharacterSelectEntry_Struct)
|
||||
+ names_length;
|
||||
|
||||
ALLOC_VAR_ENCODE(structs::CharacterSelect_Struct, total_length);
|
||||
structs::CharacterSelectEntry_Struct *eq_cse = (structs::CharacterSelectEntry_Struct *)nullptr;
|
||||
|
||||
//unsigned char *eq_buffer = new unsigned char[total_length];
|
||||
//structs::CharacterSelect_Struct *eq_head = (structs::CharacterSelect_Struct *) eq_buffer;
|
||||
eq->CharCount = character_count;
|
||||
eq->TotalChars = emu->TotalChars;
|
||||
|
||||
eq->char_count = char_count;
|
||||
eq->total_chars = 10;
|
||||
if (eq->TotalChars > consts::CHARACTER_CREATION_LIMIT)
|
||||
eq->TotalChars = consts::CHARACTER_CREATION_LIMIT;
|
||||
|
||||
unsigned char *bufptr = (unsigned char *)eq->entries;
|
||||
int r;
|
||||
for (r = 0; r < char_count; r++) {
|
||||
{ //pre-name section...
|
||||
structs::CharacterSelectEntry_Struct *eq2 = (structs::CharacterSelectEntry_Struct *) bufptr;
|
||||
eq2->level = emu->level[r];
|
||||
eq2->hairstyle = emu->hairstyle[r];
|
||||
eq2->gender = emu->gender[r];
|
||||
memcpy(eq2->name, emu->name[r], strlen(emu->name[r]) + 1);
|
||||
}
|
||||
//adjust for name.
|
||||
bufptr += strlen(emu->name[r]);
|
||||
{ //post-name section...
|
||||
structs::CharacterSelectEntry_Struct *eq2 = (structs::CharacterSelectEntry_Struct *) bufptr;
|
||||
eq2->beard = emu->beard[r];
|
||||
eq2->haircolor = emu->haircolor[r];
|
||||
eq2->face = emu->face[r];
|
||||
int k;
|
||||
for (k = 0; k < _MaterialCount; k++) {
|
||||
eq2->equip[k].material = emu->equip[r][k].material;
|
||||
eq2->equip[k].unknown1 = emu->equip[r][k].unknown1;
|
||||
eq2->equip[k].elitematerial = emu->equip[r][k].elitematerial;
|
||||
eq2->equip[k].color.color = emu->equip[r][k].color.color;
|
||||
}
|
||||
eq2->primary = emu->primary[r];
|
||||
eq2->secondary = emu->secondary[r];
|
||||
eq2->tutorial = emu->tutorial[r]; // was u15
|
||||
eq2->u15 = 0xff;
|
||||
eq2->deity = emu->deity[r];
|
||||
eq2->zone = emu->zone[r];
|
||||
eq2->u19 = 0xFF;
|
||||
eq2->race = emu->race[r];
|
||||
eq2->gohome = emu->gohome[r];
|
||||
eq2->class_ = emu->class_[r];
|
||||
eq2->eyecolor1 = emu->eyecolor1[r];
|
||||
eq2->beardcolor = emu->beardcolor[r];
|
||||
eq2->eyecolor2 = emu->eyecolor2[r];
|
||||
eq2->drakkin_heritage = emu->drakkin_heritage[r];
|
||||
eq2->drakkin_tattoo = emu->drakkin_tattoo[r];
|
||||
eq2->drakkin_details = emu->drakkin_details[r];
|
||||
// Special Underfoot adjustment - field should really be 'AdditionalChars' or 'BonusChars' in this client
|
||||
uint32 adjusted_total = eq->TotalChars - 8; // Yes, it rolls under for '< 8' - probably an int32 field
|
||||
eq->TotalChars = adjusted_total;
|
||||
|
||||
emu_ptr = __emu_buffer;
|
||||
emu_ptr += sizeof(CharacterSelect_Struct);
|
||||
|
||||
unsigned char *eq_ptr = __packet->pBuffer;
|
||||
eq_ptr += sizeof(structs::CharacterSelect_Struct);
|
||||
|
||||
for (int counter = 0; counter < character_count; ++counter) {
|
||||
emu_cse = (CharacterSelectEntry_Struct *)emu_ptr;
|
||||
eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // base address
|
||||
|
||||
eq_cse->Level = emu_cse->Level;
|
||||
eq_cse->HairStyle = emu_cse->HairStyle;
|
||||
eq_cse->Gender = emu_cse->Gender;
|
||||
|
||||
strcpy(eq_cse->Name, emu_cse->Name);
|
||||
eq_ptr += strlen(emu_cse->Name);
|
||||
eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // offset address (base + name length offset)
|
||||
eq_cse->Name[0] = '\0'; // (offset)eq_cse->Name[0] = (base)eq_cse->Name[strlen(emu_cse->Name)]
|
||||
|
||||
eq_cse->Beard = emu_cse->Beard;
|
||||
eq_cse->HairColor = emu_cse->HairColor;
|
||||
eq_cse->Face = emu_cse->Face;
|
||||
|
||||
for (int equip_index = 0; equip_index < _MaterialCount; equip_index++) {
|
||||
eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material;
|
||||
eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1;
|
||||
eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial;
|
||||
eq_cse->Equip[equip_index].Color.Color = emu_cse->Equip[equip_index].Color.Color;
|
||||
}
|
||||
|
||||
bufptr += sizeof(structs::CharacterSelectEntry_Struct);
|
||||
eq_cse->PrimaryIDFile = emu_cse->PrimaryIDFile;
|
||||
eq_cse->SecondaryIDFile = emu_cse->SecondaryIDFile;
|
||||
eq_cse->Tutorial = emu_cse->Tutorial;
|
||||
eq_cse->Unknown15 = emu_cse->Unknown15;
|
||||
eq_cse->Deity = emu_cse->Deity;
|
||||
eq_cse->Zone = emu_cse->Zone;
|
||||
eq_cse->Unknown19 = emu_cse->Unknown19;
|
||||
eq_cse->Race = emu_cse->Race;
|
||||
eq_cse->GoHome = emu_cse->GoHome;
|
||||
eq_cse->Class = emu_cse->Class;
|
||||
eq_cse->EyeColor1 = emu_cse->EyeColor1;
|
||||
eq_cse->BeardColor = emu_cse->BeardColor;
|
||||
eq_cse->EyeColor2 = emu_cse->EyeColor2;
|
||||
eq_cse->DrakkinHeritage = emu_cse->DrakkinHeritage;
|
||||
eq_cse->DrakkinTattoo = emu_cse->DrakkinTattoo;
|
||||
eq_cse->DrakkinDetails = emu_cse->DrakkinDetails;
|
||||
|
||||
emu_ptr += sizeof(CharacterSelectEntry_Struct);
|
||||
eq_ptr += sizeof(structs::CharacterSelectEntry_Struct);
|
||||
}
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -2621,7 +2672,7 @@ namespace UF
|
||||
OUT(material);
|
||||
OUT(unknown06);
|
||||
OUT(elite_material);
|
||||
OUT(color.color);
|
||||
OUT(color.Color);
|
||||
OUT(wear_slot_id);
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -2693,42 +2744,23 @@ namespace UF
|
||||
|
||||
ENCODE(OP_ZonePlayerToBind)
|
||||
{
|
||||
ENCODE_LENGTH_ATLEAST(ZonePlayerToBind_Struct);
|
||||
SETUP_VAR_ENCODE(ZonePlayerToBind_Struct);
|
||||
ALLOC_LEN_ENCODE(sizeof(structs::ZonePlayerToBind_Struct) + strlen(emu->zone_name));
|
||||
|
||||
ZonePlayerToBind_Struct *zps = (ZonePlayerToBind_Struct*)(*p)->pBuffer;
|
||||
__packet->SetWritePosition(0);
|
||||
__packet->WriteUInt16(emu->bind_zone_id);
|
||||
__packet->WriteUInt16(emu->bind_instance_id);
|
||||
__packet->WriteFloat(emu->x);
|
||||
__packet->WriteFloat(emu->y);
|
||||
__packet->WriteFloat(emu->z);
|
||||
__packet->WriteFloat(emu->heading);
|
||||
__packet->WriteString(emu->zone_name);
|
||||
__packet->WriteUInt8(1); // save items
|
||||
__packet->WriteUInt32(0); // hp
|
||||
__packet->WriteUInt32(0); // mana
|
||||
__packet->WriteUInt32(0); // endurance
|
||||
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
||||
|
||||
unsigned char *buffer1 = new unsigned char[sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name)];
|
||||
structs::ZonePlayerToBindHeader_Struct *zph = (structs::ZonePlayerToBindHeader_Struct*)buffer1;
|
||||
unsigned char *buffer2 = new unsigned char[sizeof(structs::ZonePlayerToBindFooter_Struct)];
|
||||
structs::ZonePlayerToBindFooter_Struct *zpf = (structs::ZonePlayerToBindFooter_Struct*)buffer2;
|
||||
|
||||
zph->x = zps->x;
|
||||
zph->y = zps->y;
|
||||
zph->z = zps->z;
|
||||
zph->heading = zps->heading;
|
||||
zph->bind_zone_id = zps->bind_zone_id;
|
||||
zph->bind_instance_id = zps->bind_instance_id;
|
||||
strcpy(zph->zone_name, zps->zone_name);
|
||||
|
||||
zpf->unknown021 = 1;
|
||||
zpf->unknown022 = 0;
|
||||
zpf->unknown023 = 0;
|
||||
zpf->unknown024 = 0;
|
||||
|
||||
ss.write((const char*)buffer1, (sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name)));
|
||||
ss.write((const char*)buffer2, sizeof(structs::ZonePlayerToBindFooter_Struct));
|
||||
|
||||
delete[] buffer1;
|
||||
delete[] buffer2;
|
||||
delete[](*p)->pBuffer;
|
||||
|
||||
(*p)->pBuffer = new unsigned char[ss.str().size()];
|
||||
(*p)->size = ss.str().size();
|
||||
|
||||
memcpy((*p)->pBuffer, ss.str().c_str(), ss.str().size());
|
||||
dest->FastQueuePacket(&(*p));
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ZoneServerInfo)
|
||||
@@ -2976,7 +3008,7 @@ namespace UF
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown12
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->petOwnerId);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown13
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown14 - Stance 64 = normal 4 = aggressive 40 = stun/mezzed
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->PlayerState);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown15
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown16
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown17
|
||||
@@ -3002,7 +3034,7 @@ namespace UF
|
||||
for (k = 0; k < 9; ++k)
|
||||
{
|
||||
{
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->colors[k].color);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->colors[k].Color);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3012,11 +3044,11 @@ namespace UF
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].material);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].Material);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].material);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].Material);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
|
||||
}
|
||||
@@ -3026,9 +3058,9 @@ namespace UF
|
||||
structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer;
|
||||
|
||||
for (k = 0; k < 9; k++) {
|
||||
Equipment[k].material = emu->equipment[k].material;
|
||||
Equipment[k].unknown1 = emu->equipment[k].unknown1;
|
||||
Equipment[k].elitematerial = emu->equipment[k].elitematerial;
|
||||
Equipment[k].Material = emu->equipment[k].Material;
|
||||
Equipment[k].Unknown1 = emu->equipment[k].Unknown1;
|
||||
Equipment[k].EliteMaterial = emu->equipment[k].EliteMaterial;
|
||||
}
|
||||
|
||||
Buffer += (sizeof(structs::EquipStruct) * 9);
|
||||
@@ -3329,7 +3361,7 @@ namespace UF
|
||||
IN(type);
|
||||
IN(spellid);
|
||||
IN(damage);
|
||||
emu->sequence = eq->sequence;
|
||||
IN(meleepush_xy);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@@ -3572,7 +3604,7 @@ namespace UF
|
||||
SETUP_DIRECT_DECODE(PetCommand_Struct, structs::PetCommand_Struct);
|
||||
|
||||
IN(command);
|
||||
IN(unknown);
|
||||
IN(target);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@@ -3728,7 +3760,7 @@ namespace UF
|
||||
IN(material);
|
||||
IN(unknown06);
|
||||
IN(elite_material);
|
||||
IN(color.color);
|
||||
IN(color.Color);
|
||||
IN(wear_slot_id);
|
||||
emu->hero_forge_model = 0;
|
||||
emu->unknown18 = 0;
|
||||
@@ -3834,7 +3866,7 @@ namespace UF
|
||||
|
||||
UF::structs::ItemSerializationHeaderFinish hdrf;
|
||||
hdrf.ornamentIcon = ornaIcon;
|
||||
hdrf.unknown060 = 0; //This is Always 0.. or it breaks shit..
|
||||
hdrf.unknown060 = 0; //This is Always 0.. or it breaks shit..
|
||||
hdrf.unknown061 = 0; //possibly ornament / special ornament
|
||||
hdrf.isCopied = 0; //Flag for item to be 'Copied'
|
||||
hdrf.ItemClass = item->ItemClass;
|
||||
|
||||
@@ -101,6 +101,8 @@ namespace UF {
|
||||
}
|
||||
|
||||
namespace consts {
|
||||
static const size_t CHARACTER_CREATION_LIMIT = 12;
|
||||
|
||||
static const uint16 MAP_POSSESSIONS_SIZE = slots::_MainCount;
|
||||
static const uint16 MAP_BANK_SIZE = 24;
|
||||
static const uint16 MAP_SHARED_BANK_SIZE = 2;
|
||||
@@ -174,9 +176,10 @@ namespace UF {
|
||||
static const uint16 ITEM_COMMON_SIZE = 5;
|
||||
static const uint16 ITEM_CONTAINER_SIZE = 10;
|
||||
|
||||
static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances
|
||||
static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance
|
||||
static const uint32 POTION_BELT_SIZE = 5;
|
||||
static const size_t BANDOLIERS_SIZE = 20; // number of bandolier instances
|
||||
static const size_t BANDOLIER_ITEM_COUNT = 4; // number of equipment slots in bandolier instance
|
||||
|
||||
static const size_t POTION_BELT_ITEM_COUNT = 5;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 50;
|
||||
}
|
||||
|
||||
+134
-112
@@ -103,53 +103,53 @@ struct AdventureInfo {
|
||||
*/
|
||||
struct Color_Struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8 blue;
|
||||
uint8 green;
|
||||
uint8 red;
|
||||
uint8 use_tint; // if there's a tint this is FF
|
||||
} rgb;
|
||||
uint32 color;
|
||||
union {
|
||||
struct {
|
||||
uint8 blue;
|
||||
uint8 Green;
|
||||
uint8 Red;
|
||||
uint8 UseTint; // if there's a tint this is FF
|
||||
} RGB;
|
||||
uint32 Color;
|
||||
};
|
||||
};
|
||||
|
||||
struct CharSelectEquip {
|
||||
uint32 material;
|
||||
uint32 unknown1;
|
||||
uint32 elitematerial;
|
||||
Color_Struct color;
|
||||
struct CharSelectEquip
|
||||
{
|
||||
uint32 Material;
|
||||
uint32 Unknown1;
|
||||
uint32 EliteMaterial;
|
||||
Color_Struct Color;
|
||||
};
|
||||
|
||||
struct CharacterSelectEntry_Struct {
|
||||
/*0000*/ uint8 level; //
|
||||
/*0000*/ uint8 hairstyle; //
|
||||
/*0002*/ uint8 gender; //
|
||||
/*0003*/ char name[1]; //variable length, edi+0
|
||||
/*0000*/ uint8 beard; //
|
||||
/*0001*/ uint8 haircolor; //
|
||||
/*0000*/ uint8 face; //
|
||||
/*0000*/ CharSelectEquip equip[9];
|
||||
/*0000*/ uint32 primary; //
|
||||
/*0000*/ uint32 secondary; //
|
||||
/*0000*/ uint8 u15; // 0xff
|
||||
/*0000*/ uint32 deity; //
|
||||
/*0000*/ uint16 zone; //
|
||||
/*0000*/ uint16 instance;
|
||||
/*0000*/ uint8 gohome; //
|
||||
/*0000*/ uint8 u19; // 0xff
|
||||
/*0000*/ uint32 race; //
|
||||
/*0000*/ uint8 tutorial; //
|
||||
/*0000*/ uint8 class_; //
|
||||
/*0000*/ uint8 eyecolor1; //
|
||||
/*0000*/ uint8 beardcolor; //
|
||||
/*0000*/ uint8 eyecolor2; //
|
||||
/*0000*/ uint32 drakkin_heritage; // Drakkin Heritage
|
||||
/*0000*/ uint32 drakkin_tattoo; // Drakkin Tattoo
|
||||
/*0000*/ uint32 drakkin_details; // Drakkin Details (Facial Spikes)
|
||||
/*0000*/ uint8 unknown; // New field to Underfoot
|
||||
struct CharacterSelectEntry_Struct
|
||||
{
|
||||
/*0000*/ uint8 Level; //
|
||||
/*0000*/ uint8 HairStyle; //
|
||||
/*0002*/ uint8 Gender; //
|
||||
/*0003*/ char Name[1]; // variable length, edi+0
|
||||
/*0000*/ uint8 Beard; //
|
||||
/*0001*/ uint8 HairColor; //
|
||||
/*0000*/ uint8 Face; //
|
||||
/*0000*/ CharSelectEquip Equip[9];
|
||||
/*0000*/ uint32 PrimaryIDFile; //
|
||||
/*0000*/ uint32 SecondaryIDFile; //
|
||||
/*0000*/ uint8 Unknown15; // 0xff
|
||||
/*0000*/ uint32 Deity; //
|
||||
/*0000*/ uint16 Zone; //
|
||||
/*0000*/ uint16 Instance;
|
||||
/*0000*/ uint8 GoHome; //
|
||||
/*0000*/ uint8 Unknown19; // 0xff
|
||||
/*0000*/ uint32 Race; //
|
||||
/*0000*/ uint8 Tutorial; //
|
||||
/*0000*/ uint8 Class; //
|
||||
/*0000*/ uint8 EyeColor1; //
|
||||
/*0000*/ uint8 BeardColor; //
|
||||
/*0000*/ uint8 EyeColor2; //
|
||||
/*0000*/ uint32 DrakkinHeritage; // Drakkin Heritage
|
||||
/*0000*/ uint32 DrakkinTattoo; // Drakkin Tattoo
|
||||
/*0000*/ uint32 DrakkinDetails; // Drakkin Details (Facial Spikes)
|
||||
/*0000*/ uint8 Unknown; // New field to Underfoot
|
||||
|
||||
};
|
||||
|
||||
@@ -157,20 +157,22 @@ struct CharacterSelectEntry_Struct {
|
||||
** Character Selection Struct
|
||||
**
|
||||
*/
|
||||
struct CharacterSelect_Struct {
|
||||
/*0000*/ uint32 char_count; //number of chars in this packet
|
||||
/*0004*/ uint32 total_chars; //total number of chars allowed?
|
||||
/*0008*/ CharacterSelectEntry_Struct entries[0];
|
||||
struct CharacterSelect_Struct
|
||||
{
|
||||
/*0000*/ uint32 CharCount; //number of chars in this packet
|
||||
/*0004*/ uint32 TotalChars; //total number of chars allowed?
|
||||
/*0008*/ CharacterSelectEntry_Struct Entries[0];
|
||||
};
|
||||
|
||||
/*
|
||||
* Visible equiptment.
|
||||
* Size: 12 Octets
|
||||
*/
|
||||
struct EquipStruct {
|
||||
/*00*/ uint32 material;
|
||||
/*04*/ uint32 unknown1;
|
||||
/*08*/ uint32 elitematerial;
|
||||
struct EquipStruct
|
||||
{
|
||||
/*00*/ uint32 Material;
|
||||
/*04*/ uint32 Unknown1;
|
||||
/*08*/ uint32 EliteMaterial;
|
||||
/*12*/
|
||||
};
|
||||
|
||||
@@ -284,7 +286,7 @@ struct Spawn_Struct
|
||||
/*0000*/ uint8 unknown12;
|
||||
/*0000*/ uint32 petOwnerId;
|
||||
/*0000*/ uint8 unknown13;
|
||||
/*0000*/ uint32 unknown14; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed
|
||||
/*0000*/ uint32 PlayerState; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed
|
||||
/*0000*/ uint32 unknown15;
|
||||
/*0000*/ uint32 unknown16;
|
||||
/*0000*/ uint32 unknown17;
|
||||
@@ -549,7 +551,7 @@ struct SpellBuff_Struct
|
||||
/*003*/ uint8 effect; // not real
|
||||
/*004*/ uint32 unknown004; // Seen 1 for no buff
|
||||
/*008*/ uint32 spellid;
|
||||
/*012*/ uint32 duration;
|
||||
/*012*/ int32 duration;
|
||||
/*016*/ uint32 unknown016;
|
||||
/*020*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages
|
||||
/*024*/ uint32 counters;
|
||||
@@ -566,7 +568,7 @@ struct SpellBuffFade_Struct_Underfoot {
|
||||
/*007*/ uint8 unknown7;
|
||||
/*008*/ float unknown008;
|
||||
/*012*/ uint32 spellid;
|
||||
/*016*/ uint32 duration;
|
||||
/*016*/ int32 duration;
|
||||
/*020*/ uint32 num_hits;
|
||||
/*024*/ uint32 playerId; // Global player ID?
|
||||
/*028*/ uint32 unknown020;
|
||||
@@ -583,7 +585,7 @@ struct SpellBuffFade_Struct {
|
||||
/*006*/ uint8 effect;
|
||||
/*007*/ uint8 unknown7;
|
||||
/*008*/ uint32 spellid;
|
||||
/*012*/ uint32 duration;
|
||||
/*012*/ int32 duration;
|
||||
/*016*/ uint32 unknown016;
|
||||
/*020*/ uint32 unknown020; // Global player ID?
|
||||
/*024*/ uint32 playerId; // Player id who cast the buff
|
||||
@@ -711,7 +713,7 @@ struct AA_Array
|
||||
{
|
||||
uint32 AA;
|
||||
uint32 value;
|
||||
uint32 unknown08; // Looks like AA_Array is now 12 bytes in Underfoot
|
||||
uint32 charges; // expendable
|
||||
};
|
||||
|
||||
|
||||
@@ -722,9 +724,6 @@ struct Disciplines_Struct {
|
||||
};
|
||||
|
||||
static const uint32 MAX_PLAYER_TRIBUTES = 5;
|
||||
static const uint32 MAX_PLAYER_BANDOLIER = 20;
|
||||
static const uint32 MAX_PLAYER_BANDOLIER_ITEMS = 4;
|
||||
static const uint32 MAX_POTIONS_IN_BELT = 5;
|
||||
static const uint32 TRIBUTE_NONE = 0xFFFFFFFF;
|
||||
|
||||
struct Tribute_Struct {
|
||||
@@ -732,26 +731,42 @@ struct Tribute_Struct {
|
||||
uint32 tier;
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct {
|
||||
uint32 item_id;
|
||||
uint32 icon;
|
||||
char item_name[64];
|
||||
};
|
||||
|
||||
//len = 320
|
||||
enum { //bandolier item positions
|
||||
bandolierMainHand = 0,
|
||||
bandolierOffHand,
|
||||
// Bandolier item positions
|
||||
enum
|
||||
{
|
||||
bandolierPrimary = 0,
|
||||
bandolierSecondary,
|
||||
bandolierRange,
|
||||
bandolierAmmo
|
||||
};
|
||||
struct Bandolier_Struct {
|
||||
char name[32];
|
||||
BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS];
|
||||
|
||||
//len = 72
|
||||
struct BandolierItem_Struct
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
struct PotionBelt_Struct {
|
||||
BandolierItem_Struct items[MAX_POTIONS_IN_BELT];
|
||||
|
||||
//len = 320
|
||||
struct Bandolier_Struct
|
||||
{
|
||||
char Name[32];
|
||||
BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT];
|
||||
};
|
||||
|
||||
//len = 72
|
||||
struct PotionBeltItem_Struct
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 Icon;
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
//len = 288
|
||||
struct PotionBelt_Struct
|
||||
{
|
||||
PotionBeltItem_Struct Items[consts::POTION_BELT_ITEM_COUNT];
|
||||
};
|
||||
|
||||
static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16;
|
||||
@@ -974,7 +989,7 @@ struct PlayerProfile_Struct
|
||||
/*11236*/ uint32 aapoints_spent; // Number of spent AA points
|
||||
/*11240*/ uint32 aapoints; // Unspent AA points
|
||||
/*11244*/ uint8 unknown11244[4];
|
||||
/*11248*/ Bandolier_Struct bandoliers[MAX_PLAYER_BANDOLIER]; // [6400] bandolier contents
|
||||
/*11248*/ Bandolier_Struct bandoliers[consts::BANDOLIERS_SIZE]; // [6400] bandolier contents
|
||||
/*17648*/ PotionBelt_Struct potionbelt; // [360] potion belt 72 extra octets by adding 1 more belt slot
|
||||
/*18008*/ uint8 unknown18008[8];
|
||||
/*18016*/ uint32 available_slots;
|
||||
@@ -1131,7 +1146,7 @@ struct TargetReject_Struct {
|
||||
|
||||
struct PetCommand_Struct {
|
||||
/*000*/ uint32 command;
|
||||
/*004*/ uint32 unknown;
|
||||
/*004*/ uint32 target;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1245,8 +1260,8 @@ struct RequestClientZoneChange_Struct {
|
||||
|
||||
struct Animation_Struct {
|
||||
/*00*/ uint16 spawnid;
|
||||
/*02*/ uint8 action;
|
||||
/*03*/ uint8 value;
|
||||
/*02*/ uint8 speed;
|
||||
/*03*/ uint8 action;
|
||||
/*04*/
|
||||
};
|
||||
|
||||
@@ -1315,9 +1330,10 @@ struct CombatDamage_Struct
|
||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||
/* 05 */ uint16 spellid;
|
||||
/* 07 */ int32 damage;
|
||||
/* 11 */ float unknown11; // cd cc cc 3d
|
||||
/* 15 */ float sequence; // see above notes in Action_Struct
|
||||
/* 19 */ uint8 unknown19[9]; // was [9]
|
||||
/* 11 */ float force; // cd cc cc 3d
|
||||
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
|
||||
/* 19 */ float meleepush_z;
|
||||
/* 23 */ uint8 unknown23[5]; // was [9]
|
||||
/* 28 */
|
||||
};
|
||||
|
||||
@@ -2172,7 +2188,7 @@ struct GroupFollow_Struct { // Underfoot Follow Struct
|
||||
struct InspectBuffs_Struct {
|
||||
/*000*/ uint32 spell_id[BUFF_COUNT];
|
||||
/*100*/ uint32 filler100[5]; // BUFF_COUNT is really 30...
|
||||
/*120*/ uint32 tics_remaining[BUFF_COUNT];
|
||||
/*120*/ int32 tics_remaining[BUFF_COUNT];
|
||||
/*220*/ uint32 filler220[5]; // BUFF_COUNT is really 30...
|
||||
};
|
||||
|
||||
@@ -2425,7 +2441,7 @@ struct BookRequest_Struct {
|
||||
**
|
||||
*/
|
||||
struct Object_Struct {
|
||||
/*00*/ uint32 linked_list_addr[2];// <Zaphod> They are, get this, prev and next, ala linked list
|
||||
/*00*/ uint32 linked_list_addr[2];// They are, get this, prev and next, ala linked list
|
||||
/*08*/ uint32 unknown008; // Something related to the linked list?
|
||||
/*12*/ uint32 drop_id; // Unique object id for zone
|
||||
/*16*/ uint16 zone_id; // Redudant, but: Zone the object appears in
|
||||
@@ -2445,8 +2461,8 @@ struct Object_Struct {
|
||||
/*100*/ uint32 spawn_id; // Spawn Id of client interacting with object
|
||||
/*104*/
|
||||
};
|
||||
//<Zaphod> 01 = generic drop, 02 = armor, 19 = weapon
|
||||
//[13:40] <Zaphod> and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject
|
||||
//01 = generic drop, 02 = armor, 19 = weapon
|
||||
//[13:40] and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject
|
||||
|
||||
/*
|
||||
** Click Object Struct
|
||||
@@ -3758,30 +3774,35 @@ struct DynamicWall_Struct {
|
||||
/*80*/
|
||||
};
|
||||
|
||||
enum { //bandolier actions
|
||||
BandolierCreate = 0,
|
||||
BandolierRemove = 1,
|
||||
BandolierSet = 2
|
||||
// Bandolier actions
|
||||
enum
|
||||
{
|
||||
bandolierCreate = 0,
|
||||
bandolierRemove,
|
||||
bandolierSet
|
||||
};
|
||||
|
||||
struct BandolierCreate_Struct {
|
||||
/*00*/ uint32 action; //0 for create
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ char name[32];
|
||||
/*37*/ uint16 unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 unknown39; //0
|
||||
struct BandolierCreate_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; //0 for create
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ char Name[32];
|
||||
/*37*/ uint16 Unknown37; //seen 0x93FD
|
||||
/*39*/ uint8 Unknown39; //0
|
||||
};
|
||||
|
||||
struct BandolierDelete_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierDelete_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
struct BandolierSet_Struct {
|
||||
/*00*/ uint32 action;
|
||||
/*04*/ uint8 number;
|
||||
/*05*/ uint8 unknown05[35];
|
||||
struct BandolierSet_Struct
|
||||
{
|
||||
/*00*/ uint32 Action;
|
||||
/*04*/ uint8 Number;
|
||||
/*05*/ uint8 Unknown05[35];
|
||||
};
|
||||
|
||||
// Not 100% sure on this struct. Live as of 1/1/11 is different than UF. Seems to work 'OK'
|
||||
@@ -3871,10 +3892,16 @@ struct SendAA_Struct {
|
||||
/*0069*/ uint32 last_id;
|
||||
/*0073*/ uint32 next_id;
|
||||
/*0077*/ uint32 cost2;
|
||||
/*0081*/ uint8 unknown80[7];
|
||||
/*0081*/ uint8 unknown81;
|
||||
/*0082*/ uint8 grant_only; // VetAAs, progression, etc
|
||||
/*0083*/ uint8 unknown83; // 1 for skill cap increase AAs, Mystical Attuning, and RNG attack inc, doesn't seem to matter though
|
||||
/*0084*/ uint32 expendable_charges; // max charges of the AA
|
||||
/*0088*/ uint32 aa_expansion;
|
||||
/*0092*/ uint32 special_category;
|
||||
/*0096*/ uint32 unknown0096;
|
||||
/*0096*/ uint8 shroud;
|
||||
/*0097*/ uint8 unknown97;
|
||||
/*0098*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter?
|
||||
/*0099*/ uint8 unknown99;
|
||||
/*0100*/ uint32 total_abilities;
|
||||
/*0104*/ AA_Ability abilities[0];
|
||||
};
|
||||
@@ -3890,11 +3917,6 @@ struct AA_Action {
|
||||
/*12*/ uint32 exp_value;
|
||||
};
|
||||
|
||||
struct AA_Skills { //this should be removed and changed to AA_Array
|
||||
/*00*/ uint32 aa_skill; // Total AAs Spent
|
||||
/*04*/ uint32 aa_value;
|
||||
/*08*/ uint32 unknown08;
|
||||
};
|
||||
|
||||
struct AAExpUpdate_Struct {
|
||||
/*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability
|
||||
@@ -3913,7 +3935,7 @@ struct AltAdvStats_Struct {
|
||||
};
|
||||
|
||||
struct PlayerAA_Struct { // Is this still used?
|
||||
AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct AATable_Struct {
|
||||
@@ -3923,7 +3945,7 @@ struct AATable_Struct {
|
||||
/*12*/ int32 unknown012;
|
||||
/*16*/ int32 unknown016;
|
||||
/*20*/ int32 unknown020;
|
||||
/*24*/ AA_Skills aa_list[MAX_PP_AA_ARRAY];
|
||||
/*24*/ AA_Array aa_list[MAX_PP_AA_ARRAY];
|
||||
};
|
||||
|
||||
struct Weather_Struct {
|
||||
|
||||
+2
-1
@@ -39,7 +39,8 @@ enum { //values for pTimerType
|
||||
pTimerDisciplineReuseStart = 14,
|
||||
pTimerDisciplineReuseEnd = 24,
|
||||
pTimerCombatAbility = 25,
|
||||
pTimerBeggingPickPocket = 26,
|
||||
pTimerCombatAbility2 = 26, // RoF2+ Tiger Claw is unlinked from other monk skills, generic in case other classes ever need it
|
||||
pTimerBeggingPickPocket = 27,
|
||||
|
||||
pTimerLayHands = 87, //these IDs are used by client too
|
||||
pTimerHarmTouch = 89, //so dont change them
|
||||
|
||||
@@ -47,6 +47,8 @@
|
||||
#define IKSAR 128
|
||||
#define VAHSHIR 130
|
||||
#define CONTROLLED_BOAT 141
|
||||
#define MINOR_ILL_OBJ 142
|
||||
#define TREE 143
|
||||
#define IKSAR_SKELETON 161
|
||||
#define FROGLOK 330
|
||||
#define FROGLOK2 74 // Not sure why /who all reports race as 74 for frogloks
|
||||
|
||||
+518
-497
File diff suppressed because it is too large
Load Diff
@@ -153,6 +153,8 @@
|
||||
#define ServerOP_GetWorldTime 0x200C
|
||||
#define ServerOP_SyncWorldTime 0x200E
|
||||
|
||||
#define ServerOP_ClientFileStatus 0x2020
|
||||
|
||||
#define ServerOP_LSZoneInfo 0x3001
|
||||
#define ServerOP_LSZoneStart 0x3002
|
||||
#define ServerOP_LSZoneBoot 0x3003
|
||||
@@ -1263,6 +1265,22 @@ struct ServerRequestTellQueue_Struct {
|
||||
char name[64];
|
||||
};
|
||||
|
||||
struct ServerRequestClientFileStatus
|
||||
{
|
||||
int zone_id;
|
||||
int instance_id;
|
||||
char name[64];
|
||||
};
|
||||
|
||||
struct ServerResponseClientFileStatus
|
||||
{
|
||||
char name[64];
|
||||
bool spells;
|
||||
bool skills;
|
||||
bool base_data;
|
||||
bool eqgame;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#endif
|
||||
|
||||
+20
-13
@@ -151,28 +151,31 @@ bool SharedDatabase::VerifyInventory(uint32 account_id, int16 slot_id, const Ite
|
||||
|
||||
bool SharedDatabase::SaveInventory(uint32 char_id, const ItemInst* inst, int16 slot_id) {
|
||||
|
||||
// If we never save tribute slots..how are we to ever benefit from them!!? The client
|
||||
// object is destroyed upon zoning - including its inventory object..and if tributes
|
||||
// don't exist in the database, then they will never be loaded when the new client
|
||||
// object is created in the new zone object... Something to consider... -U
|
||||
//
|
||||
// (we could add them to the 'NoRent' checks and dispose of after 30 minutes offline)
|
||||
|
||||
//never save tribute slots:
|
||||
if(slot_id >= EmuConstants::TRIBUTE_BEGIN && slot_id <= EmuConstants::TRIBUTE_END)
|
||||
return true;
|
||||
|
||||
if (slot_id >= EmuConstants::SHARED_BANK_BEGIN && slot_id <= EmuConstants::SHARED_BANK_BAGS_END) {
|
||||
// Shared bank inventory
|
||||
if (!inst)
|
||||
return DeleteSharedBankSlot(char_id, slot_id);
|
||||
else
|
||||
return UpdateSharedBankSlot(char_id, inst, slot_id);
|
||||
if (!inst) {
|
||||
return DeleteSharedBankSlot(char_id, slot_id);
|
||||
}
|
||||
else {
|
||||
// Needed to clear out bag slots that 'REPLACE' in UpdateSharedBankSlot does not overwrite..otherwise, duplication occurs
|
||||
// (This requires that parent then child items be sent..which should be how they are currently passed)
|
||||
if (Inventory::SupportsContainers(slot_id))
|
||||
DeleteSharedBankSlot(char_id, slot_id);
|
||||
return UpdateSharedBankSlot(char_id, inst, slot_id);
|
||||
}
|
||||
}
|
||||
else if (!inst) { // All other inventory
|
||||
return DeleteInventorySlot(char_id, slot_id);
|
||||
}
|
||||
|
||||
// Needed to clear out bag slots that 'REPLACE' in UpdateInventorySlot does not overwrite..otherwise, duplication occurs
|
||||
// (This requires that parent then child items be sent..which should be how they are currently passed)
|
||||
if (Inventory::SupportsContainers(slot_id))
|
||||
DeleteInventorySlot(char_id, slot_id);
|
||||
return UpdateInventorySlot(char_id, inst, slot_id);
|
||||
}
|
||||
|
||||
@@ -209,7 +212,9 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, i
|
||||
|
||||
// Save bag contents, if slot supports bag contents
|
||||
if (inst->IsType(ItemClassContainer) && Inventory::SupportsContainers(slot_id))
|
||||
for (uint8 idx = SUB_BEGIN; idx < EmuConstants::ITEM_CONTAINER_SIZE; idx++) {
|
||||
// Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID'
|
||||
// messages through attrition (and the modded code in SaveInventory)
|
||||
for (uint8 idx = SUB_BEGIN; idx < inst->GetItem()->BagSlots && idx < EmuConstants::ITEM_CONTAINER_SIZE; idx++) {
|
||||
const ItemInst* baginst = inst->GetItem(idx);
|
||||
SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx));
|
||||
}
|
||||
@@ -253,7 +258,9 @@ bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst,
|
||||
|
||||
// Save bag contents, if slot supports bag contents
|
||||
if (inst->IsType(ItemClassContainer) && Inventory::SupportsContainers(slot_id)) {
|
||||
for (uint8 idx = SUB_BEGIN; idx < EmuConstants::ITEM_CONTAINER_SIZE; idx++) {
|
||||
// Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID'
|
||||
// messages through attrition (and the modded code in SaveInventory)
|
||||
for (uint8 idx = SUB_BEGIN; idx < inst->GetItem()->BagSlots && idx < EmuConstants::ITEM_CONTAINER_SIZE; idx++) {
|
||||
const ItemInst* baginst = inst->GetItem(idx);
|
||||
SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx));
|
||||
}
|
||||
|
||||
@@ -55,3 +55,54 @@ bool EQEmu::IsSpecializedSkill(SkillUseTypes skill)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
float EQEmu::GetSkillMeleePushForce(SkillUseTypes skill)
|
||||
{
|
||||
// This is the force/magnitude of the push from an attack of this skill type
|
||||
// You can find these numbers in the clients skill struct
|
||||
switch (skill) {
|
||||
case Skill1HBlunt:
|
||||
case Skill1HSlashing:
|
||||
case SkillHandtoHand:
|
||||
case SkillThrowing:
|
||||
return 0.1f;
|
||||
case Skill2HBlunt:
|
||||
case Skill2HSlashing:
|
||||
case SkillEagleStrike:
|
||||
case SkillKick:
|
||||
case SkillTigerClaw:
|
||||
//case Skill2HPiercing:
|
||||
return 0.2f;
|
||||
case SkillArchery:
|
||||
return 0.15f;
|
||||
case SkillBackstab:
|
||||
case SkillBash:
|
||||
return 0.3f;
|
||||
case SkillDragonPunch:
|
||||
case SkillRoundKick:
|
||||
return 0.25f;
|
||||
case SkillFlyingKick:
|
||||
return 0.4f;
|
||||
case Skill1HPiercing:
|
||||
case SkillFrenzy:
|
||||
return 0.05f;
|
||||
case SkillIntimidation:
|
||||
return 2.5f;
|
||||
default:
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
bool EQEmu::IsBardInstrumentSkill(SkillUseTypes skill)
|
||||
{
|
||||
switch (skill) {
|
||||
case SkillBrassInstruments:
|
||||
case SkillSinging:
|
||||
case SkillStringedInstruments:
|
||||
case SkillWindInstruments:
|
||||
case SkillPercussionInstruments:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,6 +171,8 @@ enum SkillUseTypes
|
||||
|
||||
// temporary until it can be sorted out...
|
||||
#define HIGHEST_SKILL SkillFrenzy
|
||||
// Spell Effects use this value to determine if an effect applies to all skills.
|
||||
#define ALL_SKILLS -1
|
||||
|
||||
// server profile does not reflect this yet..so, prefixed with 'PACKET_'
|
||||
#define PACKET_SKILL_ARRAY_SIZE 100
|
||||
@@ -268,6 +270,8 @@ typedef enum {
|
||||
namespace EQEmu {
|
||||
bool IsTradeskill(SkillUseTypes skill);
|
||||
bool IsSpecializedSkill(SkillUseTypes skill);
|
||||
float GetSkillMeleePushForce(SkillUseTypes skill);
|
||||
bool IsBardInstrumentSkill(SkillUseTypes skill);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+7
-7
@@ -72,7 +72,7 @@
|
||||
|
||||
|
||||
|
||||
#include "../common/eqemu_logsys.h"
|
||||
#include "../common/eqemu_logsys.h"
|
||||
|
||||
#include "classes.h"
|
||||
#include "spdat.h"
|
||||
@@ -162,7 +162,7 @@ bool IsCureSpell(uint16 spell_id)
|
||||
bool CureEffect = false;
|
||||
|
||||
for(int i = 0; i < EFFECT_COUNT; i++){
|
||||
if (sp.effectid[i] == SE_DiseaseCounter || sp.effectid[i] == SE_PoisonCounter
|
||||
if (sp.effectid[i] == SE_DiseaseCounter || sp.effectid[i] == SE_PoisonCounter
|
||||
|| sp.effectid[i] == SE_CurseCounter || sp.effectid[i] == SE_CorruptionCounter)
|
||||
CureEffect = true;
|
||||
}
|
||||
@@ -405,7 +405,7 @@ bool IsPartialCapableSpell(uint16 spell_id)
|
||||
{
|
||||
if (spells[spell_id].no_partial_resist)
|
||||
return false;
|
||||
|
||||
|
||||
if (IsPureNukeSpell(spell_id))
|
||||
return true;
|
||||
|
||||
@@ -447,7 +447,7 @@ bool IsTGBCompatibleSpell(uint16 spell_id)
|
||||
|
||||
bool IsBardSong(uint16 spell_id)
|
||||
{
|
||||
if (IsValidSpell(spell_id) && spells[spell_id].classes[BARD - 1] < 255)
|
||||
if (IsValidSpell(spell_id) && spells[spell_id].classes[BARD - 1] < 255 && !spells[spell_id].IsDisciplineBuff)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -693,9 +693,9 @@ bool IsCombatSkill(uint16 spell_id)
|
||||
{
|
||||
if (!IsValidSpell(spell_id))
|
||||
return false;
|
||||
|
||||
|
||||
//Check if Discipline
|
||||
if ((spells[spell_id].mana == 0 && (spells[spell_id].EndurCost || spells[spell_id].EndurUpkeep)))
|
||||
if ((spells[spell_id].mana == 0 && (spells[spell_id].EndurCost || spells[spell_id].EndurUpkeep)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -1040,7 +1040,7 @@ bool IsCastonFadeDurationSpell(uint16 spell_id)
|
||||
|
||||
bool IsPowerDistModSpell(uint16 spell_id)
|
||||
{
|
||||
if (IsValidSpell(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;
|
||||
|
||||
|
||||
+19
-17
@@ -38,6 +38,7 @@
|
||||
#define MAX_RESISTABLE_EFFECTS 12 // Number of effects that are typcially checked agianst resists.
|
||||
#define MaxLimitInclude 16 //Number(x 0.5) of focus Limiters that have inclusive checks used when calcing focus effects
|
||||
#define MAX_SKILL_PROCS 4 //Number of spells to check skill procs from. (This is arbitrary) [Single spell can have multiple proc checks]
|
||||
#define MAX_SYMPATHETIC_PROCS 10 // Number of sympathetic procs a client can have (This is arbitrary)
|
||||
|
||||
|
||||
const int Z_AGGRO=10;
|
||||
@@ -132,7 +133,7 @@ typedef enum {
|
||||
/* 42 */ ST_Directional = 0x2a, //ae around this target between two angles
|
||||
/* 43 */ ST_GroupClientAndPet = 0x2b,
|
||||
/* 44 */ ST_Beam = 0x2c,
|
||||
/* 45 */ ST_Ring = 0x2d,
|
||||
/* 45 */ ST_Ring = 0x2d,
|
||||
/* 46 */ ST_TargetsTarget = 0x2e, // uses the target of your target
|
||||
/* 47 */ ST_PetMaster = 0x2f, // uses the master as target
|
||||
/* 48 */ // UNKNOWN
|
||||
@@ -150,10 +151,10 @@ typedef enum {
|
||||
} DmgShieldType;
|
||||
|
||||
//Spell Effect IDs
|
||||
// full listing: https://forums.station.sony.com/eq/index.php?threads/enumerated-spa-list.206288/
|
||||
// https://forums.daybreakgames.com/eq/index.php?threads/enumerated-spa-list.206288/
|
||||
// mirror: http://pastebin.com/MYeQqGwe
|
||||
#define SE_CurrentHP 0 // implemented - Heals and nukes, repeates every tic if in a buff
|
||||
#define SE_ArmorClass 1 // implemented
|
||||
#define SE_ArmorClass 1 // implemented
|
||||
#define SE_ATK 2 // implemented
|
||||
#define SE_MovementSpeed 3 // implemented - SoW, SoC, etc
|
||||
#define SE_STR 4 // implemented
|
||||
@@ -196,7 +197,7 @@ typedef enum {
|
||||
#define SE_Destroy 41 // implemented - Disintegrate, Banishment of Shadows
|
||||
#define SE_ShadowStep 42 // implemented
|
||||
#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_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
|
||||
@@ -246,7 +247,7 @@ typedef enum {
|
||||
#define SE_SummonCorpse 91 // implemented
|
||||
#define SE_InstantHate 92 // implemented - add hate
|
||||
#define SE_StopRain 93 // implemented - Wake of Karana
|
||||
#define SE_NegateIfCombat 94 // implemented
|
||||
#define SE_NegateIfCombat 94 // implemented
|
||||
#define SE_Sacrifice 95 // implemented
|
||||
#define SE_Silence 96 // implemented
|
||||
#define SE_ManaPool 97 // implemented
|
||||
@@ -298,7 +299,7 @@ typedef enum {
|
||||
#define SE_LimitCastTimeMin 143 // implemented
|
||||
#define SE_LimitCastTimeMax 144 // implemented (*not used in any known live spell)
|
||||
#define SE_Teleport2 145 // implemented - Banishment of the Pantheon
|
||||
//#define SE_ElectricityResist 146 // *not implemented (Lightning Rod: 23233)
|
||||
//#define SE_ElectricityResist 146 // *not implemented (Lightning Rod: 23233)
|
||||
#define SE_PercentalHeal 147 // implemented
|
||||
#define SE_StackingCommand_Block 148 // implemented?
|
||||
#define SE_StackingCommand_Overwrite 149 // implemented?
|
||||
@@ -528,7 +529,7 @@ typedef enum {
|
||||
#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_Fling 376 // *not implemented - used in 2 test spells (12945 | Movement Test Spell 1)
|
||||
#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
|
||||
@@ -559,7 +560,7 @@ typedef enum {
|
||||
#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)
|
||||
#define SE_CastonFocusEffect 407 // implemented - casts a spell if focus limits are met (ie triggers when a focus effects is applied)
|
||||
#define SE_LimitHPPercent 408 // implemented - limited to a certain percent of your hp(ie heals up to 50%)
|
||||
#define SE_LimitManaPercent 409 // implemented - limited to a certain percent of your mana
|
||||
#define SE_LimitEndPercent 410 // implemented - limited to a certain percent of your end
|
||||
@@ -575,7 +576,7 @@ typedef enum {
|
||||
#define SE_FcLimitUse 420 // implemented - increases numhits count by percent (Note: not used in any known live spells)
|
||||
#define SE_FcIncreaseNumHits 421 // implemented[AA] - increases number of hits a buff has till fade. (focus)
|
||||
#define SE_LimitUseMin 422 // implemented - limit a focus to require a min amount of numhits value (used with above)
|
||||
#define SE_LimitUseType 423 // implemented - limit a focus to require a certain numhits type
|
||||
#define SE_LimitUseType 423 // implemented - limit a focus to require a certain numhits type
|
||||
#define SE_GravityEffect 424 // implemented - Pulls/pushes you toward/away the mob at a set pace
|
||||
//#define SE_Display 425 // *not implemented - Illusion: Flying Dragon(21626)
|
||||
//#define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window
|
||||
@@ -599,9 +600,9 @@ typedef enum {
|
||||
#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 // implementet - bufff stacking blocker (26219 | Qirik's Watch)
|
||||
#define SE_BStacker 447 // implemented
|
||||
#define SE_BStacker 447 // implemented
|
||||
#define SE_CStacker 448 // implemented
|
||||
#define SE_DStacker 449 // 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
|
||||
@@ -617,6 +618,7 @@ typedef enum {
|
||||
|
||||
|
||||
#define DF_Permanent 50
|
||||
#define DF_Aura 51
|
||||
|
||||
// note this struct is historical, we don't actually need it to be
|
||||
// aligned to anything, but for maintaining it it is kept in the order that
|
||||
@@ -732,31 +734,31 @@ struct SPDat_Spell_Struct
|
||||
/* 197 */ bool not_extendable;
|
||||
/* 198- 199 */
|
||||
/* 200 */ bool suspendable; // buff is suspended in suspended buff zones
|
||||
/* 201 */ int viral_range;
|
||||
/* 201 */ int viral_range;
|
||||
/* 202 */
|
||||
/* 203 */ //int songcap; // individual song cap (how live currently does it, not implemented)
|
||||
/* 204 */
|
||||
/* 205 */ bool no_block;
|
||||
/* 206 */
|
||||
/* 206 */
|
||||
/* 207 */ int spellgroup;
|
||||
/* 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; ???
|
||||
/* 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 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
|
||||
/* 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 */
|
||||
/* 220 - 223 */
|
||||
/* 224 */ bool persistdeath; // buff doesn't get stripped on death
|
||||
/* 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
|
||||
/* 231 */ float min_range; //Min casting range
|
||||
/* 232 - 236 */
|
||||
uint8 DamageShieldType; // This field does not exist in spells_us.txt
|
||||
};
|
||||
|
||||
@@ -83,4 +83,20 @@ typedef const char Const_char; //for perl XS
|
||||
#define DLLFUNC extern "C"
|
||||
#endif
|
||||
|
||||
// htonll and ntohll already defined on windows
|
||||
#ifndef WIN32
|
||||
# if defined(__linux__)
|
||||
# include <endian.h>
|
||||
# elif defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
# include <sys/endian.h>
|
||||
# elif defined (__OpenBSD__)
|
||||
# include <sys/types.h>
|
||||
# define be16toh(x) betoh16(x)
|
||||
# define be32toh(x) betoh32(x)
|
||||
# define be64toh(x) betoh64(x)
|
||||
# endif
|
||||
# define htonll(x) htobe64(x)
|
||||
# define ntohll(x) be64toh(x)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+4
-4
@@ -24,13 +24,13 @@
|
||||
|
||||
#define CURRENT_VERSION "1.1.3"
|
||||
|
||||
/*
|
||||
Everytime a Database SQL is added to Github,
|
||||
/*
|
||||
Everytime a Database SQL is added to Github,
|
||||
increment CURRENT_BINARY_DATABASE_VERSION number and make sure you update the manifest
|
||||
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||
*/
|
||||
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9076
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9083
|
||||
#define COMPILE_DATE __DATE__
|
||||
#define COMPILE_TIME __TIME__
|
||||
#ifndef WIN32
|
||||
|
||||
@@ -113,8 +113,8 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un
|
||||
length = mysql_real_escape_string(db, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length());
|
||||
escaped_short_name[length+1] = 0;
|
||||
stringstream query(stringstream::in | stringstream::out);
|
||||
query << "SELECT WSR.ServerID, WSR.ServerTagDescription, WSR.ServerTrusted, SLT.ServerListTypeID, ";
|
||||
query << "SLT.ServerListTypeDescription, WSR.ServerAdminID FROM " << server.options.GetWorldRegistrationTable();
|
||||
query << "SELECT ifnull(WSR.ServerID,999999) AS ServerID, WSR.ServerTagDescription, ifnull(WSR.ServerTrusted,0) AS ServerTrusted, ifnull(SLT.ServerListTypeID,3) AS ServerListTypeID, ";
|
||||
query << "SLT.ServerListTypeDescription, ifnull(WSR.ServerAdminID,0) AS ServerAdminID FROM " << server.options.GetWorldRegistrationTable();
|
||||
query << " AS WSR JOIN " << server.options.GetWorldServerTypeTable() << " AS SLT ON WSR.ServerListTypeID = SLT.ServerListTypeID";
|
||||
query << " WHERE WSR.ServerShortName = '";
|
||||
query << escaped_short_name;
|
||||
@@ -254,7 +254,7 @@ bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name,
|
||||
length = mysql_real_escape_string(db, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length());
|
||||
escaped_short_name[length+1] = 0;
|
||||
stringstream query(stringstream::in | stringstream::out);
|
||||
query << "SELECT max(ServerID) FROM " << server.options.GetWorldRegistrationTable();
|
||||
query << "SELECT ifnull(max(ServerID),0) FROM " << server.options.GetWorldRegistrationTable();
|
||||
|
||||
if(mysql_query(db, query.str().c_str()) != 0)
|
||||
{
|
||||
|
||||
@@ -306,7 +306,7 @@ void Database::LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 items) {
|
||||
}
|
||||
|
||||
void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint32 items) {
|
||||
/* Merchant transactions are from the perspective of the merchant, not the player -U */
|
||||
/* Merchant transactions are from the perspective of the merchant, not the player */
|
||||
std::string query = StringFormat("INSERT INTO `qs_merchant_transaction_record` SET `time` = NOW(), "
|
||||
"`zone_id` = '%i', `merchant_id` = '%i', `merchant_pp` = '%i', "
|
||||
"`merchant_gp` = '%i', `merchant_sp` = '%i', `merchant_cp` = '%i', "
|
||||
|
||||
@@ -22,10 +22,10 @@ OP_ExpansionInfo=0x711a
|
||||
OP_GuildsList=0x2d38
|
||||
OP_EnterWorld=0x57c3
|
||||
OP_PostEnterWorld=0x0c3d
|
||||
OP_World_Client_CRC1=0x0044
|
||||
OP_World_Client_CRC2=0x26df
|
||||
OP_SendSpellChecksum=0x0000
|
||||
OP_SendSkillCapsChecksum=0x0000
|
||||
OP_World_SpellFileCheck=0x0000 # appears to be removed in RoF, maybe 0x0044? I don't have a client to check
|
||||
OP_World_SkillFileCheck=0x0000
|
||||
OP_World_BaseDataFileCheck=0x0000
|
||||
OP_World_ExeFileCheck=0x26df
|
||||
|
||||
# Character Select Related:
|
||||
OP_SendMaxCharacters=0x5349
|
||||
@@ -194,6 +194,7 @@ OP_Consent=0x400e
|
||||
OP_ConsentDeny=0x34c1
|
||||
OP_AutoFire=0x314e
|
||||
OP_PetCommands=0x0093
|
||||
OP_PetHoTT=0x0df4
|
||||
OP_DeleteSpell=0x305c
|
||||
OP_Surname=0x1a87
|
||||
OP_ClearSurname=0x17b6
|
||||
@@ -269,8 +270,8 @@ OP_RequestDuel=0x1ea9
|
||||
OP_MobRename=0x5040
|
||||
OP_AugmentItem=0x1627 # Was 0x37cb
|
||||
OP_WeaponEquip1=0x35c3
|
||||
OP_WeaponEquip2=0x012f # Was 0x6022
|
||||
OP_WeaponUnequip2=0x1076 # Was 0x0110
|
||||
OP_PlayerStateAdd=0x012f # Was 0x6022
|
||||
OP_PlayerStateRemove=0x1076 # Was 0x0110
|
||||
OP_ApplyPoison=0x1499
|
||||
OP_Save=0x2e6f
|
||||
OP_TestBuff=0x046e # Was 0x3772
|
||||
|
||||
@@ -22,10 +22,10 @@ OP_ExpansionInfo=0x590d
|
||||
OP_GuildsList=0x507a
|
||||
OP_EnterWorld=0x578f
|
||||
OP_PostEnterWorld=0x6259
|
||||
OP_World_Client_CRC1=0x12cc
|
||||
OP_World_Client_CRC2=0x0f13
|
||||
OP_SendSpellChecksum=0x0000
|
||||
OP_SendSkillCapsChecksum=0x0000
|
||||
OP_World_SpellFileCheck=0x0000 # appears to be removed in RoF
|
||||
OP_World_SkillFileCheck=0x4b8d
|
||||
OP_World_BaseDataFileCheck=0x298d
|
||||
OP_World_ExeFileCheck=0x0f13
|
||||
|
||||
# Character Select Related:
|
||||
OP_SendMaxCharacters=0x5475
|
||||
@@ -193,6 +193,7 @@ OP_Consent=0x1fd1
|
||||
OP_ConsentDeny=0x7a45
|
||||
OP_AutoFire=0x241e
|
||||
OP_PetCommands=0x0159
|
||||
OP_PetHoTT=0x794a
|
||||
OP_DeleteSpell=0x3358
|
||||
OP_Surname=0x0423
|
||||
OP_ClearSurname=0x3fb0
|
||||
@@ -268,8 +269,8 @@ OP_RequestDuel=0x3af1
|
||||
OP_MobRename=0x2c57
|
||||
OP_AugmentItem=0x661b
|
||||
OP_WeaponEquip1=0x34a7
|
||||
OP_WeaponEquip2=0x559a
|
||||
OP_WeaponUnequip2=0x2d25
|
||||
OP_PlayerStateAdd=0x559a
|
||||
OP_PlayerStateRemove=0x2d25
|
||||
OP_ApplyPoison=0x31e6
|
||||
OP_Save=0x4a39
|
||||
OP_TestBuff=0x7cb8
|
||||
@@ -294,8 +295,8 @@ OP_MarkNPC=0x1fb5
|
||||
OP_MarkRaidNPC=0x5a58 #unimplemented
|
||||
OP_ClearNPCMarks=0x2003
|
||||
OP_ClearRaidNPCMarks=0x20d3 #unimplemented
|
||||
OP_DelegateAbility=0x4c9d
|
||||
OP_SetGroupTarget=0x026
|
||||
OP_DelegateAbility=0x76b8
|
||||
OP_SetGroupTarget=0x2814
|
||||
OP_Charm=0x5d92
|
||||
OP_Stun=0x36a4
|
||||
OP_SendFindableNPCs=0x4613
|
||||
@@ -402,12 +403,12 @@ OP_LootComplete=0x55c4
|
||||
|
||||
# bazaar trader stuff:
|
||||
OP_BazaarSearch=0x39d6
|
||||
OP_TraderDelItem=0x0000
|
||||
OP_TraderDelItem=0x5829
|
||||
OP_BecomeTrader=0x61b3
|
||||
OP_TraderShop=0x31df
|
||||
OP_Trader=0x4ef5
|
||||
OP_TraderBuy=0x0000
|
||||
OP_Barter=0x243a
|
||||
OP_TraderBuy=0x0000
|
||||
OP_ShopItem=0x0000
|
||||
OP_BazaarInspect=0x0000
|
||||
OP_Bazaar=0x0000
|
||||
|
||||
@@ -26,10 +26,10 @@ OP_ExpansionInfo=0x7519 # C
|
||||
OP_GuildsList=0x5b0b # C
|
||||
OP_EnterWorld=0x1c20 # C
|
||||
OP_PostEnterWorld=0x7c94 # C
|
||||
OP_World_Client_CRC1=0x0ca5 # C
|
||||
OP_World_Client_CRC2=0x1cb3 # C
|
||||
OP_SendSpellChecksum=0x5bad # C
|
||||
OP_SendSkillCapsChecksum=0x5d24 # C
|
||||
OP_World_SpellFileCheck=0x0ca5 # C
|
||||
OP_World_SkillFileCheck=0x5bad # C
|
||||
OP_World_BaseDataFileCheck=0x5d24 # C
|
||||
OP_World_ExeFileCheck=0x1cb3 # C
|
||||
|
||||
# Character Select Related:
|
||||
OP_DeleteCharacter=0x0254 # C
|
||||
@@ -266,8 +266,8 @@ OP_RequestDuel=0x79e0 # C
|
||||
OP_MobRename=0x0a1d # C
|
||||
OP_AugmentItem=0x0370 # C
|
||||
OP_WeaponEquip1=0x719e # C
|
||||
OP_WeaponEquip2=0x7b6e # C
|
||||
OP_WeaponUnequip2=0x19a8 # C
|
||||
OP_PlayerStateAdd=0x7b6e # C
|
||||
OP_PlayerStateRemove=0x19a8 # C
|
||||
OP_ApplyPoison=0x405b # C
|
||||
OP_Save=0x5c85 # C
|
||||
OP_TestBuff=0x5fc7 # C
|
||||
|
||||
@@ -23,10 +23,10 @@ OP_ExpansionInfo=0x0A1B #SEQ 12/04/08
|
||||
OP_GuildsList=0x04FB #SEQ 12/04/08
|
||||
OP_EnterWorld=0x1340 #SEQ 12/04/08
|
||||
OP_PostEnterWorld=0x1AEE #SEQ 12/04/08
|
||||
OP_World_Client_CRC1=0x7A9E #SEQ 12/04/08
|
||||
OP_World_Client_CRC2=0x3795 #SEQ 12/04/08
|
||||
OP_SendSpellChecksum=0x22CF #SEQ 12/04/08
|
||||
OP_SendSkillCapsChecksum=0x43BA #SEQ 12/04/08
|
||||
OP_World_SpellFileCheck=0x7A9E #these are guessed but should be right I hope, who even uses SoF though
|
||||
OP_World_ExeFileCheck=0x3795
|
||||
OP_World_BaseDataFileCheck=0x22CF
|
||||
OP_SendSkillCapsChecksum=0x43BA
|
||||
|
||||
#Character Select Related:
|
||||
OP_DeleteCharacter=0x789F #SEQ 12/04/08
|
||||
@@ -262,8 +262,8 @@ OP_RequestDuel=0x3A2B #Xinu 02/22/09
|
||||
OP_MobRename=0x6be5 #Trevius 01/16/09
|
||||
OP_AugmentItem=0x172A #Trevius 03/14/09
|
||||
OP_WeaponEquip1=0x7260 #Trevius 02/27/09
|
||||
OP_WeaponEquip2=0x5C2F #Trevius 02/27/09
|
||||
OP_WeaponUnequip2=0x6213 #Trevius 02/27/09
|
||||
OP_PlayerStateAdd=0x5C2F #Trevius 02/27/09
|
||||
OP_PlayerStateRemove=0x6213 #Trevius 02/27/09
|
||||
OP_ApplyPoison=0x4543 #WildcardX 03/6/09
|
||||
OP_Save=0x72F2 #Trevius 03/15/09
|
||||
OP_TestBuff=0x07BF #/testbuff
|
||||
|
||||
@@ -27,8 +27,6 @@ OP_GuildsList=0x6957 #same as zone guild list afaik
|
||||
OP_ApproveName=0x3ea6 # EQEmu 11/28/05
|
||||
OP_EnterWorld=0x7cba # ShowEQ 10/27/05
|
||||
OP_PostEnterWorld=0x52A4 # EQEmu 06/29/05
|
||||
OP_World_Client_CRC1=0x5072 # ShowEQ 10/27/05
|
||||
OP_World_Client_CRC2=0x5b18 # ShowEQ 10/27/05
|
||||
OP_SetChatServer=0x00d7 # ShowEQ 10/27/05
|
||||
OP_SetChatServer2=0x6536 # ShowEQ 10/27/05
|
||||
OP_ZoneServerInfo=0x61b6 # ShowEQ 10/27/05
|
||||
@@ -42,6 +40,10 @@ OP_WorldLoginFailed=0x8DA7 # world->client. reject.
|
||||
OP_WorldLogout=0x7718 # client->world
|
||||
OP_WorldLevelTooHigh=0x583b # world->client. Cancels zone in.
|
||||
OP_CharInacessable=0x436A # world->client. Cancels zone in.
|
||||
OP_World_SpellFileCheck=0x5072
|
||||
OP_World_SkillFileCheck=0x0000
|
||||
OP_World_BaseDataFileCheck=0x0000
|
||||
OP_World_ExeFileCheck=0x5b18
|
||||
|
||||
#Zone in opcodes
|
||||
OP_ZoneEntry=0x7213 # ShowEQ 10/27/05
|
||||
@@ -525,7 +527,7 @@ OP_KnowledgeBase=0x0000
|
||||
OP_SlashAdventure=0x571a # /adventure
|
||||
OP_VetRewardsAvaliable=0x0557
|
||||
OP_VetClaimRequest=0x6ba0
|
||||
OP_VetClaimReply=0x0000
|
||||
OP_VetClaimReply=0x407e
|
||||
OP_BecomePVPPrompt=0x36B2 #guessed from ASM
|
||||
OP_PVPStats=0x5cc0
|
||||
OP_PVPLeaderBoardRequest=0x61d2
|
||||
@@ -534,8 +536,8 @@ OP_PVPLeaderBoardDetailsRequest=0x06a2
|
||||
OP_PVPLeaderBoardDetailsReply=0x246a
|
||||
OP_PickLockSuccess=0x40E7
|
||||
OP_WeaponEquip1=0x6c5e
|
||||
OP_WeaponEquip2=0x63da
|
||||
OP_WeaponUnequip2=0x381d
|
||||
OP_PlayerStateAdd=0x63da
|
||||
OP_PlayerStateRemove=0x381d
|
||||
OP_VoiceMacroIn=0x2866 # Client to Server
|
||||
OP_VoiceMacroOut=0x2ec6 # Server to Client
|
||||
OP_CameraEffect=0x0937 # Correct
|
||||
|
||||
@@ -26,10 +26,10 @@ OP_ExpansionInfo=0x7e4d # C
|
||||
OP_GuildsList=0x5b0b # C
|
||||
OP_EnterWorld=0x51b9 # C
|
||||
OP_PostEnterWorld=0x5d32 # C
|
||||
OP_World_Client_CRC1=0x3a18 # C
|
||||
OP_World_Client_CRC2=0x3e50 # C
|
||||
OP_SendSpellChecksum=0x46d3 # C
|
||||
OP_SendSkillCapsChecksum=0x040b # C
|
||||
OP_World_SpellFileCheck=0x3a18
|
||||
OP_World_SkillFileCheck=0x46d3
|
||||
OP_World_BaseDataFileCheck=0x040b
|
||||
OP_World_ExeFileCheck=0x3e50
|
||||
|
||||
# Character Select Related:
|
||||
OP_DeleteCharacter=0x5ca5 # C
|
||||
@@ -197,6 +197,7 @@ OP_Consent=0x6bb9 # C
|
||||
OP_ConsentDeny=0x4cd1 # C
|
||||
OP_AutoFire=0x5db5 # C
|
||||
OP_PetCommands=0x7706 # C
|
||||
OP_PetHoTT=0x2528
|
||||
OP_DeleteSpell=0x0698 # C
|
||||
OP_Surname=0x44ae # C
|
||||
OP_ClearSurname=0x6705 # C
|
||||
@@ -272,8 +273,8 @@ OP_RequestDuel=0x6cfe # C
|
||||
OP_MobRename=0x0507 # C
|
||||
OP_AugmentItem=0x7c87 # C
|
||||
OP_WeaponEquip1=0x4572 # C
|
||||
OP_WeaponEquip2=0x399b # C
|
||||
OP_WeaponUnequip2=0x416b # C
|
||||
OP_PlayerStateAdd=0x399b # C
|
||||
OP_PlayerStateRemove=0x416b # C
|
||||
OP_ApplyPoison=0x5cd3 # C
|
||||
OP_Save=0x6618 # C
|
||||
OP_TestBuff=0x3415 # C
|
||||
|
||||
+390
-44
@@ -9,12 +9,20 @@
|
||||
$menu_displayed = 0;
|
||||
|
||||
use Config;
|
||||
use File::Copy qw(copy);
|
||||
use POSIX qw(strftime);
|
||||
use File::Path;
|
||||
use File::Find;
|
||||
use URI::Escape;
|
||||
|
||||
$time_stamp = strftime('%m-%d-%Y', gmtime());
|
||||
|
||||
$console_output .= " Operating System is: $Config{osname}\n";
|
||||
if($Config{osname}=~/linux/i){ $OS = "Linux"; }
|
||||
if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; }
|
||||
|
||||
#::: If current version is less than what world is reporting, then download a new one...
|
||||
$current_version = 2;
|
||||
$current_version = 7;
|
||||
|
||||
if($ARGV[0] eq "V"){
|
||||
if($ARGV[1] > $current_version){
|
||||
@@ -36,8 +44,13 @@ print "Perl Version is " . $perl_version . "\n";
|
||||
if($perl_version > 5.12){ no warnings 'uninitialized'; }
|
||||
no warnings;
|
||||
|
||||
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime();
|
||||
|
||||
#::: Cleanup staged folder...
|
||||
rmtree("updates_staged/");
|
||||
|
||||
my $confile = "eqemu_config.xml"; #default
|
||||
open(F, "<$confile") or die "Unable to open config: $confile\n";
|
||||
open(F, "<$confile");
|
||||
my $indb = 0;
|
||||
while(<F>) {
|
||||
s/\r//g;
|
||||
@@ -97,12 +110,12 @@ if($path eq ""){
|
||||
mkdir('db_update');
|
||||
|
||||
#::: Check if db_version table exists...
|
||||
if(trim(GetMySQLResult("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne ""){
|
||||
if(trim(GetMySQLResult("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne "" && $db){
|
||||
print GetMySQLResult("DROP TABLE db_version");
|
||||
print "Old db_version table present, dropping...\n\n";
|
||||
}
|
||||
|
||||
if(GetMySQLResult("SHOW TABLES LIKE 'db_version'") eq ""){
|
||||
if(GetMySQLResult("SHOW TABLES LIKE 'db_version'") eq "" && $db){
|
||||
print GetMySQLResult("
|
||||
CREATE TABLE db_version (
|
||||
version int(11) DEFAULT '0'
|
||||
@@ -123,24 +136,24 @@ if($bin_db_ver == $local_db_ver && $ARGV[0] eq "ran_from_start"){
|
||||
exit;
|
||||
}
|
||||
else{
|
||||
print $console_output;
|
||||
print $console_output if $db;
|
||||
}
|
||||
|
||||
if($db){
|
||||
print " Binary Database Version: (" . $bin_db_ver . ")\n";
|
||||
print " Local Database Version: (" . $local_db_ver . ")\n\n";
|
||||
|
||||
print " Binary Database Version: (" . $bin_db_ver . ")\n";
|
||||
print " Local Database Version: (" . $local_db_ver . ")\n\n";
|
||||
#::: If World ran this script, and our version is up to date, continue...
|
||||
if($bin_db_ver <= $local_db_ver && $ARGV[0] eq "ran_from_world"){
|
||||
print " Database up to Date: Continuing World Bootup...\n";
|
||||
print "============================================================\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
#::: If World ran this script, and our version is up to date, continue...
|
||||
if($bin_db_ver <= $local_db_ver && $ARGV[0] eq "ran_from_world"){
|
||||
print " Database up to Date: Continuing World Bootup...\n";
|
||||
print "============================================================\n";
|
||||
exit;
|
||||
print "Retrieving latest database manifest...\n";
|
||||
GetRemoteFile("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt");
|
||||
}
|
||||
|
||||
print "Retrieving latest database manifest...\n";
|
||||
GetRemoteFile("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt");
|
||||
# GetRemoteFile("https://dl.dropboxusercontent.com/u/50023467/dl/db_update_manifest.txt", "db_update/db_update_manifest.txt");
|
||||
|
||||
if($local_db_ver < $bin_db_ver && $ARGV[0] eq "ran_from_world"){
|
||||
print "You have missing database updates, type 1 or 2 to backup your database before running them as recommended...\n\n";
|
||||
#::: Display Menu
|
||||
@@ -152,6 +165,10 @@ else{
|
||||
ShowMenuPrompt();
|
||||
}
|
||||
|
||||
sub UpdateSelf{
|
||||
GetRemoteFile("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl", "eqemu_update.pl");
|
||||
die "Rerun eqemu_update.pl";
|
||||
}
|
||||
|
||||
sub ShowMenuPrompt {
|
||||
my %dispatch = (
|
||||
@@ -160,6 +177,11 @@ sub ShowMenuPrompt {
|
||||
3 => \&Run_Database_Check,
|
||||
4 => \&AA_Fetch,
|
||||
5 => \&OpCodes_Fetch,
|
||||
6 => \&MapFiles_Fetch,
|
||||
7 => \&Plugins_Fetch,
|
||||
8 => \&QuestFiles_Fetch,
|
||||
9 => \&LUA_Modules_Fetch,
|
||||
20 => \&UpdateSelf,
|
||||
0 => \&Exit,
|
||||
);
|
||||
|
||||
@@ -198,25 +220,30 @@ sub ShowMenuPrompt {
|
||||
}
|
||||
|
||||
sub MenuOptions {
|
||||
|
||||
if(@total_updates){
|
||||
$option[3] = "Run pending REQUIRED updates... (" . scalar (@total_updates) . ")";
|
||||
}
|
||||
else{
|
||||
$option[3] = "Check for pending REQUIRED Database updates
|
||||
Stages updates for automatic upgrade...";
|
||||
$option[3] = "Check and stage pending REQUIRED Database updates";
|
||||
}
|
||||
|
||||
return <<EO_MENU;
|
||||
Database Management Menu (Please Select):
|
||||
1) Backup Database - (Saves to Backups folder)
|
||||
Ideal to perform before performing updates
|
||||
EQEmu Update Utility Menu:
|
||||
1) Backup Database - (Saves to Backups folder)
|
||||
2) Backup Database Compressed - (Saves to Backups folder)
|
||||
Ideal to perform before performing updates
|
||||
3) $option[3]
|
||||
4) AAs - Get Latest AA's from PEQ (This deletes AA's already in the database)
|
||||
5) OPCodes - Download latest opcodes from repository
|
||||
4) AAs - Download Latest AA's from PEQ (This overwrites existing data)
|
||||
5) OPCodes - Download latest opcodes
|
||||
6) Maps - Download latest map and water files
|
||||
7) Plugins - Download latest Perl plugins
|
||||
8) Quests - Download latest PEQ quests and stage updates
|
||||
9) LUA Modules - Download latest LUA Modules (Required for Lua)
|
||||
20) Force update this script (Redownload)
|
||||
0) Exit
|
||||
|
||||
Enter numbered option and press enter...
|
||||
|
||||
EO_MENU
|
||||
}
|
||||
|
||||
@@ -249,6 +276,7 @@ sub Exit{ }
|
||||
#::: Returns Tab Delimited MySQL Result from Command Line
|
||||
sub GetMySQLResult{
|
||||
my $run_query = $_[0];
|
||||
if(!$db){ return; }
|
||||
if($OS eq "Windows"){ return `"$path" --host $host --user $user --password="$pass" $db -N -B -e "$run_query"`; }
|
||||
if($OS eq "Linux"){
|
||||
$run_query =~s/`//g;
|
||||
@@ -258,6 +286,7 @@ sub GetMySQLResult{
|
||||
|
||||
sub GetMySQLResultFromFile{
|
||||
my $update_file = $_[0];
|
||||
if(!$db){ return; }
|
||||
if($OS eq "Windows"){ return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`; }
|
||||
if($OS eq "Linux"){ return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`; }
|
||||
}
|
||||
@@ -267,34 +296,67 @@ sub GetMySQLResultFromFile{
|
||||
sub GetRemoteFile{
|
||||
my $URL = $_[0];
|
||||
my $Dest_File = $_[1];
|
||||
my $content_type = $_[2];
|
||||
|
||||
#::: Build file path of the destination file so that we may check for the folder's existence and make it if necessary
|
||||
if($Dest_File=~/\//i){
|
||||
my @dir_path = split('/', $Dest_File);
|
||||
$build_path = "";
|
||||
$di = 0;
|
||||
while($dir_path[$di]){
|
||||
$build_path .= $dir_path[$di] . "/";
|
||||
#::: If path does not exist, create the directory...
|
||||
if (!-d $build_path) {
|
||||
mkdir($build_path);
|
||||
}
|
||||
if(!$dir_path[$di + 2] && $dir_path[$di + 1]){
|
||||
# print $actual_path . "\n";
|
||||
$actual_path = $build_path;
|
||||
last;
|
||||
}
|
||||
$di++;
|
||||
}
|
||||
}
|
||||
|
||||
if($OS eq "Windows"){
|
||||
require LWP::UserAgent;
|
||||
my $ua = LWP::UserAgent->new;
|
||||
$ua->timeout(10);
|
||||
$ua->env_proxy;
|
||||
my $response = $ua->get($URL);
|
||||
|
||||
if ($response->is_success){
|
||||
open (FILE, '> ' . $Dest_File . '');
|
||||
print FILE $response->decoded_content;
|
||||
close (FILE);
|
||||
print " URL: " . $URL . "\n";
|
||||
print " Saved: " . $Dest_File . " \n";
|
||||
#::: For non-text type requests...
|
||||
if($content_type == 1){
|
||||
use LWP::Simple qw(getstore);
|
||||
if(!getstore($URL, $Dest_File)){
|
||||
print "Error, no connection or failed request...\n\n";
|
||||
}
|
||||
else{
|
||||
print " o URL: (" . $URL . ")\n";
|
||||
print " o Saved: (" . $Dest_File . ") \n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
print "Error, no connection to the internet...\n\n";
|
||||
die $response->status_line;
|
||||
else{
|
||||
require LWP::UserAgent;
|
||||
my $ua = LWP::UserAgent->new;
|
||||
$ua->timeout(10);
|
||||
$ua->env_proxy;
|
||||
my $response = $ua->get($URL);
|
||||
|
||||
if ($response->is_success){
|
||||
open (FILE, '> ' . $Dest_File . '');
|
||||
print FILE $response->decoded_content;
|
||||
close (FILE);
|
||||
print " o URL: (" . $URL . ")\n";
|
||||
print " o Saved: (" . $Dest_File . ") \n";
|
||||
}
|
||||
else {
|
||||
print "Error, no connection or failed request...\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
if($OS eq "Linux"){
|
||||
#::: wget -O db_update/db_update_manifest.txt https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt
|
||||
$wget = `wget --no-check-certificate --quiet -O $Dest_File $URL`;
|
||||
print " URL: " . $URL . "\n";
|
||||
print " Saved: " . $Dest_File . " \n";
|
||||
print " o URL: (" . $URL . ")\n";
|
||||
print " o Saved: (" . $Dest_File . ") \n";
|
||||
if($wget=~/unable to resolve/i){
|
||||
print "Error, no connection to the internet...\n\n";
|
||||
die;
|
||||
print "Error, no connection or failed request...\n\n";
|
||||
#die;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -309,6 +371,11 @@ sub trim {
|
||||
|
||||
#::: Fetch Latest PEQ AA's
|
||||
sub AA_Fetch{
|
||||
if(!$db){
|
||||
print "No database present, check your eqemu_config.xml for proper MySQL/MariaDB configuration...\n";
|
||||
return;
|
||||
}
|
||||
|
||||
print "Pulling down PEQ AA Tables...\n";
|
||||
GetRemoteFile("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/peq_aa_tables.sql", "db_update/peq_aa_tables.sql");
|
||||
print "\n\nInstalling AA Tables...\n";
|
||||
@@ -341,13 +408,292 @@ sub OpCodes_Fetch{
|
||||
|
||||
print "\nDownloading (" . $opcodes{$loop}[0] . ") File: '" . $file_name . "'...\n\n";
|
||||
GetRemoteFile($opcodes{$loop}[1], $file_name);
|
||||
$loop++;
|
||||
$loop++;
|
||||
}
|
||||
print "\nDone...\n\n";
|
||||
}
|
||||
|
||||
sub CopyFile{
|
||||
$l_source_file = $_[0];
|
||||
$l_dest_file = $_[1];
|
||||
if($l_dest_file=~/\//i){
|
||||
my @dir_path = split('/', $l_dest_file);
|
||||
$build_path = "";
|
||||
$di = 0;
|
||||
while($dir_path[$di]){
|
||||
$build_path .= $dir_path[$di] . "/";
|
||||
#::: If path does not exist, create the directory...
|
||||
if (!-d $build_path) {
|
||||
mkdir($build_path);
|
||||
}
|
||||
if(!$dir_path[$di + 2] && $dir_path[$di + 1]){
|
||||
# print $actual_path . "\n";
|
||||
$actual_path = $build_path;
|
||||
last;
|
||||
}
|
||||
$di++;
|
||||
}
|
||||
}
|
||||
copy $l_source_file, $l_dest_file;
|
||||
}
|
||||
|
||||
sub MapFiles_Fetch{
|
||||
print "\n --- Fetching Latest Maps --- \n";
|
||||
|
||||
GetRemoteFile("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/!eqemu_maps_manifest.txt", "updates_staged/eqemu_maps_manifest.txt");
|
||||
|
||||
#::: Get Data from manifest
|
||||
open (FILE, "updates_staged/eqemu_maps_manifest.txt");
|
||||
$i = 0;
|
||||
while (<FILE>){
|
||||
chomp;
|
||||
$o = $_;
|
||||
@manifest_map_data = split(',', $o);
|
||||
if($manifest_map_data[0] ne ""){
|
||||
$maps_manifest[$i] = [$manifest_map_data[0], $manifest_map_data[1]];
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
#::: Download
|
||||
$fc = 0;
|
||||
for($m = 0; $m <= $i; $m++){
|
||||
my $file_existing = $maps_manifest[$m][0];
|
||||
my $file_existing_size = (stat $file_existing)[7];
|
||||
if($file_existing_size != $maps_manifest[$m][1]){
|
||||
print "Updating: '" . $maps_manifest[$m][0] . "'\n";
|
||||
GetRemoteFile("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/" . $maps_manifest[$m][0], $maps_manifest[$m][0], 1);
|
||||
$fc++;
|
||||
}
|
||||
}
|
||||
|
||||
if($fc == 0){
|
||||
print "\nNo Map Updates found... \n\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub QuestFiles_Fetch{
|
||||
if (!-e "updates_staged/Quests-Plugins-master/quests/") {
|
||||
print "\n --- Fetching Latest Quests --- \n";
|
||||
GetRemoteFile("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1);
|
||||
print "\nFetched latest quests...\n";
|
||||
mkdir('updates_staged');
|
||||
UnZip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/');
|
||||
}
|
||||
|
||||
$fc = 0;
|
||||
use File::Find;
|
||||
use File::Compare;
|
||||
|
||||
my @files;
|
||||
my $start_dir = "updates_staged/Quests-Plugins-master/quests/";
|
||||
find(
|
||||
sub { push @files, $File::Find::name unless -d; },
|
||||
$start_dir
|
||||
);
|
||||
for my $file (@files) {
|
||||
if($file=~/\.pl|\.lua|\.ext/i){
|
||||
$staged_file = $file;
|
||||
$dest_file = $file;
|
||||
$dest_file =~s/updates_staged\/Quests-Plugins-master\///g;
|
||||
|
||||
if (!-e $dest_file) {
|
||||
CopyFile($staged_file, $dest_file);
|
||||
print "Installing :: '" . $dest_file . "'\n";
|
||||
$fc++;
|
||||
}
|
||||
else{
|
||||
$diff = Diff($dest_file, $staged_file);
|
||||
if($diff ne ""){
|
||||
$backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file;
|
||||
|
||||
print $diff . "\n";
|
||||
print "\nFile Different :: '" . $dest_file . "'\n";
|
||||
print "\nDo you wish to update this Quest? '" . $dest_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n";
|
||||
my $input = <STDIN>;
|
||||
if($input=~/N/i){}
|
||||
else{
|
||||
#::: Make a backup
|
||||
CopyFile($dest_file, $backup_dest);
|
||||
#::: Copy staged to running
|
||||
copy($staged_file, $dest_file);
|
||||
print "Installing :: '" . $dest_file . "'\n\n";
|
||||
}
|
||||
$fc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($fc == 0){
|
||||
print "\nNo Quest Updates found... \n\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub LUA_Modules_Fetch{
|
||||
if (!-e "updates_staged/Quests-Plugins-master/quests/lua_modules/") {
|
||||
print "\n --- Fetching Latest LUA Modules --- \n";
|
||||
GetRemoteFile("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1);
|
||||
print "\nFetched latest LUA Modules...\n";
|
||||
UnZip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/');
|
||||
}
|
||||
|
||||
$fc = 0;
|
||||
use File::Find;
|
||||
use File::Compare;
|
||||
|
||||
my @files;
|
||||
my $start_dir = "updates_staged/Quests-Plugins-master/quests/lua_modules/";
|
||||
find(
|
||||
sub { push @files, $File::Find::name unless -d; },
|
||||
$start_dir
|
||||
);
|
||||
for my $file (@files) {
|
||||
if($file=~/\.pl|\.lua|\.ext/i){
|
||||
$staged_file = $file;
|
||||
$dest_file = $file;
|
||||
$dest_file =~s/updates_staged\/Quests-Plugins-master\/quests\///g;
|
||||
|
||||
if (!-e $dest_file) {
|
||||
CopyFile($staged_file, $dest_file);
|
||||
print "Installing :: '" . $dest_file . "'\n";
|
||||
$fc++;
|
||||
}
|
||||
else{
|
||||
$diff = Diff($dest_file, $staged_file);
|
||||
if($diff ne ""){
|
||||
$backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file;
|
||||
print $diff . "\n";
|
||||
print "\nFile Different :: '" . $dest_file . "'\n";
|
||||
print "\nDo you wish to update this LUA Module? '" . $dest_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n";
|
||||
my $input = <STDIN>;
|
||||
if($input=~/N/i){}
|
||||
else{
|
||||
#::: Make a backup
|
||||
CopyFile($dest_file, $backup_dest);
|
||||
#::: Copy staged to running
|
||||
copy($staged_file, $dest_file);
|
||||
print "Installing :: '" . $dest_file . "'\n\n";
|
||||
}
|
||||
$fc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($fc == 0){
|
||||
print "\nNo LUA Modules Updates found... \n\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub Plugins_Fetch{
|
||||
if (!-e "updates_staged/Quests-Plugins-master/plugins/") {
|
||||
print "\n --- Fetching Latest Plugins --- \n";
|
||||
GetRemoteFile("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1);
|
||||
print "\nFetched latest plugins...\n";
|
||||
UnZip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/');
|
||||
}
|
||||
|
||||
$fc = 0;
|
||||
use File::Find;
|
||||
use File::Compare;
|
||||
|
||||
my @files;
|
||||
my $start_dir = "updates_staged/Quests-Plugins-master/plugins/";
|
||||
find(
|
||||
sub { push @files, $File::Find::name unless -d; },
|
||||
$start_dir
|
||||
);
|
||||
for my $file (@files) {
|
||||
if($file=~/\.pl|\.lua|\.ext/i){
|
||||
$staged_file = $file;
|
||||
$dest_file = $file;
|
||||
$dest_file =~s/updates_staged\/Quests-Plugins-master\///g;
|
||||
|
||||
if (!-e $dest_file) {
|
||||
CopyFile($staged_file, $dest_file);
|
||||
print "Installing :: '" . $dest_file . "'\n";
|
||||
$fc++;
|
||||
}
|
||||
else{
|
||||
$diff = Diff($dest_file, $staged_file);
|
||||
if($diff ne ""){
|
||||
$backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file;
|
||||
print $diff . "\n";
|
||||
print "\nFile Different :: '" . $dest_file . "'\n";
|
||||
print "\nDo you wish to update this Plugin? '" . $dest_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n";
|
||||
my $input = <STDIN>;
|
||||
if($input=~/N/i){}
|
||||
else{
|
||||
#::: Make a backup
|
||||
CopyFile($dest_file, $backup_dest);
|
||||
#::: Copy staged to running
|
||||
copy($staged_file, $dest_file);
|
||||
print "Installing :: '" . $dest_file . "'\n\n";
|
||||
}
|
||||
$fc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($fc == 0){
|
||||
print "\nNo Plugin Updates found... \n\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub Diff{
|
||||
$file_1 = $_[0];
|
||||
$file_2 = $_[1];
|
||||
if($OS eq "Windows"){
|
||||
eval "use Text::Diff";
|
||||
$diff = diff($file_1, $file_2, { STYLE => "Unified" });
|
||||
return $diff;
|
||||
}
|
||||
if($OS eq "Linux"){
|
||||
# print 'diff -u "$file_1" "$file_2"' . "\n";
|
||||
return `diff -u "$file_1" "$file_2"`;
|
||||
}
|
||||
}
|
||||
|
||||
sub UnZip{
|
||||
$archive_to_unzip = $_[0];
|
||||
$dest_folder = $_[1];
|
||||
|
||||
if($OS eq "Windows"){
|
||||
eval "use Archive::Zip qw( :ERROR_CODES :CONSTANTS )";
|
||||
my $zip = Archive::Zip->new();
|
||||
unless ( $zip->read($archive_to_unzip) == AZ_OK ) {
|
||||
die 'read error';
|
||||
}
|
||||
print "Extracting...\n";
|
||||
$zip->extractTree('', $dest_folder);
|
||||
}
|
||||
if($OS eq "Linux"){
|
||||
print `unzip -o "$archive_to_unzip" -d "$dest_folder"`;
|
||||
}
|
||||
}
|
||||
|
||||
sub AreFileSizesDifferent{
|
||||
$file_1 = $_[0];
|
||||
$file_2 = $_[1];
|
||||
my $file_1 = (stat $file_1)[7];
|
||||
my $file_2 = (stat $file_2)[7];
|
||||
# print $file_1 . " :: " . $file_2 . "\n";
|
||||
if($file_1 != $file_2){
|
||||
return 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#::: Responsible for Database Upgrade Routines
|
||||
sub Run_Database_Check{
|
||||
|
||||
if(!$db){
|
||||
print "No database present, check your eqemu_config.xml for proper MySQL/MariaDB configuration...\n";
|
||||
return;
|
||||
}
|
||||
|
||||
#::: Run 2 - Running pending updates...
|
||||
if(defined(@total_updates)){
|
||||
@total_updates = sort @total_updates;
|
||||
|
||||
@@ -330,9 +330,16 @@
|
||||
9074|2015_02_01_logsys_packet_logs.sql|SELECT * FROM `logsys_categories` WHERE `log_category_description` LIKE 'Packet: Server -> Client'|empty|
|
||||
9075|2015_02_02_logsys_packet_logs_with_dump.sql|SELECT * FROM `logsys_categories` WHERE `log_category_description` LIKE 'Packet: Server -> Client With Dump'|empty|
|
||||
9076|2015_02_04_average_coin.sql|SHOW COLUMNS FROM `loottable` WHERE Field = 'avgcoin'|contains|smallint
|
||||
9077|2015_02_12_zone_gravity.sql|SHOW COLUMNS FROM `zone` LIKE 'gravity'|empty|
|
||||
9078|2015_05_20_BuffInstrumentMod.sql|SHOW COLUMNS FROM `character_buffs` LIKE 'instrument_mod'|empty|
|
||||
9079|2015_05_23_BuffDurations.sql|SHOW COLUMNS FROM `character_buffs` LIKE 'ticsremaining'|contains|unsigned|
|
||||
9080|2015_05_23_PetBuffInstrumentMod.sql|SHOW COLUMNS FROM `character_pet_buffs` LIKE 'instrument_mod'|empty|
|
||||
9081|2015_05_23_dbstr_us.sql|SHOW TABLES LIKE 'db_str'|empty|
|
||||
9082|2015_05_25_npc_types_texture_fields.sql|SHOW COLUMNS FROM `npc_types` LIKE 'armtexture'|empty|
|
||||
9083|2015_06_07_aa_update.sql|SHOW COLUMNS FROM `character_alternate_abilities` LIKE 'charges'|empty|
|
||||
|
||||
# Upgrade conditions:
|
||||
# This won't be needed after this system is implemented, but it is used database that are not
|
||||
# This won't be needed after this system is implemented, but it is used database that are not
|
||||
# yet using the versioning system to figure out where the database is schema wise to determine
|
||||
# which updates are necessary to run
|
||||
#
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Inventory:EnforceAugmentRestriction', 'false', 'Forces augment slot restrictions.');
|
||||
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Inventory:EnforceAugmentUsability', 'false', 'Forces augmented item usability.');
|
||||
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Inventory:EnforceAugmentWear', 'false', 'Forces augment wear slot validation.');
|
||||
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Inventory:EnforceAugmentWear', 'false', 'Forces augment wear slot validation.');
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Combat:MeleePush', 'true', 'Turns on Melee Push.');
|
||||
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Combat:MeleePushChance', '50', 'Chance that an NPC can be pushed from melee.');
|
||||
@@ -0,0 +1 @@
|
||||
UPDATE rule_values SET rule_value=100 WHERE rule_name='Watermap:FishingLineLength';
|
||||
@@ -0,0 +1 @@
|
||||
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Spells:AlwaysSendTargetBuffs', 'false', 'Allows the server to send the targets buffs ignoring the LAA.');
|
||||
@@ -0,0 +1 @@
|
||||
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Inventory:TransformSummonedBags', 'true', 'Transforms summoned bags into disenchanted ones instead of deleting.');
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE `zone`
|
||||
ADD COLUMN `gravity` float NOT NULL DEFAULT .4 AFTER `snow_duration4`;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE `character_buffs` ADD COLUMN `instrument_mod` int(10) DEFAULT 10 NOT NULL;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE `character_buffs` CHANGE COLUMN `ticsremaining` `ticsremaining` INT(11) SIGNED NOT NULL;
|
||||
ALTER TABLE `merc_buffs` CHANGE COLUMN `TicsRemaining` `TicsRemaining` INT(11) SIGNED NOT NULL DEFAULT 0;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE `character_pet_buffs` ADD COLUMN `instrument_mod` tinyint UNSIGNED DEFAULT 10 NOT NULL;
|
||||
@@ -0,0 +1,6 @@
|
||||
CREATE TABLE `db_str` (
|
||||
`id` INT(10) NOT NULL,
|
||||
`type` INT(10) NOT NULL,
|
||||
`value` TEXT NOT NULL,
|
||||
PRIMARY KEY (`id`, `type`)
|
||||
);
|
||||
@@ -0,0 +1,6 @@
|
||||
ALTER TABLE npc_types
|
||||
ADD COLUMN `armtexture` tinyint(2) NOT NULL DEFAULT '0' AFTER `raid_target`,
|
||||
ADD COLUMN `bracertexture` tinyint(2) NOT NULL DEFAULT '0' AFTER `armtexture`,
|
||||
ADD COLUMN `handtexture` tinyint(2) NOT NULL DEFAULT '0' AFTER `bracertexture`,
|
||||
ADD COLUMN `legtexture` tinyint(2) NOT NULL DEFAULT '0' AFTER `handtexture`,
|
||||
ADD COLUMN `feettexture` tinyint(2) NOT NULL DEFAULT '0' AFTER `legtexture`;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE character_alternate_abilities ADD COLUMN charges SMALLINT(11) UNSIGNED NOT NULL DEFAULT 0;
|
||||
+180
-88
@@ -16,6 +16,8 @@
|
||||
#include "../common/string_util.h"
|
||||
#include "../common/clientversions.h"
|
||||
#include "../common/random.h"
|
||||
#include "../common/shareddb.h"
|
||||
#include "../common/file_verify_manager.h"
|
||||
|
||||
#include "client.h"
|
||||
#include "worlddb.h"
|
||||
@@ -86,11 +88,11 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
charid = 0;
|
||||
pwaitingforbootup = 0;
|
||||
StartInTutorial = false;
|
||||
ClientVersionBit = 0;
|
||||
numclients++;
|
||||
|
||||
if (eqs->GetClientVersion() != ClientVersion::Unknown)
|
||||
ClientVersionBit = 1 << (static_cast<unsigned int>(eqs->GetClientVersion()) - 1);
|
||||
m_ClientVersion = eqs->GetClientVersion();
|
||||
m_ClientVersionBit = ClientBitFromVersion(m_ClientVersion);
|
||||
|
||||
numclients++;
|
||||
}
|
||||
|
||||
Client::~Client() {
|
||||
@@ -161,32 +163,34 @@ void Client::SendCharInfo() {
|
||||
cle->SetOnline(CLE_Status_CharSelect);
|
||||
}
|
||||
|
||||
if (ClientVersionBit & BIT_RoFAndLater)
|
||||
{
|
||||
// Can make max char per account into a rule - New to VoA
|
||||
SendMaxCharCreate(10);
|
||||
if (m_ClientVersionBit & BIT_RoFAndLater) {
|
||||
SendMaxCharCreate();
|
||||
SendMembership();
|
||||
SendMembershipSettings();
|
||||
}
|
||||
|
||||
seencharsel = true;
|
||||
|
||||
|
||||
// Send OP_SendCharInfo
|
||||
auto outapp = new EQApplicationPacket(OP_SendCharInfo, sizeof(CharacterSelect_Struct));
|
||||
CharacterSelect_Struct* cs = (CharacterSelect_Struct*)outapp->pBuffer;
|
||||
EQApplicationPacket *outapp = nullptr;
|
||||
database.GetCharSelectInfo(GetAccountID(), &outapp, m_ClientVersionBit);
|
||||
|
||||
database.GetCharSelectInfo(GetAccountID(), cs, ClientVersionBit);
|
||||
|
||||
QueuePacket(outapp);
|
||||
if (outapp) {
|
||||
QueuePacket(outapp);
|
||||
}
|
||||
else {
|
||||
Log.Out(Logs::General, Logs::World_Server, "[Error] Database did not return an OP_SendCharInfo packet for account %u", GetAccountID());
|
||||
}
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
void Client::SendMaxCharCreate(int max_chars) {
|
||||
void Client::SendMaxCharCreate() {
|
||||
auto outapp = new EQApplicationPacket(OP_SendMaxCharacters, sizeof(MaxCharacters_Struct));
|
||||
MaxCharacters_Struct* mc = (MaxCharacters_Struct*)outapp->pBuffer;
|
||||
|
||||
mc->max_chars = max_chars;
|
||||
mc->max_chars = EQLimits::CharacterCreationLimit(m_ClientVersion);
|
||||
if (mc->max_chars > EmuConstants::CHARACTER_CREATION_LIMIT)
|
||||
mc->max_chars = EmuConstants::CHARACTER_CREATION_LIMIT;
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
@@ -602,6 +606,10 @@ bool Client::HandleGenerateRandomNamePacket(const EQApplicationPacket *app) {
|
||||
}
|
||||
|
||||
bool Client::HandleCharacterCreateRequestPacket(const EQApplicationPacket *app) {
|
||||
if(!CanTakeAction()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// New OpCode in SoF
|
||||
uint32 allocs = character_create_allocations.size();
|
||||
uint32 combos = character_create_race_class_combos.size();
|
||||
@@ -649,6 +657,10 @@ bool Client::HandleCharacterCreateRequestPacket(const EQApplicationPacket *app)
|
||||
}
|
||||
|
||||
bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) {
|
||||
if(!CanTakeAction()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GetAccountID() == 0) {
|
||||
Log.Out(Logs::Detail, Logs::World_Server,"Account ID not set; unable to create character.");
|
||||
return false;
|
||||
@@ -671,7 +683,7 @@ bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ClientVersionBit & BIT_TitaniumAndEarlier)
|
||||
if (m_ClientVersionBit & BIT_TitaniumAndEarlier)
|
||||
StartInTutorial = true;
|
||||
SendCharInfo();
|
||||
}
|
||||
@@ -680,6 +692,11 @@ bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) {
|
||||
}
|
||||
|
||||
bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
if(!CanTakeAction()) {
|
||||
ZoneUnavail();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GetAccountID() == 0) {
|
||||
Log.Out(Logs::Detail, Logs::World_Server,"Enter world with no logged in account");
|
||||
eqs->Close();
|
||||
@@ -716,66 +733,72 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!pZoning && ew->return_home && !ew->tutorial) {
|
||||
auto cs = new CharacterSelect_Struct;
|
||||
memset(cs, 0, sizeof(CharacterSelect_Struct));
|
||||
database.GetCharSelectInfo(GetAccountID(), cs, ClientVersionBit);
|
||||
bool home_enabled = false;
|
||||
// This can probably be moved outside and have another method return requested info (don't forget to remove the #include "../common/shareddb.h" above)
|
||||
// (This is a literal translation of the original process..I don't see why it can't be changed to a single-target query over account iteration)
|
||||
if (!pZoning) {
|
||||
size_t character_limit = EQLimits::CharacterCreationLimit(eqs->GetClientVersion());
|
||||
if (character_limit > EmuConstants::CHARACTER_CREATION_LIMIT) { character_limit = EmuConstants::CHARACTER_CREATION_LIMIT; }
|
||||
if (eqs->GetClientVersion() == ClientVersion::Titanium) { character_limit = 8; }
|
||||
|
||||
for(int x = 0; x < 10; ++x)
|
||||
{
|
||||
if(strcasecmp(cs->name[x], char_name) == 0)
|
||||
{
|
||||
if(cs->gohome[x] == 1)
|
||||
{
|
||||
home_enabled = true;
|
||||
break;
|
||||
std::string tgh_query = StringFormat(
|
||||
"SELECT "
|
||||
"`id`, "
|
||||
"name, "
|
||||
"`level`, "
|
||||
"last_login "
|
||||
"FROM "
|
||||
"character_data "
|
||||
"WHERE `account_id` = %i ORDER BY `name` LIMIT %u", GetAccountID(), character_limit);
|
||||
auto tgh_results = database.QueryDatabase(tgh_query);
|
||||
|
||||
/* Check GoHome */
|
||||
if (ew->return_home && !ew->tutorial) {
|
||||
bool home_enabled = false;
|
||||
for (auto row = tgh_results.begin(); row != tgh_results.end(); ++row) {
|
||||
if (strcasecmp(row[1], char_name) == 0) {
|
||||
if (RuleB(World, EnableReturnHomeButton)) {
|
||||
int now = time(nullptr);
|
||||
if ((now - atoi(row[3])) >= RuleI(World, MinOfflineTimeToReturnHome)) {
|
||||
home_enabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
safe_delete(cs);
|
||||
|
||||
if(home_enabled) {
|
||||
zoneID = database.MoveCharacterToBind(charid,4);
|
||||
}
|
||||
else {
|
||||
Log.Out(Logs::Detail, Logs::World_Server,"'%s' is trying to go home before they're able...",char_name);
|
||||
database.SetHackerFlag(GetAccountName(), char_name, "MQGoHome: player tried to go home before they were able.");
|
||||
eqs->Close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!pZoning && (RuleB(World, EnableTutorialButton) && (ew->tutorial || StartInTutorial))) {
|
||||
auto cs = new CharacterSelect_Struct;
|
||||
memset(cs, 0, sizeof(CharacterSelect_Struct));
|
||||
database.GetCharSelectInfo(GetAccountID(), cs, ClientVersionBit);
|
||||
bool tutorial_enabled = false;
|
||||
|
||||
for(int x = 0; x < 10; ++x)
|
||||
{
|
||||
if(strcasecmp(cs->name[x], char_name) == 0)
|
||||
{
|
||||
if(cs->tutorial[x] == 1)
|
||||
{
|
||||
tutorial_enabled = true;
|
||||
break;
|
||||
}
|
||||
if (home_enabled) {
|
||||
zoneID = database.MoveCharacterToBind(charid, 4);
|
||||
}
|
||||
else {
|
||||
Log.Out(Logs::Detail, Logs::World_Server, "'%s' is trying to go home before they're able...", char_name);
|
||||
database.SetHackerFlag(GetAccountName(), char_name, "MQGoHome: player tried to go home before they were able.");
|
||||
eqs->Close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
safe_delete(cs);
|
||||
|
||||
if(tutorial_enabled)
|
||||
{
|
||||
zoneID = RuleI(World, TutorialZoneID);
|
||||
database.MoveCharacterToZone(charid, database.GetZoneName(zoneID));
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Out(Logs::Detail, Logs::World_Server,"'%s' is trying to go to tutorial but are not allowed...",char_name);
|
||||
database.SetHackerFlag(GetAccountName(), char_name, "MQTutorial: player tried to enter the tutorial without having tutorial enabled for this character.");
|
||||
eqs->Close();
|
||||
return true;
|
||||
/* Check Tutorial*/
|
||||
if (RuleB(World, EnableTutorialButton) && (ew->tutorial || StartInTutorial)) {
|
||||
bool tutorial_enabled = false;
|
||||
for (auto row = tgh_results.begin(); row != tgh_results.end(); ++row) {
|
||||
if (strcasecmp(row[1], char_name) == 0) {
|
||||
if (RuleB(World, EnableTutorialButton) && ((uint8)atoi(row[2]) <= RuleI(World, MaxLevelForTutorial))) {
|
||||
tutorial_enabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tutorial_enabled) {
|
||||
zoneID = RuleI(World, TutorialZoneID);
|
||||
database.MoveCharacterToZone(charid, database.GetZoneName(zoneID));
|
||||
}
|
||||
else {
|
||||
Log.Out(Logs::Detail, Logs::World_Server, "'%s' is trying to go to tutorial but are not allowed...", char_name);
|
||||
database.SetHackerFlag(GetAccountName(), char_name, "MQTutorial: player tried to enter the tutorial without having tutorial enabled for this character.");
|
||||
eqs->Close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -846,9 +869,9 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
|
||||
char ConnectionType;
|
||||
|
||||
if(ClientVersionBit & BIT_UFAndLater)
|
||||
if (m_ClientVersionBit & BIT_UFAndLater)
|
||||
ConnectionType = 'U';
|
||||
else if(ClientVersionBit & BIT_SoFAndLater)
|
||||
else if (m_ClientVersionBit & BIT_SoFAndLater)
|
||||
ConnectionType = 'S';
|
||||
else
|
||||
ConnectionType = 'C';
|
||||
@@ -872,7 +895,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
|
||||
outapp2 = new EQApplicationPacket(OP_SetChatServer2);
|
||||
|
||||
if(ClientVersionBit & BIT_TitaniumAndEarlier)
|
||||
if (m_ClientVersionBit & BIT_TitaniumAndEarlier)
|
||||
ConnectionType = 'M';
|
||||
|
||||
sprintf(buffer,"%s,%i,%s.%s,%c%08X",
|
||||
@@ -893,6 +916,9 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
}
|
||||
|
||||
bool Client::HandleDeleteCharacterPacket(const EQApplicationPacket *app) {
|
||||
if(!CanTakeAction()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 char_acct_id = database.GetAccountIDByChar((char*)app->pBuffer);
|
||||
if(char_acct_id == GetAccountID()) {
|
||||
@@ -906,7 +932,7 @@ bool Client::HandleDeleteCharacterPacket(const EQApplicationPacket *app) {
|
||||
|
||||
bool Client::HandleZoneChangePacket(const EQApplicationPacket *app) {
|
||||
// HoT sends this to world while zoning and wants it echoed back.
|
||||
if(ClientVersionBit & BIT_RoFAndLater)
|
||||
if (m_ClientVersionBit & BIT_RoFAndLater)
|
||||
{
|
||||
QueuePacket(app);
|
||||
}
|
||||
@@ -943,16 +969,68 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
||||
|
||||
switch(opcode)
|
||||
{
|
||||
case OP_World_Client_CRC1:
|
||||
case OP_World_Client_CRC2:
|
||||
case OP_World_SpellFileCheck:
|
||||
{
|
||||
// There is no obvious entry in the CC struct to indicate that the 'Start Tutorial button
|
||||
// is selected when a character is created. I have observed that in this case, OP_EnterWorld is sent
|
||||
// before OP_World_Client_CRC1. Therefore, if we receive OP_World_Client_CRC1 before OP_EnterWorld,
|
||||
// then 'Start Tutorial' was not chosen.
|
||||
if(EQEmu::FileVerifyManager::Get().VerifySpellFile(app, eqs->GetClientVersion())) {
|
||||
if(cle) {
|
||||
cle->SetSpellFileVerified(true);
|
||||
}
|
||||
} else {
|
||||
if(cle) {
|
||||
cle->SetSpellFileVerified(false);
|
||||
}
|
||||
}
|
||||
StartInTutorial = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
case OP_World_SkillFileCheck:
|
||||
{
|
||||
if(EQEmu::FileVerifyManager::Get().VerifySkillFile(app, eqs->GetClientVersion())) {
|
||||
if(cle) {
|
||||
cle->SetSkillFileVerified(true);
|
||||
}
|
||||
} else {
|
||||
if(cle) {
|
||||
cle->SetSkillFileVerified(false);
|
||||
}
|
||||
}
|
||||
StartInTutorial = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
case OP_World_BaseDataFileCheck:
|
||||
{
|
||||
if(EQEmu::FileVerifyManager::Get().VerifyBaseDataFile(app, eqs->GetClientVersion())) {
|
||||
if(cle) {
|
||||
cle->SetBaseDataFileVerified(true);
|
||||
}
|
||||
} else {
|
||||
if(cle) {
|
||||
cle->SetBaseDataFileVerified(false);
|
||||
}
|
||||
}
|
||||
|
||||
StartInTutorial = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
case OP_World_ExeFileCheck:
|
||||
{
|
||||
if(EQEmu::FileVerifyManager::Get().VerifyEQGame(app, eqs->GetClientVersion())) {
|
||||
if(cle) {
|
||||
cle->SetEQGameVerified(true);
|
||||
}
|
||||
} else {
|
||||
if(cle) {
|
||||
cle->SetEQGameVerified(false);
|
||||
}
|
||||
}
|
||||
|
||||
StartInTutorial = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
case OP_SendLoginInfo:
|
||||
{
|
||||
return HandleSendLoginInfoPacket(app);
|
||||
@@ -992,21 +1070,21 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
||||
// HoT sends this to world while zoning and wants it echoed back.
|
||||
return HandleZoneChangePacket(app);
|
||||
}
|
||||
case OP_LoginUnknown1:
|
||||
case OP_LoginUnknown2:
|
||||
case OP_CrashDump:
|
||||
case OP_WearChange:
|
||||
case OP_LoginComplete:
|
||||
case OP_ApproveWorld:
|
||||
case OP_WorldClientReady:
|
||||
{
|
||||
// Essentially we are just 'eating' these packets, indicating
|
||||
// they are handled.
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Log.Out(Logs::Detail, Logs::World_Server,"Received unknown EQApplicationPacket");
|
||||
|
||||
char buffer[64];
|
||||
app->build_header_dump(buffer);
|
||||
Log.Out(Logs::General, Logs::Status, "%s %s", buffer, DumpPacketToString(app).c_str());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1370,7 +1448,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
|
||||
Log.Out(Logs::Detail, Logs::World_Server, "Beard: %d Beardcolor: %d", cc->beard, cc->beardcolor);
|
||||
|
||||
/* Validate the char creation struct */
|
||||
if (ClientVersionBit & BIT_SoFAndLater) {
|
||||
if (m_ClientVersionBit & BIT_SoFAndLater) {
|
||||
if (!CheckCharCreateInfoSoF(cc)) {
|
||||
Log.Out(Logs::Detail, Logs::World_Server,"CheckCharCreateInfo did not validate the request (bad race/class/stats)");
|
||||
return false;
|
||||
@@ -1421,7 +1499,10 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
|
||||
SetRaceStartingSkills(&pp);
|
||||
SetClassStartingSkills(&pp);
|
||||
SetClassLanguages(&pp);
|
||||
pp.skills[SkillSenseHeading] = 200;
|
||||
|
||||
pp.skills[SkillSwimming] = RuleI(Skills, SwimmingStartValue);
|
||||
pp.skills[SkillSenseHeading] = RuleI(Skills, SenseHeadingStartValue);
|
||||
|
||||
// strcpy(pp.servername, WorldConfig::get()->ShortName.c_str());
|
||||
|
||||
|
||||
@@ -1438,7 +1519,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
|
||||
pp.pvp = database.GetServerType() == 1 ? 1 : 0;
|
||||
|
||||
/* If it is an SoF Client and the SoF Start Zone rule is set, send new chars there */
|
||||
if (ClientVersionBit & BIT_SoFAndLater) {
|
||||
if (m_ClientVersionBit & BIT_SoFAndLater) {
|
||||
Log.Out(Logs::Detail, Logs::World_Server,"Found 'SoFStartZoneID' rule setting: %i", RuleI(World, SoFStartZoneID));
|
||||
if (RuleI(World, SoFStartZoneID) > 0) {
|
||||
pp.zone_id = RuleI(World, SoFStartZoneID);
|
||||
@@ -1454,7 +1535,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
|
||||
}
|
||||
}
|
||||
/* use normal starting zone logic to either get defaults, or if startzone was set, load that from the db table.*/
|
||||
bool ValidStartZone = database.GetStartZone(&pp, cc, ClientVersionBit & BIT_TitaniumAndEarlier);
|
||||
bool ValidStartZone = database.GetStartZone(&pp, cc, m_ClientVersionBit & BIT_TitaniumAndEarlier);
|
||||
|
||||
if (!ValidStartZone){
|
||||
return false;
|
||||
@@ -1976,3 +2057,14 @@ void Client::SetClassLanguages(PlayerProfile_Struct *pp)
|
||||
}
|
||||
}
|
||||
|
||||
bool Client::CanTakeAction() {
|
||||
if(RuleB(World, AllowActionWithBadFiles)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!cle) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return cle->GetBaseDataFileVerified() && cle->GetEQGameVerified() && cle->GetSkillFileVerified() && cle->GetSpellFileVerified();
|
||||
}
|
||||
|
||||
+5
-2
@@ -41,7 +41,7 @@ public:
|
||||
bool Process();
|
||||
void ReceiveData(uchar* buf, int len);
|
||||
void SendCharInfo();
|
||||
void SendMaxCharCreate(int max_chars);
|
||||
void SendMaxCharCreate();
|
||||
void SendMembership();
|
||||
void SendMembershipSettings();
|
||||
void EnterWorld(bool TryBootup = true);
|
||||
@@ -84,7 +84,8 @@ private:
|
||||
uint32 pwaitingforbootup;
|
||||
|
||||
bool StartInTutorial;
|
||||
uint32 ClientVersionBit;
|
||||
ClientVersion m_ClientVersion;
|
||||
uint32 m_ClientVersionBit;
|
||||
bool OPCharCreate(char *name, CharCreate_Struct *cc);
|
||||
|
||||
void SetClassStartingSkills( PlayerProfile_Struct *pp );
|
||||
@@ -99,6 +100,8 @@ private:
|
||||
bool seencharsel;
|
||||
bool realfirstlogin;
|
||||
|
||||
bool CanTakeAction();
|
||||
|
||||
bool HandlePacket(const EQApplicationPacket *app);
|
||||
bool HandleNameApprovalPacket(const EQApplicationPacket *app);
|
||||
bool HandleSendLoginInfoPacket(const EQApplicationPacket *app);
|
||||
|
||||
@@ -46,6 +46,11 @@ ClientListEntry::ClientListEntry(uint32 in_id, uint32 iLSID, const char* iLoginN
|
||||
plocal=(local==1);
|
||||
|
||||
pinstance = 0;
|
||||
|
||||
spell_file_verified = true;
|
||||
skill_file_verified = true;
|
||||
base_data_file_verified = true;
|
||||
eqgame_file_verified = true;
|
||||
}
|
||||
|
||||
ClientListEntry::ClientListEntry(uint32 in_id, uint32 iAccID, const char* iAccName, MD5& iMD5Pass, int16 iAdmin)
|
||||
@@ -63,6 +68,11 @@ ClientListEntry::ClientListEntry(uint32 in_id, uint32 iAccID, const char* iAccNa
|
||||
padmin = iAdmin;
|
||||
|
||||
pinstance = 0;
|
||||
|
||||
spell_file_verified = true;
|
||||
skill_file_verified = true;
|
||||
base_data_file_verified = true;
|
||||
eqgame_file_verified = true;
|
||||
}
|
||||
|
||||
ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList_Struct* scl, int8 iOnline)
|
||||
@@ -86,6 +96,11 @@ ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList
|
||||
Update(iZS, scl, iOnline);
|
||||
else
|
||||
SetOnline(iOnline);
|
||||
|
||||
spell_file_verified = true;
|
||||
skill_file_verified = true;
|
||||
base_data_file_verified = true;
|
||||
eqgame_file_verified = true;
|
||||
}
|
||||
|
||||
ClientListEntry::~ClientListEntry() {
|
||||
|
||||
@@ -87,6 +87,16 @@ public:
|
||||
inline void PushToTellQueue(ServerChannelMessage_Struct *scm) { tell_queue.push_back(scm); }
|
||||
void ProcessTellQueue();
|
||||
|
||||
bool GetSpellFileVerified() { return spell_file_verified; }
|
||||
bool GetSkillFileVerified() { return skill_file_verified; }
|
||||
bool GetBaseDataFileVerified() { return base_data_file_verified; }
|
||||
bool GetEQGameVerified() { return eqgame_file_verified; }
|
||||
|
||||
void SetSpellFileVerified(bool v) { spell_file_verified = v; }
|
||||
void SetSkillFileVerified(bool v) { skill_file_verified = v; }
|
||||
void SetBaseDataFileVerified(bool v) { base_data_file_verified = v; }
|
||||
void SetEQGameVerified(bool v) { eqgame_file_verified = v; }
|
||||
|
||||
private:
|
||||
void ClearVars(bool iAll = false);
|
||||
|
||||
@@ -128,6 +138,11 @@ private:
|
||||
bool pLFGMatchFilter;
|
||||
char pLFGComments[64];
|
||||
|
||||
bool spell_file_verified;
|
||||
bool skill_file_verified;
|
||||
bool base_data_file_verified;
|
||||
bool eqgame_file_verified;
|
||||
|
||||
// Tell Queue -- really a vector :D
|
||||
std::vector<ServerChannelMessage_Struct *> tell_queue;
|
||||
};
|
||||
|
||||
+147
-105
@@ -33,20 +33,20 @@ extern std::vector<RaceClassCombos> character_create_race_class_combos;
|
||||
|
||||
|
||||
// the current stuff is at the bottom of this function
|
||||
void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct* cs, uint32 ClientVersion) {
|
||||
Inventory *inv;
|
||||
uint8 has_home = 0;
|
||||
uint8 has_bind = 0;
|
||||
|
||||
/* Initialize Variables */
|
||||
for (int i=0; i<10; i++) {
|
||||
strcpy(cs->name[i], "<none>");
|
||||
cs->zone[i] = 0;
|
||||
cs->level[i] = 0;
|
||||
cs->tutorial[i] = 0;
|
||||
cs->gohome[i] = 0;
|
||||
}
|
||||
void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **outApp, uint32 clientVersionBit)
|
||||
{
|
||||
/* Set Character Creation Limit */
|
||||
ClientVersion client_version = ClientVersionFromBit(clientVersionBit);
|
||||
size_t character_limit = EQLimits::CharacterCreationLimit(client_version);
|
||||
|
||||
// Validate against absolute server max
|
||||
if (character_limit > EmuConstants::CHARACTER_CREATION_LIMIT)
|
||||
character_limit = EmuConstants::CHARACTER_CREATION_LIMIT;
|
||||
|
||||
// Force Titanium clients to use '8'
|
||||
if (client_version == ClientVersion::Titanium)
|
||||
character_limit = 8;
|
||||
|
||||
/* Get Character Info */
|
||||
std::string cquery = StringFormat(
|
||||
"SELECT "
|
||||
@@ -72,52 +72,103 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct*
|
||||
"zone_id " // 19
|
||||
"FROM "
|
||||
"character_data "
|
||||
"WHERE `account_id` = %i ORDER BY `name` LIMIT 10 ", account_id);
|
||||
auto results = database.QueryDatabase(cquery); int char_num = 0;
|
||||
"WHERE `account_id` = %i ORDER BY `name` LIMIT %u", accountID, character_limit);
|
||||
auto results = database.QueryDatabase(cquery);
|
||||
|
||||
size_t character_count = results.RowCount();
|
||||
if (character_count == 0) {
|
||||
*outApp = new EQApplicationPacket(OP_SendCharInfo, sizeof(CharacterSelect_Struct));
|
||||
CharacterSelect_Struct *cs = (CharacterSelect_Struct *)(*outApp)->pBuffer;
|
||||
cs->CharCount = 0;
|
||||
cs->TotalChars = character_limit;
|
||||
return;
|
||||
}
|
||||
|
||||
size_t packet_size = sizeof(CharacterSelect_Struct) + (sizeof(CharacterSelectEntry_Struct) * character_count);
|
||||
*outApp = new EQApplicationPacket(OP_SendCharInfo, packet_size);
|
||||
|
||||
unsigned char *buff_ptr = (*outApp)->pBuffer;
|
||||
CharacterSelect_Struct *cs = (CharacterSelect_Struct *)buff_ptr;
|
||||
|
||||
cs->CharCount = character_count;
|
||||
cs->TotalChars = character_limit;
|
||||
|
||||
buff_ptr += sizeof(CharacterSelect_Struct);
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
CharacterSelectEntry_Struct *cse = (CharacterSelectEntry_Struct *)buff_ptr;
|
||||
PlayerProfile_Struct pp;
|
||||
Inventory inv;
|
||||
uint32 character_id = (uint32)atoi(row[0]);
|
||||
uint8 has_home = 0;
|
||||
uint8 has_bind = 0;
|
||||
|
||||
memset(&pp, 0, sizeof(PlayerProfile_Struct));
|
||||
|
||||
/* Fill CharacterSelectEntry_Struct */
|
||||
memset(cse->Name, 0, sizeof(cse->Name));
|
||||
strcpy(cse->Name, row[1]);
|
||||
cse->Class = (uint8)atoi(row[4]);
|
||||
cse->Race = (uint32)atoi(row[3]);
|
||||
cse->Level = (uint8)atoi(row[5]);
|
||||
cse->ShroudClass = cse->Class;
|
||||
cse->ShroudRace = cse->Race;
|
||||
cse->Zone = (uint16)atoi(row[19]);
|
||||
cse->Instance = 0;
|
||||
cse->Gender = (uint8)atoi(row[2]);
|
||||
cse->Face = (uint8)atoi(row[15]);
|
||||
|
||||
uint32 character_id = atoi(row[0]);
|
||||
strcpy(cs->name[char_num], row[1]);
|
||||
uint8 lvl = atoi(row[5]);
|
||||
cs->level[char_num] = lvl;
|
||||
cs->class_[char_num] = atoi(row[4]);
|
||||
cs->race[char_num] = atoi(row[3]);
|
||||
cs->gender[char_num] = atoi(row[2]);
|
||||
cs->deity[char_num] = atoi(row[6]);
|
||||
cs->zone[char_num] = atoi(row[19]);
|
||||
cs->face[char_num] = atoi(row[15]);
|
||||
cs->haircolor[char_num] = atoi(row[9]);
|
||||
cs->beardcolor[char_num] = atoi(row[10]);
|
||||
cs->eyecolor2[char_num] = atoi(row[12]);
|
||||
cs->eyecolor1[char_num] = atoi(row[11]);
|
||||
cs->hairstyle[char_num] = atoi(row[13]);
|
||||
cs->beard[char_num] = atoi(row[14]);
|
||||
cs->drakkin_heritage[char_num] = atoi(row[16]);
|
||||
cs->drakkin_tattoo[char_num] = atoi(row[17]);
|
||||
cs->drakkin_details[char_num] = atoi(row[18]);
|
||||
for (uint32 matslot = 0; matslot < _MaterialCount; matslot++) { // Processed below
|
||||
cse->Equip[matslot].Material = 0;
|
||||
cse->Equip[matslot].Unknown1 = 0;
|
||||
cse->Equip[matslot].EliteMaterial = 0;
|
||||
cse->Equip[matslot].HeroForgeModel = 0;
|
||||
cse->Equip[matslot].Material2 = 0;
|
||||
cse->Equip[matslot].Color.Color = 0;
|
||||
}
|
||||
|
||||
if (RuleB(World, EnableTutorialButton) && (lvl <= RuleI(World, MaxLevelForTutorial)))
|
||||
cs->tutorial[char_num] = 1;
|
||||
cse->Unknown15 = 0xFF;
|
||||
cse->Unknown19 = 0xFF;
|
||||
cse->DrakkinTattoo = (uint32)atoi(row[17]);
|
||||
cse->DrakkinDetails = (uint32)atoi(row[18]);
|
||||
cse->Deity = (uint32)atoi(row[6]);
|
||||
cse->PrimaryIDFile = 0; // Processed Below
|
||||
cse->SecondaryIDFile = 0; // Processed Below
|
||||
cse->HairColor = (uint8)atoi(row[9]);
|
||||
cse->BeardColor = (uint8)atoi(row[10]);
|
||||
cse->EyeColor1 = (uint8)atoi(row[11]);
|
||||
cse->EyeColor2 = (uint8)atoi(row[12]);
|
||||
cse->HairStyle = (uint8)atoi(row[13]);
|
||||
cse->Beard = (uint8)atoi(row[14]);
|
||||
cse->GoHome = 0; // Processed Below
|
||||
cse->Tutorial = 0; // Processed Below
|
||||
cse->DrakkinHeritage = (uint32)atoi(row[16]);
|
||||
cse->Unknown1 = 0;
|
||||
cse->Enabled = 1;
|
||||
cse->LastLogin = (uint32)atoi(row[7]); // RoF2 value: 1212696584
|
||||
cse->Unknown2 = 0;
|
||||
/* Fill End */
|
||||
|
||||
if (RuleB(World, EnableReturnHomeButton)) {
|
||||
int now = time(nullptr);
|
||||
if ((now - atoi(row[7])) >= RuleI(World, MinOfflineTimeToReturnHome))
|
||||
cs->gohome[char_num] = 1;
|
||||
cse->GoHome = 1;
|
||||
}
|
||||
|
||||
if (RuleB(World, EnableTutorialButton) && (cse->Level <= RuleI(World, MaxLevelForTutorial))) {
|
||||
cse->Tutorial = 1;
|
||||
}
|
||||
|
||||
/* Set Bind Point Data for any character that may possibly be missing it for any reason */
|
||||
cquery = StringFormat("SELECT `zone_id`, `instance_id`, `x`, `y`, `z`, `heading`, `is_home` FROM `character_bind` WHERE `id` = %i LIMIT 2", character_id);
|
||||
auto results_bind = database.QueryDatabase(cquery); has_home = 0; has_bind = 0;
|
||||
auto results_bind = database.QueryDatabase(cquery);
|
||||
for (auto row_b = results_bind.begin(); row_b != results_bind.end(); ++row_b) {
|
||||
if (row_b[6] && atoi(row_b[6]) == 1){ has_home = 1; }
|
||||
if (row_b[6] && atoi(row_b[6]) == 0){ has_bind = 1; }
|
||||
}
|
||||
|
||||
if (has_home == 0 || has_bind == 0){
|
||||
if (has_home == 0 || has_bind == 0) {
|
||||
cquery = StringFormat("SELECT `zone_id`, `bind_id`, `x`, `y`, `z` FROM `start_zones` WHERE `player_class` = %i AND `player_deity` = %i AND `player_race` = %i",
|
||||
cs->class_[char_num], cs->deity[char_num], cs->race[char_num]);
|
||||
cse->Class, cse->Deity, cse->Race);
|
||||
auto results_bind = database.QueryDatabase(cquery);
|
||||
for (auto row_d = results_bind.begin(); row_d != results_bind.end(); ++row_d) {
|
||||
/* If a bind_id is specified, make them start there */
|
||||
@@ -133,23 +184,22 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct*
|
||||
float z = atof(row_d[4]);
|
||||
if (x == 0 && y == 0 && z == 0){ GetSafePoints(pp.binds[4].zoneId, 0, &x, &y, &z); }
|
||||
pp.binds[4].x = x; pp.binds[4].y = y; pp.binds[4].z = z;
|
||||
|
||||
}
|
||||
}
|
||||
pp.binds[0] = pp.binds[4];
|
||||
/* If no home bind set, set it */
|
||||
if (has_home == 0){
|
||||
if (has_home == 0) {
|
||||
std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)"
|
||||
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i)",
|
||||
character_id, pp.binds[4].zoneId, 0, pp.binds[4].x, pp.binds[4].y, pp.binds[4].z, pp.binds[4].heading, 1);
|
||||
auto results_bset = QueryDatabase(query);
|
||||
auto results_bset = QueryDatabase(query);
|
||||
}
|
||||
/* If no regular bind set, set it */
|
||||
if (has_bind == 0){
|
||||
if (has_bind == 0) {
|
||||
std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)"
|
||||
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i)",
|
||||
character_id, pp.binds[0].zoneId, 0, pp.binds[0].x, pp.binds[0].y, pp.binds[0].z, pp.binds[0].heading, 0);
|
||||
auto results_bset = QueryDatabase(query);
|
||||
auto results_bset = QueryDatabase(query);
|
||||
}
|
||||
}
|
||||
/* Bind End */
|
||||
@@ -157,97 +207,78 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct*
|
||||
/* Load Character Material Data for Char Select */
|
||||
cquery = StringFormat("SELECT slot, red, green, blue, use_tint, color FROM `character_material` WHERE `id` = %u", character_id);
|
||||
auto results_b = database.QueryDatabase(cquery); uint8 slot = 0;
|
||||
for (auto row_b = results_b.begin(); row_b != results_b.end(); ++row_b)
|
||||
{
|
||||
for (auto row_b = results_b.begin(); row_b != results_b.end(); ++row_b) {
|
||||
slot = atoi(row_b[0]);
|
||||
pp.item_tint[slot].rgb.red = atoi(row_b[1]);
|
||||
pp.item_tint[slot].rgb.green = atoi(row_b[2]);
|
||||
pp.item_tint[slot].rgb.blue = atoi(row_b[3]);
|
||||
pp.item_tint[slot].rgb.use_tint = atoi(row_b[4]);
|
||||
pp.item_tint[slot].RGB.Red = atoi(row_b[1]);
|
||||
pp.item_tint[slot].RGB.Green = atoi(row_b[2]);
|
||||
pp.item_tint[slot].RGB.Blue = atoi(row_b[3]);
|
||||
pp.item_tint[slot].RGB.UseTint = atoi(row_b[4]);
|
||||
}
|
||||
/* Character Material Data End */
|
||||
|
||||
/* Load Inventory */
|
||||
inv = new Inventory;
|
||||
if (GetInventory(account_id, cs->name[char_num], inv))
|
||||
{
|
||||
// If we ensure that the material data is updated appropriately, we can do away with inventory loads
|
||||
if (GetInventory(accountID, cse->Name, &inv)) {
|
||||
const Item_Struct* item = nullptr;
|
||||
const ItemInst* inst = nullptr;
|
||||
int16 invslot = 0;
|
||||
|
||||
for (uint32 matslot = 0; matslot < _MaterialCount; matslot++)
|
||||
{
|
||||
for (uint32 matslot = 0; matslot < _MaterialCount; matslot++) {
|
||||
invslot = Inventory::CalcSlotFromMaterial(matslot);
|
||||
if (invslot == INVALID_INDEX) { continue; }
|
||||
|
||||
inst = inv->GetItem(invslot);
|
||||
inst = inv.GetItem(invslot);
|
||||
if (inst == nullptr) { continue; }
|
||||
|
||||
item = inst->GetItem();
|
||||
if (item == nullptr) { continue; }
|
||||
|
||||
if (matslot > 6)
|
||||
{
|
||||
if (matslot > 6) {
|
||||
uint32 idfile = 0;
|
||||
// Weapon Models
|
||||
if (inst->GetOrnamentationIDFile() != 0)
|
||||
{
|
||||
if (inst->GetOrnamentationIDFile() != 0) {
|
||||
idfile = inst->GetOrnamentationIDFile();
|
||||
cs->equip[char_num][matslot].material = idfile;
|
||||
cse->Equip[matslot].Material = idfile;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strlen(item->IDFile) > 2)
|
||||
{
|
||||
else {
|
||||
if (strlen(item->IDFile) > 2) {
|
||||
idfile = atoi(&item->IDFile[2]);
|
||||
cs->equip[char_num][matslot].material = idfile;
|
||||
cse->Equip[matslot].Material = idfile;
|
||||
}
|
||||
}
|
||||
if (matslot == MaterialPrimary)
|
||||
{
|
||||
cs->primary[char_num] = idfile;
|
||||
if (matslot == MaterialPrimary) {
|
||||
cse->PrimaryIDFile = idfile;
|
||||
}
|
||||
else
|
||||
{
|
||||
cs->secondary[char_num] = idfile;
|
||||
else {
|
||||
cse->SecondaryIDFile = idfile;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
uint32 color = 0;
|
||||
if (pp.item_tint[matslot].rgb.use_tint)
|
||||
{
|
||||
color = pp.item_tint[matslot].color;
|
||||
if (pp.item_tint[matslot].RGB.UseTint) {
|
||||
color = pp.item_tint[matslot].Color;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
color = inst->GetColor();
|
||||
}
|
||||
|
||||
// Armor Materials/Models
|
||||
cs->equip[char_num][matslot].material = item->Material;
|
||||
cs->equip[char_num][matslot].elitematerial = item->EliteMaterial;
|
||||
cs->equip[char_num][matslot].heroforgemodel = inst->GetOrnamentHeroModel(matslot);
|
||||
cs->equip[char_num][matslot].color.color = color;
|
||||
cse->Equip[matslot].Material = item->Material;
|
||||
cse->Equip[matslot].EliteMaterial = item->EliteMaterial;
|
||||
cse->Equip[matslot].HeroForgeModel = inst->GetOrnamentHeroModel(matslot);
|
||||
cse->Equip[matslot].Color.Color = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error loading inventory for %s\n", cs->name[char_num]);
|
||||
else {
|
||||
printf("Error loading inventory for %s\n", cse->Name);
|
||||
}
|
||||
/* Load Inventory End */
|
||||
|
||||
safe_delete(inv);
|
||||
|
||||
if (++char_num > 10)
|
||||
{
|
||||
break;
|
||||
}
|
||||
buff_ptr += sizeof(CharacterSelectEntry_Struct);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int WorldDatabase::MoveCharacterToBind(int CharID, uint8 bindnum) {
|
||||
int WorldDatabase::MoveCharacterToBind(int CharID, uint8 bindnum)
|
||||
{
|
||||
/* if an invalid bind point is specified, use the primary bind */
|
||||
if (bindnum > 4)
|
||||
{
|
||||
@@ -330,6 +361,7 @@ bool WorldDatabase::GetStartZone(PlayerProfile_Struct* in_pp, CharCreate_Struct*
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WorldDatabase::SetSoFDefaultStartZone(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_cc){
|
||||
if (in_cc->start_zone == RuleI(World, TutorialZoneID)) {
|
||||
in_pp->zone_id = in_cc->start_zone;
|
||||
@@ -348,8 +380,16 @@ void WorldDatabase::SetTitaniumDefaultStartZone(PlayerProfile_Struct* in_pp, Cha
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
in_pp->zone_id = 24; // erudnext
|
||||
in_pp->binds[0].zoneId = 38; // tox
|
||||
if (in_cc->deity == 203) // Cazic-Thule Erudites go to Paineel
|
||||
{
|
||||
in_pp->zone_id = 75; // paineel
|
||||
in_pp->binds[0].zoneId = 75;
|
||||
}
|
||||
else
|
||||
{
|
||||
in_pp->zone_id = 24; // erudnext
|
||||
in_pp->binds[0].zoneId = 38; // tox
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
@@ -432,6 +472,7 @@ void WorldDatabase::SetTitaniumDefaultStartZone(PlayerProfile_Struct* in_pp, Cha
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WorldDatabase::GetLauncherList(std::vector<std::string> &rl) {
|
||||
rl.clear();
|
||||
|
||||
@@ -447,8 +488,8 @@ void WorldDatabase::GetLauncherList(std::vector<std::string> &rl) {
|
||||
|
||||
}
|
||||
|
||||
void WorldDatabase::SetMailKey(int CharID, int IPAddress, int MailKey) {
|
||||
|
||||
void WorldDatabase::SetMailKey(int CharID, int IPAddress, int MailKey)
|
||||
{
|
||||
char MailKeyString[17];
|
||||
|
||||
if(RuleB(Chat, EnableMailKeyIPVerification) == true)
|
||||
@@ -482,7 +523,8 @@ bool WorldDatabase::GetCharacterLevel(const char *name, int &level)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WorldDatabase::LoadCharacterCreateAllocations() {
|
||||
bool WorldDatabase::LoadCharacterCreateAllocations()
|
||||
{
|
||||
character_create_allocations.clear();
|
||||
|
||||
std::string query = "SELECT * FROM char_create_point_allocations ORDER BY id";
|
||||
@@ -514,7 +556,8 @@ bool WorldDatabase::LoadCharacterCreateAllocations() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WorldDatabase::LoadCharacterCreateCombos() {
|
||||
bool WorldDatabase::LoadCharacterCreateCombos()
|
||||
{
|
||||
character_create_race_class_combos.clear();
|
||||
|
||||
std::string query = "SELECT * FROM char_create_combinations ORDER BY race, class, deity, start_zone";
|
||||
@@ -536,4 +579,3 @@ bool WorldDatabase::LoadCharacterCreateCombos() {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "../common/shareddb.h"
|
||||
#include "../common/zone_numbers.h"
|
||||
#include "../common/eq_packet.h"
|
||||
|
||||
struct PlayerProfile_Struct;
|
||||
struct CharCreate_Struct;
|
||||
@@ -29,7 +30,7 @@ struct CharacterSelect_Struct;
|
||||
class WorldDatabase : public SharedDatabase {
|
||||
public:
|
||||
bool GetStartZone(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_cc, bool isTitanium);
|
||||
void GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct*, uint32 ClientVersion);
|
||||
void GetCharSelectInfo(uint32 accountID, EQApplicationPacket **outApp, uint32 clientVersionBit);
|
||||
int MoveCharacterToBind(int CharID, uint8 bindnum = 0);
|
||||
|
||||
void GetLauncherList(std::vector<std::string> &result);
|
||||
|
||||
+37
-14
@@ -190,7 +190,7 @@ bool ZoneServer::Process() {
|
||||
Log.Out(Logs::Detail, Logs::World_Server,"Zone authorization failed.");
|
||||
auto pack = new ServerPacket(ServerOP_ZAAuthFailed);
|
||||
SendPacket(pack);
|
||||
delete pack;
|
||||
safe_delete(pack);
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
@@ -201,7 +201,7 @@ bool ZoneServer::Process() {
|
||||
Log.Out(Logs::Detail, Logs::World_Server,"Zone authorization failed.");
|
||||
auto pack = new ServerPacket(ServerOP_ZAAuthFailed);
|
||||
SendPacket(pack);
|
||||
delete pack;
|
||||
safe_delete(pack);
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
@@ -779,7 +779,7 @@ bool ZoneServer::Process() {
|
||||
whom->wrace = whoall->wrace;
|
||||
strcpy(whom->whom,whoall->whom);
|
||||
client_list.SendWhoAll(whoall->fromid,whoall->from, whoall->admin, whom, this);
|
||||
delete whom;
|
||||
safe_delete(whom);
|
||||
break;
|
||||
}
|
||||
case ServerOP_RequestOnlineGuildMembers: {
|
||||
@@ -958,13 +958,13 @@ bool ZoneServer::Process() {
|
||||
tod->start_eqtime=zoneserver_list.worldclock.getStartEQTime();
|
||||
tod->start_realtime=zoneserver_list.worldclock.getStartRealTime();
|
||||
SendPacket(pack);
|
||||
delete pack;
|
||||
safe_delete(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_SetWorldTime: {
|
||||
Log.Out(Logs::Detail, Logs::World_Server,"Received SetWorldTime");
|
||||
eqTimeOfDay* newtime = (eqTimeOfDay*) pack->pBuffer;
|
||||
zoneserver_list.worldclock.setEQTimeOfDay(newtime->start_eqtime, newtime->start_realtime);
|
||||
zoneserver_list.worldclock.SetCurrentEQTimeOfDay(newtime->start_eqtime, newtime->start_realtime);
|
||||
Log.Out(Logs::Detail, Logs::World_Server,"New time = %d-%d-%d %d:%d (%d)\n", newtime->start_eqtime.year, newtime->start_eqtime.month, (int)newtime->start_eqtime.day, (int)newtime->start_eqtime.hour, (int)newtime->start_eqtime.minute, (int)newtime->start_realtime);
|
||||
zoneserver_list.worldclock.saveFile(WorldConfig::get()->EQTimeFile.c_str());
|
||||
zoneserver_list.SendTimeSync();
|
||||
@@ -1059,8 +1059,7 @@ bool ZoneServer::Process() {
|
||||
}
|
||||
else
|
||||
{
|
||||
delete pack;
|
||||
pack = new ServerPacket(ServerOP_Consent_Response, sizeof(ServerOP_Consent_Struct));
|
||||
auto pack = new ServerPacket(ServerOP_Consent_Response, sizeof(ServerOP_Consent_Struct));
|
||||
ServerOP_Consent_Struct* scs = (ServerOP_Consent_Struct*)pack->pBuffer;
|
||||
strcpy(scs->grantname, s->grantname);
|
||||
strcpy(scs->ownername, s->ownername);
|
||||
@@ -1076,6 +1075,7 @@ bool ZoneServer::Process() {
|
||||
else {
|
||||
Log.Out(Logs::Detail, Logs::World_Server, "Unable to locate zone record for instance id %u in zoneserver list for ServerOP_Consent_Response operation.", s->instance_id);
|
||||
}
|
||||
safe_delete(pack);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1091,8 +1091,7 @@ bool ZoneServer::Process() {
|
||||
}
|
||||
else {
|
||||
// send target not found back to requester
|
||||
delete pack;
|
||||
pack = new ServerPacket(ServerOP_Consent_Response, sizeof(ServerOP_Consent_Struct));
|
||||
auto pack = new ServerPacket(ServerOP_Consent_Response, sizeof(ServerOP_Consent_Struct));
|
||||
ServerOP_Consent_Struct* scs = (ServerOP_Consent_Struct*)pack->pBuffer;
|
||||
strcpy(scs->grantname, s->grantname);
|
||||
strcpy(scs->ownername, s->ownername);
|
||||
@@ -1107,13 +1106,13 @@ bool ZoneServer::Process() {
|
||||
else {
|
||||
Log.Out(Logs::Detail, Logs::World_Server, "Unable to locate zone record for zone id %u in zoneserver list for ServerOP_Consent_Response operation.", s->zone_id);
|
||||
}
|
||||
safe_delete(pack);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// send target not found back to requester
|
||||
delete pack;
|
||||
pack = new ServerPacket(ServerOP_Consent_Response, sizeof(ServerOP_Consent_Struct));
|
||||
auto pack = new ServerPacket(ServerOP_Consent_Response, sizeof(ServerOP_Consent_Struct));
|
||||
ServerOP_Consent_Struct* scs = (ServerOP_Consent_Struct*)pack->pBuffer;
|
||||
strcpy(scs->grantname, s->grantname);
|
||||
strcpy(scs->ownername, s->ownername);
|
||||
@@ -1128,6 +1127,7 @@ bool ZoneServer::Process() {
|
||||
else {
|
||||
Log.Out(Logs::Detail, Logs::World_Server, "Unable to locate zone record for zone id %u in zoneserver list for ServerOP_Consent_Response operation.", s->zone_id);
|
||||
}
|
||||
safe_delete(pack);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1311,15 +1311,38 @@ bool ZoneServer::Process() {
|
||||
cle->ProcessTellQueue();
|
||||
break;
|
||||
}
|
||||
case ServerOP_ClientFileStatus:
|
||||
{
|
||||
ServerRequestClientFileStatus *req = (ServerRequestClientFileStatus*) pack->pBuffer;
|
||||
ClientListEntry *cle = client_list.FindCharacter(req->name);
|
||||
|
||||
if(cle) {
|
||||
ServerPacket pack(ServerOP_ClientFileStatus, sizeof(ServerResponseClientFileStatus));
|
||||
ServerResponseClientFileStatus *resp = (ServerResponseClientFileStatus*)pack.pBuffer;
|
||||
|
||||
strcpy(resp->name, req->name);
|
||||
resp->spells = cle->GetSpellFileVerified();
|
||||
resp->skills = cle->GetSkillFileVerified();
|
||||
resp->base_data = cle->GetBaseDataFileVerified();
|
||||
resp->eqgame = cle->GetEQGameVerified();
|
||||
zoneserver_list.SendPacket(req->zone_id, req->instance_id, &pack);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Log.Out(Logs::Detail, Logs::World_Server,"Unknown ServerOPcode from zone 0x%04x, size %d",pack->opcode,pack->size);
|
||||
Log.Out(Logs::Detail, Logs::World_Server, "Unknown ServerOPcode from zone 0x%04x, size %d", pack->opcode, pack->size);
|
||||
DumpPacket(pack->pBuffer, pack->size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete pack;
|
||||
if (pack) {
|
||||
safe_delete(pack);
|
||||
}
|
||||
else {
|
||||
Log.Out(Logs::Detail, Logs::World_Server, "Zoneserver process attempted to delete pack when pack does not exist.");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ SET(zone_sources
|
||||
embparser_api.cpp
|
||||
embperl.cpp
|
||||
embxs.cpp
|
||||
encounter.cpp
|
||||
entity.cpp
|
||||
exp.cpp
|
||||
fearpath.cpp
|
||||
@@ -35,6 +36,7 @@ SET(zone_sources
|
||||
lua_corpse.cpp
|
||||
lua_client.cpp
|
||||
lua_door.cpp
|
||||
lua_encounter.cpp
|
||||
lua_entity.cpp
|
||||
lua_entity_list.cpp
|
||||
lua_general.cpp
|
||||
@@ -137,6 +139,7 @@ SET(zone_headers
|
||||
embparser.h
|
||||
embperl.h
|
||||
embxs.h
|
||||
encounter.h
|
||||
entity.h
|
||||
errmsg.h
|
||||
event_codes.h
|
||||
@@ -148,6 +151,7 @@ SET(zone_headers
|
||||
lua_bit.h
|
||||
lua_client.h
|
||||
lua_corpse.h
|
||||
lua_encounter.h
|
||||
lua_entity.h
|
||||
lua_entity_list.h
|
||||
lua_general.h
|
||||
|
||||
+24
-17
@@ -525,7 +525,7 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
|
||||
|
||||
NPCType *made_npc = nullptr;
|
||||
|
||||
const NPCType *npc_type = database.GetNPCType(pet.npc_id);
|
||||
const NPCType *npc_type = database.LoadNPCTypesData(pet.npc_id);
|
||||
if(npc_type == nullptr) {
|
||||
//log write
|
||||
Log.Out(Logs::General, Logs::Error, "Unknown npc type for swarm pet spell id: %d", spell_id);
|
||||
@@ -622,7 +622,7 @@ void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_overrid
|
||||
|
||||
NPCType *made_npc = nullptr;
|
||||
|
||||
const NPCType *npc_type = database.GetNPCType(typesid);
|
||||
const NPCType *npc_type = database.LoadNPCTypesData(typesid);
|
||||
if(npc_type == nullptr) {
|
||||
//log write
|
||||
Log.Out(Logs::General, Logs::Error, "Unknown npc type for swarm pet type id: %d", typesid);
|
||||
@@ -715,7 +715,7 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration)
|
||||
return;
|
||||
|
||||
//assuming we have pets in our table; we take the first pet as a base type.
|
||||
const NPCType *base_type = database.GetNPCType(500);
|
||||
const NPCType *base_type = database.LoadNPCTypesData(500);
|
||||
NPCType *make_npc = new NPCType;
|
||||
memcpy(make_npc, base_type, sizeof(NPCType));
|
||||
|
||||
@@ -1104,9 +1104,9 @@ void Client::SendAATable() {
|
||||
|
||||
uint32 i;
|
||||
for(i=0;i < MAX_PP_AA_ARRAY;i++){
|
||||
aa2->aa_list[i].aa_skill = aa[i]->AA;
|
||||
aa2->aa_list[i].aa_value = aa[i]->value;
|
||||
aa2->aa_list[i].unknown08 = 0;
|
||||
aa2->aa_list[i].AA = aa[i]->value ? aa[i]->AA : 0; // bit of a hack to prevent expendables punching a hole
|
||||
aa2->aa_list[i].value = aa[i]->value;
|
||||
aa2->aa_list[i].charges = aa[i]->charges;
|
||||
}
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
@@ -1309,11 +1309,9 @@ void Client::SendAA(uint32 id, int seq) {
|
||||
SendAA_Struct* saa_next = nullptr;
|
||||
saa_next = zone->FindAA(saa->sof_next_id);
|
||||
|
||||
// hard-coding values like this is dangerous and makes adding/updating clients a nightmare...
|
||||
if (saa_next &&
|
||||
(((GetClientVersionBit() == 4) && (saa_next->clientver > 4))
|
||||
|| ((GetClientVersionBit() == 8) && (saa_next->clientver > 5))
|
||||
|| ((GetClientVersionBit() == 16) && (saa_next->clientver > 6)))){
|
||||
// this check should work as long as we continue to just add the clients and just increase
|
||||
// each number ....
|
||||
if (saa_next && static_cast<int>(GetClientVersion()) < saa_next->clientver - 1) {
|
||||
saa->next_id=0xFFFFFFFF;
|
||||
}
|
||||
}
|
||||
@@ -1397,26 +1395,33 @@ uint32 Client::GetAA(uint32 aa_id) const {
|
||||
bool Client::SetAA(uint32 aa_id, uint32 new_value) {
|
||||
aa_points[aa_id] = new_value;
|
||||
uint32 cur;
|
||||
auto sendaa = zone->FindAA(aa_id); // this is a bit hacky
|
||||
uint32 charges = sendaa->special_category == 7 && new_value ? 1 : 0;
|
||||
for(cur=0;cur < MAX_PP_AA_ARRAY;cur++){
|
||||
if((aa[cur]->value > 1) && ((aa[cur]->AA - aa[cur]->value + 1)== aa_id)){
|
||||
aa[cur]->value = new_value;
|
||||
if(new_value > 0)
|
||||
aa[cur]->AA++;
|
||||
else
|
||||
aa[cur]->AA = 0;
|
||||
aa[cur]->charges = charges;
|
||||
return true;
|
||||
}
|
||||
else if((aa[cur]->value == 1) && (aa[cur]->AA == aa_id)){
|
||||
aa[cur]->value = new_value;
|
||||
if(new_value > 0)
|
||||
aa[cur]->AA++;
|
||||
else
|
||||
aa[cur]->AA = 0;
|
||||
aa[cur]->charges = charges;
|
||||
return true;
|
||||
}
|
||||
// hack to prevent expendable exploit, we should probably be reshuffling the array to fix the hole
|
||||
else if(aa[cur]->value == 0 && new_value == 1 && aa[cur]->AA == aa_id) {
|
||||
aa[cur]->value = new_value;
|
||||
aa[cur]->charges = charges;
|
||||
return true;
|
||||
}
|
||||
else if(aa[cur]->AA==0){ //end of list
|
||||
aa[cur]->AA = aa_id;
|
||||
aa[cur]->value = new_value;
|
||||
aa[cur]->charges = charges;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1487,8 +1492,10 @@ void Client::ResetAA(){
|
||||
for (i=0; i < MAX_PP_AA_ARRAY; i++) {
|
||||
aa[i]->AA = 0;
|
||||
aa[i]->value = 0;
|
||||
m_pp.aa_array[MAX_PP_AA_ARRAY].AA = 0;
|
||||
m_pp.aa_array[MAX_PP_AA_ARRAY].value = 0;
|
||||
aa[i]->charges = 0;
|
||||
m_pp.aa_array[i].AA = 0;
|
||||
m_pp.aa_array[i].value = 0;
|
||||
m_pp.aa_array[i].charges= 0;
|
||||
}
|
||||
|
||||
std::map<uint32,uint8>::iterator itr;
|
||||
|
||||
+76
-29
@@ -384,7 +384,7 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
|
||||
int counter_dodge = 0;
|
||||
|
||||
if (attacker->GetSpecialAbility(COUNTER_AVOID_DAMAGE)){
|
||||
|
||||
|
||||
counter_all = attacker->GetSpecialAbilityParam(COUNTER_AVOID_DAMAGE, 0);
|
||||
counter_riposte = attacker->GetSpecialAbilityParam(COUNTER_AVOID_DAMAGE,1);
|
||||
counter_block = attacker->GetSpecialAbilityParam(COUNTER_AVOID_DAMAGE, 2);
|
||||
@@ -406,7 +406,7 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
|
||||
float riposte_chance = 0.0f;
|
||||
if (CanRiposte && damage > 0 && CanThisClassRiposte() && InFront)
|
||||
{
|
||||
riposte_chance = (100.0f + static_cast<float>(aabonuses.RiposteChance + spellbonuses.RiposteChance +
|
||||
riposte_chance = (100.0f + static_cast<float>(aabonuses.RiposteChance + spellbonuses.RiposteChance +
|
||||
itembonuses.RiposteChance - counter_riposte - counter_all)) / 100.0f;
|
||||
skill = GetSkill(SkillRiposte);
|
||||
if (IsClient()) {
|
||||
@@ -437,7 +437,7 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
|
||||
|
||||
float block_chance = 0.0f;
|
||||
if (damage > 0 && CanThisClassBlock() && (InFront || bBlockFromRear)) {
|
||||
block_chance = (100.0f + static_cast<float>(aabonuses.IncreaseBlockChance + spellbonuses.IncreaseBlockChance +
|
||||
block_chance = (100.0f + static_cast<float>(aabonuses.IncreaseBlockChance + spellbonuses.IncreaseBlockChance +
|
||||
itembonuses.IncreaseBlockChance - counter_block - counter_all)) / 100.0f;
|
||||
skill = CastToClient()->GetSkill(SkillBlock);
|
||||
if (IsClient()) {
|
||||
@@ -455,18 +455,18 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
|
||||
}
|
||||
|
||||
//Try Shield Block OR TwoHandBluntBlockCheck
|
||||
if(damage > 0 && HasShieldEquiped() && (aabonuses.ShieldBlock || spellbonuses.ShieldBlock || itembonuses.ShieldBlock) && (InFront || bBlockFromRear))
|
||||
if(damage > 0 && HasShieldEquiped() && (aabonuses.ShieldBlock || spellbonuses.ShieldBlock || itembonuses.ShieldBlock) && (InFront || bBlockFromRear))
|
||||
RollTable[1] += static_cast<float>(aabonuses.ShieldBlock + spellbonuses.ShieldBlock + itembonuses.ShieldBlock - counter_block - counter_all);
|
||||
|
||||
else if(damage > 0 && HasTwoHandBluntEquiped() && (aabonuses.TwoHandBluntBlock || spellbonuses.TwoHandBluntBlock || itembonuses.TwoHandBluntBlock) && (InFront || bBlockFromRear))
|
||||
else if(damage > 0 && HasTwoHandBluntEquiped() && (aabonuses.TwoHandBluntBlock || spellbonuses.TwoHandBluntBlock || itembonuses.TwoHandBluntBlock) && (InFront || bBlockFromRear))
|
||||
RollTable[1] += static_cast<float>(aabonuses.TwoHandBluntBlock + spellbonuses.TwoHandBluntBlock + itembonuses.TwoHandBluntBlock - counter_block - counter_all);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// parry
|
||||
//////////////////////////////////////////////////////
|
||||
float parry_chance = 0.0f;
|
||||
if (damage > 0 && CanThisClassParry() && InFront){
|
||||
parry_chance = (100.0f + static_cast<float>(aabonuses.ParryChance + itembonuses.ParryChance +
|
||||
parry_chance = (100.0f + static_cast<float>(aabonuses.ParryChance + itembonuses.ParryChance +
|
||||
itembonuses.ParryChance - counter_parry - counter_all)) / 100.0f;
|
||||
skill = CastToClient()->GetSkill(SkillParry);
|
||||
if (IsClient()) {
|
||||
@@ -490,7 +490,7 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
|
||||
float dodge_chance = 0.0f;
|
||||
if (damage > 0 && CanThisClassDodge() && InFront){
|
||||
|
||||
dodge_chance = (100.0f + static_cast<float>(aabonuses.DodgeChance + spellbonuses.DodgeChance +
|
||||
dodge_chance = (100.0f + static_cast<float>(aabonuses.DodgeChance + spellbonuses.DodgeChance +
|
||||
itembonuses.DodgeChance - counter_dodge - counter_all)) / 100.0f;
|
||||
|
||||
skill = CastToClient()->GetSkill(SkillDodge);
|
||||
@@ -917,6 +917,7 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate
|
||||
{
|
||||
int dmg = 0;
|
||||
int banedmg = 0;
|
||||
int x = 0;
|
||||
|
||||
if(!against || against->GetInvul() || against->GetSpecialAbility(IMMUNE_MELEE)){
|
||||
return 0;
|
||||
@@ -945,10 +946,20 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate
|
||||
bool MagicWeapon = false;
|
||||
if(weapon_item->GetItem() && weapon_item->GetItem()->Magic)
|
||||
MagicWeapon = true;
|
||||
else {
|
||||
else
|
||||
if(spellbonuses.MagicWeapon || itembonuses.MagicWeapon)
|
||||
MagicWeapon = true;
|
||||
}
|
||||
else
|
||||
// An augment on the weapon that is marked magic makes
|
||||
// the item magical.
|
||||
for(x = 0; MagicWeapon == false && x < EmuConstants::ITEM_COMMON_SIZE; x++)
|
||||
{
|
||||
if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem())
|
||||
{
|
||||
if (weapon_item->GetAugment(x)->GetItem()->Magic)
|
||||
MagicWeapon = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(MagicWeapon) {
|
||||
|
||||
@@ -971,14 +982,24 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate
|
||||
return 0;
|
||||
}
|
||||
else{
|
||||
if((GetClass() == MONK || GetClass() == BEASTLORD) && GetLevel() >= 30){
|
||||
dmg = GetMonkHandToHandDamage();
|
||||
if (hate) *hate += dmg;
|
||||
bool MagicGloves=false;
|
||||
if (IsClient()) {
|
||||
ItemInst *gloves=CastToClient()->GetInv().GetItem(MainHands);
|
||||
if (gloves != nullptr) {
|
||||
MagicGloves = gloves->GetItem()->Magic;
|
||||
}
|
||||
}
|
||||
|
||||
if((GetClass() == MONK || GetClass() == BEASTLORD)) {
|
||||
if(MagicGloves || GetLevel() >= 30){
|
||||
dmg = GetMonkHandToHandDamage();
|
||||
if (hate) *hate += dmg;
|
||||
}
|
||||
}
|
||||
else if(GetOwner() && GetLevel() >= RuleI(Combat, PetAttackMagicLevel)){ //pets wouldn't actually use this but...
|
||||
dmg = 1; //it gives us an idea if we can hit
|
||||
}
|
||||
else if(GetSpecialAbility(SPECATK_MAGICAL)){
|
||||
else if(MagicGloves || GetSpecialAbility(SPECATK_MAGICAL)){
|
||||
dmg = 1;
|
||||
}
|
||||
else
|
||||
@@ -2123,6 +2144,10 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
|
||||
if(give_exp && give_exp->IsClient())
|
||||
give_exp_client = give_exp->CastToClient();
|
||||
|
||||
//do faction hits even if we are a merchant, so long as a player killed us
|
||||
if (give_exp_client && !RuleB(NPC, EnableMeritBasedFaction))
|
||||
hate_list.DoFactionHits(GetNPCFactionID());
|
||||
|
||||
bool IsLdonTreasure = (this->GetClass() == LDON_TREASURE);
|
||||
if (give_exp_client && !IsCorpse())
|
||||
{
|
||||
@@ -2266,10 +2291,6 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
|
||||
}
|
||||
}
|
||||
|
||||
//do faction hits even if we are a merchant, so long as a player killed us
|
||||
if(give_exp_client && !RuleB(NPC, EnableMeritBasedFaction))
|
||||
hate_list.DoFactionHits(GetNPCFactionID());
|
||||
|
||||
if (!HasOwner() && !IsMerc() && class_ != MERCHANT && class_ != ADVENTUREMERCHANT && !GetSwarmInfo()
|
||||
&& MerchantType == 0 && killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) ||
|
||||
(killer->IsNPC() && killer->CastToNPC()->GetSwarmInfo() && killer->CastToNPC()->GetSwarmInfo()->GetOwner() && killer->CastToNPC()->GetSwarmInfo()->GetOwner()->IsClient())))
|
||||
@@ -2404,8 +2425,8 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
|
||||
|
||||
void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, bool iYellForHelp /*= true*/, bool bFrenzy /*= false*/, bool iBuffTic /*= false*/)
|
||||
{
|
||||
|
||||
assert(other != nullptr);
|
||||
if(!other)
|
||||
return;
|
||||
|
||||
if (other == this)
|
||||
return;
|
||||
@@ -2416,7 +2437,7 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
|
||||
|
||||
bool wasengaged = IsEngaged();
|
||||
Mob* owner = other->GetOwner();
|
||||
Mob* mypet = this->GetPet();
|
||||
Mob* mypet = this->GetPet();
|
||||
Mob* myowner = this->GetOwner();
|
||||
Mob* targetmob = this->GetTarget();
|
||||
|
||||
@@ -3639,6 +3660,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
|
||||
(frontal_stun_resist && zone->random.Roll(frontal_stun_resist))) &&
|
||||
!attacker->BehindMob(this, attacker->GetX(), attacker->GetY())) {
|
||||
Log.Out(Logs::Detail, Logs::Combat, "Frontal stun resisted. %d chance.", frontal_stun_resist);
|
||||
|
||||
} else {
|
||||
// Normal stun resist check.
|
||||
if (stun_resist && zone->random.Roll(stun_resist)) {
|
||||
@@ -3671,7 +3693,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
|
||||
|
||||
//send an HP update if we are hurt
|
||||
if(GetHP() < GetMaxHP())
|
||||
SendHPUpdate();
|
||||
SendHPUpdate(!iBuffTic); // the OP_Damage actually updates the client in these cases, so we skill them
|
||||
} //end `if damage was done`
|
||||
|
||||
//send damage packet...
|
||||
@@ -3688,6 +3710,23 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
|
||||
a->type = SkillDamageTypes[skill_used]; // was 0x1c
|
||||
a->damage = damage;
|
||||
a->spellid = spell_id;
|
||||
a->meleepush_xy = attacker->GetHeading() * 2.0f;
|
||||
if (RuleB(Combat, MeleePush) && damage > 0 && !IsRooted() &&
|
||||
(IsClient() || zone->random.Roll(RuleI(Combat, MeleePushChance)))) {
|
||||
a->force = EQEmu::GetSkillMeleePushForce(skill_used);
|
||||
// update NPC stuff
|
||||
auto new_pos = glm::vec3(m_Position.x + (a->force * std::sin(a->meleepush_xy) + m_Delta.x),
|
||||
m_Position.y + (a->force * std::cos(a->meleepush_xy) + m_Delta.y), m_Position.z);
|
||||
if (zone->zonemap && zone->zonemap->CheckLoS(glm::vec3(m_Position), new_pos)) { // If we have LoS on the new loc it should be reachable.
|
||||
if (IsNPC()) {
|
||||
// Is this adequate?
|
||||
Teleport(new_pos);
|
||||
SendPosUpdate();
|
||||
}
|
||||
} else {
|
||||
a->force = 0.0f; // we couldn't move there, so lets not
|
||||
}
|
||||
}
|
||||
|
||||
//Note: if players can become pets, they will not receive damage messages of their own
|
||||
//this was done to simplify the code here (since we can only effectively skip one mob on queue)
|
||||
@@ -3920,7 +3959,7 @@ void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand) {
|
||||
float chance = ProcChance * (static_cast<float>(DefensiveProcs[i].chance)/100.0f);
|
||||
if (zone->random.Roll(chance)) {
|
||||
ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on);
|
||||
CheckNumHitsRemaining(NumHit::DefensiveSpellProcs, 0,
|
||||
CheckNumHitsRemaining(NumHit::DefensiveSpellProcs, 0,
|
||||
DefensiveProcs[i].base_spellID);
|
||||
}
|
||||
}
|
||||
@@ -3956,7 +3995,7 @@ void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) {
|
||||
}
|
||||
|
||||
// Innate + aug procs from weapons
|
||||
// TODO: powersource procs
|
||||
// TODO: powersource procs -- powersource procs are on invis augs, so shouldn't need anything extra
|
||||
TryWeaponProc(weapon_g, weapon_g->GetItem(), on, hand);
|
||||
// Procs from Buffs and AA both melee and range
|
||||
TrySpellProc(weapon_g, weapon_g->GetItem(), on, hand);
|
||||
@@ -3983,7 +4022,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on
|
||||
// We can proc once here, either weapon or one aug
|
||||
bool proced = false; // silly bool to prevent augs from going if weapon does
|
||||
skillinuse = GetSkillByItemType(weapon->ItemType);
|
||||
if (weapon->Proc.Type == ET_CombatProc) {
|
||||
if (weapon->Proc.Type == ET_CombatProc && IsValidSpell(weapon->Proc.Effect)) {
|
||||
float WPC = ProcChance * (100.0f + // Proc chance for this weapon
|
||||
static_cast<float>(weapon->ProcRate)) / 100.0f;
|
||||
if (zone->random.Roll(WPC)) { // 255 dex = 0.084 chance of proc. No idea what this number should be really.
|
||||
@@ -4021,7 +4060,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on
|
||||
if (!aug)
|
||||
continue;
|
||||
|
||||
if (aug->Proc.Type == ET_CombatProc) {
|
||||
if (aug->Proc.Type == ET_CombatProc && IsValidSpell(aug->Proc.Effect)) {
|
||||
float APC = ProcChance * (100.0f + // Proc chance for this aug
|
||||
static_cast<float>(aug->ProcRate)) / 100.0f;
|
||||
if (zone->random.Roll(APC)) {
|
||||
@@ -4042,7 +4081,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: Powersource procs
|
||||
// TODO: Powersource procs -- powersource procs are from augs so shouldn't need anything extra
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -4096,7 +4135,15 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on,
|
||||
Log.Out(Logs::Detail, Logs::Combat,
|
||||
"Spell proc %d procing spell %d (%.2f percent chance)",
|
||||
i, SpellProcs[i].spellID, chance);
|
||||
ExecWeaponProc(nullptr, SpellProcs[i].spellID, on);
|
||||
auto outapp = new EQApplicationPacket(OP_BeginCast,sizeof(BeginCast_Struct));
|
||||
BeginCast_Struct* begincast = (BeginCast_Struct*)outapp->pBuffer;
|
||||
begincast->caster_id = GetID();
|
||||
begincast->spell_id = SpellProcs[i].spellID;
|
||||
begincast->cast_time = 0;
|
||||
outapp->priority = 3;
|
||||
entity_list.QueueCloseClients(this, outapp, false, 200, 0, true);
|
||||
safe_delete(outapp);
|
||||
ExecWeaponProc(nullptr, SpellProcs[i].spellID, on, SpellProcs[i].level_override);
|
||||
CheckNumHitsRemaining(NumHit::OffensiveSpellProcs, 0,
|
||||
SpellProcs[i].base_spellID);
|
||||
} else {
|
||||
@@ -4202,7 +4249,7 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack
|
||||
}
|
||||
|
||||
#ifdef BOTS
|
||||
if (this->IsPet() && this->GetOwner()->IsBot()) {
|
||||
if (this->IsPet() && this->GetOwner() && this->GetOwner()->IsBot()) {
|
||||
this->TryPetCriticalHit(defender,skill,damage);
|
||||
return;
|
||||
}
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ Beacon::Beacon(Mob *at_mob, int lifetime)
|
||||
:Mob
|
||||
(
|
||||
nullptr, nullptr, 0, 0, 0, INVISIBLE_MAN, 0, BT_NoTarget, 0, 0, 0, 0, 0, at_mob->GetPosition(), 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
),
|
||||
remove_timer(lifetime),
|
||||
spell_timer(0)
|
||||
|
||||
+73
-70
@@ -81,6 +81,8 @@ void Client::CalcBonuses()
|
||||
CalcAABonuses(&aabonuses); //we're not quite ready for this
|
||||
Log.Out(Logs::Detail, Logs::AA, "Finished calculating AA Bonuses for %s.", this->GetCleanName());
|
||||
|
||||
ProcessItemCaps(); // caps that depend on spell/aa bonuses
|
||||
|
||||
RecalcWeight();
|
||||
|
||||
CalcAC();
|
||||
@@ -183,16 +185,24 @@ void Client::CalcItemBonuses(StatBonuses* newbon) {
|
||||
AdditiveWornBonuses(inst, newbon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Caps
|
||||
if(newbon->HPRegen > CalcHPRegenCap())
|
||||
newbon->HPRegen = CalcHPRegenCap();
|
||||
// These item stat caps depend on spells/AAs so we process them after those are processed
|
||||
void Client::ProcessItemCaps()
|
||||
{
|
||||
itembonuses.HPRegen = std::min(itembonuses.HPRegen, CalcHPRegenCap());
|
||||
itembonuses.ManaRegen = std::min(itembonuses.ManaRegen, CalcManaRegenCap());
|
||||
itembonuses.EnduranceRegen = std::min(itembonuses.EnduranceRegen, CalcEnduranceRegenCap());
|
||||
|
||||
if(newbon->ManaRegen > CalcManaRegenCap())
|
||||
newbon->ManaRegen = CalcManaRegenCap();
|
||||
// The Sleeper Tomb Avatar proc counts towards item ATK
|
||||
// The client uses a 100 here, so using a 100 here the client and server will agree
|
||||
// For example, if you set the effect to be 200 it will get 100 item ATK and 100 spell ATK
|
||||
if (IsValidSpell(2434) && FindBuff(2434)) {
|
||||
itembonuses.ATK += 100;
|
||||
spellbonuses.ATK -= 100;
|
||||
}
|
||||
|
||||
if(newbon->EnduranceRegen > CalcEnduranceRegenCap())
|
||||
newbon->EnduranceRegen = CalcEnduranceRegenCap();
|
||||
itembonuses.ATK = std::min(itembonuses.ATK, CalcItemATKCap());
|
||||
}
|
||||
|
||||
void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, bool isTribute) {
|
||||
@@ -225,6 +235,7 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu
|
||||
newbon->HP += item->HP;
|
||||
newbon->Mana += item->Mana;
|
||||
newbon->Endurance += item->Endur;
|
||||
newbon->ATK += item->Attack;
|
||||
newbon->STR += (item->AStr + item->HeroicStr);
|
||||
newbon->STA += (item->ASta + item->HeroicSta);
|
||||
newbon->DEX += (item->ADex + item->HeroicDex);
|
||||
@@ -278,6 +289,7 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu
|
||||
newbon->HP += CalcRecommendedLevelBonus( lvl, reclvl, item->HP );
|
||||
newbon->Mana += CalcRecommendedLevelBonus( lvl, reclvl, item->Mana );
|
||||
newbon->Endurance += CalcRecommendedLevelBonus( lvl, reclvl, item->Endur );
|
||||
newbon->ATK += CalcRecommendedLevelBonus( lvl, reclvl, item->Attack );
|
||||
newbon->STR += CalcRecommendedLevelBonus( lvl, reclvl, (item->AStr + item->HeroicStr) );
|
||||
newbon->STA += CalcRecommendedLevelBonus( lvl, reclvl, (item->ASta + item->HeroicSta) );
|
||||
newbon->DEX += CalcRecommendedLevelBonus( lvl, reclvl, (item->ADex + item->HeroicDex) );
|
||||
@@ -335,16 +347,6 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu
|
||||
if(item->EnduranceRegen > 0)
|
||||
newbon->EnduranceRegen += item->EnduranceRegen;
|
||||
|
||||
if(item->Attack > 0) {
|
||||
|
||||
int cap = RuleI(Character, ItemATKCap);
|
||||
cap += itembonuses.ItemATKCap + spellbonuses.ItemATKCap + aabonuses.ItemATKCap;
|
||||
|
||||
if((newbon->ATK + item->Attack) > cap)
|
||||
newbon->ATK = RuleI(Character, ItemATKCap);
|
||||
else
|
||||
newbon->ATK += item->Attack;
|
||||
}
|
||||
if(item->DamageShield > 0) {
|
||||
if((newbon->DamageShield + item->DamageShield) > RuleI(Character, ItemDamageShieldCap))
|
||||
newbon->DamageShield = RuleI(Character, ItemDamageShieldCap);
|
||||
@@ -426,7 +428,7 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu
|
||||
newbon->DSMitigation += item->DSMitigation;
|
||||
}
|
||||
if (item->Worn.Effect > 0 && item->Worn.Type == ET_WornEffect) {// latent effects
|
||||
ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, item->Worn.Type);
|
||||
ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, item->Worn.Type);
|
||||
}
|
||||
|
||||
if (item->Focus.Effect>0 && (item->Focus.Type == ET_Focus)) { // focus effects
|
||||
@@ -557,7 +559,7 @@ void Client::AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool
|
||||
/*
|
||||
Powerful Non-live like option allows developers to add worn effects on items that
|
||||
can stack with other worn effects of the same spell effect type, instead of only taking the highest value.
|
||||
Ie Cleave I = 40 pct cleave - So if you equip 3 cleave I items you will have a 120 pct cleave bonus.
|
||||
Ie Cleave I = 40 pct cleave - So if you equip 3 cleave I items you will have a 120 pct cleave bonus.
|
||||
To enable use RuleI(Spells, AdditiveBonusWornType)
|
||||
Setting value = 2 Will force all live items to automatically be calculated additivily
|
||||
Setting value to anything else will indicate the item 'worntype' that if set to the same, will cause the bonuses to use this calculation
|
||||
@@ -577,7 +579,7 @@ void Client::AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool
|
||||
|
||||
if(GetLevel() < item->ReqLevel)
|
||||
return;
|
||||
|
||||
|
||||
if (item->Worn.Effect > 0 && item->Worn.Type == RuleI(Spells, AdditiveBonusWornType))
|
||||
ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, item->Worn.Type);// Non-live like - Addititive latent effects
|
||||
|
||||
@@ -689,7 +691,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
continue;
|
||||
|
||||
Log.Out(Logs::Detail, Logs::AA, "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)
|
||||
{
|
||||
@@ -701,7 +703,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
{
|
||||
//Note: AA effects that use accuracy are skill limited, while spell effect is not.
|
||||
case SE_Accuracy:
|
||||
if ((base2 == -1) && (newbon->Accuracy[HIGHEST_SKILL+1] < base1))
|
||||
if ((base2 == ALL_SKILLS) && (newbon->Accuracy[HIGHEST_SKILL+1] < base1))
|
||||
newbon->Accuracy[HIGHEST_SKILL+1] = base1;
|
||||
else if (newbon->Accuracy[base2] < base1)
|
||||
newbon->Accuracy[base2] += base1;
|
||||
@@ -1005,7 +1007,7 @@ 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;
|
||||
@@ -1043,7 +1045,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
|
||||
case SE_HitChance:
|
||||
{
|
||||
if(base2 == -1)
|
||||
if(base2 == ALL_SKILLS)
|
||||
newbon->HitChanceEffect[HIGHEST_SKILL+1] += base1;
|
||||
else
|
||||
newbon->HitChanceEffect[base2] += base1;
|
||||
@@ -1099,7 +1101,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
|
||||
case SE_CriticalHitChance:
|
||||
{
|
||||
if(base2 == -1)
|
||||
if(base2 == ALL_SKILLS)
|
||||
newbon->CriticalHitChance[HIGHEST_SKILL+1] += base1;
|
||||
else
|
||||
newbon->CriticalHitChance[base2] += base1;
|
||||
@@ -1109,7 +1111,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
case SE_CriticalDamageMob:
|
||||
{
|
||||
// base1 = effect value, base2 = skill restrictions(-1 for all)
|
||||
if(base2 == -1)
|
||||
if(base2 == ALL_SKILLS)
|
||||
newbon->CritDmgMob[HIGHEST_SKILL+1] += base1;
|
||||
else
|
||||
newbon->CritDmgMob[base2] += base1;
|
||||
@@ -1137,7 +1139,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
|
||||
case SE_SkillDamageAmount:
|
||||
{
|
||||
if(base2 == -1)
|
||||
if(base2 == ALL_SKILLS)
|
||||
newbon->SkillDamageAmount[HIGHEST_SKILL+1] += base1;
|
||||
else
|
||||
newbon->SkillDamageAmount[base2] += base1;
|
||||
@@ -1154,7 +1156,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
|
||||
case SE_DamageModifier:
|
||||
{
|
||||
if(base2 == -1)
|
||||
if(base2 == ALL_SKILLS)
|
||||
newbon->DamageModifier[HIGHEST_SKILL+1] += base1;
|
||||
else
|
||||
newbon->DamageModifier[base2] += base1;
|
||||
@@ -1163,7 +1165,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
|
||||
case SE_DamageModifier2:
|
||||
{
|
||||
if(base2 == -1)
|
||||
if(base2 == ALL_SKILLS)
|
||||
newbon->DamageModifier2[HIGHEST_SKILL+1] += base1;
|
||||
else
|
||||
newbon->DamageModifier2[base2] += base1;
|
||||
@@ -1311,7 +1313,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
|
||||
case SE_Vampirism:
|
||||
newbon->Vampirism += base1;
|
||||
break;
|
||||
break;
|
||||
|
||||
case SE_FrenziedDevastation:
|
||||
newbon->FrenziedDevastation += base2;
|
||||
@@ -1414,7 +1416,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
}
|
||||
|
||||
case SE_SkillProcSuccess:{
|
||||
|
||||
|
||||
for(int e = 0; e < MAX_SKILL_PROCS; e++)
|
||||
{
|
||||
if(newbon->SkillProcSuccess[e] && newbon->SkillProcSuccess[e] == aaid)
|
||||
@@ -1447,7 +1449,7 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon)
|
||||
int buff_count = GetMaxTotalSlots();
|
||||
for(i = 0; i < buff_count; i++) {
|
||||
if(buffs[i].spellid != SPELL_UNKNOWN){
|
||||
ApplySpellsBonuses(buffs[i].spellid, buffs[i].casterlevel, newbon, buffs[i].casterid, 0, buffs[i].ticsremaining,i);
|
||||
ApplySpellsBonuses(buffs[i].spellid, buffs[i].casterlevel, newbon, buffs[i].casterid, 0, buffs[i].ticsremaining, i, buffs[i].instrument_mod);
|
||||
|
||||
if (buffs[i].numhits > 0)
|
||||
Numhits(true);
|
||||
@@ -1470,8 +1472,9 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon)
|
||||
if (GetClass() == BARD) newbon->ManaRegen = 0; // Bards do not get mana regen from spells.
|
||||
}
|
||||
|
||||
void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* new_bonus, uint16 casterId, uint8 WornType, uint32 ticsremaining, int buffslot,
|
||||
bool IsAISpellEffect, uint16 effect_id, int32 se_base, int32 se_limit, int32 se_max)
|
||||
void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *new_bonus, uint16 casterId,
|
||||
uint8 WornType, int32 ticsremaining, int buffslot, int instrument_mod,
|
||||
bool IsAISpellEffect, uint16 effect_id, int32 se_base, int32 se_limit, int32 se_max)
|
||||
{
|
||||
int i, effect_value, base2, max, effectid;
|
||||
bool AdditiveWornBonus = false;
|
||||
@@ -1507,9 +1510,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
|
||||
if (WornType && (RuleI(Spells, AdditiveBonusWornType) == WornType))
|
||||
AdditiveWornBonus = true;
|
||||
|
||||
|
||||
effectid = spells[spell_id].effectid[i];
|
||||
effect_value = CalcSpellEffectValue(spell_id, i, casterlevel, caster, ticsremaining);
|
||||
effect_value = CalcSpellEffectValue(spell_id, i, casterlevel, instrument_mod, caster, ticsremaining);
|
||||
base2 = spells[spell_id].base2[i];
|
||||
max = spells[spell_id].max[i];
|
||||
}
|
||||
@@ -1618,10 +1621,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
|
||||
if (effect_value > 0 && effect_value > new_bonus->inhibitmelee) {
|
||||
effect_value -= ((effect_value * GetSlowMitigation()/100));
|
||||
if (effect_value > new_bonus->inhibitmelee)
|
||||
if (effect_value > new_bonus->inhibitmelee)
|
||||
new_bonus->inhibitmelee = effect_value;
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1837,7 +1840,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
new_bonus->DamageShieldType = GetDamageShieldType(spell_id, max);
|
||||
else
|
||||
new_bonus->DamageShieldType = GetDamageShieldType(spell_id);
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1873,7 +1876,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
case SE_CriticalHitChance:
|
||||
{
|
||||
if (AdditiveWornBonus) {
|
||||
if(base2 == -1)
|
||||
if(base2 == ALL_SKILLS)
|
||||
new_bonus->CriticalHitChance[HIGHEST_SKILL+1] += effect_value;
|
||||
else
|
||||
new_bonus->CriticalHitChance[base2] += effect_value;
|
||||
@@ -1881,16 +1884,16 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
|
||||
else if(effect_value < 0) {
|
||||
|
||||
if(base2 == -1 && new_bonus->CriticalHitChance[HIGHEST_SKILL+1] > effect_value)
|
||||
if(base2 == ALL_SKILLS && new_bonus->CriticalHitChance[HIGHEST_SKILL+1] > effect_value)
|
||||
new_bonus->CriticalHitChance[HIGHEST_SKILL+1] = effect_value;
|
||||
else if(base2 != -1 && new_bonus->CriticalHitChance[base2] > effect_value)
|
||||
else if(base2 != ALL_SKILLS && new_bonus->CriticalHitChance[base2] > effect_value)
|
||||
new_bonus->CriticalHitChance[base2] = effect_value;
|
||||
}
|
||||
|
||||
|
||||
else if(base2 == -1 && new_bonus->CriticalHitChance[HIGHEST_SKILL+1] < effect_value)
|
||||
else if(base2 == ALL_SKILLS && new_bonus->CriticalHitChance[HIGHEST_SKILL+1] < effect_value)
|
||||
new_bonus->CriticalHitChance[HIGHEST_SKILL+1] = effect_value;
|
||||
else if(base2 != -1 && new_bonus->CriticalHitChance[base2] < effect_value)
|
||||
else if(base2 != ALL_SKILLS && new_bonus->CriticalHitChance[base2] < effect_value)
|
||||
new_bonus->CriticalHitChance[base2] = effect_value;
|
||||
|
||||
break;
|
||||
@@ -2018,7 +2021,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
|
||||
case SE_Vampirism:
|
||||
new_bonus->Vampirism += effect_value;
|
||||
break;
|
||||
break;
|
||||
|
||||
case SE_AllInstrumentMod:
|
||||
{
|
||||
@@ -2068,7 +2071,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
{
|
||||
if(new_bonus->MeleeSkillCheck < effect_value) {
|
||||
new_bonus->MeleeSkillCheck = effect_value;
|
||||
new_bonus->MeleeSkillCheckSkill = base2==-1?255:base2;
|
||||
new_bonus->MeleeSkillCheckSkill = base2==ALL_SKILLS?255:base2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2077,13 +2080,13 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
{
|
||||
|
||||
if (AdditiveWornBonus){
|
||||
if(base2 == -1)
|
||||
if(base2 == ALL_SKILLS)
|
||||
new_bonus->HitChanceEffect[HIGHEST_SKILL+1] += effect_value;
|
||||
else
|
||||
new_bonus->HitChanceEffect[base2] += effect_value;
|
||||
}
|
||||
|
||||
else if(base2 == -1){
|
||||
else if(base2 == ALL_SKILLS){
|
||||
|
||||
if ((effect_value < 0) && (new_bonus->HitChanceEffect[HIGHEST_SKILL+1] > effect_value))
|
||||
new_bonus->HitChanceEffect[HIGHEST_SKILL+1] = effect_value;
|
||||
@@ -2109,7 +2112,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
|
||||
case SE_DamageModifier:
|
||||
{
|
||||
if(base2 == -1)
|
||||
if(base2 == ALL_SKILLS)
|
||||
new_bonus->DamageModifier[HIGHEST_SKILL+1] += effect_value;
|
||||
else
|
||||
new_bonus->DamageModifier[base2] += effect_value;
|
||||
@@ -2118,7 +2121,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
|
||||
case SE_DamageModifier2:
|
||||
{
|
||||
if(base2 == -1)
|
||||
if(base2 == ALL_SKILLS)
|
||||
new_bonus->DamageModifier2[HIGHEST_SKILL+1] += effect_value;
|
||||
else
|
||||
new_bonus->DamageModifier2[base2] += effect_value;
|
||||
@@ -2127,7 +2130,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
|
||||
case SE_MinDamageModifier:
|
||||
{
|
||||
if(base2 == -1)
|
||||
if(base2 == ALL_SKILLS)
|
||||
new_bonus->MinDamageModifier[HIGHEST_SKILL+1] += effect_value;
|
||||
else
|
||||
new_bonus->MinDamageModifier[base2] += effect_value;
|
||||
@@ -2225,14 +2228,14 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
{
|
||||
//When using npc_spells_effects if MAX value set, use stackable quest based modifier.
|
||||
if (IsAISpellEffect && max){
|
||||
if(base2 == -1)
|
||||
if(base2 == ALL_SKILLS)
|
||||
SkillDmgTaken_Mod[HIGHEST_SKILL+1] = effect_value;
|
||||
else
|
||||
SkillDmgTaken_Mod[base2] = effect_value;
|
||||
}
|
||||
else {
|
||||
|
||||
if(base2 == -1)
|
||||
if(base2 == ALL_SKILLS)
|
||||
new_bonus->SkillDmgTaken[HIGHEST_SKILL+1] += effect_value;
|
||||
else
|
||||
new_bonus->SkillDmgTaken[base2] += effect_value;
|
||||
@@ -2261,7 +2264,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
case SE_CriticalSpellChance:
|
||||
{
|
||||
new_bonus->CriticalSpellChance += effect_value;
|
||||
|
||||
|
||||
if (base2 > new_bonus->SpellCritDmgIncNoStack)
|
||||
new_bonus->SpellCritDmgIncNoStack = base2;
|
||||
break;
|
||||
@@ -2341,7 +2344,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
|
||||
case SE_CriticalDamageMob:
|
||||
{
|
||||
if(base2 == -1)
|
||||
if(base2 == ALL_SKILLS)
|
||||
new_bonus->CritDmgMob[HIGHEST_SKILL+1] += effect_value;
|
||||
else
|
||||
new_bonus->CritDmgMob[base2] += effect_value;
|
||||
@@ -2357,7 +2360,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
|
||||
case SE_SkillDamageAmount:
|
||||
{
|
||||
if(base2 == -1)
|
||||
if(base2 == ALL_SKILLS)
|
||||
new_bonus->SkillDamageAmount[HIGHEST_SKILL+1] += effect_value;
|
||||
else
|
||||
new_bonus->SkillDamageAmount[base2] += effect_value;
|
||||
@@ -2462,7 +2465,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
|
||||
case SE_SkillDamageAmount2:
|
||||
{
|
||||
if(base2 == -1)
|
||||
if(base2 == ALL_SKILLS)
|
||||
new_bonus->SkillDamageAmount2[HIGHEST_SKILL+1] += effect_value;
|
||||
else
|
||||
new_bonus->SkillDamageAmount2[base2] += effect_value;
|
||||
@@ -2471,7 +2474,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
|
||||
case SE_NegateAttacks:
|
||||
{
|
||||
if (!new_bonus->NegateAttacks[0] ||
|
||||
if (!new_bonus->NegateAttacks[0] ||
|
||||
((new_bonus->NegateAttacks[0] && new_bonus->NegateAttacks[2]) && (new_bonus->NegateAttacks[2] < max))){
|
||||
new_bonus->NegateAttacks[0] = 1;
|
||||
new_bonus->NegateAttacks[1] = buffslot;
|
||||
@@ -2491,7 +2494,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
case SE_MeleeThresholdGuard:
|
||||
{
|
||||
if (new_bonus->MeleeThresholdGuard[0] < effect_value){
|
||||
@@ -2858,17 +2861,17 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
new_bonus->NegateIfCombat = true;
|
||||
break;
|
||||
|
||||
case SE_Screech:
|
||||
case SE_Screech:
|
||||
new_bonus->Screech = effect_value;
|
||||
break;
|
||||
|
||||
case SE_AlterNPCLevel:
|
||||
|
||||
if (IsNPC()){
|
||||
if (!new_bonus->AlterNPCLevel
|
||||
|| ((effect_value < 0) && (new_bonus->AlterNPCLevel > effect_value))
|
||||
if (!new_bonus->AlterNPCLevel
|
||||
|| ((effect_value < 0) && (new_bonus->AlterNPCLevel > effect_value))
|
||||
|| ((effect_value > 0) && (new_bonus->AlterNPCLevel < effect_value))) {
|
||||
|
||||
|
||||
int tmp_lv = GetOrigLevel() + effect_value;
|
||||
if (tmp_lv < 1)
|
||||
tmp_lv = 1;
|
||||
@@ -2906,7 +2909,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
new_bonus->BerserkSPA = true;
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case SE_Metabolism:
|
||||
new_bonus->Metabolism += effect_value;
|
||||
break;
|
||||
@@ -3007,7 +3010,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
}
|
||||
|
||||
case SE_SkillProc:{
|
||||
|
||||
|
||||
for(int e = 0; e < MAX_SKILL_PROCS; e++)
|
||||
{
|
||||
if(new_bonus->SkillProc[e] && new_bonus->SkillProc[e] == spell_id)
|
||||
@@ -3022,7 +3025,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
}
|
||||
|
||||
case SE_SkillProcSuccess:{
|
||||
|
||||
|
||||
for(int e = 0; e < MAX_SKILL_PROCS; e++)
|
||||
{
|
||||
if(new_bonus->SkillProcSuccess[e] && new_bonus->SkillProcSuccess[e] == spell_id)
|
||||
@@ -3038,9 +3041,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
|
||||
//Special custom cases for loading effects on to NPC from 'npc_spels_effects' table
|
||||
if (IsAISpellEffect) {
|
||||
|
||||
|
||||
//Non-Focused Effect to modify incoming spell damage by resist type.
|
||||
case SE_FcSpellVulnerability:
|
||||
case SE_FcSpellVulnerability:
|
||||
ModVulnerability(base2, effect_value);
|
||||
break;
|
||||
}
|
||||
@@ -4392,7 +4395,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
|
||||
aabonuses.SlayUndead[0] = effect_value;
|
||||
aabonuses.SlayUndead[1] = effect_value;
|
||||
break;
|
||||
|
||||
|
||||
case SE_DoubleRangedAttack:
|
||||
spellbonuses.DoubleRangedAttack = effect_value;
|
||||
aabonuses.DoubleRangedAttack = effect_value;
|
||||
@@ -4412,7 +4415,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
|
||||
aabonuses.ShieldEquipDmgMod[1] = effect_value;
|
||||
itembonuses.ShieldEquipDmgMod[0] = effect_value;
|
||||
itembonuses.ShieldEquipDmgMod[1] = effect_value;
|
||||
break;
|
||||
break;
|
||||
|
||||
case SE_TriggerMeleeThreshold:
|
||||
spellbonuses.TriggerMeleeThreshold = false;
|
||||
|
||||
+3123
-5754
File diff suppressed because it is too large
Load Diff
+10
-4
@@ -60,6 +60,7 @@ enum SpellTypeIndex {
|
||||
};
|
||||
|
||||
class Bot : public NPC {
|
||||
friend class Mob;
|
||||
public:
|
||||
// Class enums
|
||||
enum BotfocusType { //focus types
|
||||
@@ -154,7 +155,7 @@ public:
|
||||
// Class Methods
|
||||
bool IsValidRaceClassCombo();
|
||||
bool IsValidName();
|
||||
bool IsBotNameAvailable(std::string* errorMessage);
|
||||
static bool IsBotNameAvailable(char *botName, std::string* errorMessage);
|
||||
bool DeleteBot(std::string* errorMessage);
|
||||
void Spawn(Client* botCharacterOwner, std::string* errorMessage);
|
||||
virtual void SetLevel(uint8 in_level, bool command = false);
|
||||
@@ -190,7 +191,9 @@ public:
|
||||
bool CanDoSpecialAttack(Mob *other);
|
||||
virtual int32 CheckAggroAmount(uint16 spellid);
|
||||
virtual void CalcBonuses();
|
||||
void CalcItemBonuses();
|
||||
void CalcItemBonuses(StatBonuses* newbon);
|
||||
void AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false);
|
||||
int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat);
|
||||
virtual void MakePet(uint16 spell_id, const char* pettype, const char *petname = nullptr);
|
||||
virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther);
|
||||
inline virtual bool IsPet() { return false; }
|
||||
@@ -310,7 +313,7 @@ public:
|
||||
virtual int32 GetActSpellDuration(uint16 spell_id, int32 duration);
|
||||
virtual float GetAOERange(uint16 spell_id);
|
||||
virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100);
|
||||
virtual void DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caster_level, Mob* caster = 0);
|
||||
virtual void DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster = nullptr);
|
||||
virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr);
|
||||
virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar);
|
||||
virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster);
|
||||
@@ -332,7 +335,7 @@ public:
|
||||
void EquipBot(std::string* errorMessage);
|
||||
bool CheckLoreConflict(const Item_Struct* item);
|
||||
uint32 GetEquipmentColor(uint8 material_slot) const;
|
||||
virtual void UpdateEquipLightValue() { equip_light = m_inv.FindHighestLightValue(); }
|
||||
virtual void UpdateEquipmentLight() { m_Light.Type.Equipment = m_inv.FindBrightestLightType(); m_Light.Level.Equipment = m_Light.TypeToLevel(m_Light.Type.Equipment); }
|
||||
|
||||
// Static Class Methods
|
||||
static void SaveBotGroup(Group* botGroup, std::string botGroupName, std::string* errorMessage);
|
||||
@@ -464,6 +467,7 @@ public:
|
||||
uint32 GetHealRotationNextHealTime() { return _healRotationNextHeal; }
|
||||
uint32 GetHealRotationTimer () { return _healRotationTimer; }
|
||||
bool GetBardUseOutOfCombatSongs() { return _bardUseOutOfCombatSongs;}
|
||||
bool GetShowHelm() { return _showhelm; }
|
||||
inline virtual int32 GetAC() const { return AC; }
|
||||
inline virtual int32 GetSTR() const { return STR; }
|
||||
inline virtual int32 GetSTA() const { return STA; }
|
||||
@@ -547,6 +551,7 @@ public:
|
||||
void SetHealRotationTimer( uint32 timer ) { _healRotationTimer = timer; }
|
||||
void SetNumHealRotationMembers( uint8 numMembers ) { _numHealRotationMembers = numMembers; }
|
||||
void SetBardUseOutOfCombatSongs(bool useOutOfCombatSongs) { _bardUseOutOfCombatSongs = useOutOfCombatSongs;}
|
||||
void SetShowHelm(bool showhelm) { _showhelm = showhelm; }
|
||||
|
||||
// Class Destructors
|
||||
virtual ~Bot();
|
||||
@@ -619,6 +624,7 @@ private:
|
||||
std::map<uint32, BotAA> botAAs;
|
||||
InspectMessage_Struct _botInspectMessage;
|
||||
bool _bardUseOutOfCombatSongs;
|
||||
bool _showhelm;
|
||||
|
||||
// Private "base stats" Members
|
||||
int32 _baseMR;
|
||||
|
||||
+145
-78
@@ -107,12 +107,16 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
0,
|
||||
0, // qglobal
|
||||
0, // maxlevel
|
||||
0 // scalerate
|
||||
|
||||
0, // scalerate
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
),
|
||||
//these must be listed in the order they appear in client.h
|
||||
position_timer(250),
|
||||
hpupdate_timer(1800),
|
||||
hpupdate_timer(2000),
|
||||
camp_timer(29000),
|
||||
process_timer(100),
|
||||
stamina_timer(40000),
|
||||
@@ -165,6 +169,7 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
Trader=false;
|
||||
Buyer = false;
|
||||
CustomerID = 0;
|
||||
TraderID = 0;
|
||||
TrackingID = 0;
|
||||
WID = 0;
|
||||
account_id = 0;
|
||||
@@ -203,6 +208,7 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
npclevel = 0;
|
||||
pQueuedSaveWorkID = 0;
|
||||
position_timer_counter = 0;
|
||||
position_update_same_count = 0;
|
||||
fishing_timer.Disable();
|
||||
shield_timer.Disable();
|
||||
dead_timer.Disable();
|
||||
@@ -249,7 +255,7 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
AttemptedMessages = 0;
|
||||
TotalKarma = 0;
|
||||
m_ClientVersion = ClientVersion::Unknown;
|
||||
ClientVersionBit = 0;
|
||||
m_ClientVersionBit = 0;
|
||||
AggroCount = 0;
|
||||
RestRegenHP = 0;
|
||||
RestRegenMana = 0;
|
||||
@@ -307,9 +313,6 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
|
||||
interrogateinv_flag = false;
|
||||
|
||||
active_light = innate_light;
|
||||
spell_light = equip_light = NOT_USED;
|
||||
|
||||
AI_Init();
|
||||
}
|
||||
|
||||
@@ -547,17 +550,22 @@ bool Client::SaveAA(){
|
||||
}
|
||||
}
|
||||
m_pp.aapoints_spent = spentpoints + m_epp.expended_aa;
|
||||
int highest = 0;
|
||||
for (int a = 0; a < MAX_PP_AA_ARRAY; a++) {
|
||||
if (aa[a]->AA > 0 && aa[a]->value){
|
||||
if (aa[a]->AA > 0) { // those with value 0 will be cleaned up on next load
|
||||
if (first_entry != 1){
|
||||
rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value)"
|
||||
" VALUES (%u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value);
|
||||
rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value, charges)"
|
||||
" VALUES (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges);
|
||||
first_entry = 1;
|
||||
} else {
|
||||
rquery = rquery + StringFormat(", (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges);
|
||||
}
|
||||
rquery = rquery + StringFormat(", (%u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value);
|
||||
highest = a;
|
||||
}
|
||||
}
|
||||
auto results = database.QueryDatabase(rquery);
|
||||
/* This is another part of the hack to clean up holes left by expendable AAs */
|
||||
rquery = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u AND `slot` > %d", character_id, highest);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1049,12 +1057,12 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
if(quest_manager.ProximitySayInUse())
|
||||
entity_list.ProcessProximitySay(message, this, language);
|
||||
|
||||
if (GetTarget() != 0 && GetTarget()->IsNPC()) {
|
||||
if (GetTarget() != 0 && GetTarget()->IsNPC() &&
|
||||
!IsInvisible(GetTarget())) {
|
||||
if(!GetTarget()->CastToNPC()->IsEngaged()) {
|
||||
CheckLDoNHail(GetTarget());
|
||||
CheckEmoteHail(GetTarget(), message);
|
||||
|
||||
|
||||
if(DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) <= 200) {
|
||||
NPC *tar = GetTarget()->CastToNPC();
|
||||
parse->EventNPC(EVENT_SAY, tar->CastToNPC(), this, message, language);
|
||||
@@ -1868,9 +1876,9 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
|
||||
ns->spawn.runspeed = (gmspeed == 0) ? runspeed : 3.125f;
|
||||
ns->spawn.showhelm = m_pp.showhelm ? 1 : 0;
|
||||
|
||||
UpdateEquipLightValue();
|
||||
UpdateActiveLightValue();
|
||||
ns->spawn.light = active_light;
|
||||
UpdateEquipmentLight();
|
||||
UpdateActiveLight();
|
||||
ns->spawn.light = m_Light.Type.Active;
|
||||
}
|
||||
|
||||
bool Client::GMHideMe(Client* client) {
|
||||
@@ -2538,12 +2546,12 @@ void Client::LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32
|
||||
|
||||
bool Client::BindWound(Mob* bindmob, bool start, bool fail){
|
||||
EQApplicationPacket* outapp = 0;
|
||||
if(!fail)
|
||||
if(!fail)
|
||||
{
|
||||
outapp = new EQApplicationPacket(OP_Bind_Wound, sizeof(BindWound_Struct));
|
||||
BindWound_Struct* bind_out = (BindWound_Struct*) outapp->pBuffer;
|
||||
// Start bind
|
||||
if(!bindwound_timer.Enabled())
|
||||
if(!bindwound_timer.Enabled())
|
||||
{
|
||||
//make sure we actually have a bandage... and consume it.
|
||||
int16 bslot = m_inv.HasItemByUse(ItemTypeBandage, 1, invWhereWorn|invWherePersonal);
|
||||
@@ -2590,9 +2598,9 @@ bool Client::BindWound(Mob* bindmob, bool start, bool fail){
|
||||
; // Binding self
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bindwound_timer.Check()) // Did the timer finish?
|
||||
{
|
||||
{
|
||||
// finish bind
|
||||
// disable complete timer
|
||||
bindwound_timer.Disable();
|
||||
@@ -3038,7 +3046,7 @@ void Client::Tell_StringID(uint32 string_id, const char *who, const char *messag
|
||||
|
||||
void Client::SetTint(int16 in_slot, uint32 color) {
|
||||
Color_Struct new_color;
|
||||
new_color.color = color;
|
||||
new_color.Color = color;
|
||||
SetTint(in_slot, new_color);
|
||||
database.SaveCharacterMaterialColor(this->CharacterID(), in_slot, color);
|
||||
}
|
||||
@@ -3049,8 +3057,8 @@ void Client::SetTint(int16 in_slot, Color_Struct& color) {
|
||||
uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot);
|
||||
if (matslot != _MaterialInvalid)
|
||||
{
|
||||
m_pp.item_tint[matslot].color = color.color;
|
||||
database.SaveCharacterMaterialColor(this->CharacterID(), in_slot, color.color);
|
||||
m_pp.item_tint[matslot].Color = color.Color;
|
||||
database.SaveCharacterMaterialColor(this->CharacterID(), in_slot, color.Color);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4989,7 +4997,7 @@ void Client::SetShadowStepExemption(bool v)
|
||||
if((cur_time - m_TimeSinceLastPositionCheck) > 1000)
|
||||
{
|
||||
float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck);
|
||||
float runs = GetRunspeed();
|
||||
int runs = GetRunspeed();
|
||||
if(speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor)))
|
||||
{
|
||||
printf("%s %i moving too fast! moved: %.2f in %ims, speed %.2f\n", __FILE__, __LINE__,
|
||||
@@ -5046,7 +5054,7 @@ void Client::SetKnockBackExemption(bool v)
|
||||
if((cur_time - m_TimeSinceLastPositionCheck) > 1000)
|
||||
{
|
||||
float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck);
|
||||
float runs = GetRunspeed();
|
||||
int runs = GetRunspeed();
|
||||
if(speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor)))
|
||||
{
|
||||
if(!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor)))))
|
||||
@@ -5103,7 +5111,7 @@ void Client::SetPortExemption(bool v)
|
||||
if((cur_time - m_TimeSinceLastPositionCheck) > 1000)
|
||||
{
|
||||
float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck);
|
||||
float runs = GetRunspeed();
|
||||
int runs = GetRunspeed();
|
||||
if(speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor)))
|
||||
{
|
||||
if(!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor)))))
|
||||
@@ -5361,35 +5369,35 @@ void Client::SendRewards()
|
||||
FastQueuePacket(&vetapp);
|
||||
}
|
||||
|
||||
bool Client::TryReward(uint32 claim_id) {
|
||||
//Make sure we have an open spot
|
||||
//Make sure we have it in our acct and count > 0
|
||||
//Make sure the entry was found
|
||||
//If we meet all the criteria:
|
||||
//Decrement our count by 1 if it > 1 delete if it == 1
|
||||
//Create our item in bag if necessary at the free inv slot
|
||||
//save
|
||||
bool Client::TryReward(uint32 claim_id)
|
||||
{
|
||||
// Make sure we have an open spot
|
||||
// Make sure we have it in our acct and count > 0
|
||||
// Make sure the entry was found
|
||||
// If we meet all the criteria:
|
||||
// Decrement our count by 1 if it > 1 delete if it == 1
|
||||
// Create our item in bag if necessary at the free inv slot
|
||||
// save
|
||||
uint32 free_slot = 0xFFFFFFFF;
|
||||
|
||||
for(int i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_END; ++i) {
|
||||
for (int i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_END; ++i) {
|
||||
ItemInst *item = GetInv().GetItem(i);
|
||||
if(!item) {
|
||||
if (!item) {
|
||||
free_slot = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(free_slot == 0xFFFFFFFF)
|
||||
if (free_slot == 0xFFFFFFFF)
|
||||
return false;
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
std::string query = StringFormat("SELECT amount FROM account_rewards "
|
||||
"WHERE account_id = %i AND reward_id = %i",
|
||||
AccountID(), claim_id);
|
||||
"WHERE account_id = %i AND reward_id = %i",
|
||||
AccountID(), claim_id);
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
if (!results.Success())
|
||||
return false;
|
||||
}
|
||||
|
||||
if (results.RowCount() == 0)
|
||||
return false;
|
||||
@@ -5397,58 +5405,57 @@ bool Client::TryReward(uint32 claim_id) {
|
||||
auto row = results.begin();
|
||||
|
||||
uint32 amt = atoi(row[0]);
|
||||
if(amt == 0)
|
||||
if (amt == 0)
|
||||
return false;
|
||||
|
||||
std::list<InternalVeteranReward>::iterator iter = zone->VeteranRewards.begin();
|
||||
for (; iter != zone->VeteranRewards.end(); ++row)
|
||||
if((*iter).claim_id == claim_id)
|
||||
break;
|
||||
auto iter = std::find_if(zone->VeteranRewards.begin(), zone->VeteranRewards.end(),
|
||||
[claim_id](const InternalVeteranReward &a) { return a.claim_id == claim_id; });
|
||||
|
||||
if(iter == zone->VeteranRewards.end())
|
||||
if (iter == zone->VeteranRewards.end())
|
||||
return false;
|
||||
|
||||
if(amt == 1) {
|
||||
if (amt == 1) {
|
||||
query = StringFormat("DELETE FROM account_rewards "
|
||||
"WHERE account_id = %i AND reward_id = %i",
|
||||
AccountID(), claim_id);
|
||||
"WHERE account_id = %i AND reward_id = %i",
|
||||
AccountID(), claim_id);
|
||||
auto results = database.QueryDatabase(query);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
query = StringFormat("UPDATE account_rewards SET amount = (amount-1) "
|
||||
"WHERE account_id = %i AND reward_id = %i",
|
||||
AccountID(), claim_id);
|
||||
"WHERE account_id = %i AND reward_id = %i",
|
||||
AccountID(), claim_id);
|
||||
auto results = database.QueryDatabase(query);
|
||||
}
|
||||
|
||||
InternalVeteranReward ivr = (*iter);
|
||||
auto &ivr = (*iter);
|
||||
ItemInst *claim = database.CreateItem(ivr.items[0].item_id, ivr.items[0].charges);
|
||||
if(!claim) {
|
||||
if (!claim) {
|
||||
Save();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lore_conflict = CheckLoreConflict(claim->GetItem());
|
||||
|
||||
for(int y = 1; y < 8; y++)
|
||||
if(ivr.items[y].item_id && claim->GetItem()->ItemClass == 1) {
|
||||
for (int y = 1; y < 8; y++)
|
||||
if (ivr.items[y].item_id && claim->GetItem()->ItemClass == 1) {
|
||||
ItemInst *item_temp = database.CreateItem(ivr.items[y].item_id, ivr.items[y].charges);
|
||||
if(item_temp) {
|
||||
if(CheckLoreConflict(item_temp->GetItem())) {
|
||||
if (item_temp) {
|
||||
if (CheckLoreConflict(item_temp->GetItem())) {
|
||||
lore_conflict = true;
|
||||
DuplicateLoreMessage(ivr.items[y].item_id);
|
||||
}
|
||||
claim->PutItem(y-1, *item_temp);
|
||||
claim->PutItem(y - 1, *item_temp);
|
||||
safe_delete(item_temp);
|
||||
}
|
||||
}
|
||||
|
||||
if(lore_conflict) {
|
||||
if (lore_conflict) {
|
||||
safe_delete(claim);
|
||||
return true;
|
||||
}
|
||||
|
||||
PutItemInInventory(free_slot, *claim);
|
||||
SendItemPacket(free_slot, claim, ItemPacketTrade);
|
||||
safe_delete(claim);
|
||||
|
||||
Save();
|
||||
return true;
|
||||
@@ -5708,8 +5715,8 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) {
|
||||
else if (inst && inst->GetOrnamentationIcon())
|
||||
{
|
||||
insr->itemicons[L] = inst->GetOrnamentationIcon();
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
insr->itemicons[L] = item->Icon;
|
||||
}
|
||||
@@ -6220,6 +6227,8 @@ void Client::DragCorpses()
|
||||
!corpse->CastToCorpse()->Summon(this, false, false)) {
|
||||
Message_StringID(MT_DefaultText, CORPSEDRAG_STOP);
|
||||
It = DraggedCorpses.erase(It);
|
||||
if (It == DraggedCorpses.end())
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6244,7 +6253,7 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid
|
||||
|
||||
NPCType *made_npc = nullptr;
|
||||
|
||||
const NPCType *npc_type = database.GetNPCType(pet.npc_id);
|
||||
const NPCType *npc_type = database.LoadNPCTypesData(pet.npc_id);
|
||||
if(npc_type == nullptr) {
|
||||
Log.Out(Logs::General, Logs::Error, "Unknown npc type for doppelganger spell id: %d", spell_id);
|
||||
Message(0,"Unable to find pet!");
|
||||
@@ -7467,7 +7476,7 @@ void Client::SendClearMercInfo()
|
||||
|
||||
void Client::DuplicateLoreMessage(uint32 ItemID)
|
||||
{
|
||||
if(!(ClientVersionBit & BIT_RoFAndLater))
|
||||
if (!(m_ClientVersionBit & BIT_RoFAndLater))
|
||||
{
|
||||
Message_StringID(0, PICK_LORE);
|
||||
return;
|
||||
@@ -7488,6 +7497,10 @@ void Client::GarbleMessage(char *message, uint8 variance)
|
||||
const char delimiter = 0x12;
|
||||
int delimiter_count = 0;
|
||||
|
||||
// Don't garble # commands
|
||||
if (message[0] == '#')
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < strlen(message); i++) {
|
||||
// Client expects hex values inside of a text link body
|
||||
if (message[i] == delimiter) {
|
||||
@@ -7497,7 +7510,7 @@ void Client::GarbleMessage(char *message, uint8 variance)
|
||||
}
|
||||
|
||||
uint8 chance = (uint8)zone->random.Int(0, 115); // variation just over worst possible scrambling
|
||||
if (isalpha(message[i]) && (chance <= variance)) {
|
||||
if (isalpha((unsigned char)message[i]) && (chance <= variance)) {
|
||||
uint8 rand_char = (uint8)zone->random.Int(0,51); // choose a random character from the alpha list
|
||||
message[i] = alpha_list[rand_char];
|
||||
}
|
||||
@@ -7581,7 +7594,7 @@ FACTION_VALUE Client::GetFactionLevel(uint32 char_id, uint32 npc_id, uint32 p_ra
|
||||
}
|
||||
|
||||
//Sets the characters faction standing with the specified NPC.
|
||||
void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, uint8 char_race, uint8 char_deity)
|
||||
void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, uint8 char_race, uint8 char_deity, bool quest)
|
||||
{
|
||||
int32 faction_id[MAX_NPC_FACTIONS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
int32 npc_value[MAX_NPC_FACTIONS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
@@ -7605,9 +7618,18 @@ void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, ui
|
||||
// Find out starting faction for this faction
|
||||
// It needs to be used to adj max and min personal
|
||||
// The range is still the same, 1200-3000(4200), but adjusted for base
|
||||
database.GetFactionData(&fm, GetClass(), GetRace(), GetDeity(),
|
||||
database.GetFactionData(&fm, GetClass(), GetRace(), GetDeity(),
|
||||
faction_id[i]);
|
||||
|
||||
if (quest)
|
||||
{
|
||||
//The ole switcheroo
|
||||
if (npc_value[i] > 0)
|
||||
npc_value[i] = -abs(npc_value[i]);
|
||||
else if (npc_value[i] < 0)
|
||||
npc_value[i] = abs(npc_value[i]);
|
||||
}
|
||||
|
||||
// Adjust the amount you can go up or down so the resulting range
|
||||
// is PERSONAL_MAX - PERSONAL_MIN
|
||||
//
|
||||
@@ -7646,7 +7668,7 @@ void Client::SetFactionLevel2(uint32 char_id, int32 faction_id, uint8 char_class
|
||||
// Find out starting faction for this faction
|
||||
// It needs to be used to adj max and min personal
|
||||
// The range is still the same, 1200-3000(4200), but adjusted for base
|
||||
database.GetFactionData(&fm, GetClass(), GetRace(), GetDeity(),
|
||||
database.GetFactionData(&fm, GetClass(), GetRace(), GetDeity(),
|
||||
faction_id);
|
||||
|
||||
// Adjust the amount you can go up or down so the resulting range
|
||||
@@ -7764,7 +7786,8 @@ void Client::MerchantRejectMessage(Mob *merchant, int primaryfaction)
|
||||
if (primaryfaction > 0) {
|
||||
if (database.GetFactionData(&fmod, GetClass(), GetRace(), GetDeity(), primaryfaction)) {
|
||||
tmpFactionValue = GetCharacterFactionLevel(primaryfaction);
|
||||
lowestvalue = std::min(tmpFactionValue, std::min(fmod.class_mod, fmod.race_mod));
|
||||
lowestvalue = std::min(std::min(tmpFactionValue, fmod.deity_mod),
|
||||
std::min(fmod.class_mod, fmod.race_mod));
|
||||
}
|
||||
}
|
||||
// If no primary faction or biggest influence is your faction hit
|
||||
@@ -7812,6 +7835,11 @@ void Client::MerchantRejectMessage(Mob *merchant, int primaryfaction)
|
||||
}
|
||||
} else if (lowestvalue == fmod.class_mod) {
|
||||
merchant->Say_StringID(zone->random.Int(WONT_SELL_CLASS1, WONT_SELL_CLASS5), itoa(GetClass()));
|
||||
} else {
|
||||
// Must be deity - these two sound the best for that.
|
||||
// Can't use a message with a field, GUI wants class/race names.
|
||||
// for those message IDs. These are straight text.
|
||||
merchant->Say_StringID(zone->random.Int(WONT_SELL_DEEDS1, WONT_SELL_DEEDS2));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -7826,14 +7854,14 @@ void Client::SendFactionMessage(int32 tmpvalue, int32 faction_id, int32 faction_
|
||||
char name[50];
|
||||
int32 faction_value;
|
||||
|
||||
// If we're dropping from MAX or raising from MIN or repairing,
|
||||
// If we're dropping from MAX or raising from MIN or repairing,
|
||||
// we should base the message on the new updated value so we don't show
|
||||
// a min MAX message
|
||||
//
|
||||
// If we're changing any other place, we use the value before the
|
||||
// hit. For example, if we go from 1199 to 1200 which is the MAX
|
||||
// we still want to say faction got better this time around.
|
||||
|
||||
|
||||
if ( (faction_before_hit >= this_faction_max) ||
|
||||
(faction_before_hit <= this_faction_min))
|
||||
faction_value = totalvalue;
|
||||
@@ -8369,10 +8397,10 @@ std::string Client::TextLink::GenerateLink()
|
||||
m_Link.clear();
|
||||
m_LinkBody.clear();
|
||||
m_LinkText.clear();
|
||||
|
||||
|
||||
generate_body();
|
||||
generate_text();
|
||||
|
||||
|
||||
if ((m_LinkBody.length() == EmuConstants::TEXT_LINK_BODY_LENGTH) && (m_LinkText.length() > 0)) {
|
||||
m_Link.push_back(0x12);
|
||||
m_Link.append(m_LinkBody);
|
||||
@@ -8411,7 +8439,7 @@ void Client::TextLink::generate_body()
|
||||
{
|
||||
/*
|
||||
Current server mask: EQClientRoF2
|
||||
|
||||
|
||||
RoF2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X" (56)
|
||||
RoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" (55)
|
||||
SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" (50)
|
||||
@@ -8419,7 +8447,7 @@ void Client::TextLink::generate_body()
|
||||
*/
|
||||
|
||||
memset(&m_LinkBodyStruct, 0, sizeof(TextLinkBody_Struct));
|
||||
|
||||
|
||||
const Item_Struct* item_data = nullptr;
|
||||
|
||||
switch (m_LinkType) {
|
||||
@@ -8466,7 +8494,7 @@ void Client::TextLink::generate_body()
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (m_ProxyItemID != NOT_USED) {
|
||||
m_LinkBodyStruct.item_id = m_ProxyItemID;
|
||||
}
|
||||
@@ -8571,3 +8599,42 @@ bool Client::TextLink::GenerateLinkBody(std::string& textLinkBody, const TextLin
|
||||
if (textLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp, bool faction) {
|
||||
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_Sound, sizeof(QuestReward_Struct));
|
||||
memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer));
|
||||
QuestReward_Struct* qr = (QuestReward_Struct*)outapp->pBuffer;
|
||||
|
||||
qr->mob_id = target->GetID(); // Entity ID for the from mob name
|
||||
qr->target_id = GetID(); // The Client ID (this)
|
||||
qr->copper = copper;
|
||||
qr->silver = silver;
|
||||
qr->gold = gold;
|
||||
qr->platinum = platinum;
|
||||
qr->item_id = itemid;
|
||||
qr->exp_reward = exp;
|
||||
|
||||
if (copper > 0 || silver > 0 || gold > 0 || platinum > 0)
|
||||
AddMoneyToPP(copper, silver, gold, platinum, false);
|
||||
|
||||
if (itemid > 0)
|
||||
SummonItem(itemid, 0, 0, 0, 0, 0, 0, false, MainPowerSource);
|
||||
|
||||
if (faction)
|
||||
{
|
||||
if (target->IsNPC())
|
||||
{
|
||||
int32 nfl_id = target->CastToNPC()->GetNPCFactionID();
|
||||
SetFactionLevel(CharacterID(), nfl_id, GetBaseClass(), GetBaseRace(), GetDeity(), true);
|
||||
qr->faction = target->CastToNPC()->GetPrimaryFaction();
|
||||
qr->faction_mod = 1; // Too lazy to get real value, not sure if this is even used by client anyhow.
|
||||
}
|
||||
}
|
||||
|
||||
if (exp > 0)
|
||||
AddEXP(exp);
|
||||
|
||||
QueuePacket(outapp, false, Client::CLIENT_CONNECTED);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
+21
-8
@@ -266,10 +266,11 @@ public:
|
||||
void SendBazaarResults(uint32 trader_id,uint32 class_,uint32 race,uint32 stat,uint32 slot,uint32 type,char name[64],uint32 minprice,uint32 maxprice);
|
||||
void SendTraderItem(uint32 item_id,uint16 quantity);
|
||||
uint16 FindTraderItem(int32 SerialNumber,uint16 Quantity);
|
||||
uint32 FindTraderItemSerialNumber(int32 ItemID);
|
||||
ItemInst* FindTraderItemBySerialNumber(int32 SerialNumber);
|
||||
void FindAndNukeTraderItem(int32 item_id,uint16 quantity,Client* customer,uint16 traderslot);
|
||||
void NukeTraderItem(uint16 slot,int16 charges,uint16 quantity,Client* customer,uint16 traderslot, int uniqueid);
|
||||
void ReturnTraderReq(const EQApplicationPacket* app,int16 traderitemcharges);
|
||||
void NukeTraderItem(uint16 slot, int16 charges, uint16 quantity, Client* customer, uint16 traderslot, int32 uniqueid, int32 itemid = 0);
|
||||
void ReturnTraderReq(const EQApplicationPacket* app,int16 traderitemcharges, uint32 itemid = 0);
|
||||
void TradeRequestFailed(const EQApplicationPacket* app);
|
||||
void BuyTraderItem(TraderBuy_Struct* tbs,Client* trader,const EQApplicationPacket* app);
|
||||
void TraderUpdate(uint16 slot_id,uint32 trader_id);
|
||||
@@ -556,6 +557,7 @@ public:
|
||||
void SendCrystalCounts();
|
||||
|
||||
void AddEXP(uint32 in_add_exp, uint8 conlevel = 0xFF, bool resexp = false);
|
||||
uint32 CalcEXP(uint8 conlevel = 0xFF);
|
||||
void SetEXP(uint32 set_exp, uint32 set_aaxp, bool resexp=false);
|
||||
void AddLevelBasedExp(uint8 exp_percentage, uint8 max_level=0);
|
||||
void SetLeadershipEXP(uint32 group_exp, uint32 raid_exp);
|
||||
@@ -610,7 +612,7 @@ public:
|
||||
void SendFactionMessage(int32 tmpvalue, int32 faction_id, int32 faction_before_hit, int32 totalvalue, uint8 temp, int32 this_faction_min, int32 this_faction_max);
|
||||
|
||||
void UpdatePersonalFaction(int32 char_id, int32 npc_value, int32 faction_id, int32 *current_value, int32 temp, int32 this_faction_min, int32 this_faction_max);
|
||||
void SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, uint8 char_race, uint8 char_deity);
|
||||
void SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, uint8 char_race, uint8 char_deity, bool quest = false);
|
||||
void SetFactionLevel2(uint32 char_id, int32 faction_id, uint8 char_class, uint8 char_race, uint8 char_deity, int32 value, uint8 temp);
|
||||
int32 GetRawItemAC();
|
||||
uint16 GetCombinedAC_TEST();
|
||||
@@ -730,7 +732,7 @@ public:
|
||||
#endif
|
||||
uint32 GetEquipment(uint8 material_slot) const; // returns item id
|
||||
uint32 GetEquipmentColor(uint8 material_slot) const;
|
||||
virtual void UpdateEquipLightValue() { equip_light = m_inv.FindHighestLightValue(); }
|
||||
virtual void UpdateEquipmentLight() { m_Light.Type.Equipment = m_inv.FindBrightestLightType(); m_Light.Level.Equipment = m_Light.TypeToLevel(m_Light.Type.Equipment); }
|
||||
|
||||
inline bool AutoSplitEnabled() { return m_pp.autosplit != 0; }
|
||||
|
||||
@@ -904,6 +906,7 @@ public:
|
||||
bool DecreaseByID(uint32 type, uint8 amt);
|
||||
uint8 SlotConvert2(uint8 slot); //Maybe not needed.
|
||||
void Escape(); //AA Escape
|
||||
void DisenchantSummonedBags(bool client_update = true);
|
||||
void RemoveNoRent(bool client_update = true);
|
||||
void RemoveDuplicateLore(bool client_update = true);
|
||||
void MoveSlotNotAllowed(bool client_update = true);
|
||||
@@ -1021,7 +1024,7 @@ public:
|
||||
inline int CompletedTasksInSet(int TaskSet) { return (taskstate ? taskstate->CompletedTasksInSet(TaskSet) :0); }
|
||||
|
||||
inline const ClientVersion GetClientVersion() const { return m_ClientVersion; }
|
||||
inline const uint32 GetClientVersionBit() const { return ClientVersionBit; }
|
||||
inline const uint32 GetClientVersionBit() const { return m_ClientVersionBit; }
|
||||
inline void SetClientVersion(ClientVersion in) { m_ClientVersion = in; }
|
||||
|
||||
/** Adventure Stuff **/
|
||||
@@ -1128,6 +1131,7 @@ public:
|
||||
inline bool IsDraggingCorpse() { return (DraggedCorpses.size() > 0); }
|
||||
void DragCorpses();
|
||||
inline void ClearDraggedCorpses() { DraggedCorpses.clear(); }
|
||||
inline void ResetPositionTimer() { position_timer_counter = 0; }
|
||||
void SendAltCurrencies();
|
||||
void SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount);
|
||||
void AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 method = 0);
|
||||
@@ -1139,7 +1143,7 @@ public:
|
||||
void HandleLFGuildResponse(ServerPacket *pack);
|
||||
void SendLFGuildStatus();
|
||||
void SendGuildLFGuildStatus();
|
||||
inline bool XTargettingAvailable() const { return ((ClientVersionBit & BIT_UFAndLater) && RuleB(Character, EnableXTargetting)); }
|
||||
inline bool XTargettingAvailable() const { return ((m_ClientVersionBit & BIT_UFAndLater) && RuleB(Character, EnableXTargetting)); }
|
||||
inline uint8 GetMaxXTargets() const { return MaxXTargets; }
|
||||
void SetMaxXTargets(uint8 NewMax);
|
||||
bool IsXTarget(const Mob *m) const;
|
||||
@@ -1253,6 +1257,9 @@ public:
|
||||
virtual int32 Tune_GetMeleeMitDmg(Mob* GM, Mob *attacker, int32 damage, int32 minhit, float mit_rating, float atk_rating);
|
||||
int32 GetMeleeDamage(Mob* other, bool GetMinDamage = false);
|
||||
|
||||
void QuestReward(Mob* target, uint32 copper = 0, uint32 silver = 0, uint32 gold = 0, uint32 platinum = 0, uint32 itemid = 0, uint32 exp = 0, bool faction = false);
|
||||
|
||||
void ResetHPUpdateTimer() { hpupdate_timer.Start(); }
|
||||
protected:
|
||||
friend class Mob;
|
||||
void CalcItemBonuses(StatBonuses* newbon);
|
||||
@@ -1262,11 +1269,12 @@ protected:
|
||||
void CalcEdibleBonuses(StatBonuses* newbon);
|
||||
void CalcAABonuses(StatBonuses* newbon);
|
||||
void ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon);
|
||||
void ProcessItemCaps();
|
||||
void MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message = true);
|
||||
bool client_data_loaded;
|
||||
|
||||
int16 GetFocusEffect(focusType type, uint16 spell_id);
|
||||
int16 GetSympatheticFocusEffect(focusType type, uint16 spell_id);
|
||||
uint16 GetSympatheticFocusEffect(focusType type, uint16 spell_id);
|
||||
|
||||
Mob* bind_sight_target;
|
||||
|
||||
@@ -1315,6 +1323,7 @@ private:
|
||||
int32 GetACMit();
|
||||
int32 GetACAvoid();
|
||||
int32 CalcATK();
|
||||
int32 CalcItemATKCap();
|
||||
int32 CalcHaste();
|
||||
|
||||
int32 CalcAlcoholPhysicalEffect();
|
||||
@@ -1388,6 +1397,7 @@ private:
|
||||
uint16 BoatID;
|
||||
uint16 TrackingID;
|
||||
uint16 CustomerID;
|
||||
uint16 TraderID;
|
||||
uint32 account_creation;
|
||||
uint8 firstlogon;
|
||||
uint32 mercid; // current merc
|
||||
@@ -1437,6 +1447,9 @@ private:
|
||||
Timer position_timer;
|
||||
uint8 position_timer_counter;
|
||||
|
||||
// this is used to try to cut back on position update reflections
|
||||
int position_update_same_count;
|
||||
|
||||
PTimerList p_timers; //persistent timers
|
||||
Timer hpupdate_timer;
|
||||
Timer camp_timer;
|
||||
@@ -1515,7 +1528,7 @@ private:
|
||||
uint32 AttemptedMessages;
|
||||
|
||||
ClientVersion m_ClientVersion;
|
||||
uint32 ClientVersionBit;
|
||||
uint32 m_ClientVersionBit;
|
||||
|
||||
int XPRate;
|
||||
|
||||
|
||||
+78
-86
@@ -1974,101 +1974,87 @@ int32 Client::CalcATK()
|
||||
|
||||
uint32 Mob::GetInstrumentMod(uint16 spell_id) const
|
||||
{
|
||||
if (GetClass() != BARD) {
|
||||
if (GetClass() != BARD || spells[spell_id].IsDisciplineBuff) // Puretone is Singing but doesn't get any mod
|
||||
return 10;
|
||||
}
|
||||
|
||||
uint32 effectmod = 10;
|
||||
int effectmodcap = RuleI(Character, BaseInstrumentSoftCap);
|
||||
//this should never use spell modifiers...
|
||||
//if a spell grants better modifers, they are copied into the item mods
|
||||
//because the spells are supposed to act just like having the intrument.
|
||||
//item mods are in 10ths of percent increases
|
||||
// this should never use spell modifiers...
|
||||
// if a spell grants better modifers, they are copied into the item mods
|
||||
// because the spells are supposed to act just like having the intrument.
|
||||
// item mods are in 10ths of percent increases
|
||||
// clickies (Symphony of Battle) that have a song skill don't get AA bonus for some reason
|
||||
// but clickies that are songs (selo's on Composers Greaves) do get AA mod as well
|
||||
switch (spells[spell_id].skill) {
|
||||
case SkillPercussionInstruments:
|
||||
if (itembonuses.percussionMod == 0 && spellbonuses.percussionMod == 0) {
|
||||
effectmod = 10;
|
||||
}
|
||||
else if (GetSkill(SkillPercussionInstruments) == 0) {
|
||||
effectmod = 10;
|
||||
}
|
||||
else if (itembonuses.percussionMod > spellbonuses.percussionMod) {
|
||||
effectmod = itembonuses.percussionMod;
|
||||
}
|
||||
else {
|
||||
effectmod = spellbonuses.percussionMod;
|
||||
}
|
||||
effectmod += aabonuses.percussionMod;
|
||||
break;
|
||||
case SkillStringedInstruments:
|
||||
if (itembonuses.stringedMod == 0 && spellbonuses.stringedMod == 0) {
|
||||
effectmod = 10;
|
||||
}
|
||||
else if (GetSkill(SkillStringedInstruments) == 0) {
|
||||
effectmod = 10;
|
||||
}
|
||||
else if (itembonuses.stringedMod > spellbonuses.stringedMod) {
|
||||
effectmod = itembonuses.stringedMod;
|
||||
}
|
||||
else {
|
||||
effectmod = spellbonuses.stringedMod;
|
||||
}
|
||||
effectmod += aabonuses.stringedMod;
|
||||
break;
|
||||
case SkillWindInstruments:
|
||||
if (itembonuses.windMod == 0 && spellbonuses.windMod == 0) {
|
||||
effectmod = 10;
|
||||
}
|
||||
else if (GetSkill(SkillWindInstruments) == 0) {
|
||||
effectmod = 10;
|
||||
}
|
||||
else if (itembonuses.windMod > spellbonuses.windMod) {
|
||||
effectmod = itembonuses.windMod;
|
||||
}
|
||||
else {
|
||||
effectmod = spellbonuses.windMod;
|
||||
}
|
||||
effectmod += aabonuses.windMod;
|
||||
break;
|
||||
case SkillBrassInstruments:
|
||||
if (itembonuses.brassMod == 0 && spellbonuses.brassMod == 0) {
|
||||
effectmod = 10;
|
||||
}
|
||||
else if (GetSkill(SkillBrassInstruments) == 0) {
|
||||
effectmod = 10;
|
||||
}
|
||||
else if (itembonuses.brassMod > spellbonuses.brassMod) {
|
||||
effectmod = itembonuses.brassMod;
|
||||
}
|
||||
else {
|
||||
effectmod = spellbonuses.brassMod;
|
||||
}
|
||||
effectmod += aabonuses.brassMod;
|
||||
break;
|
||||
case SkillSinging:
|
||||
if (itembonuses.singingMod == 0 && spellbonuses.singingMod == 0) {
|
||||
effectmod = 10;
|
||||
}
|
||||
else if (itembonuses.singingMod > spellbonuses.singingMod) {
|
||||
effectmod = itembonuses.singingMod;
|
||||
}
|
||||
else {
|
||||
effectmod = spellbonuses.singingMod;
|
||||
}
|
||||
effectmod += aabonuses.singingMod + spellbonuses.Amplification;
|
||||
break;
|
||||
default:
|
||||
case SkillPercussionInstruments:
|
||||
if (itembonuses.percussionMod == 0 && spellbonuses.percussionMod == 0)
|
||||
effectmod = 10;
|
||||
break;
|
||||
else if (GetSkill(SkillPercussionInstruments) == 0)
|
||||
effectmod = 10;
|
||||
else if (itembonuses.percussionMod > spellbonuses.percussionMod)
|
||||
effectmod = itembonuses.percussionMod;
|
||||
else
|
||||
effectmod = spellbonuses.percussionMod;
|
||||
if (IsBardSong(spell_id))
|
||||
effectmod += aabonuses.percussionMod;
|
||||
break;
|
||||
case SkillStringedInstruments:
|
||||
if (itembonuses.stringedMod == 0 && spellbonuses.stringedMod == 0)
|
||||
effectmod = 10;
|
||||
else if (GetSkill(SkillStringedInstruments) == 0)
|
||||
effectmod = 10;
|
||||
else if (itembonuses.stringedMod > spellbonuses.stringedMod)
|
||||
effectmod = itembonuses.stringedMod;
|
||||
else
|
||||
effectmod = spellbonuses.stringedMod;
|
||||
if (IsBardSong(spell_id))
|
||||
effectmod += aabonuses.stringedMod;
|
||||
break;
|
||||
case SkillWindInstruments:
|
||||
if (itembonuses.windMod == 0 && spellbonuses.windMod == 0)
|
||||
effectmod = 10;
|
||||
else if (GetSkill(SkillWindInstruments) == 0)
|
||||
effectmod = 10;
|
||||
else if (itembonuses.windMod > spellbonuses.windMod)
|
||||
effectmod = itembonuses.windMod;
|
||||
else
|
||||
effectmod = spellbonuses.windMod;
|
||||
if (IsBardSong(spell_id))
|
||||
effectmod += aabonuses.windMod;
|
||||
break;
|
||||
case SkillBrassInstruments:
|
||||
if (itembonuses.brassMod == 0 && spellbonuses.brassMod == 0)
|
||||
effectmod = 10;
|
||||
else if (GetSkill(SkillBrassInstruments) == 0)
|
||||
effectmod = 10;
|
||||
else if (itembonuses.brassMod > spellbonuses.brassMod)
|
||||
effectmod = itembonuses.brassMod;
|
||||
else
|
||||
effectmod = spellbonuses.brassMod;
|
||||
if (IsBardSong(spell_id))
|
||||
effectmod += aabonuses.brassMod;
|
||||
break;
|
||||
case SkillSinging:
|
||||
if (itembonuses.singingMod == 0 && spellbonuses.singingMod == 0)
|
||||
effectmod = 10;
|
||||
else if (itembonuses.singingMod > spellbonuses.singingMod)
|
||||
effectmod = itembonuses.singingMod;
|
||||
else
|
||||
effectmod = spellbonuses.singingMod;
|
||||
if (IsBardSong(spell_id))
|
||||
effectmod += aabonuses.singingMod + spellbonuses.Amplification;
|
||||
break;
|
||||
default:
|
||||
effectmod = 10;
|
||||
return effectmod;
|
||||
}
|
||||
effectmodcap += aabonuses.songModCap + spellbonuses.songModCap + itembonuses.songModCap;
|
||||
if (effectmod < 10) {
|
||||
if (effectmod < 10)
|
||||
effectmod = 10;
|
||||
}
|
||||
if (effectmod > effectmodcap) {
|
||||
if (effectmod > effectmodcap)
|
||||
effectmod = effectmodcap;
|
||||
}
|
||||
Log.Out(Logs::Detail, Logs::Spells, "%s::GetInstrumentMod() spell=%d mod=%d modcap=%d\n",
|
||||
GetName(), spell_id, effectmod, effectmodcap);
|
||||
Log.Out(Logs::Detail, Logs::Spells, "%s::GetInstrumentMod() spell=%d mod=%d modcap=%d\n", GetName(), spell_id,
|
||||
effectmod, effectmodcap);
|
||||
return effectmod;
|
||||
}
|
||||
|
||||
@@ -2148,6 +2134,12 @@ int32 Client::CalcEnduranceRegenCap()
|
||||
return (cap * RuleI(Character, EnduranceRegenMultiplier) / 100);
|
||||
}
|
||||
|
||||
int32 Client::CalcItemATKCap()
|
||||
{
|
||||
int cap = RuleI(Character, ItemATKCap) + itembonuses.ItemATKCap + spellbonuses.ItemATKCap + aabonuses.ItemATKCap;
|
||||
return cap;
|
||||
}
|
||||
|
||||
int Client::GetRawACNoShield(int &shield_ac) const
|
||||
{
|
||||
int ac = itembonuses.AC + spellbonuses.AC + aabonuses.AC;
|
||||
|
||||
+332
-156
@@ -305,6 +305,8 @@ void MapOpcodes()
|
||||
ConnectedOpcodes[OP_PetitionRefresh] = &Client::Handle_OP_PetitionRefresh;
|
||||
ConnectedOpcodes[OP_PetitionResolve] = &Client::Handle_OP_PetitionResolve;
|
||||
ConnectedOpcodes[OP_PetitionUnCheckout] = &Client::Handle_OP_PetitionUnCheckout;
|
||||
ConnectedOpcodes[OP_PlayerStateAdd] = &Client::Handle_OP_PlayerStateAdd;
|
||||
ConnectedOpcodes[OP_PlayerStateRemove] = &Client::Handle_OP_PlayerStateRemove;
|
||||
ConnectedOpcodes[OP_PickPocket] = &Client::Handle_OP_PickPocket;
|
||||
ConnectedOpcodes[OP_PopupResponse] = &Client::Handle_OP_PopupResponse;
|
||||
ConnectedOpcodes[OP_PotionBelt] = &Client::Handle_OP_PotionBelt;
|
||||
@@ -332,7 +334,13 @@ void MapOpcodes()
|
||||
ConnectedOpcodes[OP_Save] = &Client::Handle_OP_Save;
|
||||
ConnectedOpcodes[OP_SaveOnZoneReq] = &Client::Handle_OP_SaveOnZoneReq;
|
||||
ConnectedOpcodes[OP_SelectTribute] = &Client::Handle_OP_SelectTribute;
|
||||
ConnectedOpcodes[OP_SenseHeading] = &Client::Handle_OP_Ignore;
|
||||
|
||||
// Use or Ignore sense heading based on rule.
|
||||
bool train=RuleB(Skills, TrainSenseHeading);
|
||||
|
||||
ConnectedOpcodes[OP_SenseHeading] =
|
||||
(train) ? &Client::Handle_OP_SenseHeading : &Client::Handle_OP_Ignore;
|
||||
|
||||
ConnectedOpcodes[OP_SenseTraps] = &Client::Handle_OP_SenseTraps;
|
||||
ConnectedOpcodes[OP_SetGuildMOTD] = &Client::Handle_OP_SetGuildMOTD;
|
||||
ConnectedOpcodes[OP_SetRunMode] = &Client::Handle_OP_SetRunMode;
|
||||
@@ -406,10 +414,10 @@ int Client::HandlePacket(const EQApplicationPacket *app)
|
||||
|
||||
if (Log.log_settings[Logs::Client_Server_Packet].is_category_enabled == 1)
|
||||
Log.Out(Logs::General, Logs::Client_Server_Packet, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(app->GetOpcode()), app->GetOpcode(), app->Size());
|
||||
|
||||
|
||||
if (Log.log_settings[Logs::Client_Server_Packet_With_Dump].is_category_enabled == 1)
|
||||
Log.Out(Logs::General, Logs::Client_Server_Packet_With_Dump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(app->GetOpcode()), app->GetOpcode(), app->Size(), DumpPacketToString(app).c_str());
|
||||
|
||||
|
||||
EmuOpcode opcode = app->GetOpcode();
|
||||
if (opcode == OP_AckPacket) {
|
||||
return true;
|
||||
@@ -451,7 +459,7 @@ int Client::HandlePacket(const EQApplicationPacket *app)
|
||||
case CLIENT_CONNECTED: {
|
||||
ClientPacketProc p;
|
||||
p = ConnectedOpcodes[opcode];
|
||||
if(p == nullptr) {
|
||||
if(p == nullptr) {
|
||||
std::vector<EQEmu::Any> args;
|
||||
args.push_back(const_cast<EQApplicationPacket*>(app));
|
||||
parse->EventPlayer(EVENT_UNHANDLED_OPCODE, this, "", 0, &args);
|
||||
@@ -696,7 +704,7 @@ void Client::CompleteConnect()
|
||||
case SE_AddMeleeProc:
|
||||
case SE_WeaponProc:
|
||||
{
|
||||
AddProcToWeapon(GetProcID(buffs[j1].spellid, x1), false, 100 + spells[buffs[j1].spellid].base2[x1], buffs[j1].spellid);
|
||||
AddProcToWeapon(GetProcID(buffs[j1].spellid, x1), false, 100 + spells[buffs[j1].spellid].base2[x1], buffs[j1].spellid, buffs[j1].casterlevel);
|
||||
break;
|
||||
}
|
||||
case SE_DefensiveProc:
|
||||
@@ -725,8 +733,8 @@ void Client::CompleteConnect()
|
||||
SendWearChange(x);
|
||||
}
|
||||
// added due to wear change above
|
||||
UpdateActiveLightValue();
|
||||
SendAppearancePacket(AT_Light, GetActiveLightValue());
|
||||
UpdateActiveLight();
|
||||
SendAppearancePacket(AT_Light, GetActiveLightType());
|
||||
|
||||
Mob *pet = GetPet();
|
||||
if (pet != nullptr) {
|
||||
@@ -734,8 +742,8 @@ void Client::CompleteConnect()
|
||||
pet->SendWearChange(x);
|
||||
}
|
||||
// added due to wear change above
|
||||
pet->UpdateActiveLightValue();
|
||||
pet->SendAppearancePacket(AT_Light, pet->GetActiveLightValue());
|
||||
pet->UpdateActiveLight();
|
||||
pet->SendAppearancePacket(AT_Light, pet->GetActiveLightType());
|
||||
}
|
||||
|
||||
entity_list.SendTraders(this);
|
||||
@@ -779,6 +787,13 @@ void Client::CompleteConnect()
|
||||
std::string event_desc = StringFormat("Connect :: Logged into zoneid:%i instid:%i", this->GetZoneID(), this->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_Connect_State, this->CharacterID(), event_desc);
|
||||
}
|
||||
|
||||
ServerPacket pack(ServerOP_ClientFileStatus, sizeof(ServerRequestClientFileStatus));
|
||||
ServerRequestClientFileStatus *req = (ServerRequestClientFileStatus*)pack.pBuffer;
|
||||
req->zone_id = zone->GetZoneID();
|
||||
req->instance_id = zone->GetInstanceID();
|
||||
strn0cpy(req->name, GetName(), 64);
|
||||
worldserver.SendPacket(&pack);
|
||||
}
|
||||
|
||||
if (zone) {
|
||||
@@ -1191,8 +1206,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
conn_state = ReceivedZoneEntry;
|
||||
|
||||
SetClientVersion(Connection()->GetClientVersion());
|
||||
if (m_ClientVersion != ClientVersion::Unknown)
|
||||
ClientVersionBit = 1 << (static_cast<unsigned int>(m_ClientVersion) - 1);
|
||||
m_ClientVersionBit = ClientBitFromVersion(Connection()->GetClientVersion());
|
||||
|
||||
bool siv = m_inv.SetInventoryVersion(m_ClientVersion);
|
||||
Log.Out(Logs::General, Logs::None, "%s inventory version to %s(%i)", (siv ? "Succeeded in setting" : "Failed to set"), ClientVersionName(m_ClientVersion), m_ClientVersion);
|
||||
@@ -1307,9 +1321,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
/* Set item material tint */
|
||||
for (int i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_END; i++)
|
||||
{
|
||||
if (m_pp.item_tint[i].rgb.use_tint == 1 || m_pp.item_tint[i].rgb.use_tint == 255)
|
||||
if (m_pp.item_tint[i].RGB.UseTint == 1 || m_pp.item_tint[i].RGB.UseTint == 255)
|
||||
{
|
||||
m_pp.item_tint[i].rgb.use_tint = 0xFF;
|
||||
m_pp.item_tint[i].RGB.UseTint = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1432,27 +1446,33 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
if (m_pp.ldon_points_tak < 0 || m_pp.ldon_points_tak > 2000000000){ m_pp.ldon_points_tak = 0; }
|
||||
if (m_pp.ldon_points_available < 0 || m_pp.ldon_points_available > 2000000000){ m_pp.ldon_points_available = 0; }
|
||||
|
||||
/* Set Swimming Skill 100 by default if under 100 */
|
||||
if (GetSkill(SkillSwimming) < 100)
|
||||
SetSkill(SkillSwimming, 100);
|
||||
|
||||
/* Initialize AA's : Move to function eventually */
|
||||
for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++){ aa[a] = &m_pp.aa_array[a]; }
|
||||
for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++)
|
||||
aa[a] = &m_pp.aa_array[a];
|
||||
query = StringFormat(
|
||||
"SELECT "
|
||||
"slot, "
|
||||
"aa_id, "
|
||||
"aa_value "
|
||||
"aa_value, "
|
||||
"charges "
|
||||
"FROM "
|
||||
"`character_alternate_abilities` "
|
||||
"WHERE `id` = %u ORDER BY `slot`", this->CharacterID());
|
||||
results = database.QueryDatabase(query); i = 0;
|
||||
int offset = 0; // offset to fix the hole from expendables
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
i = atoi(row[0]);
|
||||
i = atoi(row[0]) - offset;
|
||||
m_pp.aa_array[i].AA = atoi(row[1]);
|
||||
m_pp.aa_array[i].value = atoi(row[2]);
|
||||
aa[i]->AA = atoi(row[1]);
|
||||
aa[i]->value = atoi(row[2]);
|
||||
m_pp.aa_array[i].charges = atoi(row[3]);
|
||||
/* A used expendable could cause there to be a "hole" in the array, this is very bad. Bad things like keeping your expendable after use.
|
||||
We could do a few things, one of them being reshuffling when the hole is created or defer the fixing until a later point, like during load!
|
||||
Or just never making a hole in the array and just have hacks every where. Fixing the hole at load really just keeps 1 hack in Client::SendAATable
|
||||
and keeping this offset that will cause the next AA to be pushed back over the hole. We also need to clean up on save so we don't have multiple
|
||||
entries for a single AA.
|
||||
*/
|
||||
if (m_pp.aa_array[i].value == 0)
|
||||
offset++;
|
||||
}
|
||||
for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++){
|
||||
uint32 id = aa[a]->AA;
|
||||
@@ -1491,7 +1511,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
for (int i = 0; i < max_slots; i++) {
|
||||
if (buffs[i].spellid != SPELL_UNKNOWN) {
|
||||
m_pp.buffs[i].spellid = buffs[i].spellid;
|
||||
m_pp.buffs[i].bard_modifier = 10;
|
||||
m_pp.buffs[i].bard_modifier = buffs[i].instrument_mod;
|
||||
m_pp.buffs[i].slotid = 2;
|
||||
m_pp.buffs[i].player_id = 0x2211;
|
||||
m_pp.buffs[i].level = buffs[i].casterlevel;
|
||||
@@ -1700,7 +1720,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
/* Time of Day packet */
|
||||
outapp = new EQApplicationPacket(OP_TimeOfDay, sizeof(TimeOfDay_Struct));
|
||||
TimeOfDay_Struct* tod = (TimeOfDay_Struct*)outapp->pBuffer;
|
||||
zone->zone_time.getEQTimeOfDay(time(0), tod);
|
||||
zone->zone_time.GetCurrentEQTimeOfDay(time(0), tod);
|
||||
outapp->priority = 6;
|
||||
FastQueuePacket(&outapp);
|
||||
|
||||
@@ -1736,7 +1756,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
if (ClientVersionBit & BIT_UFAndLater) {
|
||||
if (m_ClientVersionBit & BIT_UFAndLater) {
|
||||
outapp = new EQApplicationPacket(OP_XTargetResponse, 8);
|
||||
outapp->WriteUInt32(GetMaxXTargets());
|
||||
outapp->WriteUInt32(0);
|
||||
@@ -2624,6 +2644,9 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app)
|
||||
else {
|
||||
uint32 max_currency = GetAlternateCurrencyValue(reclaim->currency_id);
|
||||
|
||||
if(max_currency == 0 || reclaim->count == 0)
|
||||
return;
|
||||
|
||||
/* If you input more than you have currency wise, just give the max of the currency you currently have */
|
||||
if (reclaim->count > max_currency) {
|
||||
SummonItem(item_id, max_currency);
|
||||
@@ -2827,8 +2850,7 @@ void Client::Handle_OP_Animation(const EQApplicationPacket *app)
|
||||
Animation_Struct *s = (Animation_Struct *)app->pBuffer;
|
||||
|
||||
//might verify spawn ID, but it wouldent affect anything
|
||||
|
||||
DoAnim(s->action, s->value);
|
||||
DoAnim(s->action, s->speed);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -3011,7 +3033,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app)
|
||||
{
|
||||
DeleteItemInInventory(slot_id, 0, true);
|
||||
DeleteItemInInventory(MainCursor, 0, true);
|
||||
|
||||
|
||||
if (PutItemInInventory(slot_id, *itemOneToPush, true))
|
||||
{
|
||||
CalcBonuses();
|
||||
@@ -3171,7 +3193,6 @@ void Client::Handle_OP_AutoFire(const EQApplicationPacket *app)
|
||||
|
||||
void Client::Handle_OP_Bandolier(const EQApplicationPacket *app)
|
||||
{
|
||||
|
||||
// Although there are three different structs for OP_Bandolier, they are all the same size.
|
||||
//
|
||||
if (app->size != sizeof(BandolierCreate_Struct)) {
|
||||
@@ -3183,19 +3204,20 @@ void Client::Handle_OP_Bandolier(const EQApplicationPacket *app)
|
||||
|
||||
BandolierCreate_Struct *bs = (BandolierCreate_Struct*)app->pBuffer;
|
||||
|
||||
switch (bs->action) {
|
||||
case BandolierCreate:
|
||||
switch (bs->Action)
|
||||
{
|
||||
case bandolierCreate:
|
||||
CreateBandolier(app);
|
||||
break;
|
||||
case BandolierRemove:
|
||||
case bandolierRemove:
|
||||
RemoveBandolier(app);
|
||||
break;
|
||||
case BandolierSet:
|
||||
case bandolierSet:
|
||||
SetBandolier(app);
|
||||
break;
|
||||
default:
|
||||
Log.Out(Logs::General, Logs::None, "Uknown Bandolier action %i", bs->action);
|
||||
|
||||
Log.Out(Logs::General, Logs::None, "Unknown Bandolier action %i", bs->Action);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3900,7 +3922,7 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
|
||||
}
|
||||
else if (m_inv.SupportsClickCasting(castspell->inventoryslot) || (castspell->slot == POTION_BELT_SPELL_SLOT) || (castspell->slot == TARGET_RING_SPELL_SLOT)) // sanity check
|
||||
{
|
||||
// packet field types will be reviewed as packet transistions occur -U
|
||||
// packet field types will be reviewed as packet transistions occur
|
||||
const ItemInst* inst = m_inv[castspell->inventoryslot]; //slot values are int16, need to check packet on this field
|
||||
//bool cancast = true;
|
||||
if (inst && inst->IsType(ItemClassCommon))
|
||||
@@ -4123,7 +4145,7 @@ void Client::Handle_OP_ClickObject(const EQApplicationPacket *app)
|
||||
char buf[10];
|
||||
snprintf(buf, 9, "%u", click_object->drop_id);
|
||||
buf[9] = '\0';
|
||||
parse->EventPlayer(EVENT_CLICK_OBJECT, this, buf, 0, &args);
|
||||
parse->EventPlayer(EVENT_CLICK_OBJECT, this, buf, GetID(), &args);
|
||||
}
|
||||
|
||||
// Observed in RoF after OP_ClickObjectAction:
|
||||
@@ -4261,7 +4283,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
|
||||
if((cur_time - m_TimeSinceLastPositionCheck) > 0)
|
||||
{
|
||||
float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck);
|
||||
float runs = GetRunspeed();
|
||||
int runs = GetRunspeed();
|
||||
if(speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor)))
|
||||
{
|
||||
if(!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor)))))
|
||||
@@ -4329,7 +4351,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
|
||||
if((cur_time - m_TimeSinceLastPositionCheck) > 2500)
|
||||
{
|
||||
float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck);
|
||||
float runs = GetRunspeed();
|
||||
int runs = GetRunspeed();
|
||||
if(speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor)))
|
||||
{
|
||||
if(!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor)))))
|
||||
@@ -4442,9 +4464,20 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
|
||||
|
||||
// Outgoing client packet
|
||||
float tmpheading = EQ19toFloat(ppu->heading);
|
||||
/* The clients send an update at best every 1.3 seconds
|
||||
* We want to avoid reflecting these updates to other clients as much as possible
|
||||
* The client also sends an update every 280 ms while turning, if we prevent
|
||||
* sending these by checking if the location is the same too aggressively, clients end up spinning
|
||||
* so keep a count of how many packets are the same within a tolerance and stop when we get there */
|
||||
|
||||
if (!FCMP(ppu->y_pos, m_Position.y) || !FCMP(ppu->x_pos, m_Position.x) || !FCMP(tmpheading, m_Position.w) || ppu->animation != animation)
|
||||
bool pos_same = FCMP(ppu->y_pos, m_Position.y) && FCMP(ppu->x_pos, m_Position.x) && FCMP(tmpheading, m_Position.w) && ppu->animation == animation;
|
||||
if (!pos_same || (pos_same && position_update_same_count < 6))
|
||||
{
|
||||
if (pos_same)
|
||||
position_update_same_count++;
|
||||
else
|
||||
position_update_same_count = 0;
|
||||
|
||||
m_Position.x = ppu->x_pos;
|
||||
m_Position.y = ppu->y_pos;
|
||||
m_Position.z = ppu->z_pos;
|
||||
@@ -5079,6 +5112,7 @@ void Client::Handle_OP_DeleteSpell(const EQApplicationPacket *app)
|
||||
|
||||
if (m_pp.spell_book[dss->spell_slot] != SPELLBOOK_UNKNOWN) {
|
||||
m_pp.spell_book[dss->spell_slot] = SPELLBOOK_UNKNOWN;
|
||||
database.DeleteCharacterSpell(this->CharacterID(), m_pp.spell_book[dss->spell_slot], dss->spell_slot);
|
||||
dss->success = 1;
|
||||
}
|
||||
else
|
||||
@@ -5416,12 +5450,12 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app)
|
||||
/* EVENT_ENVIRONMENTAL_DAMAGE */
|
||||
int final_damage = (damage * RuleR(Character, EnvironmentDamageMulipliter));
|
||||
char buf[24];
|
||||
snprintf(buf, 23, "%u %u %i", ed->damage, ed->dmgtype, final_damage);
|
||||
snprintf(buf, 23, "%u %u %i", ed->damage, ed->dmgtype, final_damage);
|
||||
parse->EventPlayer(EVENT_ENVIRONMENTAL_DAMAGE, this, buf, 0);
|
||||
}
|
||||
|
||||
if (GetHP() <= 0) {
|
||||
mod_client_death_env();
|
||||
mod_client_death_env();
|
||||
Death(0, 32000, SPELL_UNKNOWN, SkillHandtoHand);
|
||||
}
|
||||
SendHPUpdate();
|
||||
@@ -6348,15 +6382,25 @@ void Client::Handle_OP_GroupDisband(const EQApplicationPacket *app)
|
||||
Bot::ProcessBotGroupDisband(this, std::string());
|
||||
}
|
||||
else {
|
||||
Mob* tempMember = entity_list.GetMob(gd->name2);
|
||||
if (tempMember) {
|
||||
if (tempMember->IsBot())
|
||||
Bot::ProcessBotGroupDisband(this, std::string(tempMember->GetCleanName()));
|
||||
Mob* tempMember = entity_list.GetMob(gd->name1); //Name1 is the target you are disbanding
|
||||
if (tempMember && tempMember->IsBot()) {
|
||||
tempMember->CastToBot()->RemoveBotFromGroup(tempMember->CastToBot(), group);
|
||||
if (LFP)
|
||||
{
|
||||
// If we are looking for players, update to show we are on our own now.
|
||||
UpdateLFP();
|
||||
}
|
||||
return; //No need to continue from here we were removing a bot from party
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
group = GetGroup();
|
||||
if (!group) //We must recheck this here.. incase the final bot disbanded the party..otherwise we crash
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (group->GroupCount() < 3)
|
||||
{
|
||||
group->DisbandGroup();
|
||||
@@ -9748,6 +9792,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
char val1[20] = { 0 };
|
||||
PetCommand_Struct* pet = (PetCommand_Struct*)app->pBuffer;
|
||||
Mob* mypet = this->GetPet();
|
||||
Mob *target = entity_list.GetMob(pet->target);
|
||||
|
||||
if (!mypet || pet->command == PET_LEADER)
|
||||
{
|
||||
@@ -9795,22 +9840,22 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
switch (PetCommand)
|
||||
{
|
||||
case PET_ATTACK: {
|
||||
if (!GetTarget())
|
||||
if (!target)
|
||||
break;
|
||||
if (GetTarget()->IsMezzed()) {
|
||||
Message_StringID(10, CANNOT_WAKE, mypet->GetCleanName(), GetTarget()->GetCleanName());
|
||||
if (target->IsMezzed()) {
|
||||
Message_StringID(10, CANNOT_WAKE, mypet->GetCleanName(), target->GetCleanName());
|
||||
break;
|
||||
}
|
||||
if (mypet->IsFeared())
|
||||
break; //prevent pet from attacking stuff while feared
|
||||
|
||||
if (!mypet->IsAttackAllowed(GetTarget())) {
|
||||
if (!mypet->IsAttackAllowed(target)) {
|
||||
mypet->Say_StringID(NOT_LEGAL_TARGET);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 2) || mypet->GetPetType() != petAnimation) {
|
||||
if (GetTarget() != this && DistanceSquaredNoZ(mypet->GetPosition(), GetTarget()->GetPosition()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) {
|
||||
if (target != this && DistanceSquaredNoZ(mypet->GetPosition(), target->GetPosition()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) {
|
||||
if (mypet->IsHeld()) {
|
||||
if (!mypet->IsFocused()) {
|
||||
mypet->SetHeld(false); //break the hold and guard if we explicitly tell the pet to attack.
|
||||
@@ -9818,12 +9863,12 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
mypet->SetPetOrder(SPO_Follow);
|
||||
}
|
||||
else {
|
||||
mypet->SetTarget(GetTarget());
|
||||
mypet->SetTarget(target);
|
||||
}
|
||||
}
|
||||
zone->AddAggroMob();
|
||||
mypet->AddToHateList(GetTarget(), 1);
|
||||
Message_StringID(MT_PetResponse, PET_ATTACKING, mypet->GetCleanName(), GetTarget()->GetCleanName());
|
||||
mypet->AddToHateList(target, 1);
|
||||
Message_StringID(MT_PetResponse, PET_ATTACKING, mypet->GetCleanName(), target->GetCleanName());
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -9838,7 +9883,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
Message_StringID(10, CANNOT_WAKE, mypet->GetCleanName(), GetTarget()->GetCleanName());
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (!mypet->IsAttackAllowed(GetTarget())) {
|
||||
mypet->Say_StringID(NOT_LEGAL_TARGET);
|
||||
break;
|
||||
@@ -9934,7 +9979,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
case PET_TAUNT_ON: {
|
||||
if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) {
|
||||
Message_StringID(MT_PetResponse, PET_DO_TAUNT);
|
||||
@@ -10318,6 +10363,31 @@ void Client::Handle_OP_PetitionUnCheckout(const EQApplicationPacket *app)
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_PlayerStateAdd(const EQApplicationPacket *app)
|
||||
{
|
||||
if (app->size != sizeof(PlayerState_Struct)) {
|
||||
std::cout << "Wrong size: OP_PlayerStateAdd, size=" << app->size << ", expected " << sizeof(PlayerState_Struct) << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerState_Struct *ps = (PlayerState_Struct *)app->pBuffer;
|
||||
AddPlayerState(ps->state);
|
||||
|
||||
entity_list.QueueClients(this, app, true);
|
||||
}
|
||||
|
||||
void Client::Handle_OP_PlayerStateRemove(const EQApplicationPacket *app)
|
||||
{
|
||||
if (app->size != sizeof(PlayerState_Struct)) {
|
||||
std::cout << "Wrong size: OP_PlayerStateRemove, size=" << app->size << ", expected " << sizeof(PlayerState_Struct) << std::endl;
|
||||
return;
|
||||
}
|
||||
PlayerState_Struct *ps = (PlayerState_Struct *)app->pBuffer;
|
||||
RemovePlayerState(ps->state);
|
||||
|
||||
entity_list.QueueClients(this, app, true);
|
||||
}
|
||||
|
||||
void Client::Handle_OP_PickPocket(const EQApplicationPacket *app)
|
||||
{
|
||||
if (app->size != sizeof(PickPocket_Struct))
|
||||
@@ -10442,16 +10512,16 @@ void Client::Handle_OP_PotionBelt(const EQApplicationPacket *app)
|
||||
if (mptbs->Action == 0) {
|
||||
const Item_Struct *BaseItem = database.GetItem(mptbs->ItemID);
|
||||
if (BaseItem) {
|
||||
m_pp.potionbelt.items[mptbs->SlotNumber].item_id = BaseItem->ID;
|
||||
m_pp.potionbelt.items[mptbs->SlotNumber].icon = BaseItem->Icon;
|
||||
strn0cpy(m_pp.potionbelt.items[mptbs->SlotNumber].item_name, BaseItem->Name, sizeof(BaseItem->Name));
|
||||
database.SaveCharacterPotionBelt(this->CharacterID(), mptbs->SlotNumber, m_pp.potionbelt.items[mptbs->SlotNumber].item_id, m_pp.potionbelt.items[mptbs->SlotNumber].icon);
|
||||
m_pp.potionbelt.Items[mptbs->SlotNumber].ID = BaseItem->ID;
|
||||
m_pp.potionbelt.Items[mptbs->SlotNumber].Icon = BaseItem->Icon;
|
||||
strn0cpy(m_pp.potionbelt.Items[mptbs->SlotNumber].Name, BaseItem->Name, sizeof(BaseItem->Name));
|
||||
database.SaveCharacterPotionBelt(this->CharacterID(), mptbs->SlotNumber, m_pp.potionbelt.Items[mptbs->SlotNumber].ID, m_pp.potionbelt.Items[mptbs->SlotNumber].Icon);
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_pp.potionbelt.items[mptbs->SlotNumber].item_id = 0;
|
||||
m_pp.potionbelt.items[mptbs->SlotNumber].icon = 0;
|
||||
strncpy(m_pp.potionbelt.items[mptbs->SlotNumber].item_name, "\0", 1);
|
||||
m_pp.potionbelt.Items[mptbs->SlotNumber].ID = 0;
|
||||
m_pp.potionbelt.Items[mptbs->SlotNumber].Icon = 0;
|
||||
m_pp.potionbelt.Items[mptbs->SlotNumber].Name[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11653,6 +11723,27 @@ void Client::Handle_OP_SelectTribute(const EQApplicationPacket *app)
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_SenseHeading(const EQApplicationPacket *app)
|
||||
{
|
||||
if (!HasSkill(SkillSenseHeading))
|
||||
return;
|
||||
|
||||
int chancemod=0;
|
||||
|
||||
// The client seems to limit sense heading packets based on skill
|
||||
// level. So if we're really low, we don't hit this routine very often.
|
||||
// I think it's the GUI deciding when to skill you up.
|
||||
// So, I'm adding a mod here which is larger at lower levels so
|
||||
// very low levels get a much better chance to skill up when the GUI
|
||||
// eventually sends a message.
|
||||
if (GetLevel() <= 8)
|
||||
chancemod += (9-level) * 10;
|
||||
|
||||
CheckIncreaseSkill(SkillSenseHeading, nullptr, chancemod);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_SenseTraps(const EQApplicationPacket *app)
|
||||
{
|
||||
if (!HasSkill(SkillSenseTraps))
|
||||
@@ -11952,12 +12043,6 @@ void Client::Handle_OP_ShopEnd(const EQApplicationPacket *app)
|
||||
{
|
||||
EQApplicationPacket empty(OP_ShopEndConfirm);
|
||||
QueuePacket(&empty);
|
||||
//EQApplicationPacket* outapp = new EQApplicationPacket(OP_ShopEndConfirm, 2);
|
||||
//outapp->pBuffer[0] = 0x0a;
|
||||
//outapp->pBuffer[1] = 0x66;
|
||||
//QueuePacket(outapp);
|
||||
//safe_delete(outapp);
|
||||
//Save();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -12294,7 +12379,7 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app)
|
||||
int freeslot = 0;
|
||||
if (charges > 0 && (freeslot = zone->SaveTempItem(vendor->CastToNPC()->MerchantType, vendor->GetNPCTypeID(), itemid, charges, true)) > 0){
|
||||
ItemInst* inst2 = inst->Clone();
|
||||
|
||||
|
||||
while (true) {
|
||||
if (inst2 == nullptr)
|
||||
break;
|
||||
@@ -12840,7 +12925,7 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app)
|
||||
inspect_buffs = group->GetLeadershipAA(groupAAInspectBuffs);
|
||||
}
|
||||
}
|
||||
if (nt == this || inspect_buffs || (nt->IsClient() && !nt->CastToClient()->GetPVP()) ||
|
||||
if (GetGM() || RuleB(Spells, AlwaysSendTargetsBuffs) || nt == this || inspect_buffs || (nt->IsClient() && !nt->CastToClient()->GetPVP()) ||
|
||||
(nt->IsPet() && nt->GetOwner() && nt->GetOwner()->IsClient() && !nt->GetOwner()->CastToClient()->GetPVP()) ||
|
||||
(nt->IsMerc() && nt->GetOwner() && nt->GetOwner()->IsClient() && !nt->GetOwner()->CastToClient()->GetPVP()))
|
||||
nt->SendBuffsToClient(this);
|
||||
@@ -13278,7 +13363,7 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app)
|
||||
|
||||
/*
|
||||
if (GetClientVersion() >= EQClientRoF)
|
||||
max_items = 200;
|
||||
max_items = 200;
|
||||
*/
|
||||
|
||||
//Show Items
|
||||
@@ -13290,20 +13375,25 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app)
|
||||
{
|
||||
case BazaarTrader_EndTraderMode: {
|
||||
Trader_EndTrader();
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_Trader: End Trader Session");
|
||||
break;
|
||||
}
|
||||
case BazaarTrader_EndTransaction: {
|
||||
|
||||
Client* c = entity_list.GetClientByID(sis->TraderID);
|
||||
if (c)
|
||||
{
|
||||
c->WithCustomer(0);
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_Trader: End Transaction");
|
||||
}
|
||||
else
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderBuy: Null Client Pointer");
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_Trader: Null Client Pointer");
|
||||
|
||||
break;
|
||||
}
|
||||
case BazaarTrader_ShowItems: {
|
||||
Trader_ShowItems();
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_Trader: Show Trader Items");
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -13326,6 +13416,7 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app)
|
||||
{
|
||||
GetItems_Struct* gis = GetTraderItems();
|
||||
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_Trader: Start Trader Mode");
|
||||
// Verify there are no NODROP or items with a zero price
|
||||
bool TradeItemsValid = true;
|
||||
|
||||
@@ -13362,6 +13453,10 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app)
|
||||
if (database.GetItem(gis->Items[i])) {
|
||||
database.SaveTraderItem(this->CharacterID(), gis->Items[i], gis->SerialNumber[i],
|
||||
gis->Charges[i], ints->ItemCost[i], i);
|
||||
|
||||
auto inst = FindTraderItemBySerialNumber(gis->SerialNumber[i]);
|
||||
if(inst)
|
||||
inst->SetPrice(ints->ItemCost[i]);
|
||||
}
|
||||
else {
|
||||
//return; //sony doesnt memset so assume done on first bad item
|
||||
@@ -13373,6 +13468,7 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app)
|
||||
|
||||
this->Trader_StartTrader();
|
||||
|
||||
// This refreshes the Trader window to display the End Trader button
|
||||
if (GetClientVersion() >= ClientVersion::RoF)
|
||||
{
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_Trader, sizeof(TraderStatus_Struct));
|
||||
@@ -13382,15 +13478,6 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app)
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
else if (app->size == sizeof(TraderStatus_Struct))
|
||||
{
|
||||
TraderStatus_Struct* tss = (TraderStatus_Struct*)app->pBuffer;
|
||||
|
||||
if (tss->Code == BazaarTrader_ShowItems)
|
||||
{
|
||||
Trader_ShowItems();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_Trader: Unknown TraderStruct code of: %i\n",
|
||||
ints->Code);
|
||||
@@ -13398,9 +13485,35 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app)
|
||||
Log.Out(Logs::General, Logs::Error, "Unknown TraderStruct code of: %i\n", ints->Code);
|
||||
}
|
||||
}
|
||||
else if (app->size == sizeof(TraderStatus_Struct))
|
||||
{
|
||||
TraderStatus_Struct* tss = (TraderStatus_Struct*)app->pBuffer;
|
||||
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_Trader: Trader Status Code: %d", tss->Code);
|
||||
|
||||
switch (tss->Code)
|
||||
{
|
||||
case BazaarTrader_EndTraderMode: {
|
||||
Trader_EndTrader();
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_Trader: End Trader Session");
|
||||
break;
|
||||
}
|
||||
case BazaarTrader_ShowItems: {
|
||||
Trader_ShowItems();
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_Trader: Show Trader Items");
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Unhandled action code in OP_Trader ShowItems_Struct");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if (app->size == sizeof(TraderPriceUpdate_Struct))
|
||||
{
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_Trader: Trader Price Update");
|
||||
HandleTraderPriceUpdate(app);
|
||||
}
|
||||
else {
|
||||
@@ -13419,23 +13532,22 @@ void Client::Handle_OP_TraderBuy(const EQApplicationPacket *app)
|
||||
//
|
||||
// Client has elected to buy an item from a Trader
|
||||
//
|
||||
if (app->size != sizeof(TraderBuy_Struct)) {
|
||||
Log.Out(Logs::General, Logs::Error, "Wrong size: OP_TraderBuy, size=%i, expected %i", app->size, sizeof(TraderBuy_Struct));
|
||||
return;
|
||||
}
|
||||
|
||||
if (app->size == sizeof(TraderBuy_Struct)){
|
||||
TraderBuy_Struct* tbs = (TraderBuy_Struct*)app->pBuffer;
|
||||
|
||||
TraderBuy_Struct* tbs = (TraderBuy_Struct*)app->pBuffer;
|
||||
|
||||
if (Client* Trader = entity_list.GetClientByID(tbs->TraderID)){
|
||||
|
||||
BuyTraderItem(tbs, Trader, app);
|
||||
}
|
||||
else {
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderBuy: Null Client Pointer");
|
||||
}
|
||||
if (Client* Trader = entity_list.GetClientByID(tbs->TraderID)){
|
||||
BuyTraderItem(tbs, Trader, app);
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderBuy: Buy Trader Item ");
|
||||
}
|
||||
else {
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderBuy: Struct size mismatch");
|
||||
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderBuy: Null Client Pointer");
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -13497,51 +13609,124 @@ void Client::Handle_OP_TradeRequestAck(const EQApplicationPacket *app)
|
||||
void Client::Handle_OP_TraderShop(const EQApplicationPacket *app)
|
||||
{
|
||||
// Bazaar Trader:
|
||||
//
|
||||
// This is when a potential purchaser right clicks on this client who is in Trader mode to
|
||||
// browse their goods.
|
||||
//
|
||||
|
||||
TraderClick_Struct* tcs = (TraderClick_Struct*)app->pBuffer;
|
||||
if (app->size == sizeof(TraderClick_Struct))
|
||||
{
|
||||
|
||||
if (app->size != sizeof(TraderClick_Struct)) {
|
||||
TraderClick_Struct* tcs = (TraderClick_Struct*)app->pBuffer;
|
||||
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderShop: Returning due to struct size mismatch");
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Handle_OP_TraderShop: TraderClick_Struct TraderID %d, Code %d, Unknown008 %d, Approval %d",
|
||||
tcs->TraderID, tcs->Code, tcs->Unknown008, tcs->Approval);
|
||||
|
||||
if (tcs->Code == BazaarWelcome)
|
||||
{
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderShop: Sent Bazaar Welcome Info");
|
||||
SendBazaarWelcome();
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is when a potential purchaser right clicks on this client who is in Trader mode to
|
||||
// browse their goods.
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_TraderShop, sizeof(TraderClick_Struct));
|
||||
|
||||
TraderClick_Struct* outtcs = (TraderClick_Struct*)outapp->pBuffer;
|
||||
|
||||
Client* Trader = entity_list.GetClientByID(tcs->TraderID);
|
||||
|
||||
if (Trader)
|
||||
{
|
||||
outtcs->Approval = Trader->WithCustomer(GetID());
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderShop: Shop Request (%s) to (%s) with Approval: %d", GetCleanName(), Trader->GetCleanName(), outtcs->Approval);
|
||||
}
|
||||
else {
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderShop: entity_list.GetClientByID(tcs->traderid)"
|
||||
" returned a nullptr pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
outtcs->TraderID = tcs->TraderID;
|
||||
|
||||
outtcs->Unknown008 = 0x3f800000;
|
||||
|
||||
QueuePacket(outapp);
|
||||
|
||||
|
||||
if (outtcs->Approval) {
|
||||
this->BulkSendTraderInventory(Trader->CharacterID());
|
||||
Trader->Trader_CustomerBrowsing(this);
|
||||
TraderID = tcs->TraderID;
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderShop: Trader Inventory Sent");
|
||||
}
|
||||
else
|
||||
{
|
||||
Message_StringID(clientMessageYellow, TRADER_BUSY);
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderShop: Trader Busy");
|
||||
}
|
||||
|
||||
safe_delete(outapp);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_TraderShop, sizeof(TraderClick_Struct));
|
||||
|
||||
TraderClick_Struct* outtcs = (TraderClick_Struct*)outapp->pBuffer;
|
||||
|
||||
Client* Customer = entity_list.GetClientByID(tcs->TraderID);
|
||||
|
||||
if (Customer)
|
||||
outtcs->Approval = Customer->WithCustomer(GetID());
|
||||
else {
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderShop: entity_list.GetClientByID(tcs->traderid)"
|
||||
" returned a nullptr pointer");
|
||||
return;
|
||||
else if (app->size == sizeof(BazaarWelcome_Struct))
|
||||
{
|
||||
// RoF+
|
||||
// Client requested Bazaar Welcome Info (Trader and Item Total Counts)
|
||||
SendBazaarWelcome();
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderShop: Sent Bazaar Welcome Info");
|
||||
}
|
||||
else if (app->size == sizeof(TraderBuy_Struct))
|
||||
{
|
||||
// RoF+
|
||||
// Customer has purchased an item from the Trader
|
||||
|
||||
outtcs->TraderID = tcs->TraderID;
|
||||
TraderBuy_Struct* tbs = (TraderBuy_Struct*)app->pBuffer;
|
||||
|
||||
outtcs->Unknown008 = 0x3f800000;
|
||||
if (Client* Trader = entity_list.GetClientByID(tbs->TraderID))
|
||||
{
|
||||
BuyTraderItem(tbs, Trader, app);
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Handle_OP_TraderShop: Buy Action %d, Price %d, Trader %d, ItemID %d, Quantity %d, ItemName, %s",
|
||||
tbs->Action, tbs->Price, tbs->TraderID, tbs->ItemID, tbs->Quantity, tbs->ItemName);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Out(Logs::Detail, Logs::Trading, "OP_TraderShop: Null Client Pointer");
|
||||
}
|
||||
}
|
||||
else if (app->size == 4)
|
||||
{
|
||||
// RoF+
|
||||
// Customer has closed the trade window
|
||||
uint32 Command = *((uint32 *)app->pBuffer);
|
||||
|
||||
QueuePacket(outapp);
|
||||
|
||||
|
||||
if (outtcs->Approval) {
|
||||
this->BulkSendTraderInventory(Customer->CharacterID());
|
||||
Customer->Trader_CustomerBrowsing(this);
|
||||
if (Command == 4)
|
||||
{
|
||||
Client* c = entity_list.GetClientByID(TraderID);
|
||||
TraderID = 0;
|
||||
if (c)
|
||||
{
|
||||
c->WithCustomer(0);
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_Trader: End Transaction - Code %d", Command);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_Trader: Null Client Pointer for Trader - Code %d", Command);
|
||||
}
|
||||
EQApplicationPacket empty(OP_ShopEndConfirm);
|
||||
QueuePacket(&empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_Trader: Unhandled Code %d", Command);
|
||||
}
|
||||
}
|
||||
else
|
||||
Message_StringID(clientMessageYellow, TRADER_BUSY);
|
||||
|
||||
safe_delete(outapp);
|
||||
|
||||
return;
|
||||
{
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Unknown size for OP_TraderShop: %i\n", app->size);
|
||||
Log.Out(Logs::General, Logs::Error, "Unknown size for OP_TraderShop: %i\n", app->size);
|
||||
DumpPacket(app);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Client::Handle_OP_TradeSkillCombine(const EQApplicationPacket *app)
|
||||
@@ -13704,41 +13889,32 @@ void Client::Handle_OP_TributeUpdate(const EQApplicationPacket *app)
|
||||
|
||||
void Client::Handle_OP_VetClaimRequest(const EQApplicationPacket *app)
|
||||
{
|
||||
if (app->size < sizeof(VeteranClaimRequest))
|
||||
{
|
||||
Log.Out(Logs::General, Logs::None, "OP_VetClaimRequest size lower than expected: got %u expected at least %u", app->size, sizeof(VeteranClaimRequest));
|
||||
if (app->size < sizeof(VeteranClaim)) {
|
||||
Log.Out(Logs::General, Logs::None,
|
||||
"OP_VetClaimRequest size lower than expected: got %u expected at least %u", app->size,
|
||||
sizeof(VeteranClaim));
|
||||
DumpPacket(app);
|
||||
return;
|
||||
}
|
||||
|
||||
VeteranClaimRequest *vcr = (VeteranClaimRequest*)app->pBuffer;
|
||||
VeteranClaim *vcr = (VeteranClaim *)app->pBuffer;
|
||||
|
||||
if (vcr->claim_id == 0xFFFFFFFF) //request update packet
|
||||
{
|
||||
if (vcr->claim_id == 0xFFFFFFFF) { // request update packet
|
||||
SendRewards();
|
||||
return;
|
||||
}
|
||||
else //try to claim something!
|
||||
{
|
||||
if (!TryReward(vcr->claim_id))
|
||||
{
|
||||
Message(13, "Your claim has been rejected.");
|
||||
EQApplicationPacket *vetapp = new EQApplicationPacket(OP_VetClaimReply, sizeof(VeteranClaimReply));
|
||||
VeteranClaimReply * cr = (VeteranClaimReply*)vetapp->pBuffer;
|
||||
strcpy(cr->name, GetName());
|
||||
cr->claim_id = vcr->claim_id;
|
||||
cr->reject_field = -1;
|
||||
FastQueuePacket(&vetapp);
|
||||
}
|
||||
else
|
||||
{
|
||||
EQApplicationPacket *vetapp = new EQApplicationPacket(OP_VetClaimReply, sizeof(VeteranClaimReply));
|
||||
VeteranClaimReply * cr = (VeteranClaimReply*)vetapp->pBuffer;
|
||||
strcpy(cr->name, GetName());
|
||||
cr->claim_id = vcr->claim_id;
|
||||
cr->reject_field = 0;
|
||||
FastQueuePacket(&vetapp);
|
||||
}
|
||||
}
|
||||
// try to claim something!
|
||||
EQApplicationPacket *vetapp = new EQApplicationPacket(OP_VetClaimReply, sizeof(VeteranClaim));
|
||||
VeteranClaim *cr = (VeteranClaim *)vetapp->pBuffer;
|
||||
strcpy(cr->name, GetName());
|
||||
cr->claim_id = vcr->claim_id;
|
||||
|
||||
if (!TryReward(vcr->claim_id))
|
||||
cr->action = 1;
|
||||
else
|
||||
cr->action = 0;
|
||||
|
||||
FastQueuePacket(&vetapp);
|
||||
}
|
||||
|
||||
void Client::Handle_OP_VoiceMacroIn(const EQApplicationPacket *app)
|
||||
|
||||
@@ -218,6 +218,8 @@
|
||||
void Handle_OP_PetitionRefresh(const EQApplicationPacket *app);
|
||||
void Handle_OP_PetitionResolve(const EQApplicationPacket *app);
|
||||
void Handle_OP_PetitionUnCheckout(const EQApplicationPacket *app);
|
||||
void Handle_OP_PlayerStateAdd(const EQApplicationPacket *app);
|
||||
void Handle_OP_PlayerStateRemove(const EQApplicationPacket *app);
|
||||
void Handle_OP_PickPocket(const EQApplicationPacket *app);
|
||||
void Handle_OP_PopupResponse(const EQApplicationPacket *app);
|
||||
void Handle_OP_PotionBelt(const EQApplicationPacket *app);
|
||||
|
||||
+21
-16
@@ -129,7 +129,9 @@ bool Client::Process() {
|
||||
if(IsTracking() && (GetClientVersion() >= ClientVersion::SoD) && TrackingTimer.Check())
|
||||
DoTracking();
|
||||
|
||||
if(hpupdate_timer.Check())
|
||||
// SendHPUpdate calls hpupdate_timer.Start so it can delay this timer, so lets not reset with the check
|
||||
// since the function will anyways
|
||||
if(hpupdate_timer.Check(false))
|
||||
SendHPUpdate();
|
||||
|
||||
if(mana_timer.Check())
|
||||
@@ -197,10 +199,8 @@ bool Client::Process() {
|
||||
instalog = true;
|
||||
}
|
||||
|
||||
if (IsStunned() && stunned_timer.Check()) {
|
||||
this->stunned = false;
|
||||
this->stunned_timer.Disable();
|
||||
}
|
||||
if (IsStunned() && stunned_timer.Check())
|
||||
Mob::UnStun();
|
||||
|
||||
if(!m_CheatDetectMoved)
|
||||
{
|
||||
@@ -262,9 +262,10 @@ bool Client::Process() {
|
||||
}
|
||||
|
||||
if(light_update_timer.Check()) {
|
||||
UpdateEquipLightValue();
|
||||
if(UpdateActiveLightValue()) {
|
||||
SendAppearancePacket(AT_Light, GetActiveLightValue());
|
||||
|
||||
UpdateEquipmentLight();
|
||||
if(UpdateActiveLight()) {
|
||||
SendAppearancePacket(AT_Light, GetActiveLightType());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -561,7 +562,7 @@ bool Client::Process() {
|
||||
}
|
||||
|
||||
ProjectileAttack();
|
||||
|
||||
|
||||
if(spellbonuses.GravityEffect == 1) {
|
||||
if(gravity_timer.Check())
|
||||
DoGravityEffect();
|
||||
@@ -792,7 +793,7 @@ void Client::OnDisconnect(bool hard_disconnect) {
|
||||
Mob *Other = trade->With();
|
||||
if(Other)
|
||||
{
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client disconnected during a trade. Returning their items.");
|
||||
Log.Out(Logs::Detail, Logs::Trading, "Client disconnected during a trade. Returning their items.");
|
||||
FinishTrade(this);
|
||||
|
||||
if(Other->IsClient())
|
||||
@@ -816,14 +817,14 @@ void Client::OnDisconnect(bool hard_disconnect) {
|
||||
|
||||
// Sends the client complete inventory used in character login
|
||||
|
||||
// DO WE STILL NEED THE 'ITEMCOMBINED' CONDITIONAL CODE? -U
|
||||
// DO WE STILL NEED THE 'ITEMCOMBINED' CONDITIONAL CODE?
|
||||
|
||||
//#ifdef ITEMCOMBINED
|
||||
void Client::BulkSendInventoryItems() {
|
||||
int16 slot_id = 0;
|
||||
|
||||
// LINKDEAD TRADE ITEMS
|
||||
// Move trade slot items back into normal inventory..need them there now for the proceeding validity checks -U
|
||||
// Move trade slot items back into normal inventory..need them there now for the proceeding validity checks
|
||||
for(slot_id = EmuConstants::TRADE_BEGIN; slot_id <= EmuConstants::TRADE_END; slot_id++) {
|
||||
ItemInst* inst = m_inv.PopItem(slot_id);
|
||||
if(inst) {
|
||||
@@ -837,12 +838,16 @@ void Client::BulkSendInventoryItems() {
|
||||
}
|
||||
|
||||
bool deletenorent = database.NoRentExpired(GetName());
|
||||
if(deletenorent){ RemoveNoRent(false); } //client was offline for more than 30 minutes, delete no rent items
|
||||
if (deletenorent) { //client was offline for more than 30 minutes, delete no rent items
|
||||
if (RuleB(Inventory, TransformSummonedBags))
|
||||
DisenchantSummonedBags(false);
|
||||
RemoveNoRent(false);
|
||||
}
|
||||
|
||||
RemoveDuplicateLore(false);
|
||||
MoveSlotNotAllowed(false);
|
||||
|
||||
// The previous three method calls took care of moving/removing expired/illegal item placements -U
|
||||
// The previous three method calls took care of moving/removing expired/illegal item placements
|
||||
|
||||
//TODO: this function is just retarded... it re-allocates the buffer for every
|
||||
//new item. It should be changed to loop through once, gather the
|
||||
@@ -968,7 +973,7 @@ void Client::BulkSendInventoryItems()
|
||||
void Client::BulkSendMerchantInventory(int merchant_id, int npcid) {
|
||||
const Item_Struct* handyitem = nullptr;
|
||||
uint32 numItemSlots = 80; //The max number of items passed in the transaction.
|
||||
if (ClientVersionBit & BIT_RoFAndLater) { // RoF+ can send 200 items
|
||||
if (m_ClientVersionBit & BIT_RoFAndLater) { // RoF+ can send 200 items
|
||||
numItemSlots = 200;
|
||||
}
|
||||
const Item_Struct *item;
|
||||
@@ -1894,7 +1899,7 @@ void Client::DoHPRegen() {
|
||||
}
|
||||
|
||||
void Client::DoManaRegen() {
|
||||
if (GetMana() >= max_mana)
|
||||
if (GetMana() >= max_mana && spellbonuses.ManaRegen >= 0)
|
||||
return;
|
||||
|
||||
SetMana(GetMana() + CalcManaRegen() + RestRegenMana);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user