From 7a28a6e9a7eabee61e74089127a2ef6184a6a155 Mon Sep 17 00:00:00 2001 From: adam Date: Fri, 22 Feb 2019 19:17:09 -0500 Subject: [PATCH 1/6] fix for mob movement getting 'stuck' when paths don't have updated locations. --- zone/mob_movement_manager.cpp | 44 +++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/zone/mob_movement_manager.cpp b/zone/mob_movement_manager.cpp index 23cccc8f4..f9f2cd29e 100644 --- a/zone/mob_movement_manager.cpp +++ b/zone/mob_movement_manager.cpp @@ -810,11 +810,55 @@ void MobMovementManager::UpdatePathGround(Mob * who, float x, float y, float z, } AdjustRoute(route, who); + + + + //avoid doing any processing if the mob is stuck to allow normal stuck code to work. + if (!stuck) + { + //there are times when the routes returned are no differen than where the mob is currently standing. What basically happens + //is a mob will get 'stuck' in such a way that it should be moving but the 'moving' place is the exact same spot it is at. + //this is a problem and creates an area of ground that if a mob gets to, will stay there forever. If socal this creates a + //"Ball of Death" (tm). This code tries to prevent this by simply warping the mob to the requested x/y. Better to have a warp than + //have stuck mobs. + + auto routeNode = route.begin(); + bool noValidPath = true; + while (routeNode != route.end() && noValidPath == true) { + auto ¤tNode = (*routeNode); + + if (routeNode == route.end()) + { + continue; + } + + if (!(currentNode.pos.x == who->GetX() && currentNode.pos.y == who->GetY())) + { + //if one of the nodes to move to, is not our current node, pass it. + noValidPath = false; + break; + } + //move to the next node + routeNode++; + + } + + if (noValidPath) + { + //we are 'stuck' in a path, lets just get out of this by 'teleporting' to the next position. + PushTeleportTo(ent.second, x, y, z, + CalculateHeadingAngleBetweenPositions(who->GetX(), who->GetY(), x, y)); + return; + } + + } + auto iter = route.begin(); glm::vec3 previous_pos(who->GetX(), who->GetY(), who->GetZ()); bool first_node = true; + while (iter != route.end()) { auto ¤t_node = (*iter); From 87b1d32ce84bd021426d3907004c511f67d15fa7 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 8 Jul 2019 21:58:47 -0400 Subject: [PATCH 2/6] Updated PerlembParser::ExportItemVariables to new inventory standard --- zone/embparser.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 848299580..759fe5931 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -1099,10 +1099,6 @@ void PerlembParser::ExportZoneVariables(std::string &package_name) { } } -#define HASITEM_FIRST 0 -#define HASITEM_LAST 29 // this includes worn plus 8 base slots -#define HASITEM_ISNULLITEM(item) ((item==-1) || (item==0)) - void PerlembParser::ExportItemVariables(std::string &package_name, Mob *mob) { if(mob && mob->IsClient()) { @@ -1111,11 +1107,11 @@ void PerlembParser::ExportItemVariables(std::string &package_name, Mob *mob) { //start with an empty hash perl->eval(std::string("%").append(hashname).append(" = ();").c_str()); - for(int slot = HASITEM_FIRST; slot <= HASITEM_LAST; slot++) + for(int slot = EQEmu::invslot::EQUIPMENT_BEGIN; slot <= EQEmu::invslot::GENERAL_END; slot++) { char *hi_decl=nullptr; int itemid = mob->CastToClient()->GetItemIDAt(slot); - if(!HASITEM_ISNULLITEM(itemid)) + if(itemid != -1 && itemid != 0) { MakeAnyLenString(&hi_decl, "push (@{$%s{%d}},%d);", hashname.c_str(), itemid, slot); perl->eval(hi_decl); @@ -1129,7 +1125,7 @@ void PerlembParser::ExportItemVariables(std::string &package_name, Mob *mob) { perl->eval(std::string("%").append(hashname).append(" = ();").c_str()); char *hi_decl = nullptr; int itemid = mob->CastToClient()->GetItemIDAt(EQEmu::invslot::slotCursor); - if(!HASITEM_ISNULLITEM(itemid)) { + if(itemid != -1 && itemid != 0) { MakeAnyLenString(&hi_decl, "push (@{$%s{%d}},%d);",hashname.c_str(), itemid, EQEmu::invslot::slotCursor); perl->eval(hi_decl); safe_delete_array(hi_decl); @@ -1137,10 +1133,6 @@ void PerlembParser::ExportItemVariables(std::string &package_name, Mob *mob) { } } -#undef HASITEM_FIRST -#undef HASITEM_LAST -#undef HASITEM_ISNULLITEM - void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID event, uint32 objid, const char * data, NPC* npcmob, EQEmu::ItemInstance* item_inst, Mob* mob, uint32 extradata, std::vector *extra_pointers) { From 525813be025541105b62a79381dd78d4ce51f5db Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 10 Jul 2019 01:20:51 -0400 Subject: [PATCH 3/6] Adjust VARSTRUCT_ENCODE_STRING macros for smarter compilers This is no more dangerous than what we were doing before (not checking return value of sprintf) Maybe we should sometime --- common/misc_functions.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/misc_functions.h b/common/misc_functions.h index d5d90d98f..4f295c68a 100644 --- a/common/misc_functions.h +++ b/common/misc_functions.h @@ -32,8 +32,8 @@ // #define VARSTRUCT_DECODE_TYPE(Type, Buffer) *(Type *)Buffer; Buffer += sizeof(Type); #define VARSTRUCT_DECODE_STRING(String, Buffer) strcpy(String, Buffer); Buffer += strlen(String)+1; -#define VARSTRUCT_ENCODE_STRING(Buffer, String) { sprintf(Buffer, "%s", String); Buffer += strlen(String) + 1; } -#define VARSTRUCT_ENCODE_INTSTRING(Buffer, Number) { sprintf(Buffer, "%i", Number); Buffer += strlen(Buffer) + 1; } +#define VARSTRUCT_ENCODE_STRING(Buffer, String) { int length = sprintf(Buffer, "%s", String); Buffer += length + 1; } +#define VARSTRUCT_ENCODE_INTSTRING(Buffer, Number) { int length = sprintf(Buffer, "%i", Number); Buffer += length + 1; } #define VARSTRUCT_ENCODE_TYPE(Type, Buffer, Value) { *(Type *)Buffer = Value; Buffer += sizeof(Type); } #define VARSTRUCT_SKIP_TYPE(Type, Buffer) Buffer += sizeof(Type); From dfa90aaac5d2807ee176bef8a258a8d3b54d8c6d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 10 Jul 2019 01:44:59 -0400 Subject: [PATCH 4/6] Fix OP_SpecialMesg encoding This broke with newer GCCs. It also worked even though the code was just wrong before??? --- common/patches/rof.cpp | 24 ++++++++++-------------- common/patches/rof2.cpp | 24 ++++++++++-------------- common/patches/sod.cpp | 24 ++++++++++-------------- common/patches/sof.cpp | 24 ++++++++++-------------- common/patches/titanium.cpp | 24 ++++++++++-------------- common/patches/uf.cpp | 24 ++++++++++-------------- 6 files changed, 60 insertions(+), 84 deletions(-) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index be077d750..d7fa21c41 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -3202,14 +3202,18 @@ namespace RoF SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer; unsigned char *__emu_buffer = in->pBuffer; + // break strlen optimizations! + char *message = emu->sayer; + auto sayer_length = std::char_traits::length(message); + message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats - std::string old_message = &emu->message[strlen(emu->sayer)]; + std::string old_message = message; std::string new_message; ServerToRoFSayLink(new_message, old_message); //in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; - in->size = strlen(emu->sayer) + new_message.length() + 25; + in->size = sayer_length + new_message.length() + 25; in->pBuffer = new unsigned char[in->size]; char *OutBuffer = (char *)in->pBuffer; @@ -3223,18 +3227,10 @@ namespace RoF VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[0]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[1]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[2]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[3]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[4]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[5]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[6]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[7]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[8]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[9]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[10]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[11]); + // TODO: figure this shit out + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f); + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f); + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f); VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str()); diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 33af8506f..66e699e2a 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -3269,14 +3269,18 @@ namespace RoF2 SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer; unsigned char *__emu_buffer = in->pBuffer; + // break strlen optimizations! + char *message = emu->sayer; + auto sayer_length = std::char_traits::length(message); + message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats - std::string old_message = &emu->message[strlen(emu->sayer)]; + std::string old_message = message; std::string new_message; ServerToRoF2SayLink(new_message, old_message); //in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; - in->size = strlen(emu->sayer) + new_message.length() + 25; + in->size = sayer_length + new_message.length() + 25; in->pBuffer = new unsigned char[in->size]; char *OutBuffer = (char *)in->pBuffer; @@ -3290,18 +3294,10 @@ namespace RoF2 VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[0]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[1]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[2]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[3]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[4]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[5]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[6]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[7]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[8]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[9]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[10]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[11]); + // TODO: figure this shit out + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f); + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f); + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f); VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str()); diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 1241e142a..2c9d70edf 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -2072,14 +2072,18 @@ namespace SoD SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer; unsigned char *__emu_buffer = in->pBuffer; + // break strlen optimizations! + char *message = emu->sayer; + auto sayer_length = std::char_traits::length(message); + message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats - std::string old_message = &emu->message[strlen(emu->sayer)]; + std::string old_message = message; std::string new_message; ServerToSoDSayLink(new_message, old_message); //in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; - in->size = strlen(emu->sayer) + new_message.length() + 25; + in->size = sayer_length + new_message.length() + 25; in->pBuffer = new unsigned char[in->size]; char *OutBuffer = (char *)in->pBuffer; @@ -2093,18 +2097,10 @@ namespace SoD VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[0]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[1]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[2]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[3]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[4]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[5]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[6]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[7]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[8]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[9]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[10]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[11]); + // TODO: figure this shit out + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f); + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f); + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f); VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str()); diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 247912dfd..0b3043c70 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1723,14 +1723,18 @@ namespace SoF SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer; unsigned char *__emu_buffer = in->pBuffer; + // break strlen optimizations! + char *message = emu->sayer; + auto sayer_length = std::char_traits::length(message); + message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats - std::string old_message = &emu->message[strlen(emu->sayer)]; + std::string old_message = message; std::string new_message; ServerToSoFSayLink(new_message, old_message); //in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; - in->size = strlen(emu->sayer) + new_message.length() + 25; + in->size = sayer_length + new_message.length() + 25; in->pBuffer = new unsigned char[in->size]; char *OutBuffer = (char *)in->pBuffer; @@ -1744,18 +1748,10 @@ namespace SoF VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[0]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[1]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[2]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[3]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[4]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[5]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[6]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[7]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[8]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[9]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[10]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[11]); + // TODO: figure this shit out + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f); + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f); + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f); VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str()); diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index e15913669..c4bef5bea 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1423,14 +1423,18 @@ namespace Titanium SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer; unsigned char *__emu_buffer = in->pBuffer; + // break strlen optimizations! + char *message = emu->sayer; + auto sayer_length = std::char_traits::length(message); + message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats - std::string old_message = &emu->message[strlen(emu->sayer)]; + std::string old_message = message; std::string new_message; ServerToTitaniumSayLink(new_message, old_message); //in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; - in->size = strlen(emu->sayer) + new_message.length() + 25; + in->size = sayer_length + new_message.length() + 25; in->pBuffer = new unsigned char[in->size]; char *OutBuffer = (char *)in->pBuffer; @@ -1444,18 +1448,10 @@ namespace Titanium VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[0]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[1]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[2]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[3]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[4]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[5]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[6]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[7]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[8]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[9]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[10]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[11]); + // TODO: figure this shit out + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f); + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f); + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f); VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str()); diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 549fa7698..7db0cfb92 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -2372,14 +2372,18 @@ namespace UF SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer; unsigned char *__emu_buffer = in->pBuffer; + // break strlen optimizations! + char *message = emu->sayer; + auto sayer_length = std::char_traits::length(message); + message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats - std::string old_message = &emu->message[strlen(emu->sayer)]; + std::string old_message = message; std::string new_message; ServerToUFSayLink(new_message, old_message); //in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; - in->size = strlen(emu->sayer) + new_message.length() + 25; + in->size = sayer_length + new_message.length() + 25; in->pBuffer = new unsigned char[in->size]; char *OutBuffer = (char *)in->pBuffer; @@ -2393,18 +2397,10 @@ namespace UF VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[0]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[1]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[2]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[3]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[4]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[5]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[6]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[7]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[8]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[9]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[10]); - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[11]); + // TODO: figure this shit out + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f); + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f); + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f); VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str()); From 35eb5b24ddae10adb3fd911b02e2873a7ca39f63 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 10 Jul 2019 03:39:07 -0500 Subject: [PATCH 5/6] Implement flymode --- changelog.txt | 5 + common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../git/required/2019_07_10_npc_flymode.sql | 1 + zone/command.cpp | 10 +- zone/npc.cpp | 5 + zone/zonedb.cpp | 281 ++++++++++-------- zone/zonedump.h | 1 + 8 files changed, 172 insertions(+), 134 deletions(-) create mode 100644 utils/sql/git/required/2019_07_10_npc_flymode.sql diff --git a/changelog.txt b/changelog.txt index e79e0bb26..dc9d0f16c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,10 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 7/10/2019 == + +Akkadius: Add #npcedit flymode [0 = ground, 1 = flying, 2 = levitate, 3 = water, 4 = floating] +Akkadius: Added "flymode" to npc_types database table + == 7/3/2019 == Akkadius/KLS: diff --git a/common/version.h b/common/version.h index f77ffcac2..f7a161dc1 100644 --- a/common/version.h +++ b/common/version.h @@ -31,7 +31,7 @@ */ -#define CURRENT_BINARY_DATABASE_VERSION 9140 +#define CURRENT_BINARY_DATABASE_VERSION 9141 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9024 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 682636d12..92bcfd260 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -394,6 +394,7 @@ 9138|2018_12_12_convert_to_client_functions.sql|SELECT `id` FROM `faction_list` WHERE `id` > 4999|empty| 9139|2019_03_25_optional_npc_model.sql|SHOW COLUMNS FROM `npc_types` LIKE 'model'|empty| 9140|2019_07_03_update_range.sql|SHOW COLUMNS FROM `npc_types` LIKE 'max_movement_update_range'|empty| +9141|2019_07_10_npc_flymode.sql|SHOW COLUMNS FROM `npc_types` LIKE 'flymode'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2019_07_10_npc_flymode.sql b/utils/sql/git/required/2019_07_10_npc_flymode.sql new file mode 100644 index 000000000..aacc5ad00 --- /dev/null +++ b/utils/sql/git/required/2019_07_10_npc_flymode.sql @@ -0,0 +1 @@ +ALTER TABLE `npc_types` ADD COLUMN `flymode` tinyint(4) NOT NULL DEFAULT -1; \ No newline at end of file diff --git a/zone/command.cpp b/zone/command.cpp index 0451f87e2..1675be8b8 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -7342,6 +7342,7 @@ void command_npcedit(Client *c, const Seperator *sep) c->Message(0, "#npcedit no_target - Set an NPC's ability to be targeted with the target hotkey"); c->Message(0, "#npcedit version - Set an NPC's version"); c->Message(0, "#npcedit slow_mitigation - Set an NPC's slow mitigation"); + c->Message(0, "#npcedit flymode - Set an NPC's flymode [0 = ground, 1 = flying, 2 = levitate, 3 = water, 4 = floating]"); } @@ -7355,7 +7356,14 @@ void command_npcedit(Client *c, const Seperator *sep) if (strcasecmp(sep->arg[1], "lastname") == 0) { c->Message(15,"NPCID %u now has the lastname %s.", npcTypeID, sep->argplus[2]); - std::string query = StringFormat("UPDATE npc_types SET lastname = '%s' WHERE id = %i", sep->argplus[2],npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET lastname = '%s' WHERE id = %i", sep->argplus[2],npcTypeID); + database.QueryDatabase(query); + return; + } + + if (strcasecmp(sep->arg[1], "flymode") == 0) { + c->Message(15,"NPCID %u now has flymode [%s]", npcTypeID, sep->argplus[2]); + std::string query = StringFormat("UPDATE npc_types SET flymode = '%s' WHERE id = %i", sep->argplus[2],npcTypeID); database.QueryDatabase(query); return; } diff --git a/zone/npc.cpp b/zone/npc.cpp index b0367f469..60e6f73c4 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -226,6 +226,11 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi merchant_open = GetClass() == MERCHANT; adventure_template_id = npc_type_data->adventure_template; flymode = iflymode; + + if (npc_type_data->flymode >= 0) { + flymode = static_cast(npc_type_data->flymode); + } + guard_anim = eaStanding; roambox_distance = 0; roambox_max_x = -2; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 11a90eac5..e2825da5a 100755 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2366,29 +2366,33 @@ bool ZoneDatabase::RestoreCharacterInvSnapshot(uint32 character_id, uint32 times return results.Success(); } -const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load /*= false*/) +const NPCType *ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load /*= false*/) { const NPCType *npc = nullptr; /* If there is a cached NPC entry, load it */ auto itr = zone->npctable.find(npc_type_id); - if(itr != zone->npctable.end()) + if (itr != zone->npctable.end()) { return itr->second; + } std::string where_condition = ""; - if (bulk_load){ + if (bulk_load) { Log(Logs::General, Logs::Debug, "Performing bulk NPC Types load"); where_condition = StringFormat( "INNER JOIN spawnentry ON npc_types.id = spawnentry.npcID " "INNER JOIN spawn2 ON spawnentry.spawngroupID = spawn2.spawngroupID " - "WHERE spawn2.zone = '%s' and spawn2.version = %u GROUP BY npc_types.id", zone->GetShortName(), zone->GetInstanceVersion()); + "WHERE spawn2.zone = '%s' and spawn2.version = %u GROUP BY npc_types.id", + zone->GetShortName(), + zone->GetInstanceVersion()); } - else{ + else { where_condition = StringFormat("WHERE id = %u", npc_type_id); } - std::string query = StringFormat("SELECT " + std::string query = StringFormat( + "SELECT " "npc_types.id, " "npc_types.name, " "npc_types.level, " @@ -2499,115 +2503,122 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load "npc_types.skip_global_loot, " "npc_types.rare_spawn, " "npc_types.stuck_behavior, " - "npc_types.model " + "npc_types.model, " + "npc_types.flymode " "FROM npc_types %s", where_condition.c_str() ); - auto results = QueryDatabase(query); - if (!results.Success()) { - return nullptr; - } + auto results = QueryDatabase(query); + if (!results.Success()) { + return nullptr; + } - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto row = results.begin(); row != results.end(); ++row) { NPCType *temp_npctype_data; temp_npctype_data = new NPCType; - memset (temp_npctype_data, 0, sizeof *temp_npctype_data); + memset(temp_npctype_data, 0, sizeof *temp_npctype_data); temp_npctype_data->npc_id = atoi(row[0]); strn0cpy(temp_npctype_data->name, row[1], 50); - temp_npctype_data->level = atoi(row[2]); - temp_npctype_data->race = atoi(row[3]); - temp_npctype_data->class_ = atoi(row[4]); - temp_npctype_data->max_hp = atoi(row[5]); - temp_npctype_data->current_hp = temp_npctype_data->max_hp; - temp_npctype_data->Mana = atoi(row[6]); - temp_npctype_data->gender = atoi(row[7]); - temp_npctype_data->texture = atoi(row[8]); - temp_npctype_data->helmtexture = atoi(row[9]); - temp_npctype_data->herosforgemodel = atoul(row[10]); - temp_npctype_data->size = atof(row[11]); - temp_npctype_data->loottable_id = atoi(row[12]); - temp_npctype_data->merchanttype = atoi(row[13]); - temp_npctype_data->alt_currency_type = atoi(row[14]); + temp_npctype_data->level = atoi(row[2]); + temp_npctype_data->race = atoi(row[3]); + temp_npctype_data->class_ = atoi(row[4]); + temp_npctype_data->max_hp = atoi(row[5]); + temp_npctype_data->current_hp = temp_npctype_data->max_hp; + temp_npctype_data->Mana = atoi(row[6]); + temp_npctype_data->gender = atoi(row[7]); + temp_npctype_data->texture = atoi(row[8]); + temp_npctype_data->helmtexture = atoi(row[9]); + temp_npctype_data->herosforgemodel = atoul(row[10]); + temp_npctype_data->size = atof(row[11]); + temp_npctype_data->loottable_id = atoi(row[12]); + temp_npctype_data->merchanttype = atoi(row[13]); + temp_npctype_data->alt_currency_type = atoi(row[14]); temp_npctype_data->adventure_template = atoi(row[15]); - temp_npctype_data->trap_template = atoi(row[16]); - temp_npctype_data->attack_speed = atof(row[17]); - temp_npctype_data->STR = atoi(row[18]); - temp_npctype_data->STA = atoi(row[19]); - temp_npctype_data->DEX = atoi(row[20]); - temp_npctype_data->AGI = atoi(row[21]); - temp_npctype_data->INT = atoi(row[22]); - temp_npctype_data->WIS = atoi(row[23]); - temp_npctype_data->CHA = atoi(row[24]); - temp_npctype_data->MR = atoi(row[25]); - temp_npctype_data->CR = atoi(row[26]); - temp_npctype_data->DR = atoi(row[27]); - temp_npctype_data->FR = atoi(row[28]); - temp_npctype_data->PR = atoi(row[29]); - temp_npctype_data->Corrup = atoi(row[30]); - temp_npctype_data->PhR = atoi(row[31]); - temp_npctype_data->min_dmg = atoi(row[32]); - temp_npctype_data->max_dmg = atoi(row[33]); - temp_npctype_data->attack_count = atoi(row[34]); + temp_npctype_data->trap_template = atoi(row[16]); + temp_npctype_data->attack_speed = atof(row[17]); + temp_npctype_data->STR = atoi(row[18]); + temp_npctype_data->STA = atoi(row[19]); + temp_npctype_data->DEX = atoi(row[20]); + temp_npctype_data->AGI = atoi(row[21]); + temp_npctype_data->INT = atoi(row[22]); + temp_npctype_data->WIS = atoi(row[23]); + temp_npctype_data->CHA = atoi(row[24]); + temp_npctype_data->MR = atoi(row[25]); + temp_npctype_data->CR = atoi(row[26]); + temp_npctype_data->DR = atoi(row[27]); + temp_npctype_data->FR = atoi(row[28]); + temp_npctype_data->PR = atoi(row[29]); + temp_npctype_data->Corrup = atoi(row[30]); + temp_npctype_data->PhR = atoi(row[31]); + temp_npctype_data->min_dmg = atoi(row[32]); + temp_npctype_data->max_dmg = atoi(row[33]); + temp_npctype_data->attack_count = atoi(row[34]); - if (row[35] != nullptr) + if (row[35] != nullptr) { strn0cpy(temp_npctype_data->special_abilities, row[35], 512); - else + } + else { temp_npctype_data->special_abilities[0] = '\0'; + } - temp_npctype_data->npc_spells_id = atoi(row[36]); + temp_npctype_data->npc_spells_id = atoi(row[36]); temp_npctype_data->npc_spells_effects_id = atoi(row[37]); - temp_npctype_data->d_melee_texture1 = atoi(row[38]); - temp_npctype_data->d_melee_texture2 = atoi(row[39]); + temp_npctype_data->d_melee_texture1 = atoi(row[38]); + temp_npctype_data->d_melee_texture2 = atoi(row[39]); strn0cpy(temp_npctype_data->ammo_idfile, row[40], 30); temp_npctype_data->prim_melee_type = atoi(row[41]); - temp_npctype_data->sec_melee_type = atoi(row[42]); - temp_npctype_data->ranged_type = atoi(row[43]); - temp_npctype_data->runspeed= atof(row[44]); - temp_npctype_data->findable = atoi(row[45]) == 0? false : true; - temp_npctype_data->trackable = atoi(row[46]) == 0? false : true; - temp_npctype_data->hp_regen = atoi(row[47]); - temp_npctype_data->mana_regen = atoi(row[48]); + temp_npctype_data->sec_melee_type = atoi(row[42]); + temp_npctype_data->ranged_type = atoi(row[43]); + temp_npctype_data->runspeed = atof(row[44]); + temp_npctype_data->findable = atoi(row[45]) == 0 ? false : true; + temp_npctype_data->trackable = atoi(row[46]) == 0 ? false : true; + temp_npctype_data->hp_regen = atoi(row[47]); + temp_npctype_data->mana_regen = atoi(row[48]); // set default value for aggroradius - temp_npctype_data->aggroradius = (int32)atoi(row[49]); - if (temp_npctype_data->aggroradius <= 0) + temp_npctype_data->aggroradius = (int32) atoi(row[49]); + if (temp_npctype_data->aggroradius <= 0) { temp_npctype_data->aggroradius = 70; + } - temp_npctype_data->assistradius = (int32)atoi(row[50]); - if (temp_npctype_data->assistradius <= 0) + temp_npctype_data->assistradius = (int32) atoi(row[50]); + if (temp_npctype_data->assistradius <= 0) { temp_npctype_data->assistradius = temp_npctype_data->aggroradius; + } - if (row[51] && strlen(row[51])) - temp_npctype_data->bodytype = (uint8)atoi(row[51]); - else - temp_npctype_data->bodytype = 0; + if (row[51] && strlen(row[51])) { + temp_npctype_data->bodytype = (uint8) atoi(row[51]); + } + else { + temp_npctype_data->bodytype = 0; + } temp_npctype_data->npc_faction_id = atoi(row[52]); - temp_npctype_data->luclinface = atoi(row[53]); - temp_npctype_data->hairstyle = atoi(row[54]); - temp_npctype_data->haircolor = atoi(row[55]); - temp_npctype_data->eyecolor1 = atoi(row[56]); - temp_npctype_data->eyecolor2 = atoi(row[57]); - temp_npctype_data->beardcolor = atoi(row[58]); - temp_npctype_data->beard = atoi(row[59]); + temp_npctype_data->luclinface = atoi(row[53]); + temp_npctype_data->hairstyle = atoi(row[54]); + temp_npctype_data->haircolor = atoi(row[55]); + temp_npctype_data->eyecolor1 = atoi(row[56]); + temp_npctype_data->eyecolor2 = atoi(row[57]); + temp_npctype_data->beardcolor = atoi(row[58]); + temp_npctype_data->beard = atoi(row[59]); temp_npctype_data->drakkin_heritage = atoi(row[60]); - temp_npctype_data->drakkin_tattoo = atoi(row[61]); - temp_npctype_data->drakkin_details = atoi(row[62]); + temp_npctype_data->drakkin_tattoo = atoi(row[61]); + temp_npctype_data->drakkin_details = atoi(row[62]); uint32 armor_tint_id = atoi(row[63]); temp_npctype_data->armor_tint.Head.Color = (atoi(row[64]) & 0xFF) << 16; - temp_npctype_data->armor_tint.Head.Color |= (atoi(row[65]) & 0xFF) << 8; + temp_npctype_data->armor_tint.Head.Color |= (atoi(row[65]) & 0xFF) << 8; temp_npctype_data->armor_tint.Head.Color |= (atoi(row[66]) & 0xFF); temp_npctype_data->armor_tint.Head.Color |= (temp_npctype_data->armor_tint.Head.Color) ? (0xFF << 24) : 0; if (armor_tint_id != 0) { - std::string armortint_query = StringFormat( + std::string armortint_query = StringFormat( "SELECT red1h, grn1h, blu1h, " "red2c, grn2c, blu2c, " "red3a, grn3a, blu3a, " @@ -2618,21 +2629,24 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load "red8x, grn8x, blu8x, " "red9x, grn9x, blu9x " "FROM npc_types_tint WHERE id = %d", - armor_tint_id); - auto armortint_results = QueryDatabase(armortint_query); - if (!armortint_results.Success() || armortint_results.RowCount() == 0) - armor_tint_id = 0; - else { - auto armorTint_row = armortint_results.begin(); + armor_tint_id + ); + auto armortint_results = QueryDatabase(armortint_query); + if (!armortint_results.Success() || armortint_results.RowCount() == 0) { + armor_tint_id = 0; + } + else { + auto armorTint_row = armortint_results.begin(); for (int index = EQEmu::textures::textureBegin; index <= EQEmu::textures::LastTexture; index++) { - temp_npctype_data->armor_tint.Slot[index].Color = atoi(armorTint_row[index * 3]) << 16; + temp_npctype_data->armor_tint.Slot[index].Color = atoi(armorTint_row[index * 3]) << 16; temp_npctype_data->armor_tint.Slot[index].Color |= atoi(armorTint_row[index * 3 + 1]) << 8; temp_npctype_data->armor_tint.Slot[index].Color |= atoi(armorTint_row[index * 3 + 2]); - temp_npctype_data->armor_tint.Slot[index].Color |= (temp_npctype_data->armor_tint.Slot[index].Color) ? (0xFF << 24) : 0; - } - } - } + temp_npctype_data->armor_tint.Slot[index].Color |= (temp_npctype_data->armor_tint.Slot[index].Color) + ? (0xFF << 24) : 0; + } + } + } // Try loading npc_types tint fields if armor tint is 0 or query failed to get results if (armor_tint_id == 0) { for (int index = EQEmu::textures::armorChest; index < EQEmu::textures::materialCount; index++) { @@ -2640,56 +2654,59 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load } } - temp_npctype_data->see_invis = atoi(row[67]); - temp_npctype_data->see_invis_undead = atoi(row[68]) == 0? false: true; // Set see_invis_undead flag + temp_npctype_data->see_invis = atoi(row[67]); + temp_npctype_data->see_invis_undead = atoi(row[68]) == 0 ? false : true; // Set see_invis_undead flag - if (row[69] != nullptr) + if (row[69] != nullptr) { strn0cpy(temp_npctype_data->lastname, row[69], 32); + } - temp_npctype_data->qglobal = atoi(row[70]) == 0? false: true; // qglobal - temp_npctype_data->AC = atoi(row[71]); - temp_npctype_data->npc_aggro = atoi(row[72]) == 0? false: true; - temp_npctype_data->spawn_limit = atoi(row[73]); - temp_npctype_data->see_hide = atoi(row[74]) == 0? false: true; - temp_npctype_data->see_improved_hide = atoi(row[75]) == 0? false: true; - temp_npctype_data->ATK = atoi(row[76]); - temp_npctype_data->accuracy_rating = atoi(row[77]); - temp_npctype_data->avoidance_rating = atoi(row[78]); - temp_npctype_data->slow_mitigation = atoi(row[79]); - temp_npctype_data->maxlevel = atoi(row[80]); - temp_npctype_data->scalerate = atoi(row[81]); - temp_npctype_data->private_corpse = atoi(row[82]) == 1 ? true: false; - temp_npctype_data->unique_spawn_by_name = atoi(row[83]) == 1 ? true: false; - temp_npctype_data->underwater = atoi(row[84]) == 1 ? true: false; - temp_npctype_data->emoteid = atoi(row[85]); - temp_npctype_data->spellscale = atoi(row[86]); - temp_npctype_data->healscale = atoi(row[87]); - temp_npctype_data->no_target_hotkey = atoi(row[88]) == 1 ? true: false; - temp_npctype_data->raid_target = atoi(row[89]) == 0 ? false : true; - temp_npctype_data->attack_delay = atoi(row[90]) * 100; // TODO: fix DB - temp_npctype_data->light = (atoi(row[91]) & 0x0F); + temp_npctype_data->qglobal = atoi(row[70]) == 0 ? false : true; // qglobal + temp_npctype_data->AC = atoi(row[71]); + temp_npctype_data->npc_aggro = atoi(row[72]) == 0 ? false : true; + temp_npctype_data->spawn_limit = atoi(row[73]); + temp_npctype_data->see_hide = atoi(row[74]) == 0 ? false : true; + temp_npctype_data->see_improved_hide = atoi(row[75]) == 0 ? false : true; + temp_npctype_data->ATK = atoi(row[76]); + temp_npctype_data->accuracy_rating = atoi(row[77]); + temp_npctype_data->avoidance_rating = atoi(row[78]); + temp_npctype_data->slow_mitigation = atoi(row[79]); + temp_npctype_data->maxlevel = atoi(row[80]); + temp_npctype_data->scalerate = atoi(row[81]); + temp_npctype_data->private_corpse = atoi(row[82]) == 1 ? true : false; + temp_npctype_data->unique_spawn_by_name = atoi(row[83]) == 1 ? true : false; + temp_npctype_data->underwater = atoi(row[84]) == 1 ? true : false; + temp_npctype_data->emoteid = atoi(row[85]); + temp_npctype_data->spellscale = atoi(row[86]); + temp_npctype_data->healscale = atoi(row[87]); + temp_npctype_data->no_target_hotkey = atoi(row[88]) == 1 ? true : false; + temp_npctype_data->raid_target = atoi(row[89]) == 0 ? false : true; + temp_npctype_data->attack_delay = atoi(row[90]) * 100; // TODO: fix DB + temp_npctype_data->light = (atoi(row[91]) & 0x0F); - temp_npctype_data->armtexture = atoi(row[92]); - temp_npctype_data->bracertexture = atoi(row[93]); - temp_npctype_data->handtexture = atoi(row[94]); - temp_npctype_data->legtexture = atoi(row[95]); - temp_npctype_data->feettexture = atoi(row[96]); + temp_npctype_data->armtexture = atoi(row[92]); + temp_npctype_data->bracertexture = atoi(row[93]); + temp_npctype_data->handtexture = atoi(row[94]); + temp_npctype_data->legtexture = atoi(row[95]); + temp_npctype_data->feettexture = atoi(row[96]); temp_npctype_data->ignore_despawn = atoi(row[97]) == 1 ? true : false; - temp_npctype_data->show_name = atoi(row[98]) != 0 ? true : false; - temp_npctype_data->untargetable = atoi(row[99]) != 0 ? true : false; + temp_npctype_data->show_name = atoi(row[98]) != 0 ? true : false; + temp_npctype_data->untargetable = atoi(row[99]) != 0 ? true : false; - temp_npctype_data->charm_ac = atoi(row[100]); - temp_npctype_data->charm_min_dmg = atoi(row[101]); - temp_npctype_data->charm_max_dmg = atoi(row[102]); - temp_npctype_data->charm_attack_delay = atoi(row[103]) * 100; // TODO: fix DB - temp_npctype_data->charm_accuracy_rating = atoi(row[104]); + temp_npctype_data->charm_ac = atoi(row[100]); + temp_npctype_data->charm_min_dmg = atoi(row[101]); + temp_npctype_data->charm_max_dmg = atoi(row[102]); + temp_npctype_data->charm_attack_delay = atoi(row[103]) * 100; // TODO: fix DB + temp_npctype_data->charm_accuracy_rating = atoi(row[104]); temp_npctype_data->charm_avoidance_rating = atoi(row[105]); - temp_npctype_data->charm_atk = atoi(row[106]); + temp_npctype_data->charm_atk = atoi(row[106]); temp_npctype_data->skip_global_loot = atoi(row[107]) != 0; - temp_npctype_data->rare_spawn = atoi(row[108]) != 0; - temp_npctype_data->stuck_behavior = atoi(row[109]); - temp_npctype_data->use_model = atoi(row[110]); + temp_npctype_data->rare_spawn = atoi(row[108]) != 0; + temp_npctype_data->stuck_behavior = atoi(row[109]); + temp_npctype_data->use_model = atoi(row[110]); + temp_npctype_data->flymode = atoi(row[111]); + temp_npctype_data->skip_auto_scale = false; // hardcoded here for now // If NPC with duplicate NPC id already in table, @@ -2700,9 +2717,9 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load return nullptr; } - zone->npctable[temp_npctype_data->npc_id] = temp_npctype_data; - npc = temp_npctype_data; - } + zone->npctable[temp_npctype_data->npc_id] = temp_npctype_data; + npc = temp_npctype_data; + } return npc; } diff --git a/zone/zonedump.h b/zone/zonedump.h index 71f530171..302d4ee25 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -146,6 +146,7 @@ struct NPCType bool skip_auto_scale; // just so it doesn't mess up bots or mercs, probably should add to DB too just in case int8 stuck_behavior; uint16 use_model; + int8 flymode; }; namespace player_lootitem { From 1ba78d09882ccb9f0b530cd1c1b2c8d8cc5d5dba Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 10 Jul 2019 14:33:33 -0400 Subject: [PATCH 6/6] Switch to char_traits::length in SerializeBuffer This benches a bit faster --- common/serialize_buffer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/serialize_buffer.h b/common/serialize_buffer.h index 9b350b4fa..65ae36f70 100644 --- a/common/serialize_buffer.h +++ b/common/serialize_buffer.h @@ -143,7 +143,7 @@ public: void WriteString(const char *str) { assert(str != nullptr); - auto len = strlen(str) + 1; + auto len = std::char_traits::length(str) + 1; if (m_pos + len > m_capacity) Grow(m_capacity + len); memcpy(m_buffer + m_pos, str, len);