diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a20677ec..64d53cc6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -213,14 +213,14 @@ ADD_DEFINITIONS(-DGLM_FORCE_CTOR_INIT) ADD_DEFINITIONS(-DGLM_ENABLE_EXPERIMENTAL) #Find everything we need -FIND_PACKAGE(ZLIB REQUIRED) +FIND_PACKAGE(ZLIB) FIND_PACKAGE(MySQL REQUIRED) IF(EQEMU_BUILD_PERL) FIND_PACKAGE(PerlLibs REQUIRED) INCLUDE_DIRECTORIES(SYSTEM "${PERL_INCLUDE_PATH}") ENDIF(EQEMU_BUILD_PERL) -SET(SERVER_LIBS common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} uv_a fmt RecastNavigation::Detour) +SET(SERVER_LIBS common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} uv_a fmt RecastNavigation::Detour) FIND_PACKAGE(Sodium REQUIRED) IF(SODIUM_FOUND) @@ -236,14 +236,14 @@ IF(ZLIB_FOUND) OPTION(EQEMU_BUILD_ZLIB "Build internal version of zlib." OFF) IF(EQEMU_BUILD_ZLIB) - INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng") + INCLUDE_DIRECTORIES(BEFORE SYSTEM "${CMAKE_CURRENT_BINARY_DIR}/libs/zlibng" "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng") SET(SERVER_LIBS ${SERVER_LIBS} "zlibstatic") ELSE() INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}") SET(SERVER_LIBS ${SERVER_LIBS} ${ZLIB_LIBRARY}) ENDIF() ELSE() - INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng") + INCLUDE_DIRECTORIES(BEFORE SYSTEM "${CMAKE_CURRENT_BINARY_DIR}/libs/zlibng" "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng") SET(SERVER_LIBS ${SERVER_LIBS} "zlibstatic") ENDIF() 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/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); diff --git a/common/net/daybreak_connection.h b/common/net/daybreak_connection.h index 4d2f62e27..b4f3ca41c 100644 --- a/common/net/daybreak_connection.h +++ b/common/net/daybreak_connection.h @@ -257,7 +257,7 @@ namespace EQ resend_delay_min = 150; resend_delay_max = 5000; connect_delay_ms = 500; - stale_connection_ms = 90000; + stale_connection_ms = 30000; connect_stale_ms = 5000; crc_length = 2; max_packet_size = 512; @@ -269,7 +269,7 @@ namespace EQ simulated_in_packet_loss = 0; simulated_out_packet_loss = 0; tic_rate_hertz = 60.0; - resend_timeout = 90000; + resend_timeout = 30000; connection_close_time = 2000; outgoing_data_rate = 0.0; } 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()); diff --git a/common/ruletypes.h b/common/ruletypes.h index e3be272ca..8d9803d08 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -225,8 +225,6 @@ RULE_BOOL(World, MaxClientsSetByStatus, false) // If True, IP Limiting will be s RULE_BOOL(World, EnableIPExemptions, false) // If True, ip_exemptions table is used, if there is no entry for the IP it will default to RuleI(World, MaxClientsPerIP) RULE_BOOL(World, ClearTempMerchantlist, true) // Clears temp merchant items when world boots. RULE_BOOL(World, DeleteStaleCorpeBackups, true) // Deletes stale corpse backups older than 2 weeks. -RULE_INT(World, AccountSessionLimit, -1) //Max number of characters allowed on at once from a single account (-1 is disabled) -RULE_INT(World, ExemptAccountLimitStatus, -1) //Min status required to be exempt from multi-session per account limiting (-1 is disabled) RULE_BOOL(World, GMAccountIPList, false) // Check ip list against GM Accounts, AntiHack GM Accounts. RULE_INT(World, MinGMAntiHackStatus, 1) //Minimum GM status to check against AntiHack list RULE_INT(World, SoFStartZoneID, -1) //Sets the Starting Zone for SoF Clients separate from Titanium Clients (-1 is disabled) @@ -241,10 +239,11 @@ RULE_BOOL (World, IPLimitDisconnectAll, false) RULE_BOOL(World, MaxClientsSimplifiedLogic, false) // New logic that only uses ExemptMaxClientsStatus and MaxClientsPerIP. Done on the loginserver. This mimics the P99-style special IP rules. RULE_INT (World, TellQueueSize, 20) RULE_BOOL(World, StartZoneSameAsBindOnCreation, true) //Should the start zone ALWAYS be the same location as your bind? +RULE_BOOL(World, DisallowDuplicateAccountLogins, true) RULE_CATEGORY_END() RULE_CATEGORY(Zone) -RULE_INT(Zone, ClientLinkdeadMS, 180000) //the time a client remains link dead on the server after a sudden disconnection +RULE_INT(Zone, ClientLinkdeadMS, 90000) //the time a client remains link dead on the server after a sudden disconnection RULE_INT(Zone, GraveyardTimeMS, 1200000) //ms time until a player corpse is moved to a zone's graveyard, if one is specified for the zone RULE_BOOL(Zone, EnableShadowrest, 1) // enables or disables the shadowrest zone feature for player corpses. Default is turned on. RULE_BOOL(Zone, UsePlayerCorpseBackups, true) // Keeps backups of player corpses. 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); diff --git a/common/servertalk.h b/common/servertalk.h index 4befd253d..5cef5a08b 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -216,6 +216,15 @@ enum { QSG_LFGuild_PlayerMatches = 0, QSG_LFGuild_UpdatePlayerInfo, QSG_LFGuild_ #define ServerOP_Speech 0x4513 +enum { + UserToWorldStatusWorldUnavail = 0, + UserToWorldStatusSuccess = 1, + UserToWorldStatusSuspended = -1, + UserToWorldStatusBanned = -2, + UserToWorldStatusWorldAtCapacity = -3, + UserToWorldStatusAlreadyOnline = -4 +}; + /************ PACKET RELATED STRUCT ************/ class ServerPacket { 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/libs/zlibng/CMakeLists.txt b/libs/zlibng/CMakeLists.txt index b1845522b..9767a00c8 100644 --- a/libs/zlibng/CMakeLists.txt +++ b/libs/zlibng/CMakeLists.txt @@ -861,5 +861,5 @@ if (ZLIB_ENABLE_TESTS) endif() endif() -FEATURE_SUMMARY(WHAT ALL INCLUDE_QUIET_PACKAGES) +# FEATURE_SUMMARY(WHAT ALL INCLUDE_QUIET_PACKAGES) diff --git a/loginserver/world_server.cpp b/loginserver/world_server.cpp index 4f880d506..b188f68e6 100644 --- a/loginserver/world_server.cpp +++ b/loginserver/world_server.cpp @@ -251,21 +251,26 @@ void WorldServer::ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Ne } switch (user_to_world_response->response) { - case 1: + case UserToWorldStatusSuccess: per->Message = 101; break; - case 0: + case UserToWorldStatusWorldUnavail: per->Message = 326; break; - case -1: + case UserToWorldStatusSuspended: per->Message = 337; break; - case -2: + case UserToWorldStatusBanned: per->Message = 338; break; - case -3: - per->Message = 303; + case UserToWorldStatusWorldAtCapacity: + per->Message = 339; break; + case UserToWorldStatusAlreadyOnline: + per->Message = 111; + break; + default: + per->Message = 102; } if (server.options.IsWorldTraceOn()) { 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/optional/2019_07_13_linkdead_changes.sql b/utils/sql/git/optional/2019_07_13_linkdead_changes.sql new file mode 100644 index 000000000..6bc6bde50 --- /dev/null +++ b/utils/sql/git/optional/2019_07_13_linkdead_changes.sql @@ -0,0 +1,2 @@ +UPDATE `rule_values` SET `rule_value`='90000' WHERE `rule_name`='Zone:ClientLinkdeadMS'; +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'DisallowDuplicateAccountLogins', 'true', 'Requires account logins to be unique.'); 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/world/clientlist.cpp b/world/clientlist.cpp index c3404fb37..388e42e23 100644 --- a/world/clientlist.cpp +++ b/world/clientlist.cpp @@ -99,52 +99,6 @@ ClientListEntry* ClientList::GetCLE(uint32 iID) { return 0; } -//Account Limiting Code to limit the number of characters allowed on from a single account at once. -void ClientList::EnforceSessionLimit(uint32 iLSAccountID) { - - ClientListEntry* ClientEntry = 0; - - LinkedListIterator iterator(clientlist, BACKWARD); - - int CharacterCount = 0; - - iterator.Reset(); - - while(iterator.MoreElements()) { - - ClientEntry = iterator.GetData(); - - if ((ClientEntry->LSAccountID() == iLSAccountID) && - ((ClientEntry->Admin() <= (RuleI(World, ExemptAccountLimitStatus))) || (RuleI(World, ExemptAccountLimitStatus) < 0))) { - - CharacterCount++; - - if (CharacterCount >= (RuleI(World, AccountSessionLimit))){ - // If we have a char name, they are in a zone, so send a kick to the zone server - if(strlen(ClientEntry->name())) { - - auto pack = - new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct)); - ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*) pack->pBuffer; - strcpy(skp->adminname, "SessionLimit"); - strcpy(skp->name, ClientEntry->name()); - skp->adminrank = 255; - zoneserver_list.SendPacket(pack); - safe_delete(pack); - } - - ClientEntry->SetOnline(CLE_Status_Offline); - - iterator.RemoveCurrent(); - - continue; - } - } - iterator.Advance(); - } -} - - //Check current CLE Entry IPs against incoming connection void ClientList::GetCLEIP(uint32 iIP) { @@ -272,7 +226,7 @@ ClientListEntry* ClientList::FindCharacter(const char* name) { } iterator.Advance(); } - return 0; + return nullptr; } ClientListEntry* ClientList::FindCLEByAccountID(uint32 iAccID) { @@ -285,7 +239,7 @@ ClientListEntry* ClientList::FindCLEByAccountID(uint32 iAccID) { } iterator.Advance(); } - return 0; + return nullptr; } ClientListEntry* ClientList::FindCLEByCharacterID(uint32 iCharID) { @@ -298,7 +252,20 @@ ClientListEntry* ClientList::FindCLEByCharacterID(uint32 iCharID) { } iterator.Advance(); } - return 0; + return nullptr; +} + +ClientListEntry* ClientList::FindCLEByLSID(uint32 iLSID) { + LinkedListIterator iterator(clientlist); + + iterator.Reset(); + while (iterator.MoreElements()) { + if (iterator.GetData()->LSID() == iLSID) { + return iterator.GetData(); + } + iterator.Advance(); + } + return nullptr; } void ClientList::SendCLEList(const int16& admin, const char* to, WorldTCPConnection* connection, const char* iName) { diff --git a/world/clientlist.h b/world/clientlist.h index 5eb8d0a0d..4a691b999 100644 --- a/world/clientlist.h +++ b/world/clientlist.h @@ -55,11 +55,11 @@ public: ClientListEntry* FindCharacter(const char* name); ClientListEntry* FindCLEByAccountID(uint32 iAccID); ClientListEntry* FindCLEByCharacterID(uint32 iCharID); + ClientListEntry* FindCLEByLSID(uint32 iLSID); ClientListEntry* GetCLE(uint32 iID); void GetCLEIP(uint32 iIP); uint32 GetCLEIPCount(uint32 iLSAccountID); void DisconnectByIP(uint32 iIP); - void EnforceSessionLimit(uint32 iLSAccountID); void CLCheckStale(); void CLEKeepAlive(uint32 numupdates, uint32* wid); void CLEAdd(uint32 iLSID, const char* iLoginServerName, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin = 0, uint32 ip = 0, uint8 local=0); diff --git a/world/login_server.cpp b/world/login_server.cpp index 41fa92efa..dc7d3d5d9 100644 --- a/world/login_server.cpp +++ b/world/login_server.cpp @@ -34,6 +34,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "worlddb.h" #include "zonelist.h" #include "clientlist.h" +#include "cliententry.h" #include "world_config.h" @@ -67,42 +68,59 @@ void LoginServer::ProcessUsertoWorldReqLeg(uint16_t opcode, EQ::Net::Packet &p) uint32 id = database.GetAccountIDFromLSID("eqemu", utwr->lsaccountid); int16 status = database.CheckStatus(id); - auto outpack = new ServerPacket; - outpack->opcode = ServerOP_UsertoWorldRespLeg; - outpack->size = sizeof(UsertoWorldResponseLegacy_Struct); - outpack->pBuffer = new uchar[outpack->size]; - memset(outpack->pBuffer, 0, outpack->size); - UsertoWorldResponseLegacy_Struct *utwrs = (UsertoWorldResponseLegacy_Struct *) outpack->pBuffer; + ServerPacket outpack; + outpack.opcode = ServerOP_UsertoWorldResp; + outpack.size = sizeof(UsertoWorldResponse_Struct); + outpack.pBuffer = new uchar[outpack.size]; + memset(outpack.pBuffer, 0, outpack.size); + + UsertoWorldResponse_Struct *utwrs = (UsertoWorldResponse_Struct *) outpack.pBuffer; utwrs->lsaccountid = utwr->lsaccountid; utwrs->ToID = utwr->FromID; + utwrs->worldid = utwr->worldid; + utwrs->response = UserToWorldStatusSuccess; - if (Config->Locked == true) { - if ((status == 0 || status < 100) && (status != -2 || status != -1)) { - utwrs->response = 0; + if (Config->Locked == true) + { + if (status < 100) { + utwrs->response = UserToWorldStatusWorldUnavail; + SendPacket(&outpack); + return; } - if (status >= 100) { - utwrs->response = 1; - } - } - else { - utwrs->response = 1; } int32 x = Config->MaxClients; - if ((int32) numplayers >= x && x != -1 && x != 255 && status < 80) { - utwrs->response = -3; + if ((int32)numplayers >= x && x != -1 && x != 255 && status < 80) { + utwrs->response = UserToWorldStatusWorldAtCapacity; + SendPacket(&outpack); + return; } if (status == -1) { - utwrs->response = -1; - } - if (status == -2) { - utwrs->response = -2; + utwrs->response = UserToWorldStatusSuspended; + SendPacket(&outpack); + return; } - utwrs->worldid = utwr->worldid; - SendPacket(outpack); - delete outpack; + if (status == -2) { + utwrs->response = UserToWorldStatusBanned; + SendPacket(&outpack); + return; + } + + if (RuleB(World, DisallowDuplicateAccountLogins)) { + auto cle = client_list.FindCLEByLSID(utwr->lsaccountid); + if (cle != nullptr) { + auto status = cle->GetOnline(); + if (CLE_Status_Never != status && CLE_Status_Offline != status) { + utwrs->response = UserToWorldStatusAlreadyOnline; + SendPacket(&outpack); + return; + } + } + } + + SendPacket(&outpack); } void LoginServer::ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p) @@ -119,10 +137,13 @@ void LoginServer::ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p) outpack->size = sizeof(UsertoWorldResponse_Struct); outpack->pBuffer = new uchar[outpack->size]; memset(outpack->pBuffer, 0, outpack->size); + UsertoWorldResponse_Struct *utwrs = (UsertoWorldResponse_Struct *) outpack->pBuffer; utwrs->lsaccountid = utwr->lsaccountid; utwrs->ToID = utwr->FromID; strn0cpy(utwrs->login, utwr->login, 64); + utwrs->worldid = utwr->worldid; + utwrs->response = UserToWorldStatusSuccess; if (Config->Locked == true) { if ((status == 0 || status < 100) && (status != -2 || status != -1)) { @@ -161,12 +182,6 @@ void LoginServer::ProcessLSClientAuthLegacy(uint16_t opcode, EQ::Net::Packet &p) try { auto client_authentication_request = p.GetSerialize(0); - if (RuleI(World, AccountSessionLimit) >= 0) { - // Enforce the limit on the number of characters on the same account that can be - // online at the same time. - client_list.EnforceSessionLimit(client_authentication_request.loginserver_account_id); - } - LogDebug( "Processing Loginserver Auth Legacy | account_id [{0}] account_name [{1}] key [{2}] admin [{3}] ip [{4}] " "local_network [{5}]", @@ -201,12 +216,6 @@ void LoginServer::ProcessLSClientAuth(uint16_t opcode, EQ::Net::Packet &p) try { auto client_authentication_request = p.GetSerialize(0); - if (RuleI(World, AccountSessionLimit) >= 0) { - // Enforce the limit on the number of characters on the same account that can be - // online at the same time. - client_list.EnforceSessionLimit(client_authentication_request.loginserver_account_id); - } - LogDebug( "Processing Loginserver Auth | account_id [{0}] account_name [{1}] loginserver_name [{2}] key [{3}] " "admin [{4}] ip [{5}] local_network [{6}]", diff --git a/zone/command.cpp b/zone/command.cpp index e47b9be01..ba5b4d2aa 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -7355,6 +7355,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]"); } @@ -7368,7 +7369,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/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) { diff --git a/zone/mob_movement_manager.cpp b/zone/mob_movement_manager.cpp index cd47270d8..1fcc19187 100644 --- a/zone/mob_movement_manager.cpp +++ b/zone/mob_movement_manager.cpp @@ -813,11 +813,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); 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 {