mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-24 10:02:28 +00:00
Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a65d8836af | |||
| f5cfec529e | |||
| 9d9374ec19 | |||
| 979c819075 | |||
| ff4e549ec0 | |||
| a8ec176432 | |||
| 212f8a3062 | |||
| cca5fe3286 | |||
| 9ac15d7a4b | |||
| 23a187f6c1 | |||
| f3255c17da | |||
| 90eb9e9da2 | |||
| ffb5b2393f | |||
| cd32a5a47a | |||
| debc2644b1 | |||
| 9c9615e8bb | |||
| 53ec007459 | |||
| f5da6e18fc | |||
| 72ae1b0e0b | |||
| 780f8f8515 | |||
| 186834594f | |||
| f4310c5a06 | |||
| 4d77ba28fe | |||
| 222fd060a3 | |||
| 31d0adbacc | |||
| 9fe17f4d46 | |||
| 16d6014a87 | |||
| 7801b295d6 | |||
| 460468224e | |||
| 6bdc9b6ba5 | |||
| 7181b46608 | |||
| eb8cd1a5b4 | |||
| a8e65cdce1 | |||
| 1ba78d0988 | |||
| 35eb5b24dd | |||
| dfa90aaac5 | |||
| 525813be02 | |||
| 87b1d32ce8 | |||
| 5fdf976137 | |||
| 6a31af81ee | |||
| 7a28a6e9a7 |
+37
-29
@@ -26,6 +26,8 @@
|
||||
#EQEMU_BUILD_CLIENT_FILES
|
||||
#EQEMU_USE_MAP_MMFS
|
||||
#EQEMU_MAP_DIR
|
||||
#EQEMU_ARCH
|
||||
#EQEMU_ARCH_ALT
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
IF(POLICY CMP0074)
|
||||
@@ -57,33 +59,37 @@ ENDIF(MSVC OR MINGW)
|
||||
|
||||
IF(MSVC)
|
||||
IF(CMAKE_CL_64)
|
||||
SET(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib_x64")
|
||||
SET(MYSQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/mysql_x64")
|
||||
SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_x64")
|
||||
SET(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/openssl_x64")
|
||||
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
|
||||
IF(MSVC_VERSION GREATER 1800)
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v140/dynamic")
|
||||
ELSEIF(MSVC_VERSION EQUAL 1800)
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v120/dynamic")
|
||||
ELSE()
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v110/dynamic")
|
||||
ENDIF()
|
||||
SET(EQEMU_ARCH "x64")
|
||||
SET(EQEMU_ARCH_ALT "x64")
|
||||
ELSE(CMAKE_CL_64)
|
||||
SET(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib_x86")
|
||||
SET(MYSQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/mysql_x86")
|
||||
SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_x86")
|
||||
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
|
||||
SET(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/openssl_x86")
|
||||
IF(MSVC_VERSION GREATER 1800)
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v140/dynamic")
|
||||
ELSEIF(MSVC_VERSION EQUAL 1800)
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v120/dynamic")
|
||||
ELSE()
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v110/dynamic")
|
||||
ENDIF()
|
||||
SET(EQEMU_ARCH "x86")
|
||||
SET(EQEMU_ARCH_ALT "Win32")
|
||||
ENDIF(CMAKE_CL_64)
|
||||
|
||||
|
||||
SET(MYSQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/mysql_${EQEMU_ARCH}")
|
||||
|
||||
IF(VCPKG_TOOLCHAIN)
|
||||
IF(NOT MSVC_VERSION GREATER 1800)
|
||||
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
|
||||
ENDIF()
|
||||
ELSE(VCPKG_TOOLCHAIN)
|
||||
SET(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib_${EQEMU_ARCH}")
|
||||
SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_${EQEMU_ARCH}")
|
||||
SET(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/openssl_${EQEMU_ARCH}")
|
||||
|
||||
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
|
||||
ENDIF(VCPKG_TOOLCHAIN)
|
||||
|
||||
IF(SODIUM_INCLUDE_HINTS)
|
||||
IF(MSVC_VERSION GREATER 1800)
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/${EQEMU_ARCH_ALT}/Release/v140/dynamic")
|
||||
ELSEIF(MSVC_VERSION EQUAL 1800)
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/${EQEMU_ARCH_ALT}/Release/v120/dynamic")
|
||||
ELSE()
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/${EQEMU_ARCH_ALT}/Release/v110/dynamic")
|
||||
ENDIF()
|
||||
ENDIF(SODIUM_INCLUDE_HINTS)
|
||||
|
||||
#disable CRT warnings on windows cause they're annoying as shit and we use C functions everywhere
|
||||
OPTION(EQEMU_DISABLE_CRT_SECURE_WARNINGS "Disable Secure CRT Warnings" ON)
|
||||
IF(EQEMU_DISABLE_CRT_SECURE_WARNINGS)
|
||||
@@ -290,14 +296,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)
|
||||
@@ -313,14 +319,16 @@ 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")
|
||||
MESSAGE(STATUS "Could NOT find ZLIB - using ZLIBSTATIC package.")
|
||||
SET(EQEMU_BUILD_ZLIB ON)
|
||||
INCLUDE_DIRECTORIES(BEFORE SYSTEM "${CMAKE_CURRENT_BINARY_DIR}/libs/zlibng" "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng")
|
||||
SET(SERVER_LIBS ${SERVER_LIBS} "zlibstatic")
|
||||
ENDIF()
|
||||
|
||||
|
||||
@@ -70,3 +70,9 @@ forum, although pull requests will be much quicker and easier on all parties.
|
||||
* GPL Perl - GPL / ActiveState (under the assumption that this is a free project)
|
||||
* CPPUnit - GLP StringUtilities - Apache
|
||||
* LUA - MIT
|
||||
|
||||
## Contributors
|
||||
|
||||
<a href="https://github.com/EQEmu/server/graphs/contributors">
|
||||
<img src="https://contributors-img.firebaseapp.com/image?repo=EQEmu/server" />
|
||||
</a>
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||
-------------------------------------------------------
|
||||
== 7/22/2019 ==
|
||||
Uleat: Added script 'vcxproj_dependencies.py' - a script to help determine conflicting project dependencies (alpha-stage)
|
||||
|
||||
== 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:
|
||||
|
||||
@@ -213,6 +213,7 @@ SET(common_headers
|
||||
zone_numbers.h
|
||||
event/event_loop.h
|
||||
event/task.h
|
||||
event/task_scheduler.h
|
||||
event/timer.h
|
||||
json/json.h
|
||||
json/json-forwards.h
|
||||
|
||||
@@ -75,6 +75,7 @@ public:
|
||||
uint32 ReadUInt32() { uint32 value = *(uint32 *)(pBuffer + _rpos); _rpos += sizeof(uint32); return value; }
|
||||
uint32 ReadUInt32(uint32 Offset) const { uint32 value = *(uint32 *)(pBuffer + Offset); return value; }
|
||||
void ReadString(char *str) { uint32 len = static_cast<uint32>(strlen((char *)(pBuffer + _rpos))) + 1; memcpy(str, pBuffer + _rpos, len); _rpos += len; }
|
||||
void ReadString(std::string &str) { str = reinterpret_cast<char *>(pBuffer + _rpos); _rpos += str.length() + 1; }
|
||||
void ReadString(char *str, uint32 Offset, uint32 MaxLength) const;
|
||||
|
||||
uint32 GetWritePosition() { return _wpos; }
|
||||
|
||||
@@ -87,6 +87,7 @@ typedef enum {
|
||||
_eaMaxAppearance
|
||||
} EmuAppearance;
|
||||
|
||||
#define MT_NPCQuestSay 10
|
||||
// msg_type's for custom usercolors
|
||||
#define MT_Say 256
|
||||
#define MT_Tell 257
|
||||
@@ -523,4 +524,25 @@ static const uint8 SkillDamageTypes[EQEmu::skills::HIGHEST_SKILL + 1] = // chang
|
||||
|
||||
static const uint32 MAX_SPELL_DB_ID_VAL = 65535;
|
||||
|
||||
enum ChatChannelNames : uint16
|
||||
{
|
||||
ChatChannel_Guild = 0,
|
||||
ChatChannel_Group = 2,
|
||||
ChatChannel_Shout = 3,
|
||||
ChatChannel_Auction = 4,
|
||||
ChatChannel_OOC = 5,
|
||||
ChatChannel_Broadcast = 6,
|
||||
ChatChannel_Tell = 7,
|
||||
ChatChannel_Say = 8,
|
||||
ChatChannel_Petition = 10,
|
||||
ChatChannel_GMSAY = 11,
|
||||
ChatChannel_TellEcho = 14,
|
||||
ChatChannel_Raid = 15,
|
||||
|
||||
ChatChannel_UNKNOWN_Guild = 17,
|
||||
ChatChannel_UNKNOWN_GMSAY = 18,
|
||||
ChatChannel_UCSRelay = 20,
|
||||
ChatChannel_Emotes = 22
|
||||
};
|
||||
|
||||
#endif /*COMMON_EQ_CONSTANTS_H*/
|
||||
|
||||
@@ -1188,6 +1188,20 @@ struct SpecialMesg_Struct
|
||||
/*24*/ char message[1]; // What is being said?
|
||||
};
|
||||
|
||||
struct SpecialMesgHeader_Struct
|
||||
{
|
||||
/*00*/ char SpeakMode; // 2 shouts, 4 %1 %2, 3 %2, 5 tells group, 0 copy, default says
|
||||
/*01*/ char JournalMode; // 1 and 2 go to journal
|
||||
/*02*/ char language;
|
||||
/*03*/ uint32 msg_type; // Color of text (see MT_*** below)
|
||||
/*07*/ uint32 target_spawn_id; // Who is it being said to?
|
||||
/*11*/ // speaker's name
|
||||
/*xx*/ // unknown, location, client doesn't care
|
||||
/*xx*/ // unknown
|
||||
/*xx*/ // unknown
|
||||
/*xx*/ // message
|
||||
};
|
||||
|
||||
/*
|
||||
** When somebody changes what they're wearing or give a pet a weapon (model changes)
|
||||
** Length: 19 Bytes
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <queue>
|
||||
#include <future>
|
||||
|
||||
namespace EQ
|
||||
{
|
||||
namespace Event
|
||||
{
|
||||
class TaskScheduler
|
||||
{
|
||||
public:
|
||||
static const int DefaultThreadCount = 4;
|
||||
|
||||
TaskScheduler() : _running(false)
|
||||
{
|
||||
Start(DefaultThreadCount);
|
||||
}
|
||||
|
||||
TaskScheduler(size_t threads) : _running(false)
|
||||
{
|
||||
Start(threads);
|
||||
}
|
||||
|
||||
~TaskScheduler() {
|
||||
Stop();
|
||||
}
|
||||
|
||||
void Start(size_t threads) {
|
||||
if (true == _running) {
|
||||
return;
|
||||
}
|
||||
|
||||
_running = true;
|
||||
|
||||
for (size_t i = 0; i < threads; ++i) {
|
||||
_threads.push_back(std::thread(std::bind(&TaskScheduler::ProcessWork, this)));
|
||||
}
|
||||
}
|
||||
|
||||
void Stop() {
|
||||
if (false == _running) {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_lock);
|
||||
_running = false;
|
||||
}
|
||||
|
||||
_cv.notify_all();
|
||||
|
||||
for (auto &t : _threads) {
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Fn, typename... Args>
|
||||
auto Enqueue(Fn&& fn, Args&&... args) -> std::future<typename std::result_of<Fn(Args...)>::type> {
|
||||
using return_type = typename std::result_of<Fn(Args...)>::type;
|
||||
|
||||
auto task = std::make_shared<std::packaged_task<return_type()>>(
|
||||
std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...)
|
||||
);
|
||||
|
||||
std::future<return_type> res = task->get_future();
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_lock);
|
||||
|
||||
if (false == _running) {
|
||||
throw std::runtime_error("Enqueue on stopped scheduler.");
|
||||
}
|
||||
|
||||
_tasks.emplace([task]() { (*task)(); });
|
||||
}
|
||||
|
||||
_cv.notify_one();
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
void ProcessWork() {
|
||||
for (;;) {
|
||||
std::function<void()> work;
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_lock);
|
||||
_cv.wait(lock, [this] { return !_running || !_tasks.empty(); });
|
||||
|
||||
if (false == _running) {
|
||||
return;
|
||||
}
|
||||
|
||||
work = std::move(_tasks.front());
|
||||
_tasks.pop();
|
||||
}
|
||||
|
||||
work();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool _running = true;
|
||||
std::vector<std::thread> _threads;
|
||||
std::mutex _lock;
|
||||
std::condition_variable _cv;
|
||||
std::queue<std::function<void()>> _tasks;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+21
-33
@@ -3199,47 +3199,35 @@ namespace RoF
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
||||
SerializeBuffer buf(in->size);
|
||||
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // language
|
||||
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
std::string name;
|
||||
in->ReadString(name); // NPC names max out at 63 chars
|
||||
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
buf.WriteString(name);
|
||||
|
||||
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
|
||||
std::string old_message;
|
||||
std::string new_message;
|
||||
|
||||
in->ReadString(old_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->pBuffer = new unsigned char[in->size];
|
||||
buf.WriteString(new_message);
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
||||
|
||||
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]);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
dest->FastQueuePacket(&outapp, ack_req);
|
||||
delete in;
|
||||
}
|
||||
|
||||
ENCODE(OP_Stun)
|
||||
|
||||
+21
-33
@@ -3266,47 +3266,35 @@ namespace RoF2
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
||||
SerializeBuffer buf(in->size);
|
||||
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // language
|
||||
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
std::string name;
|
||||
in->ReadString(name); // NPC names max out at 63 chars
|
||||
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
buf.WriteString(name);
|
||||
|
||||
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
|
||||
std::string old_message;
|
||||
std::string new_message;
|
||||
|
||||
in->ReadString(old_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->pBuffer = new unsigned char[in->size];
|
||||
buf.WriteString(new_message);
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
||||
|
||||
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]);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
dest->FastQueuePacket(&outapp, ack_req);
|
||||
delete in;
|
||||
}
|
||||
|
||||
ENCODE(OP_Stun)
|
||||
|
||||
+21
-33
@@ -2069,47 +2069,35 @@ namespace SoD
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
||||
SerializeBuffer buf(in->size);
|
||||
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // language
|
||||
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
std::string name;
|
||||
in->ReadString(name); // NPC names max out at 63 chars
|
||||
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
buf.WriteString(name);
|
||||
|
||||
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
|
||||
std::string old_message;
|
||||
std::string new_message;
|
||||
|
||||
in->ReadString(old_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->pBuffer = new unsigned char[in->size];
|
||||
buf.WriteString(new_message);
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
||||
|
||||
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]);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
dest->FastQueuePacket(&outapp, ack_req);
|
||||
delete in;
|
||||
}
|
||||
|
||||
ENCODE(OP_Stun)
|
||||
|
||||
+21
-33
@@ -1720,47 +1720,35 @@ namespace SoF
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
||||
SerializeBuffer buf(in->size);
|
||||
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // language
|
||||
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
std::string name;
|
||||
in->ReadString(name);
|
||||
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
buf.WriteString(name);
|
||||
|
||||
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
|
||||
std::string old_message;
|
||||
std::string new_message;
|
||||
|
||||
in->ReadString(old_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->pBuffer = new unsigned char[in->size];
|
||||
buf.WriteString(new_message);
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
||||
|
||||
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]);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
dest->FastQueuePacket(&outapp, ack_req);
|
||||
delete in;
|
||||
}
|
||||
|
||||
ENCODE(OP_Stun)
|
||||
|
||||
+21
-33
@@ -1420,47 +1420,35 @@ namespace Titanium
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
||||
SerializeBuffer buf(in->size);
|
||||
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // language
|
||||
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
std::string name;
|
||||
in->ReadString(name); // NPC names max out at 63 chars
|
||||
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
buf.WriteString(name);
|
||||
|
||||
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
|
||||
std::string old_message;
|
||||
std::string new_message;
|
||||
|
||||
in->ReadString(old_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->pBuffer = new unsigned char[in->size];
|
||||
buf.WriteString(new_message);
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
||||
|
||||
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]);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
dest->FastQueuePacket(&outapp, ack_req);
|
||||
delete in;
|
||||
}
|
||||
|
||||
ENCODE(OP_TaskDescription)
|
||||
|
||||
+21
-33
@@ -2369,47 +2369,35 @@ namespace UF
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
||||
SerializeBuffer buf(in->size);
|
||||
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||
buf.WriteInt8(in->ReadUInt8()); // language
|
||||
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
std::string name;
|
||||
in->ReadString(name); // NPC names max out at 63 chars
|
||||
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
buf.WriteString(name);
|
||||
|
||||
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
buf.WriteInt32(in->ReadUInt32());
|
||||
|
||||
std::string old_message;
|
||||
std::string new_message;
|
||||
|
||||
in->ReadString(old_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->pBuffer = new unsigned char[in->size];
|
||||
buf.WriteString(new_message);
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
||||
|
||||
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]);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
dest->FastQueuePacket(&outapp, ack_req);
|
||||
delete in;
|
||||
}
|
||||
|
||||
ENCODE(OP_Stun)
|
||||
|
||||
+3
-3
@@ -205,6 +205,7 @@ RULE_CATEGORY_END()
|
||||
RULE_CATEGORY(GM)
|
||||
RULE_INT(GM, MinStatusToSummonItem, 250)
|
||||
RULE_INT(GM, MinStatusToZoneAnywhere, 250)
|
||||
RULE_INT(GM, MinStatusToLevelTarget, 100)
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(World)
|
||||
@@ -225,8 +226,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 +240,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, EnforceCharacterLimitAtLogin, false)
|
||||
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.
|
||||
|
||||
@@ -143,7 +143,7 @@ public:
|
||||
void WriteString(const char *str)
|
||||
{
|
||||
assert(str != nullptr);
|
||||
auto len = strlen(str) + 1;
|
||||
auto len = std::char_traits<char>::length(str) + 1;
|
||||
if (m_pos + len > m_capacity)
|
||||
Grow(m_capacity + len);
|
||||
memcpy(m_buffer + m_pos, str, len);
|
||||
|
||||
+20
-1
@@ -80,6 +80,7 @@
|
||||
#define ServerOP_GroupJoin 0x003e //for joining ooz folks
|
||||
#define ServerOP_UpdateSpawn 0x003f
|
||||
#define ServerOP_SpawnStatusChange 0x0040
|
||||
#define ServerOP_DropClient 0x0041 // DropClient
|
||||
#define ServerOP_ReloadTasks 0x0060
|
||||
#define ServerOP_DepopAllPlayersCorpses 0x0061
|
||||
#define ServerOP_ReloadTitles 0x0062
|
||||
@@ -213,6 +214,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
|
||||
{
|
||||
@@ -308,11 +318,17 @@ struct ServerZoneIncomingClient_Struct {
|
||||
uint32 accid;
|
||||
int16 admin;
|
||||
uint32 charid;
|
||||
uint32 lsid;
|
||||
bool tellsoff;
|
||||
char charname[64];
|
||||
char lskey[30];
|
||||
};
|
||||
|
||||
struct ServerZoneDropClient_Struct
|
||||
{
|
||||
uint32 lsid;
|
||||
};
|
||||
|
||||
struct ServerChangeWID_Struct {
|
||||
uint32 charid;
|
||||
uint32 newwid;
|
||||
@@ -343,7 +359,8 @@ struct ServerChannelMessage_Struct {
|
||||
bool noreply;
|
||||
uint16 chan_num;
|
||||
uint32 guilddbid;
|
||||
uint16 language;
|
||||
uint8 language;
|
||||
uint8 lang_skill;
|
||||
uint8 queued; // 0 = not queued, 1 = queued, 2 = queue full, 3 = offline
|
||||
char message[0];
|
||||
};
|
||||
@@ -856,6 +873,8 @@ struct ServerRaidGroupAction_Struct { //add / remove depends on opcode.
|
||||
struct ServerRaidMessage_Struct {
|
||||
uint32 rid;
|
||||
uint32 gid;
|
||||
uint8 language;
|
||||
uint8 lang_skill;
|
||||
char from[64];
|
||||
char message[0];
|
||||
};
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -861,5 +861,5 @@ if (ZLIB_ENABLE_TESTS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
FEATURE_SUMMARY(WHAT ALL INCLUDE_QUIET_PACKAGES)
|
||||
# FEATURE_SUMMARY(WHAT ALL INCLUDE_QUIET_PACKAGES)
|
||||
|
||||
|
||||
@@ -165,21 +165,26 @@ void WorldServer::ProcessUsertoWorldResp(uint16_t opcode, const EQ::Net::Packet
|
||||
|
||||
switch (utwr->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.IsTraceOn())
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
opcode_handlers_output
|
||||
opcode_handlers_output
|
||||
vcxproj_dependencies_output
|
||||
|
||||
@@ -0,0 +1,793 @@
|
||||
#! /usr/bin/env python
|
||||
#
|
||||
|
||||
"""
|
||||
'VCXProj-Dependencies' for EQEmulator
|
||||
|
||||
This script locates external dependency paths and generates lists for each
|
||||
project. In addition, it will cross-check these lists to determine if any
|
||||
discrepancies exist for any dependencies globally and across all projects.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
import sys
|
||||
import os
|
||||
import fnmatch
|
||||
|
||||
try:
|
||||
import xml.etree.cElementTree as ElementTree
|
||||
except ImportError:
|
||||
import xml.etree.ElementTree as ElementTree
|
||||
|
||||
from time import time, ctime
|
||||
|
||||
|
||||
QUIET_REPORT = True
|
||||
|
||||
include_projects = []
|
||||
exclude_projects = ['VCTargetsPath', 'CompilerIdC', 'CompilerIdCXX'] # these three should be left in by default
|
||||
|
||||
base_path = os.getcwd()[:-14] # '/utils/scripts'
|
||||
base_path = base_path.replace('\\', '/')
|
||||
|
||||
file_extensions = ['vcxproj']
|
||||
project_paths = []
|
||||
master_dependencies = []
|
||||
# {[project]:{[build]:{[resource]:{[reference]:[paths]}}}}
|
||||
project_dependencies = {}
|
||||
|
||||
out_files = {}
|
||||
|
||||
col1 = '{0}'.format(' ' * 0)
|
||||
col2 = '{0}'.format(' ' * 2)
|
||||
col3 = '{0}'.format(' ' * 4)
|
||||
col4 = '{0}'.format(' ' * 6)
|
||||
col5 = '{0}'.format(' ' * 8)
|
||||
|
||||
|
||||
def main():
|
||||
""" main """
|
||||
|
||||
if not create_output_directory():
|
||||
exit()
|
||||
|
||||
if not open_output_files():
|
||||
exit()
|
||||
|
||||
print 'Locating project paths...'
|
||||
locate_project_paths()
|
||||
print '..project count: {0}'.format(len(project_paths))
|
||||
print 'Parsing project files...'
|
||||
parse_project_files()
|
||||
print 'Building master dependencies...'
|
||||
build_master_dependencies()
|
||||
print '..dependency count: {0}'.format(len(master_dependencies))
|
||||
print 'Checking for version discrepancies...'
|
||||
check_for_version_discrepancies()
|
||||
close_output_files()
|
||||
print '\n__fin__'
|
||||
|
||||
return
|
||||
|
||||
|
||||
def create_output_directory():
|
||||
""" Check for output directory - create if does not exist """
|
||||
|
||||
try:
|
||||
output_path = '{0}/utils/scripts/vcxproj_dependencies_output'.format(base_path)
|
||||
if not os.path.exists(output_path):
|
||||
os.mkdir(output_path)
|
||||
|
||||
return True
|
||||
|
||||
except IOError:
|
||||
print('(Exception Error: {0}) create_output_directory()'.format(sys.exc_info()[0]))
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def open_output_files():
|
||||
""" Open all output files """
|
||||
|
||||
try:
|
||||
file_name = '{0}/utils/scripts/vcxproj_dependencies_output/ProjectPaths.txt'.format(base_path)
|
||||
out_files['ProjectPaths'] = open(file_name, 'w')
|
||||
file_name = '{0}/utils/scripts/vcxproj_dependencies_output/MasterDependencies.txt'.format(base_path)
|
||||
out_files['MasterDependencies'] = open(file_name, 'w')
|
||||
file_name = '{0}/utils/scripts/vcxproj_dependencies_output/ProjectDependencies.txt'.format(base_path)
|
||||
out_files['ProjectDependencies'] = open(file_name, 'w')
|
||||
file_name = '{0}/utils/scripts/vcxproj_dependencies_output/ContextTree.txt'.format(base_path)
|
||||
out_files['ContextTree'] = open(file_name, 'w')
|
||||
file_name = '{0}/utils/scripts/vcxproj_dependencies_output/DiscrepancyReport.txt'.format(base_path)
|
||||
out_files['DiscrepancyReport'] = open(file_name, 'w')
|
||||
for file in out_files:
|
||||
out_files[file].write('>> \'VCXProj-Dependencies\' {0} file\n'.format(file))
|
||||
out_files[file].write('>> file generated @ {0}\n\n'.format(ctime(time())))
|
||||
|
||||
return True
|
||||
|
||||
except IOError:
|
||||
print('(Exception Error: {0}) open_output_files()'.format(sys.exc_info()[0]))
|
||||
close_output_files()
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def locate_project_paths():
|
||||
""" Locate vcxproj files in the build folder """
|
||||
|
||||
for root, dirs, files in os.walk('{0}/build'.format(base_path)):
|
||||
for name in files:
|
||||
project = name.split('.')[0]
|
||||
if not len(include_projects) == 0 and project not in include_projects:
|
||||
continue
|
||||
if not len(exclude_projects) == 0 and project in exclude_projects:
|
||||
continue
|
||||
for extension in file_extensions:
|
||||
if fnmatch.fnmatch(name, '*.{0}'.format(extension)):
|
||||
project_paths.append(os.path.join(root, name).replace('\\', '/').lower())
|
||||
for path in project_paths:
|
||||
out_files['ProjectPaths'].write('{0};\n'.format(path))
|
||||
|
||||
return
|
||||
|
||||
|
||||
def fixup_path(project_path, dependency_path):
|
||||
""" Fix-up malformed dependency paths """
|
||||
|
||||
trailing = dependency_path.replace('\\', '/')
|
||||
if '../' in trailing:
|
||||
if trailing[:3] == '../': # windows
|
||||
leading = project_path[:project_path.rfind('/')]
|
||||
while trailing[:3] == '../':
|
||||
leading = leading[:leading.rfind('/')]
|
||||
trailing = trailing[3:]
|
||||
trailing = trailing.lower()
|
||||
trailing = '{0}/{1}'.format(leading, trailing)
|
||||
else: # unix
|
||||
print '..processing unix-style path fix-up'
|
||||
while '../' in trailing:
|
||||
backout = trailing.find('../')
|
||||
backdir = trailing.rfind('/', 0, backout - 1)
|
||||
trailing = trailing.replace(trailing[backdir:backout + 2], '', 1)
|
||||
trailing = trailing.lower()
|
||||
else:
|
||||
trailing = trailing.lower()
|
||||
|
||||
return trailing
|
||||
|
||||
|
||||
def parse_project_files():
|
||||
""" Parse each vcxproj file's xml data """
|
||||
|
||||
for key1 in project_paths:
|
||||
with open(key1, 'r') as vcxproj_file:
|
||||
project_dependencies[key1] = {}
|
||||
xml_tree = ElementTree.ElementTree(file=vcxproj_file)
|
||||
for element1 in xml_tree.getroot():
|
||||
if not element1.tag[-19:] == 'ItemDefinitionGroup':
|
||||
continue
|
||||
# add '.split('|')[0]' to remove the '|Win##' attribute
|
||||
key2 = element1.attrib['Condition'].split('==')[1][1:-1]
|
||||
project_dependencies[key1][key2] = {}
|
||||
for element2 in element1.getiterator():
|
||||
if element2.tag[-9:] == 'ClCompile':
|
||||
key3 = element2.tag[-9:]
|
||||
project_dependencies[key1][key2][key3] = {}
|
||||
for element3 in element2.getiterator():
|
||||
if element3.tag[-28:] == 'AdditionalIncludeDirectories':
|
||||
key4 = element3.tag[-28:]
|
||||
project_dependencies[key1][key2][key3][key4] = []
|
||||
paths = element3.text.split(';')
|
||||
for path in paths:
|
||||
project_dependencies[key1][key2][key3][key4].append(fixup_path(key1, path))
|
||||
elif element2.tag[-15:] == 'ResourceCompile':
|
||||
key3 = element2.tag[-15:]
|
||||
project_dependencies[key1][key2][key3] = {}
|
||||
for element3 in element2.getiterator():
|
||||
if element3.tag[-28:] == 'AdditionalIncludeDirectories':
|
||||
key4 = element3.tag[-28:]
|
||||
project_dependencies[key1][key2][key3][key4] = []
|
||||
paths = element3.text.split(';')
|
||||
for path in paths:
|
||||
project_dependencies[key1][key2][key3][key4].append(fixup_path(key1, path))
|
||||
elif element2.tag[-4:] == 'Midl':
|
||||
key3 = element2.tag[-4:]
|
||||
project_dependencies[key1][key2][key3] = {}
|
||||
for element3 in element2.getiterator():
|
||||
if element3.tag[-28:] == 'AdditionalIncludeDirectories':
|
||||
key4 = element3.tag[-28:]
|
||||
project_dependencies[key1][key2][key3][key4] = []
|
||||
paths = element3.text.split(';')
|
||||
for path in paths:
|
||||
project_dependencies[key1][key2][key3][key4].append(fixup_path(key1, path))
|
||||
elif element2.tag[-4:] == 'Link':
|
||||
key3 = element2.tag[-4:]
|
||||
project_dependencies[key1][key2][key3] = {}
|
||||
for element3 in element2.getiterator():
|
||||
if element3.tag[-22:] == 'AdditionalDependencies':
|
||||
key4 = element3.tag[-22:]
|
||||
project_dependencies[key1][key2][key3][key4] = []
|
||||
paths = element3.text.split(';')
|
||||
for path in paths:
|
||||
project_dependencies[key1][key2][key3][key4].append(fixup_path(key1, path))
|
||||
if element3.tag[-28:] == 'AdditionalLibraryDirectories':
|
||||
key4 = element3.tag[-28:]
|
||||
project_dependencies[key1][key2][key3][key4] = []
|
||||
paths = element3.text.split(';')
|
||||
for path in paths:
|
||||
project_dependencies[key1][key2][key3][key4].append(fixup_path(key1, path))
|
||||
vcxproj_file.close()
|
||||
|
||||
return
|
||||
|
||||
|
||||
def build_master_dependencies():
|
||||
""" Build master dependencies list """
|
||||
|
||||
def write(message):
|
||||
""" internal 'ProjectDependencies' write method - performed here so processing takes place after fix-up """
|
||||
|
||||
out_files['ProjectDependencies'].write('{0}\n'.format(message))
|
||||
|
||||
return
|
||||
|
||||
for key1 in project_dependencies:
|
||||
write('{0}<Project Path="{1}">'.format(col1, key1))
|
||||
for key2 in project_dependencies[key1]:
|
||||
write('{0}<Build Type="{1}">'.format(col2, key2))
|
||||
for key3 in project_dependencies[key1][key2]:
|
||||
write('{0}<Resource Type="{1}">'.format(col3, key3))
|
||||
for key4 in project_dependencies[key1][key2][key3]:
|
||||
write('{0}<Reference Type="{1}">'.format(col4, key4))
|
||||
for path in project_dependencies[key1][key2][key3][key4]:
|
||||
write('{0}{1}'.format(col4, path))
|
||||
if path not in master_dependencies:
|
||||
master_dependencies.append(path)
|
||||
write('{0}</Reference>'.format(col4))
|
||||
write('{0}</Resource>'.format(col3))
|
||||
write('{0}</Build>'.format(col2))
|
||||
write('{0}</Project>'.format(col1))
|
||||
master_dependencies.sort()
|
||||
for path in master_dependencies:
|
||||
out_files['MasterDependencies'].write('{0}\n'.format(path))
|
||||
|
||||
return
|
||||
|
||||
|
||||
def check_for_version_discrepancies():
|
||||
""" Check for dependency version discrepancies """
|
||||
|
||||
def twrite(message):
|
||||
""" internal 'ContextTree' write method """
|
||||
|
||||
out_files['ContextTree'].write('{0}\n'.format(message))
|
||||
|
||||
return
|
||||
|
||||
def rwrite(message):
|
||||
""" internal 'DiscrepancyReport' write method """
|
||||
|
||||
out_files['DiscrepancyReport'].write('{0}\n'.format(message))
|
||||
|
||||
return
|
||||
|
||||
libraries = [
|
||||
'mysql',
|
||||
'zlib',
|
||||
'perl',
|
||||
'lua',
|
||||
'boost',
|
||||
'sodium',
|
||||
'openssl'
|
||||
]
|
||||
references = [
|
||||
'include',
|
||||
'source',
|
||||
'library'
|
||||
]
|
||||
priorities = {
|
||||
0: 'NOT FOUND',
|
||||
1: 'install',
|
||||
2: 'dependencies',
|
||||
3: 'libs',
|
||||
4: 'vcpkg',
|
||||
5: 'static',
|
||||
6: 'submodule'
|
||||
}
|
||||
# use all lowercase for path description
|
||||
# use forward slash ('/') for directory name separators
|
||||
# use '|' token for multiple hints ('my_file_path_1|my_file_path_2')
|
||||
# use '!!' token for explicit argument ('/perl/core!!' will find '../perl/core' but not '../perl/core/perl512.lib')
|
||||
# use '##' token for joined hints ('my_file_##_1')
|
||||
# use '&&', '^' and '@' tokens for multiple argument hints ('my_file_&&path_1^path_2^path_3@')
|
||||
# (i.e., 'my_file_path_1|my_file_##_2|my_##_##&&_3^_4!!@')
|
||||
# {[library]:{[reference]:[[priority]:hint]}}
|
||||
hints = {
|
||||
# Notes:
|
||||
'mysql': {
|
||||
'include': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/dependencies/mysql_##/include', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'source': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'library': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'dependencies/mysql_##/lib', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
]
|
||||
},
|
||||
'zlib': {
|
||||
'include': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/zlib_x##/include', # 'dependencies'
|
||||
# not sure if this should be '/libs/zlibng' or '/build/libs/zlibng' based on cmake behavior
|
||||
'/server/build/libs/zlibng!!', # 'libs'
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/include', # 'vcpkg'
|
||||
'/server/build/libs/zlibng!!', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'source': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'', # 'dependencies'
|
||||
'/server/libs/zlibng!!', # 'libs'
|
||||
'', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'library': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/zlib_x##/lib/zdll.lib', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/&&lib/zlib.lib!!'
|
||||
'^debug/lib/zlibd.lib!!@', # 'vcpkg'
|
||||
'/server/build/libs/zlibng/&&debug/zlibstaticd.lib!!^minsizerel/zlibstatic.lib!!'
|
||||
'^release/zlibstatic.lib!!^relwithdebinfo/zlibstatic.lib!!@', # 'static'
|
||||
'' # 'submodule'
|
||||
]
|
||||
},
|
||||
'perl': {
|
||||
'include': [
|
||||
'', # 'NOT FOUND'
|
||||
'/perl/lib/core!!', # 'install'
|
||||
'', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'source': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'library': [
|
||||
'', # 'NOT FOUND'
|
||||
'/perl/lib/core/perl51##.lib', # 'install'
|
||||
'', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
]
|
||||
},
|
||||
'lua': {
|
||||
'include': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/luaj_x##/src', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/include', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'source': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/luaj_x##/src', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'library': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/luaj_x##/bin/lua51.lib', # 'dependencies'
|
||||
'', # 'libs'
|
||||
# debug lua package likely incorrect..should be 'lua51d.lib' - or whatever debug version is
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/&&lib/lua51.lib!!'
|
||||
'^debug/lib/lua51.lib!!@', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
]
|
||||
},
|
||||
'boost': {
|
||||
'include': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/boost', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/include', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'source': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/include', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'library': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/boost', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/lib!!', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
]
|
||||
},
|
||||
'sodium': {
|
||||
'include': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/libsodium/include', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/include', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'source': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'library': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/libsodium/##/dynamic/libsodium.lib', # 'dependencies'
|
||||
'', # 'libs'
|
||||
# debug libsodium package likely incorrect..should be 'libsodiumd.lib' - or whatever debug version is
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/&&lib/libsodium.lib!!^'
|
||||
'debug/lib/libsodium.lib!!@', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
]
|
||||
},
|
||||
'openssl': {
|
||||
'include': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/openssl_x##/include', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/include', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'source': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'library': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/openssl_x##/lib/VC/&&libeay32MD.lib!!^libeay32MDd.lib!!^'
|
||||
'ssleay32MD.lib!!^ssleay32MDd.lib!!@', # 'dependencies'
|
||||
'', # 'libs'
|
||||
# debug openssl package likely incorrect..should be
|
||||
# 'libeay32d.lib' and 'ssleay32d.lib' - or whatever debug versions are
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/&&lib/libeay32.lib!!^'
|
||||
'lib/ssleay32.lib!!^debug/lib/libeay32.lib!!^debug/lib/ssleay32.lib!!@', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
]
|
||||
}
|
||||
}
|
||||
# {[project]:{[build]:{[resource]:{[library]:{[reference]:priority}}}}}
|
||||
context_tree = {}
|
||||
# {[library]:priority}
|
||||
global_priorities = {}
|
||||
# {[build]:{[library]:priority}}
|
||||
build_priorities = {}
|
||||
# loop for discovering first occurence dependency sources (assumes same search precedence as compiler includes)
|
||||
for project in project_dependencies:
|
||||
if project not in context_tree.keys():
|
||||
context_tree[project] = {}
|
||||
for build in project_dependencies[project]:
|
||||
if build not in context_tree[project].keys():
|
||||
context_tree[project][build] = {}
|
||||
if build not in build_priorities.keys():
|
||||
build_priorities[build] = {}
|
||||
for resource in project_dependencies[project][build]:
|
||||
if resource not in context_tree[project][build].keys():
|
||||
context_tree[project][build][resource] = {}
|
||||
for reference_project in project_dependencies[project][build][resource]:
|
||||
for path in project_dependencies[project][build][resource][reference_project]:
|
||||
for library in libraries:
|
||||
if library not in context_tree[project][build][resource].keys():
|
||||
context_tree[project][build][resource][library] = {}
|
||||
if library not in build_priorities[build].keys():
|
||||
build_priorities[build][library] = 0
|
||||
if library not in global_priorities.keys():
|
||||
global_priorities[library] = 0
|
||||
for reference in references:
|
||||
if reference not in context_tree[project][build][resource][library].keys():
|
||||
context_tree[project][build][resource][library][reference] = 0
|
||||
elif not context_tree[project][build][resource][library][reference] == 0:
|
||||
continue
|
||||
for priority in priorities:
|
||||
if hints[library][reference][priority] == '':
|
||||
continue
|
||||
hint_found = False
|
||||
for hint in hints[library][reference][priority].split('|'):
|
||||
if not find_hint_in_path(hint, path) == -1:
|
||||
context_tree[project][build][resource][library][reference] = priority
|
||||
if context_tree[project][build][resource][library][reference] >\
|
||||
build_priorities[build][library]:
|
||||
build_priorities[build][library] =\
|
||||
context_tree[project][build][resource][library][reference]
|
||||
if context_tree[project][build][resource][library][reference] >\
|
||||
global_priorities[library]:
|
||||
global_priorities[library] =\
|
||||
context_tree[project][build][resource][library][reference]
|
||||
hint_found = True
|
||||
break
|
||||
if hint_found is True:
|
||||
break
|
||||
# loop for hack to fix odd behavior caused by 'FindZLIB.cmake' - ref: '../server/build/libs/zlibng/zconf.h'
|
||||
# this does not change anything in the build files..only silences a false discrepancy due to mixing priority types
|
||||
if global_priorities['zlib'] == 5:
|
||||
for project in context_tree:
|
||||
for build in context_tree[project]:
|
||||
for resource in context_tree[project][build]:
|
||||
if context_tree[project][build][resource]['zlib']['source'] == 3:
|
||||
context_tree[project][build][resource]['zlib']['source'] = 5
|
||||
if context_tree[project][build][resource]['zlib']['include'] == 3:
|
||||
context_tree[project][build][resource]['zlib']['include'] = 5
|
||||
# loop for dumping 'global_priorities'
|
||||
twrite('{0}<Global>'.format(col1))
|
||||
for library in libraries:
|
||||
twrite('{0}<Library Name="{1}">{2}</Library>'.format(col2, library, global_priorities[library]))
|
||||
twrite('{0}</Global>'.format(col1))
|
||||
twrite('')
|
||||
# loop for dumping 'build_priorities'
|
||||
for build in build_priorities:
|
||||
twrite('{0}<Build Type="{1}">'.format(col1, build))
|
||||
for library in libraries:
|
||||
twrite('{0}<Library Name="{1}">{2}</Library>'.format(col2, library, build_priorities[build][library]))
|
||||
twrite('{0}</Build>'.format(col1))
|
||||
twrite('')
|
||||
# loop for dumping 'context_tree'
|
||||
for project in context_tree:
|
||||
twrite('{0}<Project Path="{1}">'.format(col1, project))
|
||||
for build in context_tree[project]:
|
||||
twrite('{0}<Built Type="{1}">'.format(col2, build))
|
||||
for resource in context_tree[project][build]:
|
||||
twrite('{0}<Resource Name="{1}">'.format(col3, resource))
|
||||
for library in context_tree[project][build][resource]:
|
||||
twrite('{0}<Library Name="{1}">'.format(col4, library))
|
||||
for reference in context_tree[project][build][resource][library]:
|
||||
twrite(
|
||||
'{0}<Reference Name="{1}">{2}</Reference>'.format(
|
||||
col5,
|
||||
reference,
|
||||
context_tree[project][build][resource][library][reference]
|
||||
)
|
||||
)
|
||||
twrite('{0}</Library>'.format(col4))
|
||||
twrite('{0}</Resource>'.format(col3))
|
||||
twrite('{0}</Build>'.format(col2))
|
||||
twrite('{0}</Project>'.format(col1))
|
||||
if QUIET_REPORT is False:
|
||||
for library in libraries:
|
||||
rwrite(
|
||||
'> Global Library \'{0}\' status: \'{1}\' ({2})'.format(
|
||||
library,
|
||||
priorities[global_priorities[library]],
|
||||
global_priorities[library]
|
||||
)
|
||||
)
|
||||
# loop for identifying dependency discrepancies
|
||||
for project in context_tree:
|
||||
for build in context_tree[project]:
|
||||
for resource in context_tree[project][build]:
|
||||
for library in context_tree[project][build][resource]:
|
||||
if global_priorities[library] == 0:
|
||||
if QUIET_REPORT is False:
|
||||
rwrite(
|
||||
'> No Global Library \'{0}\' .. skipping Project:Build:Resource'
|
||||
' "{1}":"{2}":"{3}"'.format(
|
||||
library,
|
||||
project,
|
||||
build,
|
||||
resource
|
||||
)
|
||||
)
|
||||
continue
|
||||
if build_priorities[build][library] == 0:
|
||||
if QUIET_REPORT is False:
|
||||
rwrite(
|
||||
'> No Build Library \'{0}\' .. skipping Project:Build:Resource'
|
||||
' "{1}":"{2}":"{3}"'.format(
|
||||
library,
|
||||
project,
|
||||
build,
|
||||
resource
|
||||
)
|
||||
)
|
||||
continue
|
||||
for reference in context_tree[project][build][resource][library]:
|
||||
if context_tree[project][build][resource][library][reference] == 0:
|
||||
continue
|
||||
if not global_priorities[library] == context_tree[project][build][resource][library][reference]:
|
||||
rwrite(
|
||||
'> Global-Project Library \'{0}\' mis-match \'{1}!={2}\''
|
||||
' ({3}!={4}) Project:Build:Resource "{5}":"{6}":"{7}"'.format(
|
||||
library,
|
||||
priorities[global_priorities[library]],
|
||||
priorities[context_tree[project][build][resource][library][reference]],
|
||||
global_priorities[library],
|
||||
context_tree[project][build][resource][library][reference],
|
||||
project,
|
||||
build,
|
||||
resource
|
||||
)
|
||||
)
|
||||
# 'builds' are allowed to have different dependencies..so, we'll start crossing at 'resource'
|
||||
for cross_resource in context_tree[project][build]:
|
||||
for cross_reference in context_tree[project][build][cross_resource][library]:
|
||||
if cross_resource == resource and cross_reference == reference:
|
||||
continue
|
||||
if context_tree[project][build][cross_resource][library][cross_reference] == 0:
|
||||
continue
|
||||
if QUIET_REPORT is False and\
|
||||
not context_tree[project][build][cross_resource][library][cross_reference] ==\
|
||||
context_tree[project][build][resource][library][reference]:
|
||||
rwrite(
|
||||
'> Project Library \'{0}\' mis-match \'{1}:{2}:{3}!={4}:{5}:{6}\''
|
||||
' ({7}!={8}) Project:Build "{9}":"{10}"'.format(
|
||||
library,
|
||||
resource,
|
||||
reference,
|
||||
priorities[context_tree[project][build][resource][library][reference]],
|
||||
cross_resource,
|
||||
cross_reference,
|
||||
priorities[context_tree[project][build][cross_resource][library]
|
||||
[cross_reference]],
|
||||
context_tree[project][build][resource][library][reference],
|
||||
context_tree[project][build][cross_resource][library][cross_reference],
|
||||
project,
|
||||
build
|
||||
)
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
|
||||
def find_hint_in_path(hint, path):
|
||||
"""
|
||||
Helper function for parsing and checking for hints in paths
|
||||
|
||||
Hints strings should be split ('|') and passed as a singular hint into this function
|
||||
|
||||
"""
|
||||
|
||||
if hint == '' or path == '':
|
||||
return -1
|
||||
|
||||
joined_index = hint.find('##')
|
||||
pretext_index = hint.find('&&')
|
||||
if joined_index == -1 and pretext_index == -1:
|
||||
if '^' in hint or '@' in hint:
|
||||
print '..malformed or improper handling of hint: \'{0}\' path: \'{1}\''.format(hint, path)
|
||||
|
||||
return -1
|
||||
|
||||
explicit_index = hint.find('!!')
|
||||
if explicit_index == -1:
|
||||
return path.find(hint)
|
||||
|
||||
else:
|
||||
explicit_hint = hint[:explicit_index]
|
||||
found_index = path.find(explicit_hint)
|
||||
if (len(explicit_hint) + found_index) == len(path):
|
||||
return found_index
|
||||
|
||||
else:
|
||||
return -1
|
||||
|
||||
elif (not joined_index == -1 and pretext_index == -1) or\
|
||||
(not joined_index == -1 and not pretext_index == -1 and joined_index < pretext_index):
|
||||
start_index = 0
|
||||
for partial_hint in hint.split('##', 1):
|
||||
if partial_hint == '':
|
||||
continue
|
||||
found_index = find_hint_in_path(partial_hint, path[start_index:])
|
||||
if found_index == -1:
|
||||
return found_index
|
||||
|
||||
start_index = found_index + len(partial_hint)
|
||||
|
||||
return start_index
|
||||
|
||||
elif (joined_index == -1 and not pretext_index == -1) or\
|
||||
(not joined_index == -1 and not pretext_index == -1 and joined_index > pretext_index):
|
||||
pretext_hints = hint.split('&&', 1)
|
||||
found_index = 0
|
||||
if not pretext_hints[0] == '':
|
||||
found_index = find_hint_in_path(pretext_hints[0], path)
|
||||
if found_index == -1:
|
||||
return found_index
|
||||
|
||||
start_index = found_index + len(pretext_hints[0])
|
||||
partial_hints = pretext_hints[1].split('@', 1)
|
||||
for partial_hint in partial_hints:
|
||||
if partial_hint == '':
|
||||
continue
|
||||
for alt_hint in partial_hint.split('^'):
|
||||
if alt_hint == '':
|
||||
continue
|
||||
found_index = find_hint_in_path(alt_hint, path[start_index:])
|
||||
if found_index == 0:
|
||||
if not partial_hints[1] == '':
|
||||
print '..unhandled hint method: \'{0}\''.format(partial_hints[1])
|
||||
else:
|
||||
return found_index
|
||||
|
||||
return -1
|
||||
|
||||
else:
|
||||
return -1
|
||||
|
||||
|
||||
def close_output_files():
|
||||
""" Close all output files """
|
||||
|
||||
while not len(out_files) == 0:
|
||||
key = out_files.keys()[0]
|
||||
out_files[key].close()
|
||||
del out_files[key]
|
||||
|
||||
return
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -393,7 +393,8 @@
|
||||
9137|2018_12_12_client_faction_tables.sql|SHOW TABLES LIKE 'faction_base_data'|empty|
|
||||
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|
|
||||
9140|2019_07_03_update_range.sql|SHOW COLUMNS FROM `zone` 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
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`)
|
||||
VALUES (1, 'GM:MinStatusToLevelTarget', '100', 'GM status needed to use #level on your target');
|
||||
@@ -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.');
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE `npc_types` ADD COLUMN `flymode` tinyint(4) NOT NULL DEFAULT -1;
|
||||
+1
-1
@@ -287,7 +287,7 @@ void Adventure::Finished(AdventureWinStatus ws)
|
||||
ClientListEntry *current = client_list.FindCharacter((*iter).c_str());
|
||||
if(current)
|
||||
{
|
||||
if(current->Online() == CLE_Status_InZone)
|
||||
if(current->Online() == CLE_Status::InZone)
|
||||
{
|
||||
//We can send our packets only.
|
||||
auto pack =
|
||||
|
||||
+11
-11
@@ -88,7 +88,6 @@ extern volatile bool UCSServerAvailable_;
|
||||
|
||||
Client::Client(EQStreamInterface* ieqs)
|
||||
: autobootup_timeout(RuleI(World, ZoneAutobootTimeoutMS)),
|
||||
CLE_keepalive_timer(RuleI(World, ClientKeepaliveTimeoutMS)),
|
||||
connect(1000),
|
||||
eqs(ieqs)
|
||||
{
|
||||
@@ -115,7 +114,7 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
|
||||
Client::~Client() {
|
||||
if (RunLoops && cle && zone_id == 0)
|
||||
cle->SetOnline(CLE_Status_Offline);
|
||||
cle->SetOnline(CLE_Status::Offline);
|
||||
|
||||
numclients--;
|
||||
|
||||
@@ -185,7 +184,7 @@ void Client::SendExpansionInfo() {
|
||||
|
||||
void Client::SendCharInfo() {
|
||||
if (cle) {
|
||||
cle->SetOnline(CLE_Status_CharSelect);
|
||||
cle->SetOnline(CLE_Status::CharSelect);
|
||||
}
|
||||
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskRoFAndLater) {
|
||||
@@ -461,7 +460,7 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) {
|
||||
// Track who is in and who is out of the game
|
||||
char *inout= (char *) "";
|
||||
|
||||
if (cle->GetOnline() == CLE_Status_Never){
|
||||
if (cle->GetOnline() == CLE_Status::Never){
|
||||
// Desktop -> Char Select
|
||||
inout = (char *) "In";
|
||||
}
|
||||
@@ -474,7 +473,7 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) {
|
||||
// Either from a fresh client launch or coming back from the game.
|
||||
// Exiting the game entirely does not come through here.
|
||||
// Could use a Logging Out Completely message somewhere.
|
||||
cle->SetOnline(CLE_Status_CharSelect);
|
||||
cle->SetOnline(CLE_Status::CharSelect);
|
||||
|
||||
Log(Logs::General, Logs::World_Server,
|
||||
"Account (%s) Logging(%s) to character select :: LSID: %d ",
|
||||
@@ -1076,7 +1075,7 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
||||
{
|
||||
// I don't see this getting executed on logout
|
||||
eqs->Close();
|
||||
cle->SetOnline(CLE_Status_Offline); //allows this player to log in again without an ip restriction.
|
||||
cle->SetOnline(CLE_Status::Offline); //allows this player to log in again without an ip restriction.
|
||||
return false;
|
||||
}
|
||||
case OP_ZoneChange:
|
||||
@@ -1124,10 +1123,9 @@ bool Client::Process() {
|
||||
SendApproveWorld();
|
||||
connect.Disable();
|
||||
}
|
||||
if (CLE_keepalive_timer.Check()) {
|
||||
if (cle)
|
||||
cle->KeepAlive();
|
||||
}
|
||||
|
||||
if (cle)
|
||||
cle->KeepAlive();
|
||||
|
||||
/************ Get all packets from packet manager out queue and process them ************/
|
||||
EQApplicationPacket *app = 0;
|
||||
@@ -1191,6 +1189,8 @@ void Client::EnterWorld(bool TryBootup) {
|
||||
else
|
||||
zone_server = zoneserver_list.FindByZoneID(zone_id);
|
||||
|
||||
//Tell all the zones to drop any client with this lsid because we're coming back in.
|
||||
zoneserver_list.DropClient(GetLSID());
|
||||
|
||||
const char *zone_name = database.GetZoneName(zone_id, true);
|
||||
if (zone_server) {
|
||||
@@ -1344,7 +1344,7 @@ void Client::Clearance(int8 response)
|
||||
safe_delete(outapp);
|
||||
|
||||
if (cle)
|
||||
cle->SetOnline(CLE_Status_Zoning);
|
||||
cle->SetOnline(CLE_Status::Zoning);
|
||||
}
|
||||
|
||||
void Client::TellClientZoneUnavailable() {
|
||||
|
||||
@@ -94,7 +94,6 @@ private:
|
||||
void SetClassLanguages(PlayerProfile_Struct *pp);
|
||||
|
||||
ClientListEntry* cle;
|
||||
Timer CLE_keepalive_timer;
|
||||
Timer connect;
|
||||
bool firstlogin;
|
||||
bool seen_character_select;
|
||||
|
||||
+18
-16
@@ -73,7 +73,7 @@ ClientListEntry::ClientListEntry(uint32 in_id, uint32 iAccID, const char* iAccNa
|
||||
memset(pLFGComments, 0, 64);
|
||||
}
|
||||
|
||||
ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList_Struct* scl, int8 iOnline)
|
||||
ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList_Struct* scl, CLE_Status iOnline)
|
||||
: id(in_id)
|
||||
{
|
||||
ClearVars(true);
|
||||
@@ -94,7 +94,7 @@ ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList
|
||||
pLFGMatchFilter = false;
|
||||
memset(pLFGComments, 0, 64);
|
||||
|
||||
if (iOnline >= CLE_Status_Zoning)
|
||||
if (iOnline >= CLE_Status::Zoning)
|
||||
Update(iZS, scl, iOnline);
|
||||
else
|
||||
SetOnline(iOnline);
|
||||
@@ -115,22 +115,24 @@ void ClientListEntry::SetChar(uint32 iCharID, const char* iCharName) {
|
||||
strn0cpy(pname, iCharName, sizeof(pname));
|
||||
}
|
||||
|
||||
void ClientListEntry::SetOnline(ZoneServer* iZS, int8 iOnline) {
|
||||
void ClientListEntry::SetOnline(ZoneServer* iZS, CLE_Status iOnline) {
|
||||
if (iZS == this->Server())
|
||||
SetOnline(iOnline);
|
||||
}
|
||||
|
||||
void ClientListEntry::SetOnline(int8 iOnline) {
|
||||
if (iOnline >= CLE_Status_Online && pOnline < CLE_Status_Online)
|
||||
void ClientListEntry::SetOnline(CLE_Status iOnline) {
|
||||
Log(Logs::General, Logs::World_Server, "ClientListEntry::SetOnline for %s(%i) = %i", AccountName(), AccountID(), iOnline);
|
||||
|
||||
if (iOnline >= CLE_Status::Online && pOnline < CLE_Status::Online)
|
||||
numplayers++;
|
||||
else if (iOnline < CLE_Status_Online && pOnline >= CLE_Status_Online) {
|
||||
else if (iOnline < CLE_Status::Online && pOnline >= CLE_Status::Online) {
|
||||
numplayers--;
|
||||
}
|
||||
if (iOnline != CLE_Status_Online || pOnline < CLE_Status_Online)
|
||||
if (iOnline != CLE_Status::Online || pOnline < CLE_Status::Online)
|
||||
pOnline = iOnline;
|
||||
if (iOnline < CLE_Status_Zoning)
|
||||
if (iOnline < CLE_Status::Zoning)
|
||||
Camp();
|
||||
if (pOnline >= CLE_Status_Online)
|
||||
if (pOnline >= CLE_Status::Online)
|
||||
stale = 0;
|
||||
}
|
||||
void ClientListEntry::LSUpdate(ZoneServer* iZS){
|
||||
@@ -161,7 +163,7 @@ void ClientListEntry::LSZoneChange(ZoneToZone_Struct* ztz){
|
||||
safe_delete(pack);
|
||||
}
|
||||
}
|
||||
void ClientListEntry::Update(ZoneServer* iZS, ServerClientList_Struct* scl, int8 iOnline) {
|
||||
void ClientListEntry::Update(ZoneServer* iZS, ServerClientList_Struct* scl, CLE_Status iOnline) {
|
||||
if (pzoneserver != iZS) {
|
||||
if (pzoneserver){
|
||||
pzoneserver->RemovePlayer();
|
||||
@@ -208,7 +210,7 @@ void ClientListEntry::Update(ZoneServer* iZS, ServerClientList_Struct* scl, int8
|
||||
SetOnline(iOnline);
|
||||
}
|
||||
|
||||
void ClientListEntry::LeavingZone(ZoneServer* iZS, int8 iOnline) {
|
||||
void ClientListEntry::LeavingZone(ZoneServer* iZS, CLE_Status iOnline) {
|
||||
if (iZS != 0 && iZS != pzoneserver)
|
||||
return;
|
||||
SetOnline(iOnline);
|
||||
@@ -223,7 +225,7 @@ void ClientListEntry::LeavingZone(ZoneServer* iZS, int8 iOnline) {
|
||||
|
||||
void ClientListEntry::ClearVars(bool iAll) {
|
||||
if (iAll) {
|
||||
pOnline = CLE_Status_Never;
|
||||
pOnline = CLE_Status::Never;
|
||||
stale = 0;
|
||||
|
||||
pLSID = 0;
|
||||
@@ -269,10 +271,10 @@ void ClientListEntry::Camp(ZoneServer* iZS) {
|
||||
bool ClientListEntry::CheckStale() {
|
||||
stale++;
|
||||
if (stale > 20) {
|
||||
if (pOnline > CLE_Status_Offline)
|
||||
SetOnline(CLE_Status_Offline);
|
||||
else
|
||||
return true;
|
||||
if (pOnline > CLE_Status::Offline)
|
||||
SetOnline(CLE_Status::Offline);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
+17
-15
@@ -8,13 +8,15 @@
|
||||
#include "../common/rulesys.h"
|
||||
#include <vector>
|
||||
|
||||
|
||||
#define CLE_Status_Never -1
|
||||
#define CLE_Status_Offline 0
|
||||
#define CLE_Status_Online 1 // Will not overwrite more specific online status
|
||||
#define CLE_Status_CharSelect 2
|
||||
#define CLE_Status_Zoning 3
|
||||
#define CLE_Status_InZone 4
|
||||
typedef enum
|
||||
{
|
||||
Never,
|
||||
Offline,
|
||||
Online,
|
||||
CharSelect,
|
||||
Zoning,
|
||||
InZone
|
||||
} CLE_Status;
|
||||
|
||||
class ZoneServer;
|
||||
struct ServerClientList_Struct;
|
||||
@@ -23,25 +25,25 @@ class ClientListEntry {
|
||||
public:
|
||||
ClientListEntry(uint32 id, uint32 iLSID, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin = 0, uint32 ip = 0, uint8 local=0);
|
||||
ClientListEntry(uint32 id, uint32 iAccID, const char* iAccName, MD5& iMD5Pass, int16 iAdmin = 0);
|
||||
ClientListEntry(uint32 id, ZoneServer* iZS, ServerClientList_Struct* scl, int8 iOnline);
|
||||
ClientListEntry(uint32 id, ZoneServer* iZS, ServerClientList_Struct* scl, CLE_Status iOnline);
|
||||
~ClientListEntry();
|
||||
bool CheckStale();
|
||||
void Update(ZoneServer* zoneserver, ServerClientList_Struct* scl, int8 iOnline = CLE_Status_InZone);
|
||||
void Update(ZoneServer* zoneserver, ServerClientList_Struct* scl, CLE_Status iOnline = CLE_Status::InZone);
|
||||
void LSUpdate(ZoneServer* zoneserver);
|
||||
void LSZoneChange(ZoneToZone_Struct* ztz);
|
||||
bool CheckAuth(uint32 iLSID, const char* key);
|
||||
bool CheckAuth(const char* iName, MD5& iMD5Password);
|
||||
bool CheckAuth(uint32 id, const char* key, uint32 ip);
|
||||
void SetOnline(ZoneServer* iZS, int8 iOnline);
|
||||
void SetOnline(int8 iOnline = CLE_Status_Online);
|
||||
void SetOnline(ZoneServer* iZS, CLE_Status iOnline);
|
||||
void SetOnline(CLE_Status iOnline = CLE_Status::Online);
|
||||
void SetChar(uint32 iCharID, const char* iCharName);
|
||||
inline int8 Online() { return pOnline; }
|
||||
inline CLE_Status Online() { return pOnline; }
|
||||
inline const uint32 GetID() const { return id; }
|
||||
inline const uint32 GetIP() const { return pIP; }
|
||||
inline void SetIP(const uint32& iIP) { pIP = iIP; }
|
||||
inline void KeepAlive() { stale = 0; }
|
||||
inline uint8 GetStaleCounter() const { return stale; }
|
||||
void LeavingZone(ZoneServer* iZS = 0, int8 iOnline = CLE_Status_Offline);
|
||||
void LeavingZone(ZoneServer* iZS = 0, CLE_Status iOnline = CLE_Status::Offline);
|
||||
void Camp(ZoneServer* iZS = 0);
|
||||
|
||||
// Login Server stuff
|
||||
@@ -50,7 +52,7 @@ public:
|
||||
inline const char* LSName() const { return plsname; }
|
||||
inline int16 WorldAdmin() const { return pworldadmin; }
|
||||
inline const char* GetLSKey() const { return plskey; }
|
||||
inline const int8 GetOnline() const { return pOnline; }
|
||||
inline const CLE_Status GetOnline() const { return pOnline; }
|
||||
|
||||
// Account stuff
|
||||
inline uint32 AccountID() const { return paccountid; }
|
||||
@@ -93,7 +95,7 @@ private:
|
||||
|
||||
const uint32 id;
|
||||
uint32 pIP;
|
||||
int8 pOnline;
|
||||
CLE_Status pOnline;
|
||||
uint8 stale;
|
||||
|
||||
// Login Server stuff
|
||||
|
||||
+44
-67
@@ -41,7 +41,7 @@ extern ZSList zoneserver_list;
|
||||
uint32 numplayers = 0; //this really wants to be a member variable of ClientList...
|
||||
|
||||
ClientList::ClientList()
|
||||
: CLStale_timer(45000)
|
||||
: CLStale_timer(10000)
|
||||
{
|
||||
NextCLEID = 1;
|
||||
|
||||
@@ -64,8 +64,6 @@ void ClientList::Process() {
|
||||
struct in_addr in;
|
||||
in.s_addr = iterator.GetData()->GetIP();
|
||||
Log(Logs::Detail, Logs::World_Server,"Removing client from %s:%d", inet_ntoa(in), iterator.GetData()->GetPort());
|
||||
//the client destructor should take care of this.
|
||||
// iterator.GetData()->Free();
|
||||
iterator.RemoveCurrent();
|
||||
}
|
||||
else
|
||||
@@ -99,52 +97,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<ClientListEntry*> 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) {
|
||||
@@ -168,7 +120,7 @@ void ClientList::GetCLEIP(uint32 iIP) {
|
||||
return;
|
||||
} else {
|
||||
Log(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str());
|
||||
countCLEIPs->SetOnline(CLE_Status_Offline);
|
||||
countCLEIPs->SetOnline(CLE_Status::Offline);
|
||||
iterator.RemoveCurrent();
|
||||
continue;
|
||||
}
|
||||
@@ -184,7 +136,7 @@ void ClientList::GetCLEIP(uint32 iIP) {
|
||||
return;
|
||||
} else {
|
||||
Log(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str());
|
||||
countCLEIPs->SetOnline(CLE_Status_Offline); // Remove the connection
|
||||
countCLEIPs->SetOnline(CLE_Status::Offline); // Remove the connection
|
||||
iterator.RemoveCurrent();
|
||||
continue;
|
||||
}
|
||||
@@ -196,7 +148,7 @@ void ClientList::GetCLEIP(uint32 iIP) {
|
||||
return;
|
||||
} else {
|
||||
Log(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str());
|
||||
countCLEIPs->SetOnline(CLE_Status_Offline); // Remove the connection
|
||||
countCLEIPs->SetOnline(CLE_Status::Offline); // Remove the connection
|
||||
iterator.RemoveCurrent();
|
||||
continue;
|
||||
}
|
||||
@@ -207,7 +159,7 @@ void ClientList::GetCLEIP(uint32 iIP) {
|
||||
return;
|
||||
} else {
|
||||
Log(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str());
|
||||
countCLEIPs->SetOnline(CLE_Status_Offline); // Remove the connection
|
||||
countCLEIPs->SetOnline(CLE_Status::Offline); // Remove the connection
|
||||
iterator.RemoveCurrent();
|
||||
continue;
|
||||
}
|
||||
@@ -228,7 +180,7 @@ uint32 ClientList::GetCLEIPCount(uint32 iIP) {
|
||||
|
||||
while (iterator.MoreElements()) {
|
||||
countCLEIPs = iterator.GetData();
|
||||
if ((countCLEIPs->GetIP() == iIP) && ((countCLEIPs->Admin() < (RuleI(World, ExemptMaxClientsStatus))) || (RuleI(World, ExemptMaxClientsStatus) < 0)) && countCLEIPs->Online() >= CLE_Status_Online) { // If the IP matches, and the connection admin status is below the exempt status, or exempt status is less than 0 (no-one is exempt)
|
||||
if ((countCLEIPs->GetIP() == iIP) && ((countCLEIPs->Admin() < (RuleI(World, ExemptMaxClientsStatus))) || (RuleI(World, ExemptMaxClientsStatus) < 0)) && countCLEIPs->Online() >= CLE_Status::Online) { // If the IP matches, and the connection admin status is below the exempt status, or exempt status is less than 0 (no-one is exempt)
|
||||
IPInstances++; // Increment the occurences of this IP address
|
||||
}
|
||||
iterator.Advance();
|
||||
@@ -254,7 +206,7 @@ void ClientList::DisconnectByIP(uint32 iIP) {
|
||||
zoneserver_list.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
}
|
||||
countCLEIPs->SetOnline(CLE_Status_Offline);
|
||||
countCLEIPs->SetOnline(CLE_Status::Offline);
|
||||
iterator.RemoveCurrent();
|
||||
}
|
||||
iterator.Advance();
|
||||
@@ -272,7 +224,7 @@ ClientListEntry* ClientList::FindCharacter(const char* name) {
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ClientListEntry* ClientList::FindCLEByAccountID(uint32 iAccID) {
|
||||
@@ -285,7 +237,7 @@ ClientListEntry* ClientList::FindCLEByAccountID(uint32 iAccID) {
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ClientListEntry* ClientList::FindCLEByCharacterID(uint32 iCharID) {
|
||||
@@ -298,7 +250,7 @@ ClientListEntry* ClientList::FindCLEByCharacterID(uint32 iCharID) {
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ClientList::SendCLEList(const int16& admin, const char* to, WorldTCPConnection* connection, const char* iName) {
|
||||
@@ -376,10 +328,10 @@ void ClientList::ClientUpdate(ZoneServer* zoneserver, ServerClientList_Struct* s
|
||||
if (iterator.GetData()->GetID() == scl->wid) {
|
||||
cle = iterator.GetData();
|
||||
if (scl->remove == 2){
|
||||
cle->LeavingZone(zoneserver, CLE_Status_Offline);
|
||||
cle->LeavingZone(zoneserver, CLE_Status::Offline);
|
||||
}
|
||||
else if (scl->remove == 1)
|
||||
cle->LeavingZone(zoneserver, CLE_Status_Zoning);
|
||||
cle->LeavingZone(zoneserver, CLE_Status::Zoning);
|
||||
else
|
||||
cle->Update(zoneserver, scl);
|
||||
return;
|
||||
@@ -387,11 +339,11 @@ void ClientList::ClientUpdate(ZoneServer* zoneserver, ServerClientList_Struct* s
|
||||
iterator.Advance();
|
||||
}
|
||||
if (scl->remove == 2)
|
||||
cle = new ClientListEntry(GetNextCLEID(), zoneserver, scl, CLE_Status_Online);
|
||||
cle = new ClientListEntry(GetNextCLEID(), zoneserver, scl, CLE_Status::Online);
|
||||
else if (scl->remove == 1)
|
||||
cle = new ClientListEntry(GetNextCLEID(), zoneserver, scl, CLE_Status_Zoning);
|
||||
cle = new ClientListEntry(GetNextCLEID(), zoneserver, scl, CLE_Status::Zoning);
|
||||
else
|
||||
cle = new ClientListEntry(GetNextCLEID(), zoneserver, scl, CLE_Status_InZone);
|
||||
cle = new ClientListEntry(GetNextCLEID(), zoneserver, scl, CLE_Status::InZone);
|
||||
clientlist.Insert(cle);
|
||||
zoneserver->ChangeWID(scl->charid, cle->GetID());
|
||||
}
|
||||
@@ -571,7 +523,7 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S
|
||||
countcle = countclients.GetData();
|
||||
const char* tmpZone = database.GetZoneName(countcle->zone());
|
||||
if (
|
||||
(countcle->Online() >= CLE_Status_Zoning) &&
|
||||
(countcle->Online() >= CLE_Status::Zoning) &&
|
||||
(!countcle->GetGM() || countcle->Anon() != 1 || admin >= countcle->Admin()) &&
|
||||
(whom == 0 || (
|
||||
((countcle->Admin() >= 80 && countcle->GetGM()) || whom->gmlookup == 0xFFFF) &&
|
||||
@@ -651,7 +603,7 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S
|
||||
|
||||
const char* tmpZone = database.GetZoneName(cle->zone());
|
||||
if (
|
||||
(cle->Online() >= CLE_Status_Zoning) &&
|
||||
(cle->Online() >= CLE_Status::Zoning) &&
|
||||
(!cle->GetGM() || cle->Anon() != 1 || admin >= cle->Admin()) &&
|
||||
(whom == 0 || (
|
||||
((cle->Admin() >= 80 && cle->GetGM()) || whom->gmlookup == 0xFFFF) &&
|
||||
@@ -824,7 +776,7 @@ void ClientList::SendFriendsWho(ServerFriendsWho_Struct *FriendsWho, WorldTCPCon
|
||||
Friend_[Seperator - FriendsPointer] = 0;
|
||||
|
||||
ClientListEntry* CLE = FindCharacter(Friend_);
|
||||
if(CLE && CLE->name() && (CLE->Online() >= CLE_Status_Zoning) && !(CLE->GetGM() && CLE->Anon())) {
|
||||
if(CLE && CLE->name() && (CLE->Online() >= CLE_Status::Zoning) && !(CLE->GetGM() && CLE->Anon())) {
|
||||
FriendsCLEs.push_back(CLE);
|
||||
TotalLength += strlen(CLE->name());
|
||||
int GuildNameLength = strlen(guild_mgr.GetGuildName(CLE->GuildID()));
|
||||
@@ -1036,7 +988,7 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct*
|
||||
cle = iterator.GetData();
|
||||
const char* tmpZone = database.GetZoneName(cle->zone());
|
||||
if (
|
||||
(cle->Online() >= CLE_Status_Zoning)
|
||||
(cle->Online() >= CLE_Status::Zoning)
|
||||
&& (whom == 0 || (
|
||||
((cle->Admin() >= 80 && cle->GetGM()) || whom->gmlookup == 0xFFFF) &&
|
||||
(whom->lvllow == 0xFFFF || (cle->level() >= whom->lvllow && cle->level() <= whom->lvlhigh)) &&
|
||||
@@ -1310,7 +1262,32 @@ void ClientList::UpdateClientGuild(uint32 char_id, uint32 guild_id) {
|
||||
}
|
||||
}
|
||||
|
||||
void ClientList::RemoveCLEByLSID(uint32 iLSID)
|
||||
{
|
||||
LinkedListIterator<ClientListEntry*> iterator(clientlist);
|
||||
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
if (iterator.GetData()->LSAccountID() == iLSID) {
|
||||
iterator.RemoveCurrent();
|
||||
}
|
||||
else
|
||||
iterator.Advance();
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientList::IsAccountInGame(uint32 iLSID) {
|
||||
LinkedListIterator<ClientListEntry*> iterator(clientlist);
|
||||
|
||||
while (iterator.MoreElements()) {
|
||||
if (iterator.GetData()->LSID() == iLSID && iterator.GetData()->Online() == CLE_Status::InZone) {
|
||||
return true;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int ClientList::GetClientCount() {
|
||||
return(numplayers);
|
||||
|
||||
+2
-1
@@ -61,11 +61,12 @@ public:
|
||||
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* iLoginName, const char* iLoginKey, int16 iWorldAdmin = 0, uint32 ip = 0, uint8 local=0);
|
||||
void UpdateClientGuild(uint32 char_id, uint32 guild_id);
|
||||
void RemoveCLEByLSID(uint32 iLSID);
|
||||
bool IsAccountInGame(uint32 iLSID);
|
||||
|
||||
int GetClientCount();
|
||||
void GetClients(const char *zone_name, std::vector<ClientListEntry *> &into);
|
||||
|
||||
+39
-29
@@ -35,6 +35,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"
|
||||
|
||||
extern ZSList zoneserver_list;
|
||||
@@ -65,38 +66,54 @@ void LoginServer::ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p) {
|
||||
uint32 id = database.GetAccountIDFromLSID(utwr->lsaccountid);
|
||||
int16 status = database.CheckStatus(id);
|
||||
|
||||
auto outpack = new ServerPacket;
|
||||
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;
|
||||
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 (status >= 100)
|
||||
utwrs->response = 1;
|
||||
}
|
||||
else {
|
||||
utwrs->response = 1;
|
||||
if (status < 100) {
|
||||
utwrs->response = UserToWorldStatusWorldUnavail;
|
||||
SendPacket(&outpack);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
if (status == -1) {
|
||||
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, EnforceCharacterLimitAtLogin)) {
|
||||
if (client_list.IsAccountInGame(utwr->lsaccountid)) {
|
||||
utwrs->response = UserToWorldStatusAlreadyOnline;
|
||||
SendPacket(&outpack);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SendPacket(&outpack);
|
||||
}
|
||||
|
||||
void LoginServer::ProcessLSClientAuth(uint16_t opcode, EQ::Net::Packet &p) {
|
||||
@@ -105,13 +122,6 @@ void LoginServer::ProcessLSClientAuth(uint16_t opcode, EQ::Net::Packet &p) {
|
||||
|
||||
try {
|
||||
auto slsca = p.GetSerialize<ClientAuth_Struct>(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(slsca.lsaccount_id);
|
||||
}
|
||||
|
||||
client_list.CLEAdd(slsca.lsaccount_id, slsca.name, slsca.key, slsca.worldadmin, slsca.ip, slsca.local);
|
||||
}
|
||||
catch (std::exception &ex) {
|
||||
|
||||
@@ -708,6 +708,13 @@ void ZSList::WorldShutDown(uint32 time, uint32 interval)
|
||||
}
|
||||
}
|
||||
|
||||
void ZSList::DropClient(uint32 lsid) {
|
||||
ServerPacket packet(ServerOP_DropClient, sizeof(ServerZoneDropClient_Struct));
|
||||
auto drop = (ServerZoneDropClient_Struct*)packet.pBuffer;
|
||||
drop->lsid = lsid;
|
||||
SendPacket(&packet);
|
||||
}
|
||||
|
||||
void ZSList::OnTick(EQ::Timer *t)
|
||||
{
|
||||
if (!EventSubscriptionWatcher::Get()->IsSubscribed("EQW::ZoneUpdate")) {
|
||||
|
||||
@@ -57,6 +57,7 @@ public:
|
||||
void SOPZoneBootup(const char *adminname, uint32 ZoneServerID, const char *zonename, bool iMakeStatic = false);
|
||||
void UpdateUCSServerAvailable(bool ucss_available = true);
|
||||
void WorldShutDown(uint32 time, uint32 interval);
|
||||
void DropClient(uint32 lsid);
|
||||
|
||||
ZoneServer* FindByPort(uint16 port);
|
||||
ZoneServer* FindByID(uint32 ZoneID);
|
||||
|
||||
@@ -409,12 +409,12 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
if (pack->size < sizeof(ServerChannelMessage_Struct))
|
||||
break;
|
||||
ServerChannelMessage_Struct* scm = (ServerChannelMessage_Struct*)pack->pBuffer;
|
||||
if (scm->chan_num == 20)
|
||||
if (scm->chan_num == ChatChannel_UCSRelay)
|
||||
{
|
||||
UCSLink.SendMessage(scm->from, scm->message);
|
||||
break;
|
||||
}
|
||||
if (scm->chan_num == 7 || scm->chan_num == 14) {
|
||||
if (scm->chan_num == ChatChannel_Tell || scm->chan_num == ChatChannel_TellEcho) {
|
||||
if (scm->deliverto[0] == '*') {
|
||||
|
||||
if (console) {
|
||||
@@ -437,7 +437,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
}
|
||||
|
||||
ClientListEntry* cle = client_list.FindCharacter(scm->deliverto);
|
||||
if (cle == 0 || cle->Online() < CLE_Status_Zoning ||
|
||||
if (cle == 0 || cle->Online() < CLE_Status::Zoning ||
|
||||
(cle->TellsOff() && ((cle->Anon() == 1 && scm->fromadmin < cle->Admin()) || scm->fromadmin < 80))) {
|
||||
if (!scm->noreply) {
|
||||
ClientListEntry* sender = client_list.FindCharacter(scm->from);
|
||||
@@ -450,7 +450,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
sender->Server()->SendPacket(pack);
|
||||
}
|
||||
}
|
||||
else if (cle->Online() == CLE_Status_Zoning) {
|
||||
else if (cle->Online() == CLE_Status::Zoning) {
|
||||
if (!scm->noreply) {
|
||||
ClientListEntry* sender = client_list.FindCharacter(scm->from);
|
||||
if (cle->TellQueueFull()) {
|
||||
@@ -486,7 +486,8 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
cle->Server()->SendPacket(pack);
|
||||
}
|
||||
else {
|
||||
if (scm->chan_num == 5 || scm->chan_num == 6 || scm->chan_num == 11) {
|
||||
if (scm->chan_num == ChatChannel_OOC || scm->chan_num == ChatChannel_Broadcast
|
||||
|| scm->chan_num == ChatChannel_GMSAY) {
|
||||
if (console) {
|
||||
console->SendChannelMessage(scm, [&scm]() {
|
||||
auto pack = new ServerPacket(ServerOP_ChannelMessage,
|
||||
@@ -517,7 +518,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
|
||||
ClientListEntry* cle = client_list.FindCharacter(svm->To);
|
||||
|
||||
if (!cle || (cle->Online() < CLE_Status_Zoning) || !cle->Server()) {
|
||||
if (!cle || (cle->Online() < CLE_Status::Zoning) || !cle->Server()) {
|
||||
|
||||
zoneserver_list.SendEmoteMessage(svm->From, 0, 0, 0, "'%s is not online at this time'", svm->To);
|
||||
|
||||
@@ -1456,6 +1457,7 @@ void ZoneServer::IncomingClient(Client* client) {
|
||||
s->accid = client->GetAccountID();
|
||||
s->admin = client->GetAdmin();
|
||||
s->charid = client->GetCharID();
|
||||
s->lsid = client->GetLSID();
|
||||
if (client->GetCLE())
|
||||
s->tellsoff = client->GetCLE()->TellsOff();
|
||||
strn0cpy(s->charname, client->GetCharName(), sizeof(s->charname));
|
||||
|
||||
+64
-105
@@ -446,7 +446,7 @@ Client::~Client() {
|
||||
numclients--;
|
||||
UpdateWindowTitle();
|
||||
if(zone)
|
||||
zone->RemoveAuth(GetName());
|
||||
zone->RemoveAuth(GetName(), lskey);
|
||||
|
||||
//let the stream factory know were done with this stream
|
||||
eqs->Close();
|
||||
@@ -823,7 +823,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
{
|
||||
if(strcmp(targetname, "discard") != 0)
|
||||
{
|
||||
if(chan_num == 3 || chan_num == 4 || chan_num == 5 || chan_num == 7)
|
||||
if(chan_num == ChatChannel_Shout || chan_num == ChatChannel_Auction || chan_num == ChatChannel_OOC || chan_num == ChatChannel_Tell)
|
||||
{
|
||||
if(GlobalChatLimiterTimer)
|
||||
{
|
||||
@@ -869,7 +869,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
auto pack = new ServerPacket(ServerOP_Speech, sizeof(Server_Speech_Struct) + strlen(message) + 1);
|
||||
Server_Speech_Struct* sem = (Server_Speech_Struct*) pack->pBuffer;
|
||||
|
||||
if(chan_num == 0)
|
||||
if(chan_num == ChatChannel_Guild)
|
||||
sem->guilddbid = GuildID();
|
||||
else
|
||||
sem->guilddbid = 0;
|
||||
@@ -892,30 +892,38 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
if(!mod_client_message(message, chan_num)) { return; }
|
||||
|
||||
// Garble the message based on drunkness
|
||||
if (m_pp.intoxication > 0) {
|
||||
if (m_pp.intoxication > 0 && !(RuleB(Chat, ServerWideOOC) && chan_num == ChatChannel_OOC) && !GetGM()) {
|
||||
GarbleMessage(message, (int)(m_pp.intoxication / 3));
|
||||
language = 0; // No need for language when drunk
|
||||
lang_skill = 100;
|
||||
}
|
||||
|
||||
// some channels don't use languages
|
||||
if (chan_num == ChatChannel_OOC || chan_num == ChatChannel_GMSAY || chan_num == ChatChannel_Broadcast || chan_num == ChatChannel_Petition)
|
||||
{
|
||||
language = 0;
|
||||
lang_skill = 100;
|
||||
}
|
||||
|
||||
// Censor the message
|
||||
if (EQEmu::ProfanityManager::IsCensorshipActive() && (chan_num != 8))
|
||||
if (EQEmu::ProfanityManager::IsCensorshipActive() && (chan_num != ChatChannel_Say))
|
||||
EQEmu::ProfanityManager::RedactMessage(message);
|
||||
|
||||
switch(chan_num)
|
||||
{
|
||||
case 0: { /* Guild Chat */
|
||||
case ChatChannel_Guild: { /* Guild Chat */
|
||||
if (!IsInAGuild())
|
||||
Message_StringID(MT_DefaultText, GUILD_NOT_MEMBER2); //You are not a member of any guild.
|
||||
else if (!guild_mgr.CheckPermission(GuildID(), GuildRank(), GUILD_SPEAK))
|
||||
Message(0, "Error: You dont have permission to speak to the guild.");
|
||||
else if (!worldserver.SendChannelMessage(this, targetname, chan_num, GuildID(), language, message))
|
||||
else if (!worldserver.SendChannelMessage(this, targetname, chan_num, GuildID(), language, lang_skill, message))
|
||||
Message(0, "Error: World server disconnected");
|
||||
break;
|
||||
}
|
||||
case 2: { /* Group Chat */
|
||||
case ChatChannel_Group: { /* Group Chat */
|
||||
Raid* raid = entity_list.GetRaidByClient(this);
|
||||
if(raid) {
|
||||
raid->RaidGroupSay((const char*) message, this);
|
||||
raid->RaidGroupSay((const char*) message, this, language, lang_skill);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -925,14 +933,14 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 15: { /* Raid Say */
|
||||
case ChatChannel_Raid: { /* Raid Say */
|
||||
Raid* raid = entity_list.GetRaidByClient(this);
|
||||
if(raid){
|
||||
raid->RaidSay((const char*) message, this);
|
||||
raid->RaidSay((const char*) message, this, language, lang_skill);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: { /* Shout */
|
||||
case ChatChannel_Shout: { /* Shout */
|
||||
Mob *sender = this;
|
||||
if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SE_VoiceGraft))
|
||||
sender = GetPet();
|
||||
@@ -940,13 +948,13 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message);
|
||||
break;
|
||||
}
|
||||
case 4: { /* Auction */
|
||||
case ChatChannel_Auction: { /* Auction */
|
||||
if(RuleB(Chat, ServerWideAuction))
|
||||
{
|
||||
if(!global_channel_timer.Check())
|
||||
{
|
||||
if(strlen(targetname) == 0)
|
||||
ChannelMessageReceived(5, language, lang_skill, message, "discard"); //Fast typer or spammer??
|
||||
ChannelMessageReceived(chan_num, language, lang_skill, message, "discard"); //Fast typer or spammer??
|
||||
else
|
||||
return;
|
||||
}
|
||||
@@ -966,7 +974,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
}
|
||||
}
|
||||
|
||||
if (!worldserver.SendChannelMessage(this, 0, 4, 0, language, message))
|
||||
if (!worldserver.SendChannelMessage(this, 0, chan_num, 0, language, lang_skill, message))
|
||||
Message(0, "Error: World server disconnected");
|
||||
}
|
||||
else if(!RuleB(Chat, ServerWideAuction)) {
|
||||
@@ -975,17 +983,17 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SE_VoiceGraft))
|
||||
sender = GetPet();
|
||||
|
||||
entity_list.ChannelMessage(sender, chan_num, language, message);
|
||||
entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 5: { /* OOC */
|
||||
case ChatChannel_OOC: { /* OOC */
|
||||
if(RuleB(Chat, ServerWideOOC))
|
||||
{
|
||||
if(!global_channel_timer.Check())
|
||||
{
|
||||
if(strlen(targetname) == 0)
|
||||
ChannelMessageReceived(5, language, lang_skill, message, "discard"); //Fast typer or spammer??
|
||||
ChannelMessageReceived(chan_num, language, lang_skill, message, "discard"); //Fast typer or spammer??
|
||||
else
|
||||
return;
|
||||
}
|
||||
@@ -1010,7 +1018,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
}
|
||||
}
|
||||
|
||||
if (!worldserver.SendChannelMessage(this, 0, 5, 0, language, message))
|
||||
if (!worldserver.SendChannelMessage(this, 0, chan_num, 0, language, lang_skill, message))
|
||||
{
|
||||
Message(0, "Error: World server disconnected");
|
||||
}
|
||||
@@ -1022,19 +1030,19 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SE_VoiceGraft))
|
||||
sender = GetPet();
|
||||
|
||||
entity_list.ChannelMessage(sender, chan_num, language, message);
|
||||
entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 6: /* Broadcast */
|
||||
case 11: { /* GM Say */
|
||||
case ChatChannel_Broadcast: /* Broadcast */
|
||||
case ChatChannel_GMSAY: { /* GM Say */
|
||||
if (!(admin >= 80))
|
||||
Message(0, "Error: Only GMs can use this channel");
|
||||
else if (!worldserver.SendChannelMessage(this, targetname, chan_num, 0, language, message))
|
||||
else if (!worldserver.SendChannelMessage(this, targetname, chan_num, 0, language, lang_skill, message))
|
||||
Message(0, "Error: World server disconnected");
|
||||
break;
|
||||
}
|
||||
case 7: { /* Tell */
|
||||
case ChatChannel_Tell: { /* Tell */
|
||||
if(!global_channel_timer.Check())
|
||||
{
|
||||
if(strlen(targetname) == 0)
|
||||
@@ -1078,11 +1086,11 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
target_name[x] = '\0';
|
||||
}
|
||||
|
||||
if(!worldserver.SendChannelMessage(this, target_name, chan_num, 0, language, message))
|
||||
if(!worldserver.SendChannelMessage(this, target_name, chan_num, 0, language, lang_skill, message))
|
||||
Message(0, "Error: World server disconnected");
|
||||
break;
|
||||
}
|
||||
case 8: { /* Say */
|
||||
case ChatChannel_Say: { /* Say */
|
||||
if(message[0] == COMMAND_CHAR) {
|
||||
if(command_dispatch(this, message) == -2) {
|
||||
if(parse->PlayerHasQuestSub(EVENT_COMMAND)) {
|
||||
@@ -1158,14 +1166,14 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 20:
|
||||
case ChatChannel_UCSRelay:
|
||||
{
|
||||
// UCS Relay for Underfoot and later.
|
||||
if(!worldserver.SendChannelMessage(this, 0, chan_num, 0, language, message))
|
||||
if(!worldserver.SendChannelMessage(this, 0, chan_num, 0, language, lang_skill, message))
|
||||
Message(0, "Error: World server disconnected");
|
||||
break;
|
||||
}
|
||||
case 22:
|
||||
case ChatChannel_Emotes:
|
||||
{
|
||||
// Emotes for Underfoot and later.
|
||||
// crash protection -- cheater
|
||||
@@ -1189,11 +1197,6 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
}
|
||||
}
|
||||
|
||||
// if no language skill is specified, call the function with a skill of 100.
|
||||
void Client::ChannelMessageSend(const char* from, const char* to, uint8 chan_num, uint8 language, const char* message, ...) {
|
||||
ChannelMessageSend(from, to, chan_num, language, 100, message);
|
||||
}
|
||||
|
||||
void Client::ChannelMessageSend(const char* from, const char* to, uint8 chan_num, uint8 language, uint8 lang_skill, const char* message, ...) {
|
||||
if ((chan_num==11 && !(this->GetGM())) || (chan_num==10 && this->Admin()<80)) // dont need to send /pr & /petition to everybody
|
||||
return;
|
||||
@@ -1218,7 +1221,7 @@ void Client::ChannelMessageSend(const char* from, const char* to, uint8 chan_num
|
||||
}
|
||||
if (to != 0)
|
||||
strcpy((char *) cm->targetname, to);
|
||||
else if (chan_num == 7)
|
||||
else if (chan_num == ChatChannel_Tell)
|
||||
strcpy(cm->targetname, m_pp.name);
|
||||
else
|
||||
cm->targetname[0] = 0;
|
||||
@@ -1227,7 +1230,7 @@ void Client::ChannelMessageSend(const char* from, const char* to, uint8 chan_num
|
||||
|
||||
if (language < MAX_PP_LANGUAGE) {
|
||||
ListenerSkill = m_pp.languages[language];
|
||||
if (ListenerSkill == 0) {
|
||||
if (ListenerSkill < 24) {
|
||||
cm->language = (MAX_PP_LANGUAGE - 1); // in an unknown tongue
|
||||
}
|
||||
else {
|
||||
@@ -1253,7 +1256,7 @@ void Client::ChannelMessageSend(const char* from, const char* to, uint8 chan_num
|
||||
bool weAreNotSender = strcmp(this->GetCleanName(), cm->sender);
|
||||
|
||||
if (senderCanTrainSelf || weAreNotSender) {
|
||||
if ((chan_num == 2) && (ListenerSkill < 100)) { // group message in unmastered language, check for skill up
|
||||
if ((chan_num == ChatChannel_Group) && (ListenerSkill < 100)) { // group message in unmastered language, check for skill up
|
||||
if (m_pp.languages[language] <= lang_skill)
|
||||
CheckLanguageSkillIncrease(language, lang_skill);
|
||||
}
|
||||
@@ -1274,21 +1277,19 @@ void Client::Message(uint32 type, const char* message, ...) {
|
||||
vsnprintf(buffer, 4096, message, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
size_t len = strlen(buffer);
|
||||
SerializeBuffer buf(sizeof(SpecialMesgHeader_Struct) + 12 + 64 + 64);
|
||||
buf.WriteInt8(static_cast<int8>(Journal::SpeakMode::Raw));
|
||||
buf.WriteInt8(static_cast<int8>(Journal::Mode::None));
|
||||
buf.WriteInt8(0); // language
|
||||
buf.WriteUInt32(type);
|
||||
buf.WriteUInt32(0); // target spawn ID used for journal filtering, ignored here
|
||||
buf.WriteString(""); // send name, not applicable here
|
||||
buf.WriteInt32(0); // location, client seems to ignore
|
||||
buf.WriteInt32(0);
|
||||
buf.WriteInt32(0);
|
||||
buf.WriteString(buffer);
|
||||
|
||||
//client dosent like our packet all the time unless
|
||||
//we make it really big, then it seems to not care that
|
||||
//our header is malformed.
|
||||
//len = 4096 - sizeof(SpecialMesg_Struct);
|
||||
|
||||
uint32 len_packet = sizeof(SpecialMesg_Struct)+len;
|
||||
auto app = new EQApplicationPacket(OP_SpecialMesg, len_packet);
|
||||
SpecialMesg_Struct* sm=(SpecialMesg_Struct*)app->pBuffer;
|
||||
sm->header[0] = 0x00; // Header used for #emote style messages..
|
||||
sm->header[1] = 0x00; // Play around with these to see other types
|
||||
sm->header[2] = 0x00;
|
||||
sm->msg_type = type;
|
||||
memcpy(sm->message, buffer, len+1);
|
||||
auto app = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||
|
||||
FastQueuePacket(&app);
|
||||
|
||||
@@ -1305,67 +1306,25 @@ void Client::FilteredMessage(Mob *sender, uint32 type, eqFilterType filter, cons
|
||||
vsnprintf(buffer, 4096, message, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
size_t len = strlen(buffer);
|
||||
SerializeBuffer buf(sizeof(SpecialMesgHeader_Struct) + 12 + 64 + 64);
|
||||
buf.WriteInt8(static_cast<int8>(Journal::SpeakMode::Raw));
|
||||
buf.WriteInt8(static_cast<int8>(Journal::Mode::None));
|
||||
buf.WriteInt8(0); // language
|
||||
buf.WriteUInt32(type);
|
||||
buf.WriteUInt32(0); // target spawn ID used for journal filtering, ignored here
|
||||
buf.WriteString(""); // send name, not applicable here
|
||||
buf.WriteInt32(0); // location, client seems to ignore
|
||||
buf.WriteInt32(0);
|
||||
buf.WriteInt32(0);
|
||||
buf.WriteString(buffer);
|
||||
|
||||
//client dosent like our packet all the time unless
|
||||
//we make it really big, then it seems to not care that
|
||||
//our header is malformed.
|
||||
//len = 4096 - sizeof(SpecialMesg_Struct);
|
||||
|
||||
uint32 len_packet = sizeof(SpecialMesg_Struct) + len;
|
||||
auto app = new EQApplicationPacket(OP_SpecialMesg, len_packet);
|
||||
SpecialMesg_Struct* sm = (SpecialMesg_Struct*)app->pBuffer;
|
||||
sm->header[0] = 0x00; // Header used for #emote style messages..
|
||||
sm->header[1] = 0x00; // Play around with these to see other types
|
||||
sm->header[2] = 0x00;
|
||||
sm->msg_type = type;
|
||||
memcpy(sm->message, buffer, len + 1);
|
||||
auto app = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||
|
||||
FastQueuePacket(&app);
|
||||
|
||||
safe_delete_array(buffer);
|
||||
}
|
||||
|
||||
void Client::QuestJournalledMessage(const char *npcname, const char* message) {
|
||||
|
||||
// npcnames longer than 60 characters crash the client when they log back in
|
||||
const int MaxNPCNameLength = 60;
|
||||
// I assume there is an upper safe limit on the message length. Don't know what it is, but 4000 doesn't crash
|
||||
// the client.
|
||||
const int MaxMessageLength = 4000;
|
||||
|
||||
char OutNPCName[MaxNPCNameLength+1];
|
||||
char OutMessage[MaxMessageLength+1];
|
||||
|
||||
// Apparently Visual C++ snprintf is not C99 compliant and doesn't put the null terminator
|
||||
// in if the formatted string >= the maximum length, so we put it in.
|
||||
//
|
||||
snprintf(OutNPCName, MaxNPCNameLength, "%s", npcname); OutNPCName[MaxNPCNameLength]='\0';
|
||||
snprintf(OutMessage, MaxMessageLength, "%s", message); OutMessage[MaxMessageLength]='\0';
|
||||
|
||||
uint32 len_packet = sizeof(SpecialMesg_Struct) + strlen(OutNPCName) + strlen(OutMessage);
|
||||
auto app = new EQApplicationPacket(OP_SpecialMesg, len_packet);
|
||||
SpecialMesg_Struct* sm=(SpecialMesg_Struct*)app->pBuffer;
|
||||
|
||||
sm->header[0] = 0;
|
||||
sm->header[1] = 2;
|
||||
sm->header[2] = 0;
|
||||
sm->msg_type = 0x0a;
|
||||
sm->target_spawn_id = GetID();
|
||||
|
||||
char *dest = &sm->sayer[0];
|
||||
|
||||
memcpy(dest, OutNPCName, strlen(OutNPCName) + 1);
|
||||
|
||||
dest = dest + strlen(OutNPCName) + 13;
|
||||
|
||||
memcpy(dest, OutMessage, strlen(OutMessage) + 1);
|
||||
|
||||
QueuePacket(app);
|
||||
|
||||
safe_delete(app);
|
||||
}
|
||||
|
||||
void Client::SetMaxHP() {
|
||||
if(dead)
|
||||
return;
|
||||
|
||||
@@ -338,11 +338,9 @@ public:
|
||||
void QueuePacket(const EQApplicationPacket* app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL, eqFilterType filter=FilterNone);
|
||||
void FastQueuePacket(EQApplicationPacket** app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL);
|
||||
void ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_skill, const char* orig_message, const char* targetname=nullptr);
|
||||
void ChannelMessageSend(const char* from, const char* to, uint8 chan_num, uint8 language, const char* message, ...);
|
||||
void ChannelMessageSend(const char* from, const char* to, uint8 chan_num, uint8 language, uint8 lang_skill, const char* message, ...);
|
||||
void Message(uint32 type, const char* message, ...);
|
||||
void FilteredMessage(Mob *sender, uint32 type, eqFilterType filter, const char* message, ...);
|
||||
void QuestJournalledMessage(const char *npcname, const char* message);
|
||||
void VoiceMacroReceived(uint32 Type, char *Target, uint32 MacroNumber);
|
||||
void SendSound();
|
||||
void LearnRecipe(uint32 recipeID);
|
||||
|
||||
@@ -1166,8 +1166,8 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
*/
|
||||
Client* client = entity_list.GetClientByName(cze->char_name);
|
||||
if (!zone->GetAuth(ip, cze->char_name, &WID, &account_id, &character_id, &admin, lskey, &tellsoff)) {
|
||||
Log(Logs::General, Logs::Error, "GetAuth() returned false kicking client");
|
||||
if (client != 0) {
|
||||
Log(Logs::General, Logs::Client_Login, "%s failed zone auth check.", cze->char_name);
|
||||
if (nullptr != client) {
|
||||
client->Save();
|
||||
client->Kick();
|
||||
}
|
||||
@@ -4181,7 +4181,12 @@ void Client::Handle_OP_ChannelMessage(const EQApplicationPacket *app)
|
||||
return;
|
||||
}
|
||||
|
||||
ChannelMessageReceived(cm->chan_num, cm->language, cm->skill_in_language, cm->message, cm->targetname);
|
||||
uint8 skill_in_language = 100;
|
||||
if (cm->language < MAX_PP_LANGUAGE)
|
||||
{
|
||||
skill_in_language = m_pp.languages[cm->language];
|
||||
}
|
||||
ChannelMessageReceived(cm->chan_num, cm->language, skill_in_language, cm->message, cm->targetname);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+62
-4
@@ -56,6 +56,7 @@
|
||||
#include "../common/eqemu_logsys.h"
|
||||
#include "../common/profanity_manager.h"
|
||||
#include "../common/net/eqstream.h"
|
||||
#include "../common/event/task_scheduler.h"
|
||||
|
||||
#include "data_bucket.h"
|
||||
#include "command.h"
|
||||
@@ -78,6 +79,7 @@ extern TaskManager *taskmanager;
|
||||
extern FastMath g_Math;
|
||||
void CatchSignal(int sig_num);
|
||||
|
||||
EQ::Event::TaskScheduler task_scheduler;
|
||||
|
||||
int commandcount; // how many commands we have
|
||||
|
||||
@@ -395,6 +397,7 @@ int command_init(void)
|
||||
command_add("tempname", "[newname] - Temporarily renames your target. Leave name blank to restore the original name.", 100, command_tempname) ||
|
||||
command_add("petname", "[newname] - Temporarily renames your pet. Leave name blank to restore the original name.", 100, command_petname) ||
|
||||
command_add("test", "Test command", 200, command_test) ||
|
||||
command_add("test_login", "Test login command", 200, command_test_login) ||
|
||||
command_add("texture", "[texture] [helmtexture] - Change your or your target's appearance, use 255 to show equipment", 10, command_texture) ||
|
||||
command_add("time", "[HH] [MM] - Set EQ time", 90, command_time) ||
|
||||
command_add("timers", "- Display persistent timers for target", 200, command_timers) ||
|
||||
@@ -887,7 +890,7 @@ void command_chat(Client *c, const Seperator *sep)
|
||||
if (sep->arg[2][0] == 0)
|
||||
c->Message(0, "Usage: #chat [channum] [message]");
|
||||
else
|
||||
if (!worldserver.SendChannelMessage(0, 0, (uint8) atoi(sep->arg[1]), 0, 0, sep->argplus[2]))
|
||||
if (!worldserver.SendChannelMessage(0, 0, (uint8) atoi(sep->arg[1]), 0, 0, 100, sep->argplus[2]))
|
||||
c->Message(0, "Error: World server disconnected");
|
||||
}
|
||||
|
||||
@@ -2799,7 +2802,7 @@ void command_level(Client *c, const Seperator *sep)
|
||||
if ((level <= 0) || ((level > RuleI(Character, MaxLevel)) && (c->Admin() < commandLevelAboveCap))) {
|
||||
c->Message(0, "Error: #Level: Invalid Level");
|
||||
}
|
||||
else if (c->Admin() < 100) {
|
||||
else if (c->Admin() < RuleI(GM, MinStatusToLevelTarget)) {
|
||||
c->SetLevel(level, true);
|
||||
#ifdef BOTS
|
||||
if(RuleB(Bots, BotLevelsWithOwner))
|
||||
@@ -4490,7 +4493,7 @@ void command_gmzone(Client *c, const Seperator *sep)
|
||||
identifier = sep->arg[3];
|
||||
}
|
||||
|
||||
std::string bucket_key = StringFormat("%s-%s-instance", zone_short_name, identifier.c_str());
|
||||
std::string bucket_key = StringFormat("%s-%s-%u-instance", zone_short_name, identifier.c_str(), zone_version);
|
||||
std::string existing_zone_instance = DataBucket::GetData(bucket_key);
|
||||
|
||||
if (existing_zone_instance.length() > 0) {
|
||||
@@ -7342,6 +7345,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 +7359,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;
|
||||
}
|
||||
@@ -12416,6 +12427,53 @@ void command_network(Client *c, const Seperator *sep)
|
||||
}
|
||||
}
|
||||
|
||||
void command_test_login(Client *c, const Seperator *sep) {
|
||||
auto res = task_scheduler.Enqueue([]() -> bool {
|
||||
bool running = true;
|
||||
bool ret = false;
|
||||
EQ::Net::DaybreakConnectionManager mgr;
|
||||
std::shared_ptr<EQ::Net::DaybreakConnection> c;
|
||||
|
||||
mgr.OnNewConnection([&](std::shared_ptr<EQ::Net::DaybreakConnection> connection) {
|
||||
c = connection;
|
||||
});
|
||||
|
||||
mgr.OnConnectionStateChange([&](std::shared_ptr<EQ::Net::DaybreakConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) {
|
||||
if (EQ::Net::StatusConnected == to) {
|
||||
EQ::Net::DynamicPacket p;
|
||||
p.PutUInt16(0, 1); //OP_SessionReady
|
||||
p.PutUInt32(2, 2);
|
||||
c->QueuePacket(p);
|
||||
}
|
||||
else if (EQ::Net::StatusDisconnected == to) {
|
||||
running = false;
|
||||
}
|
||||
});
|
||||
|
||||
mgr.OnPacketRecv([&](std::shared_ptr<EQ::Net::DaybreakConnection> conn, const EQ::Net::Packet & p) {
|
||||
auto opcode = p.GetUInt16(0);
|
||||
switch (opcode) {
|
||||
case 0x0017: //OP_ChatMessage
|
||||
//Would do the actual sending and parsing here if eqcrypto wasn't in loginserver.
|
||||
ret = true;
|
||||
running = false;
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
mgr.Connect("127.0.0.1", 5999);
|
||||
|
||||
auto &loop = EQ::EventLoop::Get();
|
||||
while (true == running) {
|
||||
loop.Process();
|
||||
}
|
||||
|
||||
return ret;
|
||||
});
|
||||
|
||||
c->Message(0, "Result was %s", res.get() ? "true" : "false");
|
||||
}
|
||||
|
||||
// All new code added to command.cpp should be BEFORE this comment line. Do no append code to this file below the BOTS code block.
|
||||
#ifdef BOTS
|
||||
#include "bot_command.h"
|
||||
|
||||
@@ -304,6 +304,7 @@ void command_petname(Client *c, const Seperator *sep);
|
||||
void command_test(Client *c, const Seperator *sep);
|
||||
void command_testspawn(Client *c, const Seperator *sep);
|
||||
void command_testspawnkill(Client *c, const Seperator *sep);
|
||||
void command_test_login(Client *c, const Seperator *sep);
|
||||
void command_texture(Client *c, const Seperator *sep);
|
||||
void command_time(Client *c, const Seperator *sep);
|
||||
void command_timers(Client *c, const Seperator *sep);
|
||||
|
||||
@@ -272,6 +272,31 @@ enum class LootRequestType : uint8 {
|
||||
AllowedPVPDefined,
|
||||
};
|
||||
|
||||
namespace Journal {
|
||||
enum class SpeakMode : uint8 {
|
||||
Raw = 0, // this just uses the raw message
|
||||
Say = 1, // prints with "%1 says,%2 '%3'" if in another language else "%1 says '%2'"
|
||||
Shout = 2, // prints with "%1 shouts,%2 '%3'" if in another language else "%1 shouts '%2'"
|
||||
EmoteAlt = 3, // prints "%2", this should just be the same as raw ...
|
||||
Emote = 4, // prints "%1 %2" if message doesn't start with "\" or "@", else "%1%2"
|
||||
Group = 5 // prints "%1 tells the group,%2 '%3'"
|
||||
};
|
||||
|
||||
enum class Mode : uint8 {
|
||||
None = 0,
|
||||
Log1 = 1, // 1 and 2 log to journal
|
||||
Log2 = 2, // our current code uses 2
|
||||
};
|
||||
|
||||
struct Options {
|
||||
SpeakMode speak_mode;
|
||||
Mode journal_mode;
|
||||
int8 language;
|
||||
uint32 message_type;
|
||||
uint32 target_spawn_id; // who the message is talking to (limits journaling)
|
||||
};
|
||||
};
|
||||
|
||||
//this is our internal representation of the BUFF struct, can put whatever we want in it
|
||||
struct Buffs_Struct {
|
||||
uint16 spellid;
|
||||
|
||||
+3
-11
@@ -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<EQEmu::Any> *extra_pointers)
|
||||
{
|
||||
|
||||
+25
-6
@@ -155,12 +155,31 @@ XS(XS__say); // prototype to pass -Wmissing-prototypes
|
||||
XS(XS__say) {
|
||||
dXSARGS;
|
||||
|
||||
if (items == 1)
|
||||
quest_manager.say(SvPV_nolen(ST(0)));
|
||||
else if (items == 2)
|
||||
quest_manager.say(SvPV_nolen(ST(0)), (int) SvIV(ST(1)));
|
||||
else
|
||||
Perl_croak(aTHX_ "Usage: quest::say(string message, int language_id])");
|
||||
Journal::Options opts;
|
||||
// we currently default to these
|
||||
opts.speak_mode = Journal::SpeakMode::Say;
|
||||
opts.journal_mode = Journal::Mode::Log2;
|
||||
opts.language = 0;
|
||||
opts.message_type = MT_NPCQuestSay;
|
||||
if (items == 0 || items > 5) {
|
||||
Perl_croak(aTHX_ "Usage: quest::say(string message, [int language_id], [int message_type], [int speak_mode], [int journal_mode])");
|
||||
} else if (items == 2) {
|
||||
opts.language = (int)SvIV(ST(1));
|
||||
} else if (items == 3) {
|
||||
opts.language = (int)SvIV(ST(1));
|
||||
opts.message_type = (int)SvIV(ST(2));
|
||||
} else if (items == 4) {
|
||||
opts.language = (int)SvIV(ST(1));
|
||||
opts.message_type = (int)SvIV(ST(2));
|
||||
opts.speak_mode = (Journal::SpeakMode)SvIV(ST(3));
|
||||
} else if (items == 5) {
|
||||
opts.language = (int)SvIV(ST(1));
|
||||
opts.message_type = (int)SvIV(ST(2));
|
||||
opts.speak_mode = (Journal::SpeakMode)SvIV(ST(3));
|
||||
opts.journal_mode = (Journal::Mode)SvIV(ST(4));
|
||||
}
|
||||
|
||||
quest_manager.say(SvPV_nolen(ST(0)), opts);
|
||||
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
+38
-38
@@ -1235,33 +1235,19 @@ void EntityList::ChannelMessage(Mob *from, uint8 chan_num, uint8 language,
|
||||
while(it != client_list.end()) {
|
||||
Client *client = it->second;
|
||||
eqFilterType filter = FilterNone;
|
||||
if (chan_num == 3) //shout
|
||||
if (chan_num == ChatChannel_Shout) //shout
|
||||
filter = FilterShouts;
|
||||
else if (chan_num == 4) //auction
|
||||
else if (chan_num == ChatChannel_Auction) //auction
|
||||
filter = FilterAuctions;
|
||||
//
|
||||
// Only say is limited in range
|
||||
if (chan_num != 8 || Distance(client->GetPosition(), from->GetPosition()) < 200)
|
||||
if (chan_num != ChatChannel_Say || Distance(client->GetPosition(), from->GetPosition()) < 200)
|
||||
if (filter == FilterNone || client->GetFilter(filter) != FilterHide)
|
||||
client->ChannelMessageSend(from->GetName(), 0, chan_num, language, lang_skill, buffer);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::ChannelMessageSend(Mob *to, uint8 chan_num, uint8 language, const char *message, ...)
|
||||
{
|
||||
if (!to->IsClient())
|
||||
return;
|
||||
va_list argptr;
|
||||
char buffer[4096];
|
||||
|
||||
va_start(argptr, message);
|
||||
vsnprintf(buffer, 4096, message, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
to->CastToClient()->ChannelMessageSend(0, 0, chan_num, language, buffer);
|
||||
}
|
||||
|
||||
void EntityList::SendZoneSpawns(Client *client)
|
||||
{
|
||||
EQApplicationPacket *app;
|
||||
@@ -1727,6 +1713,18 @@ Client *EntityList::GetClientByWID(uint32 iWID)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Client *EntityList::GetClientByLSID(uint32 iLSID)
|
||||
{
|
||||
auto it = client_list.begin();
|
||||
while (it != client_list.end()) {
|
||||
if (it->second->LSAccountID() == iLSID) {
|
||||
return it->second;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Client *EntityList::GetRandomClient(const glm::vec3& location, float Distance, Client *ExcludeClient)
|
||||
{
|
||||
std::vector<Client *> ClientsInRange;
|
||||
@@ -1995,22 +1993,22 @@ Client *EntityList::GetClientByAccID(uint32 accid)
|
||||
}
|
||||
|
||||
void EntityList::ChannelMessageFromWorld(const char *from, const char *to,
|
||||
uint8 chan_num, uint32 guild_id, uint8 language, const char *message)
|
||||
uint8 chan_num, uint32 guild_id, uint8 language, uint8 lang_skill, const char *message)
|
||||
{
|
||||
for (auto it = client_list.begin(); it != client_list.end(); ++it) {
|
||||
Client *client = it->second;
|
||||
if (chan_num == 0) {
|
||||
if (chan_num == ChatChannel_Guild) {
|
||||
if (!client->IsInGuild(guild_id))
|
||||
continue;
|
||||
if (!guild_mgr.CheckPermission(guild_id, client->GuildRank(), GUILD_HEAR))
|
||||
continue;
|
||||
if (client->GetFilter(FilterGuildChat) == FilterHide)
|
||||
continue;
|
||||
} else if (chan_num == 5) {
|
||||
} else if (chan_num == ChatChannel_OOC) {
|
||||
if (client->GetFilter(FilterOOC) == FilterHide)
|
||||
continue;
|
||||
}
|
||||
client->ChannelMessageSend(from, to, chan_num, language, message);
|
||||
client->ChannelMessageSend(from, to, chan_num, language, lang_skill, message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3747,24 +3745,26 @@ bool Entity::CheckCoordLosNoZLeaps(float cur_x, float cur_y, float cur_z,
|
||||
}
|
||||
|
||||
void EntityList::QuestJournalledSayClose(Mob *sender, Client *QuestInitiator,
|
||||
float dist, const char* mobname, const char* message)
|
||||
float dist, const char* mobname, const char* message, Journal::Options &opts)
|
||||
{
|
||||
Client *c = nullptr;
|
||||
float dist2 = dist * dist;
|
||||
SerializeBuffer buf(sizeof(SpecialMesgHeader_Struct) + 12 + 64 + 64);
|
||||
|
||||
// Send the message to the quest initiator such that the client will enter it into the NPC Quest Journal
|
||||
if (QuestInitiator) {
|
||||
auto buf = new char[strlen(mobname) + strlen(message) + 10];
|
||||
sprintf(buf, "%s says, '%s'", mobname, message);
|
||||
QuestInitiator->QuestJournalledMessage(mobname, buf);
|
||||
safe_delete_array(buf);
|
||||
}
|
||||
// Use the old method for all other nearby clients
|
||||
for (auto it = client_list.begin(); it != client_list.end(); ++it) {
|
||||
c = it->second;
|
||||
if(c && (c != QuestInitiator) && DistanceSquared(c->GetPosition(), sender->GetPosition()) <= dist2)
|
||||
c->Message_StringID(10, GENERIC_SAY, mobname, message);
|
||||
}
|
||||
buf.WriteInt8(static_cast<int8>(opts.speak_mode));
|
||||
buf.WriteInt8(static_cast<int8>(opts.journal_mode));
|
||||
buf.WriteInt8(opts.language);
|
||||
buf.WriteInt32(opts.message_type);
|
||||
buf.WriteInt32(opts.target_spawn_id);
|
||||
buf.WriteString(mobname);
|
||||
buf.WriteInt32(0); // location, client doesn't seem to do anything with this
|
||||
buf.WriteInt32(0);
|
||||
buf.WriteInt32(0);
|
||||
buf.WriteString(message);
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||
|
||||
// client only bothers logging if target spawn ID matches, safe to send to everyone
|
||||
QueueCloseClients(sender, outapp, false, dist);
|
||||
delete outapp;
|
||||
}
|
||||
|
||||
Corpse *EntityList::GetClosestCorpse(Mob *sender, const char *Name)
|
||||
@@ -3880,7 +3880,7 @@ void EntityList::GroupMessage(uint32 gid, const char *from, const char *message)
|
||||
g = it->second->GetGroup();
|
||||
if (g) {
|
||||
if (g->GetID() == gid)
|
||||
it->second->ChannelMessageSend(from, it->second->GetName(), 2, 0, message);
|
||||
it->second->ChannelMessageSend(from, it->second->GetName(), ChatChannel_Group, 0, 100, message);
|
||||
}
|
||||
}
|
||||
++it;
|
||||
|
||||
+4
-3
@@ -29,6 +29,7 @@
|
||||
|
||||
#include "position.h"
|
||||
#include "zonedump.h"
|
||||
#include "common.h"
|
||||
|
||||
class Encounter;
|
||||
class Beacon;
|
||||
@@ -175,6 +176,7 @@ public:
|
||||
}
|
||||
Client *GetClientByCharID(uint32 iCharID);
|
||||
Client *GetClientByWID(uint32 iWID);
|
||||
Client *GetClientByLSID(uint32 iLSID);
|
||||
Client *GetClient(uint32 ip, uint16 port);
|
||||
Client *GetRandomClient(const glm::vec3& location, float Distance, Client *ExcludeClient = nullptr);
|
||||
Group *GetGroupByMob(Mob* mob);
|
||||
@@ -323,10 +325,9 @@ public:
|
||||
void FilteredMessage_StringID(Mob *sender, bool skipsender, uint32 type, eqFilterType filter, uint32 string_id, const char* message1=0,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0);
|
||||
void MessageClose_StringID(Mob *sender, bool skipsender, float dist, uint32 type, uint32 string_id, const char* message1=0,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0);
|
||||
void FilteredMessageClose_StringID(Mob *sender, bool skipsender, float dist, uint32 type, eqFilterType filter, uint32 string_id, const char* message1=0,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0);
|
||||
void ChannelMessageFromWorld(const char* from, const char* to, uint8 chan_num, uint32 guilddbid, uint8 language, const char* message);
|
||||
void ChannelMessageFromWorld(const char* from, const char* to, uint8 chan_num, uint32 guilddbid, uint8 language, uint8 lang_skill, const char* message);
|
||||
void ChannelMessage(Mob* from, uint8 chan_num, uint8 language, const char* message, ...);
|
||||
void ChannelMessage(Mob* from, uint8 chan_num, uint8 language, uint8 lang_skill, const char* message, ...);
|
||||
void ChannelMessageSend(Mob* to, uint8 chan_num, uint8 language, const char* message, ...);
|
||||
void SendZoneSpawns(Client*);
|
||||
void SendZonePVPUpdates(Client *);
|
||||
void SendZoneSpawnsBulk(Client* client);
|
||||
@@ -338,7 +339,7 @@ public:
|
||||
void SendNimbusEffects(Client *c);
|
||||
void SendUntargetable(Client *c);
|
||||
void DuelMessage(Mob* winner, Mob* loser, bool flee);
|
||||
void QuestJournalledSayClose(Mob *sender, Client *QuestIntiator, float dist, const char* mobname, const char* message);
|
||||
void QuestJournalledSayClose(Mob *sender, Client *QuestIntiator, float dist, const char* mobname, const char* message, Journal::Options &opts);
|
||||
void GroupMessage(uint32 gid, const char *from, const char *message);
|
||||
void ExpeditionWarning(uint32 minutes_left);
|
||||
|
||||
|
||||
+2
-2
@@ -910,7 +910,7 @@ void Group::GroupMessage(Mob* sender, uint8 language, uint8 lang_skill, const ch
|
||||
continue;
|
||||
|
||||
if (members[i]->IsClient() && members[i]->CastToClient()->GetFilter(FilterGroupChat)!=0)
|
||||
members[i]->CastToClient()->ChannelMessageSend(sender->GetName(),members[i]->GetName(),2,language,lang_skill,message);
|
||||
members[i]->CastToClient()->ChannelMessageSend(sender->GetName(),members[i]->GetName(),ChatChannel_Group,language,lang_skill,message);
|
||||
}
|
||||
|
||||
auto pack =
|
||||
@@ -2493,4 +2493,4 @@ void Group::QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_r
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ struct BodyTypes { };
|
||||
struct Filters { };
|
||||
struct MessageTypes { };
|
||||
struct Rule { };
|
||||
struct Journal_SpeakMode { };
|
||||
struct Journal_Mode { };
|
||||
|
||||
struct lua_registered_event {
|
||||
std::string encounter_name;
|
||||
@@ -2232,6 +2234,7 @@ luabind::scope lua_register_message_types() {
|
||||
return luabind::class_<MessageTypes>("MT")
|
||||
.enum_("constants")
|
||||
[
|
||||
luabind::value("NPCQuestSay", MT_NPCQuestSay),
|
||||
luabind::value("Say", MT_Say),
|
||||
luabind::value("Tell", MT_Tell),
|
||||
luabind::value("Group", MT_Group),
|
||||
@@ -2362,4 +2365,27 @@ luabind::scope lua_register_ruleb() {
|
||||
];
|
||||
}
|
||||
|
||||
luabind::scope lua_register_journal_speakmode() {
|
||||
return luabind::class_<Journal_SpeakMode>("SpeakMode")
|
||||
.enum_("constants")
|
||||
[
|
||||
luabind::value("Raw", static_cast<int>(Journal::SpeakMode::Raw)),
|
||||
luabind::value("Say", static_cast<int>(Journal::SpeakMode::Say)),
|
||||
luabind::value("Shout", static_cast<int>(Journal::SpeakMode::Shout)),
|
||||
luabind::value("EmoteAlt", static_cast<int>(Journal::SpeakMode::EmoteAlt)),
|
||||
luabind::value("Emote", static_cast<int>(Journal::SpeakMode::Emote)),
|
||||
luabind::value("Group", static_cast<int>(Journal::SpeakMode::Group))
|
||||
];
|
||||
}
|
||||
|
||||
luabind::scope lua_register_journal_mode() {
|
||||
return luabind::class_<Journal_Mode>("JournalMode")
|
||||
.enum_("constants")
|
||||
[
|
||||
luabind::value("None", static_cast<int>(Journal::Mode::None)),
|
||||
luabind::value("Log1", static_cast<int>(Journal::Mode::Log1)),
|
||||
luabind::value("Log2", static_cast<int>(Journal::Mode::Log2))
|
||||
];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,6 +19,8 @@ luabind::scope lua_register_rules_const();
|
||||
luabind::scope lua_register_rulei();
|
||||
luabind::scope lua_register_ruler();
|
||||
luabind::scope lua_register_ruleb();
|
||||
luabind::scope lua_register_journal_speakmode();
|
||||
luabind::scope lua_register_journal_mode();
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
+75
-4
@@ -753,9 +753,72 @@ void Lua_Mob::Say(const char *message) {
|
||||
self->Say(message);
|
||||
}
|
||||
|
||||
void Lua_Mob::Say(const char* message, int language) {
|
||||
Lua_Safe_Call_Void();
|
||||
entity_list.ChannelMessage(self, ChatChannel_Say, language, message); // these run through the client channels and probably shouldn't for NPCs, but oh well
|
||||
}
|
||||
|
||||
void Lua_Mob::QuestSay(Lua_Client client, const char *message) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->QuestJournalledSay(client, message);
|
||||
Journal::Options journal_opts;
|
||||
journal_opts.speak_mode = Journal::SpeakMode::Say;
|
||||
journal_opts.journal_mode = RuleB(NPC, EnableNPCQuestJournal) ? Journal::Mode::Log2 : Journal::Mode::None;
|
||||
journal_opts.language = 0;
|
||||
journal_opts.message_type = MT_NPCQuestSay;
|
||||
journal_opts.target_spawn_id = 0;
|
||||
self->QuestJournalledSay(client, message, journal_opts);
|
||||
}
|
||||
|
||||
void Lua_Mob::QuestSay(Lua_Client client, const char *message, luabind::adl::object opts) {
|
||||
Lua_Safe_Call_Void();
|
||||
|
||||
Journal::Options journal_opts;
|
||||
// defaults
|
||||
journal_opts.speak_mode = Journal::SpeakMode::Say;
|
||||
journal_opts.journal_mode = Journal::Mode::Log2;
|
||||
journal_opts.language = 0;
|
||||
journal_opts.message_type = MT_NPCQuestSay;
|
||||
journal_opts.target_spawn_id = 0;
|
||||
|
||||
if (luabind::type(opts) == LUA_TTABLE) {
|
||||
auto cur = opts["speak_mode"];
|
||||
if (luabind::type(cur) != LUA_TNIL) {
|
||||
try {
|
||||
journal_opts.speak_mode = static_cast<Journal::SpeakMode>(luabind::object_cast<int>(cur));
|
||||
} catch (luabind::cast_failed) {
|
||||
}
|
||||
}
|
||||
|
||||
cur = opts["journal_mode"];
|
||||
if (luabind::type(cur) != LUA_TNIL) {
|
||||
try {
|
||||
journal_opts.journal_mode = static_cast<Journal::Mode>(luabind::object_cast<int>(cur));
|
||||
} catch (luabind::cast_failed) {
|
||||
}
|
||||
}
|
||||
|
||||
cur = opts["language"];
|
||||
if (luabind::type(cur) != LUA_TNIL) {
|
||||
try {
|
||||
journal_opts.language = luabind::object_cast<int>(cur);
|
||||
} catch (luabind::cast_failed) {
|
||||
}
|
||||
}
|
||||
|
||||
cur = opts["message_type"];
|
||||
if (luabind::type(cur) != LUA_TNIL) {
|
||||
try {
|
||||
journal_opts.message_type = luabind::object_cast<int>(cur);
|
||||
} catch (luabind::cast_failed) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if rule disables it, we override provided
|
||||
if (!RuleB(NPC, EnableNPCQuestJournal))
|
||||
journal_opts.journal_mode = Journal::Mode::None;
|
||||
|
||||
self->QuestJournalledSay(client, message, journal_opts);
|
||||
}
|
||||
|
||||
void Lua_Mob::Shout(const char *message) {
|
||||
@@ -763,6 +826,11 @@ void Lua_Mob::Shout(const char *message) {
|
||||
self->Shout(message);
|
||||
}
|
||||
|
||||
void Lua_Mob::Shout(const char* message, int language) {
|
||||
Lua_Safe_Call_Void();
|
||||
entity_list.ChannelMessage(self, ChatChannel_Shout, language, message);
|
||||
}
|
||||
|
||||
void Lua_Mob::Emote(const char *message) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->Emote(message);
|
||||
@@ -2319,9 +2387,12 @@ luabind::scope lua_register_mob() {
|
||||
.def("GetSize", &Lua_Mob::GetSize)
|
||||
.def("Message", &Lua_Mob::Message)
|
||||
.def("Message_StringID", &Lua_Mob::Message_StringID)
|
||||
.def("Say", &Lua_Mob::Say)
|
||||
.def("QuestSay", &Lua_Mob::QuestSay)
|
||||
.def("Shout", &Lua_Mob::Shout)
|
||||
.def("Say", (void(Lua_Mob::*)(const char*))& Lua_Mob::Say)
|
||||
.def("Say", (void(Lua_Mob::*)(const char*, int))& Lua_Mob::Say)
|
||||
.def("QuestSay", (void(Lua_Mob::*)(Lua_Client,const char *))&Lua_Mob::QuestSay)
|
||||
.def("QuestSay", (void(Lua_Mob::*)(Lua_Client,const char *,luabind::adl::object))&Lua_Mob::QuestSay)
|
||||
.def("Shout", (void(Lua_Mob::*)(const char*))& Lua_Mob::Shout)
|
||||
.def("Shout", (void(Lua_Mob::*)(const char*, int))& Lua_Mob::Shout)
|
||||
.def("Emote", &Lua_Mob::Emote)
|
||||
.def("InterruptSpell", (void(Lua_Mob::*)(void))&Lua_Mob::InterruptSpell)
|
||||
.def("InterruptSpell", (void(Lua_Mob::*)(int))&Lua_Mob::InterruptSpell)
|
||||
|
||||
@@ -168,8 +168,11 @@ public:
|
||||
void Message(int type, const char *message);
|
||||
void Message_StringID(int type, int string_id, uint32 distance);
|
||||
void Say(const char *message);
|
||||
void Say(const char* message, int language);
|
||||
void QuestSay(Lua_Client client, const char *message);
|
||||
void QuestSay(Lua_Client client, const char *message, luabind::adl::object opts);
|
||||
void Shout(const char *message);
|
||||
void Shout(const char* message, int language);
|
||||
void Emote(const char *message);
|
||||
void InterruptSpell();
|
||||
void InterruptSpell(int spell_id);
|
||||
|
||||
+3
-1
@@ -1102,7 +1102,9 @@ void LuaParser::MapFunctions(lua_State *L) {
|
||||
lua_register_rules_const(),
|
||||
lua_register_rulei(),
|
||||
lua_register_ruler(),
|
||||
lua_register_ruleb()
|
||||
lua_register_ruleb(),
|
||||
lua_register_journal_speakmode(),
|
||||
lua_register_journal_mode()
|
||||
];
|
||||
|
||||
} catch(std::exception &ex) {
|
||||
|
||||
+6
-2
@@ -2911,9 +2911,13 @@ void Mob::Emote(const char *format, ...)
|
||||
GENERIC_EMOTE, GetCleanName(), buf);
|
||||
}
|
||||
|
||||
void Mob::QuestJournalledSay(Client *QuestInitiator, const char *str)
|
||||
void Mob::QuestJournalledSay(Client *QuestInitiator, const char *str, Journal::Options &opts)
|
||||
{
|
||||
entity_list.QuestJournalledSayClose(this, QuestInitiator, 200, GetCleanName(), str);
|
||||
// just in case
|
||||
if (opts.target_spawn_id == 0 && QuestInitiator)
|
||||
opts.target_spawn_id = QuestInitiator->GetID();
|
||||
|
||||
entity_list.QuestJournalledSayClose(this, QuestInitiator, 200, GetCleanName(), str, opts);
|
||||
}
|
||||
|
||||
const char *Mob::GetCleanName()
|
||||
|
||||
+1
-1
@@ -744,7 +744,7 @@ public:
|
||||
const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0);
|
||||
void Shout(const char *format, ...);
|
||||
void Emote(const char *format, ...);
|
||||
void QuestJournalledSay(Client *QuestInitiator, const char *str);
|
||||
void QuestJournalledSay(Client *QuestInitiator, const char *str, Journal::Options &opts);
|
||||
int32 GetItemStat(uint32 itemid, const char *identifier);
|
||||
|
||||
int16 CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, bool best_focus=false);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
+1
-1
@@ -514,7 +514,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
else {
|
||||
if (worldwasconnected && is_zone_loaded) {
|
||||
entity_list.ChannelMessageFromWorld(0, 0, 6, 0, 0, "WARNING: World server connection lost");
|
||||
entity_list.ChannelMessageFromWorld(0, 0, ChatChannel_Broadcast, 0, 0, 100, "WARNING: World server connection lost");
|
||||
worldwasconnected = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<GravityBehavior>(npc_type_data->flymode);
|
||||
}
|
||||
|
||||
guard_anim = eaStanding;
|
||||
roambox_distance = 0;
|
||||
roambox_max_x = -2;
|
||||
|
||||
+6
-17
@@ -154,30 +154,19 @@ void QuestManager::echo(int colour, const char *str) {
|
||||
entity_list.MessageClose(initiator, false, 200, colour, str);
|
||||
}
|
||||
|
||||
void QuestManager::say(const char *str) {
|
||||
void QuestManager::say(const char *str, Journal::Options &opts) {
|
||||
QuestManagerCurrentQuestVars();
|
||||
if (!owner) {
|
||||
Log(Logs::General, Logs::Quests, "QuestManager::say called with nullptr owner. Probably syntax error in quest file.");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if(RuleB(NPC, EnableNPCQuestJournal) && initiator) {
|
||||
owner->QuestJournalledSay(initiator, str);
|
||||
if (!RuleB(NPC, EnableNPCQuestJournal))
|
||||
opts.journal_mode = Journal::Mode::None;
|
||||
if (initiator) {
|
||||
opts.target_spawn_id = initiator->GetID();
|
||||
owner->QuestJournalledSay(initiator, str, opts);
|
||||
}
|
||||
else {
|
||||
owner->Say(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QuestManager::say(const char *str, uint8 language) {
|
||||
QuestManagerCurrentQuestVars();
|
||||
if (!owner) {
|
||||
Log(Logs::General, Logs::Quests, "QuestManager::say called with nullptr owner. Probably syntax error in quest file.");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
entity_list.ChannelMessage(owner, 8, language, str);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -62,8 +62,7 @@ public:
|
||||
|
||||
//quest functions
|
||||
void echo(int colour, const char *str);
|
||||
void say(const char *str);
|
||||
void say(const char *str, uint8 language);
|
||||
void say(const char *str, Journal::Options &opts);
|
||||
void me(const char *str);
|
||||
void summonitem(uint32 itemid, int16 charges = -1);
|
||||
void write(const char *file, const char *str);
|
||||
|
||||
+7
-3
@@ -446,7 +446,7 @@ uint32 Raid::GetGroup(Client *c)
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
void Raid::RaidSay(const char *msg, Client *c)
|
||||
void Raid::RaidSay(const char *msg, Client *c, uint8 language, uint8 lang_skill)
|
||||
{
|
||||
if(!c)
|
||||
return;
|
||||
@@ -455,6 +455,8 @@ void Raid::RaidSay(const char *msg, Client *c)
|
||||
ServerRaidMessage_Struct *rga = (ServerRaidMessage_Struct*)pack->pBuffer;
|
||||
rga->rid = GetID();
|
||||
rga->gid = 0xFFFFFFFF;
|
||||
rga->language = language;
|
||||
rga->lang_skill = lang_skill;
|
||||
strn0cpy(rga->from, c->GetName(), 64);
|
||||
|
||||
strcpy(rga->message, msg); // this is safe because we are allocating enough space for the entire msg above
|
||||
@@ -463,7 +465,7 @@ void Raid::RaidSay(const char *msg, Client *c)
|
||||
safe_delete(pack);
|
||||
}
|
||||
|
||||
void Raid::RaidGroupSay(const char *msg, Client *c)
|
||||
void Raid::RaidGroupSay(const char *msg, Client *c, uint8 language, uint8 lang_skill)
|
||||
{
|
||||
if(!c)
|
||||
return;
|
||||
@@ -477,6 +479,8 @@ void Raid::RaidGroupSay(const char *msg, Client *c)
|
||||
ServerRaidMessage_Struct *rga = (ServerRaidMessage_Struct*)pack->pBuffer;
|
||||
rga->rid = GetID();
|
||||
rga->gid = groupToUse;
|
||||
rga->language = language;
|
||||
rga->lang_skill = lang_skill;
|
||||
strn0cpy(rga->from, c->GetName(), 64);
|
||||
|
||||
strcpy(rga->message, msg); // this is safe because we are allocating enough space for the entire msg above
|
||||
@@ -1821,4 +1825,4 @@ void Raid::QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_re
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -177,8 +177,8 @@ public:
|
||||
void SendHPManaEndPacketsFrom(Mob *mob);
|
||||
void SendManaPacketFrom(Mob *mob);
|
||||
void SendEndurancePacketFrom(Mob *mob);
|
||||
void RaidSay(const char *msg, Client *c);
|
||||
void RaidGroupSay(const char *msg, Client *c);
|
||||
void RaidSay(const char *msg, Client *c, uint8 language, uint8 lang_skill);
|
||||
void RaidGroupSay(const char *msg, Client *c, uint8 language, uint8 lang_skill);
|
||||
|
||||
//Packet Functions
|
||||
void SendRaidCreate(Client *to);
|
||||
|
||||
+37
-12
@@ -200,29 +200,35 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
break;
|
||||
ServerChannelMessage_Struct* scm = (ServerChannelMessage_Struct*)pack->pBuffer;
|
||||
if (scm->deliverto[0] == 0) {
|
||||
entity_list.ChannelMessageFromWorld(scm->from, scm->to, scm->chan_num, scm->guilddbid, scm->language, scm->message);
|
||||
entity_list.ChannelMessageFromWorld(scm->from, scm->to, scm->chan_num, scm->guilddbid, scm->language, scm->lang_skill, scm->message);
|
||||
}
|
||||
else {
|
||||
Client* client = entity_list.GetClientByName(scm->deliverto);
|
||||
if (client) {
|
||||
if (client->Connected()) {
|
||||
if (client && client->Connected()) {
|
||||
if (scm->chan_num == ChatChannel_TellEcho) {
|
||||
if (scm->queued == 1) // tell was queued
|
||||
client->Tell_StringID(QUEUED_TELL, scm->to, scm->message);
|
||||
else if (scm->queued == 2) // tell queue was full
|
||||
client->Tell_StringID(QUEUE_TELL_FULL, scm->to, scm->message);
|
||||
else if (scm->queued == 3) // person was offline
|
||||
client->Message_StringID(MT_TellEcho, TOLD_NOT_ONLINE, scm->to);
|
||||
else // normal stuff
|
||||
client->ChannelMessageSend(scm->from, scm->to, scm->chan_num, scm->language, scm->message);
|
||||
if (!scm->noreply && scm->chan_num != 2) { //dont echo on group chat
|
||||
// if it's a tell, echo back so it shows up
|
||||
scm->noreply = true;
|
||||
scm->chan_num = 14;
|
||||
else // normal tell echo "You told Soanso, 'something'"
|
||||
// tell echo doesn't use language, so it looks normal to you even if nobody can understand your tells
|
||||
client->ChannelMessageSend(scm->from, scm->to, scm->chan_num, 0, 100, scm->message);
|
||||
}
|
||||
else if (scm->chan_num == ChatChannel_Tell) {
|
||||
client->ChannelMessageSend(scm->from, scm->to, scm->chan_num, scm->language, scm->lang_skill, scm->message);
|
||||
if (scm->queued == 0) { // this is not a queued tell
|
||||
// if it's a tell, echo back to acknowledge it and make it show on the sender's client
|
||||
scm->chan_num = ChatChannel_TellEcho;
|
||||
memset(scm->deliverto, 0, sizeof(scm->deliverto));
|
||||
strcpy(scm->deliverto, scm->from);
|
||||
SendPacket(pack);
|
||||
}
|
||||
}
|
||||
else {
|
||||
client->ChannelMessageSend(scm->from, scm->to, scm->chan_num, scm->language, scm->lang_skill, scm->message);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -528,6 +534,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
ServerZoneIncomingClient_Struct* szic = (ServerZoneIncomingClient_Struct*)pack->pBuffer;
|
||||
if (is_zone_loaded) {
|
||||
SetZoneData(zone->GetZoneID(), zone->GetInstanceID());
|
||||
|
||||
if (szic->zoneid == zone->GetZoneID()) {
|
||||
zone->AddAuth(szic);
|
||||
// This packet also doubles as "incoming client" notification, lets not shut down before they get here
|
||||
@@ -541,6 +548,23 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_DropClient: {
|
||||
if (pack->size != sizeof(ServerZoneDropClient_Struct)) {
|
||||
break;
|
||||
}
|
||||
|
||||
ServerZoneDropClient_Struct* drop = (ServerZoneDropClient_Struct*)pack->pBuffer;
|
||||
if (zone) {
|
||||
zone->RemoveAuth(drop->lsid);
|
||||
|
||||
auto client = entity_list.GetClientByLSID(drop->lsid);
|
||||
if (client) {
|
||||
client->Kick();
|
||||
client->Save();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_ZonePlayer: {
|
||||
ServerZonePlayer_Struct* szp = (ServerZonePlayer_Struct*)pack->pBuffer;
|
||||
Client* client = entity_list.GetClientByName(szp->name);
|
||||
@@ -1352,7 +1376,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
if (r->members[x].GroupNumber == rmsg->gid) {
|
||||
if (r->members[x].member->GetFilter(FilterGroupChat) != 0)
|
||||
{
|
||||
r->members[x].member->ChannelMessageSend(rmsg->from, r->members[x].member->GetName(), 2, 0, rmsg->message);
|
||||
r->members[x].member->ChannelMessageSend(rmsg->from, r->members[x].member->GetName(), ChatChannel_Group, rmsg->language, rmsg->lang_skill, rmsg->message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1377,7 +1401,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
{
|
||||
if (r->members[x].member->GetFilter(FilterGroupChat) != 0)
|
||||
{
|
||||
r->members[x].member->ChannelMessageSend(rmsg->from, r->members[x].member->GetName(), 15, 0, rmsg->message);
|
||||
r->members[x].member->ChannelMessageSend(rmsg->from, r->members[x].member->GetName(), ChatChannel_Raid, rmsg->language, rmsg->lang_skill, rmsg->message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1950,7 +1974,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
}
|
||||
}
|
||||
|
||||
bool WorldServer::SendChannelMessage(Client* from, const char* to, uint8 chan_num, uint32 guilddbid, uint8 language, const char* message, ...) {
|
||||
bool WorldServer::SendChannelMessage(Client* from, const char* to, uint8 chan_num, uint32 guilddbid, uint8 language, uint8 lang_skill, const char* message, ...) {
|
||||
if (!worldserver.Connected())
|
||||
return false;
|
||||
va_list argptr;
|
||||
@@ -1984,6 +2008,7 @@ bool WorldServer::SendChannelMessage(Client* from, const char* to, uint8 chan_nu
|
||||
scm->chan_num = chan_num;
|
||||
scm->guilddbid = guilddbid;
|
||||
scm->language = language;
|
||||
scm->lang_skill = lang_skill;
|
||||
scm->queued = 0;
|
||||
strcpy(scm->message, buffer);
|
||||
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ public:
|
||||
|
||||
void HandleMessage(uint16 opcode, const EQ::Net::Packet &p);
|
||||
|
||||
bool SendChannelMessage(Client* from, const char* to, uint8 chan_num, uint32 guilddbid, uint8 language, const char* message, ...);
|
||||
bool SendChannelMessage(Client* from, const char* to, uint8 chan_num, uint32 guilddbid, uint8 language, uint8 lang_skill, const char* message, ...);
|
||||
bool SendEmoteMessage(const char* to, uint32 to_guilddbid, uint32 type, const char* message, ...);
|
||||
bool SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...);
|
||||
bool SendVoiceMacro(Client* From, uint32 Type, char* Target, uint32 MacroNumber, uint32 GroupOrRaidID = 0);
|
||||
|
||||
+20
-4
@@ -1106,6 +1106,7 @@ void Zone::AddAuth(ServerZoneIncomingClient_Struct* szic) {
|
||||
zca->accid = szic->accid;
|
||||
zca->admin = szic->admin;
|
||||
zca->charid = szic->charid;
|
||||
zca->lsid = szic->lsid;
|
||||
zca->tellsoff = szic->tellsoff;
|
||||
strn0cpy(zca->charname, szic->charname, sizeof(zca->charname));
|
||||
strn0cpy(zca->lskey, szic->lskey, sizeof(zca->lskey));
|
||||
@@ -1113,16 +1114,31 @@ void Zone::AddAuth(ServerZoneIncomingClient_Struct* szic) {
|
||||
client_auth_list.Insert(zca);
|
||||
}
|
||||
|
||||
void Zone::RemoveAuth(const char* iCharName)
|
||||
void Zone::RemoveAuth(const char* iCharName, const char* iLSKey)
|
||||
{
|
||||
LinkedListIterator<ZoneClientAuth_Struct*> iterator(client_auth_list);
|
||||
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
ZoneClientAuth_Struct* zca = iterator.GetData();
|
||||
if (strcasecmp(zca->charname, iCharName) == 0) {
|
||||
iterator.RemoveCurrent();
|
||||
return;
|
||||
if (strcasecmp(zca->charname, iCharName) == 0 && strcasecmp(zca->lskey, iLSKey) == 0) {
|
||||
iterator.RemoveCurrent();
|
||||
return;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
}
|
||||
|
||||
void Zone::RemoveAuth(uint32 lsid)
|
||||
{
|
||||
LinkedListIterator<ZoneClientAuth_Struct*> iterator(client_auth_list);
|
||||
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
ZoneClientAuth_Struct* zca = iterator.GetData();
|
||||
if (zca->lsid == lsid) {
|
||||
iterator.RemoveCurrent();
|
||||
continue;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
|
||||
+3
-1
@@ -52,6 +52,7 @@ struct ZoneClientAuth_Struct {
|
||||
uint32 accid;
|
||||
int16 admin;
|
||||
uint32 charid;
|
||||
uint32 lsid;
|
||||
bool tellsoff;
|
||||
char charname[64];
|
||||
char lskey[30];
|
||||
@@ -243,7 +244,8 @@ public:
|
||||
void LoadZoneDoors(const char *zone, int16 version);
|
||||
void ReloadStaticData();
|
||||
void ReloadWorld(uint32 Option);
|
||||
void RemoveAuth(const char *iCharName);
|
||||
void RemoveAuth(const char *iCharName, const char *iLSKey);
|
||||
void RemoveAuth(uint32 lsid);
|
||||
void Repop(uint32 delay = 0);
|
||||
void RepopClose(const glm::vec4 &client_position, uint32 repop_distance);
|
||||
void RequestUCSServerStatus();
|
||||
|
||||
+149
-132
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user