mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-27 08:52:27 +00:00
Compare commits
426 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 46cb96a026 | |||
| bbc3733c3a | |||
| 5995afa1b8 | |||
| 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 | |||
| ff3cb9fc54 | |||
| 56e7d1b0dc | |||
| 0321bf72a5 | |||
| 739a7b6f75 | |||
| 979590db9f | |||
| 7341ecc185 | |||
| 7bd185b7b7 | |||
| 7662eaf983 | |||
| 78eb8747aa | |||
| fc1d6c0676 | |||
| 7e1c296ecf | |||
| 51a314fa31 | |||
| b3efd8a817 | |||
| bf93d72a43 | |||
| 026278504f | |||
| a5872b165f | |||
| 8bd22e8c38 | |||
| e304e67cf1 | |||
| b6a01871d8 | |||
| a569e20110 | |||
| 75146350fc | |||
| 2635d37095 | |||
| a75f4e70a1 | |||
| b6cc070633 | |||
| 94d118fdf8 | |||
| 4dcb679c53 | |||
| ad9e9ba2d6 | |||
| 279ed8d86c | |||
| c4a7acb6d1 | |||
| e6835804af | |||
| 9598ce45c9 | |||
| 9ef4825a72 | |||
| eed57ddf97 | |||
| 202c59eb48 | |||
| f86c6d9c5e | |||
| 340ed6c59d | |||
| 0cf5cca415 | |||
| f021ee5491 | |||
| 6c26bc9c8f | |||
| 93eb727ade | |||
| 1c454d9569 | |||
| 3b9f62f0a1 | |||
| 21ce5c6daa | |||
| cd82aae183 | |||
| d08d50f4b5 | |||
| c5fb9ba6dd | |||
| 2bcb964326 | |||
| b3a0370e71 | |||
| 9344cfb4e3 | |||
| bcf8b1af8e | |||
| 2003efb5ab | |||
| 13743caf19 | |||
| 6a241d44cc | |||
| b36d9fe115 | |||
| c313bd8d07 | |||
| be9066235b | |||
| 1f540666f8 | |||
| 2cf2ef4fac | |||
| c305582c77 | |||
| 69d02b7e72 | |||
| 00af95502e | |||
| c96ee79b1e | |||
| dda8ae4803 | |||
| bd9665e35b | |||
| 316aa5ef73 | |||
| 9fcdf5367e | |||
| 0210d6f6bf | |||
| fe294e60b5 | |||
| 972d3d8874 | |||
| f95806b47b | |||
| abc5ddc5f8 | |||
| 10f1e69ad8 | |||
| d3249397f3 | |||
| 69e9adf796 | |||
| 4835b7063c | |||
| 14b5a8d817 | |||
| 20cbe4af44 | |||
| 8dfa0a7220 | |||
| 7870bf103a | |||
| 2b8bdb9158 | |||
| 7851f272e5 | |||
| 18b4d068ea | |||
| e15ee6e320 | |||
| 1f0b86a0d5 | |||
| 568938d003 | |||
| 215861dd86 | |||
| e47f9d95b0 | |||
| c62cff1ce7 | |||
| 69612b44d4 | |||
| 0b6d71181f | |||
| 8bce7893ed | |||
| 318a664b09 | |||
| 180c4c3286 | |||
| 221c1f17c7 | |||
| d601a70546 | |||
| ba49e5f696 | |||
| 19fc02c284 | |||
| 4e4168852b | |||
| b05581499a | |||
| 9d866c1889 | |||
| a567812f35 | |||
| 167b6f5ebf | |||
| ca278d029e | |||
| 2bed129037 | |||
| 273574d4db | |||
| c71a5888ff | |||
| a0ea6066ed | |||
| c8c2209617 | |||
| eff818ca42 | |||
| b3c53e5907 | |||
| f511862004 | |||
| a537981ad0 | |||
| 32cb219e64 | |||
| 4f3360aa49 | |||
| e61f647bf2 | |||
| a90e9cf4c6 | |||
| 7afb29cf02 | |||
| 0a351bf6e1 | |||
| 2d617f0ea7 | |||
| 9a19d59cf7 | |||
| c5a217842f | |||
| 551c0ef368 | |||
| 921a292f5b | |||
| a5274b9b6e | |||
| 3b45a66498 | |||
| 414db873b7 | |||
| 7deb4d5e78 | |||
| fe77c6fb3f | |||
| fc2492a859 | |||
| aaa9595b59 | |||
| 2d40adcf66 | |||
| 57ccddbb36 | |||
| b6dd604de2 | |||
| 911a515923 | |||
| 701e194ece | |||
| ea38fd2421 | |||
| e7fc6420f2 | |||
| b75e6308dd | |||
| 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 | |||
| 7f65080c45 | |||
| c8acb7bd43 | |||
| 69d727cbe5 | |||
| 9daf572ea7 | |||
| f613d12c61 | |||
| 927e4f83ff | |||
| 82b9af3956 | |||
| 82933a80d1 | |||
| 543e265b0a | |||
| c4eb6e2881 | |||
| e6eb4e16d1 | |||
| 95b66583b3 | |||
| 8cde649e39 | |||
| 45e7ff9193 | |||
| 48c65628d8 | |||
| 0521cae8d0 | |||
| 4629c7c8c4 | |||
| 8b925f549b | |||
| cb81d956f6 | |||
| 1149f04389 | |||
| 9aac1b0081 | |||
| 3392f4b1c3 | |||
| 20712ce0e6 | |||
| 9a15361e93 | |||
| 452b1a1eae | |||
| edbd055277 | |||
| 7bf054bd58 | |||
| 67ee327f5b | |||
| 63810d5c1b | |||
| d5047da637 | |||
| 9446d75444 | |||
| c9cd733d9a | |||
| 5a619bddaf | |||
| 5d64012d74 | |||
| 2bf2485b4c | |||
| 8acaa47b8f | |||
| bc6199a86f | |||
| f26d303ee1 | |||
| b96e5a7f4d | |||
| 36d53f69d6 | |||
| ef5d475978 | |||
| dce6ccf4de | |||
| b169544711 | |||
| 1495eb42a3 | |||
| dd17597c92 | |||
| 54c3f9ab94 | |||
| ecd05d821e | |||
| 4bd2e04482 | |||
| cafd0eaba1 | |||
| facd7d357d | |||
| 8bc5e5eee1 | |||
| bfa6bd3458 | |||
| 33767aeb91 | |||
| ff8a19b1cb | |||
| 356316db84 | |||
| 379219aff1 | |||
| a677d40f6d | |||
| aed3d9ef85 | |||
| f2667cee23 | |||
| e1c49f93e2 | |||
| d2b9d4ab20 | |||
| 20c99e36d8 | |||
| 3ec39ce06b | |||
| 10e3c31ad6 | |||
| 4b08c75527 | |||
| 8aa8982b66 | |||
| 5daa29aa3f | |||
| 75c48e5800 | |||
| 6c982179bc | |||
| 02e56331ec | |||
| 774e429d87 | |||
| 3340d01902 | |||
| 180612bb21 | |||
| 8649ed1dcb | |||
| f9ba99e99f | |||
| 1d40f20da0 | |||
| 614014a238 | |||
| 1ff2a043f4 | |||
| 115d0d14ac | |||
| b3ea1a9da7 | |||
| 5fcd3eb38e | |||
| e35205eaf4 | |||
| 081a61a948 | |||
| d75c632d73 | |||
| d9c47fcd41 | |||
| 387b445685 | |||
| 46ac254b3a | |||
| 5f64b1e1c8 | |||
| 5c729e65c9 | |||
| 4f4eee2b16 | |||
| ed9bdaf60c | |||
| a6b95aeceb | |||
| 54fae508c5 | |||
| 0cd320dd75 | |||
| 725c5633f6 | |||
| ef082b9144 | |||
| 7fed01ddea |
+369
-205
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();
|
||||
|
||||
@@ -76,6 +78,24 @@ int GetSpellColumns(SharedDatabase *db) {
|
||||
return results.RowCount();
|
||||
}
|
||||
|
||||
bool IsStringField(int i) {
|
||||
switch(i)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ImportSpells(SharedDatabase *db) {
|
||||
Log.Out(Logs::General, Logs::Status, "Importing Spells...");
|
||||
FILE *f = fopen("import/spells_us.txt", "r");
|
||||
@@ -113,7 +133,12 @@ void ImportSpells(SharedDatabase *db) {
|
||||
sql += "'";
|
||||
}
|
||||
|
||||
sql += split[i];
|
||||
if(split[i].compare("") == 0 && !IsStringField(i)) {
|
||||
sql += "0";
|
||||
}
|
||||
else {
|
||||
sql += split[i];
|
||||
}
|
||||
sql += "'";
|
||||
}
|
||||
|
||||
@@ -128,7 +153,12 @@ void ImportSpells(SharedDatabase *db) {
|
||||
sql += "'";
|
||||
}
|
||||
|
||||
sql += split[i];
|
||||
if(split[i].compare("") == 0 && !IsStringField(i)) {
|
||||
sql += "0";
|
||||
} else {
|
||||
sql += split[i];
|
||||
}
|
||||
|
||||
sql += "'";
|
||||
}
|
||||
|
||||
@@ -174,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());
|
||||
@@ -234,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);
|
||||
}
|
||||
|
||||
+18
-1
@@ -30,9 +30,16 @@ SET(common_sources
|
||||
faction.cpp
|
||||
guild_base.cpp
|
||||
guilds.cpp
|
||||
inventory.cpp
|
||||
inventory_db_data_model.cpp
|
||||
ipc_mutex.cpp
|
||||
item.cpp
|
||||
item_container.cpp
|
||||
item_container_default_serialization.cpp
|
||||
item_container_personal_serialization.cpp
|
||||
item_instance.cpp
|
||||
md5.cpp
|
||||
memory_buffer.cpp
|
||||
memory_mapped_file.cpp
|
||||
misc.cpp
|
||||
misc_functions.cpp
|
||||
@@ -135,15 +142,25 @@ SET(common_headers
|
||||
global_define.h
|
||||
guild_base.h
|
||||
guilds.h
|
||||
inventory.h
|
||||
inventory_data_model.h
|
||||
inventory_db_data_model.h
|
||||
inventory_null_data_model.h
|
||||
ipc_mutex.h
|
||||
item.h
|
||||
item_container.h
|
||||
item_container_default_serialization.h
|
||||
item_container_personal_serialization.h
|
||||
item_container_serialization_strategy.h
|
||||
item_data.h
|
||||
item_fieldlist.h
|
||||
item_struct.h
|
||||
item_instance.h
|
||||
languages.h
|
||||
linked_list.h
|
||||
loottable.h
|
||||
mail_oplist.h
|
||||
md5.h
|
||||
memory_buffer.h
|
||||
memory_mapped_file.h
|
||||
misc.h
|
||||
misc_functions.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; }
|
||||
|
||||
+88
-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
|
||||
|
||||
@@ -46,32 +67,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 */
|
||||
|
||||
+11
-11
@@ -23,23 +23,23 @@
|
||||
namespace EQEmu
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
T Clamp(const T& value, const T& lower, const T& upper) {
|
||||
return std::max(lower, std::min(value, upper));
|
||||
template <typename T, typename U, typename V>
|
||||
T Clamp(const T& value, const U& lower, const V& upper) {
|
||||
return std::max(static_cast<T>(lower), std::min(value, static_cast<T>(upper)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T ClampLower(const T& value, const T& lower) {
|
||||
return std::max(lower, value);
|
||||
template <typename T, typename U>
|
||||
T ClampLower(const T& value, const U& lower) {
|
||||
return std::max(static_cast<T>(lower), value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T ClampUpper(const T& value, const T& upper) {
|
||||
return std::min(value, upper);
|
||||
template <typename T, typename U>
|
||||
T ClampUpper(const T& value, const U& upper) {
|
||||
return std::min(value, static_cast<T>(upper));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool ValueWithin(const T& value, const T& lower, const T& upper) {
|
||||
template <typename T, typename U, typename V>
|
||||
bool ValueWithin(const T& value, const U& lower, const V& upper) {
|
||||
return value >= lower && value <= upper;
|
||||
}
|
||||
|
||||
|
||||
+13
-3
@@ -677,7 +677,7 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe
|
||||
}
|
||||
|
||||
/* This only for new Character creation storing */
|
||||
bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv) {
|
||||
bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, InventoryOld* inv) {
|
||||
uint32 charid = 0;
|
||||
char zone[50];
|
||||
float x, y, z;
|
||||
@@ -1984,7 +1984,7 @@ void Database::GetRaidLeadershipInfo(uint32 rid, char *maintank,
|
||||
|
||||
void Database::SetRaidGroupLeaderInfo(uint32 gid, uint32 rid)
|
||||
{
|
||||
std::string query = StringFormat("UPDATE raid_leaders SET leadershipaa = '', WHERE gid = %lu AND rid = %lu",
|
||||
std::string query = StringFormat("UPDATE raid_leaders SET leadershipaa = '' WHERE gid = %lu AND rid = %lu",
|
||||
(unsigned long)gid, (unsigned long)rid);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
@@ -2154,6 +2154,16 @@ void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings)
|
||||
log_settings[log_category].log_to_file = atoi(row[3]);
|
||||
log_settings[log_category].log_to_gmsay = atoi(row[4]);
|
||||
|
||||
/* Determine if any output method is enabled for the category
|
||||
and set it to 1 so it can used to check if category is enabled */
|
||||
const bool log_to_console = log_settings[log_category].log_to_console > 0;
|
||||
const bool log_to_file = log_settings[log_category].log_to_file > 0;
|
||||
const bool log_to_gmsay = log_settings[log_category].log_to_gmsay > 0;
|
||||
const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay;
|
||||
|
||||
if (is_category_enabled)
|
||||
log_settings[log_category].is_category_enabled = 1;
|
||||
|
||||
/*
|
||||
This determines whether or not the process needs to actually file log anything.
|
||||
If we go through this whole loop and nothing is set to any debug level, there is no point to create a file or keep anything open
|
||||
@@ -2162,4 +2172,4 @@ void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings)
|
||||
Log.file_logs_enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -27,6 +27,7 @@
|
||||
#include "dbcore.h"
|
||||
#include "linked_list.h"
|
||||
#include "eq_packet_structs.h"
|
||||
#include "inventory.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
@@ -36,7 +37,7 @@
|
||||
//atoi is not uint32 or uint32 safe!!!!
|
||||
#define atoul(str) strtoul(str, nullptr, 10)
|
||||
|
||||
class Inventory;
|
||||
class InventoryOld;
|
||||
class MySQLRequestResult;
|
||||
class Client;
|
||||
|
||||
@@ -102,7 +103,7 @@ public:
|
||||
bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp);
|
||||
bool SetHackerFlag(const char* accountname, const char* charactername, const char* hacked);
|
||||
bool SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone);
|
||||
bool StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv);
|
||||
bool StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, InventoryOld* inv);
|
||||
bool UpdateName(const char* oldname, const char* newname);
|
||||
|
||||
/* General Information Queries */
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+5
-3
@@ -110,7 +110,8 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo
|
||||
|
||||
/* Implement Logging at the Root */
|
||||
if (mysql_errno(&mysql) > 0 && strlen(query) > 0){
|
||||
Log.Out(Logs::General, Logs::MySQLError, "%i: %s \n %s", mysql_errno(&mysql), mysql_error(&mysql), query);
|
||||
if (Log.log_settings[Logs::MySQLError].is_category_enabled == 1)
|
||||
Log.Out(Logs::General, Logs::MySQLError, "%i: %s \n %s", mysql_errno(&mysql), mysql_error(&mysql), query);
|
||||
}
|
||||
|
||||
return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(&mysql),errorBuffer);
|
||||
@@ -125,8 +126,9 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo
|
||||
rowCount = (uint32)mysql_num_rows(res);
|
||||
|
||||
MySQLRequestResult requestResult(res, (uint32)mysql_affected_rows(&mysql), rowCount, (uint32)mysql_field_count(&mysql), (uint32)mysql_insert_id(&mysql));
|
||||
|
||||
Log.Out(Logs::General, Logs::MySQLQuery, "%s (%u rows returned)", query, rowCount, requestResult.RowCount());
|
||||
|
||||
if (Log.log_settings[Logs::MySQLQuery].is_category_enabled == 1)
|
||||
Log.Out(Logs::General, Logs::MySQLQuery, "%s (%u rows returned)", query, rowCount, requestResult.RowCount());
|
||||
|
||||
return requestResult;
|
||||
}
|
||||
|
||||
+3
-2
@@ -348,6 +348,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 +365,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,8 +522,6 @@ 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),
|
||||
|
||||
+49
-2
@@ -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
|
||||
{
|
||||
@@ -259,7 +306,7 @@ enum AugmentationRestrictionTypes : uint8 {
|
||||
/*
|
||||
** Container use types
|
||||
**
|
||||
** This correlates to world 'object.type' (object.h/Object.cpp) as well as Item_Struct.BagType
|
||||
** This correlates to world 'object.type' (object.h/Object.cpp) as well as ItemData.BagType
|
||||
**
|
||||
** (ref: database, web forums and eqstr_us.txt)
|
||||
*/
|
||||
|
||||
+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 */
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "platform.h"
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef STATIC_OPCODE
|
||||
@@ -510,3 +511,8 @@ void DumpPacket(const EQApplicationPacket* app, bool iShowInfo) {
|
||||
// DumpPacketAscii(app->pBuffer, app->size);
|
||||
}
|
||||
|
||||
std::string DumpPacketToString(const EQApplicationPacket* app){
|
||||
std::ostringstream out;
|
||||
out << DumpPacketHexToString(app->pBuffer, app->size);
|
||||
return out.str();
|
||||
}
|
||||
+2
-1
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "base_packet.h"
|
||||
#include "platform.h"
|
||||
#include <iostream>
|
||||
|
||||
#ifdef STATIC_OPCODE
|
||||
typedef unsigned short EmuOpcode;
|
||||
@@ -146,6 +147,6 @@ protected:
|
||||
};
|
||||
|
||||
extern void DumpPacket(const EQApplicationPacket* app, bool iShowInfo = false);
|
||||
|
||||
extern std::string DumpPacketToString(const EQApplicationPacket* app);
|
||||
|
||||
#endif
|
||||
|
||||
+213
-183
@@ -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
|
||||
|
||||
@@ -24,7 +25,7 @@
|
||||
#include <list>
|
||||
#include <time.h>
|
||||
#include "../common/version.h"
|
||||
//#include "../common/item_struct.h"
|
||||
//#include "../common/item_data.h"
|
||||
|
||||
static const uint32 BUFF_COUNT = 25;
|
||||
static const uint32 MAX_MERC = 100;
|
||||
@@ -123,83 +124,89 @@ 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 Inventory_Slot_Struct
|
||||
{
|
||||
int16 type;
|
||||
int16 slot;
|
||||
int16 bag;
|
||||
int16 aug;
|
||||
};
|
||||
|
||||
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 +281,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 +375,11 @@ union
|
||||
|
||||
};
|
||||
|
||||
struct PlayerState_Struct {
|
||||
/*00*/ uint32 spawn_id;
|
||||
/*04*/ uint32 state;
|
||||
};
|
||||
|
||||
/*
|
||||
** New Spawn
|
||||
** Length: 176 Bytes
|
||||
@@ -548,7 +561,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 +574,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 +592,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 +734,7 @@ struct AA_Array
|
||||
{
|
||||
uint32 AA;
|
||||
uint32 value;
|
||||
uint32 charges;
|
||||
};
|
||||
|
||||
|
||||
@@ -756,29 +764,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 +1128,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 +1169,7 @@ struct TargetReject_Struct {
|
||||
|
||||
struct PetCommand_Struct {
|
||||
/*000*/ uint32 command;
|
||||
/*004*/ uint32 unknown;
|
||||
/*004*/ uint32 target;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1249,7 +1274,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 +1288,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 +1327,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 */
|
||||
};
|
||||
|
||||
@@ -1541,7 +1566,7 @@ struct DeleteItem_Struct {
|
||||
/*0012*/
|
||||
};
|
||||
|
||||
struct MoveItem_Struct
|
||||
struct MoveItemOld_Struct
|
||||
{
|
||||
/*0000*/ uint32 from_slot;
|
||||
/*0004*/ uint32 to_slot;
|
||||
@@ -1549,6 +1574,19 @@ struct MoveItem_Struct
|
||||
/*0012*/
|
||||
};
|
||||
|
||||
struct MoveItem_Struct
|
||||
{
|
||||
int16 from_type;
|
||||
int16 from_slot;
|
||||
int16 from_bag_slot;
|
||||
int16 from_aug_slot;
|
||||
int16 to_type;
|
||||
int16 to_slot;
|
||||
int16 to_bag_slot;
|
||||
int16 to_aug_slot;
|
||||
uint32 number_in_stack;
|
||||
};
|
||||
|
||||
// both MoveItem_Struct/DeleteItem_Struct server structures will be changing to a structure-based slot format..this will
|
||||
// be used for handling SoF/SoD/etc... time stamps sent using the MoveItem_Struct format. (nothing will be done with this
|
||||
// info at the moment..but, it is forwarded on to the server for handling/future use)
|
||||
@@ -1940,13 +1978,11 @@ Unknowns:
|
||||
|
||||
|
||||
struct Merchant_Sell_Struct {
|
||||
/*000*/ uint32 npcid; // Merchant NPC's entity id
|
||||
/*004*/ uint32 playerid; // Player's entity id
|
||||
/*008*/ uint32 itemslot;
|
||||
uint32 unknown12;
|
||||
/*016*/ uint8 quantity; // Already sold
|
||||
/*017*/ uint8 Unknown016[3];
|
||||
/*020*/ uint32 price;
|
||||
uint32 npcid;
|
||||
uint32 playerid;
|
||||
uint32 itemslot;
|
||||
int32 quantity;
|
||||
uint32 price;
|
||||
};
|
||||
struct Merchant_Purchase_Struct {
|
||||
/*000*/ uint32 npcid; // Merchant NPC's entity id
|
||||
@@ -2082,7 +2118,7 @@ struct AdventureLeaderboard_Struct
|
||||
/*struct Item_Shop_Struct {
|
||||
uint16 merchantid;
|
||||
uint8 itemtype;
|
||||
Item_Struct item;
|
||||
ItemData item;
|
||||
uint8 iss_unknown001[6];
|
||||
};*/
|
||||
|
||||
@@ -2132,24 +2168,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 +2441,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 +2554,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 +2573,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 +2631,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 +2797,8 @@ struct BazaarWelcome_Struct {
|
||||
BazaarWindowStart_Struct Beginning;
|
||||
uint32 Traders;
|
||||
uint32 Items;
|
||||
uint8 Unknown012[8];
|
||||
uint32 Unknown012;
|
||||
uint32 Unknown016;
|
||||
};
|
||||
|
||||
struct BazaarSearch_Struct {
|
||||
@@ -3146,6 +3183,7 @@ struct Trader_ShowItems_Struct{
|
||||
/*000*/ uint32 Code;
|
||||
/*004*/ uint32 TraderID;
|
||||
/*008*/ uint32 Unknown08[3];
|
||||
/*020*/
|
||||
};
|
||||
|
||||
struct TraderBuy_Struct{
|
||||
@@ -3191,9 +3229,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 +4050,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 +4143,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 +4296,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 +4313,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 +4566,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 +4743,7 @@ struct BuffIconEntry_Struct
|
||||
{
|
||||
uint32 buff_slot;
|
||||
uint32 spell_id;
|
||||
uint32 tics_remaining;
|
||||
int32 tics_remaining;
|
||||
uint32 num_hits;
|
||||
};
|
||||
|
||||
@@ -4723,6 +4752,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];
|
||||
};
|
||||
|
||||
|
||||
+50
-27
@@ -23,6 +23,7 @@
|
||||
#include "op_codes.h"
|
||||
#include "crc16.h"
|
||||
#include "platform.h"
|
||||
#include "string_util.h"
|
||||
|
||||
#include <string>
|
||||
#include <iomanip>
|
||||
@@ -71,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;
|
||||
|
||||
@@ -463,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;
|
||||
@@ -555,21 +566,35 @@ void EQStream::FastQueuePacket(EQApplicationPacket **p, bool ack_req)
|
||||
|
||||
void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p)
|
||||
{
|
||||
uint32 chunksize,used;
|
||||
uint32 chunksize, used;
|
||||
uint32 length;
|
||||
|
||||
if (Log.log_settings[Logs::Server_Client_Packet].is_category_enabled == 1){
|
||||
if (p->GetOpcode() != OP_SpecialMesg){
|
||||
Log.Out(Logs::General, Logs::Server_Client_Packet, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size());
|
||||
}
|
||||
}
|
||||
|
||||
if (Log.log_settings[Logs::Server_Client_Packet_With_Dump].is_category_enabled == 1){
|
||||
if (p->GetOpcode() != OP_SpecialMesg){
|
||||
Log.Out(Logs::General, Logs::Server_Client_Packet_With_Dump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size(), DumpPacketToString(p).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
@@ -580,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;
|
||||
@@ -951,14 +976,12 @@ EQRawApplicationPacket *p=nullptr;
|
||||
}
|
||||
MInboundQueue.unlock();
|
||||
|
||||
//resolve the opcode if we can.
|
||||
if(p) {
|
||||
if(OpMgr != nullptr && *OpMgr != nullptr) {
|
||||
if (p) {
|
||||
if (OpMgr != nullptr && *OpMgr != nullptr) {
|
||||
EmuOpcode emu_op = (*OpMgr)->EQToEmu(p->opcode);
|
||||
if (emu_op == OP_Unknown) {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[ERROR] Unable to convert EQ opcode 0x%.4x to an Application opcode.", p->opcode);
|
||||
}
|
||||
|
||||
// Log.Out(Logs::General, Logs::Client_Server_Packet_Unhandled, "Unknown :: [%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->opcode, p->Size(), DumpPacketToString(p).c_str());
|
||||
}
|
||||
p->SetOpcode(emu_op);
|
||||
}
|
||||
}
|
||||
@@ -1090,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:
|
||||
|
||||
@@ -288,7 +288,7 @@ void EQEmuLogSys::Out(Logs::DebugLevel debug_level, uint16 log_category, std::st
|
||||
|
||||
if (log_to_console) EQEmuLogSys::ProcessConsoleMessage(debug_level, log_category, output_debug_message);
|
||||
if (log_to_gmsay) EQEmuLogSys::ProcessGMSay(debug_level, log_category, output_debug_message);
|
||||
if (log_to_file) EQEmuLogSys::ProcessLogWrite(debug_level, log_category, output_message);
|
||||
if (log_to_file) EQEmuLogSys::ProcessLogWrite(debug_level, log_category, output_debug_message);
|
||||
}
|
||||
|
||||
void EQEmuLogSys::SetCurrentTimeStamp(char* time_stamp)
|
||||
|
||||
+11
-2
@@ -78,6 +78,10 @@ namespace Logs {
|
||||
MySQLQuery,
|
||||
Mercenaries,
|
||||
QuestDebug,
|
||||
Server_Client_Packet,
|
||||
Client_Server_Packet_Unhandled,
|
||||
Server_Client_Packet_With_Dump,
|
||||
Client_Server_Packet_With_Dump,
|
||||
MaxCategoryID /* Don't Remove this*/
|
||||
};
|
||||
|
||||
@@ -88,7 +92,7 @@ namespace Logs {
|
||||
"AI",
|
||||
"Aggro",
|
||||
"Attack",
|
||||
"Client Server Packet",
|
||||
"Packet :: Client -> Server",
|
||||
"Combat",
|
||||
"Commands",
|
||||
"Crash",
|
||||
@@ -121,7 +125,11 @@ namespace Logs {
|
||||
"MySQL Error",
|
||||
"MySQL Query",
|
||||
"Mercenaries",
|
||||
"Quest Debug"
|
||||
"Quest Debug",
|
||||
"Packet :: Server -> Client",
|
||||
"Packet :: Client -> Server Unhandled",
|
||||
"Packet :: Server -> Client (Dump)",
|
||||
"Packet :: Client -> Server (Dump)",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -160,6 +168,7 @@ public:
|
||||
uint8 log_to_file;
|
||||
uint8 log_to_console;
|
||||
uint8 log_to_gmsay;
|
||||
uint8 is_category_enabled; /* When any log output in a category > 0, set this to 1 as (Enabled) */
|
||||
};
|
||||
|
||||
/* Internally used memory reference for all log settings per category.
|
||||
|
||||
+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,782 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
#include "inventory.h"
|
||||
#include "inventory_null_data_model.h"
|
||||
#include "item_container_personal_serialization.h"
|
||||
#include "data_verification.h"
|
||||
#include "string_util.h"
|
||||
#include <map>
|
||||
|
||||
bool EQEmu::InventorySlot::IsValid() const {
|
||||
if(type_ == InvTypePersonal && EQEmu::ValueWithin(slot_, PersonalSlotCharm, PersonalSlotCursor)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(type_ == InvTypeBank && EQEmu::ValueWithin(slot_, 0, 23)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(type_ == InvTypeSharedBank && EQEmu::ValueWithin(slot_, 0, 1)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(type_ == InvTypeTribute && EQEmu::ValueWithin(slot_, 0, 4)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(type_ == InvTypeTrade && EQEmu::ValueWithin(slot_, 0, 7)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(type_ == InvTypeWorld && EQEmu::ValueWithin(slot_, 0, 255)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EQEmu::InventorySlot::IsDelete() const {
|
||||
return type_ == -1 && slot_ == -1 && bag_index_ == -1 && aug_index_ == -1;
|
||||
}
|
||||
|
||||
bool EQEmu::InventorySlot::IsBank() const {
|
||||
if(type_ == InvTypeBank && EQEmu::ValueWithin(slot_, 0, 23)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(type_ == InvTypeSharedBank && EQEmu::ValueWithin(slot_, 0, 1)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EQEmu::InventorySlot::IsCursor() const {
|
||||
if(type_ == InvTypePersonal && slot_ == PersonalSlotCursor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(type_ == InvTypeCursorBuffer) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EQEmu::InventorySlot::IsEquipment() const {
|
||||
if(type_ == InvTypePersonal && EQEmu::ValueWithin(slot_, PersonalSlotCharm, PersonalSlotAmmo)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EQEmu::InventorySlot::IsGeneral() const {
|
||||
if(type_ == InvTypePersonal && EQEmu::ValueWithin(slot_, PersonalSlotGeneral1, PersonalSlotGeneral10)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EQEmu::InventorySlot::IsWeapon() const {
|
||||
if(type_ == InvTypePersonal &&
|
||||
(EQEmu::ValueWithin(slot_, PersonalSlotPrimary, PersonalSlotSecondary) || slot_ == PersonalSlotRange))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EQEmu::InventorySlot::IsTrade() const {
|
||||
if(type_ == InvTypeTrade) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string EQEmu::InventorySlot::ToString() const {
|
||||
return StringFormat("(%i, %i, %i, %i)", type_, slot_, bag_index_, aug_index_);
|
||||
}
|
||||
|
||||
struct EQEmu::Inventory::impl
|
||||
{
|
||||
std::map<int, ItemContainer> containers_;
|
||||
int race_;
|
||||
int class_;
|
||||
int deity_;
|
||||
std::unique_ptr<InventoryDataModel> data_model_;
|
||||
};
|
||||
|
||||
EQEmu::Inventory::Inventory(int race, int class_, int deity) {
|
||||
impl_ = new impl;
|
||||
impl_->race_ = race;
|
||||
impl_->class_ = class_;
|
||||
impl_->deity_ = deity;
|
||||
impl_->data_model_ = std::unique_ptr<InventoryDataModel>(new InventoryNullDataModel());
|
||||
}
|
||||
|
||||
EQEmu::Inventory::~Inventory() {
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
void EQEmu::Inventory::SetRace(int race) {
|
||||
impl_->race_ = race;
|
||||
}
|
||||
|
||||
void EQEmu::Inventory::SetClass(int class_) {
|
||||
impl_->class_ = class_;
|
||||
}
|
||||
|
||||
void EQEmu::Inventory::SetDeity(int deity) {
|
||||
impl_->deity_ = deity;
|
||||
}
|
||||
|
||||
void EQEmu::Inventory::SetDataModel(InventoryDataModel *dm) {
|
||||
impl_->data_model_ = std::unique_ptr<InventoryDataModel>(dm);
|
||||
}
|
||||
|
||||
EQEmu::ItemInstance::pointer EQEmu::Inventory::Get(const InventorySlot &slot) {
|
||||
auto iter = impl_->containers_.find(slot.Type());
|
||||
if(iter != impl_->containers_.end()) {
|
||||
auto item = iter->second.Get(slot.Slot());
|
||||
if(item) {
|
||||
if(slot.BagIndex() > -1) {
|
||||
auto sub_item = item->Get(slot.BagIndex());
|
||||
if(sub_item) {
|
||||
if(slot.AugIndex() > -1) {
|
||||
return sub_item->Get(slot.AugIndex());
|
||||
} else {
|
||||
return sub_item;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ItemInstance::pointer(nullptr);
|
||||
}
|
||||
|
||||
bool EQEmu::Inventory::Put(const InventorySlot &slot, ItemInstance::pointer &inst) {
|
||||
if(impl_->containers_.count(slot.Type()) == 0) {
|
||||
if(slot.Type() == 0) {
|
||||
impl_->containers_.insert(std::pair<int, ItemContainer>(slot.Type(), ItemContainer(new ItemContainerPersonalSerialization())));
|
||||
} else {
|
||||
impl_->containers_.insert(std::pair<int, ItemContainer>(slot.Type(), ItemContainer()));
|
||||
}
|
||||
}
|
||||
|
||||
//Verify item can be put into the slot requested
|
||||
|
||||
auto &container = impl_->containers_[slot.Type()];
|
||||
if(slot.BagIndex() > -1) {
|
||||
auto item = container.Get(slot.Slot());
|
||||
if(!item)
|
||||
return false;
|
||||
|
||||
if(slot.AugIndex() > -1) {
|
||||
auto bag_item = item->Get(slot.BagIndex());
|
||||
if(!bag_item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return bag_item->Put(slot.AugIndex(), inst);
|
||||
} else {
|
||||
return item->Put(slot.BagIndex(), inst);
|
||||
}
|
||||
} else {
|
||||
if(slot.AugIndex() > -1) {
|
||||
auto item = container.Get(slot.Slot());
|
||||
if(!item)
|
||||
return false;
|
||||
|
||||
return item->Put(slot.AugIndex(), inst);
|
||||
}
|
||||
|
||||
return container.Put(slot.Slot(), inst);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EQEmu::Inventory::Swap(const InventorySlot &src, const InventorySlot &dest, int charges) {
|
||||
if(src == dest) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!src.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(src.Type() == InvTypeCursorBuffer || dest.Type() == InvTypeCursorBuffer) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(dest.IsDelete()) {
|
||||
impl_->data_model_->Begin();
|
||||
bool v = _destroy(src);
|
||||
if(v) {
|
||||
impl_->data_model_->Commit();
|
||||
}
|
||||
else {
|
||||
impl_->data_model_->Rollback();
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
if(!dest.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto i_src = Get(src);
|
||||
auto i_dest = Get(dest);
|
||||
|
||||
if(!i_src) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(i_src->GetBaseItem()->ItemClass == ItemClassContainer && dest.BagIndex() > -1) {
|
||||
if(i_src->GetContainer()->Size() > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(dest.IsEquipment() && !CanEquip(i_src, dest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Check this -> trade no drop
|
||||
if(dest.IsTrade() && i_src->IsNoDrop()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
impl_->data_model_->Begin();
|
||||
if(i_src->IsStackable()) {
|
||||
//move # charges from src to dest
|
||||
|
||||
//0 means *all* the charges
|
||||
if(charges == 0) {
|
||||
charges = i_src->GetCharges();
|
||||
}
|
||||
|
||||
//src needs to have that many charges
|
||||
if(i_src->GetCharges() < charges) {
|
||||
impl_->data_model_->Rollback();
|
||||
return false;
|
||||
}
|
||||
|
||||
//if dest exists it needs to not only be the same item id but also be able to hold enough charges to combine
|
||||
//we can also swap if src id != dest id
|
||||
if(i_dest) {
|
||||
uint32 src_id = i_src->GetBaseItem()->ID;
|
||||
uint32 dest_id = i_dest->GetBaseItem()->ID;
|
||||
if(src_id != dest_id) {
|
||||
bool v = _swap(src, dest);
|
||||
if(v) {
|
||||
impl_->data_model_->Commit();
|
||||
}
|
||||
else {
|
||||
impl_->data_model_->Rollback();
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
int charges_avail = i_dest->GetBaseItem()->StackSize - i_dest->GetCharges();
|
||||
if(charges_avail < charges) {
|
||||
impl_->data_model_->Rollback();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(i_src->GetCharges() == charges) {
|
||||
if(!_destroy(src)) {
|
||||
impl_->data_model_->Rollback();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
i_src->SetCharges(i_src->GetCharges() - charges);
|
||||
impl_->data_model_->Insert(src, i_src);
|
||||
}
|
||||
|
||||
i_dest->SetCharges(i_dest->GetCharges() + charges);
|
||||
impl_->data_model_->Delete(dest);
|
||||
impl_->data_model_->Insert(dest, i_dest);
|
||||
impl_->data_model_->Commit();
|
||||
return true;
|
||||
} else {
|
||||
//if dest does not exist and src charges > # charges then we need to create a new item with # charges in dest
|
||||
//if dest does not exist and src charges == # charges then we need to swap src to dest
|
||||
if(i_src->GetCharges() > charges) {
|
||||
auto split = i_src->Split(charges);
|
||||
if(!split) {
|
||||
impl_->data_model_->Rollback();
|
||||
return false;
|
||||
}
|
||||
|
||||
Put(dest, split);
|
||||
impl_->data_model_->Delete(src);
|
||||
impl_->data_model_->Delete(dest);
|
||||
impl_->data_model_->Insert(src, i_src);
|
||||
impl_->data_model_->Insert(dest, split);
|
||||
impl_->data_model_->Commit();
|
||||
return true;
|
||||
} else {
|
||||
bool v = _swap(src, dest);
|
||||
if(v) {
|
||||
impl_->data_model_->Commit();
|
||||
} else {
|
||||
impl_->data_model_->Rollback();
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bool v = _swap(src, dest);
|
||||
if(v) {
|
||||
impl_->data_model_->Commit();
|
||||
}
|
||||
else {
|
||||
impl_->data_model_->Rollback();
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
impl_->data_model_->Commit();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EQEmu::Inventory::Summon(const InventorySlot &slot, ItemInstance::pointer &inst) {
|
||||
if(!inst)
|
||||
return false;
|
||||
|
||||
if(CheckLoreConflict(inst->GetBaseItem())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto cur = Get(slot);
|
||||
if(cur) {
|
||||
if(slot.IsCursor()) {
|
||||
PushToCursorBuffer(inst);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
impl_->data_model_->Begin();
|
||||
bool v = Put(slot, inst);
|
||||
if(v) {
|
||||
impl_->data_model_->Insert(slot, inst);
|
||||
impl_->data_model_->Commit();
|
||||
} else {
|
||||
impl_->data_model_->Rollback();
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
bool EQEmu::Inventory::PushToCursorBuffer(ItemInstance::pointer &inst) {
|
||||
if(impl_->containers_.count(InvTypeCursorBuffer) == 0) {
|
||||
impl_->containers_.insert(std::pair<int, ItemContainer>(InvTypeCursorBuffer, ItemContainer()));
|
||||
}
|
||||
|
||||
int32 top = 0;
|
||||
auto &container = impl_->containers_[InvTypeCursorBuffer];
|
||||
auto iter = container.Begin();
|
||||
while(iter != container.End()) {
|
||||
top = iter->first;
|
||||
++iter;
|
||||
}
|
||||
|
||||
InventorySlot slot(InvTypeCursorBuffer, top + 1);
|
||||
impl_->data_model_->Begin();
|
||||
bool v = Put(slot, inst);
|
||||
if(v) {
|
||||
impl_->data_model_->Insert(slot, inst);
|
||||
impl_->data_model_->Commit();
|
||||
}
|
||||
else {
|
||||
impl_->data_model_->Rollback();
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
bool EQEmu::Inventory::PopFromCursorBuffer() {
|
||||
InventorySlot cursor(InvTypePersonal, PersonalSlotCursor);
|
||||
auto inst = Get(cursor);
|
||||
if(inst) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(impl_->containers_.count(InvTypeCursorBuffer) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32 top = 0;
|
||||
auto &container = impl_->containers_[InvTypeCursorBuffer];
|
||||
auto iter = container.Begin();
|
||||
while(iter != container.End()) {
|
||||
top = iter->first;
|
||||
++iter;
|
||||
}
|
||||
|
||||
InventorySlot slot(InvTypeCursorBuffer, top);
|
||||
inst = Get(slot);
|
||||
|
||||
if(inst) {
|
||||
impl_->data_model_->Begin();
|
||||
|
||||
bool v = _destroy(slot);
|
||||
impl_->data_model_->Delete(slot);
|
||||
|
||||
if(!v) {
|
||||
impl_->data_model_->Rollback();
|
||||
return false;
|
||||
}
|
||||
|
||||
v = Put(cursor, inst);
|
||||
impl_->data_model_->Insert(cursor, inst);
|
||||
if(!v) {
|
||||
impl_->data_model_->Rollback();
|
||||
return false;
|
||||
}
|
||||
|
||||
impl_->data_model_->Commit();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
EQEmu::InventorySlot EQEmu::Inventory::FindFreeSlot(ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end) {
|
||||
bool for_bag = inst->GetItem()->ItemClass == ItemClassContainer;
|
||||
int min_size = inst->GetItem()->Size;
|
||||
bool is_arrow = inst->GetItem()->ItemType == ItemTypeArrow;
|
||||
|
||||
//check upper level inventory
|
||||
for(int i = slot_id_start; i <= slot_id_end; ++i) {
|
||||
EQEmu::InventorySlot slot(container_id, i);
|
||||
if(!Get(slot)) {
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
|
||||
//if not for a bag then check inside bags
|
||||
if (!for_bag) {
|
||||
for(int i = slot_id_start; i <= slot_id_end; ++i) {
|
||||
EQEmu::InventorySlot slot(container_id, i);
|
||||
auto inst = Get(slot);
|
||||
|
||||
if(inst && inst->GetBaseItem()->ItemClass == ItemClassContainer && inst->GetBaseItem()->BagSize >= min_size)
|
||||
{
|
||||
if(inst->GetBaseItem()->BagType == BagTypeQuiver && !is_arrow)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int slots = inst->GetBaseItem()->BagSlots;
|
||||
for(int b_i = 0; b_i < slots; ++b_i) {
|
||||
EQEmu::InventorySlot bag_slot(container_id, i, b_i);
|
||||
|
||||
if(!Get(bag_slot)) {
|
||||
return bag_slot;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EQEmu::InventorySlot();
|
||||
}
|
||||
|
||||
int EQEmu::Inventory::FindFreeStackSlots(ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end) {
|
||||
if(!inst->IsStackable()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool is_arrow = inst->GetItem()->ItemType == ItemTypeArrow;
|
||||
int item_id = inst->GetItem()->ID;
|
||||
|
||||
int charges_to_check = inst->GetCharges();
|
||||
int charges = 0;
|
||||
|
||||
auto iter = impl_->containers_.find(container_id);
|
||||
if(iter == impl_->containers_.end()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto &container = iter->second;
|
||||
for(int i = slot_id_start; i <= slot_id_end; ++i) {
|
||||
auto current = container.Get(i);
|
||||
if(!current) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(current->GetItem()->ID == item_id) {
|
||||
int free_charges = current->GetItem()->StackSize - current->GetCharges();
|
||||
if(free_charges)
|
||||
charges += free_charges;
|
||||
|
||||
if(charges >= charges_to_check) {
|
||||
return charges_to_check;
|
||||
}
|
||||
} else if(current->GetItem()->ItemClass == ItemClassContainer) {
|
||||
int sz = current->GetItem()->BagSlots;
|
||||
for(int i = 0; i < sz; ++i) {
|
||||
auto sub_item = current->Get(i);
|
||||
if(!sub_item) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(sub_item->GetItem()->ID == item_id) {
|
||||
int free_charges = sub_item->GetItem()->StackSize - sub_item->GetCharges();
|
||||
if(free_charges)
|
||||
charges += free_charges;
|
||||
|
||||
if(charges >= charges_to_check) {
|
||||
return charges_to_check;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(charges >= charges_to_check) {
|
||||
return charges_to_check;
|
||||
}
|
||||
|
||||
return charges;
|
||||
}
|
||||
|
||||
void EQEmu::Inventory::UpdateSlot(const InventorySlot &slot, ItemInstance::pointer &inst) {
|
||||
impl_->data_model_->Begin();
|
||||
|
||||
impl_->data_model_->Delete(slot);
|
||||
if(inst) {
|
||||
impl_->data_model_->Insert(slot, inst);
|
||||
}
|
||||
|
||||
impl_->data_model_->Commit();
|
||||
}
|
||||
|
||||
int EQEmu::Inventory::CalcMaterialFromSlot(const InventorySlot &slot) {
|
||||
if(slot.Type() != 0)
|
||||
return _MaterialInvalid;
|
||||
|
||||
switch(slot.Slot()) {
|
||||
case PersonalSlotHead:
|
||||
return MaterialHead;
|
||||
case PersonalSlotChest:
|
||||
return MaterialChest;
|
||||
case PersonalSlotArms:
|
||||
return MaterialArms;
|
||||
case PersonalSlotWrist1:
|
||||
return MaterialWrist;
|
||||
case PersonalSlotHands:
|
||||
return MaterialHands;
|
||||
case PersonalSlotLegs:
|
||||
return MaterialLegs;
|
||||
case PersonalSlotFeet:
|
||||
return MaterialFeet;
|
||||
case PersonalSlotPrimary:
|
||||
return MaterialPrimary;
|
||||
case PersonalSlotSecondary:
|
||||
return MaterialSecondary;
|
||||
default:
|
||||
return _MaterialInvalid;
|
||||
}
|
||||
}
|
||||
|
||||
EQEmu::InventorySlot EQEmu::Inventory::CalcSlotFromMaterial(int material) {
|
||||
switch(material)
|
||||
{
|
||||
case MaterialHead:
|
||||
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotHead);
|
||||
case MaterialChest:
|
||||
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotChest);
|
||||
case MaterialArms:
|
||||
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotArms);
|
||||
case MaterialWrist:
|
||||
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotWrist1);
|
||||
case MaterialHands:
|
||||
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotHands);
|
||||
case MaterialLegs:
|
||||
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotLegs);
|
||||
case MaterialFeet:
|
||||
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotFeet);
|
||||
case MaterialPrimary:
|
||||
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotPrimary);
|
||||
case MaterialSecondary:
|
||||
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotSecondary);
|
||||
default:
|
||||
return EQEmu::InventorySlot(-1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
bool EQEmu::Inventory::CanEquip(EQEmu::ItemInstance::pointer &inst, const EQEmu::InventorySlot &slot) {
|
||||
if(!inst) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(slot.Type() != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!EQEmu::ValueWithin(slot.Slot(), EQEmu::PersonalSlotCharm, EQEmu::PersonalSlotAmmo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto item = inst->GetItem();
|
||||
//check slot
|
||||
|
||||
int use_slot = -1;
|
||||
if(slot.Slot() == EQEmu::PersonalSlotPowerSource) {
|
||||
use_slot = EQEmu::PersonalSlotAmmo;
|
||||
}
|
||||
else if(slot.Slot() == EQEmu::PersonalSlotAmmo) {
|
||||
use_slot = EQEmu::PersonalSlotPowerSource;
|
||||
}
|
||||
else {
|
||||
use_slot = slot.Slot();
|
||||
}
|
||||
|
||||
if(!(item->Slots & (1 << use_slot))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//todo: check deity
|
||||
if(!item->IsEquipable(impl_->race_, impl_->class_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Checking augments
|
||||
auto iter = inst->GetContainer()->Begin();
|
||||
auto end = inst->GetContainer()->End();
|
||||
while(iter != end) {
|
||||
EQEmu::ItemInstance::pointer itm = iter->second;
|
||||
if(!CanEquip(itm, InventorySlot(slot.Type(), slot.Slot(), slot.BagIndex(), iter->first))) {
|
||||
return false;
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EQEmu::Inventory::CheckLoreConflict(const ItemData *item) {
|
||||
if(!item)
|
||||
return false;
|
||||
|
||||
if(!item->LoreFlag)
|
||||
return false;
|
||||
|
||||
if(item->LoreGroup == 0)
|
||||
return false;
|
||||
|
||||
if(item->LoreGroup == 0xFFFFFFFF) {
|
||||
//look everywhere except shared bank
|
||||
for(auto &container : impl_->containers_) {
|
||||
if(container.first != InvTypeSharedBank && container.second.HasItem(item->ID)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
//look everywhere except shared bank
|
||||
for(auto &container : impl_->containers_) {
|
||||
if(container.first != InvTypeSharedBank && container.second.HasItemByLoreGroup(item->LoreGroup)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EQEmu::Inventory::Serialize(MemoryBuffer &buf) {
|
||||
buf.SetWritePosition(0);
|
||||
buf.SetReadPosition(0);
|
||||
buf.Resize(0);
|
||||
buf.Write<int32>(105);
|
||||
|
||||
bool value = false;
|
||||
for(auto &iter : impl_->containers_) {
|
||||
bool v = iter.second.Serialize(buf, iter.first);
|
||||
if(v && !value) {
|
||||
value = true;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void EQEmu::Inventory::Interrogate() {
|
||||
printf("Inventory:\n");
|
||||
printf("Class: %u, Race: %u, Deity: %u\n", impl_->class_, impl_->race_, impl_->deity_);
|
||||
for(auto &iter : impl_->containers_) {
|
||||
printf("Container: %u\n", iter.first);
|
||||
iter.second.Interrogate(1);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
bool EQEmu::Inventory::_swap(const InventorySlot &src, const InventorySlot &dest) {
|
||||
auto src_i = Get(src);
|
||||
auto dest_i = Get(dest);
|
||||
|
||||
if(src_i) {
|
||||
if(!_destroy(src)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(dest_i) {
|
||||
if(!_destroy(dest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
impl_->data_model_->Insert(src, dest_i);
|
||||
if(!Put(src, dest_i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(src_i) {
|
||||
impl_->data_model_->Insert(dest, src_i);
|
||||
if(!Put(dest, src_i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EQEmu::Inventory::_destroy(const InventorySlot &slot) {
|
||||
bool v = Put(slot, EQEmu::ItemInstance::pointer(nullptr));
|
||||
impl_->data_model_->Delete(slot);
|
||||
return v;
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/* 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 COMMON_INVENTORY_H
|
||||
#define COMMON_INVENTORY_H
|
||||
|
||||
#include "item_container.h"
|
||||
#include <string>
|
||||
|
||||
namespace EQEmu
|
||||
{
|
||||
enum InventoryType : int
|
||||
{
|
||||
InvTypePersonal = 0,
|
||||
InvTypeBank,
|
||||
InvTypeSharedBank,
|
||||
InvTypeTrade,
|
||||
InvTypeWorld,
|
||||
InvTypeCursorBuffer,
|
||||
InvTypeTribute,
|
||||
InvTypeTrophyTribute,
|
||||
InvTypeGuildTribute,
|
||||
InvTypeMerchant
|
||||
};
|
||||
|
||||
enum PersonaInventorySlot : int
|
||||
{
|
||||
PersonalSlotCharm = 0,
|
||||
PersonalSlotEar1,
|
||||
PersonalSlotHead,
|
||||
PersonalSlotFace,
|
||||
PersonalSlotEar2,
|
||||
PersonalSlotNeck,
|
||||
PersonalSlotShoulders,
|
||||
PersonalSlotArms,
|
||||
PersonalSlotBack,
|
||||
PersonalSlotWrist1,
|
||||
PersonalSlotWrist2,
|
||||
PersonalSlotRange,
|
||||
PersonalSlotHands,
|
||||
PersonalSlotPrimary,
|
||||
PersonalSlotSecondary,
|
||||
PersonalSlotFinger1,
|
||||
PersonalSlotFinger2,
|
||||
PersonalSlotChest,
|
||||
PersonalSlotLegs,
|
||||
PersonalSlotFeet,
|
||||
PersonalSlotWaist,
|
||||
PersonalSlotPowerSource,
|
||||
PersonalSlotAmmo,
|
||||
PersonalSlotGeneral1,
|
||||
PersonalSlotGeneral2,
|
||||
PersonalSlotGeneral3,
|
||||
PersonalSlotGeneral4,
|
||||
PersonalSlotGeneral5,
|
||||
PersonalSlotGeneral6,
|
||||
PersonalSlotGeneral7,
|
||||
PersonalSlotGeneral8,
|
||||
PersonalSlotGeneral9,
|
||||
PersonalSlotGeneral10,
|
||||
PersonalSlotCursor
|
||||
};
|
||||
|
||||
class InventorySlot
|
||||
{
|
||||
public:
|
||||
InventorySlot() : type_(-1), slot_(-1), bag_index_(-1), aug_index_(-1) { }
|
||||
InventorySlot(int type, int slot)
|
||||
: type_(type), slot_(slot), bag_index_(-1), aug_index_(-1) { }
|
||||
InventorySlot(int type, int slot, int bag_index)
|
||||
: type_(type), slot_(slot), bag_index_(bag_index), aug_index_(-1) { }
|
||||
InventorySlot(int type, int slot, int bag_index, int aug_index)
|
||||
: type_(type), slot_(slot), bag_index_(bag_index), aug_index_(aug_index) { }
|
||||
|
||||
bool IsValid() const;
|
||||
bool IsDelete() const;
|
||||
bool IsBank() const;
|
||||
bool IsCursor() const;
|
||||
bool IsEquipment() const;
|
||||
bool IsGeneral() const;
|
||||
bool IsWeapon() const;
|
||||
bool IsTrade() const;
|
||||
|
||||
const std::string ToString() const;
|
||||
|
||||
inline int Type() { return type_; }
|
||||
inline int Type() const { return type_; }
|
||||
inline int Slot() { return slot_; }
|
||||
inline int Slot() const { return slot_; }
|
||||
inline int BagIndex() { return bag_index_; }
|
||||
inline int BagIndex() const { return bag_index_; }
|
||||
inline int AugIndex() { return aug_index_; }
|
||||
inline int AugIndex() const { return aug_index_; }
|
||||
|
||||
private:
|
||||
int type_;
|
||||
int slot_;
|
||||
int bag_index_;
|
||||
int aug_index_;
|
||||
};
|
||||
|
||||
inline bool operator==(const InventorySlot &lhs, const InventorySlot &rhs) {
|
||||
return lhs.Type() == rhs.Type() &&
|
||||
lhs.Slot() == rhs.Slot() &&
|
||||
lhs.BagIndex() == rhs.BagIndex() &&
|
||||
lhs.AugIndex() == rhs.AugIndex(); }
|
||||
inline bool operator!=(const InventorySlot &lhs, const InventorySlot &rhs) { return !(lhs == rhs); }
|
||||
|
||||
class InventoryDataModel;
|
||||
class Inventory
|
||||
{
|
||||
public:
|
||||
Inventory(int race, int class_, int deity);
|
||||
~Inventory();
|
||||
|
||||
void SetRace(int race);
|
||||
void SetClass(int class_);
|
||||
void SetDeity(int deity);
|
||||
void SetDataModel(InventoryDataModel *dm);
|
||||
|
||||
ItemInstance::pointer Get(const InventorySlot &slot);
|
||||
bool Put(const InventorySlot &slot, ItemInstance::pointer &inst);
|
||||
bool Swap(const InventorySlot &src, const InventorySlot &dest, int charges);
|
||||
bool Summon(const InventorySlot &slot, ItemInstance::pointer &inst);
|
||||
bool PushToCursorBuffer(ItemInstance::pointer &inst);
|
||||
bool PopFromCursorBuffer();
|
||||
InventorySlot FindFreeSlot(ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end);
|
||||
int FindFreeStackSlots(ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end);
|
||||
void UpdateSlot(const InventorySlot &slot, ItemInstance::pointer &inst);
|
||||
|
||||
//utility
|
||||
static int CalcMaterialFromSlot(const InventorySlot &slot);
|
||||
static InventorySlot CalcSlotFromMaterial(int material);
|
||||
bool CanEquip(EQEmu::ItemInstance::pointer &inst, const EQEmu::InventorySlot &slot);
|
||||
bool CheckLoreConflict(const ItemData *item);
|
||||
bool Serialize(MemoryBuffer &buf);
|
||||
|
||||
//testing
|
||||
void Interrogate();
|
||||
private:
|
||||
bool _swap(const InventorySlot &src, const InventorySlot &dest);
|
||||
bool _destroy(const InventorySlot &slot);
|
||||
|
||||
struct impl;
|
||||
impl *impl_;
|
||||
};
|
||||
|
||||
} // EQEmu
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
/* 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 COMMON_INVENTORY_DATA_MODEL_H
|
||||
#define COMMON_INVENTORY_DATA_MODEL_H
|
||||
|
||||
#include "inventory.h"
|
||||
|
||||
namespace EQEmu
|
||||
{
|
||||
class InventoryDataModel
|
||||
{
|
||||
public:
|
||||
InventoryDataModel() { }
|
||||
virtual ~InventoryDataModel() { }
|
||||
|
||||
virtual void Begin() = 0;
|
||||
virtual bool Commit() = 0;
|
||||
virtual void Rollback() = 0;
|
||||
virtual void Insert(const InventorySlot &slot, ItemInstance::pointer &inst) = 0;
|
||||
virtual void Delete(const InventorySlot &slot) = 0;
|
||||
};
|
||||
} // EQEmu
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,212 @@
|
||||
#include "inventory_db_data_model.h"
|
||||
#include "shareddb.h"
|
||||
#include "string_util.h"
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
enum DataEventTypes
|
||||
{
|
||||
DB_Insert,
|
||||
DB_Delete
|
||||
};
|
||||
|
||||
struct DataEvent
|
||||
{
|
||||
DataEventTypes evt;
|
||||
EQEmu::InventorySlot slot;
|
||||
EQEmu::ItemInstance::pointer inst;
|
||||
};
|
||||
|
||||
struct EQEmu::InventoryDatabaseDataModel::impl {
|
||||
SharedDatabase *db_;
|
||||
std::list<DataEvent> events_;
|
||||
uint32 char_id_;
|
||||
};
|
||||
|
||||
EQEmu::InventoryDatabaseDataModel::InventoryDatabaseDataModel(SharedDatabase *db, uint32 char_id) {
|
||||
impl_ = new impl;
|
||||
impl_->db_ = db;
|
||||
impl_->char_id_ = char_id;
|
||||
}
|
||||
|
||||
EQEmu::InventoryDatabaseDataModel::~InventoryDatabaseDataModel() {
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
void EQEmu::InventoryDatabaseDataModel::Begin() {
|
||||
impl_->db_->TransactionBegin();
|
||||
impl_->events_.clear();
|
||||
}
|
||||
|
||||
bool EQEmu::InventoryDatabaseDataModel::Commit() {
|
||||
std::string base_insert = "INSERT INTO character_inventory(id, type, slot, bag_index, aug_index, "
|
||||
"item_id, charges, color, attuned, custom_data, ornament_icon, ornament_idfile, ornament_hero_model"
|
||||
", tracking_id) VALUES";
|
||||
|
||||
std::string current_insert = base_insert;
|
||||
bool insert = false;
|
||||
for(auto iter : impl_->events_) {
|
||||
if(iter.evt == DB_Delete) {
|
||||
if(insert) {
|
||||
insert = false;
|
||||
|
||||
//commit the current_insert
|
||||
auto res = impl_->db_->QueryDatabase(current_insert);
|
||||
if(!res.Success()) {
|
||||
Rollback();
|
||||
return false;
|
||||
}
|
||||
|
||||
current_insert = base_insert;
|
||||
}
|
||||
|
||||
std::string current_delete;
|
||||
if(iter.slot.BagIndex() > -1) {
|
||||
if(iter.slot.AugIndex() > -1) {
|
||||
current_delete = StringFormat("DELETE FROM character_inventory WHERE id=%u AND type=%u AND slot=%u AND bag_index=%u AND aug_index=%u",
|
||||
impl_->char_id_, iter.slot.Type(), iter.slot.Slot(), iter.slot.BagIndex(), iter.slot.AugIndex());
|
||||
}
|
||||
else {
|
||||
current_delete = StringFormat("DELETE FROM character_inventory WHERE id=%u AND type=%u AND slot=%u AND bag_index=%u",
|
||||
impl_->char_id_, iter.slot.Type(), iter.slot.Slot(), iter.slot.BagIndex());
|
||||
}
|
||||
}
|
||||
else if(iter.slot.AugIndex() > -1) {
|
||||
current_delete = StringFormat("DELETE FROM character_inventory WHERE id=%u AND type=%u AND slot=%u AND aug_index=%u",
|
||||
impl_->char_id_, iter.slot.Type(), iter.slot.Slot(), iter.slot.AugIndex());
|
||||
}
|
||||
else {
|
||||
current_delete = StringFormat("DELETE FROM character_inventory WHERE id=%u AND type=%u AND slot=%u",
|
||||
impl_->char_id_, iter.slot.Type(), iter.slot.Slot());
|
||||
}
|
||||
|
||||
auto res = impl_->db_->QueryDatabase(current_delete);
|
||||
if(!res.Success()) {
|
||||
Rollback();
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
//insert
|
||||
if(!insert) {
|
||||
insert = true;
|
||||
} else {
|
||||
current_insert += ",";
|
||||
}
|
||||
|
||||
current_insert += StringFormat("(%u, %i, %i, %i, %i, %u, %i, %u, %u, '%s', %u, %u, %u, %llu)",
|
||||
impl_->char_id_,
|
||||
iter.slot.Type(),
|
||||
iter.slot.Slot(),
|
||||
iter.slot.BagIndex(),
|
||||
iter.slot.AugIndex(),
|
||||
iter.inst->GetBaseItem()->ID,
|
||||
iter.inst->GetCharges(),
|
||||
iter.inst->GetColor(),
|
||||
iter.inst->GetAttuned(),
|
||||
EscapeString(iter.inst->GetCustomData()).c_str(),
|
||||
iter.inst->GetOrnamentIcon(),
|
||||
iter.inst->GetOrnamentIDFile(),
|
||||
iter.inst->GetOrnamentHeroModel(),
|
||||
iter.inst->GetTrackingID());
|
||||
}
|
||||
}
|
||||
|
||||
if(insert) {
|
||||
insert = false;
|
||||
|
||||
//commit the current_insert
|
||||
auto res = impl_->db_->QueryDatabase(current_insert);
|
||||
if(!res.Success()) {
|
||||
Rollback();
|
||||
return false;
|
||||
}
|
||||
|
||||
current_insert = base_insert;
|
||||
}
|
||||
|
||||
impl_->db_->TransactionCommit();
|
||||
impl_->events_.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
void EQEmu::InventoryDatabaseDataModel::Rollback() {
|
||||
impl_->db_->TransactionRollback();
|
||||
impl_->events_.clear();
|
||||
}
|
||||
|
||||
void EQEmu::InventoryDatabaseDataModel::Insert(const InventorySlot &slot, ItemInstance::pointer &inst) {
|
||||
DataEvent evt;
|
||||
evt.evt = DB_Insert;
|
||||
evt.inst = inst;
|
||||
evt.slot = slot;
|
||||
impl_->events_.push_back(evt);
|
||||
|
||||
//insert current item
|
||||
if(slot.BagIndex() < 0 && slot.AugIndex() < 0) {
|
||||
//if bag put all bag contents in
|
||||
//if common put all augment contents in
|
||||
if(inst->GetBaseItem()->ItemClass == ItemClassContainer) {
|
||||
auto container = inst->GetContainer();
|
||||
auto iter = container->Begin();
|
||||
while(iter != container->End()) {
|
||||
DataEvent evt;
|
||||
evt.evt = DB_Insert;
|
||||
evt.inst = iter->second;
|
||||
evt.slot = InventorySlot(slot.Type(), slot.Slot(), iter->first, -1);
|
||||
impl_->events_.push_back(evt);
|
||||
|
||||
//do augments here
|
||||
if(evt.inst->GetBaseItem()->ItemClass == ItemClassCommon) {
|
||||
auto inst_container = evt.inst->GetContainer();
|
||||
auto inst_iter = inst_container->Begin();
|
||||
while(inst_iter != inst_container->End()) {
|
||||
DataEvent evt;
|
||||
evt.evt = DB_Insert;
|
||||
evt.inst = inst_iter->second;
|
||||
evt.slot = InventorySlot(slot.Type(), slot.Slot(), iter->first, inst_iter->first);
|
||||
impl_->events_.push_back(evt);
|
||||
++inst_iter;
|
||||
}
|
||||
}
|
||||
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
else if(inst->GetBaseItem()->ItemClass == ItemClassCommon) {
|
||||
auto container = inst->GetContainer();
|
||||
auto iter = container->Begin();
|
||||
while(iter != container->End()) {
|
||||
DataEvent evt;
|
||||
evt.evt = DB_Insert;
|
||||
evt.inst = iter->second;
|
||||
evt.slot = InventorySlot(slot.Type(), slot.Slot(), -1, iter->first);
|
||||
impl_->events_.push_back(evt);
|
||||
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(slot.AugIndex() < 0 && inst->GetBaseItem()->ItemClass == ItemClassCommon) {
|
||||
//bag item that can have augs
|
||||
//if common put all augment contents in
|
||||
auto container = inst->GetContainer();
|
||||
auto iter = container->Begin();
|
||||
while(iter != container->End()) {
|
||||
DataEvent evt;
|
||||
evt.evt = DB_Insert;
|
||||
evt.inst = iter->second;
|
||||
evt.slot = InventorySlot(slot.Type(), slot.Slot(), slot.BagIndex(), iter->first);
|
||||
impl_->events_.push_back(evt);
|
||||
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EQEmu::InventoryDatabaseDataModel::Delete(const InventorySlot &slot) {
|
||||
DataEvent evt;
|
||||
evt.evt = DB_Delete;
|
||||
evt.slot = slot;
|
||||
impl_->events_.push_back(evt);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/* 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 COMMON_INVENTORY_DB_DATA_MODEL_H
|
||||
#define COMMON_INVENTORY_DB_DATA_MODEL_H
|
||||
|
||||
#include "inventory_data_model.h"
|
||||
|
||||
class SharedDatabase;
|
||||
|
||||
namespace EQEmu
|
||||
{
|
||||
class InventoryDatabaseDataModel : public InventoryDataModel
|
||||
{
|
||||
public:
|
||||
InventoryDatabaseDataModel(SharedDatabase *db, uint32 char_id);
|
||||
virtual ~InventoryDatabaseDataModel();
|
||||
|
||||
virtual void Begin();
|
||||
virtual bool Commit();
|
||||
virtual void Rollback();
|
||||
virtual void Insert(const InventorySlot &slot, ItemInstance::pointer &inst);
|
||||
virtual void Delete(const InventorySlot &slot);
|
||||
private:
|
||||
struct impl;
|
||||
impl *impl_;
|
||||
};
|
||||
} // EQEmu
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
/* 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 COMMON_INVENTORY_NULL_DATA_MODEL_H
|
||||
#define COMMON_INVENTORY_NULL_DATA_MODEL_H
|
||||
|
||||
#include "inventory_data_model.h"
|
||||
|
||||
namespace EQEmu
|
||||
{
|
||||
class InventoryNullDataModel : public InventoryDataModel
|
||||
{
|
||||
public:
|
||||
InventoryNullDataModel() { }
|
||||
virtual ~InventoryNullDataModel() { }
|
||||
|
||||
virtual void Begin() { }
|
||||
virtual bool Commit() { return true; }
|
||||
virtual void Rollback() { }
|
||||
virtual void Insert(const InventorySlot &slot, ItemInstance::pointer &inst) { }
|
||||
virtual void Delete(const InventorySlot &slot) { }
|
||||
};
|
||||
} // EQEmu
|
||||
|
||||
#endif
|
||||
+212
-130
@@ -105,9 +105,9 @@ ItemInst* ItemInstQueue::peek_front() const
|
||||
|
||||
|
||||
//
|
||||
// class Inventory
|
||||
// class InventoryOld
|
||||
//
|
||||
Inventory::~Inventory()
|
||||
InventoryOld::~InventoryOld()
|
||||
{
|
||||
for (auto iter = m_worn.begin(); iter != m_worn.end(); ++iter) {
|
||||
safe_delete(iter->second);
|
||||
@@ -135,7 +135,7 @@ Inventory::~Inventory()
|
||||
m_trade.clear();
|
||||
}
|
||||
|
||||
void Inventory::CleanDirty() {
|
||||
void InventoryOld::CleanDirty() {
|
||||
auto iter = dirty_inst.begin();
|
||||
while (iter != dirty_inst.end()) {
|
||||
delete (*iter);
|
||||
@@ -144,14 +144,14 @@ void Inventory::CleanDirty() {
|
||||
dirty_inst.clear();
|
||||
}
|
||||
|
||||
void Inventory::MarkDirty(ItemInst *inst) {
|
||||
void InventoryOld::MarkDirty(ItemInst *inst) {
|
||||
if (inst) {
|
||||
dirty_inst.push_back(inst);
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve item at specified slot; returns false if item not found
|
||||
ItemInst* Inventory::GetItem(int16 slot_id) const
|
||||
ItemInst* InventoryOld::GetItem(int16 slot_id) const
|
||||
{
|
||||
ItemInst* result = nullptr;
|
||||
|
||||
@@ -186,37 +186,37 @@ ItemInst* Inventory::GetItem(int16 slot_id) const
|
||||
// Inner bag slots
|
||||
else if (slot_id >= EmuConstants::TRADE_BAGS_BEGIN && slot_id <= EmuConstants::TRADE_BAGS_END) {
|
||||
// Trade bag slots
|
||||
ItemInst* inst = _GetItem(m_trade, Inventory::CalcSlotId(slot_id));
|
||||
ItemInst* inst = _GetItem(m_trade, InventoryOld::CalcSlotId(slot_id));
|
||||
if (inst && inst->IsType(ItemClassContainer)) {
|
||||
result = inst->GetItem(Inventory::CalcBagIdx(slot_id));
|
||||
result = inst->GetItem(InventoryOld::CalcBagIdx(slot_id));
|
||||
}
|
||||
}
|
||||
else if (slot_id >= EmuConstants::SHARED_BANK_BAGS_BEGIN && slot_id <= EmuConstants::SHARED_BANK_BAGS_END) {
|
||||
// Shared Bank bag slots
|
||||
ItemInst* inst = _GetItem(m_shbank, Inventory::CalcSlotId(slot_id));
|
||||
ItemInst* inst = _GetItem(m_shbank, InventoryOld::CalcSlotId(slot_id));
|
||||
if (inst && inst->IsType(ItemClassContainer)) {
|
||||
result = inst->GetItem(Inventory::CalcBagIdx(slot_id));
|
||||
result = inst->GetItem(InventoryOld::CalcBagIdx(slot_id));
|
||||
}
|
||||
}
|
||||
else if (slot_id >= EmuConstants::BANK_BAGS_BEGIN && slot_id <= EmuConstants::BANK_BAGS_END) {
|
||||
// Bank bag slots
|
||||
ItemInst* inst = _GetItem(m_bank, Inventory::CalcSlotId(slot_id));
|
||||
ItemInst* inst = _GetItem(m_bank, InventoryOld::CalcSlotId(slot_id));
|
||||
if (inst && inst->IsType(ItemClassContainer)) {
|
||||
result = inst->GetItem(Inventory::CalcBagIdx(slot_id));
|
||||
result = inst->GetItem(InventoryOld::CalcBagIdx(slot_id));
|
||||
}
|
||||
}
|
||||
else if (slot_id >= EmuConstants::CURSOR_BAG_BEGIN && slot_id <= EmuConstants::CURSOR_BAG_END) {
|
||||
// Cursor bag slots
|
||||
ItemInst* inst = m_cursor.peek_front();
|
||||
if (inst && inst->IsType(ItemClassContainer)) {
|
||||
result = inst->GetItem(Inventory::CalcBagIdx(slot_id));
|
||||
result = inst->GetItem(InventoryOld::CalcBagIdx(slot_id));
|
||||
}
|
||||
}
|
||||
else if (slot_id >= EmuConstants::GENERAL_BAGS_BEGIN && slot_id <= EmuConstants::GENERAL_BAGS_END) {
|
||||
// Personal inventory bag slots
|
||||
ItemInst* inst = _GetItem(m_inv, Inventory::CalcSlotId(slot_id));
|
||||
ItemInst* inst = _GetItem(m_inv, InventoryOld::CalcSlotId(slot_id));
|
||||
if (inst && inst->IsType(ItemClassContainer)) {
|
||||
result = inst->GetItem(Inventory::CalcBagIdx(slot_id));
|
||||
result = inst->GetItem(InventoryOld::CalcBagIdx(slot_id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,13 +224,13 @@ ItemInst* Inventory::GetItem(int16 slot_id) const
|
||||
}
|
||||
|
||||
// Retrieve item at specified position within bag
|
||||
ItemInst* Inventory::GetItem(int16 slot_id, uint8 bagidx) const
|
||||
ItemInst* InventoryOld::GetItem(int16 slot_id, uint8 bagidx) const
|
||||
{
|
||||
return GetItem(Inventory::CalcSlotId(slot_id, bagidx));
|
||||
return GetItem(InventoryOld::CalcSlotId(slot_id, bagidx));
|
||||
}
|
||||
|
||||
// Put an item snto specified slot
|
||||
int16 Inventory::PutItem(int16 slot_id, const ItemInst& inst)
|
||||
int16 InventoryOld::PutItem(int16 slot_id, const ItemInst& inst)
|
||||
{
|
||||
// Clean up item already in slot (if exists)
|
||||
DeleteItem(slot_id);
|
||||
@@ -245,19 +245,19 @@ int16 Inventory::PutItem(int16 slot_id, const ItemInst& inst)
|
||||
return _PutItem(slot_id, inst.Clone());
|
||||
}
|
||||
|
||||
int16 Inventory::PushCursor(const ItemInst& inst)
|
||||
int16 InventoryOld::PushCursor(const ItemInst& inst)
|
||||
{
|
||||
m_cursor.push(inst.Clone());
|
||||
return MainCursor;
|
||||
}
|
||||
|
||||
ItemInst* Inventory::GetCursorItem()
|
||||
ItemInst* InventoryOld::GetCursorItem()
|
||||
{
|
||||
return m_cursor.peek_front();
|
||||
}
|
||||
|
||||
// Swap items in inventory
|
||||
bool Inventory::SwapItem(int16 slot_a, int16 slot_b)
|
||||
bool InventoryOld::SwapItem(int16 slot_a, int16 slot_b)
|
||||
{
|
||||
// Temp holding areas for a and b
|
||||
ItemInst* inst_a = GetItem(slot_a);
|
||||
@@ -273,7 +273,7 @@ bool Inventory::SwapItem(int16 slot_a, int16 slot_b)
|
||||
}
|
||||
|
||||
// Remove item from inventory (with memory delete)
|
||||
bool Inventory::DeleteItem(int16 slot_id, uint8 quantity)
|
||||
bool InventoryOld::DeleteItem(int16 slot_id, uint8 quantity)
|
||||
{
|
||||
// Pop item out of inventory map (or queue)
|
||||
ItemInst* item_to_delete = PopItem(slot_id);
|
||||
@@ -293,7 +293,7 @@ bool Inventory::DeleteItem(int16 slot_id, uint8 quantity)
|
||||
((item_to_delete->GetItem()->MaxCharges == 0) || item_to_delete->IsExpendable()))
|
||||
) {
|
||||
// Item can now be destroyed
|
||||
Inventory::MarkDirty(item_to_delete);
|
||||
InventoryOld::MarkDirty(item_to_delete);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -303,19 +303,19 @@ bool Inventory::DeleteItem(int16 slot_id, uint8 quantity)
|
||||
return false;
|
||||
}
|
||||
|
||||
Inventory::MarkDirty(item_to_delete);
|
||||
InventoryOld::MarkDirty(item_to_delete);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
// Checks All items in a bag for No Drop
|
||||
bool Inventory::CheckNoDrop(int16 slot_id) {
|
||||
bool InventoryOld::CheckNoDrop(int16 slot_id) {
|
||||
ItemInst* inst = GetItem(slot_id);
|
||||
if (!inst) return false;
|
||||
if (!inst->GetItem()->NoDrop) return true;
|
||||
if (inst->GetItem()->ItemClass == 1) {
|
||||
for (uint8 i = SUB_BEGIN; i < EmuConstants::ITEM_CONTAINER_SIZE; i++) {
|
||||
ItemInst* bagitem = GetItem(Inventory::CalcSlotId(slot_id, i));
|
||||
ItemInst* bagitem = GetItem(InventoryOld::CalcSlotId(slot_id, i));
|
||||
if (bagitem && !bagitem->GetItem()->NoDrop)
|
||||
return true;
|
||||
}
|
||||
@@ -325,7 +325,7 @@ bool Inventory::CheckNoDrop(int16 slot_id) {
|
||||
|
||||
// Remove item from bucket without memory delete
|
||||
// Returns item pointer if full delete was successful
|
||||
ItemInst* Inventory::PopItem(int16 slot_id)
|
||||
ItemInst* InventoryOld::PopItem(int16 slot_id)
|
||||
{
|
||||
ItemInst* p = nullptr;
|
||||
|
||||
@@ -358,9 +358,9 @@ ItemInst* Inventory::PopItem(int16 slot_id)
|
||||
}
|
||||
else {
|
||||
// Is slot inside bag?
|
||||
ItemInst* baginst = GetItem(Inventory::CalcSlotId(slot_id));
|
||||
ItemInst* baginst = GetItem(InventoryOld::CalcSlotId(slot_id));
|
||||
if (baginst != nullptr && baginst->IsType(ItemClassContainer)) {
|
||||
p = baginst->PopItem(Inventory::CalcBagIdx(slot_id));
|
||||
p = baginst->PopItem(InventoryOld::CalcBagIdx(slot_id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,7 +368,7 @@ ItemInst* Inventory::PopItem(int16 slot_id)
|
||||
return p;
|
||||
}
|
||||
|
||||
bool Inventory::HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity) {
|
||||
bool InventoryOld::HasSpaceForItem(const ItemData *ItemToTry, int16 Quantity) {
|
||||
|
||||
if (ItemToTry->Stackable) {
|
||||
|
||||
@@ -388,7 +388,7 @@ bool Inventory::HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity) {
|
||||
}
|
||||
if (InvItem && InvItem->IsType(ItemClassContainer)) {
|
||||
|
||||
int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_BEGIN);
|
||||
int16 BaseSlotID = InventoryOld::CalcSlotId(i, SUB_BEGIN);
|
||||
uint8 BagSize = InvItem->GetItem()->BagSlots;
|
||||
for (uint8 BagSlot = SUB_BEGIN; BagSlot < BagSize; BagSlot++) {
|
||||
|
||||
@@ -432,7 +432,7 @@ bool Inventory::HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity) {
|
||||
}
|
||||
else if (InvItem->IsType(ItemClassContainer) && CanItemFitInContainer(ItemToTry, InvItem->GetItem())) {
|
||||
|
||||
int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_BEGIN);
|
||||
int16 BaseSlotID = InventoryOld::CalcSlotId(i, SUB_BEGIN);
|
||||
|
||||
uint8 BagSize = InvItem->GetItem()->BagSlots;
|
||||
|
||||
@@ -468,7 +468,7 @@ bool Inventory::HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity) {
|
||||
|
||||
//This function has a flaw in that it only returns the last stack that it looked at
|
||||
//when quantity is greater than 1 and not all of quantity can be found in 1 stack.
|
||||
int16 Inventory::HasItem(uint32 item_id, uint8 quantity, uint8 where)
|
||||
int16 InventoryOld::HasItem(uint32 item_id, uint8 quantity, uint8 where)
|
||||
{
|
||||
int16 slot_id = INVALID_INDEX;
|
||||
|
||||
@@ -506,6 +506,7 @@ int16 Inventory::HasItem(uint32 item_id, uint8 quantity, uint8 where)
|
||||
return slot_id;
|
||||
}
|
||||
|
||||
// Behavioral change - Limbo is no longer checked due to improper handling of return value
|
||||
if (where & invWhereCursor) {
|
||||
// Check cursor queue
|
||||
slot_id = _HasItem(m_cursor, item_id, quantity);
|
||||
@@ -517,7 +518,7 @@ int16 Inventory::HasItem(uint32 item_id, uint8 quantity, uint8 where)
|
||||
}
|
||||
|
||||
//this function has the same quantity flaw mentioned above in HasItem()
|
||||
int16 Inventory::HasItemByUse(uint8 use, uint8 quantity, uint8 where)
|
||||
int16 InventoryOld::HasItemByUse(uint8 use, uint8 quantity, uint8 where)
|
||||
{
|
||||
int16 slot_id = INVALID_INDEX;
|
||||
|
||||
@@ -552,6 +553,7 @@ int16 Inventory::HasItemByUse(uint8 use, uint8 quantity, uint8 where)
|
||||
return slot_id;
|
||||
}
|
||||
|
||||
// Behavioral change - Limbo is no longer checked due to improper handling of return value
|
||||
if (where & invWhereCursor) {
|
||||
// Check cursor queue
|
||||
slot_id = _HasItemByUse(m_cursor, use, quantity);
|
||||
@@ -562,7 +564,7 @@ int16 Inventory::HasItemByUse(uint8 use, uint8 quantity, uint8 where)
|
||||
return slot_id;
|
||||
}
|
||||
|
||||
int16 Inventory::HasItemByLoreGroup(uint32 loregroup, uint8 where)
|
||||
int16 InventoryOld::HasItemByLoreGroup(uint32 loregroup, uint8 where)
|
||||
{
|
||||
int16 slot_id = INVALID_INDEX;
|
||||
|
||||
@@ -597,6 +599,7 @@ int16 Inventory::HasItemByLoreGroup(uint32 loregroup, uint8 where)
|
||||
return slot_id;
|
||||
}
|
||||
|
||||
// Behavioral change - Limbo is no longer checked due to improper handling of return value
|
||||
if (where & invWhereCursor) {
|
||||
// Check cursor queue
|
||||
slot_id = _HasItemByLoreGroup(m_cursor, loregroup);
|
||||
@@ -609,7 +612,7 @@ int16 Inventory::HasItemByLoreGroup(uint32 loregroup, uint8 where)
|
||||
|
||||
// Locate an available inventory slot
|
||||
// Returns slot_id when there's one available, else SLOT_INVALID
|
||||
int16 Inventory::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, bool is_arrow)
|
||||
int16 InventoryOld::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, bool is_arrow)
|
||||
{
|
||||
// Check basic inventory
|
||||
for (int16 i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_END; i++) {
|
||||
@@ -628,7 +631,7 @@ int16 Inventory::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, boo
|
||||
continue;
|
||||
}
|
||||
|
||||
int16 base_slot_id = Inventory::CalcSlotId(i, SUB_BEGIN);
|
||||
int16 base_slot_id = InventoryOld::CalcSlotId(i, SUB_BEGIN);
|
||||
|
||||
uint8 slots = inst->GetItem()->BagSlots;
|
||||
uint8 j;
|
||||
@@ -653,11 +656,11 @@ int16 Inventory::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, boo
|
||||
}
|
||||
|
||||
// This is a mix of HasSpaceForItem and FindFreeSlot..due to existing coding behavior, it was better to add a new helper function...
|
||||
int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) {
|
||||
int16 InventoryOld::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().
|
||||
// If you have a need, use it..but, understand it is not a compatible replacement for InventoryOld::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;
|
||||
@@ -698,7 +701,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) {
|
||||
continue;
|
||||
|
||||
if ((sub_inst->GetID() == inst->GetID()) && (sub_inst->GetCharges() < sub_inst->GetItem()->StackSize))
|
||||
return Inventory::CalcSlotId(free_slot, free_bag_slot);
|
||||
return InventoryOld::CalcSlotId(free_slot, free_bag_slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -714,7 +717,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) {
|
||||
|
||||
for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EmuConstants::ITEM_CONTAINER_SIZE); ++free_bag_slot) {
|
||||
if (!main_inst->GetItem(free_bag_slot))
|
||||
return Inventory::CalcSlotId(free_slot, free_bag_slot);
|
||||
return InventoryOld::CalcSlotId(free_slot, free_bag_slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -729,7 +732,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) {
|
||||
|
||||
for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EmuConstants::ITEM_CONTAINER_SIZE); ++free_bag_slot) {
|
||||
if (!main_inst->GetItem(free_bag_slot))
|
||||
return Inventory::CalcSlotId(free_slot, free_bag_slot);
|
||||
return InventoryOld::CalcSlotId(free_slot, free_bag_slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -751,7 +754,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) {
|
||||
|
||||
for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EmuConstants::ITEM_CONTAINER_SIZE); ++free_bag_slot) {
|
||||
if (!main_inst->GetItem(free_bag_slot))
|
||||
return Inventory::CalcSlotId(free_slot, free_bag_slot);
|
||||
return InventoryOld::CalcSlotId(free_slot, free_bag_slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -761,7 +764,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) {
|
||||
}
|
||||
|
||||
// Opposite of below: Get parent bag slot_id from a slot inside of bag
|
||||
int16 Inventory::CalcSlotId(int16 slot_id) {
|
||||
int16 InventoryOld::CalcSlotId(int16 slot_id) {
|
||||
int16 parent_slot_id = INVALID_INDEX;
|
||||
|
||||
// this is not a bag range... using this risks over-writing existing items
|
||||
@@ -789,8 +792,8 @@ int16 Inventory::CalcSlotId(int16 slot_id) {
|
||||
}
|
||||
|
||||
// Calculate slot_id for an item within a bag
|
||||
int16 Inventory::CalcSlotId(int16 bagslot_id, uint8 bagidx) {
|
||||
if (!Inventory::SupportsContainers(bagslot_id))
|
||||
int16 InventoryOld::CalcSlotId(int16 bagslot_id, uint8 bagidx) {
|
||||
if (!InventoryOld::SupportsContainers(bagslot_id))
|
||||
return INVALID_INDEX;
|
||||
|
||||
int16 slot_id = INVALID_INDEX;
|
||||
@@ -814,7 +817,7 @@ int16 Inventory::CalcSlotId(int16 bagslot_id, uint8 bagidx) {
|
||||
return slot_id;
|
||||
}
|
||||
|
||||
uint8 Inventory::CalcBagIdx(int16 slot_id) {
|
||||
uint8 InventoryOld::CalcBagIdx(int16 slot_id) {
|
||||
uint8 index = 0;
|
||||
|
||||
// this is not a bag range... using this risks over-writing existing items
|
||||
@@ -843,7 +846,7 @@ uint8 Inventory::CalcBagIdx(int16 slot_id) {
|
||||
return index;
|
||||
}
|
||||
|
||||
int16 Inventory::CalcSlotFromMaterial(uint8 material)
|
||||
int16 InventoryOld::CalcSlotFromMaterial(uint8 material)
|
||||
{
|
||||
switch (material)
|
||||
{
|
||||
@@ -870,7 +873,7 @@ int16 Inventory::CalcSlotFromMaterial(uint8 material)
|
||||
}
|
||||
}
|
||||
|
||||
uint8 Inventory::CalcMaterialFromSlot(int16 equipslot)
|
||||
uint8 InventoryOld::CalcMaterialFromSlot(int16 equipslot)
|
||||
{
|
||||
switch (equipslot)
|
||||
{
|
||||
@@ -898,7 +901,7 @@ uint8 Inventory::CalcMaterialFromSlot(int16 equipslot)
|
||||
}
|
||||
}
|
||||
|
||||
bool Inventory::CanItemFitInContainer(const Item_Struct *ItemToTry, const Item_Struct *Container) {
|
||||
bool InventoryOld::CanItemFitInContainer(const ItemData *ItemToTry, const ItemData *Container) {
|
||||
|
||||
if (!ItemToTry || !Container)
|
||||
return false;
|
||||
@@ -915,7 +918,7 @@ bool Inventory::CanItemFitInContainer(const Item_Struct *ItemToTry, const Item_S
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Inventory::SupportsClickCasting(int16 slot_id)
|
||||
bool InventoryOld::SupportsClickCasting(int16 slot_id)
|
||||
{
|
||||
// there are a few non-potion items that identify as ItemTypePotion..so, we still need to ubiquitously include the equipment range
|
||||
if ((uint16)slot_id <= EmuConstants::GENERAL_END || slot_id == MainPowerSource)
|
||||
@@ -931,7 +934,7 @@ bool Inventory::SupportsClickCasting(int16 slot_id)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Inventory::SupportsPotionBeltCasting(int16 slot_id)
|
||||
bool InventoryOld::SupportsPotionBeltCasting(int16 slot_id)
|
||||
{
|
||||
if ((uint16)slot_id <= EmuConstants::GENERAL_END || slot_id == MainPowerSource || (slot_id >= EmuConstants::GENERAL_BAGS_BEGIN && slot_id <= EmuConstants::GENERAL_BAGS_END))
|
||||
return true;
|
||||
@@ -940,7 +943,7 @@ bool Inventory::SupportsPotionBeltCasting(int16 slot_id)
|
||||
}
|
||||
|
||||
// Test whether a given slot can support a container item
|
||||
bool Inventory::SupportsContainers(int16 slot_id)
|
||||
bool InventoryOld::SupportsContainers(int16 slot_id)
|
||||
{
|
||||
if ((slot_id == MainCursor) ||
|
||||
(slot_id >= EmuConstants::GENERAL_BEGIN && slot_id <= EmuConstants::GENERAL_END) ||
|
||||
@@ -954,7 +957,7 @@ bool Inventory::SupportsContainers(int16 slot_id)
|
||||
return false;
|
||||
}
|
||||
|
||||
int Inventory::GetSlotByItemInst(ItemInst *inst) {
|
||||
int InventoryOld::GetSlotByItemInst(ItemInst *inst) {
|
||||
if (!inst)
|
||||
return INVALID_INDEX;
|
||||
|
||||
@@ -990,36 +993,46 @@ int Inventory::GetSlotByItemInst(ItemInst *inst) {
|
||||
return INVALID_INDEX;
|
||||
}
|
||||
|
||||
uint8 Inventory::FindHighestLightValue()
|
||||
uint8 InventoryOld::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; }
|
||||
if (item->ItemType != ItemTypeMisc && item->ItemType != ItemTypeLight) { 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() {
|
||||
void InventoryOld::dumpEntireInventory() {
|
||||
|
||||
dumpWornItems();
|
||||
dumpInventory();
|
||||
@@ -1029,29 +1042,29 @@ void Inventory::dumpEntireInventory() {
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
void Inventory::dumpWornItems() {
|
||||
void InventoryOld::dumpWornItems() {
|
||||
std::cout << "Worn items:" << std::endl;
|
||||
dumpItemCollection(m_worn);
|
||||
}
|
||||
|
||||
void Inventory::dumpInventory() {
|
||||
void InventoryOld::dumpInventory() {
|
||||
std::cout << "Inventory items:" << std::endl;
|
||||
dumpItemCollection(m_inv);
|
||||
}
|
||||
|
||||
void Inventory::dumpBankItems() {
|
||||
void InventoryOld::dumpBankItems() {
|
||||
|
||||
std::cout << "Bank items:" << std::endl;
|
||||
dumpItemCollection(m_bank);
|
||||
}
|
||||
|
||||
void Inventory::dumpSharedBankItems() {
|
||||
void InventoryOld::dumpSharedBankItems() {
|
||||
|
||||
std::cout << "Shared Bank items:" << std::endl;
|
||||
dumpItemCollection(m_shbank);
|
||||
}
|
||||
|
||||
int Inventory::GetSlotByItemInstCollection(const std::map<int16, ItemInst*> &collection, ItemInst *inst) {
|
||||
int InventoryOld::GetSlotByItemInstCollection(const std::map<int16, ItemInst*> &collection, ItemInst *inst) {
|
||||
for (auto iter = collection.begin(); iter != collection.end(); ++iter) {
|
||||
ItemInst *t_inst = iter->second;
|
||||
if (t_inst == inst) {
|
||||
@@ -1059,9 +1072,9 @@ int Inventory::GetSlotByItemInstCollection(const std::map<int16, ItemInst*> &col
|
||||
}
|
||||
|
||||
if (t_inst && !t_inst->IsType(ItemClassContainer)) {
|
||||
for (auto b_iter = t_inst->_begin(); b_iter != t_inst->_end(); ++b_iter) {
|
||||
for (auto b_iter = t_inst->_cbegin(); b_iter != t_inst->_cend(); ++b_iter) {
|
||||
if (b_iter->second == inst) {
|
||||
return Inventory::CalcSlotId(iter->first, b_iter->first);
|
||||
return InventoryOld::CalcSlotId(iter->first, b_iter->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1070,13 +1083,10 @@ int Inventory::GetSlotByItemInstCollection(const std::map<int16, ItemInst*> &col
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Inventory::dumpItemCollection(const std::map<int16, ItemInst*> &collection) {
|
||||
iter_inst it;
|
||||
iter_contents itb;
|
||||
ItemInst* inst = nullptr;
|
||||
|
||||
for (it = collection.begin(); it != collection.end(); ++it) {
|
||||
inst = it->second;
|
||||
void InventoryOld::dumpItemCollection(const std::map<int16, ItemInst*> &collection)
|
||||
{
|
||||
for (auto it = collection.cbegin(); it != collection.cend(); ++it) {
|
||||
auto inst = it->second;
|
||||
if (!inst || !inst->GetItem())
|
||||
continue;
|
||||
|
||||
@@ -1087,19 +1097,18 @@ void Inventory::dumpItemCollection(const std::map<int16, ItemInst*> &collection)
|
||||
}
|
||||
}
|
||||
|
||||
void Inventory::dumpBagContents(ItemInst *inst, iter_inst *it) {
|
||||
iter_contents itb;
|
||||
|
||||
void InventoryOld::dumpBagContents(ItemInst *inst, std::map<int16, ItemInst*>::const_iterator *it)
|
||||
{
|
||||
if (!inst || !inst->IsType(ItemClassContainer))
|
||||
return;
|
||||
|
||||
// Go through bag, if bag
|
||||
for (itb = inst->_begin(); itb != inst->_end(); ++itb) {
|
||||
for (auto itb = inst->_cbegin(); itb != inst->_cend(); ++itb) {
|
||||
ItemInst* baginst = itb->second;
|
||||
if (!baginst || !baginst->GetItem())
|
||||
continue;
|
||||
|
||||
std::string subSlot = StringFormat(" Slot %d: %s (%d)", Inventory::CalcSlotId((*it)->first, itb->first),
|
||||
std::string subSlot = StringFormat(" Slot %d: %s (%d)", InventoryOld::CalcSlotId((*it)->first, itb->first),
|
||||
baginst->GetItem()->Name, (baginst->GetCharges() <= 0) ? 1 : baginst->GetCharges());
|
||||
std::cout << subSlot << std::endl;
|
||||
}
|
||||
@@ -1107,9 +1116,9 @@ void Inventory::dumpBagContents(ItemInst *inst, iter_inst *it) {
|
||||
}
|
||||
|
||||
// Internal Method: Retrieves item within an inventory bucket
|
||||
ItemInst* Inventory::_GetItem(const std::map<int16, ItemInst*>& bucket, int16 slot_id) const
|
||||
ItemInst* InventoryOld::_GetItem(const std::map<int16, ItemInst*>& bucket, int16 slot_id) const
|
||||
{
|
||||
iter_inst it = bucket.find(slot_id);
|
||||
auto it = bucket.find(slot_id);
|
||||
if (it != bucket.end()) {
|
||||
return it->second;
|
||||
}
|
||||
@@ -1120,8 +1129,10 @@ ItemInst* Inventory::_GetItem(const std::map<int16, ItemInst*>& bucket, int16 sl
|
||||
|
||||
// Internal Method: "put" item into bucket, without regard for what is currently in bucket
|
||||
// Assumes item has already been allocated
|
||||
int16 Inventory::_PutItem(int16 slot_id, ItemInst* inst)
|
||||
int16 InventoryOld::_PutItem(int16 slot_id, ItemInst* inst)
|
||||
{
|
||||
// What happens here when we _PutItem(MainCursor)? Bad things..really bad things...
|
||||
//
|
||||
// If putting a nullptr into slot, we need to remove slot without memory delete
|
||||
if (inst == nullptr) {
|
||||
//Why do we not delete the poped item here????
|
||||
@@ -1164,25 +1175,25 @@ int16 Inventory::_PutItem(int16 slot_id, ItemInst* inst)
|
||||
}
|
||||
else {
|
||||
// Slot must be within a bag
|
||||
parentSlot = Inventory::CalcSlotId(slot_id);
|
||||
parentSlot = InventoryOld::CalcSlotId(slot_id);
|
||||
ItemInst* baginst = GetItem(parentSlot); // Get parent bag
|
||||
if (baginst && baginst->IsType(ItemClassContainer))
|
||||
{
|
||||
baginst->_PutItem(Inventory::CalcBagIdx(slot_id), inst);
|
||||
baginst->_PutItem(InventoryOld::CalcBagIdx(slot_id), inst);
|
||||
result = slot_id;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == INVALID_INDEX) {
|
||||
Log.Out(Logs::General, Logs::Error, "Inventory::_PutItem: Invalid slot_id specified (%i) with parent slot id (%i)", slot_id, parentSlot);
|
||||
Inventory::MarkDirty(inst); // Slot not found, clean up
|
||||
Log.Out(Logs::General, Logs::Error, "InventoryOld::_PutItem: Invalid slot_id specified (%i) with parent slot id (%i)", slot_id, parentSlot);
|
||||
InventoryOld::MarkDirty(inst); // Slot not found, clean up
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Internal Method: Checks an inventory bucket for a particular item
|
||||
int16 Inventory::_HasItem(std::map<int16, ItemInst*>& bucket, uint32 item_id, uint8 quantity)
|
||||
int16 InventoryOld::_HasItem(std::map<int16, ItemInst*>& bucket, uint32 item_id, uint8 quantity)
|
||||
{
|
||||
uint8 quantity_found = 0;
|
||||
|
||||
@@ -1203,14 +1214,14 @@ int16 Inventory::_HasItem(std::map<int16, ItemInst*>& bucket, uint32 item_id, ui
|
||||
|
||||
if (!inst->IsType(ItemClassContainer)) { continue; }
|
||||
|
||||
for (auto bag_iter = inst->_begin(); bag_iter != inst->_end(); ++bag_iter) {
|
||||
for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) {
|
||||
auto bag_inst = bag_iter->second;
|
||||
if (bag_inst == nullptr) { continue; }
|
||||
|
||||
if (bag_inst->GetID() == item_id) {
|
||||
quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges();
|
||||
if (quantity_found >= quantity)
|
||||
return Inventory::CalcSlotId(iter->first, bag_iter->first);
|
||||
return InventoryOld::CalcSlotId(iter->first, bag_iter->first);
|
||||
}
|
||||
|
||||
for (int index = AUG_BEGIN; index < EmuConstants::ITEM_COMMON_SIZE; ++index) {
|
||||
@@ -1224,17 +1235,17 @@ int16 Inventory::_HasItem(std::map<int16, ItemInst*>& bucket, uint32 item_id, ui
|
||||
}
|
||||
|
||||
// Internal Method: Checks an inventory queue type bucket for a particular item
|
||||
int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity)
|
||||
int16 InventoryOld::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity)
|
||||
{
|
||||
// The downfall of this (these) queue procedure is that callers presume that when an item is
|
||||
// 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;
|
||||
|
||||
for (auto iter = iqueue.begin(); iter != iqueue.end(); ++iter) {
|
||||
for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) {
|
||||
auto inst = *iter;
|
||||
if (inst == nullptr) { continue; }
|
||||
|
||||
@@ -1251,14 +1262,14 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity)
|
||||
|
||||
if (!inst->IsType(ItemClassContainer)) { continue; }
|
||||
|
||||
for (auto bag_iter = inst->_begin(); bag_iter != inst->_end(); ++bag_iter) {
|
||||
for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) {
|
||||
auto bag_inst = bag_iter->second;
|
||||
if (bag_inst == nullptr) { continue; }
|
||||
|
||||
if (bag_inst->GetID() == item_id) {
|
||||
quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges();
|
||||
if (quantity_found >= quantity)
|
||||
return Inventory::CalcSlotId(MainCursor, bag_iter->first);
|
||||
return InventoryOld::CalcSlotId(MainCursor, bag_iter->first);
|
||||
}
|
||||
|
||||
for (int index = AUG_BEGIN; index < EmuConstants::ITEM_COMMON_SIZE; ++index) {
|
||||
@@ -1266,13 +1277,16 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity)
|
||||
return legacy::SLOT_AUGMENT;
|
||||
}
|
||||
}
|
||||
|
||||
// We only check the visible cursor due to lack of queue processing ability (client allows duplicate in limbo)
|
||||
break;
|
||||
}
|
||||
|
||||
return INVALID_INDEX;
|
||||
}
|
||||
|
||||
// Internal Method: Checks an inventory bucket for a particular item
|
||||
int16 Inventory::_HasItemByUse(std::map<int16, ItemInst*>& bucket, uint8 use, uint8 quantity)
|
||||
int16 InventoryOld::_HasItemByUse(std::map<int16, ItemInst*>& bucket, uint8 use, uint8 quantity)
|
||||
{
|
||||
uint8 quantity_found = 0;
|
||||
|
||||
@@ -1288,14 +1302,14 @@ int16 Inventory::_HasItemByUse(std::map<int16, ItemInst*>& bucket, uint8 use, ui
|
||||
|
||||
if (!inst->IsType(ItemClassContainer)) { continue; }
|
||||
|
||||
for (auto bag_iter = inst->_begin(); bag_iter != inst->_end(); ++bag_iter) {
|
||||
for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) {
|
||||
auto bag_inst = bag_iter->second;
|
||||
if (bag_inst == nullptr) { continue; }
|
||||
|
||||
if (bag_inst->IsType(ItemClassCommon) && bag_inst->GetItem()->ItemType == use) {
|
||||
quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges();
|
||||
if (quantity_found >= quantity)
|
||||
return Inventory::CalcSlotId(iter->first, bag_iter->first);
|
||||
return InventoryOld::CalcSlotId(iter->first, bag_iter->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1304,11 +1318,11 @@ int16 Inventory::_HasItemByUse(std::map<int16, ItemInst*>& bucket, uint8 use, ui
|
||||
}
|
||||
|
||||
// Internal Method: Checks an inventory queue type bucket for a particular item
|
||||
int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity)
|
||||
int16 InventoryOld::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity)
|
||||
{
|
||||
uint8 quantity_found = 0;
|
||||
|
||||
for (auto iter = iqueue.begin(); iter != iqueue.end(); ++iter) {
|
||||
for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) {
|
||||
auto inst = *iter;
|
||||
if (inst == nullptr) { continue; }
|
||||
|
||||
@@ -1320,22 +1334,25 @@ int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity)
|
||||
|
||||
if (!inst->IsType(ItemClassContainer)) { continue; }
|
||||
|
||||
for (auto bag_iter = inst->_begin(); bag_iter != inst->_end(); ++bag_iter) {
|
||||
for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) {
|
||||
auto bag_inst = bag_iter->second;
|
||||
if (bag_inst == nullptr) { continue; }
|
||||
|
||||
if (bag_inst->IsType(ItemClassCommon) && bag_inst->GetItem()->ItemType == use) {
|
||||
quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges();
|
||||
if (quantity_found >= quantity)
|
||||
return Inventory::CalcSlotId(MainCursor, bag_iter->first);
|
||||
return InventoryOld::CalcSlotId(MainCursor, bag_iter->first);
|
||||
}
|
||||
}
|
||||
|
||||
// We only check the visible cursor due to lack of queue processing ability (client allows duplicate in limbo)
|
||||
break;
|
||||
}
|
||||
|
||||
return INVALID_INDEX;
|
||||
}
|
||||
|
||||
int16 Inventory::_HasItemByLoreGroup(std::map<int16, ItemInst*>& bucket, uint32 loregroup)
|
||||
int16 InventoryOld::_HasItemByLoreGroup(std::map<int16, ItemInst*>& bucket, uint32 loregroup)
|
||||
{
|
||||
for (auto iter = bucket.begin(); iter != bucket.end(); ++iter) {
|
||||
auto inst = iter->second;
|
||||
@@ -1354,12 +1371,12 @@ int16 Inventory::_HasItemByLoreGroup(std::map<int16, ItemInst*>& bucket, uint32
|
||||
|
||||
if (!inst->IsType(ItemClassContainer)) { continue; }
|
||||
|
||||
for (auto bag_iter = inst->_begin(); bag_iter != inst->_end(); ++bag_iter) {
|
||||
for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) {
|
||||
auto bag_inst = bag_iter->second;
|
||||
if (bag_inst == nullptr) { continue; }
|
||||
|
||||
if (bag_inst->IsType(ItemClassCommon) && bag_inst->GetItem()->LoreGroup == loregroup)
|
||||
return Inventory::CalcSlotId(iter->first, bag_iter->first);
|
||||
return InventoryOld::CalcSlotId(iter->first, bag_iter->first);
|
||||
|
||||
for (int index = AUG_BEGIN; index < EmuConstants::ITEM_COMMON_SIZE; ++index) {
|
||||
auto aug_inst = bag_inst->GetAugment(index);
|
||||
@@ -1375,9 +1392,9 @@ int16 Inventory::_HasItemByLoreGroup(std::map<int16, ItemInst*>& bucket, uint32
|
||||
}
|
||||
|
||||
// Internal Method: Checks an inventory queue type bucket for a particular item
|
||||
int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup)
|
||||
int16 InventoryOld::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup)
|
||||
{
|
||||
for (auto iter = iqueue.begin(); iter != iqueue.end(); ++iter) {
|
||||
for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) {
|
||||
auto inst = *iter;
|
||||
if (inst == nullptr) { continue; }
|
||||
|
||||
@@ -1394,12 +1411,12 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup)
|
||||
|
||||
if (!inst->IsType(ItemClassContainer)) { continue; }
|
||||
|
||||
for (auto bag_iter = inst->_begin(); bag_iter != inst->_end(); ++bag_iter) {
|
||||
for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) {
|
||||
auto bag_inst = bag_iter->second;
|
||||
if (bag_inst == nullptr) { continue; }
|
||||
|
||||
if (bag_inst->IsType(ItemClassCommon) && bag_inst->GetItem()->LoreGroup == loregroup)
|
||||
return Inventory::CalcSlotId(MainCursor, bag_iter->first);
|
||||
return InventoryOld::CalcSlotId(MainCursor, bag_iter->first);
|
||||
|
||||
for (int index = AUG_BEGIN; index < EmuConstants::ITEM_COMMON_SIZE; ++index) {
|
||||
auto aug_inst = bag_inst->GetAugment(index);
|
||||
@@ -1409,6 +1426,9 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup)
|
||||
return legacy::SLOT_AUGMENT;
|
||||
}
|
||||
}
|
||||
|
||||
// We only check the visible cursor due to lack of queue processing ability (client allows duplicate in limbo)
|
||||
break;
|
||||
}
|
||||
|
||||
return INVALID_INDEX;
|
||||
@@ -1418,7 +1438,7 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup)
|
||||
//
|
||||
// class ItemInst
|
||||
//
|
||||
ItemInst::ItemInst(const Item_Struct* item, int16 charges) {
|
||||
ItemInst::ItemInst(const ItemData* item, int16 charges) {
|
||||
m_use_type = ItemInstNormal;
|
||||
m_item = item;
|
||||
m_charges = charges;
|
||||
@@ -1504,8 +1524,7 @@ ItemInst::ItemInst(const ItemInst& copy)
|
||||
m_attuned=copy.m_attuned;
|
||||
m_merchantcount=copy.m_merchantcount;
|
||||
// Copy container contents
|
||||
iter_contents it;
|
||||
for (it=copy.m_contents.begin(); it!=copy.m_contents.end(); ++it) {
|
||||
for (auto it = copy.m_contents.begin(); it != copy.m_contents.end(); ++it) {
|
||||
ItemInst* inst_old = it->second;
|
||||
ItemInst* inst_new = nullptr;
|
||||
|
||||
@@ -1529,7 +1548,7 @@ ItemInst::ItemInst(const ItemInst& copy)
|
||||
m_evolveLvl = copy.m_evolveLvl;
|
||||
m_activated = copy.m_activated;
|
||||
if (copy.m_scaledItem)
|
||||
m_scaledItem = new Item_Struct(*copy.m_scaledItem);
|
||||
m_scaledItem = new ItemData(*copy.m_scaledItem);
|
||||
else
|
||||
m_scaledItem = nullptr;
|
||||
|
||||
@@ -1675,7 +1694,7 @@ bool ItemInst::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const
|
||||
// Retrieve item inside container
|
||||
ItemInst* ItemInst::GetItem(uint8 index) const
|
||||
{
|
||||
iter_contents it = m_contents.find(index);
|
||||
auto it = m_contents.find(index);
|
||||
if (it != m_contents.end()) {
|
||||
return it->second;
|
||||
}
|
||||
@@ -1738,7 +1757,7 @@ void ItemInst::ClearByFlags(byFlagSetting is_nodrop, byFlagSetting is_norent)
|
||||
// TODO: This needs work...
|
||||
|
||||
// Destroy container contents
|
||||
iter_contents cur, end, del;
|
||||
std::map<uint8, ItemInst*>::const_iterator cur, end, del;
|
||||
cur = m_contents.begin();
|
||||
end = m_contents.end();
|
||||
for (; cur != end;) {
|
||||
@@ -1748,7 +1767,7 @@ void ItemInst::ClearByFlags(byFlagSetting is_nodrop, byFlagSetting is_norent)
|
||||
continue;
|
||||
}
|
||||
|
||||
const Item_Struct* item = inst->GetItem();
|
||||
const ItemData* item = inst->GetItem();
|
||||
if (item == nullptr) {
|
||||
cur = m_contents.erase(cur);
|
||||
continue;
|
||||
@@ -1889,7 +1908,7 @@ bool ItemInst::UpdateOrnamentationInfo() {
|
||||
int32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType);
|
||||
if (GetOrnamentationAug(ornamentationAugtype))
|
||||
{
|
||||
const Item_Struct* ornamentItem;
|
||||
const ItemData* ornamentItem;
|
||||
ornamentItem = GetOrnamentationAug(ornamentationAugtype)->GetItem();
|
||||
if (ornamentItem != nullptr)
|
||||
{
|
||||
@@ -1916,7 +1935,7 @@ bool ItemInst::UpdateOrnamentationInfo() {
|
||||
return ornamentSet;
|
||||
}
|
||||
|
||||
bool ItemInst::CanTransform(const Item_Struct *ItemToTry, const Item_Struct *Container, bool AllowAll) {
|
||||
bool ItemInst::CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll) {
|
||||
if (!ItemToTry || !Container) return false;
|
||||
|
||||
if (ItemToTry->ItemType == ItemTypeArrow || strnlen(Container->CharmFile, 30) == 0)
|
||||
@@ -1984,7 +2003,7 @@ void ItemInst::PutAugment(SharedDatabase *db, uint8 slot, uint32 item_id)
|
||||
if (item_id == NO_ITEM) { return; }
|
||||
if (db == nullptr) { return; /* TODO: add log message for nullptr */ }
|
||||
|
||||
const ItemInst* aug = db->CreateItem(item_id);
|
||||
const ItemInst* aug = db->CreateItemOld(item_id);
|
||||
if (aug) {
|
||||
PutAugment(slot, *aug);
|
||||
safe_delete(aug);
|
||||
@@ -2050,7 +2069,7 @@ bool ItemInst::IsAmmo() const
|
||||
|
||||
}
|
||||
|
||||
const Item_Struct* ItemInst::GetItem() const
|
||||
const ItemData* ItemInst::GetItem() const
|
||||
{
|
||||
if (!m_item)
|
||||
return nullptr;
|
||||
@@ -2061,7 +2080,7 @@ const Item_Struct* ItemInst::GetItem() const
|
||||
return m_item;
|
||||
}
|
||||
|
||||
const Item_Struct* ItemInst::GetUnscaledItem() const
|
||||
const ItemData* ItemInst::GetUnscaledItem() const
|
||||
{
|
||||
// No operator calls and defaults to nullptr
|
||||
return m_item;
|
||||
@@ -2138,9 +2157,9 @@ 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 (InventoryOld::SupportsContainers(slot_id)) { return true; }
|
||||
else if (m_item->Slots & (1 << slot_id)) { return true; }
|
||||
else if (slot_id == MainPowerSource && (m_item->Slots & (1 << 22))) { return true; } // got lazy... <watch>
|
||||
else if (slot_id != MainPowerSource && slot_id > EmuConstants::EQUIPMENT_END) { return true; }
|
||||
@@ -2169,10 +2188,10 @@ void ItemInst::ScaleItem() {
|
||||
return;
|
||||
|
||||
if (m_scaledItem) {
|
||||
memcpy(m_scaledItem, m_item, sizeof(Item_Struct));
|
||||
memcpy(m_scaledItem, m_item, sizeof(ItemData));
|
||||
}
|
||||
else {
|
||||
m_scaledItem = new Item_Struct(*m_item);
|
||||
m_scaledItem = new ItemData(*m_item);
|
||||
}
|
||||
|
||||
float Mult = (float)(GetExp()) / 10000; // scaling is determined by exp, with 10,000 being full stats
|
||||
@@ -2316,9 +2335,9 @@ EvolveInfo::~EvolveInfo() {
|
||||
|
||||
|
||||
//
|
||||
// struct Item_Struct
|
||||
// struct ItemData
|
||||
//
|
||||
bool Item_Struct::IsEquipable(uint16 Race, uint16 Class_) const
|
||||
bool ItemData::IsEquipable(uint16 Race, uint16 Class_) const
|
||||
{
|
||||
bool IsRace = false;
|
||||
bool IsClass = false;
|
||||
@@ -2351,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]);
|
||||
}
|
||||
|
||||
+62
-26
@@ -27,15 +27,12 @@ class ItemParse; // Parses item packets
|
||||
class EvolveInfo; // Stores information about an evolving item family
|
||||
|
||||
#include "../common/eq_constants.h"
|
||||
#include "../common/item_struct.h"
|
||||
#include "../common/item_data.h"
|
||||
#include "../common/timer.h"
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
// Helper typedefs
|
||||
typedef std::map<int16, ItemInst*>::const_iterator iter_inst;
|
||||
typedef std::map<uint8, ItemInst*>::const_iterator iter_contents;
|
||||
|
||||
namespace ItemField
|
||||
{
|
||||
@@ -86,8 +83,8 @@ public:
|
||||
// Public Methods
|
||||
/////////////////////////
|
||||
|
||||
inline std::list<ItemInst*>::const_iterator begin() { return m_list.begin(); }
|
||||
inline std::list<ItemInst*>::const_iterator end() { return m_list.end(); }
|
||||
inline std::list<ItemInst*>::const_iterator cbegin() { return m_list.cbegin(); }
|
||||
inline std::list<ItemInst*>::const_iterator cend() { return m_list.cend(); }
|
||||
|
||||
inline int size() { return static_cast<int>(m_list.size()); } // TODO: change to size_t
|
||||
inline bool empty() { return m_list.empty(); }
|
||||
@@ -107,9 +104,9 @@ protected:
|
||||
};
|
||||
|
||||
// ########################################
|
||||
// Class: Inventory
|
||||
// Class: InventoryOld
|
||||
// Character inventory
|
||||
class Inventory
|
||||
class InventoryOld
|
||||
{
|
||||
friend class ItemInst;
|
||||
public:
|
||||
@@ -117,8 +114,8 @@ public:
|
||||
// Public Methods
|
||||
///////////////////////////////
|
||||
|
||||
Inventory() { m_version = ClientVersion::Unknown; m_versionset = false; }
|
||||
~Inventory();
|
||||
InventoryOld() { m_version = ClientVersion::Unknown; m_versionset = false; }
|
||||
~InventoryOld();
|
||||
|
||||
// Inventory v2 creep
|
||||
bool SetInventoryVersion(ClientVersion version) {
|
||||
@@ -140,8 +137,8 @@ public:
|
||||
ItemInst* GetItem(int16 slot_id) const;
|
||||
ItemInst* GetItem(int16 slot_id, uint8 bagidx) const;
|
||||
|
||||
inline std::list<ItemInst*>::const_iterator cursor_begin() { return m_cursor.begin(); }
|
||||
inline std::list<ItemInst*>::const_iterator cursor_end() { return m_cursor.end(); }
|
||||
inline std::list<ItemInst*>::const_iterator cursor_cbegin() { return m_cursor.cbegin(); }
|
||||
inline std::list<ItemInst*>::const_iterator cursor_cend() { return m_cursor.cend(); }
|
||||
|
||||
inline int CursorSize() { return m_cursor.size(); }
|
||||
inline bool CursorEmpty() { return m_cursor.empty(); }
|
||||
@@ -171,7 +168,7 @@ public:
|
||||
ItemInst* PopItem(int16 slot_id);
|
||||
|
||||
// Check whether there is space for the specified number of the specified item.
|
||||
bool HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity);
|
||||
bool HasSpaceForItem(const ItemData *ItemToTry, int16 Quantity);
|
||||
|
||||
// Check whether item exists in inventory
|
||||
// where argument specifies OR'd list of invWhere constants to look
|
||||
@@ -196,7 +193,7 @@ public:
|
||||
static int16 CalcSlotFromMaterial(uint8 material);
|
||||
static uint8 CalcMaterialFromSlot(int16 equipslot);
|
||||
|
||||
static bool CanItemFitInContainer(const Item_Struct *ItemToTry, const Item_Struct *Container);
|
||||
static bool CanItemFitInContainer(const ItemData *ItemToTry, const ItemData *Container);
|
||||
|
||||
// Test for valid inventory casting slot
|
||||
bool SupportsClickCasting(int16 slot_id);
|
||||
@@ -207,7 +204,7 @@ public:
|
||||
|
||||
int GetSlotByItemInst(ItemInst *inst);
|
||||
|
||||
uint8 FindHighestLightValue();
|
||||
uint8 FindBrightestLightType();
|
||||
|
||||
void dumpEntireInventory();
|
||||
void dumpWornItems();
|
||||
@@ -227,7 +224,7 @@ protected:
|
||||
|
||||
int GetSlotByItemInstCollection(const std::map<int16, ItemInst*> &collection, ItemInst *inst);
|
||||
void dumpItemCollection(const std::map<int16, ItemInst*> &collection);
|
||||
void dumpBagContents(ItemInst *inst, iter_inst *it);
|
||||
void dumpBagContents(ItemInst *inst, std::map<int16, ItemInst*>::const_iterator *it);
|
||||
|
||||
// Retrieves item within an inventory bucket
|
||||
ItemInst* _GetItem(const std::map<int16, ItemInst*>& bucket, int16 slot_id) const;
|
||||
@@ -273,7 +270,7 @@ public:
|
||||
/////////////////////////
|
||||
|
||||
// Constructors/Destructor
|
||||
ItemInst(const Item_Struct* item = nullptr, int16 charges = 0);
|
||||
ItemInst(const ItemData* item = nullptr, int16 charges = 0);
|
||||
|
||||
ItemInst(SharedDatabase *db, uint32 item_id, int16 charges = 0);
|
||||
|
||||
@@ -334,7 +331,7 @@ public:
|
||||
bool IsAugmented();
|
||||
ItemInst* GetOrnamentationAug(int32 ornamentationAugtype) const;
|
||||
bool UpdateOrnamentationInfo();
|
||||
static bool CanTransform(const Item_Struct *ItemToTry, const Item_Struct *Container, bool AllowAll = false);
|
||||
static bool CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll = false);
|
||||
|
||||
// Has attack/delay?
|
||||
bool IsWeapon() const;
|
||||
@@ -343,8 +340,8 @@ public:
|
||||
// Accessors
|
||||
const uint32 GetID() const { return ((m_item) ? m_item->ID : NO_ITEM); }
|
||||
const uint32 GetItemScriptID() const { return ((m_item) ? m_item->ScriptFileID : NO_ITEM); }
|
||||
const Item_Struct* GetItem() const;
|
||||
const Item_Struct* GetUnscaledItem() const;
|
||||
const ItemData* GetItem() const;
|
||||
const ItemData* GetUnscaledItem() const;
|
||||
|
||||
int16 GetCharges() const { return m_charges; }
|
||||
void SetCharges(int16 charges) { m_charges = charges; }
|
||||
@@ -379,7 +376,7 @@ public:
|
||||
// Allows treatment of this object as though it were a pointer to m_item
|
||||
operator bool() const { return (m_item != nullptr); }
|
||||
|
||||
// Compare inner Item_Struct of two ItemInst objects
|
||||
// Compare inner ItemData of two ItemInst objects
|
||||
bool operator==(const ItemInst& right) const { return (this->m_item == right.m_item); }
|
||||
bool operator!=(const ItemInst& right) const { return (this->m_item != right.m_item); }
|
||||
|
||||
@@ -425,16 +422,16 @@ protected:
|
||||
//////////////////////////
|
||||
// Protected Members
|
||||
//////////////////////////
|
||||
iter_contents _begin() { return m_contents.begin(); }
|
||||
iter_contents _end() { return m_contents.end(); }
|
||||
std::map<uint8, ItemInst*>::const_iterator _cbegin() { return m_contents.cbegin(); }
|
||||
std::map<uint8, ItemInst*>::const_iterator _cend() { return m_contents.cend(); }
|
||||
|
||||
friend class Inventory;
|
||||
friend class InventoryOld;
|
||||
|
||||
|
||||
void _PutItem(uint8 index, ItemInst* inst) { m_contents[index] = inst; }
|
||||
|
||||
ItemInstTypes m_use_type; // Usage type for item
|
||||
const Item_Struct* m_item; // Ptr to item data
|
||||
const ItemData* m_item; // Ptr to item data
|
||||
int16 m_charges; // # of charges for chargeable items
|
||||
uint32 m_price; // Bazaar /trader price
|
||||
uint32 m_color;
|
||||
@@ -446,7 +443,7 @@ protected:
|
||||
uint32 m_exp;
|
||||
int8 m_evolveLvl;
|
||||
bool m_activated;
|
||||
Item_Struct* m_scaledItem;
|
||||
ItemData* m_scaledItem;
|
||||
EvolveInfo* m_evolveInfo;
|
||||
bool m_scaling;
|
||||
uint32 m_ornamenticon;
|
||||
@@ -475,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
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
#include "item_container.h"
|
||||
#include "item_container_default_serialization.h"
|
||||
#include <utility>
|
||||
|
||||
struct EQEmu::ItemContainer::impl
|
||||
{
|
||||
std::map<int, ItemInstance::pointer> items_;
|
||||
ItemContainerSerializationStrategy *serialize_strat_;
|
||||
};
|
||||
|
||||
EQEmu::ItemContainer::ItemContainer()
|
||||
{
|
||||
impl_ = new impl();
|
||||
impl_->serialize_strat_ = new ItemContainerDefaultSerialization();
|
||||
}
|
||||
|
||||
EQEmu::ItemContainer::ItemContainer(ItemContainerSerializationStrategy *strategy) {
|
||||
impl_ = new impl();
|
||||
impl_->serialize_strat_ = strategy;
|
||||
}
|
||||
|
||||
EQEmu::ItemContainer::~ItemContainer()
|
||||
{
|
||||
if(impl_) {
|
||||
delete impl_->serialize_strat_;
|
||||
delete impl_;
|
||||
}
|
||||
}
|
||||
|
||||
EQEmu::ItemContainer::ItemContainer(ItemContainer &&other) {
|
||||
impl_ = other.impl_;
|
||||
other.impl_ = nullptr;
|
||||
}
|
||||
|
||||
EQEmu::ItemContainer& EQEmu::ItemContainer::operator=(ItemContainer &&other) {
|
||||
if(this == &other)
|
||||
return *this;
|
||||
|
||||
impl_ = other.impl_;
|
||||
other.impl_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
EQEmu::ItemInstance::pointer EQEmu::ItemContainer::Get(const int slot_id) {
|
||||
auto iter = impl_->items_.find(slot_id);
|
||||
if(iter != impl_->items_.end()) {
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
return EQEmu::ItemInstance::pointer(nullptr);
|
||||
}
|
||||
|
||||
bool EQEmu::ItemContainer::Put(const int slot_id, ItemInstance::pointer &inst) {
|
||||
if(!inst) {
|
||||
impl_->items_.erase(slot_id);
|
||||
return true;
|
||||
} else {
|
||||
auto iter = impl_->items_.find(slot_id);
|
||||
if(iter == impl_->items_.end()) {
|
||||
impl_->items_[slot_id] = inst;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EQEmu::ItemContainer::HasItem(uint32 item_id) {
|
||||
for(auto &item : impl_->items_) {
|
||||
if(item.second->GetBaseItem()->ID == item_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EQEmu::ItemContainer::HasItemByLoreGroup(uint32 loregroup) {
|
||||
if(loregroup == 0xFFFFFFFF)
|
||||
return false;
|
||||
|
||||
for(auto &item : impl_->items_) {
|
||||
if(item.second->GetBaseItem()->LoreGroup == loregroup) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemContainer::Size() {
|
||||
return (uint32)impl_->items_.size();
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemContainer::Size() const {
|
||||
return (uint32)impl_->items_.size();
|
||||
}
|
||||
|
||||
bool EQEmu::ItemContainer::Delete(const int slot_id) {
|
||||
auto iter = impl_->items_.find(slot_id);
|
||||
if(iter == impl_->items_.end()) {
|
||||
return false;
|
||||
} else {
|
||||
impl_->items_.erase(iter);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool EQEmu::ItemContainer::Serialize(MemoryBuffer &buf, int container_number) {
|
||||
if(impl_->serialize_strat_) {
|
||||
return impl_->serialize_strat_->Serialize(buf, container_number, impl_->items_);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
EQEmu::ItemContainer::ItemContainerIter EQEmu::ItemContainer::Begin() {
|
||||
return impl_->items_.begin();
|
||||
}
|
||||
|
||||
EQEmu::ItemContainer::ItemContainerIter EQEmu::ItemContainer::End() {
|
||||
return impl_->items_.end();
|
||||
}
|
||||
|
||||
void EQEmu::ItemContainer::Interrogate(int level) {
|
||||
char buffer[16] = { 0 };
|
||||
for(int i = 0; i < level; ++i) {
|
||||
buffer[i] = '\t';
|
||||
}
|
||||
|
||||
for(auto &iter : impl_->items_) {
|
||||
printf("%s%u: (%u)%s (%u)\n", buffer, iter.first, iter.second->GetBaseItem()->ID, iter.second->GetBaseItem()->Name, iter.second->GetCharges());
|
||||
iter.second->Interrogate(level + 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/* 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 COMMON_ITEM_CONTAINER_H
|
||||
#define COMMON_ITEM_CONTAINER_H
|
||||
|
||||
#include "item_instance.h"
|
||||
#include "item_container_serialization_strategy.h"
|
||||
#include "memory_buffer.h"
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
namespace EQEmu
|
||||
{
|
||||
class ItemContainerSerializationStrategy;
|
||||
class ItemContainer
|
||||
{
|
||||
public:
|
||||
typedef std::map<int, ItemInstance::pointer>::const_iterator ItemContainerIter;
|
||||
|
||||
ItemContainer();
|
||||
ItemContainer(ItemContainerSerializationStrategy *strategy);
|
||||
~ItemContainer();
|
||||
ItemContainer(ItemContainer &&other);
|
||||
ItemContainer& operator=(ItemContainer &&other);
|
||||
|
||||
ItemInstance::pointer Get(const int slot_id);
|
||||
bool Put(const int slot_id, ItemInstance::pointer &inst);
|
||||
bool Delete(const int slot_id);
|
||||
|
||||
//Utility
|
||||
bool HasItem(uint32 item_id);
|
||||
bool HasItemByLoreGroup(uint32 loregroup);
|
||||
|
||||
uint32 Size();
|
||||
uint32 Size() const;
|
||||
|
||||
//Low level interface for encode/decode
|
||||
bool Serialize(MemoryBuffer &buf, int container_number);
|
||||
ItemContainerIter Begin();
|
||||
ItemContainerIter End();
|
||||
|
||||
//testing
|
||||
void Interrogate(int level);
|
||||
protected:
|
||||
struct impl;
|
||||
impl *impl_;
|
||||
|
||||
private:
|
||||
ItemContainer(const ItemContainer &other);
|
||||
ItemContainer& operator=(const ItemContainer &other);
|
||||
};
|
||||
} // EQEmu
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "item_container_default_serialization.h"
|
||||
|
||||
bool EQEmu::ItemContainerDefaultSerialization::Serialize(MemoryBuffer &buf, const int container_number, const std::map<int, ItemInstance::pointer>& items) {
|
||||
if(items.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
for(auto &iter : items) {
|
||||
buf.Write<int32>(container_number);
|
||||
buf.Write<int32>(iter.first);
|
||||
buf.Write<int32>(-1);
|
||||
buf.Write<int32>(-1);
|
||||
buf.Write<void*>(iter.second.get());
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/* 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 COMMON_ITEM_CONTAINER_DEFAULT_SERIALIZATION_H
|
||||
#define COMMON_ITEM_CONTAINER_DEFAULT_SERIALIZATION_H
|
||||
|
||||
#include "item_container_serialization_strategy.h"
|
||||
|
||||
namespace EQEmu
|
||||
{
|
||||
class ItemContainerDefaultSerialization : public ItemContainerSerializationStrategy
|
||||
{
|
||||
public:
|
||||
ItemContainerDefaultSerialization() { }
|
||||
virtual ~ItemContainerDefaultSerialization() { }
|
||||
virtual bool Serialize(MemoryBuffer &buf, const int container_number, const std::map<int, ItemInstance::pointer>& items);
|
||||
};
|
||||
} // EQEmu
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
#include "item_container_personal_serialization.h"
|
||||
|
||||
bool EQEmu::ItemContainerPersonalSerialization::Serialize(MemoryBuffer &buf, const int container_number, const std::map<int, ItemInstance::pointer>& items) {
|
||||
if(items.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
for(auto &iter : items) {
|
||||
if(iter.first < 33) {
|
||||
buf.Write<int32>(container_number);
|
||||
buf.Write<int32>(iter.first);
|
||||
buf.Write<int32>(-1);
|
||||
buf.Write<int32>(-1);
|
||||
buf.Write<void*>(iter.second.get());
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/* 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 COMMON_ITEM_CONTAINER_PERSONAL_SERIALIZATION_H
|
||||
#define COMMON_ITEM_CONTAINER_PERSONAL_SERIALIZATION_H
|
||||
|
||||
#include "item_container_serialization_strategy.h"
|
||||
|
||||
namespace EQEmu
|
||||
{
|
||||
class ItemContainerPersonalSerialization : public ItemContainerSerializationStrategy
|
||||
{
|
||||
public:
|
||||
ItemContainerPersonalSerialization() { }
|
||||
virtual ~ItemContainerPersonalSerialization() { }
|
||||
virtual bool Serialize(MemoryBuffer &buf, const int container_number, const std::map<int, ItemInstance::pointer>& items);
|
||||
};
|
||||
} // EQEmu
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
/* 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 COMMON_ITEM_CONTAINER_SERIALIZATION_STRATEGY_H
|
||||
#define COMMON_ITEM_CONTAINER_SERIALIZATION_STRATEGY_H
|
||||
|
||||
#include "item_container.h"
|
||||
#include "memory_buffer.h"
|
||||
#include <map>
|
||||
|
||||
namespace EQEmu
|
||||
{
|
||||
class ItemContainerSerializationStrategy
|
||||
{
|
||||
public:
|
||||
ItemContainerSerializationStrategy() { }
|
||||
virtual ~ItemContainerSerializationStrategy() { }
|
||||
virtual bool Serialize(MemoryBuffer &buf, const int container_number, const std::map<int, ItemInstance::pointer>& items) = 0;
|
||||
};
|
||||
} // EQEmu
|
||||
|
||||
#endif
|
||||
@@ -16,8 +16,8 @@
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef ITEM_STRUCT_H
|
||||
#define ITEM_STRUCT_H
|
||||
#ifndef COMMON_ITEM_DATA_H
|
||||
#define COMMON_ITEM_DATA_H
|
||||
|
||||
/*
|
||||
* Note: (Doodman)
|
||||
@@ -35,7 +35,7 @@
|
||||
*
|
||||
* Note #3: (Doodman)
|
||||
* Please take care when adding new found data fields to add them
|
||||
* to the appropriate structure. Item_Struct has elements that are
|
||||
* to the appropriate structure. ItemData has elements that are
|
||||
* global to all types of items only.
|
||||
*
|
||||
* Note #4: (Doodman)
|
||||
@@ -46,7 +46,7 @@
|
||||
#include "eq_dictionary.h"
|
||||
|
||||
/*
|
||||
** Child struct of Item_Struct:
|
||||
** Child struct of ItemData:
|
||||
** Effect data: Click, Proc, Focus, Worn, Scroll
|
||||
**
|
||||
*/
|
||||
@@ -69,10 +69,18 @@ struct InternalSerializedItem_Struct {
|
||||
const void * inst;
|
||||
};
|
||||
|
||||
struct SerializedItemInstance_Struct {
|
||||
int32 container_id;
|
||||
int32 slot_id;
|
||||
int32 bag_id;
|
||||
int32 aug_id;
|
||||
void *inst;
|
||||
};
|
||||
|
||||
// use EmuConstants::ITEM_COMMON_SIZE
|
||||
//#define MAX_AUGMENT_SLOTS 5
|
||||
|
||||
struct Item_Struct {
|
||||
struct ItemData {
|
||||
bool IsEquipable(uint16 Race, uint16 Class) const;
|
||||
// Non packet based fields
|
||||
uint8 MinStatus;
|
||||
@@ -99,17 +107,10 @@ struct Item_Struct {
|
||||
uint32 Favor; // Individual favor
|
||||
uint32 GuildFavor; // Guild favor
|
||||
uint32 PointType;
|
||||
|
||||
//uint32 Unk117;
|
||||
//uint32 Unk118;
|
||||
//uint32 Unk121;
|
||||
//uint32 Unk124;
|
||||
|
||||
uint8 BagType; // 0:Small Bag, 1:Large Bag, 2:Quiver, 3:Belt Pouch ... there are 50 types
|
||||
uint8 BagSlots; // Number of slots: can only be 2, 4, 6, 8, or 10
|
||||
uint8 BagSlots; // Number of slots
|
||||
uint8 BagSize; // 0:TINY, 1:SMALL, 2:MEDIUM, 3:LARGE, 4:GIANT
|
||||
uint8 BagWR; // 0->100
|
||||
|
||||
bool BenefitFlag;
|
||||
bool Tradeskills; // Is this a tradeskill item?
|
||||
int8 CR; // Save vs Cold
|
||||
@@ -128,7 +129,6 @@ struct Item_Struct {
|
||||
int32 Mana; // Mana
|
||||
int32 AC; // AC
|
||||
uint32 Deity; // Bitmask of Deities that can equip this item
|
||||
//uint32 Unk033
|
||||
int32 SkillModValue; // % Mod to skill specified in SkillModType
|
||||
uint32 SkillModType; // Type of skill for SkillModValue to apply to
|
||||
uint32 BaneDmgRace; // Bane Damage Race
|
||||
@@ -150,13 +150,11 @@ struct Item_Struct {
|
||||
uint32 Color; // RR GG BB 00 <-- as it appears in pc
|
||||
uint32 Classes; // Bitfield of classes that can equip item (1 << class#)
|
||||
uint32 Races; // Bitfield of races that can equip item (1 << race#)
|
||||
//uint32 Unk054;
|
||||
int16 MaxCharges; // Maximum charges items can hold: -1 if not a chargeable item
|
||||
uint8 ItemType; // Item Type/Skill (itemClass* from above)
|
||||
uint8 Material; // Item material type
|
||||
uint32 HerosForgeModel;// Hero's Forge Armor Model Type (2-13?)
|
||||
float SellRate; // Sell rate
|
||||
//uint32 Unk059;
|
||||
union {
|
||||
uint32 Fulfilment; // Food fulfilment (How long it lasts)
|
||||
int16 CastTime; // Cast Time for clicky effects, in milliseconds
|
||||
@@ -185,7 +183,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;
|
||||
@@ -211,7 +209,6 @@ struct Item_Struct {
|
||||
int16 StackSize;
|
||||
uint8 PotionBeltSlots;
|
||||
ItemEffect_Struct Click, Proc, Worn, Focus, Scroll, Bard;
|
||||
|
||||
uint8 Book; // 0=Not book, 1=Book
|
||||
uint32 BookType;
|
||||
char Filename[33]; // Filename for book data
|
||||
@@ -240,11 +237,11 @@ struct Item_Struct {
|
||||
uint32 ScriptFileID;
|
||||
uint16 ExpendableArrow;
|
||||
uint32 Clairvoyance;
|
||||
char ClickName[65];
|
||||
char ProcName[65];
|
||||
char WornName[65];
|
||||
char FocusName[65];
|
||||
char ScrollName[65];
|
||||
char ClickName[65];
|
||||
char ProcName[65];
|
||||
char WornName[65];
|
||||
char FocusName[65];
|
||||
char ScrollName[65];
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,389 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
#include "item_instance.h"
|
||||
#include "data_verification.h"
|
||||
#include "item_container.h"
|
||||
|
||||
uint32 ItemInstanceSerial = 1;
|
||||
uint32 EQEmu::GetNextItemInstanceSerial() {
|
||||
ItemInstanceSerial++;
|
||||
return ItemInstanceSerial;
|
||||
}
|
||||
|
||||
struct EQEmu::ItemInstance::impl {
|
||||
const ItemData *base_item_;
|
||||
ItemData *modified_item_;
|
||||
int16 charges_;
|
||||
uint32 color_;
|
||||
bool attuned_;
|
||||
std::string custom_data_;
|
||||
uint32 ornament_idfile_;
|
||||
uint32 ornament_icon_;
|
||||
uint32 ornament_hero_model_;
|
||||
char tracking_id_[17];
|
||||
uint32 serial_id_;
|
||||
uint32 recast_timestamp_;
|
||||
uint32 merchant_slot_;
|
||||
uint32 merchant_count_;
|
||||
uint32 price_;
|
||||
ItemContainer contents_;
|
||||
};
|
||||
|
||||
EQEmu::ItemInstance::ItemInstance(const ItemData* idata) {
|
||||
impl_ = new impl;
|
||||
impl_->base_item_ = idata;
|
||||
impl_->modified_item_ = nullptr;
|
||||
impl_->charges_ = -1;
|
||||
impl_->color_ = 0;
|
||||
impl_->attuned_ = false;
|
||||
impl_->ornament_idfile_ = 0;
|
||||
impl_->ornament_icon_ = 0;
|
||||
impl_->ornament_hero_model_ = 0;
|
||||
impl_->serial_id_ = 0;
|
||||
impl_->recast_timestamp_ = 0;
|
||||
impl_->merchant_slot_ = 0;
|
||||
impl_->merchant_count_ = 0;
|
||||
impl_->price_ = 0;
|
||||
memset(impl_->tracking_id_, 0, 17);
|
||||
}
|
||||
|
||||
EQEmu::ItemInstance::ItemInstance(const ItemData* idata, int16 charges) {
|
||||
impl_ = new impl;
|
||||
impl_->base_item_ = idata;
|
||||
impl_->modified_item_ = nullptr;
|
||||
impl_->charges_ = charges;
|
||||
impl_->color_ = 0;
|
||||
impl_->attuned_ = false;
|
||||
impl_->ornament_idfile_ = 0;
|
||||
impl_->ornament_icon_ = 0;
|
||||
impl_->ornament_hero_model_ = 0;
|
||||
impl_->recast_timestamp_ = 0;
|
||||
impl_->serial_id_ = 0;
|
||||
impl_->merchant_slot_ = 0;
|
||||
impl_->merchant_count_ = 0;
|
||||
impl_->price_ = 0;
|
||||
memset(impl_->tracking_id_, 0, 17);
|
||||
}
|
||||
|
||||
EQEmu::ItemInstance::~ItemInstance() {
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
|
||||
EQEmu::ItemInstance::pointer EQEmu::ItemInstance::Split(int charges) {
|
||||
if(!IsStackable()) {
|
||||
//Can't split non stackable items!
|
||||
return pointer(nullptr);
|
||||
}
|
||||
|
||||
if(charges >= GetCharges()) {
|
||||
return pointer(nullptr);
|
||||
}
|
||||
|
||||
if(impl_->contents_.Size() > 0) {
|
||||
return pointer(nullptr);
|
||||
}
|
||||
|
||||
pointer split = pointer(new EQEmu::ItemInstance(impl_->base_item_, charges));
|
||||
split->SetSerialNumber(EQEmu::GetNextItemInstanceSerial());
|
||||
//Set Tracking here
|
||||
split->impl_->attuned_ = impl_->attuned_;
|
||||
split->impl_->custom_data_ = impl_->custom_data_;
|
||||
split->impl_->recast_timestamp_ = impl_->recast_timestamp_;
|
||||
split->impl_->price_ = impl_->price_;
|
||||
split->impl_->color_ = impl_->color_;
|
||||
split->impl_->merchant_count_ = impl_->merchant_count_;
|
||||
split->impl_->merchant_slot_ = impl_->merchant_slot_;
|
||||
split->impl_->ornament_hero_model_ = impl_->ornament_hero_model_;
|
||||
split->impl_->ornament_icon_ = impl_->ornament_icon_;
|
||||
split->impl_->ornament_idfile_ = impl_->ornament_idfile_;
|
||||
|
||||
SetCharges(GetCharges() - charges);
|
||||
return split;
|
||||
}
|
||||
|
||||
const ItemData *EQEmu::ItemInstance::GetItem() {
|
||||
return impl_->modified_item_ ? impl_->modified_item_ : impl_->base_item_;
|
||||
}
|
||||
|
||||
const ItemData *EQEmu::ItemInstance::GetBaseItem() {
|
||||
return impl_->base_item_;
|
||||
}
|
||||
|
||||
const ItemData *EQEmu::ItemInstance::GetBaseItem() const {
|
||||
return impl_->base_item_;
|
||||
}
|
||||
|
||||
EQEmu::ItemInstance::pointer EQEmu::ItemInstance::Get(const int index) {
|
||||
if(EQEmu::ValueWithin(index, 0, 255)) {
|
||||
return impl_->contents_.Get(index);
|
||||
}
|
||||
|
||||
return pointer(nullptr);
|
||||
}
|
||||
|
||||
bool EQEmu::ItemInstance::Put(const int index, pointer &inst) {
|
||||
if(!impl_->base_item_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto item = impl_->base_item_;
|
||||
if(item->ItemClass == ItemClassContainer) { // Bag
|
||||
if(!EQEmu::ValueWithin(index, 0, item->BagSlots)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return impl_->contents_.Put(index, inst);
|
||||
}
|
||||
else if(item->ItemClass == ItemClassCommon) { // Augment
|
||||
if(!EQEmu::ValueWithin(index, 0, EmuConstants::ITEM_COMMON_SIZE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!item->AugSlotVisible[index]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(inst) {
|
||||
auto *aug_item = inst->GetItem();
|
||||
int aug_type = aug_item->AugType;
|
||||
if(aug_type == -1 || (1 << (item->AugSlotType[index] - 1)) & aug_type) {
|
||||
return impl_->contents_.Put(index, inst);
|
||||
}
|
||||
} else {
|
||||
return impl_->contents_.Put(index, inst);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int16 EQEmu::ItemInstance::GetCharges() {
|
||||
return impl_->charges_;
|
||||
}
|
||||
|
||||
int16 EQEmu::ItemInstance::GetCharges() const {
|
||||
return impl_->charges_;
|
||||
}
|
||||
|
||||
void EQEmu::ItemInstance::SetCharges(const int16 charges) {
|
||||
impl_->charges_ = charges;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetColor() {
|
||||
return impl_->color_;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetColor() const {
|
||||
return impl_->color_;
|
||||
}
|
||||
|
||||
void EQEmu::ItemInstance::SetColor(const uint32 color) {
|
||||
impl_->color_ = color;
|
||||
}
|
||||
|
||||
bool EQEmu::ItemInstance::GetAttuned() {
|
||||
return impl_->attuned_;
|
||||
}
|
||||
|
||||
bool EQEmu::ItemInstance::GetAttuned() const {
|
||||
return impl_->attuned_;
|
||||
}
|
||||
|
||||
void EQEmu::ItemInstance::SetAttuned(const bool attuned) {
|
||||
impl_->attuned_ = attuned;
|
||||
}
|
||||
|
||||
std::string EQEmu::ItemInstance::GetCustomData() {
|
||||
return impl_->custom_data_;
|
||||
}
|
||||
|
||||
std::string EQEmu::ItemInstance::GetCustomData() const {
|
||||
return impl_->custom_data_;
|
||||
}
|
||||
|
||||
void EQEmu::ItemInstance::SetCustomData(const std::string &custom_data) {
|
||||
//We need to actually set the custom data stuff based on this string
|
||||
impl_->custom_data_ = custom_data;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetOrnamentIDFile() {
|
||||
return impl_->ornament_idfile_;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetOrnamentIDFile() const {
|
||||
return impl_->ornament_idfile_;
|
||||
}
|
||||
|
||||
void EQEmu::ItemInstance::SetOrnamentIDFile(const uint32 ornament_idfile) {
|
||||
impl_->ornament_idfile_ = ornament_idfile;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetOrnamentIcon() {
|
||||
return impl_->ornament_icon_;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetOrnamentIcon() const {
|
||||
return impl_->ornament_icon_;
|
||||
}
|
||||
|
||||
void EQEmu::ItemInstance::SetOrnamentIcon(const uint32 ornament_icon) {
|
||||
impl_->ornament_icon_ = ornament_icon;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetOrnamentHeroModel() {
|
||||
return impl_->ornament_hero_model_;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetOrnamentHeroModel() const {
|
||||
return impl_->ornament_hero_model_;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetOrnamentHeroModel(int material_slot) {
|
||||
uint32 hero_model = 0;
|
||||
if(impl_->ornament_hero_model_ > 0)
|
||||
{
|
||||
hero_model = impl_->ornament_hero_model_;
|
||||
if(material_slot >= 0)
|
||||
{
|
||||
hero_model = (impl_->ornament_hero_model_ * 100) + material_slot;
|
||||
}
|
||||
}
|
||||
return hero_model;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetOrnamentHeroModel(int material_slot) const {
|
||||
uint32 hero_model = 0;
|
||||
if(impl_->ornament_hero_model_ > 0)
|
||||
{
|
||||
hero_model = impl_->ornament_hero_model_;
|
||||
if(material_slot >= 0)
|
||||
{
|
||||
hero_model = (impl_->ornament_hero_model_ * 100) + material_slot;
|
||||
}
|
||||
}
|
||||
return hero_model;
|
||||
}
|
||||
|
||||
void EQEmu::ItemInstance::SetOrnamentHeroModel(const uint32 ornament_hero_model) {
|
||||
impl_->ornament_hero_model_ = ornament_hero_model;
|
||||
}
|
||||
|
||||
const char* EQEmu::ItemInstance::GetTrackingID() {
|
||||
return impl_->tracking_id_;
|
||||
}
|
||||
|
||||
const char* EQEmu::ItemInstance::GetTrackingID() const {
|
||||
return impl_->tracking_id_;
|
||||
}
|
||||
|
||||
void EQEmu::ItemInstance::SetTrackingID(const char *tracking_id) {
|
||||
size_t len = strlen(tracking_id);
|
||||
if(len > 16) {
|
||||
return;
|
||||
}
|
||||
|
||||
strncpy(impl_->tracking_id_, tracking_id, 16);
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetRecastTimestamp() {
|
||||
return impl_->recast_timestamp_;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetRecastTimestamp() const {
|
||||
return impl_->recast_timestamp_;
|
||||
}
|
||||
|
||||
void EQEmu::ItemInstance::SetRecastTimestamp(const uint32 recast_timestamp) {
|
||||
impl_->recast_timestamp_ = recast_timestamp;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetMerchantSlot() {
|
||||
return impl_->merchant_slot_;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetMerchantSlot() const {
|
||||
return impl_->merchant_slot_;
|
||||
}
|
||||
|
||||
void EQEmu::ItemInstance::SetMerchantSlot(uint32 slot) {
|
||||
impl_->merchant_slot_ = slot;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetMerchantCount() {
|
||||
return impl_->merchant_count_;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetMerchantCount() const {
|
||||
return impl_->merchant_count_;
|
||||
}
|
||||
|
||||
void EQEmu::ItemInstance::SetMerchantCount(const uint32 cnt) {
|
||||
impl_->merchant_count_ = cnt;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetPrice() {
|
||||
return impl_->price_;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetPrice() const {
|
||||
return impl_->price_;
|
||||
}
|
||||
|
||||
void EQEmu::ItemInstance::SetPrice(const uint32 p) {
|
||||
impl_->price_ = p;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetSerialNumber() {
|
||||
return impl_->serial_id_;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetSerialNumber() const {
|
||||
return impl_->serial_id_;
|
||||
}
|
||||
|
||||
void EQEmu::ItemInstance::SetSerialNumber(const uint32 sn) {
|
||||
impl_->serial_id_ = sn;
|
||||
}
|
||||
|
||||
bool EQEmu::ItemInstance::IsStackable() {
|
||||
return impl_->base_item_->Stackable;
|
||||
}
|
||||
|
||||
bool EQEmu::ItemInstance::IsStackable() const {
|
||||
return impl_->base_item_->Stackable;
|
||||
}
|
||||
|
||||
bool EQEmu::ItemInstance::IsNoDrop() {
|
||||
return GetAttuned() || GetBaseItem()->NoDrop == 0;
|
||||
}
|
||||
|
||||
bool EQEmu::ItemInstance::IsNoDrop() const {
|
||||
return GetAttuned() || GetBaseItem()->NoDrop == 0;
|
||||
}
|
||||
|
||||
EQEmu::ItemContainer *EQEmu::ItemInstance::GetContainer() {
|
||||
return &(impl_->contents_);
|
||||
}
|
||||
|
||||
void EQEmu::ItemInstance::Interrogate(int level) {
|
||||
impl_->contents_.Interrogate(level);
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/* 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 COMMON_ITEM_INSTANCE_H
|
||||
#define COMMON_ITEM_INSTANCE_H
|
||||
|
||||
#include "item_data.h"
|
||||
#include <memory>
|
||||
|
||||
namespace EQEmu
|
||||
{
|
||||
uint32 GetNextItemInstanceSerial();
|
||||
|
||||
class ItemContainer;
|
||||
class ItemInstance
|
||||
{
|
||||
public:
|
||||
typedef std::shared_ptr<ItemInstance> pointer;
|
||||
ItemInstance(const ItemData* idata);
|
||||
ItemInstance(const ItemData* idata, const int16 charges);
|
||||
~ItemInstance();
|
||||
|
||||
const ItemData *GetItem();
|
||||
const ItemData *GetBaseItem();
|
||||
const ItemData *GetBaseItem() const;
|
||||
|
||||
pointer Split(int charges);
|
||||
|
||||
//Container
|
||||
pointer Get(const int index);
|
||||
bool Put(const int index, pointer &inst);
|
||||
|
||||
//Persistent State
|
||||
int16 GetCharges();
|
||||
int16 GetCharges() const;
|
||||
void SetCharges(const int16 charges);
|
||||
|
||||
uint32 GetColor();
|
||||
uint32 GetColor() const;
|
||||
void SetColor(const uint32 color);
|
||||
|
||||
bool GetAttuned();
|
||||
bool GetAttuned() const;
|
||||
void SetAttuned(const bool attuned);
|
||||
|
||||
std::string GetCustomData();
|
||||
std::string GetCustomData() const;
|
||||
void SetCustomData(const std::string &custom_data);
|
||||
|
||||
uint32 GetOrnamentIDFile();
|
||||
uint32 GetOrnamentIDFile() const;
|
||||
void SetOrnamentIDFile(const uint32 ornament_idfile);
|
||||
|
||||
uint32 GetOrnamentIcon();
|
||||
uint32 GetOrnamentIcon() const;
|
||||
void SetOrnamentIcon(const uint32 ornament_icon);
|
||||
|
||||
uint32 GetOrnamentHeroModel();
|
||||
uint32 GetOrnamentHeroModel() const;
|
||||
uint32 GetOrnamentHeroModel(int material_slot);
|
||||
uint32 GetOrnamentHeroModel(int material_slot) const;
|
||||
void SetOrnamentHeroModel(const uint32 ornament_hero_model);
|
||||
|
||||
const char* GetTrackingID();
|
||||
const char* GetTrackingID() const;
|
||||
void SetTrackingID(const char *tracking_id);
|
||||
|
||||
uint32 GetRecastTimestamp();
|
||||
uint32 GetRecastTimestamp() const;
|
||||
void SetRecastTimestamp(const uint32 recast_timestamp);
|
||||
|
||||
//Merchant
|
||||
uint32 GetMerchantSlot();
|
||||
uint32 GetMerchantSlot() const;
|
||||
void SetMerchantSlot(const uint32 slot);
|
||||
|
||||
uint32 GetMerchantCount();
|
||||
uint32 GetMerchantCount() const;
|
||||
void SetMerchantCount(const uint32 cnt);
|
||||
|
||||
uint32 GetPrice();
|
||||
uint32 GetPrice() const;
|
||||
void SetPrice(const uint32 p);
|
||||
|
||||
//Serial Number
|
||||
uint32 GetSerialNumber();
|
||||
uint32 GetSerialNumber() const;
|
||||
void SetSerialNumber(uint32 sn);
|
||||
|
||||
//Basic Stats
|
||||
bool IsStackable();
|
||||
bool IsStackable() const;
|
||||
|
||||
bool IsNoDrop();
|
||||
bool IsNoDrop() const;
|
||||
|
||||
void CheckStackRemaining(pointer &insert, int &charges);
|
||||
|
||||
//Internal state
|
||||
//Used for low level operations such as encode/decode
|
||||
ItemContainer *GetContainer();
|
||||
|
||||
void Interrogate(int level);
|
||||
private:
|
||||
struct impl;
|
||||
impl *impl_;
|
||||
};
|
||||
|
||||
} // EQEmu
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,212 @@
|
||||
#include "memory_buffer.h"
|
||||
|
||||
EQEmu::MemoryBuffer::MemoryBuffer() {
|
||||
buffer_ = nullptr;
|
||||
size_ = 0;
|
||||
capacity_ = 0;
|
||||
read_pos_ = 0;
|
||||
write_pos_ = 0;
|
||||
}
|
||||
|
||||
EQEmu::MemoryBuffer::MemoryBuffer(size_t sz) {
|
||||
buffer_ = nullptr;
|
||||
size_ = 0;
|
||||
capacity_ = 0;
|
||||
read_pos_ = 0;
|
||||
write_pos_ = 0;
|
||||
Resize(sz);
|
||||
}
|
||||
|
||||
EQEmu::MemoryBuffer::MemoryBuffer(const MemoryBuffer &other) {
|
||||
if(other.capacity_) {
|
||||
buffer_ = new uchar[other.capacity_];
|
||||
memcpy(buffer_, other.buffer_, other.capacity_);
|
||||
} else {
|
||||
buffer_ = nullptr;
|
||||
}
|
||||
|
||||
size_ = other.size_;
|
||||
capacity_ = other.capacity_;
|
||||
write_pos_ = other.write_pos_;
|
||||
read_pos_ = other.read_pos_;
|
||||
}
|
||||
|
||||
EQEmu::MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) {
|
||||
uchar *tbuf = other.buffer_;
|
||||
size_t tsz = other.size_;
|
||||
size_t tcapacity = other.capacity_;
|
||||
size_t twrite_pos = other.write_pos_;
|
||||
size_t tread_pos = other.read_pos_;
|
||||
|
||||
other.buffer_ = nullptr;
|
||||
other.size_ = 0;
|
||||
other.capacity_ = 0;
|
||||
other.read_pos_ = 0;
|
||||
other.write_pos_ = 0;
|
||||
|
||||
buffer_ = tbuf;
|
||||
size_ = tsz;
|
||||
capacity_ = tcapacity;
|
||||
write_pos_ = twrite_pos;
|
||||
read_pos_ = tread_pos;
|
||||
}
|
||||
|
||||
EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator=(const MemoryBuffer &other) {
|
||||
if(this == &other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
if(buffer_) {
|
||||
delete[] buffer_;
|
||||
}
|
||||
|
||||
if(other.capacity_) {
|
||||
buffer_ = new uchar[other.capacity_];
|
||||
memcpy(buffer_, other.buffer_, other.capacity_);
|
||||
}
|
||||
else {
|
||||
buffer_ = nullptr;
|
||||
}
|
||||
|
||||
size_ = other.size_;
|
||||
capacity_ = other.capacity_;
|
||||
write_pos_ = other.write_pos_;
|
||||
read_pos_ = other.read_pos_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator=(MemoryBuffer &&other) {
|
||||
uchar *tbuf = other.buffer_;
|
||||
size_t tsz = other.size_;
|
||||
size_t tcapacity = other.capacity_;
|
||||
size_t twrite_pos = other.write_pos_;
|
||||
size_t tread_pos = other.read_pos_;
|
||||
|
||||
other.buffer_ = nullptr;
|
||||
other.size_ = 0;
|
||||
other.capacity_ = 0;
|
||||
other.read_pos_ = 0;
|
||||
other.write_pos_ = 0;
|
||||
|
||||
buffer_ = tbuf;
|
||||
size_ = tsz;
|
||||
capacity_ = tcapacity;
|
||||
write_pos_ = twrite_pos;
|
||||
read_pos_ = tread_pos;
|
||||
return *this;
|
||||
}
|
||||
|
||||
EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator+=(const MemoryBuffer &rhs) {
|
||||
if(!rhs.buffer_) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
if(buffer_) {
|
||||
size_t old_size = size_;
|
||||
Resize(size_ + rhs.size_);
|
||||
memcpy(&buffer_[old_size], rhs.buffer_, rhs.size_);
|
||||
} else {
|
||||
buffer_ = new uchar[rhs.capacity_];
|
||||
memcpy(buffer_, rhs.buffer_, rhs.capacity_);
|
||||
size_ = rhs.size_;
|
||||
capacity_ = rhs.capacity_;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
EQEmu::MemoryBuffer::~MemoryBuffer() { Clear(); }
|
||||
|
||||
uchar& EQEmu::MemoryBuffer::operator[](size_t pos) {
|
||||
return buffer_[pos];
|
||||
}
|
||||
|
||||
const uchar& EQEmu::MemoryBuffer::operator[](size_t pos) const {
|
||||
return buffer_[pos];
|
||||
}
|
||||
|
||||
bool EQEmu::MemoryBuffer::Empty() {
|
||||
return size_ == 0;
|
||||
}
|
||||
|
||||
bool EQEmu::MemoryBuffer::Empty() const {
|
||||
return size_ == 0;
|
||||
}
|
||||
|
||||
size_t EQEmu::MemoryBuffer::Size() {
|
||||
return size_;
|
||||
}
|
||||
|
||||
size_t EQEmu::MemoryBuffer::Size() const {
|
||||
return size_;
|
||||
}
|
||||
|
||||
size_t EQEmu::MemoryBuffer::Capacity() {
|
||||
return capacity_;
|
||||
}
|
||||
|
||||
size_t EQEmu::MemoryBuffer::Capacity() const {
|
||||
return capacity_;
|
||||
}
|
||||
|
||||
void EQEmu::MemoryBuffer::Resize(size_t sz) {
|
||||
if(!buffer_) {
|
||||
size_t new_size = sz + 64;
|
||||
buffer_ = new uchar[new_size];
|
||||
capacity_ = new_size;
|
||||
size_ = sz;
|
||||
memset(buffer_, 0, capacity_);
|
||||
return;
|
||||
}
|
||||
|
||||
if(sz > capacity_) {
|
||||
size_t new_size = sz + 32;
|
||||
uchar *temp = new uchar[new_size];
|
||||
memcpy(temp, buffer_, capacity_);
|
||||
delete[] buffer_;
|
||||
buffer_ = temp;
|
||||
|
||||
capacity_ = new_size;
|
||||
size_ = sz;
|
||||
}
|
||||
else {
|
||||
size_ = sz;
|
||||
}
|
||||
}
|
||||
|
||||
void EQEmu::MemoryBuffer::Clear() {
|
||||
if(buffer_) {
|
||||
delete[] buffer_;
|
||||
buffer_ = nullptr;
|
||||
}
|
||||
|
||||
size_ = 0;
|
||||
capacity_ = 0;
|
||||
write_pos_ = 0;
|
||||
read_pos_ = 0;
|
||||
}
|
||||
|
||||
void EQEmu::MemoryBuffer::Zero() {
|
||||
if(buffer_) {
|
||||
memset(buffer_, 0, capacity_);
|
||||
}
|
||||
}
|
||||
|
||||
void EQEmu::MemoryBuffer::Write(const char *val, size_t len) {
|
||||
size_t size_needed = write_pos_ + len;
|
||||
Resize(size_needed);
|
||||
|
||||
memcpy(&buffer_[write_pos_], val, len);
|
||||
write_pos_ += len;
|
||||
}
|
||||
|
||||
void EQEmu::MemoryBuffer::Read(uchar *buf, size_t len) {
|
||||
memcpy(buf, &buffer_[read_pos_], len);
|
||||
read_pos_ += len;
|
||||
}
|
||||
|
||||
void EQEmu::MemoryBuffer::Read(char *str) {
|
||||
size_t len = strlen((const char*)&buffer_[read_pos_]);
|
||||
memcpy(str, &buffer_[read_pos_], len);
|
||||
read_pos_ += len;
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/* 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 COMMON_MEMORY_BUFFER_H
|
||||
#define COMMON_MEMORY_BUFFER_H
|
||||
|
||||
#include "types.h"
|
||||
#include <type_traits>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
|
||||
namespace EQEmu
|
||||
{
|
||||
class MemoryBuffer
|
||||
{
|
||||
public:
|
||||
MemoryBuffer();
|
||||
MemoryBuffer(size_t sz);
|
||||
MemoryBuffer(const MemoryBuffer &other);
|
||||
MemoryBuffer(MemoryBuffer &&other);
|
||||
MemoryBuffer& operator=(const MemoryBuffer &other);
|
||||
MemoryBuffer& operator=(MemoryBuffer &&other);
|
||||
MemoryBuffer& operator+=(const MemoryBuffer &rhs);
|
||||
friend MemoryBuffer operator+(MemoryBuffer lhs, const MemoryBuffer& rhs) { return lhs += rhs; }
|
||||
~MemoryBuffer();
|
||||
|
||||
uchar& operator[](size_t pos);
|
||||
const uchar& operator[](size_t pos) const;
|
||||
|
||||
template<typename T>
|
||||
operator T*() {
|
||||
return reinterpret_cast<T*>(buffer_);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
operator T*() const {
|
||||
return reinterpret_cast<T*>(buffer_);
|
||||
}
|
||||
|
||||
operator bool() { return buffer_ != nullptr; }
|
||||
operator bool() const { return buffer_ != nullptr; }
|
||||
|
||||
bool Empty();
|
||||
bool Empty() const;
|
||||
size_t Size();
|
||||
size_t Size() const;
|
||||
size_t Capacity();
|
||||
size_t Capacity() const;
|
||||
|
||||
void Resize(size_t sz);
|
||||
void Clear();
|
||||
void Zero();
|
||||
|
||||
template<typename T>
|
||||
void Write(T val) {
|
||||
static_assert(std::is_pod<T>::value, "MemoryBuffer::Write<T>(T val) only works on pod and string types.");
|
||||
Write((const char*)&val, sizeof(T));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T Read() {
|
||||
static_assert(std::is_pod<T>::value, "MemoryBuffer::Read<T>() only works on pod and string types.");
|
||||
T temp;
|
||||
Read((uchar*)&temp, sizeof(T));
|
||||
return temp;
|
||||
}
|
||||
|
||||
void Write(const std::string &val) {
|
||||
Write(val.c_str(), val.length());
|
||||
Write((uint8)0);
|
||||
}
|
||||
|
||||
void Write(const char *val) {
|
||||
size_t len = strlen(val);
|
||||
Write(val, len);
|
||||
Write((uint8)0);
|
||||
}
|
||||
|
||||
std::string ReadString() {
|
||||
std::string ret;
|
||||
size_t len = strlen((const char*)&buffer_[read_pos_]);
|
||||
ret.resize(len);
|
||||
memcpy(&ret[0], &buffer_[read_pos_], len);
|
||||
read_pos_ += len + 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Write(const char *val, size_t len);
|
||||
void Read(uchar *buf, size_t len);
|
||||
void Read(char *str);
|
||||
|
||||
inline size_t GetWritePosition() { return write_pos_; }
|
||||
inline void SetWritePosition(size_t wp) { write_pos_ = wp; }
|
||||
inline void WriteSkipBytes(size_t skip) { write_pos_ += skip; }
|
||||
inline size_t GetReadPosition() { return read_pos_; }
|
||||
inline void SetReadPosition(size_t wp) { read_pos_ = wp; }
|
||||
inline void ReadSkipBytes(size_t skip) { read_pos_ += skip; }
|
||||
|
||||
private:
|
||||
uchar *buffer_;
|
||||
size_t size_;
|
||||
size_t capacity_;
|
||||
size_t write_pos_;
|
||||
size_t read_pos_;
|
||||
};
|
||||
|
||||
} // EQEmu
|
||||
|
||||
#endif
|
||||
@@ -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
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -89,6 +90,54 @@ void DumpPacketHex(const uchar* buf, uint32 size, uint32 cols, uint32 skip) {
|
||||
safe_delete_array(ascii);
|
||||
}
|
||||
|
||||
std::string DumpPacketHexToString(const uchar* buf, uint32 size, uint32 cols, uint32 skip) {
|
||||
std::ostringstream out;
|
||||
if (size == 0 || size > 39565)
|
||||
return "";
|
||||
|
||||
out << "\n";
|
||||
|
||||
// Output as HEX
|
||||
char output[4];
|
||||
int j = 0;
|
||||
char* ascii = new char[cols + 1];
|
||||
memset(ascii, 0, cols + 1);
|
||||
uint32 i;
|
||||
for (i = skip; i < size; i++)
|
||||
{
|
||||
if ((i - skip) % cols == 0) {
|
||||
if (i != skip)
|
||||
out << " | " << ascii << std::endl;
|
||||
out << std::setw(4) << std::setfill(' ') << i - skip << ": ";
|
||||
memset(ascii, 0, cols + 1);
|
||||
j = 0;
|
||||
}
|
||||
else if ((i - skip) % (cols / 2) == 0) {
|
||||
out << "- ";
|
||||
}
|
||||
sprintf(output, "%02X ", (unsigned char)buf[i]);
|
||||
out << output;
|
||||
|
||||
if (buf[i] >= 32 && buf[i] < 127) {
|
||||
ascii[j++] = buf[i];
|
||||
}
|
||||
else {
|
||||
ascii[j++] = '.';
|
||||
}
|
||||
// std::cout << std::setfill(0) << std::setw(2) << std::hex << (int)buf[i] << " "; // unknown intent [CODEBUG]
|
||||
}
|
||||
uint32 k = ((i - skip) - 1) % cols;
|
||||
if (k < 8)
|
||||
out << " ";
|
||||
for (uint32 h = k + 1; h < cols; h++) {
|
||||
out << " ";
|
||||
}
|
||||
out << " | " << ascii << std::endl;
|
||||
safe_delete_array(ascii);
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
||||
void DumpPacket(const uchar* buf, uint32 size)
|
||||
{
|
||||
DumpPacketHex(buf, size);
|
||||
|
||||
@@ -24,6 +24,7 @@ class ServerPacket;
|
||||
|
||||
void DumpPacketAscii(const uchar* buf, uint32 size, uint32 cols=16, uint32 skip=0);
|
||||
void DumpPacketHex(const uchar* buf, uint32 size, uint32 cols=16, uint32 skip=0);
|
||||
std::string DumpPacketHexToString(const uchar* buf, uint32 size, uint32 cols = 16, uint32 skip = 0);
|
||||
void DumpPacketBin(const void* data, uint32 len);
|
||||
void DumpPacket(const uchar* buf, uint32 size);
|
||||
void DumpPacket(const ServerPacket* pack, bool iShowInfo = false);
|
||||
|
||||
+10
-10
@@ -10,19 +10,19 @@
|
||||
#include "rof2.h"
|
||||
|
||||
void RegisterAllPatches(EQStreamIdentifier &into) {
|
||||
Titanium::Register(into);
|
||||
SoF::Register(into);
|
||||
SoD::Register(into);
|
||||
UF::Register(into);
|
||||
RoF::Register(into);
|
||||
//Titanium::Register(into);
|
||||
//SoF::Register(into);
|
||||
//SoD::Register(into);
|
||||
//UF::Register(into);
|
||||
//RoF::Register(into);
|
||||
RoF2::Register(into);
|
||||
}
|
||||
|
||||
void ReloadAllPatches() {
|
||||
Titanium::Reload();
|
||||
SoF::Reload();
|
||||
SoD::Reload();
|
||||
UF::Reload();
|
||||
RoF::Reload();
|
||||
//Titanium::Reload();
|
||||
//SoF::Reload();
|
||||
//SoD::Reload();
|
||||
//UF::Reload();
|
||||
//RoF::Reload();
|
||||
RoF2::Reload();
|
||||
}
|
||||
|
||||
+348
-280
@@ -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);
|
||||
@@ -530,71 +532,72 @@ namespace RoF
|
||||
{
|
||||
//consume the packet
|
||||
EQApplicationPacket *in = *p;
|
||||
delete in;
|
||||
|
||||
*p = nullptr;
|
||||
|
||||
if (in->size == 0) {
|
||||
|
||||
in->size = 4;
|
||||
in->pBuffer = new uchar[in->size];
|
||||
|
||||
*((uint32 *)in->pBuffer) = 0;
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
return;
|
||||
}
|
||||
|
||||
//store away the emu struct
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
|
||||
|
||||
if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
|
||||
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
|
||||
opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
|
||||
|
||||
delete in;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
|
||||
|
||||
in->pBuffer = new uchar[4];
|
||||
*(uint32 *)in->pBuffer = ItemCount;
|
||||
in->size = 4;
|
||||
|
||||
for (int r = 0; r < ItemCount; r++, eq++) {
|
||||
|
||||
uint32 Length = 0;
|
||||
|
||||
char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
|
||||
|
||||
if (Serialized) {
|
||||
|
||||
uchar *OldBuffer = in->pBuffer;
|
||||
in->pBuffer = new uchar[in->size + Length];
|
||||
memcpy(in->pBuffer, OldBuffer, in->size);
|
||||
|
||||
safe_delete_array(OldBuffer);
|
||||
|
||||
memcpy(in->pBuffer + in->size, Serialized, Length);
|
||||
in->size += Length;
|
||||
|
||||
safe_delete_array(Serialized);
|
||||
}
|
||||
else {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] __emu_buffer;
|
||||
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
|
||||
//Log.Hex(Logs::Netcode, in->pBuffer, in->size);
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
//*p = nullptr;
|
||||
//
|
||||
//if (in->size == 0) {
|
||||
//
|
||||
// in->size = 4;
|
||||
// in->pBuffer = new uchar[in->size];
|
||||
//
|
||||
// *((uint32 *)in->pBuffer) = 0;
|
||||
//
|
||||
// dest->FastQueuePacket(&in, ack_req);
|
||||
// return;
|
||||
//}
|
||||
//
|
||||
////store away the emu struct
|
||||
//unsigned char *__emu_buffer = in->pBuffer;
|
||||
//
|
||||
//int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
|
||||
//
|
||||
//if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
|
||||
//
|
||||
// Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
|
||||
// opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
|
||||
//
|
||||
// delete in;
|
||||
//
|
||||
// return;
|
||||
//}
|
||||
//
|
||||
//InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
|
||||
//
|
||||
//in->pBuffer = new uchar[4];
|
||||
//*(uint32 *)in->pBuffer = ItemCount;
|
||||
//in->size = 4;
|
||||
//
|
||||
//for (int r = 0; r < ItemCount; r++, eq++) {
|
||||
//
|
||||
// uint32 Length = 0;
|
||||
//
|
||||
// char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
|
||||
//
|
||||
// if (Serialized) {
|
||||
//
|
||||
// uchar *OldBuffer = in->pBuffer;
|
||||
// in->pBuffer = new uchar[in->size + Length];
|
||||
// memcpy(in->pBuffer, OldBuffer, in->size);
|
||||
//
|
||||
// safe_delete_array(OldBuffer);
|
||||
//
|
||||
// memcpy(in->pBuffer + in->size, Serialized, Length);
|
||||
// in->size += Length;
|
||||
//
|
||||
// safe_delete_array(Serialized);
|
||||
// }
|
||||
// else {
|
||||
// Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//delete[] __emu_buffer;
|
||||
//
|
||||
////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
|
||||
////Log.Hex(Logs::Netcode, in->pBuffer, in->size);
|
||||
//
|
||||
//dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_ClickObjectAction)
|
||||
@@ -656,7 +659,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 +705,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 +976,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 +1252,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
|
||||
}
|
||||
|
||||
@@ -1704,14 +1709,14 @@ namespace RoF
|
||||
|
||||
ENCODE(OP_MoveItem)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(MoveItem_Struct);
|
||||
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
|
||||
eq->from_slot = ServerToRoFSlot(emu->from_slot);
|
||||
eq->to_slot = ServerToRoFSlot(emu->to_slot);
|
||||
OUT(number_in_stack);
|
||||
|
||||
FINISH_ENCODE();
|
||||
//ENCODE_LENGTH_EXACT(MoveItem_Struct);
|
||||
//SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
//
|
||||
//eq->from_slot = ServerToRoFSlot(emu->from_slot);
|
||||
//eq->to_slot = ServerToRoFSlot(emu->to_slot);
|
||||
//OUT(number_in_stack);
|
||||
//
|
||||
//FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
|
||||
@@ -2043,7 +2048,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 +2058,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 +2121,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 +2291,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 +2429,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 +2819,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 +2853,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 +2869,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 +2887,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 +2903,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 +3051,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; }
|
||||
}
|
||||
|
||||
@@ -3039,13 +3066,13 @@ namespace RoF
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(Merchant_Sell_Struct);
|
||||
SETUP_DIRECT_ENCODE(Merchant_Sell_Struct, structs::Merchant_Sell_Struct);
|
||||
|
||||
|
||||
OUT(npcid);
|
||||
OUT(playerid);
|
||||
OUT(itemslot);
|
||||
OUT(quantity);
|
||||
OUT(price);
|
||||
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
@@ -3291,7 +3318,7 @@ namespace RoF
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
|
||||
|
||||
#if 0 // original code
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
@@ -3588,37 +3615,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 +3694,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 +3782,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 +3849,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 +3973,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 +3993,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 +4005,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 +4029,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 +4123,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 +4247,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 +4394,7 @@ namespace RoF
|
||||
IN(type);
|
||||
IN(spellid);
|
||||
IN(damage);
|
||||
emu->sequence = eq->sequence;
|
||||
IN(meleepush_xy);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@@ -4646,16 +4704,16 @@ namespace RoF
|
||||
|
||||
DECODE(OP_MoveItem)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
|
||||
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Moved item from %u to %u", eq->from_slot.MainSlot, eq->to_slot.MainSlot);
|
||||
Log.Out(Logs::General, Logs::Netcode, "[RoF] MoveItem SlotType from %i to %i, MainSlot from %i to %i, SubSlot from %i to %i, AugSlot from %i to %i, Unknown01 from %i to %i, Number %u", eq->from_slot.SlotType, eq->to_slot.SlotType, eq->from_slot.MainSlot, eq->to_slot.MainSlot, eq->from_slot.SubSlot, eq->to_slot.SubSlot, eq->from_slot.AugSlot, eq->to_slot.AugSlot, eq->from_slot.Unknown01, eq->to_slot.Unknown01, eq->number_in_stack);
|
||||
emu->from_slot = RoFToServerSlot(eq->from_slot);
|
||||
emu->to_slot = RoFToServerSlot(eq->to_slot);
|
||||
IN(number_in_stack);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
//DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
|
||||
//SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
//
|
||||
////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Moved item from %u to %u", eq->from_slot.MainSlot, eq->to_slot.MainSlot);
|
||||
//Log.Out(Logs::General, Logs::Netcode, "[RoF] MoveItem SlotType from %i to %i, MainSlot from %i to %i, SubSlot from %i to %i, AugSlot from %i to %i, Unknown01 from %i to %i, Number %u", eq->from_slot.SlotType, eq->to_slot.SlotType, eq->from_slot.MainSlot, eq->to_slot.MainSlot, eq->from_slot.SubSlot, eq->to_slot.SubSlot, eq->from_slot.AugSlot, eq->to_slot.AugSlot, eq->from_slot.Unknown01, eq->to_slot.Unknown01, eq->number_in_stack);
|
||||
//emu->from_slot = RoFToServerSlot(eq->from_slot);
|
||||
//emu->to_slot = RoFToServerSlot(eq->to_slot);
|
||||
//IN(number_in_stack);
|
||||
//
|
||||
//FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_PetCommands)
|
||||
@@ -4664,7 +4722,7 @@ namespace RoF
|
||||
SETUP_DIRECT_DECODE(PetCommand_Struct, structs::PetCommand_Struct);
|
||||
|
||||
IN(command);
|
||||
emu->unknown = eq->unknown04;
|
||||
IN(target);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@@ -4783,13 +4841,13 @@ namespace RoF
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::Merchant_Sell_Struct);
|
||||
SETUP_DIRECT_DECODE(Merchant_Sell_Struct, structs::Merchant_Sell_Struct);
|
||||
|
||||
|
||||
IN(npcid);
|
||||
IN(playerid);
|
||||
IN(itemslot);
|
||||
IN(quantity);
|
||||
IN(price);
|
||||
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
@@ -4888,7 +4946,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 +4981,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);
|
||||
@@ -4976,14 +5044,14 @@ namespace RoF
|
||||
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
||||
|
||||
const Item_Struct *item = inst->GetUnscaledItem();
|
||||
const ItemData *item = inst->GetUnscaledItem();
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name);
|
||||
|
||||
RoF::structs::ItemSerializationHeader hdr;
|
||||
|
||||
//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;
|
||||
@@ -5035,7 +5103,7 @@ namespace RoF
|
||||
ss.write(tmp, strlen(tmp));
|
||||
ss.write((const char*)&null_term, sizeof(uint8));
|
||||
ornaIcon = inst->GetOrnamentationIcon();
|
||||
heroModel = inst->GetOrnamentHeroModel(Inventory::CalcMaterialFromSlot(slot_id_in));
|
||||
heroModel = inst->GetOrnamentHeroModel(InventoryOld::CalcMaterialFromSlot(slot_id_in));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -5054,7 +5122,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));
|
||||
@@ -5478,7 +5546,7 @@ namespace RoF
|
||||
|
||||
/*
|
||||
// TEST CODE: <watch>
|
||||
SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x);
|
||||
SubSlotNumber = InventoryOld::CalcSlotID(slot_id_in, x);
|
||||
*/
|
||||
|
||||
SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1);
|
||||
|
||||
+595
-463
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)
|
||||
|
||||
+252
-182
@@ -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 */
|
||||
};
|
||||
|
||||
@@ -2280,7 +2310,7 @@ struct AdventureLeaderboard_Struct
|
||||
/*struct Item_Shop_Struct {
|
||||
uint16 merchantid;
|
||||
uint8 itemtype;
|
||||
Item_Struct item;
|
||||
ItemData item;
|
||||
uint8 iss_unknown001[6];
|
||||
};*/
|
||||
|
||||
@@ -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 {
|
||||
@@ -2865,7 +2895,7 @@ struct SetRunMode_Struct {
|
||||
};
|
||||
|
||||
// EnvDamage is EnvDamage2 without a few bytes at the end.
|
||||
// Size: 37 bytes
|
||||
// Size: 39 bytes
|
||||
struct EnvDamage2_Struct {
|
||||
/*0000*/ uint32 id;
|
||||
/*0004*/ uint16 unknown4;
|
||||
@@ -2877,7 +2907,8 @@ struct EnvDamage2_Struct {
|
||||
/*0031*/ uint16 unknown31; // New to Underfoot - Seen 66
|
||||
/*0033*/ uint16 constant; // Always FFFF
|
||||
/*0035*/ uint16 unknown35;
|
||||
/*0037*/
|
||||
/*0037*/ uint16 unknown37;
|
||||
/*0039*/
|
||||
};
|
||||
|
||||
//Bazaar Stuff
|
||||
@@ -2913,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 {
|
||||
@@ -3199,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;
|
||||
@@ -3216,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;
|
||||
@@ -3245,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{
|
||||
@@ -3566,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*/
|
||||
};
|
||||
|
||||
@@ -4087,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 {
|
||||
@@ -4131,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*/
|
||||
};
|
||||
@@ -4192,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;
|
||||
@@ -4207,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];
|
||||
};
|
||||
@@ -4227,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
|
||||
@@ -4252,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 {
|
||||
@@ -4269,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 {
|
||||
@@ -4352,7 +4406,7 @@ struct RoF2SlotStruct
|
||||
|
||||
struct ItemSerializationHeader
|
||||
{
|
||||
/*000*/ char unknown000[13]; // New for HoT. Looks like a string.
|
||||
/*000*/ char tracking_id[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 = ?
|
||||
@@ -4497,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];
|
||||
@@ -4672,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)
|
||||
|
||||
+201
-159
@@ -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 */
|
||||
};
|
||||
|
||||
@@ -2309,7 +2338,7 @@ struct AdventureLeaderboard_Struct
|
||||
/*struct Item_Shop_Struct {
|
||||
uint16 merchantid;
|
||||
uint8 itemtype;
|
||||
Item_Struct item;
|
||||
ItemData item;
|
||||
uint8 iss_unknown001[6];
|
||||
};*/
|
||||
|
||||
@@ -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
|
||||
|
||||
+232
-206
@@ -336,71 +336,72 @@ namespace SoD
|
||||
{
|
||||
//consume the packet
|
||||
EQApplicationPacket *in = *p;
|
||||
delete in;
|
||||
|
||||
*p = nullptr;
|
||||
|
||||
if (in->size == 0) {
|
||||
|
||||
in->size = 4;
|
||||
|
||||
in->pBuffer = new uchar[in->size];
|
||||
|
||||
*((uint32 *)in->pBuffer) = 0;
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//store away the emu struct
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
|
||||
|
||||
if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
|
||||
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
|
||||
opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
|
||||
|
||||
delete in;
|
||||
return;
|
||||
}
|
||||
|
||||
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
|
||||
in->pBuffer = new uchar[4];
|
||||
*(uint32 *)in->pBuffer = ItemCount;
|
||||
in->size = 4;
|
||||
|
||||
for (int r = 0; r < ItemCount; r++, eq++) {
|
||||
|
||||
uint32 Length = 0;
|
||||
char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
|
||||
|
||||
if (Serialized) {
|
||||
|
||||
uchar *OldBuffer = in->pBuffer;
|
||||
in->pBuffer = new uchar[in->size + Length];
|
||||
memcpy(in->pBuffer, OldBuffer, in->size);
|
||||
|
||||
safe_delete_array(OldBuffer);
|
||||
|
||||
memcpy(in->pBuffer + in->size, Serialized, Length);
|
||||
in->size += Length;
|
||||
|
||||
safe_delete_array(Serialized);
|
||||
|
||||
}
|
||||
else {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] __emu_buffer;
|
||||
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
|
||||
//Log.Hex(Logs::Netcode, in->pBuffer, in->size);
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
//*p = nullptr;
|
||||
//
|
||||
//if (in->size == 0) {
|
||||
//
|
||||
// in->size = 4;
|
||||
//
|
||||
// in->pBuffer = new uchar[in->size];
|
||||
//
|
||||
// *((uint32 *)in->pBuffer) = 0;
|
||||
//
|
||||
// dest->FastQueuePacket(&in, ack_req);
|
||||
//
|
||||
// return;
|
||||
//}
|
||||
//
|
||||
////store away the emu struct
|
||||
//unsigned char *__emu_buffer = in->pBuffer;
|
||||
//
|
||||
//int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
|
||||
//
|
||||
//if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
|
||||
//
|
||||
// Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
|
||||
// opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
|
||||
//
|
||||
// delete in;
|
||||
// return;
|
||||
//}
|
||||
//
|
||||
//InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
|
||||
//in->pBuffer = new uchar[4];
|
||||
//*(uint32 *)in->pBuffer = ItemCount;
|
||||
//in->size = 4;
|
||||
//
|
||||
//for (int r = 0; r < ItemCount; r++, eq++) {
|
||||
//
|
||||
// uint32 Length = 0;
|
||||
// char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
|
||||
//
|
||||
// if (Serialized) {
|
||||
//
|
||||
// uchar *OldBuffer = in->pBuffer;
|
||||
// in->pBuffer = new uchar[in->size + Length];
|
||||
// memcpy(in->pBuffer, OldBuffer, in->size);
|
||||
//
|
||||
// safe_delete_array(OldBuffer);
|
||||
//
|
||||
// memcpy(in->pBuffer + in->size, Serialized, Length);
|
||||
// in->size += Length;
|
||||
//
|
||||
// safe_delete_array(Serialized);
|
||||
//
|
||||
// }
|
||||
// else {
|
||||
// Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//delete[] __emu_buffer;
|
||||
//
|
||||
////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
|
||||
////Log.Hex(Logs::Netcode, in->pBuffer, in->size);
|
||||
//
|
||||
//dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_ClientUpdate)
|
||||
@@ -446,7 +447,9 @@ namespace SoD
|
||||
OUT(type);
|
||||
OUT(spellid);
|
||||
OUT(damage);
|
||||
eq->sequence = emu->sequence;
|
||||
OUT(force)
|
||||
OUT(meleepush_xy);
|
||||
OUT(meleepush_z)
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@@ -1264,14 +1267,14 @@ namespace SoD
|
||||
|
||||
ENCODE(OP_MoveItem)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(MoveItem_Struct);
|
||||
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
|
||||
eq->from_slot = ServerToSoDSlot(emu->from_slot);
|
||||
eq->to_slot = ServerToSoDSlot(emu->to_slot);
|
||||
OUT(number_in_stack);
|
||||
|
||||
FINISH_ENCODE();
|
||||
//ENCODE_LENGTH_EXACT(MoveItem_Struct);
|
||||
//SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
//
|
||||
//eq->from_slot = ServerToSoDSlot(emu->from_slot);
|
||||
//eq->to_slot = ServerToSoDSlot(emu->to_slot);
|
||||
//OUT(number_in_stack);
|
||||
//
|
||||
//FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
|
||||
@@ -1542,13 +1545,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 +1559,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 +1610,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 +1900,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 +1916,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 +2400,7 @@ namespace SoD
|
||||
OUT(material);
|
||||
OUT(unknown06);
|
||||
OUT(elite_material);
|
||||
OUT(color.color);
|
||||
OUT(color.Color);
|
||||
OUT(wear_slot_id);
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -2427,42 +2472,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 +2741,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 +2768,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 +2778,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 +2793,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);
|
||||
@@ -3239,16 +3265,16 @@ namespace SoD
|
||||
|
||||
DECODE(OP_MoveItem)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
|
||||
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
|
||||
Log.Out(Logs::General, Logs::Netcode, "[SoD] Moved item from %u to %u", eq->from_slot, eq->to_slot);
|
||||
|
||||
emu->from_slot = SoDToServerSlot(eq->from_slot);
|
||||
emu->to_slot = SoDToServerSlot(eq->to_slot);
|
||||
IN(number_in_stack);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
//DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
|
||||
//SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
//
|
||||
//Log.Out(Logs::General, Logs::Netcode, "[SoD] Moved item from %u to %u", eq->from_slot, eq->to_slot);
|
||||
//
|
||||
//emu->from_slot = SoDToServerSlot(eq->from_slot);
|
||||
//emu->to_slot = SoDToServerSlot(eq->to_slot);
|
||||
//IN(number_in_stack);
|
||||
//
|
||||
//FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_PetCommands)
|
||||
@@ -3329,7 +3355,7 @@ namespace SoD
|
||||
default:
|
||||
emu->command = eq->command;
|
||||
}
|
||||
OUT(unknown);
|
||||
IN(target);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@@ -3484,7 +3510,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;
|
||||
@@ -3534,7 +3560,7 @@ namespace SoD
|
||||
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
||||
|
||||
const Item_Struct *item = inst->GetUnscaledItem();
|
||||
const ItemData *item = inst->GetUnscaledItem();
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name);
|
||||
SoD::structs::ItemSerializationHeader hdr;
|
||||
hdr.stacksize = stackable ? charges : 1;
|
||||
@@ -3932,7 +3958,7 @@ namespace SoD
|
||||
|
||||
/*
|
||||
// TEST CODE: <watch>
|
||||
SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x);
|
||||
SubSlotNumber = InventoryOld::CalcSlotID(slot_id_in, x);
|
||||
*/
|
||||
|
||||
SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+133
-113
@@ -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 */
|
||||
};
|
||||
|
||||
@@ -1958,7 +1973,7 @@ struct AdventureLeaderboard_Struct
|
||||
/*struct Item_Shop_Struct {
|
||||
uint16 merchantid;
|
||||
uint8 itemtype;
|
||||
Item_Struct item;
|
||||
ItemData item;
|
||||
uint8 iss_unknown001[6];
|
||||
};*/
|
||||
|
||||
@@ -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 {
|
||||
|
||||
+229
-202
@@ -318,69 +318,70 @@ namespace SoF
|
||||
{
|
||||
//consume the packet
|
||||
EQApplicationPacket *in = *p;
|
||||
delete in;
|
||||
|
||||
*p = nullptr;
|
||||
|
||||
if (in->size == 0) {
|
||||
in->size = 4;
|
||||
in->pBuffer = new uchar[in->size];
|
||||
*((uint32 *)in->pBuffer) = 0;
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
return;
|
||||
}
|
||||
|
||||
//store away the emu struct
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
|
||||
|
||||
if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
|
||||
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
|
||||
opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
|
||||
|
||||
delete in;
|
||||
return;
|
||||
}
|
||||
|
||||
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
|
||||
|
||||
in->pBuffer = new uchar[4];
|
||||
*(uint32 *)in->pBuffer = ItemCount;
|
||||
in->size = 4;
|
||||
|
||||
for (int r = 0; r < ItemCount; r++, eq++) {
|
||||
|
||||
uint32 Length = 0;
|
||||
|
||||
char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
|
||||
|
||||
if (Serialized) {
|
||||
uchar *OldBuffer = in->pBuffer;
|
||||
|
||||
in->pBuffer = new uchar[in->size + Length];
|
||||
memcpy(in->pBuffer, OldBuffer, in->size);
|
||||
|
||||
safe_delete_array(OldBuffer);
|
||||
|
||||
memcpy(in->pBuffer + in->size, Serialized, Length);
|
||||
in->size += Length;
|
||||
|
||||
safe_delete_array(Serialized);
|
||||
|
||||
}
|
||||
else {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] __emu_buffer;
|
||||
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
|
||||
//Log.Hex(Logs::Netcode, in->pBuffer, in->size);
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
//*p = nullptr;
|
||||
//
|
||||
//if (in->size == 0) {
|
||||
// in->size = 4;
|
||||
// in->pBuffer = new uchar[in->size];
|
||||
// *((uint32 *)in->pBuffer) = 0;
|
||||
//
|
||||
// dest->FastQueuePacket(&in, ack_req);
|
||||
// return;
|
||||
//}
|
||||
//
|
||||
////store away the emu struct
|
||||
//unsigned char *__emu_buffer = in->pBuffer;
|
||||
//
|
||||
//int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
|
||||
//
|
||||
//if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
|
||||
//
|
||||
// Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
|
||||
// opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
|
||||
//
|
||||
// delete in;
|
||||
// return;
|
||||
//}
|
||||
//
|
||||
//InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
|
||||
//
|
||||
//in->pBuffer = new uchar[4];
|
||||
//*(uint32 *)in->pBuffer = ItemCount;
|
||||
//in->size = 4;
|
||||
//
|
||||
//for (int r = 0; r < ItemCount; r++, eq++) {
|
||||
//
|
||||
// uint32 Length = 0;
|
||||
//
|
||||
// char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
|
||||
//
|
||||
// if (Serialized) {
|
||||
// uchar *OldBuffer = in->pBuffer;
|
||||
//
|
||||
// in->pBuffer = new uchar[in->size + Length];
|
||||
// memcpy(in->pBuffer, OldBuffer, in->size);
|
||||
//
|
||||
// safe_delete_array(OldBuffer);
|
||||
//
|
||||
// memcpy(in->pBuffer + in->size, Serialized, Length);
|
||||
// in->size += Length;
|
||||
//
|
||||
// safe_delete_array(Serialized);
|
||||
//
|
||||
// }
|
||||
// else {
|
||||
// Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//delete[] __emu_buffer;
|
||||
//
|
||||
////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
|
||||
////Log.Hex(Logs::Netcode, in->pBuffer, in->size);
|
||||
//
|
||||
//dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_ClientUpdate)
|
||||
@@ -426,7 +427,9 @@ namespace SoF
|
||||
OUT(type);
|
||||
OUT(spellid);
|
||||
OUT(damage);
|
||||
eq->sequence = emu->sequence;
|
||||
OUT(force)
|
||||
OUT(meleepush_xy);
|
||||
OUT(meleepush_z)
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@@ -929,14 +932,14 @@ namespace SoF
|
||||
|
||||
ENCODE(OP_MoveItem)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(MoveItem_Struct);
|
||||
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
|
||||
eq->from_slot = ServerToSoFSlot(emu->from_slot);
|
||||
eq->to_slot = ServerToSoFSlot(emu->to_slot);
|
||||
OUT(number_in_stack);
|
||||
|
||||
FINISH_ENCODE();
|
||||
//ENCODE_LENGTH_EXACT(MoveItem_Struct);
|
||||
//SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
//
|
||||
//eq->from_slot = ServerToSoFSlot(emu->from_slot);
|
||||
//eq->to_slot = ServerToSoFSlot(emu->to_slot);
|
||||
//OUT(number_in_stack);
|
||||
//
|
||||
//FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
|
||||
@@ -1200,13 +1203,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 +1217,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 +1268,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 +1559,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 +1575,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 +1986,7 @@ namespace SoF
|
||||
OUT(material);
|
||||
OUT(unknown06);
|
||||
OUT(elite_material);
|
||||
OUT(color.color);
|
||||
OUT(color.Color);
|
||||
OUT(wear_slot_id);
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -1951,42 +1996,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 +2070,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 +2092,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 +2136,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;
|
||||
@@ -2577,16 +2604,16 @@ namespace SoF
|
||||
|
||||
DECODE(OP_MoveItem)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
|
||||
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
|
||||
Log.Out(Logs::General, Logs::Netcode, "[SoF] Moved item from %u to %u", eq->from_slot, eq->to_slot);
|
||||
|
||||
emu->from_slot = SoFToServerSlot(eq->from_slot);
|
||||
emu->to_slot = SoFToServerSlot(eq->to_slot);
|
||||
IN(number_in_stack);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
//DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
|
||||
//SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
//
|
||||
//Log.Out(Logs::General, Logs::Netcode, "[SoF] Moved item from %u to %u", eq->from_slot, eq->to_slot);
|
||||
//
|
||||
//emu->from_slot = SoFToServerSlot(eq->from_slot);
|
||||
//emu->to_slot = SoFToServerSlot(eq->to_slot);
|
||||
//IN(number_in_stack);
|
||||
//
|
||||
//FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_PetCommands)
|
||||
@@ -2667,7 +2694,7 @@ namespace SoF
|
||||
default:
|
||||
emu->command = eq->command;
|
||||
}
|
||||
OUT(unknown);
|
||||
IN(target);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@@ -2808,7 +2835,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;
|
||||
@@ -2858,7 +2885,7 @@ namespace SoF
|
||||
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
||||
|
||||
const Item_Struct *item = inst->GetUnscaledItem();
|
||||
const ItemData *item = inst->GetUnscaledItem();
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name);
|
||||
SoF::structs::ItemSerializationHeader hdr;
|
||||
hdr.stacksize = stackable ? charges : 1;
|
||||
@@ -3254,7 +3281,7 @@ namespace SoF
|
||||
|
||||
/*
|
||||
// TEST CODE: <watch>
|
||||
SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x);
|
||||
SubSlotNumber = InventoryOld::CalcSlotID(slot_id_in, x);
|
||||
*/
|
||||
|
||||
SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+131
-111
@@ -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 */
|
||||
};
|
||||
|
||||
@@ -1931,7 +1948,7 @@ struct AdventureLeaderboard_Struct
|
||||
/*struct Item_Shop_Struct {
|
||||
uint16 merchantid;
|
||||
uint8 itemtype;
|
||||
Item_Struct item;
|
||||
ItemData item;
|
||||
uint8 iss_unknown001[6];
|
||||
};*/
|
||||
|
||||
@@ -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; \
|
||||
}
|
||||
|
||||
|
||||
+195
-112
@@ -122,7 +122,7 @@ namespace Titanium
|
||||
EAT_ENCODE(OP_GuildMemberLevelUpdate); // added ;
|
||||
|
||||
EAT_ENCODE(OP_ZoneServerReady); // added ;
|
||||
|
||||
|
||||
ENCODE(OP_Action)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(Action_Struct);
|
||||
@@ -263,40 +263,42 @@ namespace Titanium
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
//store away the emu struct
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
delete in;
|
||||
|
||||
int itemcount = in->size / sizeof(InternalSerializedItem_Struct);
|
||||
if (itemcount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
|
||||
delete in;
|
||||
return;
|
||||
}
|
||||
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
|
||||
|
||||
//do the transform...
|
||||
int r;
|
||||
std::string serial_string;
|
||||
for (r = 0; r < itemcount; r++, eq++) {
|
||||
uint32 length;
|
||||
char *serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &length, 0);
|
||||
if (serialized) {
|
||||
serial_string.append(serialized, length + 1);
|
||||
safe_delete_array(serialized);
|
||||
}
|
||||
else {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
in->size = serial_string.length();
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
memcpy(in->pBuffer, serial_string.c_str(), serial_string.length());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
////store away the emu struct
|
||||
//unsigned char *__emu_buffer = in->pBuffer;
|
||||
//
|
||||
//int itemcount = in->size / sizeof(InternalSerializedItem_Struct);
|
||||
//if (itemcount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
|
||||
// Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
|
||||
// delete in;
|
||||
// return;
|
||||
//}
|
||||
//InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
|
||||
//
|
||||
////do the transform...
|
||||
//int r;
|
||||
//std::string serial_string;
|
||||
//for (r = 0; r < itemcount; r++, eq++) {
|
||||
// uint32 length;
|
||||
// char *serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &length, 0);
|
||||
// if (serialized) {
|
||||
// serial_string.append(serialized, length + 1);
|
||||
// safe_delete_array(serialized);
|
||||
// }
|
||||
// else {
|
||||
// Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
// }
|
||||
//
|
||||
//}
|
||||
//
|
||||
//in->size = serial_string.length();
|
||||
//in->pBuffer = new unsigned char[in->size];
|
||||
//memcpy(in->pBuffer, serial_string.c_str(), serial_string.length());
|
||||
//
|
||||
//delete[] __emu_buffer;
|
||||
//
|
||||
//dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_DeleteCharge) { ENCODE_FORWARD(OP_MoveItem); }
|
||||
@@ -326,7 +328,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)
|
||||
@@ -776,14 +778,14 @@ namespace Titanium
|
||||
|
||||
ENCODE(OP_MoveItem)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(MoveItem_Struct);
|
||||
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
|
||||
eq->from_slot = ServerToTitaniumSlot(emu->from_slot);
|
||||
eq->to_slot = ServerToTitaniumSlot(emu->to_slot);
|
||||
OUT(number_in_stack);
|
||||
|
||||
FINISH_ENCODE();
|
||||
//ENCODE_LENGTH_EXACT(MoveItem_Struct);
|
||||
//SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
//
|
||||
//eq->from_slot = ServerToTitaniumSlot(emu->from_slot);
|
||||
//eq->to_slot = ServerToTitaniumSlot(emu->to_slot);
|
||||
//OUT(number_in_stack);
|
||||
//
|
||||
//FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
|
||||
@@ -865,7 +867,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 +924,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 +1072,7 @@ namespace Titanium
|
||||
|
||||
ENCODE(OP_ReadBook)
|
||||
{
|
||||
// no apparent slot translation needed -U
|
||||
// no apparent slot translation needed
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
@@ -1076,8 +1100,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 +1157,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 +1310,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 +1353,7 @@ namespace Titanium
|
||||
InBuffer += strlen(InBuffer) + 1;
|
||||
|
||||
memcpy(OutBuffer, InBuffer, sizeof(TaskDescriptionTrailer_Struct));
|
||||
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
@@ -1383,7 +1466,7 @@ namespace Titanium
|
||||
|
||||
OUT(spawn_id);
|
||||
OUT(material);
|
||||
OUT(color.color);
|
||||
OUT(color.Color);
|
||||
OUT(wear_slot_id);
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -1468,15 +1551,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 +1623,7 @@ namespace Titanium
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
|
||||
DECODE(OP_ApplyPoison)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::ApplyPoison_Struct);
|
||||
@@ -1771,16 +1854,16 @@ namespace Titanium
|
||||
|
||||
DECODE(OP_MoveItem)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
|
||||
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
|
||||
Log.Out(Logs::General, Logs::Netcode, "[Titanium] Moved item from %u to %u", eq->from_slot, eq->to_slot);
|
||||
|
||||
emu->from_slot = TitaniumToServerSlot(eq->from_slot);
|
||||
emu->to_slot = TitaniumToServerSlot(eq->to_slot);
|
||||
IN(number_in_stack);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
//DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
|
||||
//SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
//
|
||||
//Log.Out(Logs::General, Logs::Netcode, "[Titanium] Moved item from %u to %u", eq->from_slot, eq->to_slot);
|
||||
//
|
||||
//emu->from_slot = TitaniumToServerSlot(eq->from_slot);
|
||||
//emu->to_slot = TitaniumToServerSlot(eq->to_slot);
|
||||
//IN(number_in_stack);
|
||||
//
|
||||
//FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_PetCommands)
|
||||
@@ -1861,14 +1944,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 +2035,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;
|
||||
@@ -1989,7 +2072,7 @@ namespace Titanium
|
||||
int16 slot_id = ServerToTitaniumSlot(slot_id_in);
|
||||
uint32 merchant_slot = inst->GetMerchantSlot();
|
||||
int16 charges = inst->GetCharges();
|
||||
const Item_Struct *item = inst->GetUnscaledItem();
|
||||
const ItemData *item = inst->GetUnscaledItem();
|
||||
int i;
|
||||
uint32 sub_length;
|
||||
|
||||
@@ -2070,7 +2153,7 @@ namespace Titanium
|
||||
|
||||
return serverSlot; // deprecated
|
||||
}
|
||||
|
||||
|
||||
static inline int16 ServerToTitaniumCorpseSlot(uint32 serverCorpseSlot)
|
||||
{
|
||||
//int16 TitaniumCorpse;
|
||||
@@ -2085,7 +2168,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 */
|
||||
};
|
||||
|
||||
@@ -1687,7 +1700,7 @@ struct AdventureRequestResponse_Struct{
|
||||
/*struct Item_Shop_Struct {
|
||||
uint16 merchantid;
|
||||
uint8 itemtype;
|
||||
Item_Struct item;
|
||||
ItemData item;
|
||||
uint8 iss_unknown001[6];
|
||||
};*/
|
||||
|
||||
@@ -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 {
|
||||
|
||||
+246
-213
@@ -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();
|
||||
/*
|
||||
@@ -474,68 +474,69 @@ namespace UF
|
||||
{
|
||||
//consume the packet
|
||||
EQApplicationPacket *in = *p;
|
||||
|
||||
*p = nullptr;
|
||||
|
||||
if (in->size == 0) {
|
||||
|
||||
in->size = 4;
|
||||
in->pBuffer = new uchar[in->size];
|
||||
*((uint32 *)in->pBuffer) = 0;
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
return;
|
||||
}
|
||||
|
||||
//store away the emu struct
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
|
||||
|
||||
if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
|
||||
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
|
||||
opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
|
||||
|
||||
delete in;
|
||||
return;
|
||||
}
|
||||
|
||||
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
|
||||
|
||||
in->pBuffer = new uchar[4];
|
||||
*(uint32 *)in->pBuffer = ItemCount;
|
||||
in->size = 4;
|
||||
|
||||
for (int r = 0; r < ItemCount; r++, eq++) {
|
||||
|
||||
uint32 Length = 0;
|
||||
char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
|
||||
|
||||
if (Serialized) {
|
||||
|
||||
uchar *OldBuffer = in->pBuffer;
|
||||
in->pBuffer = new uchar[in->size + Length];
|
||||
memcpy(in->pBuffer, OldBuffer, in->size);
|
||||
|
||||
safe_delete_array(OldBuffer);
|
||||
|
||||
memcpy(in->pBuffer + in->size, Serialized, Length);
|
||||
in->size += Length;
|
||||
|
||||
safe_delete_array(Serialized);
|
||||
}
|
||||
else {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] __emu_buffer;
|
||||
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
|
||||
//Log.Hex(Logs::Netcode, in->pBuffer, in->size);
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
delete in;
|
||||
|
||||
//*p = nullptr;
|
||||
//
|
||||
//if (in->size == 0) {
|
||||
//
|
||||
// in->size = 4;
|
||||
// in->pBuffer = new uchar[in->size];
|
||||
// *((uint32 *)in->pBuffer) = 0;
|
||||
//
|
||||
// dest->FastQueuePacket(&in, ack_req);
|
||||
// return;
|
||||
//}
|
||||
//
|
||||
////store away the emu struct
|
||||
//unsigned char *__emu_buffer = in->pBuffer;
|
||||
//
|
||||
//int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
|
||||
//
|
||||
//if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
|
||||
//
|
||||
// Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
|
||||
// opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
|
||||
//
|
||||
// delete in;
|
||||
// return;
|
||||
//}
|
||||
//
|
||||
//InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
|
||||
//
|
||||
//in->pBuffer = new uchar[4];
|
||||
//*(uint32 *)in->pBuffer = ItemCount;
|
||||
//in->size = 4;
|
||||
//
|
||||
//for (int r = 0; r < ItemCount; r++, eq++) {
|
||||
//
|
||||
// uint32 Length = 0;
|
||||
// char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
|
||||
//
|
||||
// if (Serialized) {
|
||||
//
|
||||
// uchar *OldBuffer = in->pBuffer;
|
||||
// in->pBuffer = new uchar[in->size + Length];
|
||||
// memcpy(in->pBuffer, OldBuffer, in->size);
|
||||
//
|
||||
// safe_delete_array(OldBuffer);
|
||||
//
|
||||
// memcpy(in->pBuffer + in->size, Serialized, Length);
|
||||
// in->size += Length;
|
||||
//
|
||||
// safe_delete_array(Serialized);
|
||||
// }
|
||||
// else {
|
||||
// Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//delete[] __emu_buffer;
|
||||
//
|
||||
////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
|
||||
////Log.Hex(Logs::Netcode, in->pBuffer, in->size);
|
||||
//
|
||||
//dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_ClientUpdate)
|
||||
@@ -581,7 +582,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 +858,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);
|
||||
@@ -1503,14 +1506,14 @@ namespace UF
|
||||
|
||||
ENCODE(OP_MoveItem)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(MoveItem_Struct);
|
||||
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
|
||||
eq->from_slot = ServerToUFSlot(emu->from_slot);
|
||||
eq->to_slot = ServerToUFSlot(emu->to_slot);
|
||||
OUT(number_in_stack);
|
||||
|
||||
FINISH_ENCODE();
|
||||
//ENCODE_LENGTH_EXACT(MoveItem_Struct);
|
||||
//SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
//
|
||||
//eq->from_slot = ServerToUFSlot(emu->from_slot);
|
||||
//eq->to_slot = ServerToUFSlot(emu->to_slot);
|
||||
//OUT(number_in_stack);
|
||||
//
|
||||
//FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
|
||||
@@ -1791,13 +1794,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 +1808,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 +1872,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 +2136,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 +2183,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 +2199,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 +2673,7 @@ namespace UF
|
||||
OUT(material);
|
||||
OUT(unknown06);
|
||||
OUT(elite_material);
|
||||
OUT(color.color);
|
||||
OUT(color.Color);
|
||||
OUT(wear_slot_id);
|
||||
|
||||
FINISH_ENCODE();
|
||||
@@ -2693,42 +2745,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 +3009,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 +3035,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 +3045,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 +3059,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 +3362,7 @@ namespace UF
|
||||
IN(type);
|
||||
IN(spellid);
|
||||
IN(damage);
|
||||
emu->sequence = eq->sequence;
|
||||
IN(meleepush_xy);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@@ -3554,16 +3587,16 @@ namespace UF
|
||||
|
||||
DECODE(OP_MoveItem)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
|
||||
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
|
||||
Log.Out(Logs::General, Logs::Netcode, "[UF] Moved item from %u to %u", eq->from_slot, eq->to_slot);
|
||||
|
||||
emu->from_slot = UFToServerSlot(eq->from_slot);
|
||||
emu->to_slot = UFToServerSlot(eq->to_slot);
|
||||
IN(number_in_stack);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
//DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
|
||||
//SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
//
|
||||
//Log.Out(Logs::General, Logs::Netcode, "[UF] Moved item from %u to %u", eq->from_slot, eq->to_slot);
|
||||
//
|
||||
//emu->from_slot = UFToServerSlot(eq->from_slot);
|
||||
//emu->to_slot = UFToServerSlot(eq->to_slot);
|
||||
//IN(number_in_stack);
|
||||
//
|
||||
//FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_PetCommands)
|
||||
@@ -3572,7 +3605,7 @@ namespace UF
|
||||
SETUP_DIRECT_DECODE(PetCommand_Struct, structs::PetCommand_Struct);
|
||||
|
||||
IN(command);
|
||||
IN(unknown);
|
||||
IN(target);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@@ -3728,7 +3761,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;
|
||||
@@ -3779,7 +3812,7 @@ namespace UF
|
||||
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
||||
|
||||
const Item_Struct *item = inst->GetUnscaledItem();
|
||||
const ItemData *item = inst->GetUnscaledItem();
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name);
|
||||
UF::structs::ItemSerializationHeader hdr;
|
||||
hdr.stacksize = stackable ? charges : 1;
|
||||
@@ -3817,7 +3850,7 @@ namespace UF
|
||||
//ORNAMENT IDFILE / ICON -
|
||||
uint16 ornaIcon = 0;
|
||||
if (inst->GetOrnamentationAug(ornamentationAugtype)) {
|
||||
const Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem();
|
||||
const ItemData *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem();
|
||||
ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile));
|
||||
ss.write((const char*)&null_term, sizeof(uint8));
|
||||
ornaIcon = aug_weap->Icon;
|
||||
@@ -3834,7 +3867,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;
|
||||
@@ -4233,7 +4266,7 @@ namespace UF
|
||||
|
||||
/*
|
||||
// TEST CODE: <watch>
|
||||
SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x);
|
||||
SubSlotNumber = InventoryOld::CalcSlotID(slot_id_in, x);
|
||||
*/
|
||||
|
||||
SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+135
-113
@@ -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 */
|
||||
};
|
||||
|
||||
@@ -2016,7 +2032,7 @@ struct AdventureLeaderboard_Struct
|
||||
/*struct Item_Shop_Struct {
|
||||
uint16 merchantid;
|
||||
uint8 itemtype;
|
||||
Item_Struct item;
|
||||
ItemData item;
|
||||
uint8 iss_unknown001[6];
|
||||
};*/
|
||||
|
||||
@@ -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
|
||||
|
||||
+497
-496
File diff suppressed because it is too large
Load Diff
+1
-134
@@ -181,14 +181,7 @@
|
||||
#define ServerOP_CZMessagePlayer 0x4008
|
||||
#define ServerOP_ReloadWorld 0x4009
|
||||
#define ServerOP_ReloadLogs 0x4010
|
||||
/* Query Server OP Codes */
|
||||
#define ServerOP_QSPlayerLogTrades 0x5010
|
||||
#define ServerOP_QSPlayerLogHandins 0x5011
|
||||
#define ServerOP_QSPlayerLogNPCKills 0x5012
|
||||
#define ServerOP_QSPlayerLogDeletes 0x5013
|
||||
#define ServerOP_QSPlayerLogMoves 0x5014
|
||||
#define ServerOP_QSPlayerLogMerchantTransactions 0x5015
|
||||
#define ServerOP_QSSendQuery 0x5016
|
||||
#define ServerOP_QSSendQuery 0x5000
|
||||
#define ServerOP_CZSignalNPC 0x5017
|
||||
#define ServerOP_CZSetEntityVariableByNPCTypeID 0x5018
|
||||
|
||||
@@ -1113,132 +1106,6 @@ struct CZClientSignalByName_Struct {
|
||||
uint32 data;
|
||||
};
|
||||
|
||||
struct QSTradeItems_Struct {
|
||||
uint32 from_id;
|
||||
uint16 from_slot;
|
||||
uint32 to_id;
|
||||
uint16 to_slot;
|
||||
uint32 item_id;
|
||||
uint16 charges;
|
||||
uint32 aug_1;
|
||||
uint32 aug_2;
|
||||
uint32 aug_3;
|
||||
uint32 aug_4;
|
||||
uint32 aug_5;
|
||||
};
|
||||
|
||||
struct QSPlayerLogTrade_Struct {
|
||||
uint32 char1_id;
|
||||
MoneyUpdate_Struct char1_money;
|
||||
uint16 char1_count;
|
||||
uint32 char2_id;
|
||||
MoneyUpdate_Struct char2_money;
|
||||
uint16 char2_count;
|
||||
uint16 _detail_count;
|
||||
QSTradeItems_Struct items[0];
|
||||
};
|
||||
|
||||
struct QSHandinItems_Struct {
|
||||
char action_type[7]; // handin, return or reward
|
||||
uint16 char_slot;
|
||||
uint32 item_id;
|
||||
uint16 charges;
|
||||
uint32 aug_1;
|
||||
uint32 aug_2;
|
||||
uint32 aug_3;
|
||||
uint32 aug_4;
|
||||
uint32 aug_5;
|
||||
};
|
||||
|
||||
struct QSPlayerLogHandin_Struct {
|
||||
uint32 quest_id;
|
||||
uint32 char_id;
|
||||
MoneyUpdate_Struct char_money;
|
||||
uint16 char_count;
|
||||
uint32 npc_id;
|
||||
MoneyUpdate_Struct npc_money;
|
||||
uint16 npc_count;
|
||||
uint16 _detail_count;
|
||||
QSHandinItems_Struct items[0];
|
||||
};
|
||||
|
||||
struct QSPlayerLogNPCKillSub_Struct{
|
||||
uint32 NPCID;
|
||||
uint32 ZoneID;
|
||||
uint32 Type;
|
||||
};
|
||||
|
||||
struct QSPlayerLogNPCKillsPlayers_Struct{
|
||||
uint32 char_id;
|
||||
};
|
||||
|
||||
struct QSPlayerLogNPCKill_Struct{
|
||||
QSPlayerLogNPCKillSub_Struct s1;
|
||||
QSPlayerLogNPCKillsPlayers_Struct Chars[0];
|
||||
};
|
||||
|
||||
struct QSDeleteItems_Struct {
|
||||
uint16 char_slot;
|
||||
uint32 item_id;
|
||||
uint16 charges;
|
||||
uint32 aug_1;
|
||||
uint32 aug_2;
|
||||
uint32 aug_3;
|
||||
uint32 aug_4;
|
||||
uint32 aug_5;
|
||||
};
|
||||
|
||||
struct QSPlayerLogDelete_Struct {
|
||||
uint32 char_id;
|
||||
uint16 stack_size; // '0' indicates full stack or non-stackable item move
|
||||
uint16 char_count;
|
||||
QSDeleteItems_Struct items[0];
|
||||
};
|
||||
|
||||
struct QSMoveItems_Struct {
|
||||
uint16 from_slot;
|
||||
uint16 to_slot;
|
||||
uint32 item_id;
|
||||
uint16 charges;
|
||||
uint32 aug_1;
|
||||
uint32 aug_2;
|
||||
uint32 aug_3;
|
||||
uint32 aug_4;
|
||||
uint32 aug_5;
|
||||
};
|
||||
|
||||
struct QSPlayerLogMove_Struct {
|
||||
uint32 char_id;
|
||||
uint16 from_slot;
|
||||
uint16 to_slot;
|
||||
uint16 stack_size; // '0' indicates full stack or non-stackable item move
|
||||
uint16 char_count;
|
||||
bool postaction;
|
||||
QSMoveItems_Struct items[0];
|
||||
};
|
||||
|
||||
struct QSTransactionItems_Struct {
|
||||
uint16 char_slot;
|
||||
uint32 item_id;
|
||||
uint16 charges;
|
||||
uint32 aug_1;
|
||||
uint32 aug_2;
|
||||
uint32 aug_3;
|
||||
uint32 aug_4;
|
||||
uint32 aug_5;
|
||||
};
|
||||
|
||||
struct QSMerchantLogTransaction_Struct {
|
||||
uint32 zone_id;
|
||||
uint32 merchant_id;
|
||||
MoneyUpdate_Struct merchant_money;
|
||||
uint16 merchant_count;
|
||||
uint32 char_id;
|
||||
MoneyUpdate_Struct char_money;
|
||||
uint16 char_count;
|
||||
QSTransactionItems_Struct items[0];
|
||||
};
|
||||
|
||||
struct QSGeneralQuery_Struct {
|
||||
char QueryString[0];
|
||||
};
|
||||
|
||||
+165
-223
@@ -151,74 +151,77 @@ 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
|
||||
return true;
|
||||
//// 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)
|
||||
//
|
||||
// (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);
|
||||
}
|
||||
else if (!inst) { // All other inventory
|
||||
return DeleteInventorySlot(char_id, slot_id);
|
||||
}
|
||||
|
||||
return UpdateInventorySlot(char_id, inst, slot_id);
|
||||
////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);
|
||||
//}
|
||||
//else if (!inst) { // All other inventory
|
||||
// return DeleteInventorySlot(char_id, slot_id);
|
||||
//}
|
||||
//
|
||||
//return UpdateInventorySlot(char_id, inst, slot_id);
|
||||
}
|
||||
|
||||
bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, int16 slot_id) {
|
||||
// need to check 'inst' argument for valid pointer
|
||||
|
||||
uint32 augslot[EmuConstants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM };
|
||||
if (inst->IsType(ItemClassCommon)) {
|
||||
for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) {
|
||||
ItemInst *auginst = inst->GetItem(i);
|
||||
augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : NO_ITEM;
|
||||
}
|
||||
}
|
||||
|
||||
uint16 charges = 0;
|
||||
if(inst->GetCharges() >= 0)
|
||||
charges = inst->GetCharges();
|
||||
else
|
||||
charges = 0x7FFF;
|
||||
|
||||
// Update/Insert item
|
||||
std::string query = StringFormat("REPLACE INTO inventory "
|
||||
"(charid, slotid, itemid, charges, instnodrop, custom_data, color, "
|
||||
"augslot1, augslot2, augslot3, augslot4, augslot5, augslot6, ornamenticon, ornamentidfile, ornament_hero_model) "
|
||||
"VALUES( %lu, %lu, %lu, %lu, %lu, '%s', %lu, "
|
||||
"%lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu)",
|
||||
(unsigned long)char_id, (unsigned long)slot_id, (unsigned long)inst->GetItem()->ID,
|
||||
(unsigned long)charges, (unsigned long)(inst->IsAttuned()? 1: 0),
|
||||
inst->GetCustomDataString().c_str(), (unsigned long)inst->GetColor(),
|
||||
(unsigned long)augslot[0], (unsigned long)augslot[1], (unsigned long)augslot[2],
|
||||
(unsigned long)augslot[3], (unsigned long)augslot[4], (unsigned long)augslot[5], (unsigned long)inst->GetOrnamentationIcon(),
|
||||
(unsigned long)inst->GetOrnamentationIDFile(), (unsigned long)inst->GetOrnamentHeroModel());
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
// 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++) {
|
||||
const ItemInst* baginst = inst->GetItem(idx);
|
||||
SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx));
|
||||
}
|
||||
|
||||
if (!results.Success()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
// need to check 'inst' argument for valid pointer
|
||||
//
|
||||
//uint32 augslot[EmuConstants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM };
|
||||
//if (inst->IsType(ItemClassCommon)) {
|
||||
// for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) {
|
||||
// ItemInst *auginst = inst->GetItem(i);
|
||||
// augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : NO_ITEM;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//uint16 charges = 0;
|
||||
//if(inst->GetCharges() >= 0)
|
||||
// charges = inst->GetCharges();
|
||||
//else
|
||||
// charges = 0x7FFF;
|
||||
//
|
||||
//// Update/Insert item
|
||||
//std::string query = StringFormat("REPLACE INTO inventory "
|
||||
// "(charid, slotid, itemid, charges, instnodrop, custom_data, color, "
|
||||
// "augslot1, augslot2, augslot3, augslot4, augslot5, augslot6, ornamenticon, ornamentidfile, ornament_hero_model) "
|
||||
// "VALUES( %lu, %lu, %lu, %lu, %lu, '%s', %lu, "
|
||||
// "%lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu)",
|
||||
// (unsigned long)char_id, (unsigned long)slot_id, (unsigned long)inst->GetItem()->ID,
|
||||
// (unsigned long)charges, (unsigned long)(inst->IsAttuned()? 1: 0),
|
||||
// inst->GetCustomDataString().c_str(), (unsigned long)inst->GetColor(),
|
||||
// (unsigned long)augslot[0], (unsigned long)augslot[1], (unsigned long)augslot[2],
|
||||
// (unsigned long)augslot[3], (unsigned long)augslot[4], (unsigned long)augslot[5], (unsigned long)inst->GetOrnamentationIcon(),
|
||||
// (unsigned long)inst->GetOrnamentationIDFile(), (unsigned long)inst->GetOrnamentHeroModel());
|
||||
//auto results = QueryDatabase(query);
|
||||
//
|
||||
//// Save bag contents, if slot supports bag contents
|
||||
//if (inst->IsType(ItemClassContainer) && InventoryOld::SupportsContainers(slot_id))
|
||||
// for (uint8 idx = SUB_BEGIN; idx < EmuConstants::ITEM_CONTAINER_SIZE; idx++) {
|
||||
// const ItemInst* baginst = inst->GetItem(idx);
|
||||
// SaveInventory(char_id, baginst, InventoryOld::CalcSlotId(slot_id, idx));
|
||||
// }
|
||||
//
|
||||
//if (!results.Success()) {
|
||||
// return false;
|
||||
//}
|
||||
//
|
||||
//return true;
|
||||
}
|
||||
|
||||
bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst, int16 slot_id) {
|
||||
@@ -252,10 +255,12 @@ bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst,
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
// 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++) {
|
||||
if (inst->IsType(ItemClassContainer) && InventoryOld::SupportsContainers(slot_id)) {
|
||||
// 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));
|
||||
SaveInventory(char_id, baginst, InventoryOld::CalcSlotId(slot_id, idx));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,10 +281,10 @@ bool SharedDatabase::DeleteInventorySlot(uint32 char_id, int16 slot_id) {
|
||||
}
|
||||
|
||||
// Delete bag slots, if need be
|
||||
if (!Inventory::SupportsContainers(slot_id))
|
||||
if (!InventoryOld::SupportsContainers(slot_id))
|
||||
return true;
|
||||
|
||||
int16 base_slot_id = Inventory::CalcSlotId(slot_id, SUB_BEGIN);
|
||||
int16 base_slot_id = InventoryOld::CalcSlotId(slot_id, SUB_BEGIN);
|
||||
query = StringFormat("DELETE FROM inventory WHERE charid = %i AND slotid >= %i AND slotid < %i",
|
||||
char_id, base_slot_id, (base_slot_id+10));
|
||||
results = QueryDatabase(query);
|
||||
@@ -302,10 +307,10 @@ bool SharedDatabase::DeleteSharedBankSlot(uint32 char_id, int16 slot_id) {
|
||||
}
|
||||
|
||||
// Delete bag slots, if need be
|
||||
if (!Inventory::SupportsContainers(slot_id))
|
||||
if (!InventoryOld::SupportsContainers(slot_id))
|
||||
return true;
|
||||
|
||||
int16 base_slot_id = Inventory::CalcSlotId(slot_id, SUB_BEGIN);
|
||||
int16 base_slot_id = InventoryOld::CalcSlotId(slot_id, SUB_BEGIN);
|
||||
query = StringFormat("DELETE FROM sharedbank WHERE acctid = %i "
|
||||
"AND slotid >= %i AND slotid < %i",
|
||||
account_id, base_slot_id, (base_slot_id+10));
|
||||
@@ -345,9 +350,9 @@ bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) {
|
||||
bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, InventoryOld* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) {
|
||||
|
||||
const Item_Struct* myitem;
|
||||
const ItemData* myitem;
|
||||
|
||||
std::string query = StringFormat("SELECT itemid, item_charges, slot FROM starting_items "
|
||||
"WHERE (race = %i or race = 0) AND (class = %i or class = 0) AND "
|
||||
@@ -368,7 +373,7 @@ bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv,
|
||||
if(!myitem)
|
||||
continue;
|
||||
|
||||
ItemInst* myinst = CreateBaseItem(myitem, charges);
|
||||
ItemInst* myinst = CreateBaseItemOld(myitem, charges);
|
||||
|
||||
if(slot < 0)
|
||||
slot = inv->FindFreeSlot(0, 0);
|
||||
@@ -382,7 +387,7 @@ bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv,
|
||||
|
||||
|
||||
// Retrieve shared bank inventory based on either account or character
|
||||
bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid)
|
||||
bool SharedDatabase::GetSharedBank(uint32 id, InventoryOld *inv, bool is_charid)
|
||||
{
|
||||
std::string query;
|
||||
|
||||
@@ -419,7 +424,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid)
|
||||
aug[4] = (uint32)atoi(row[7]);
|
||||
aug[5] = (uint32)atoi(row[8]);
|
||||
|
||||
const Item_Struct *item = GetItem(item_id);
|
||||
const ItemData *item = GetItem(item_id);
|
||||
|
||||
if (!item) {
|
||||
Log.Out(Logs::General, Logs::Error,
|
||||
@@ -430,7 +435,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid)
|
||||
|
||||
int16 put_slot_id = INVALID_INDEX;
|
||||
|
||||
ItemInst *inst = CreateBaseItem(item, charges);
|
||||
ItemInst *inst = CreateBaseItemOld(item, charges);
|
||||
if (inst && item->ItemClass == ItemClassCommon) {
|
||||
for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) {
|
||||
if (aug[i])
|
||||
@@ -482,150 +487,68 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid)
|
||||
}
|
||||
|
||||
// Overloaded: Retrieve character inventory based on character id
|
||||
bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv)
|
||||
bool SharedDatabase::GetInventory(uint32 char_id, EQEmu::Inventory *inv)
|
||||
{
|
||||
// Retrieve character inventory
|
||||
std::string query =
|
||||
StringFormat("SELECT slotid, itemid, charges, color, augslot1, augslot2, augslot3, augslot4, augslot5, "
|
||||
"augslot6, instnodrop, custom_data, ornamenticon, ornamentidfile, ornament_hero_model FROM "
|
||||
"inventory WHERE charid = %i ORDER BY slotid",
|
||||
char_id);
|
||||
std::string query = StringFormat("SELECT type, slot, bag_index, aug_index, item_id, charges, color, attuned, "
|
||||
"custom_data, ornament_icon, ornament_idfile, ornament_hero_model, tracking_id "
|
||||
"FROM character_inventory WHERE id=%u ORDER BY type, slot, bag_index, aug_index",
|
||||
char_id);
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success()) {
|
||||
Log.Out(Logs::General, Logs::Error, "If you got an error related to the 'instnodrop' field, run the "
|
||||
"following SQL Queries:\nalter table inventory add instnodrop "
|
||||
"tinyint(1) unsigned default 0 not null;\n");
|
||||
Log.Out(Logs::General, Logs::Error, "Error with query in SharedDatabase::GetInventory, could not get inventory"
|
||||
" for character %u", char_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto timestamps = GetItemRecastTimestamps(char_id);
|
||||
for(auto row : results) {
|
||||
int type = atoi(row[0]);
|
||||
int slot = atoi(row[1]);
|
||||
int bag_index = atoi(row[2]);
|
||||
int aug_index = atoi(row[3]);
|
||||
int item_id = atoi(row[4]);
|
||||
int charges = atoi(row[5]);
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
int16 slot_id = atoi(row[0]);
|
||||
uint32 item_id = atoi(row[1]);
|
||||
uint16 charges = atoi(row[2]);
|
||||
uint32 color = atoul(row[3]);
|
||||
auto inst = CreateItem(item_id, charges);
|
||||
if(inst) {
|
||||
uint32 color = (uint32)std::stoul(row[6]);
|
||||
int attuned = atoi(row[7]);
|
||||
uint32 ornament_icon = (uint32)std::stoul(row[9]);
|
||||
uint32 ornament_idfile = (uint32)std::stoul(row[10]);
|
||||
uint32 ornament_hero_model = (uint32)std::stoul(row[11]);
|
||||
|
||||
uint32 aug[EmuConstants::ITEM_COMMON_SIZE];
|
||||
|
||||
aug[0] = (uint32)atoul(row[4]);
|
||||
aug[1] = (uint32)atoul(row[5]);
|
||||
aug[2] = (uint32)atoul(row[6]);
|
||||
aug[3] = (uint32)atoul(row[7]);
|
||||
aug[4] = (uint32)atoul(row[8]);
|
||||
aug[5] = (uint32)atoul(row[9]);
|
||||
|
||||
bool instnodrop = (row[10] && (uint16)atoi(row[10])) ? true : false;
|
||||
|
||||
uint32 ornament_icon = (uint32)atoul(row[12]);
|
||||
uint32 ornament_idfile = (uint32)atoul(row[13]);
|
||||
uint32 ornament_hero_model = (uint32)atoul(row[14]);
|
||||
|
||||
const Item_Struct *item = GetItem(item_id);
|
||||
|
||||
if (!item) {
|
||||
Log.Out(Logs::General, Logs::Error,
|
||||
"Warning: charid %i has an invalid item_id %i in inventory slot %i", char_id, item_id,
|
||||
slot_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
int16 put_slot_id = INVALID_INDEX;
|
||||
|
||||
ItemInst *inst = CreateBaseItem(item, charges);
|
||||
|
||||
if (inst == nullptr)
|
||||
continue;
|
||||
|
||||
if (row[11]) {
|
||||
std::string data_str(row[11]);
|
||||
std::string idAsString;
|
||||
std::string value;
|
||||
bool use_id = true;
|
||||
|
||||
for (int i = 0; i < data_str.length(); ++i) {
|
||||
if (data_str[i] == '^') {
|
||||
if (!use_id) {
|
||||
inst->SetCustomData(idAsString, value);
|
||||
idAsString.clear();
|
||||
value.clear();
|
||||
}
|
||||
|
||||
use_id = !use_id;
|
||||
continue;
|
||||
}
|
||||
|
||||
char v = data_str[i];
|
||||
if (use_id)
|
||||
idAsString.push_back(v);
|
||||
else
|
||||
value.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
inst->SetOrnamentIcon(ornament_icon);
|
||||
inst->SetOrnamentationIDFile(ornament_idfile);
|
||||
inst->SetOrnamentHeroModel(ornament_hero_model);
|
||||
|
||||
if (instnodrop ||
|
||||
(((slot_id >= EmuConstants::EQUIPMENT_BEGIN && slot_id <= EmuConstants::EQUIPMENT_END) ||
|
||||
slot_id == MainPowerSource) &&
|
||||
inst->GetItem()->Attuneable))
|
||||
inst->SetAttuned(true);
|
||||
|
||||
if (color > 0)
|
||||
inst->SetColor(color);
|
||||
inst->SetAttuned(attuned ? true : false);
|
||||
inst->SetCustomData(row[8]);
|
||||
inst->SetOrnamentIcon(ornament_icon);
|
||||
inst->SetOrnamentIDFile(ornament_idfile);
|
||||
inst->SetOrnamentHeroModel(ornament_hero_model);
|
||||
inst->SetTrackingID(row[12]);
|
||||
|
||||
if (charges == 0x7FFF)
|
||||
inst->SetCharges(-1);
|
||||
else if (charges == 0 &&
|
||||
inst->IsStackable()) // Stackable items need a minimum charge of 1 remain moveable.
|
||||
inst->SetCharges(1);
|
||||
else
|
||||
inst->SetCharges(charges);
|
||||
|
||||
if (item->RecastDelay) {
|
||||
if (timestamps.count(item->RecastType))
|
||||
inst->SetRecastTimestamp(timestamps.at(item->RecastType));
|
||||
else
|
||||
inst->SetRecastTimestamp(0);
|
||||
}
|
||||
|
||||
if (item->ItemClass == ItemClassCommon) {
|
||||
for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) {
|
||||
if (aug[i])
|
||||
inst->PutAugment(this, i, aug[i]);
|
||||
auto *item = inst->GetItem();
|
||||
if(item->RecastDelay) {
|
||||
if(timestamps.count(item->RecastType)) {
|
||||
inst->SetRecastTimestamp(timestamps.at(item->RecastType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (slot_id >= 8000 && slot_id <= 8999) {
|
||||
put_slot_id = inv->PushCursor(*inst);
|
||||
} else if (slot_id >= 3111 && slot_id <= 3179) {
|
||||
// Admins: please report any occurrences of this error
|
||||
Log.Out(Logs::General, Logs::Error, "Warning: Defunct location for item in inventory: "
|
||||
"charid=%i, item_id=%i, slot_id=%i .. pushing to cursor...",
|
||||
char_id, item_id, slot_id);
|
||||
put_slot_id = inv->PushCursor(*inst);
|
||||
if(!inv->Put(EQEmu::InventorySlot(type, slot, bag_index, aug_index), inst)) {
|
||||
Log.Out(Logs::General, Logs::Error, "Error putting item %u into (%d, %d, %d, %d) for char %u.",
|
||||
item_id, type, slot, bag_index, aug_index, char_id);
|
||||
}
|
||||
} else {
|
||||
put_slot_id = inv->PutItem(slot_id, *inst);
|
||||
}
|
||||
|
||||
safe_delete(inst);
|
||||
|
||||
// Save ptr to item in inventory
|
||||
if (put_slot_id == INVALID_INDEX) {
|
||||
Log.Out(Logs::General, Logs::Error,
|
||||
"Warning: Invalid slot_id for item in inventory: charid=%i, item_id=%i, slot_id=%i",
|
||||
char_id, item_id, slot_id);
|
||||
Log.Out(Logs::General, Logs::Error, "Error putting item %u into (%d, %d, %d, %d) for char %u. Item does not exist.",
|
||||
item_id, type, slot, bag_index, aug_index, char_id);
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve shared inventory
|
||||
return GetSharedBank(char_id, inv, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Overloaded: Retrieve character inventory based on account_id and character name
|
||||
bool SharedDatabase::GetInventory(uint32 account_id, char *name, Inventory *inv)
|
||||
bool SharedDatabase::GetInventory(uint32 account_id, char *name, InventoryOld *inv)
|
||||
{
|
||||
// Retrieve character inventory
|
||||
std::string query =
|
||||
@@ -662,12 +585,12 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, Inventory *inv)
|
||||
uint32 ornament_idfile = (uint32)atoul(row[13]);
|
||||
uint32 ornament_hero_model = (uint32)atoul(row[14]);
|
||||
|
||||
const Item_Struct *item = GetItem(item_id);
|
||||
const ItemData *item = GetItem(item_id);
|
||||
int16 put_slot_id = INVALID_INDEX;
|
||||
if (!item)
|
||||
continue;
|
||||
|
||||
ItemInst *inst = CreateBaseItem(item, charges);
|
||||
ItemInst *inst = CreateBaseItemOld(item, charges);
|
||||
|
||||
if (inst == nullptr)
|
||||
continue;
|
||||
@@ -806,12 +729,12 @@ bool SharedDatabase::LoadItems() {
|
||||
if(items == -1) {
|
||||
EQ_EXCEPT("SharedDatabase", "Database returned no result");
|
||||
}
|
||||
uint32 size = static_cast<uint32>(EQEmu::FixedMemoryHashSet<Item_Struct>::estimated_size(items, max_item));
|
||||
uint32 size = static_cast<uint32>(EQEmu::FixedMemoryHashSet<ItemData>::estimated_size(items, max_item));
|
||||
if(items_mmf->Size() != size) {
|
||||
EQ_EXCEPT("SharedDatabase", "Couldn't load items because items_mmf->Size() != size");
|
||||
}
|
||||
|
||||
items_hash = new EQEmu::FixedMemoryHashSet<Item_Struct>(reinterpret_cast<uint8*>(items_mmf->Get()), size);
|
||||
items_hash = new EQEmu::FixedMemoryHashSet<ItemData>(reinterpret_cast<uint8*>(items_mmf->Get()), size);
|
||||
mutex.Unlock();
|
||||
} catch(std::exception& ex) {
|
||||
Log.Out(Logs::General, Logs::Error, "Error Loading Items: %s", ex.what());
|
||||
@@ -822,7 +745,7 @@ bool SharedDatabase::LoadItems() {
|
||||
}
|
||||
|
||||
void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id) {
|
||||
EQEmu::FixedMemoryHashSet<Item_Struct> hash(reinterpret_cast<uint8*>(data), size, items, max_item_id);
|
||||
EQEmu::FixedMemoryHashSet<ItemData> hash(reinterpret_cast<uint8*>(data), size, items, max_item_id);
|
||||
|
||||
char ndbuffer[4];
|
||||
bool disableNoRent = false;
|
||||
@@ -850,7 +773,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_
|
||||
}
|
||||
}
|
||||
|
||||
Item_Struct item;
|
||||
ItemData item;
|
||||
|
||||
const std::string query = "SELECT source,"
|
||||
#define F(x) "`"#x"`,"
|
||||
@@ -863,7 +786,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_
|
||||
}
|
||||
|
||||
for(auto row = results.begin(); row != results.end(); ++row) {
|
||||
memset(&item, 0, sizeof(Item_Struct));
|
||||
memset(&item, 0, sizeof(ItemData));
|
||||
|
||||
item.ItemClass = (uint8)atoi(row[ItemField::itemclass]);
|
||||
strcpy(item.Name,row[ItemField::name]);
|
||||
@@ -1078,7 +1001,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_
|
||||
|
||||
}
|
||||
|
||||
const Item_Struct* SharedDatabase::GetItem(uint32 id) {
|
||||
const ItemData* SharedDatabase::GetItem(uint32 id) {
|
||||
if (id == 0)
|
||||
{
|
||||
return nullptr;
|
||||
@@ -1097,7 +1020,7 @@ const Item_Struct* SharedDatabase::GetItem(uint32 id) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const Item_Struct* SharedDatabase::IterateItems(uint32* id) {
|
||||
const ItemData* SharedDatabase::IterateItems(uint32* id) {
|
||||
if(!items_hash || !id) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1158,7 +1081,7 @@ void SharedDatabase::GetFactionListInfo(uint32 &list_count, uint32 &max_lists) {
|
||||
auto row = results.begin();
|
||||
|
||||
list_count = static_cast<uint32>(atoul(row[0]));
|
||||
max_lists = static_cast<uint32>(atoul(row[1]));
|
||||
max_lists = static_cast<uint32>(atoul(row[1] ? row[1] : "0"));
|
||||
}
|
||||
|
||||
const NPCFactionList* SharedDatabase::GetNPCFactionEntry(uint32 id) {
|
||||
@@ -1235,9 +1158,6 @@ bool SharedDatabase::LoadNPCFactionLists() {
|
||||
uint32 list_count = 0;
|
||||
uint32 max_lists = 0;
|
||||
GetFactionListInfo(list_count, max_lists);
|
||||
if(list_count == 0) {
|
||||
EQ_EXCEPT("SharedDatabase", "Database returned no result");
|
||||
}
|
||||
uint32 size = static_cast<uint32>(EQEmu::FixedMemoryHashSet<NPCFactionList>::estimated_size(
|
||||
list_count, max_lists));
|
||||
|
||||
@@ -1256,14 +1176,14 @@ bool SharedDatabase::LoadNPCFactionLists() {
|
||||
}
|
||||
|
||||
// Create appropriate ItemInst class
|
||||
ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned)
|
||||
ItemInst* SharedDatabase::CreateItemOld(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned)
|
||||
{
|
||||
const Item_Struct* item = nullptr;
|
||||
const ItemData* item = nullptr;
|
||||
ItemInst* inst = nullptr;
|
||||
|
||||
item = GetItem(item_id);
|
||||
if (item) {
|
||||
inst = CreateBaseItem(item, charges);
|
||||
inst = CreateBaseItemOld(item, charges);
|
||||
|
||||
if (inst == nullptr) {
|
||||
Log.Out(Logs::General, Logs::Error, "Error: valid item data returned a null reference for ItemInst creation in SharedDatabase::CreateItem()");
|
||||
@@ -1285,14 +1205,14 @@ ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1,
|
||||
|
||||
|
||||
// Create appropriate ItemInst class
|
||||
ItemInst* SharedDatabase::CreateItem(const Item_Struct* item, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned)
|
||||
ItemInst* SharedDatabase::CreateItemOld(const ItemData* item, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned)
|
||||
{
|
||||
ItemInst* inst = nullptr;
|
||||
if (item) {
|
||||
inst = CreateBaseItem(item, charges);
|
||||
inst = CreateBaseItemOld(item, charges);
|
||||
|
||||
if (inst == nullptr) {
|
||||
Log.Out(Logs::General, Logs::Error, "Error: valid item data returned a null reference for ItemInst creation in SharedDatabase::CreateItem()");
|
||||
Log.Out(Logs::General, Logs::Error, "Error: valid item data returned a null reference for ItemInst creation in SharedDatabase::CreateItemOld()");
|
||||
Log.Out(Logs::General, Logs::Error, "Item Data = ID: %u, Name: %s, Charges: %i", item->ID, item->Name, charges);
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1309,7 +1229,7 @@ ItemInst* SharedDatabase::CreateItem(const Item_Struct* item, int16 charges, uin
|
||||
return inst;
|
||||
}
|
||||
|
||||
ItemInst* SharedDatabase::CreateBaseItem(const Item_Struct* item, int16 charges) {
|
||||
ItemInst* SharedDatabase::CreateBaseItemOld(const ItemData* item, int16 charges) {
|
||||
ItemInst* inst = nullptr;
|
||||
if (item) {
|
||||
// if maxcharges is -1 that means it is an unlimited use item.
|
||||
@@ -1323,7 +1243,7 @@ ItemInst* SharedDatabase::CreateBaseItem(const Item_Struct* item, int16 charges)
|
||||
inst = new ItemInst(item, charges);
|
||||
|
||||
if (inst == nullptr) {
|
||||
Log.Out(Logs::General, Logs::Error, "Error: valid item data returned a null reference for ItemInst creation in SharedDatabase::CreateBaseItem()");
|
||||
Log.Out(Logs::General, Logs::Error, "Error: valid item data returned a null reference for ItemInst creation in SharedDatabase::CreateBaseItemOld()");
|
||||
Log.Out(Logs::General, Logs::Error, "Item Data = ID: %u, Name: %s, Charges: %i", item->ID, item->Name, charges);
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1335,6 +1255,28 @@ ItemInst* SharedDatabase::CreateBaseItem(const Item_Struct* item, int16 charges)
|
||||
return inst;
|
||||
}
|
||||
|
||||
EQEmu::ItemInstance::pointer SharedDatabase::CreateItem(uint32 item_id, int16 charges, bool unique) {
|
||||
const ItemData* item = GetItem(item_id);
|
||||
if(item) {
|
||||
if(charges == 0 && item->MaxCharges == -1) {
|
||||
charges = 1;
|
||||
}
|
||||
|
||||
if(charges <= 0 && item->Stackable) {
|
||||
charges = 1;
|
||||
}
|
||||
|
||||
EQEmu::ItemInstance::pointer inst = EQEmu::ItemInstance::pointer(new EQEmu::ItemInstance(item, charges));
|
||||
if(unique) {
|
||||
inst->SetSerialNumber(EQEmu::GetNextItemInstanceSerial());
|
||||
//Set Tracking here
|
||||
}
|
||||
return inst;
|
||||
}
|
||||
|
||||
return EQEmu::ItemInstance::pointer(nullptr);
|
||||
}
|
||||
|
||||
int32 SharedDatabase::DeleteStalePlayerCorpses() {
|
||||
if(RuleB(Zone, EnableShadowrest)) {
|
||||
std::string query = StringFormat(
|
||||
@@ -1837,7 +1779,7 @@ void SharedDatabase::GetLootTableInfo(uint32 &loot_table_count, uint32 &max_loot
|
||||
auto row = results.begin();
|
||||
|
||||
loot_table_count = static_cast<uint32>(atoul(row[0]));
|
||||
max_loot_table = static_cast<uint32>(atoul(row[1]));
|
||||
max_loot_table = static_cast<uint32>(atoul(row[1] ? row[1] : "0"));
|
||||
loot_table_entries = static_cast<uint32>(atoul(row[2]));
|
||||
}
|
||||
|
||||
@@ -1858,7 +1800,7 @@ void SharedDatabase::GetLootDropInfo(uint32 &loot_drop_count, uint32 &max_loot_d
|
||||
auto row =results.begin();
|
||||
|
||||
loot_drop_count = static_cast<uint32>(atoul(row[0]));
|
||||
max_loot_drop = static_cast<uint32>(atoul(row[1]));
|
||||
max_loot_drop = static_cast<uint32>(atoul(row[1] ? row[1] : "0"));
|
||||
loot_drop_entries = static_cast<uint32>(atoul(row[2]));
|
||||
}
|
||||
|
||||
|
||||
+14
-12
@@ -9,18 +9,19 @@
|
||||
#include "base_data.h"
|
||||
#include "fixed_memory_hash_set.h"
|
||||
#include "fixed_memory_variable_hash_set.h"
|
||||
#include "inventory.h"
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
class EvolveInfo;
|
||||
class Inventory;
|
||||
class InventoryOld;
|
||||
class ItemInst;
|
||||
struct BaseDataStruct;
|
||||
struct InspectMessage_Struct;
|
||||
struct PlayerProfile_Struct;
|
||||
struct SPDat_Spell_Struct;
|
||||
struct Item_Struct;
|
||||
struct ItemData;
|
||||
struct NPCFactionList;
|
||||
struct LootTable_Struct;
|
||||
struct LootDrop_Struct;
|
||||
@@ -65,15 +66,15 @@ class SharedDatabase : public Database
|
||||
bool UpdateInventorySlot(uint32 char_id, const ItemInst* inst, int16 slot_id);
|
||||
bool UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst, int16 slot_id);
|
||||
bool VerifyInventory(uint32 account_id, int16 slot_id, const ItemInst* inst);
|
||||
bool GetSharedBank(uint32 id, Inventory* inv, bool is_charid);
|
||||
bool GetSharedBank(uint32 id, InventoryOld* inv, bool is_charid);
|
||||
int32 GetSharedPlatinum(uint32 account_id);
|
||||
bool SetSharedPlatinum(uint32 account_id, int32 amount_to_add);
|
||||
bool GetInventory(uint32 char_id, Inventory* inv);
|
||||
bool GetInventory(uint32 account_id, char* name, Inventory* inv);
|
||||
bool GetInventory(uint32 char_id, EQEmu::Inventory* inv);
|
||||
bool GetInventory(uint32 account_id, char* name, InventoryOld* inv);
|
||||
std::map<uint32, uint32> GetItemRecastTimestamps(uint32 char_id);
|
||||
uint32 GetItemRecastTimestamp(uint32 char_id, uint32 recast_type);
|
||||
void ClearOldRecastTimestamps(uint32 char_id);
|
||||
bool SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin);
|
||||
bool SetStartingItems(PlayerProfile_Struct* pp, InventoryOld* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin);
|
||||
|
||||
|
||||
std::string GetBook(const char *txtfile);
|
||||
@@ -81,9 +82,10 @@ class SharedDatabase : public Database
|
||||
/*
|
||||
Item Methods
|
||||
*/
|
||||
ItemInst* CreateItem(uint32 item_id, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0);
|
||||
ItemInst* CreateItem(const Item_Struct* item, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0);
|
||||
ItemInst* CreateBaseItem(const Item_Struct* item, int16 charges = 0);
|
||||
ItemInst* CreateItemOld(uint32 item_id, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0);
|
||||
ItemInst* CreateItemOld(const ItemData* item, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0);
|
||||
ItemInst* CreateBaseItemOld(const ItemData* item, int16 charges = 0);
|
||||
EQEmu::ItemInstance::pointer CreateItem(uint32 item_id, int16 charges = 0, bool unique = true);
|
||||
|
||||
/*
|
||||
Shared Memory crap
|
||||
@@ -93,8 +95,8 @@ class SharedDatabase : public Database
|
||||
void GetItemsCount(int32 &item_count, uint32 &max_id);
|
||||
void LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id);
|
||||
bool LoadItems();
|
||||
const Item_Struct* IterateItems(uint32* id);
|
||||
const Item_Struct* GetItem(uint32 id);
|
||||
const ItemData* IterateItems(uint32* id);
|
||||
const ItemData* GetItem(uint32 id);
|
||||
const EvolveInfo* GetEvolveInfo(uint32 loregroup);
|
||||
|
||||
//faction lists
|
||||
@@ -130,7 +132,7 @@ class SharedDatabase : public Database
|
||||
|
||||
EQEmu::MemoryMappedFile *skill_caps_mmf;
|
||||
EQEmu::MemoryMappedFile *items_mmf;
|
||||
EQEmu::FixedMemoryHashSet<Item_Struct> *items_hash;
|
||||
EQEmu::FixedMemoryHashSet<ItemData> *items_hash;
|
||||
EQEmu::MemoryMappedFile *faction_mmf;
|
||||
EQEmu::FixedMemoryHashSet<NPCFactionList> *faction_hash;
|
||||
EQEmu::MemoryMappedFile *loot_table_mmf;
|
||||
|
||||
@@ -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] < 127 && !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
|
||||
};
|
||||
|
||||
@@ -71,7 +71,6 @@ const std::string StringFormat(const char* format, ...)
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
// normal strncpy doesnt put a null term on copied strings, this one does
|
||||
// ref: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcecrt/htm/_wcecrt_strncpy_wcsncpy.asp
|
||||
char* strn0cpy(char* dest, const char* source, uint32 size) {
|
||||
@@ -408,3 +407,11 @@ bool isAlphaNumeric(const char *text)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void find_replace(std::string& string_subject, const std::string& search_string, const std::string& replace_string) {
|
||||
auto index = string_subject.find_first_of(search_string);
|
||||
while (index != std::string::npos) {
|
||||
string_subject.replace(index, index + 1, replace_string);
|
||||
index = string_subject.find_first_of(search_string);
|
||||
}
|
||||
}
|
||||
|
||||
+18
-21
@@ -23,37 +23,34 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
const std::string vStringFormat(const char* format, va_list args);
|
||||
const std::string StringFormat(const char* format, ...);
|
||||
std::string EscapeString(const std::string &s);
|
||||
std::string EscapeString(const char *src, size_t sz);
|
||||
|
||||
const char *MakeLowerString(const char *source);
|
||||
|
||||
void MakeLowerString(const char *source, char *target);
|
||||
|
||||
int MakeAnyLenString(char** ret, const char* format, ...);
|
||||
uint32 AppendAnyLenString(char** ret, uint32* bufsize, uint32* strlen, const char* format, ...);
|
||||
|
||||
uint32 hextoi(const char* num);
|
||||
uint64 hextoi64(const char* num);
|
||||
bool atobool(const char* iBool);
|
||||
|
||||
char* strn0cpy(char* dest, const char* source, uint32 size);
|
||||
// return value =true if entire string(source) fit, false if it was truncated
|
||||
bool isAlphaNumeric(const char *text);
|
||||
bool strn0cpyt(char* dest, const char* source, uint32 size);
|
||||
|
||||
char *CleanMobName(const char *in, char *out);
|
||||
char *RemoveApostrophes(const char *s);
|
||||
char* strn0cpy(char* dest, const char* source, uint32 size);
|
||||
|
||||
const char *ConvertArray(int input, char *returnchar);
|
||||
const char *ConvertArrayF(float input, char *returnchar);
|
||||
const char *MakeLowerString(const char *source);
|
||||
const std::string StringFormat(const char* format, ...);
|
||||
const std::string vStringFormat(const char* format, va_list args);
|
||||
|
||||
void RemoveApostrophes(std::string &s);
|
||||
char *RemoveApostrophes(const char *s);
|
||||
int MakeAnyLenString(char** ret, const char* format, ...);
|
||||
|
||||
std::string EscapeString(const char *src, size_t sz);
|
||||
std::string EscapeString(const std::string &s);
|
||||
|
||||
std::vector<std::string> SplitString(const std::string &s, char delim);
|
||||
|
||||
bool isAlphaNumeric(const char *text);
|
||||
uint32 AppendAnyLenString(char** ret, uint32* bufsize, uint32* strlen, const char* format, ...);
|
||||
uint32 hextoi(const char* num);
|
||||
|
||||
uint64 hextoi64(const char* num);
|
||||
|
||||
void MakeLowerString(const char *source, char *target);
|
||||
void RemoveApostrophes(std::string &s);
|
||||
void find_replace(std::string& string_subject, const std::string& search_string, const std::string& replace_string);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
|
||||
+5
-5
@@ -22,15 +22,15 @@
|
||||
#define LOGIN_VERSION "0.8.0"
|
||||
#define EQEMU_PROTOCOL_VERSION "0.3.10"
|
||||
|
||||
#define CURRENT_VERSION "1.0.0"
|
||||
#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 9073
|
||||
#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)
|
||||
{
|
||||
|
||||
+10
-223
@@ -123,229 +123,6 @@ void Database::AddSpeech(const char* from, const char* to, const char* message,
|
||||
|
||||
}
|
||||
|
||||
void Database::LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 detailCount) {
|
||||
|
||||
std::string query = StringFormat("INSERT INTO `qs_player_trade_record` SET `time` = NOW(), "
|
||||
"`char1_id` = '%i', `char1_pp` = '%i', `char1_gp` = '%i', "
|
||||
"`char1_sp` = '%i', `char1_cp` = '%i', `char1_items` = '%i', "
|
||||
"`char2_id` = '%i', `char2_pp` = '%i', `char2_gp` = '%i', "
|
||||
"`char2_sp` = '%i', `char2_cp` = '%i', `char2_items` = '%i'",
|
||||
QS->char1_id, QS->char1_money.platinum, QS->char1_money.gold,
|
||||
QS->char1_money.silver, QS->char1_money.copper, QS->char1_count,
|
||||
QS->char2_id, QS->char2_money.platinum, QS->char2_money.gold,
|
||||
QS->char2_money.silver, QS->char2_money.copper, QS->char2_count);
|
||||
auto results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "Failed Trade Log Record Insert: %s", results.ErrorMessage().c_str());
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
|
||||
}
|
||||
|
||||
if(detailCount == 0)
|
||||
return;
|
||||
|
||||
int lastIndex = results.LastInsertedID();
|
||||
|
||||
for(int i = 0; i < detailCount; i++) {
|
||||
query = StringFormat("INSERT INTO `qs_player_trade_record_entries` SET `event_id` = '%i', "
|
||||
"`from_id` = '%i', `from_slot` = '%i', `to_id` = '%i', `to_slot` = '%i', "
|
||||
"`item_id` = '%i', `charges` = '%i', `aug_1` = '%i', `aug_2` = '%i', "
|
||||
"`aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'",
|
||||
lastIndex, QS->items[i].from_id, QS->items[i].from_slot,
|
||||
QS->items[i].to_id, QS->items[i].to_slot, QS->items[i].item_id,
|
||||
QS->items[i].charges, QS->items[i].aug_1, QS->items[i].aug_2,
|
||||
QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5);
|
||||
results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "Failed Trade Log Record Entry Insert: %s", results.ErrorMessage().c_str());
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Database::LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 detailCount) {
|
||||
|
||||
std::string query = StringFormat("INSERT INTO `qs_player_handin_record` SET `time` = NOW(), "
|
||||
"`quest_id` = '%i', `char_id` = '%i', `char_pp` = '%i', "
|
||||
"`char_gp` = '%i', `char_sp` = '%i', `char_cp` = '%i', "
|
||||
"`char_items` = '%i', `npc_id` = '%i', `npc_pp` = '%i', "
|
||||
"`npc_gp` = '%i', `npc_sp` = '%i', `npc_cp` = '%i', "
|
||||
"`npc_items`='%i'",
|
||||
QS->quest_id, QS->char_id, QS->char_money.platinum,
|
||||
QS->char_money.gold, QS->char_money.silver, QS->char_money.copper,
|
||||
QS->char_count, QS->npc_id, QS->npc_money.platinum,
|
||||
QS->npc_money.gold, QS->npc_money.silver, QS->npc_money.copper,
|
||||
QS->npc_count);
|
||||
auto results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "Failed Handin Log Record Insert: %s", results.ErrorMessage().c_str());
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
|
||||
}
|
||||
|
||||
if(detailCount == 0)
|
||||
return;
|
||||
|
||||
int lastIndex = results.LastInsertedID();
|
||||
|
||||
for(int i = 0; i < detailCount; i++) {
|
||||
query = StringFormat("INSERT INTO `qs_player_handin_record_entries` SET `event_id` = '%i', "
|
||||
"`action_type` = '%s', `char_slot` = '%i', `item_id` = '%i', "
|
||||
"`charges` = '%i', `aug_1` = '%i', `aug_2` = '%i', `aug_3` = '%i', "
|
||||
"`aug_4` = '%i', `aug_5` = '%i'",
|
||||
lastIndex, QS->items[i].action_type, QS->items[i].char_slot,
|
||||
QS->items[i].item_id, QS->items[i].charges, QS->items[i].aug_1,
|
||||
QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4,
|
||||
QS->items[i].aug_5);
|
||||
if(!results.Success()) {
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "Failed Handin Log Record Entry Insert: %s", results.ErrorMessage().c_str());
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Database::LogPlayerNPCKill(QSPlayerLogNPCKill_Struct* QS, uint32 members){
|
||||
|
||||
std::string query = StringFormat("INSERT INTO `qs_player_npc_kill_record` "
|
||||
"SET `npc_id` = '%i', `type` = '%i', "
|
||||
"`zone_id` = '%i', `time` = NOW()",
|
||||
QS->s1.NPCID, QS->s1.Type, QS->s1.ZoneID);
|
||||
auto results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "Failed NPC Kill Log Record Insert: %s", results.ErrorMessage().c_str());
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
|
||||
}
|
||||
|
||||
if(members == 0)
|
||||
return;
|
||||
|
||||
int lastIndex = results.LastInsertedID();
|
||||
|
||||
for (int i = 0; i < members; i++) {
|
||||
query = StringFormat("INSERT INTO `qs_player_npc_kill_record_entries` "
|
||||
"SET `event_id` = '%i', `char_id` = '%i'",
|
||||
lastIndex, QS->Chars[i].char_id);
|
||||
auto results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "Failed NPC Kill Log Entry Insert: %s", results.ErrorMessage().c_str());
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Database::LogPlayerDelete(QSPlayerLogDelete_Struct* QS, uint32 items) {
|
||||
|
||||
std::string query = StringFormat("INSERT INTO `qs_player_delete_record` SET `time` = NOW(), "
|
||||
"`char_id` = '%i', `stack_size` = '%i', `char_items` = '%i'",
|
||||
QS->char_id, QS->stack_size, QS->char_count, QS->char_count);
|
||||
auto results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "Failed Delete Log Record Insert: %s", results.ErrorMessage().c_str());
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
|
||||
}
|
||||
|
||||
if(items == 0)
|
||||
return;
|
||||
|
||||
int lastIndex = results.LastInsertedID();
|
||||
|
||||
for(int i = 0; i < items; i++) {
|
||||
query = StringFormat("INSERT INTO `qs_player_delete_record_entries` SET `event_id` = '%i', "
|
||||
"`char_slot` = '%i', `item_id` = '%i', `charges` = '%i', `aug_1` = '%i', "
|
||||
"`aug_2` = '%i', `aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'",
|
||||
lastIndex, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges,
|
||||
QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4,
|
||||
QS->items[i].aug_5);
|
||||
results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "Failed Delete Log Record Entry Insert: %s", results.ErrorMessage().c_str());
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Database::LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 items) {
|
||||
/* These are item moves */
|
||||
|
||||
std::string query = StringFormat("INSERT INTO `qs_player_move_record` SET `time` = NOW(), "
|
||||
"`char_id` = '%i', `from_slot` = '%i', `to_slot` = '%i', "
|
||||
"`stack_size` = '%i', `char_items` = '%i', `postaction` = '%i'",
|
||||
QS->char_id, QS->from_slot, QS->to_slot, QS->stack_size,
|
||||
QS->char_count, QS->postaction);
|
||||
auto results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "Failed Move Log Record Insert: %s", results.ErrorMessage().c_str());
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
|
||||
}
|
||||
|
||||
if(items == 0)
|
||||
return;
|
||||
|
||||
int lastIndex = results.LastInsertedID();
|
||||
|
||||
for(int i = 0; i < items; i++) {
|
||||
query = StringFormat("INSERT INTO `qs_player_move_record_entries` SET `event_id` = '%i', "
|
||||
"`from_slot` = '%i', `to_slot` = '%i', `item_id` = '%i', `charges` = '%i', "
|
||||
"`aug_1` = '%i', `aug_2` = '%i', `aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'",
|
||||
lastIndex, QS->items[i].from_slot, QS->items[i].to_slot, QS->items[i].item_id,
|
||||
QS->items[i].charges, QS->items[i].aug_1, QS->items[i].aug_2,
|
||||
QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5);
|
||||
results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "Failed Move Log Record Entry Insert: %s", results.ErrorMessage().c_str());
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint32 items) {
|
||||
/* Merchant transactions are from the perspective of the merchant, not the player -U */
|
||||
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', "
|
||||
"`merchant_items` = '%i', `char_id` = '%i', `char_pp` = '%i', "
|
||||
"`char_gp` = '%i', `char_sp` = '%i', `char_cp` = '%i', "
|
||||
"`char_items` = '%i'",
|
||||
QS->zone_id, QS->merchant_id, QS->merchant_money.platinum,
|
||||
QS->merchant_money.gold, QS->merchant_money.silver,
|
||||
QS->merchant_money.copper, QS->merchant_count, QS->char_id,
|
||||
QS->char_money.platinum, QS->char_money.gold, QS->char_money.silver,
|
||||
QS->char_money.copper, QS->char_count);
|
||||
auto results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "Failed Transaction Log Record Insert: %s", results.ErrorMessage().c_str());
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
|
||||
}
|
||||
|
||||
if(items == 0)
|
||||
return;
|
||||
|
||||
int lastIndex = results.LastInsertedID();
|
||||
|
||||
for(int i = 0; i < items; i++) {
|
||||
query = StringFormat("INSERT INTO `qs_merchant_transaction_record_entries` SET `event_id` = '%i', "
|
||||
"`char_slot` = '%i', `item_id` = '%i', `charges` = '%i', `aug_1` = '%i', "
|
||||
"`aug_2` = '%i', `aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'",
|
||||
lastIndex, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges,
|
||||
QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4,
|
||||
QS->items[i].aug_5);
|
||||
results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "Failed Transaction Log Record Entry Insert: %s", results.ErrorMessage().c_str());
|
||||
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Database::GeneralQueryReceive(ServerPacket *pack) {
|
||||
/*
|
||||
These are general queries passed from anywhere in zone instead of packing structures and breaking them down again and again
|
||||
@@ -386,6 +163,16 @@ void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings){
|
||||
log_settings[log_category].log_to_file = atoi(row[3]);
|
||||
log_settings[log_category].log_to_gmsay = atoi(row[4]);
|
||||
|
||||
/* Determine if any output method is enabled for the category
|
||||
and set it to 1 so it can used to check if category is enabled */
|
||||
const bool log_to_console = log_settings[log_category].log_to_console > 0;
|
||||
const bool log_to_file = log_settings[log_category].log_to_file > 0;
|
||||
const bool log_to_gmsay = log_settings[log_category].log_to_gmsay > 0;
|
||||
const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay;
|
||||
|
||||
if (is_category_enabled)
|
||||
log_settings[log_category].is_category_enabled = 1;
|
||||
|
||||
/*
|
||||
This determines whether or not the process needs to actually file log anything.
|
||||
If we go through this whole loop and nothing is set to any debug level, there is no point to create a file or keep anything open
|
||||
|
||||
@@ -44,12 +44,6 @@ public:
|
||||
~Database();
|
||||
|
||||
void AddSpeech(const char* from, const char* to, const char* message, uint16 minstatus, uint32 guilddbid, uint8 type);
|
||||
void LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 DetailCount);
|
||||
void LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 DetailCount);
|
||||
void LogPlayerNPCKill(QSPlayerLogNPCKill_Struct* QS, uint32 Members);
|
||||
void LogPlayerDelete(QSPlayerLogDelete_Struct* QS, uint32 Items);
|
||||
void LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 Items);
|
||||
void LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint32 Items);
|
||||
void GeneralQueryReceive(ServerPacket *pack);
|
||||
|
||||
void LoadLogSettings(EQEmuLogSys::LogSettings* log_settings);
|
||||
|
||||
@@ -81,41 +81,6 @@ void WorldServer::Process()
|
||||
database.AddSpeech(tmp1.c_str(), tmp2.c_str(), SSS->message, SSS->minstatus, SSS->guilddbid, SSS->type);
|
||||
break;
|
||||
}
|
||||
case ServerOP_QSPlayerLogTrades: {
|
||||
QSPlayerLogTrade_Struct *QS = (QSPlayerLogTrade_Struct*)pack->pBuffer;
|
||||
database.LogPlayerTrade(QS, QS->_detail_count);
|
||||
break;
|
||||
}
|
||||
case ServerOP_QSPlayerLogHandins: {
|
||||
QSPlayerLogHandin_Struct *QS = (QSPlayerLogHandin_Struct*)pack->pBuffer;
|
||||
database.LogPlayerHandin(QS, QS->_detail_count);
|
||||
break;
|
||||
}
|
||||
case ServerOP_QSPlayerLogNPCKills: {
|
||||
QSPlayerLogNPCKill_Struct *QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer;
|
||||
uint32 Members = pack->size - sizeof(QSPlayerLogNPCKill_Struct);
|
||||
if (Members > 0) Members = Members / sizeof(QSPlayerLogNPCKillsPlayers_Struct);
|
||||
database.LogPlayerNPCKill(QS, Members);
|
||||
break;
|
||||
}
|
||||
case ServerOP_QSPlayerLogDeletes: {
|
||||
QSPlayerLogDelete_Struct *QS = (QSPlayerLogDelete_Struct*)pack->pBuffer;
|
||||
uint32 Items = QS->char_count;
|
||||
database.LogPlayerDelete(QS, Items);
|
||||
break;
|
||||
}
|
||||
case ServerOP_QSPlayerLogMoves: {
|
||||
QSPlayerLogMove_Struct *QS = (QSPlayerLogMove_Struct*)pack->pBuffer;
|
||||
uint32 Items = QS->char_count;
|
||||
database.LogPlayerMove(QS, Items);
|
||||
break;
|
||||
}
|
||||
case ServerOP_QSPlayerLogMerchantTransactions: {
|
||||
QSMerchantLogTransaction_Struct *QS = (QSMerchantLogTransaction_Struct*)pack->pBuffer;
|
||||
uint32 Items = QS->char_count + QS->merchant_count;
|
||||
database.LogMerchantTransaction(QS, Items);
|
||||
break;
|
||||
}
|
||||
case ServerOP_QueryServGeneric: {
|
||||
/*
|
||||
The purpose of ServerOP_QueryServerGeneric is so that we don't have to add code to world just to relay packets
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "../common/ipc_mutex.h"
|
||||
#include "../common/memory_mapped_file.h"
|
||||
#include "../common/eqemu_exception.h"
|
||||
#include "../common/item_struct.h"
|
||||
#include "../common/item_data.h"
|
||||
|
||||
void LoadItems(SharedDatabase *database) {
|
||||
EQEmu::IPCMutex mutex("items");
|
||||
@@ -35,7 +35,7 @@ void LoadItems(SharedDatabase *database) {
|
||||
EQ_EXCEPT("Shared Memory", "Unable to get any items from the database.");
|
||||
}
|
||||
|
||||
uint32 size = static_cast<uint32>(EQEmu::FixedMemoryHashSet<Item_Struct>::estimated_size(items, max_item));
|
||||
uint32 size = static_cast<uint32>(EQEmu::FixedMemoryHashSet<ItemData>::estimated_size(items, max_item));
|
||||
EQEmu::MemoryMappedFile mmf("shared/items", size);
|
||||
mmf.ZeroFile();
|
||||
|
||||
|
||||
@@ -31,9 +31,6 @@ void LoadFactions(SharedDatabase *database) {
|
||||
uint32 lists = 0;
|
||||
uint32 max_list = 0;
|
||||
database->GetFactionListInfo(lists, max_list);
|
||||
if(lists == 0) {
|
||||
EQ_EXCEPT("Shared Memory", "Unable to get any factions from the database.");
|
||||
}
|
||||
|
||||
uint32 size = static_cast<uint32>(EQEmu::FixedMemoryHashSet<NPCFactionList>::estimated_size(lists, max_list));
|
||||
EQEmu::MemoryMappedFile mmf("shared/faction", size);
|
||||
|
||||
@@ -12,7 +12,9 @@ SET(tests_headers
|
||||
fixed_memory_test.h
|
||||
fixed_memory_variable_test.h
|
||||
hextoi_32_64_test.h
|
||||
inventory_test.h
|
||||
ipc_mutex_test.h
|
||||
memory_buffer_test.h
|
||||
memory_mapped_file_test.h
|
||||
string_util_test.h
|
||||
skills_util_test.h
|
||||
@@ -20,7 +22,7 @@ SET(tests_headers
|
||||
|
||||
ADD_EXECUTABLE(tests ${tests_sources} ${tests_headers})
|
||||
|
||||
TARGET_LINK_LIBRARIES(tests common cppunit)
|
||||
TARGET_LINK_LIBRARIES(tests common cppunit debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE})
|
||||
|
||||
INSTALL(TARGETS tests RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
|
||||
|
||||
+23
-23
@@ -27,7 +27,7 @@ class FixedMemoryHashTest : public Test::Suite {
|
||||
typedef void(FixedMemoryHashTest::*TestFunction)(void);
|
||||
public:
|
||||
FixedMemoryHashTest() {
|
||||
size_ = EQEmu::FixedMemoryHashSet<Item_Struct>::estimated_size(72000, 190000);
|
||||
size_ = EQEmu::FixedMemoryHashSet<ItemData>::estimated_size(72000, 190000);
|
||||
data_ = new uint8[size_];
|
||||
memset(data_, 0, size_);
|
||||
TEST_ADD(FixedMemoryHashTest::InitTest);
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
|
||||
private:
|
||||
void InitTest() {
|
||||
EQEmu::FixedMemoryHashSet<Item_Struct> hash(data_, size_, 72000, 190000);
|
||||
EQEmu::FixedMemoryHashSet<ItemData> hash(data_, size_, 72000, 190000);
|
||||
TEST_ASSERT(!hash.exists(1001));
|
||||
TEST_ASSERT(hash.size() == 0);
|
||||
TEST_ASSERT(hash.max_size() == 72000);
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
}
|
||||
|
||||
void LoadTest() {
|
||||
EQEmu::FixedMemoryHashSet<Item_Struct> hash(data_, size_);
|
||||
EQEmu::FixedMemoryHashSet<ItemData> hash(data_, size_);
|
||||
TEST_ASSERT(!hash.exists(1001));
|
||||
TEST_ASSERT(hash.size() == 0);
|
||||
TEST_ASSERT(hash.max_size() == 72000);
|
||||
@@ -65,8 +65,8 @@ public:
|
||||
}
|
||||
|
||||
void InsertTest() {
|
||||
EQEmu::FixedMemoryHashSet<Item_Struct> hash(data_, size_);
|
||||
Item_Struct item;
|
||||
EQEmu::FixedMemoryHashSet<ItemData> hash(data_, size_);
|
||||
ItemData item;
|
||||
memset(&item, 0, sizeof(item));
|
||||
strcpy(item.Name, "Iron Sword");
|
||||
item.ID = 1001;
|
||||
@@ -79,20 +79,20 @@ public:
|
||||
}
|
||||
|
||||
void RetrieveTest() {
|
||||
EQEmu::FixedMemoryHashSet<Item_Struct> hash(data_, size_);
|
||||
EQEmu::FixedMemoryHashSet<ItemData> hash(data_, size_);
|
||||
TEST_ASSERT(hash.exists(1001));
|
||||
TEST_ASSERT(hash.size() == 1);
|
||||
TEST_ASSERT(hash.max_size() == 72000);
|
||||
TEST_ASSERT(!hash.empty());
|
||||
|
||||
Item_Struct item = hash[1001];
|
||||
ItemData item = hash[1001];
|
||||
TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0);
|
||||
TEST_ASSERT(item.ID == 1001);
|
||||
}
|
||||
|
||||
void OverwriteTest() {
|
||||
EQEmu::FixedMemoryHashSet<Item_Struct> hash(data_, size_);
|
||||
Item_Struct item;
|
||||
EQEmu::FixedMemoryHashSet<ItemData> hash(data_, size_);
|
||||
ItemData item;
|
||||
memset(&item, 0, sizeof(item));
|
||||
strcpy(item.Name, "Steel Sword");
|
||||
item.ID = 1001;
|
||||
@@ -105,20 +105,20 @@ public:
|
||||
}
|
||||
|
||||
void OverwriteRetrieveTest() {
|
||||
EQEmu::FixedMemoryHashSet<Item_Struct> hash(data_, size_);
|
||||
EQEmu::FixedMemoryHashSet<ItemData> hash(data_, size_);
|
||||
TEST_ASSERT(hash.exists(1001));
|
||||
TEST_ASSERT(hash.size() == 1);
|
||||
TEST_ASSERT((hash.max_size() == 72000));
|
||||
TEST_ASSERT(!hash.empty());
|
||||
|
||||
Item_Struct item = hash[1001];
|
||||
ItemData item = hash[1001];
|
||||
TEST_ASSERT(strcmp(item.Name, "Steel Sword") == 0);
|
||||
TEST_ASSERT(item.ID == 1001);
|
||||
}
|
||||
|
||||
void InsertAgainTest() {
|
||||
EQEmu::FixedMemoryHashSet<Item_Struct> hash(data_, size_);
|
||||
Item_Struct item;
|
||||
EQEmu::FixedMemoryHashSet<ItemData> hash(data_, size_);
|
||||
ItemData item;
|
||||
memset(&item, 0, sizeof(item));
|
||||
strcpy(item.Name, "Iron Sword");
|
||||
item.ID = 1000;
|
||||
@@ -132,14 +132,14 @@ public:
|
||||
}
|
||||
|
||||
void RetrieveAgainTest() {
|
||||
EQEmu::FixedMemoryHashSet<Item_Struct> hash(data_, size_);
|
||||
EQEmu::FixedMemoryHashSet<ItemData> hash(data_, size_);
|
||||
TEST_ASSERT(hash.exists(1000));
|
||||
TEST_ASSERT(hash.exists(1001));
|
||||
TEST_ASSERT(hash.size() == 2);
|
||||
TEST_ASSERT(hash.max_size() == 72000);
|
||||
TEST_ASSERT(!hash.empty());
|
||||
|
||||
Item_Struct item = hash[1000];
|
||||
ItemData item = hash[1000];
|
||||
TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0);
|
||||
TEST_ASSERT(item.ID == 1000);
|
||||
|
||||
@@ -149,8 +149,8 @@ public:
|
||||
}
|
||||
|
||||
void InsertBeginTest() {
|
||||
EQEmu::FixedMemoryHashSet<Item_Struct> hash(data_, size_);
|
||||
Item_Struct item;
|
||||
EQEmu::FixedMemoryHashSet<ItemData> hash(data_, size_);
|
||||
ItemData item;
|
||||
memset(&item, 0, sizeof(item));
|
||||
strcpy(item.Name, "Bronze Sword");
|
||||
item.ID = 0;
|
||||
@@ -165,7 +165,7 @@ public:
|
||||
}
|
||||
|
||||
void RetrieveBeginTest() {
|
||||
EQEmu::FixedMemoryHashSet<Item_Struct> hash(data_, size_);
|
||||
EQEmu::FixedMemoryHashSet<ItemData> hash(data_, size_);
|
||||
TEST_ASSERT(hash.exists(1000));
|
||||
TEST_ASSERT(hash.exists(1001));
|
||||
TEST_ASSERT(hash.exists(0));
|
||||
@@ -173,7 +173,7 @@ public:
|
||||
TEST_ASSERT(hash.max_size() == 72000);
|
||||
TEST_ASSERT(!hash.empty());
|
||||
|
||||
Item_Struct item = hash[1000];
|
||||
ItemData item = hash[1000];
|
||||
TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0);
|
||||
TEST_ASSERT(item.ID == 1000);
|
||||
|
||||
@@ -187,8 +187,8 @@ public:
|
||||
}
|
||||
|
||||
void InsertEndTest() {
|
||||
EQEmu::FixedMemoryHashSet<Item_Struct> hash(data_, size_);
|
||||
Item_Struct item;
|
||||
EQEmu::FixedMemoryHashSet<ItemData> hash(data_, size_);
|
||||
ItemData item;
|
||||
memset(&item, 0, sizeof(item));
|
||||
strcpy(item.Name, "Jade Sword");
|
||||
item.ID = 190000;
|
||||
@@ -204,7 +204,7 @@ public:
|
||||
}
|
||||
|
||||
void RetrieveEndTest() {
|
||||
EQEmu::FixedMemoryHashSet<Item_Struct> hash(data_, size_);
|
||||
EQEmu::FixedMemoryHashSet<ItemData> hash(data_, size_);
|
||||
TEST_ASSERT(hash.exists(1000));
|
||||
TEST_ASSERT(hash.exists(1001));
|
||||
TEST_ASSERT(hash.exists(0));
|
||||
@@ -213,7 +213,7 @@ public:
|
||||
TEST_ASSERT(hash.max_size() == 72000);
|
||||
TEST_ASSERT(!hash.empty());
|
||||
|
||||
Item_Struct item = hash[1000];
|
||||
ItemData item = hash[1000];
|
||||
TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0);
|
||||
TEST_ASSERT(item.ID == 1000);
|
||||
|
||||
|
||||
@@ -0,0 +1,337 @@
|
||||
/* 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 __EQEMU_TESTS_INVENTORY_H
|
||||
#define __EQEMU_TESTS_INVENTORY_H
|
||||
|
||||
#include "cppunit/cpptest.h"
|
||||
#include "../common/inventory.h"
|
||||
#include <string.h>
|
||||
|
||||
class InventoryTest : public Test::Suite {
|
||||
typedef void(InventoryTest::*TestFunction)(void);
|
||||
public:
|
||||
InventoryTest() : inv(1, 1, 1) {
|
||||
InitContainer();
|
||||
InitArmor();
|
||||
InitAugment();
|
||||
InitStackable();
|
||||
InitInventory();
|
||||
TEST_ADD(InventoryTest::InventoryVerifyInitialItemsTest);
|
||||
TEST_ADD(InventoryTest::InventoryCanEquipTest);
|
||||
TEST_ADD(InventoryTest::InventorySwapGeneral1ToCursor);
|
||||
TEST_ADD(InventoryTest::InventorySwapCursorToGeneral2);
|
||||
TEST_ADD(InventoryTest::InventorySplitStackToCursor);
|
||||
TEST_ADD(InventoryTest::InventoryStackCombine);
|
||||
TEST_ADD(InventoryTest::InventorySplitStackToCursor2);
|
||||
TEST_ADD(InventoryTest::InventoryStackCombine2);
|
||||
}
|
||||
|
||||
~InventoryTest() {
|
||||
}
|
||||
|
||||
private:
|
||||
void InitContainer() {
|
||||
memset(&container, 0, sizeof(container));
|
||||
strcpy(container.Name, "Backpack");
|
||||
strcpy(container.IDFile, "IT64");
|
||||
container.ID = 1000;
|
||||
container.BagSize = 3;
|
||||
container.BagSlots = 8;
|
||||
container.BagType = 5;
|
||||
container.BagWR = 50;
|
||||
container.ItemClass = 1;
|
||||
container.Classes = 65535U;
|
||||
container.Focus.Effect = -1;
|
||||
container.ItemType = 11;
|
||||
container.NoDrop = 1;
|
||||
container.NoRent = 1;
|
||||
container.Races = 131071U;
|
||||
container.Size = 3;
|
||||
container.SkillModType = -1;
|
||||
container.Click.Effect = -1;
|
||||
container.Weight = 30;
|
||||
container.StackSize = 1;
|
||||
container.Proc.Effect = -1;
|
||||
container.Worn.Effect = -1;
|
||||
container.Scroll.Effect = -1;
|
||||
}
|
||||
|
||||
void InitArmor() {
|
||||
memset(&armor, 0, sizeof(armor));
|
||||
strcpy(armor.Name, "Cloth Shirt");
|
||||
strcpy(armor.IDFile, "IT64");
|
||||
armor.ID = 1001;
|
||||
armor.AC = 4;
|
||||
armor.AugSlotType[0] = 7;
|
||||
for(int i = 0; i < 6; ++i)
|
||||
armor.AugSlotVisible[i] = 1;
|
||||
armor.Size = 2;
|
||||
armor.Slots = 131072;
|
||||
armor.Classes = 65535U;
|
||||
armor.Focus.Effect = -1;
|
||||
armor.ItemType = 10;
|
||||
armor.NoDrop = 1;
|
||||
armor.NoRent = 1;
|
||||
armor.Races = 131071U;
|
||||
armor.SkillModType = -1;
|
||||
armor.Click.Effect = -1;
|
||||
armor.Weight = 8;
|
||||
armor.StackSize = 1;
|
||||
armor.Proc.Effect = -1;
|
||||
armor.Worn.Effect = -1;
|
||||
armor.Scroll.Effect = -1;
|
||||
}
|
||||
|
||||
void InitAugment() {
|
||||
memset(&augment, 0, sizeof(augment));
|
||||
strcpy(augment.Name, "Cloth Augment");
|
||||
strcpy(augment.IDFile, "IT64");
|
||||
augment.ID = 1002;
|
||||
augment.AWis = 10;
|
||||
augment.AInt = 10;
|
||||
augment.AugType = 64;
|
||||
augment.Slots = 2072574;
|
||||
augment.Classes = 65535U;
|
||||
augment.Focus.Effect = -1;
|
||||
augment.ItemType = 54;
|
||||
augment.NoDrop = 1;
|
||||
augment.NoRent = 1;
|
||||
augment.Races = 131071U;
|
||||
augment.SkillModType = -1;
|
||||
augment.Click.Effect = -1;
|
||||
augment.Weight = 5;
|
||||
augment.StackSize = 1;
|
||||
augment.Size = 1;
|
||||
augment.Proc.Effect = -1;
|
||||
augment.Worn.Effect = -1;
|
||||
augment.Scroll.Effect = -1;
|
||||
}
|
||||
|
||||
void InitStackable() {
|
||||
memset(&stackable, 0, sizeof(stackable));
|
||||
strcpy(stackable.Name, "Stackable Item");
|
||||
strcpy(stackable.IDFile, "IT64");
|
||||
stackable.ID = 1003;
|
||||
stackable.Classes = 65535U;
|
||||
stackable.Focus.Effect = -1;
|
||||
stackable.ItemType = 54;
|
||||
stackable.NoDrop = 1;
|
||||
stackable.NoRent = 1;
|
||||
stackable.Races = 131071U;
|
||||
stackable.SkillModType = -1;
|
||||
stackable.Click.Effect = -1;
|
||||
stackable.Weight = 5;
|
||||
stackable.StackSize = 105;
|
||||
stackable.Stackable = 1;
|
||||
stackable.Size = 1;
|
||||
stackable.Proc.Effect = -1;
|
||||
stackable.Worn.Effect = -1;
|
||||
stackable.Scroll.Effect = -1;
|
||||
}
|
||||
|
||||
void InitInventory()
|
||||
{
|
||||
EQEmu::ItemInstance::pointer m_bag(new EQEmu::ItemInstance(&container));
|
||||
EQEmu::ItemInstance::pointer m_armor(new EQEmu::ItemInstance(&armor));
|
||||
EQEmu::ItemInstance::pointer m_augment(new EQEmu::ItemInstance(&augment));
|
||||
EQEmu::ItemInstance::pointer m_stackable(new EQEmu::ItemInstance(&stackable, 100));
|
||||
inv.Put(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral1), m_bag);
|
||||
inv.Put(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral1, 0), m_armor);
|
||||
inv.Put(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral1, 1), m_augment);
|
||||
inv.Put(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral1, 7), m_stackable);
|
||||
}
|
||||
|
||||
void InventoryVerifyInitialItemsTest()
|
||||
{
|
||||
auto m_bag = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral1));
|
||||
TEST_ASSERT(m_bag);
|
||||
TEST_ASSERT(m_bag->GetItem());
|
||||
TEST_ASSERT(m_bag->GetItem()->ID == 1000);
|
||||
|
||||
auto m_armor = m_bag->Get(0);
|
||||
TEST_ASSERT(m_armor);
|
||||
TEST_ASSERT(m_armor->GetItem());
|
||||
TEST_ASSERT(m_armor->GetItem()->ID == 1001);
|
||||
|
||||
auto m_augment = m_bag->Get(1);
|
||||
TEST_ASSERT(m_augment);
|
||||
TEST_ASSERT(m_augment->GetItem());
|
||||
TEST_ASSERT(m_augment->GetItem()->ID == 1002);
|
||||
|
||||
auto m_stackable = m_bag->Get(7);
|
||||
TEST_ASSERT(m_stackable);
|
||||
TEST_ASSERT(m_stackable->GetItem());
|
||||
TEST_ASSERT(m_stackable->GetItem()->ID == 1003);
|
||||
}
|
||||
|
||||
void InventoryCanEquipTest() {
|
||||
auto m_bag = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral1));
|
||||
TEST_ASSERT(m_bag);
|
||||
TEST_ASSERT(m_bag->GetItem());
|
||||
TEST_ASSERT(m_bag->GetItem()->ID == 1000);
|
||||
|
||||
auto m_armor = m_bag->Get(0);
|
||||
TEST_ASSERT(m_armor);
|
||||
TEST_ASSERT(m_armor->GetItem());
|
||||
TEST_ASSERT(m_armor->GetItem()->ID == 1001);
|
||||
|
||||
auto can_equip = inv.CanEquip(m_armor, EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotChest));
|
||||
TEST_ASSERT(can_equip);
|
||||
|
||||
can_equip = inv.CanEquip(m_armor, EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotWaist));
|
||||
TEST_ASSERT(!can_equip);
|
||||
|
||||
armor.Classes -= 1;
|
||||
can_equip = inv.CanEquip(m_armor, EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotChest));
|
||||
TEST_ASSERT(!can_equip);
|
||||
armor.Classes += 1;
|
||||
|
||||
armor.Races -= 1;
|
||||
can_equip = inv.CanEquip(m_armor, EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotChest));
|
||||
TEST_ASSERT(!can_equip);
|
||||
armor.Races += 1;
|
||||
}
|
||||
|
||||
void InventorySwapGeneral1ToCursor() {
|
||||
auto swap_result = inv.Swap(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral1),
|
||||
EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor), 0);
|
||||
|
||||
TEST_ASSERT(swap_result == true);
|
||||
|
||||
auto m_bag = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor));
|
||||
TEST_ASSERT(m_bag);
|
||||
TEST_ASSERT(m_bag->GetItem());
|
||||
TEST_ASSERT(m_bag->GetItem()->ID == 1000);
|
||||
|
||||
auto m_armor = m_bag->Get(0);
|
||||
TEST_ASSERT(m_armor);
|
||||
TEST_ASSERT(m_armor->GetItem());
|
||||
TEST_ASSERT(m_armor->GetItem()->ID == 1001);
|
||||
|
||||
auto m_augment = m_bag->Get(1);
|
||||
TEST_ASSERT(m_augment);
|
||||
TEST_ASSERT(m_augment->GetItem());
|
||||
TEST_ASSERT(m_augment->GetItem()->ID == 1002);
|
||||
|
||||
auto m_stackable = m_bag->Get(7);
|
||||
TEST_ASSERT(m_stackable);
|
||||
TEST_ASSERT(m_stackable->GetItem());
|
||||
TEST_ASSERT(m_stackable->GetItem()->ID == 1003);
|
||||
}
|
||||
|
||||
void InventorySwapCursorToGeneral2() {
|
||||
auto swap_result = inv.Swap(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor),
|
||||
EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2), 0);
|
||||
|
||||
TEST_ASSERT(swap_result == true);
|
||||
|
||||
auto m_bag = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2));
|
||||
TEST_ASSERT(m_bag);
|
||||
TEST_ASSERT(m_bag->GetItem());
|
||||
TEST_ASSERT(m_bag->GetItem()->ID == 1000);
|
||||
|
||||
auto m_armor = m_bag->Get(0);
|
||||
TEST_ASSERT(m_armor);
|
||||
TEST_ASSERT(m_armor->GetItem());
|
||||
TEST_ASSERT(m_armor->GetItem()->ID == 1001);
|
||||
|
||||
auto m_augment = m_bag->Get(1);
|
||||
TEST_ASSERT(m_augment);
|
||||
TEST_ASSERT(m_augment->GetItem());
|
||||
TEST_ASSERT(m_augment->GetItem()->ID == 1002);
|
||||
|
||||
auto m_stackable = m_bag->Get(7);
|
||||
TEST_ASSERT(m_stackable);
|
||||
TEST_ASSERT(m_stackable->GetItem());
|
||||
TEST_ASSERT(m_stackable->GetItem()->ID == 1003);
|
||||
}
|
||||
|
||||
void InventorySplitStackToCursor() {
|
||||
auto swap_result = inv.Swap(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2, 7),
|
||||
EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor), 10);
|
||||
|
||||
TEST_ASSERT(swap_result == true);
|
||||
|
||||
auto m_stackable_cursor = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor));
|
||||
auto m_stackable = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2, 7));
|
||||
|
||||
TEST_ASSERT(m_stackable_cursor);
|
||||
TEST_ASSERT(m_stackable);
|
||||
|
||||
TEST_ASSERT(m_stackable_cursor->GetCharges() == 10);
|
||||
TEST_ASSERT(m_stackable->GetCharges() == 90);
|
||||
}
|
||||
|
||||
void InventoryStackCombine() {
|
||||
auto swap_result = inv.Swap(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor),
|
||||
EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2, 7), 0);
|
||||
|
||||
TEST_ASSERT(swap_result == true);
|
||||
|
||||
auto m_cursor = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor));
|
||||
auto m_stackable = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2, 7));
|
||||
|
||||
TEST_ASSERT(!m_cursor);
|
||||
TEST_ASSERT(m_stackable);
|
||||
|
||||
TEST_ASSERT(m_stackable->GetCharges() == 100);
|
||||
}
|
||||
|
||||
void InventorySplitStackToCursor2() {
|
||||
EQEmu::ItemInstance::pointer m_stackable_i(new EQEmu::ItemInstance(&stackable, 10));
|
||||
inv.Put(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2, 8), m_stackable_i);
|
||||
|
||||
auto swap_result = inv.Swap(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2, 8),
|
||||
EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor), 0);
|
||||
|
||||
TEST_ASSERT(swap_result == true);
|
||||
|
||||
auto m_stackable_cursor = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor));
|
||||
auto m_stackable = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2, 8));
|
||||
|
||||
TEST_ASSERT(m_stackable_cursor);
|
||||
TEST_ASSERT(!m_stackable);
|
||||
|
||||
TEST_ASSERT(m_stackable_cursor->GetCharges() == 10);
|
||||
}
|
||||
|
||||
void InventoryStackCombine2() {
|
||||
auto swap_result = inv.Swap(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor),
|
||||
EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2, 7), 5);
|
||||
|
||||
TEST_ASSERT(swap_result == true);
|
||||
|
||||
auto m_cursor = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor));
|
||||
auto m_stackable = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2, 7));
|
||||
|
||||
TEST_ASSERT(m_cursor);
|
||||
TEST_ASSERT(m_stackable);
|
||||
|
||||
TEST_ASSERT(m_stackable->GetCharges() == 105);
|
||||
TEST_ASSERT(m_cursor->GetCharges() == 5);
|
||||
}
|
||||
|
||||
EQEmu::Inventory inv;
|
||||
ItemData container;
|
||||
ItemData armor;
|
||||
ItemData augment;
|
||||
ItemData stackable;
|
||||
};
|
||||
|
||||
#endif
|
||||
+8
-1
@@ -20,6 +20,7 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include "../common/eqemu_logsys.h"
|
||||
#include "memory_mapped_file_test.h"
|
||||
#include "ipc_mutex_test.h"
|
||||
#include "fixed_memory_test.h"
|
||||
@@ -29,6 +30,10 @@
|
||||
#include "string_util_test.h"
|
||||
#include "data_verification_test.h"
|
||||
#include "skills_util_test.h"
|
||||
#include "inventory_test.h"
|
||||
#include "memory_buffer_test.h"
|
||||
|
||||
EQEmuLogSys Log;
|
||||
|
||||
int main() {
|
||||
try {
|
||||
@@ -44,7 +49,9 @@ int main() {
|
||||
tests.add(new StringUtilTest());
|
||||
tests.add(new DataVerificationTest());
|
||||
tests.add(new SkillsUtilsTest());
|
||||
tests.run(*output, true);
|
||||
tests.add(new InventoryTest());
|
||||
tests.add(new MemoryBufferTest());
|
||||
tests.run(*output, false);
|
||||
} catch(...) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,605 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2013 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 __EQEMU_TESTS_MEMORY_BUFFER_H
|
||||
#define __EQEMU_TESTS_MEMORY_BUFFER_H
|
||||
|
||||
#include "cppunit/cpptest.h"
|
||||
#include "../common/memory_buffer.h"
|
||||
|
||||
class MemoryBufferTest : public Test::Suite {
|
||||
typedef void(MemoryBufferTest::*TestFunction)(void);
|
||||
public:
|
||||
MemoryBufferTest() {
|
||||
TEST_ADD(MemoryBufferTest::WriteTest);
|
||||
TEST_ADD(MemoryBufferTest::ReadTest);
|
||||
TEST_ADD(MemoryBufferTest::ConvertTest);
|
||||
TEST_ADD(MemoryBufferTest::ResizeTest);
|
||||
TEST_ADD(MemoryBufferTest::CopyTest);
|
||||
TEST_ADD(MemoryBufferTest::AssignTest);
|
||||
TEST_ADD(MemoryBufferTest::MoveTest);
|
||||
TEST_ADD(MemoryBufferTest::SelfTest);
|
||||
TEST_ADD(MemoryBufferTest::ZeroTest);
|
||||
TEST_ADD(MemoryBufferTest::ClearTest);
|
||||
TEST_ADD(MemoryBufferTest::AddTest)
|
||||
}
|
||||
|
||||
~MemoryBufferTest() {
|
||||
}
|
||||
|
||||
private:
|
||||
void WriteTest() {
|
||||
uint8 a = 0;
|
||||
uint16 b = 5 ;
|
||||
uint32 c = 10;
|
||||
uint64 d = 15;
|
||||
std::string s2 = "test2";
|
||||
|
||||
mb.Write(a);
|
||||
mb.Write(b);
|
||||
mb.Write(c);
|
||||
mb.Write(d);
|
||||
mb.Write("test1");
|
||||
mb.Write(s2);
|
||||
|
||||
TEST_ASSERT(mb.Size() == 27);
|
||||
|
||||
uchar *data = (uchar*)mb;
|
||||
TEST_ASSERT(data != nullptr);
|
||||
TEST_ASSERT(data[0] == 0);
|
||||
TEST_ASSERT(data[1] == 5);
|
||||
TEST_ASSERT(data[2] == 0);
|
||||
TEST_ASSERT(data[3] == 10);
|
||||
TEST_ASSERT(data[4] == 0);
|
||||
TEST_ASSERT(data[5] == 0);
|
||||
TEST_ASSERT(data[6] == 0);
|
||||
TEST_ASSERT(data[7] == 15);
|
||||
TEST_ASSERT(data[8] == 0);
|
||||
TEST_ASSERT(data[9] == 0);
|
||||
TEST_ASSERT(data[10] == 0);
|
||||
TEST_ASSERT(data[11] == 0);
|
||||
TEST_ASSERT(data[12] == 0);
|
||||
TEST_ASSERT(data[13] == 0);
|
||||
TEST_ASSERT(data[14] == 0);
|
||||
TEST_ASSERT(data[15] == 't');
|
||||
TEST_ASSERT(data[16] == 'e');
|
||||
TEST_ASSERT(data[17] == 's');
|
||||
TEST_ASSERT(data[18] == 't');
|
||||
TEST_ASSERT(data[19] == '1');
|
||||
TEST_ASSERT(data[20] == 0);
|
||||
TEST_ASSERT(data[21] == 't');
|
||||
TEST_ASSERT(data[22] == 'e');
|
||||
TEST_ASSERT(data[23] == 's');
|
||||
TEST_ASSERT(data[24] == 't');
|
||||
TEST_ASSERT(data[25] == '2');
|
||||
TEST_ASSERT(data[26] == 0);
|
||||
}
|
||||
|
||||
void ReadTest() {
|
||||
uint8 a = mb.Read<uint8>();
|
||||
uint16 b = mb.Read<uint16>();
|
||||
uint32 c = mb.Read<uint32>();
|
||||
uint64 d = mb.Read<uint64>();
|
||||
std::string s1 = mb.ReadString();
|
||||
std::string s2 = mb.ReadString();
|
||||
|
||||
TEST_ASSERT(a == 0);
|
||||
TEST_ASSERT(b == 5);
|
||||
TEST_ASSERT(c == 10);
|
||||
TEST_ASSERT(d == 15);
|
||||
TEST_ASSERT(s1.compare("test1") == 0);
|
||||
TEST_ASSERT(s2.compare("test2") == 0);
|
||||
}
|
||||
|
||||
#pragma pack(1)
|
||||
struct ConvertStruct
|
||||
{
|
||||
uint8 a;
|
||||
uint16 b;
|
||||
uint32 c;
|
||||
uint64 d;
|
||||
char test1[6];
|
||||
char test2[6];
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
void ConvertTest()
|
||||
{
|
||||
uchar *v1 = mb;
|
||||
char *v2 = mb;
|
||||
ConvertStruct *cs = (ConvertStruct*)mb;
|
||||
|
||||
TEST_ASSERT(v1 != nullptr);
|
||||
TEST_ASSERT(v1[0] == 0);
|
||||
TEST_ASSERT(v1[1] == 5);
|
||||
TEST_ASSERT(v1[2] == 0);
|
||||
TEST_ASSERT(v1[3] == 10);
|
||||
TEST_ASSERT(v1[4] == 0);
|
||||
TEST_ASSERT(v1[5] == 0);
|
||||
TEST_ASSERT(v1[6] == 0);
|
||||
TEST_ASSERT(v1[7] == 15);
|
||||
TEST_ASSERT(v1[8] == 0);
|
||||
TEST_ASSERT(v1[9] == 0);
|
||||
TEST_ASSERT(v1[10] == 0);
|
||||
TEST_ASSERT(v1[11] == 0);
|
||||
TEST_ASSERT(v1[12] == 0);
|
||||
TEST_ASSERT(v1[13] == 0);
|
||||
TEST_ASSERT(v1[14] == 0);
|
||||
TEST_ASSERT(v1[15] == 't');
|
||||
TEST_ASSERT(v1[16] == 'e');
|
||||
TEST_ASSERT(v1[17] == 's');
|
||||
TEST_ASSERT(v1[18] == 't');
|
||||
TEST_ASSERT(v1[19] == '1');
|
||||
TEST_ASSERT(v1[20] == 0);
|
||||
TEST_ASSERT(v1[21] == 't');
|
||||
TEST_ASSERT(v1[22] == 'e');
|
||||
TEST_ASSERT(v1[23] == 's');
|
||||
TEST_ASSERT(v1[24] == 't');
|
||||
TEST_ASSERT(v1[25] == '2');
|
||||
TEST_ASSERT(v1[26] == 0);
|
||||
|
||||
TEST_ASSERT(v2 != nullptr);
|
||||
TEST_ASSERT(v2[0] == 0);
|
||||
TEST_ASSERT(v2[1] == 5);
|
||||
TEST_ASSERT(v2[2] == 0);
|
||||
TEST_ASSERT(v2[3] == 10);
|
||||
TEST_ASSERT(v2[4] == 0);
|
||||
TEST_ASSERT(v2[5] == 0);
|
||||
TEST_ASSERT(v2[6] == 0);
|
||||
TEST_ASSERT(v2[7] == 15);
|
||||
TEST_ASSERT(v2[8] == 0);
|
||||
TEST_ASSERT(v2[9] == 0);
|
||||
TEST_ASSERT(v2[10] == 0);
|
||||
TEST_ASSERT(v2[11] == 0);
|
||||
TEST_ASSERT(v2[12] == 0);
|
||||
TEST_ASSERT(v2[13] == 0);
|
||||
TEST_ASSERT(v2[14] == 0);
|
||||
TEST_ASSERT(v2[15] == 't');
|
||||
TEST_ASSERT(v2[16] == 'e');
|
||||
TEST_ASSERT(v2[17] == 's');
|
||||
TEST_ASSERT(v2[18] == 't');
|
||||
TEST_ASSERT(v2[19] == '1');
|
||||
TEST_ASSERT(v2[20] == 0);
|
||||
TEST_ASSERT(v2[21] == 't');
|
||||
TEST_ASSERT(v2[22] == 'e');
|
||||
TEST_ASSERT(v2[23] == 's');
|
||||
TEST_ASSERT(v2[24] == 't');
|
||||
TEST_ASSERT(v2[25] == '2');
|
||||
TEST_ASSERT(v2[26] == 0);
|
||||
|
||||
TEST_ASSERT(cs != nullptr);
|
||||
TEST_ASSERT(cs->a == 0);
|
||||
TEST_ASSERT(cs->b == 5);
|
||||
TEST_ASSERT(cs->c == 10);
|
||||
TEST_ASSERT(cs->d == 15);
|
||||
TEST_ASSERT(strcmp(cs->test1, "test1") == 0);
|
||||
TEST_ASSERT(strcmp(cs->test2, "test2") == 0);
|
||||
}
|
||||
|
||||
void ResizeTest()
|
||||
{
|
||||
mb.Resize(21);
|
||||
TEST_ASSERT(mb.Size() == 21);
|
||||
|
||||
mb.Resize(27);
|
||||
uchar *data = (uchar*)mb;
|
||||
TEST_ASSERT(data != nullptr);
|
||||
TEST_ASSERT(data[21] == 't');
|
||||
TEST_ASSERT(data[22] == 'e');
|
||||
TEST_ASSERT(data[23] == 's');
|
||||
TEST_ASSERT(data[24] == 't');
|
||||
TEST_ASSERT(data[25] == '2');
|
||||
TEST_ASSERT(data[26] == 0);
|
||||
|
||||
mb.Resize(40);
|
||||
data = (uchar*)mb;
|
||||
TEST_ASSERT(data != nullptr);
|
||||
TEST_ASSERT(mb.Capacity() >= 40);
|
||||
TEST_ASSERT(mb.Size() == 40);
|
||||
TEST_ASSERT(data[0] == 0);
|
||||
TEST_ASSERT(data[1] == 5);
|
||||
TEST_ASSERT(data[2] == 0);
|
||||
TEST_ASSERT(data[3] == 10);
|
||||
TEST_ASSERT(data[4] == 0);
|
||||
TEST_ASSERT(data[5] == 0);
|
||||
TEST_ASSERT(data[6] == 0);
|
||||
TEST_ASSERT(data[7] == 15);
|
||||
TEST_ASSERT(data[8] == 0);
|
||||
TEST_ASSERT(data[9] == 0);
|
||||
TEST_ASSERT(data[10] == 0);
|
||||
TEST_ASSERT(data[11] == 0);
|
||||
TEST_ASSERT(data[12] == 0);
|
||||
TEST_ASSERT(data[13] == 0);
|
||||
TEST_ASSERT(data[14] == 0);
|
||||
TEST_ASSERT(data[15] == 't');
|
||||
TEST_ASSERT(data[16] == 'e');
|
||||
TEST_ASSERT(data[17] == 's');
|
||||
TEST_ASSERT(data[18] == 't');
|
||||
TEST_ASSERT(data[19] == '1');
|
||||
TEST_ASSERT(data[20] == 0);
|
||||
TEST_ASSERT(data[21] == 't');
|
||||
TEST_ASSERT(data[22] == 'e');
|
||||
TEST_ASSERT(data[23] == 's');
|
||||
TEST_ASSERT(data[24] == 't');
|
||||
TEST_ASSERT(data[25] == '2');
|
||||
TEST_ASSERT(data[26] == 0);
|
||||
}
|
||||
|
||||
void CopyTest()
|
||||
{
|
||||
EQEmu::MemoryBuffer mb2(mb);
|
||||
|
||||
uchar *data = (uchar*)mb2;
|
||||
TEST_ASSERT(data != nullptr);
|
||||
TEST_ASSERT(mb.Size() == 40);
|
||||
TEST_ASSERT(data[0] == 0);
|
||||
TEST_ASSERT(data[1] == 5);
|
||||
TEST_ASSERT(data[2] == 0);
|
||||
TEST_ASSERT(data[3] == 10);
|
||||
TEST_ASSERT(data[4] == 0);
|
||||
TEST_ASSERT(data[5] == 0);
|
||||
TEST_ASSERT(data[6] == 0);
|
||||
TEST_ASSERT(data[7] == 15);
|
||||
TEST_ASSERT(data[8] == 0);
|
||||
TEST_ASSERT(data[9] == 0);
|
||||
TEST_ASSERT(data[10] == 0);
|
||||
TEST_ASSERT(data[11] == 0);
|
||||
TEST_ASSERT(data[12] == 0);
|
||||
TEST_ASSERT(data[13] == 0);
|
||||
TEST_ASSERT(data[14] == 0);
|
||||
TEST_ASSERT(data[15] == 't');
|
||||
TEST_ASSERT(data[16] == 'e');
|
||||
TEST_ASSERT(data[17] == 's');
|
||||
TEST_ASSERT(data[18] == 't');
|
||||
TEST_ASSERT(data[19] == '1');
|
||||
TEST_ASSERT(data[20] == 0);
|
||||
TEST_ASSERT(data[21] == 't');
|
||||
TEST_ASSERT(data[22] == 'e');
|
||||
TEST_ASSERT(data[23] == 's');
|
||||
TEST_ASSERT(data[24] == 't');
|
||||
TEST_ASSERT(data[25] == '2');
|
||||
TEST_ASSERT(data[26] == 0);
|
||||
|
||||
data = (uchar*)mb;
|
||||
TEST_ASSERT(data != nullptr);
|
||||
TEST_ASSERT(mb.Size() == 40);
|
||||
TEST_ASSERT(data[0] == 0);
|
||||
TEST_ASSERT(data[1] == 5);
|
||||
TEST_ASSERT(data[2] == 0);
|
||||
TEST_ASSERT(data[3] == 10);
|
||||
TEST_ASSERT(data[4] == 0);
|
||||
TEST_ASSERT(data[5] == 0);
|
||||
TEST_ASSERT(data[6] == 0);
|
||||
TEST_ASSERT(data[7] == 15);
|
||||
TEST_ASSERT(data[8] == 0);
|
||||
TEST_ASSERT(data[9] == 0);
|
||||
TEST_ASSERT(data[10] == 0);
|
||||
TEST_ASSERT(data[11] == 0);
|
||||
TEST_ASSERT(data[12] == 0);
|
||||
TEST_ASSERT(data[13] == 0);
|
||||
TEST_ASSERT(data[14] == 0);
|
||||
TEST_ASSERT(data[15] == 't');
|
||||
TEST_ASSERT(data[16] == 'e');
|
||||
TEST_ASSERT(data[17] == 's');
|
||||
TEST_ASSERT(data[18] == 't');
|
||||
TEST_ASSERT(data[19] == '1');
|
||||
TEST_ASSERT(data[20] == 0);
|
||||
TEST_ASSERT(data[21] == 't');
|
||||
TEST_ASSERT(data[22] == 'e');
|
||||
TEST_ASSERT(data[23] == 's');
|
||||
TEST_ASSERT(data[24] == 't');
|
||||
TEST_ASSERT(data[25] == '2');
|
||||
TEST_ASSERT(data[26] == 0);
|
||||
TEST_ASSERT((void*)mb != (void*)mb2);
|
||||
}
|
||||
|
||||
void AssignTest()
|
||||
{
|
||||
EQEmu::MemoryBuffer mb2 = mb;
|
||||
|
||||
uchar *data = (uchar*)mb2;
|
||||
TEST_ASSERT(data != nullptr);
|
||||
TEST_ASSERT(mb.Size() == 40);
|
||||
TEST_ASSERT(data[0] == 0);
|
||||
TEST_ASSERT(data[1] == 5);
|
||||
TEST_ASSERT(data[2] == 0);
|
||||
TEST_ASSERT(data[3] == 10);
|
||||
TEST_ASSERT(data[4] == 0);
|
||||
TEST_ASSERT(data[5] == 0);
|
||||
TEST_ASSERT(data[6] == 0);
|
||||
TEST_ASSERT(data[7] == 15);
|
||||
TEST_ASSERT(data[8] == 0);
|
||||
TEST_ASSERT(data[9] == 0);
|
||||
TEST_ASSERT(data[10] == 0);
|
||||
TEST_ASSERT(data[11] == 0);
|
||||
TEST_ASSERT(data[12] == 0);
|
||||
TEST_ASSERT(data[13] == 0);
|
||||
TEST_ASSERT(data[14] == 0);
|
||||
TEST_ASSERT(data[15] == 't');
|
||||
TEST_ASSERT(data[16] == 'e');
|
||||
TEST_ASSERT(data[17] == 's');
|
||||
TEST_ASSERT(data[18] == 't');
|
||||
TEST_ASSERT(data[19] == '1');
|
||||
TEST_ASSERT(data[20] == 0);
|
||||
TEST_ASSERT(data[21] == 't');
|
||||
TEST_ASSERT(data[22] == 'e');
|
||||
TEST_ASSERT(data[23] == 's');
|
||||
TEST_ASSERT(data[24] == 't');
|
||||
TEST_ASSERT(data[25] == '2');
|
||||
TEST_ASSERT(data[26] == 0);
|
||||
|
||||
data = (uchar*)mb;
|
||||
TEST_ASSERT(data != nullptr);
|
||||
TEST_ASSERT(mb.Size() == 40);
|
||||
TEST_ASSERT(data[0] == 0);
|
||||
TEST_ASSERT(data[1] == 5);
|
||||
TEST_ASSERT(data[2] == 0);
|
||||
TEST_ASSERT(data[3] == 10);
|
||||
TEST_ASSERT(data[4] == 0);
|
||||
TEST_ASSERT(data[5] == 0);
|
||||
TEST_ASSERT(data[6] == 0);
|
||||
TEST_ASSERT(data[7] == 15);
|
||||
TEST_ASSERT(data[8] == 0);
|
||||
TEST_ASSERT(data[9] == 0);
|
||||
TEST_ASSERT(data[10] == 0);
|
||||
TEST_ASSERT(data[11] == 0);
|
||||
TEST_ASSERT(data[12] == 0);
|
||||
TEST_ASSERT(data[13] == 0);
|
||||
TEST_ASSERT(data[14] == 0);
|
||||
TEST_ASSERT(data[15] == 't');
|
||||
TEST_ASSERT(data[16] == 'e');
|
||||
TEST_ASSERT(data[17] == 's');
|
||||
TEST_ASSERT(data[18] == 't');
|
||||
TEST_ASSERT(data[19] == '1');
|
||||
TEST_ASSERT(data[20] == 0);
|
||||
TEST_ASSERT(data[21] == 't');
|
||||
TEST_ASSERT(data[22] == 'e');
|
||||
TEST_ASSERT(data[23] == 's');
|
||||
TEST_ASSERT(data[24] == 't');
|
||||
TEST_ASSERT(data[25] == '2');
|
||||
TEST_ASSERT(data[26] == 0);
|
||||
TEST_ASSERT((void*)mb != (void*)mb2);
|
||||
}
|
||||
|
||||
void MoveTest()
|
||||
{
|
||||
EQEmu::MemoryBuffer mb2 = std::move(mb);
|
||||
uchar *data = (uchar*)mb;
|
||||
uchar *data2 = (uchar*)mb2;
|
||||
TEST_ASSERT(data == nullptr);
|
||||
TEST_ASSERT(data2 != nullptr);
|
||||
TEST_ASSERT(mb.Size() == 0);
|
||||
TEST_ASSERT(mb2.Size() == 40);
|
||||
TEST_ASSERT(data2[0] == 0);
|
||||
TEST_ASSERT(data2[1] == 5);
|
||||
TEST_ASSERT(data2[2] == 0);
|
||||
TEST_ASSERT(data2[3] == 10);
|
||||
TEST_ASSERT(data2[4] == 0);
|
||||
TEST_ASSERT(data2[5] == 0);
|
||||
TEST_ASSERT(data2[6] == 0);
|
||||
TEST_ASSERT(data2[7] == 15);
|
||||
TEST_ASSERT(data2[8] == 0);
|
||||
TEST_ASSERT(data2[9] == 0);
|
||||
TEST_ASSERT(data2[10] == 0);
|
||||
TEST_ASSERT(data2[11] == 0);
|
||||
TEST_ASSERT(data2[12] == 0);
|
||||
TEST_ASSERT(data2[13] == 0);
|
||||
TEST_ASSERT(data2[14] == 0);
|
||||
TEST_ASSERT(data2[15] == 't');
|
||||
TEST_ASSERT(data2[16] == 'e');
|
||||
TEST_ASSERT(data2[17] == 's');
|
||||
TEST_ASSERT(data2[18] == 't');
|
||||
TEST_ASSERT(data2[19] == '1');
|
||||
TEST_ASSERT(data2[20] == 0);
|
||||
TEST_ASSERT(data2[21] == 't');
|
||||
TEST_ASSERT(data2[22] == 'e');
|
||||
TEST_ASSERT(data2[23] == 's');
|
||||
TEST_ASSERT(data2[24] == 't');
|
||||
TEST_ASSERT(data2[25] == '2');
|
||||
TEST_ASSERT(data2[26] == 0);
|
||||
|
||||
mb = std::move(mb2);
|
||||
|
||||
data = (uchar*)mb;
|
||||
data2 = (uchar*)mb2;
|
||||
TEST_ASSERT(data != nullptr);
|
||||
TEST_ASSERT(data2 == nullptr);
|
||||
TEST_ASSERT(mb.Size() == 40);
|
||||
TEST_ASSERT(mb2.Size() == 0);
|
||||
TEST_ASSERT(data[0] == 0);
|
||||
TEST_ASSERT(data[1] == 5);
|
||||
TEST_ASSERT(data[2] == 0);
|
||||
TEST_ASSERT(data[3] == 10);
|
||||
TEST_ASSERT(data[4] == 0);
|
||||
TEST_ASSERT(data[5] == 0);
|
||||
TEST_ASSERT(data[6] == 0);
|
||||
TEST_ASSERT(data[7] == 15);
|
||||
TEST_ASSERT(data[8] == 0);
|
||||
TEST_ASSERT(data[9] == 0);
|
||||
TEST_ASSERT(data[10] == 0);
|
||||
TEST_ASSERT(data[11] == 0);
|
||||
TEST_ASSERT(data[12] == 0);
|
||||
TEST_ASSERT(data[13] == 0);
|
||||
TEST_ASSERT(data[14] == 0);
|
||||
TEST_ASSERT(data[15] == 't');
|
||||
TEST_ASSERT(data[16] == 'e');
|
||||
TEST_ASSERT(data[17] == 's');
|
||||
TEST_ASSERT(data[18] == 't');
|
||||
TEST_ASSERT(data[19] == '1');
|
||||
TEST_ASSERT(data[20] == 0);
|
||||
TEST_ASSERT(data[21] == 't');
|
||||
TEST_ASSERT(data[22] == 'e');
|
||||
TEST_ASSERT(data[23] == 's');
|
||||
TEST_ASSERT(data[24] == 't');
|
||||
TEST_ASSERT(data[25] == '2');
|
||||
TEST_ASSERT(data[26] == 0);
|
||||
}
|
||||
|
||||
void SelfTest()
|
||||
{
|
||||
EQEmu::MemoryBuffer mb2(mb);
|
||||
void *addr = (void*)mb2;
|
||||
|
||||
mb2 = mb2;
|
||||
void *addr2 = (void*)mb2;
|
||||
|
||||
TEST_ASSERT(addr == addr2);
|
||||
|
||||
mb2 = std::move(mb2);
|
||||
addr2 = (void*)mb2;
|
||||
|
||||
TEST_ASSERT(addr2 != nullptr);
|
||||
}
|
||||
|
||||
void ZeroTest()
|
||||
{
|
||||
mb.Zero();
|
||||
uchar *data = (uchar*)mb;
|
||||
TEST_ASSERT(data != nullptr);
|
||||
TEST_ASSERT(mb.Size() == 40);
|
||||
TEST_ASSERT(data[0] == 0);
|
||||
TEST_ASSERT(data[1] == 0);
|
||||
TEST_ASSERT(data[2] == 0);
|
||||
TEST_ASSERT(data[3] == 0);
|
||||
TEST_ASSERT(data[4] == 0);
|
||||
TEST_ASSERT(data[5] == 0);
|
||||
TEST_ASSERT(data[6] == 0);
|
||||
TEST_ASSERT(data[7] == 0);
|
||||
TEST_ASSERT(data[8] == 0);
|
||||
TEST_ASSERT(data[9] == 0);
|
||||
TEST_ASSERT(data[10] == 0);
|
||||
TEST_ASSERT(data[11] == 0);
|
||||
TEST_ASSERT(data[12] == 0);
|
||||
TEST_ASSERT(data[13] == 0);
|
||||
TEST_ASSERT(data[14] == 0);
|
||||
TEST_ASSERT(data[15] == 0);
|
||||
TEST_ASSERT(data[16] == 0);
|
||||
TEST_ASSERT(data[17] == 0);
|
||||
TEST_ASSERT(data[18] == 0);
|
||||
TEST_ASSERT(data[19] == 0);
|
||||
TEST_ASSERT(data[20] == 0);
|
||||
TEST_ASSERT(data[21] == 0);
|
||||
TEST_ASSERT(data[22] == 0);
|
||||
TEST_ASSERT(data[23] == 0);
|
||||
TEST_ASSERT(data[24] == 0);
|
||||
TEST_ASSERT(data[25] == 0);
|
||||
TEST_ASSERT(data[26] == 0);
|
||||
TEST_ASSERT(data[27] == 0);
|
||||
TEST_ASSERT(data[28] == 0);
|
||||
TEST_ASSERT(data[29] == 0);
|
||||
TEST_ASSERT(data[30] == 0);
|
||||
TEST_ASSERT(data[31] == 0);
|
||||
TEST_ASSERT(data[32] == 0);
|
||||
TEST_ASSERT(data[33] == 0);
|
||||
TEST_ASSERT(data[34] == 0);
|
||||
TEST_ASSERT(data[35] == 0);
|
||||
TEST_ASSERT(data[36] == 0);
|
||||
TEST_ASSERT(data[37] == 0);
|
||||
TEST_ASSERT(data[38] == 0);
|
||||
TEST_ASSERT(data[39] == 0);
|
||||
}
|
||||
|
||||
void ClearTest()
|
||||
{
|
||||
mb.Clear();
|
||||
TEST_ASSERT(!mb);
|
||||
uchar *data = (uchar*)mb;
|
||||
TEST_ASSERT(data == nullptr);
|
||||
}
|
||||
|
||||
void AddTest()
|
||||
{
|
||||
EQEmu::MemoryBuffer mb2;
|
||||
EQEmu::MemoryBuffer mb3;
|
||||
|
||||
mb2 += mb3;
|
||||
|
||||
TEST_ASSERT(!mb2);
|
||||
TEST_ASSERT(mb2.Size() == 0);
|
||||
|
||||
mb2.Write("test1");
|
||||
mb2.Write("test2");
|
||||
|
||||
mb2 += mb3;
|
||||
TEST_ASSERT(mb2);
|
||||
TEST_ASSERT(mb2.Size() == 12);
|
||||
|
||||
uchar *data = (uchar*)mb2;
|
||||
TEST_ASSERT(data != nullptr);
|
||||
TEST_ASSERT(data[0] == 't');
|
||||
TEST_ASSERT(data[1] == 'e');
|
||||
TEST_ASSERT(data[2] == 's');
|
||||
TEST_ASSERT(data[3] == 't');
|
||||
TEST_ASSERT(data[4] == '1');
|
||||
TEST_ASSERT(data[5] == 0);
|
||||
TEST_ASSERT(data[6] == 't');
|
||||
TEST_ASSERT(data[7] == 'e');
|
||||
TEST_ASSERT(data[8] == 's');
|
||||
TEST_ASSERT(data[9] == 't');
|
||||
TEST_ASSERT(data[10] == '2');
|
||||
TEST_ASSERT(data[11] == 0);
|
||||
|
||||
mb3 += mb2;
|
||||
TEST_ASSERT(mb3);
|
||||
TEST_ASSERT(mb3.Size() == 12);
|
||||
|
||||
data = (uchar*)mb3;
|
||||
TEST_ASSERT(data != nullptr);
|
||||
TEST_ASSERT(data[0] == 't');
|
||||
TEST_ASSERT(data[1] == 'e');
|
||||
TEST_ASSERT(data[2] == 's');
|
||||
TEST_ASSERT(data[3] == 't');
|
||||
TEST_ASSERT(data[4] == '1');
|
||||
TEST_ASSERT(data[5] == 0);
|
||||
TEST_ASSERT(data[6] == 't');
|
||||
TEST_ASSERT(data[7] == 'e');
|
||||
TEST_ASSERT(data[8] == 's');
|
||||
TEST_ASSERT(data[9] == 't');
|
||||
TEST_ASSERT(data[10] == '2');
|
||||
TEST_ASSERT(data[11] == 0);
|
||||
|
||||
mb2.Clear();
|
||||
mb3.Clear();
|
||||
|
||||
mb2.Write("test1");
|
||||
mb3.Write("test2");
|
||||
|
||||
mb2 += mb3;
|
||||
TEST_ASSERT(mb2);
|
||||
TEST_ASSERT(mb2.Size() == 12);
|
||||
|
||||
data = (uchar*)mb2;
|
||||
TEST_ASSERT(data != nullptr);
|
||||
TEST_ASSERT(data[0] == 't');
|
||||
TEST_ASSERT(data[1] == 'e');
|
||||
TEST_ASSERT(data[2] == 's');
|
||||
TEST_ASSERT(data[3] == 't');
|
||||
TEST_ASSERT(data[4] == '1');
|
||||
TEST_ASSERT(data[5] == 0);
|
||||
TEST_ASSERT(data[6] == 't');
|
||||
TEST_ASSERT(data[7] == 'e');
|
||||
TEST_ASSERT(data[8] == 's');
|
||||
TEST_ASSERT(data[9] == 't');
|
||||
TEST_ASSERT(data[10] == '2');
|
||||
TEST_ASSERT(data[11] == 0);
|
||||
}
|
||||
|
||||
EQEmu::MemoryBuffer mb;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -600,6 +600,16 @@ void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings){
|
||||
log_settings[log_category].log_to_file = atoi(row[3]);
|
||||
log_settings[log_category].log_to_gmsay = atoi(row[4]);
|
||||
|
||||
/* Determine if any output method is enabled for the category
|
||||
and set it to 1 so it can used to check if category is enabled */
|
||||
const bool log_to_console = log_settings[log_category].log_to_console > 0;
|
||||
const bool log_to_file = log_settings[log_category].log_to_file > 0;
|
||||
const bool log_to_gmsay = log_settings[log_category].log_to_gmsay > 0;
|
||||
const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay;
|
||||
|
||||
if (is_category_enabled)
|
||||
log_settings[log_category].is_category_enabled = 1;
|
||||
|
||||
/*
|
||||
This determines whether or not the process needs to actually file log anything.
|
||||
If we go through this whole loop and nothing is set to any debug level, there is no point to create a file or keep anything open
|
||||
|
||||
@@ -129,7 +129,7 @@ OP_GuildInviteAccept=0x78a5
|
||||
OP_GuildDemote=0x3100
|
||||
OP_GuildPromote=0x2945
|
||||
OP_GuildPublicNote=0x3c2c
|
||||
OP_GuildManageBanker=0x096d # Was 0x0737
|
||||
OP_GuildManageBanker=0x389c # Was 0x096d
|
||||
OP_GuildBank=0x2ab0 # Was 0x10c3
|
||||
OP_SetGuildRank=0x3599
|
||||
OP_GuildUpdateURLAndChannel=0x7851
|
||||
@@ -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
|
||||
|
||||
@@ -128,7 +128,7 @@ OP_GuildInviteAccept=0x7053
|
||||
OP_GuildDemote=0x2d4e
|
||||
OP_GuildPromote=0x6a98
|
||||
OP_GuildPublicNote=0x5053
|
||||
OP_GuildManageBanker=0x748f
|
||||
OP_GuildManageBanker=0x3f35
|
||||
OP_GuildBank=0x5134
|
||||
OP_SetGuildRank=0x0b9c
|
||||
OP_GuildUpdateURLAndChannel=0x2958
|
||||
@@ -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
|
||||
@@ -353,21 +354,22 @@ OP_Marquee=0x502e
|
||||
OP_ItemRecastDelay=0x15a9
|
||||
#OP_OpenInventory=0x0000 # Likely does not exist in RoF -U
|
||||
|
||||
OP_DzQuit=0x205f
|
||||
OP_DzListTimers=0x0398
|
||||
OP_DzAddPlayer=0x59ca
|
||||
OP_DzRemovePlayer=0x4701
|
||||
OP_DzSwapPlayer=0x1abc
|
||||
OP_DzMakeLeader=0x405b
|
||||
OP_DzPlayerList=0x543d
|
||||
OP_DzJoinExpeditionConfirm=0x14c6
|
||||
OP_DzJoinExpeditionReply=0x7f4b
|
||||
OP_DzExpeditionInfo=0x4f7e
|
||||
OP_DzExpeditionList=0x9119
|
||||
OP_DzMemberStatus=0xb2e3
|
||||
OP_DzLeaderStatus=0x32f0
|
||||
# Expeditions
|
||||
OP_DzAddPlayer=0x4701
|
||||
OP_DzRemovePlayer=0x1abc
|
||||
OP_DzSwapPlayer=0x405b
|
||||
OP_DzMakeLeader=0x543d
|
||||
OP_DzPlayerList=0x14c6
|
||||
OP_DzJoinExpeditionConfirm=0x7f4b
|
||||
OP_DzJoinExpeditionReply=0x1950
|
||||
OP_DzListTimers=0x7b68
|
||||
OP_DzExpeditionInfo=0x9119
|
||||
OP_DzExpeditionList=0x205f
|
||||
OP_DzQuit=0xb2e3
|
||||
OP_DzMemberStatus=0x32f0
|
||||
OP_DzLeaderStatus=0x3de9
|
||||
OP_DzMemberList=0x5ae4
|
||||
OP_DzExpeditionEndsWarning=0x383c
|
||||
OP_DzMemberList=0x3de9
|
||||
OP_DzCompass=0x3e0e
|
||||
OP_DzChooseZone=0x0b7d
|
||||
|
||||
@@ -401,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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -525,7 +525,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 +534,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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user