mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 01:11:29 +00:00
Merge remote-tracking branch 'remotes/origin/master' into logging_changes
Conflicts: zone/command.cpp zone/command.h zone/inventory.cpp
This commit is contained in:
commit
3d74035e24
@ -1,5 +1,34 @@
|
||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||
-------------------------------------------------------
|
||||
== 01/15/2015 ==
|
||||
Uleat: Attempted fix for elusive inventory bug:
|
||||
- Removed 'iter_queue' typedef and converted lcast to explicit or auto defines
|
||||
- Reworked several functions that manipulate the cursor queue
|
||||
- Found/corrected one occurrence of post-processing iterator incrementing in an ItemInstQueue handler
|
||||
- Added many scope declarations in code that handles inventory manipulation (loose macros are bad...)
|
||||
Uleat: Added Item_Struct pointer checks to ItemInst methods that did not have them
|
||||
Uleat: Changed IsEquippable(race,class) to use bit-wise 'and' (&) over '(x%2)==1' in conditional check.
|
||||
Uleat: Changed DyeArmor() assignment of 'armor_color' to use bit-wise 'or' and bit-shifting (|,<<) over multiplication and addition (*,+).
|
||||
|
||||
== 01/13/2015 ==
|
||||
Uleat: Placed an upper limit on the cursor queue save loop.
|
||||
Trevius: (RoF2) Guild invites now add new members as members instead of recruits, and /guild chat works properly.
|
||||
Trevius: (RoF2) Guild Promote is now functional.
|
||||
|
||||
== 01/12/2015 ==
|
||||
Uleat: Fix for OP_FormattedMessage text link server crashes
|
||||
Uleat: Added text link translators for OP_TaskDescription (RoF+ -- all clients current)
|
||||
Uleat: Fix for load_bots.sql using '\\' as a delimiter (Changed to '$$')
|
||||
|
||||
== 01/11/2015 ==
|
||||
Uleat: Added text link translators for OP_TaskDescription (Ti thru UF..RoF+ in-work)
|
||||
|
||||
== 01/10/2015 ==
|
||||
Uleat: Added text link translators for OP_Emote
|
||||
|
||||
== 01/09/2015 ==
|
||||
Uleat: Added text link translators for OP_FormattedMessage
|
||||
|
||||
== 01/08/2015 ==
|
||||
Trevius: Added some extra checks and clean-up related to Groups and Mercenaries.
|
||||
|
||||
|
||||
@ -2388,7 +2388,7 @@ struct AugmentItem_Struct {
|
||||
|
||||
// OP_Emote
|
||||
struct Emote_Struct {
|
||||
/*0000*/ uint32 unknown01;
|
||||
/*0000*/ uint32 type; // 0 - custom, 0xffffffff - command (/dance, /flip, etc...)
|
||||
/*0004*/ char message[1024];
|
||||
/*1028*/
|
||||
};
|
||||
|
||||
781
common/item.cpp
781
common/item.cpp
File diff suppressed because it is too large
Load Diff
@ -34,7 +34,6 @@ class EvolveInfo; // Stores information about an evolving item family
|
||||
#include <map>
|
||||
|
||||
// Helper typedefs
|
||||
typedef std::list<ItemInst*>::const_iterator iter_queue;
|
||||
typedef std::map<int16, ItemInst*>::const_iterator iter_inst;
|
||||
typedef std::map<uint8, ItemInst*>::const_iterator iter_contents;
|
||||
|
||||
@ -87,15 +86,17 @@ public:
|
||||
// Public Methods
|
||||
/////////////////////////
|
||||
|
||||
inline iter_queue begin() { return m_list.begin(); }
|
||||
inline iter_queue end() { return m_list.end(); }
|
||||
inline std::list<ItemInst*>::const_iterator begin() { return m_list.begin(); }
|
||||
inline std::list<ItemInst*>::const_iterator end() { return m_list.end(); }
|
||||
|
||||
inline int size() { return static_cast<int>(m_list.size()); } // TODO: change to size_t
|
||||
inline bool empty() { return m_list.empty(); }
|
||||
|
||||
void push(ItemInst* inst);
|
||||
void push_front(ItemInst* inst);
|
||||
ItemInst* pop();
|
||||
ItemInst* pop_back();
|
||||
ItemInst* peek_front() const;
|
||||
inline int size() { return static_cast<int>(m_list.size()); }
|
||||
|
||||
protected:
|
||||
/////////////////////////
|
||||
@ -103,7 +104,6 @@ protected:
|
||||
/////////////////////////
|
||||
|
||||
std::list<ItemInst*> m_list;
|
||||
|
||||
};
|
||||
|
||||
// ########################################
|
||||
@ -140,9 +140,11 @@ public:
|
||||
ItemInst* GetItem(int16 slot_id) const;
|
||||
ItemInst* GetItem(int16 slot_id, uint8 bagidx) const;
|
||||
|
||||
inline iter_queue cursor_begin() { return m_cursor.begin(); }
|
||||
inline iter_queue cursor_end() { return m_cursor.end(); }
|
||||
inline bool CursorEmpty() { return (m_cursor.size() == 0); }
|
||||
inline std::list<ItemInst*>::const_iterator cursor_begin() { return m_cursor.begin(); }
|
||||
inline std::list<ItemInst*>::const_iterator cursor_end() { return m_cursor.end(); }
|
||||
|
||||
inline int CursorSize() { return m_cursor.size(); }
|
||||
inline bool CursorEmpty() { return m_cursor.empty(); }
|
||||
|
||||
// Retrieve a read-only item from inventory
|
||||
inline const ItemInst* operator[](int16 slot_id) const { return GetItem(slot_id); }
|
||||
@ -291,15 +293,15 @@ public:
|
||||
bool IsEquipable(int16 slot_id) const;
|
||||
|
||||
//
|
||||
// Augements
|
||||
// Augments
|
||||
//
|
||||
inline bool IsAugmentable() const { return m_item->AugSlotType[0] != 0 || m_item->AugSlotType[1] != 0 || m_item->AugSlotType[2] != 0 || m_item->AugSlotType[3] != 0 || m_item->AugSlotType[4] != 0 || m_item->AugSlotType[5] != 0; }
|
||||
bool IsAugmentable() const;
|
||||
bool AvailableWearSlot(uint32 aug_wear_slots) const;
|
||||
int8 AvailableAugmentSlot(int32 augtype) const;
|
||||
bool IsAugmentSlotAvailable(int32 augtype, uint8 slot) const;
|
||||
inline int32 GetAugmentType() const { return m_item->AugType; }
|
||||
inline int32 GetAugmentType() const { return ((m_item) ? m_item->AugType : NO_ITEM); }
|
||||
|
||||
inline bool IsExpendable() const { return ((m_item->Click.Type == ET_Expendable ) || (m_item->ItemType == ItemTypePotion)); }
|
||||
inline bool IsExpendable() const { return ((m_item) ? ((m_item->Click.Type == ET_Expendable ) || (m_item->ItemType == ItemTypePotion)) : false); }
|
||||
|
||||
//
|
||||
// Contents
|
||||
@ -337,8 +339,8 @@ public:
|
||||
bool IsAmmo() const;
|
||||
|
||||
// Accessors
|
||||
const uint32 GetID() const { return m_item->ID; }
|
||||
const uint32 GetItemScriptID() const { return m_item->ScriptFileID; }
|
||||
const uint32 GetID() const { return ((m_item) ? m_item->ID : NO_ITEM); }
|
||||
const uint32 GetItemScriptID() const { return ((m_item) ? m_item->ScriptFileID : NO_ITEM); }
|
||||
const Item_Struct* GetItem() const;
|
||||
const Item_Struct* GetUnscaledItem() const;
|
||||
|
||||
@ -351,18 +353,18 @@ public:
|
||||
void SetColor(uint32 color) { m_color = color; }
|
||||
uint32 GetColor() const { return m_color; }
|
||||
|
||||
uint32 GetMerchantSlot() const { return m_merchantslot; }
|
||||
uint32 GetMerchantSlot() const { return m_merchantslot; }
|
||||
void SetMerchantSlot(uint32 slot) { m_merchantslot = slot; }
|
||||
|
||||
int32 GetMerchantCount() const { return m_merchantcount; }
|
||||
int32 GetMerchantCount() const { return m_merchantcount; }
|
||||
void SetMerchantCount(int32 count) { m_merchantcount = count; }
|
||||
|
||||
int16 GetCurrentSlot() const { return m_currentslot; }
|
||||
void SetCurrentSlot(int16 curr_slot) { m_currentslot = curr_slot; }
|
||||
|
||||
// Is this item already attuned?
|
||||
bool IsAttuned() const { return m_attuned; }
|
||||
void SetAttuned(bool flag) { m_attuned=flag; }
|
||||
bool IsAttuned() const { return m_attuned; }
|
||||
void SetAttuned(bool flag) { m_attuned=flag; }
|
||||
|
||||
std::string GetCustomDataString() const;
|
||||
std::string GetCustomData(std::string identifier);
|
||||
|
||||
@ -831,6 +831,34 @@ namespace RoF
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_Emote)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
Emote_Struct *emu = (Emote_Struct *)in->pBuffer;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToRoFTextLink(new_message, old_message);
|
||||
|
||||
//if (new_message.length() > 512) // length restricted in packet building function due vari-length name size (no nullterm)
|
||||
// new_message = new_message.substr(0, 512);
|
||||
|
||||
in->size = new_message.length() + 5;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->type);
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_ExpansionInfo)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(ExpansionInfo_Struct);
|
||||
@ -841,6 +869,55 @@ namespace RoF
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_FormattedMessage)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
FormattedMessage_Struct *emu = (FormattedMessage_Struct *)in->pBuffer;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
char *old_message_ptr = (char *)in->pBuffer;
|
||||
old_message_ptr += sizeof(FormattedMessage_Struct);
|
||||
|
||||
std::string old_message_array[9];
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (*old_message_ptr == 0) { break; }
|
||||
old_message_array[i] = old_message_ptr;
|
||||
old_message_ptr += old_message_array[i].length() + 1;
|
||||
}
|
||||
|
||||
uint32 new_message_size = 0;
|
||||
std::string new_message_array[9];
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (old_message_array[i].length() == 0) { break; }
|
||||
ServerToRoFTextLink(new_message_array[i], old_message_array[i]);
|
||||
new_message_size += new_message_array[i].length() + 1;
|
||||
}
|
||||
|
||||
in->size = sizeof(FormattedMessage_Struct) + new_message_size + 1;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->unknown0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->string_id);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->type);
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (new_message_array[i].length() == 0) { break; }
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message_array[i].c_str());
|
||||
}
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0);
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_GMLastName)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(GMLastName_Struct);
|
||||
@ -3118,10 +3195,11 @@ namespace RoF
|
||||
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
|
||||
ServerToRoFTextLink(new_message, old_message);
|
||||
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = 25 + strlen(emu->sayer) + new_message.length();
|
||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
@ -3135,9 +3213,18 @@ namespace RoF
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
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());
|
||||
|
||||
@ -3164,6 +3251,51 @@ namespace RoF
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
char *InBuffer = (char *)in->pBuffer;
|
||||
char *block_start = InBuffer;
|
||||
|
||||
InBuffer += sizeof(TaskDescriptionHeader_Struct);
|
||||
uint32 title_size = strlen(InBuffer) + 1;
|
||||
InBuffer += title_size;
|
||||
|
||||
TaskDescriptionData1_Struct *emu_tdd1 = (TaskDescriptionData1_Struct *)InBuffer;
|
||||
emu_tdd1->StartTime = (time(nullptr) - emu_tdd1->StartTime); // RoF has elapsed time here rather than start time
|
||||
|
||||
InBuffer += sizeof(TaskDescriptionData1_Struct);
|
||||
uint32 description_size = strlen(InBuffer) + 1;
|
||||
InBuffer += description_size;
|
||||
InBuffer += sizeof(TaskDescriptionData2_Struct);
|
||||
|
||||
std::string old_message = InBuffer; // start 'Reward' as string
|
||||
std::string new_message;
|
||||
ServerToRoFTextLink(new_message, old_message);
|
||||
|
||||
in->size = sizeof(TaskDescriptionHeader_Struct) + sizeof(TaskDescriptionData1_Struct)+
|
||||
sizeof(TaskDescriptionData2_Struct) + sizeof(TaskDescriptionTrailer_Struct)+
|
||||
title_size + description_size + new_message.length() + 1;
|
||||
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
memcpy(OutBuffer, block_start, (InBuffer - block_start));
|
||||
OutBuffer += (InBuffer - block_start);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
InBuffer += strlen(InBuffer) + 1;
|
||||
|
||||
memcpy(OutBuffer, InBuffer, sizeof(TaskDescriptionTrailer_Struct));
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
|
||||
#if 0 // original code
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_TaskDescription, in->size + 1);
|
||||
// Set the Write pointer as we don't know what has been done with the packet before we get it.
|
||||
in->SetReadPosition(0);
|
||||
@ -3187,6 +3319,7 @@ namespace RoF
|
||||
|
||||
delete in;
|
||||
dest->FastQueuePacket(&outapp, ack_req);
|
||||
#endif
|
||||
}
|
||||
|
||||
ENCODE(OP_TaskHistoryReply)
|
||||
@ -4220,6 +4353,27 @@ namespace RoF
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_Emote)
|
||||
{
|
||||
unsigned char *__eq_buffer = __packet->pBuffer;
|
||||
|
||||
std::string old_message = (char *)&__eq_buffer[4]; // unknown01 offset
|
||||
std::string new_message;
|
||||
RoFToServerTextLink(new_message, old_message);
|
||||
|
||||
__packet->size = sizeof(Emote_Struct);
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
|
||||
char *InBuffer = (char *)__packet->pBuffer;
|
||||
|
||||
memcpy(InBuffer, __eq_buffer, 4);
|
||||
InBuffer += 4;
|
||||
strcpy(InBuffer, new_message.substr(0, 1023).c_str());
|
||||
InBuffer[1023] = '\0';
|
||||
|
||||
delete[] __eq_buffer;
|
||||
}
|
||||
|
||||
DECODE(OP_EnvDamage)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::EnvDamage2_Struct);
|
||||
@ -5644,73 +5798,73 @@ namespace RoF
|
||||
|
||||
static inline void ServerToRoFTextLink(std::string& rofTextLink, const std::string& serverTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) {
|
||||
if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) {
|
||||
rofTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(serverTextLink, delimiter);
|
||||
auto segments = SplitString(serverTextLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
std::string new_segment;
|
||||
if (segments[segment_iter].length() <= EmuConstants::TEXT_LINK_BODY_LENGTH) {
|
||||
rofTextLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
|
||||
// Idx: 0 1 6 11 16 21 26 31 36 37 41 43 48 (Source)
|
||||
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
|
||||
// RoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (55)
|
||||
// Diff: ^
|
||||
|
||||
new_segment.append(segments[segment_iter].substr(0, 41).c_str());
|
||||
rofTextLink.push_back('\x12');
|
||||
rofTextLink.append(segments[segment_iter].substr(0, 41));
|
||||
|
||||
if (segments[segment_iter].substr(41, 1) == "0")
|
||||
new_segment.append(segments[segment_iter].substr(42, 1).c_str());
|
||||
if (segments[segment_iter][41] == '0')
|
||||
rofTextLink.push_back(segments[segment_iter][42]);
|
||||
else
|
||||
new_segment.append("F");
|
||||
rofTextLink.push_back('F');
|
||||
|
||||
new_segment.append(segments[segment_iter].substr(43).c_str());
|
||||
|
||||
rofTextLink.push_back(delimiter);
|
||||
rofTextLink.append(new_segment.c_str());
|
||||
rofTextLink.push_back(delimiter);
|
||||
rofTextLink.append(segments[segment_iter].substr(43));
|
||||
rofTextLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
rofTextLink.append(segments[segment_iter].c_str());
|
||||
rofTextLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void RoFToServerTextLink(std::string& serverTextLink, const std::string& rofTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rofTextLink.find(delimiter) == std::string::npos)) {
|
||||
if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rofTextLink.find('\x12') == std::string::npos)) {
|
||||
serverTextLink = rofTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(rofTextLink, delimiter);
|
||||
auto segments = SplitString(rofTextLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
std::string new_segment;
|
||||
if (segments[segment_iter].length() <= consts::TEXT_LINK_BODY_LENGTH) {
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
|
||||
// Idx: 0 1 6 11 16 21 26 31 36 37 41 42 47 (Source)
|
||||
// RoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (55)
|
||||
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
|
||||
// Diff: ^
|
||||
|
||||
new_segment.append(segments[segment_iter].substr(0, 41).c_str());
|
||||
new_segment.append("0");
|
||||
new_segment.append(segments[segment_iter].substr(41).c_str());
|
||||
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.append(new_segment.c_str());
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.push_back('\x12');
|
||||
serverTextLink.append(segments[segment_iter].substr(0, 41));
|
||||
serverTextLink.push_back('0');
|
||||
serverTextLink.append(segments[segment_iter].substr(41));
|
||||
serverTextLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[segment_iter].c_str());
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -897,6 +897,34 @@ namespace RoF2
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_Emote)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
Emote_Struct *emu = (Emote_Struct *)in->pBuffer;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToRoF2TextLink(new_message, old_message);
|
||||
|
||||
//if (new_message.length() > 512) // length restricted in packet building function due vari-length name size (no nullterm)
|
||||
// new_message = new_message.substr(0, 512);
|
||||
|
||||
in->size = new_message.length() + 5;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->type);
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_ExpansionInfo)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(ExpansionInfo_Struct);
|
||||
@ -907,6 +935,55 @@ namespace RoF2
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_FormattedMessage)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
FormattedMessage_Struct *emu = (FormattedMessage_Struct *)in->pBuffer;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
char *old_message_ptr = (char *)in->pBuffer;
|
||||
old_message_ptr += sizeof(FormattedMessage_Struct);
|
||||
|
||||
std::string old_message_array[9];
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (*old_message_ptr == 0) { break; }
|
||||
old_message_array[i] = old_message_ptr;
|
||||
old_message_ptr += old_message_array[i].length() + 1;
|
||||
}
|
||||
|
||||
uint32 new_message_size = 0;
|
||||
std::string new_message_array[9];
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (old_message_array[i].length() == 0) { break; }
|
||||
ServerToRoF2TextLink(new_message_array[i], old_message_array[i]);
|
||||
new_message_size += new_message_array[i].length() + 1;
|
||||
}
|
||||
|
||||
in->size = sizeof(FormattedMessage_Struct) + new_message_size + 1;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->unknown0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->string_id);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->type);
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (new_message_array[i].length() == 0) { break; }
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message_array[i].c_str());
|
||||
}
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0);
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_GMLastName)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(GMLastName_Struct);
|
||||
@ -3184,10 +3261,11 @@ namespace RoF2
|
||||
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
|
||||
ServerToRoF2TextLink(new_message, old_message);
|
||||
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = 25 + strlen(emu->sayer) + new_message.length();
|
||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
@ -3201,9 +3279,18 @@ namespace RoF2
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
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());
|
||||
|
||||
@ -3230,6 +3317,51 @@ namespace RoF2
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
char *InBuffer = (char *)in->pBuffer;
|
||||
char *block_start = InBuffer;
|
||||
|
||||
InBuffer += sizeof(TaskDescriptionHeader_Struct);
|
||||
uint32 title_size = strlen(InBuffer) + 1;
|
||||
InBuffer += title_size;
|
||||
|
||||
TaskDescriptionData1_Struct *emu_tdd1 = (TaskDescriptionData1_Struct *)InBuffer;
|
||||
emu_tdd1->StartTime = (time(nullptr) - emu_tdd1->StartTime); // RoF2 has elapsed time here rather than start time
|
||||
|
||||
InBuffer += sizeof(TaskDescriptionData1_Struct);
|
||||
uint32 description_size = strlen(InBuffer) + 1;
|
||||
InBuffer += description_size;
|
||||
InBuffer += sizeof(TaskDescriptionData2_Struct);
|
||||
|
||||
std::string old_message = InBuffer; // start 'Reward' as string
|
||||
std::string new_message;
|
||||
ServerToRoF2TextLink(new_message, old_message);
|
||||
|
||||
in->size = sizeof(TaskDescriptionHeader_Struct) + sizeof(TaskDescriptionData1_Struct)+
|
||||
sizeof(TaskDescriptionData2_Struct) + sizeof(TaskDescriptionTrailer_Struct)+
|
||||
title_size + description_size + new_message.length() + 1;
|
||||
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
memcpy(OutBuffer, block_start, (InBuffer - block_start));
|
||||
OutBuffer += (InBuffer - block_start);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
InBuffer += strlen(InBuffer) + 1;
|
||||
|
||||
memcpy(OutBuffer, InBuffer, sizeof(TaskDescriptionTrailer_Struct));
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
|
||||
#if 0 // original code
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_TaskDescription, in->size + 1);
|
||||
// Set the Write pointer as we don't know what has been done with the packet before we get it.
|
||||
in->SetReadPosition(0);
|
||||
@ -3253,6 +3385,7 @@ namespace RoF2
|
||||
|
||||
delete in;
|
||||
dest->FastQueuePacket(&outapp, ack_req);
|
||||
#endif
|
||||
}
|
||||
|
||||
ENCODE(OP_TaskHistoryReply)
|
||||
@ -4292,6 +4425,27 @@ namespace RoF2
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_Emote)
|
||||
{
|
||||
unsigned char *__eq_buffer = __packet->pBuffer;
|
||||
|
||||
std::string old_message = (char *)&__eq_buffer[4]; // unknown01 offset
|
||||
std::string new_message;
|
||||
RoF2ToServerTextLink(new_message, old_message);
|
||||
|
||||
__packet->size = sizeof(Emote_Struct);
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
|
||||
char *InBuffer = (char *)__packet->pBuffer;
|
||||
|
||||
memcpy(InBuffer, __eq_buffer, 4);
|
||||
InBuffer += 4;
|
||||
strcpy(InBuffer, new_message.substr(0, 1023).c_str());
|
||||
InBuffer[1023] = '\0';
|
||||
|
||||
delete[] __eq_buffer;
|
||||
}
|
||||
|
||||
DECODE(OP_EnvDamage)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::EnvDamage2_Struct);
|
||||
@ -5738,64 +5892,64 @@ namespace RoF2
|
||||
|
||||
static inline void ServerToRoF2TextLink(std::string& rof2TextLink, const std::string& serverTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) {
|
||||
if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) {
|
||||
rof2TextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(serverTextLink, delimiter);
|
||||
auto segments = SplitString(serverTextLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
std::string new_segment;
|
||||
if (segments[segment_iter].length() <= EmuConstants::TEXT_LINK_BODY_LENGTH) {
|
||||
rof2TextLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
|
||||
// Idx: 0 1 6 11 16 21 26 31 36 37 41 43 48 (Source)
|
||||
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
|
||||
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
|
||||
// Diff:
|
||||
|
||||
new_segment.append(segments[segment_iter]);
|
||||
|
||||
rof2TextLink.push_back(delimiter);
|
||||
rof2TextLink.append(new_segment.c_str());
|
||||
rof2TextLink.push_back(delimiter);
|
||||
rof2TextLink.push_back('\x12');
|
||||
rof2TextLink.append(segments[segment_iter]);
|
||||
rof2TextLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
rof2TextLink.append(segments[segment_iter].c_str());
|
||||
rof2TextLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void RoF2ToServerTextLink(std::string& serverTextLink, const std::string& rof2TextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rof2TextLink.find(delimiter) == std::string::npos)) {
|
||||
if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rof2TextLink.find('\x12') == std::string::npos)) {
|
||||
serverTextLink = rof2TextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(rof2TextLink, delimiter);
|
||||
auto segments = SplitString(rof2TextLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
std::string new_segment;
|
||||
if (segments[segment_iter].length() <= consts::TEXT_LINK_BODY_LENGTH) {
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
|
||||
// Idx: 0 1 6 11 16 21 26 31 36 37 41 43 48 (Source)
|
||||
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
|
||||
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
|
||||
// Diff:
|
||||
|
||||
new_segment.append(segments[segment_iter]);
|
||||
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.append(new_segment.c_str());
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.push_back('\x12');
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
serverTextLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[segment_iter].c_str());
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,7 +42,9 @@ E(OP_DzExpeditionList)
|
||||
E(OP_DzJoinExpeditionConfirm)
|
||||
E(OP_DzLeaderStatus)
|
||||
E(OP_DzMemberList)
|
||||
E(OP_Emote)
|
||||
E(OP_ExpansionInfo)
|
||||
E(OP_FormattedMessage)
|
||||
E(OP_GMLastName)
|
||||
E(OP_GMTrainSkillConfirm)
|
||||
E(OP_GroundSpawn)
|
||||
@ -133,6 +135,7 @@ D(OP_ConsiderCorpse)
|
||||
D(OP_Consume)
|
||||
D(OP_Damage)
|
||||
D(OP_DeleteItem)
|
||||
D(OP_Emote)
|
||||
D(OP_EnvDamage)
|
||||
D(OP_FaceChange)
|
||||
D(OP_FindPersonRequest)
|
||||
|
||||
@ -31,7 +31,9 @@ E(OP_DzExpeditionList)
|
||||
E(OP_DzJoinExpeditionConfirm)
|
||||
E(OP_DzLeaderStatus)
|
||||
E(OP_DzMemberList)
|
||||
E(OP_Emote)
|
||||
E(OP_ExpansionInfo)
|
||||
E(OP_FormattedMessage)
|
||||
E(OP_GMLastName)
|
||||
E(OP_GMTrainSkillConfirm)
|
||||
E(OP_GroundSpawn)
|
||||
@ -122,6 +124,7 @@ D(OP_ConsiderCorpse)
|
||||
D(OP_Consume)
|
||||
D(OP_Damage)
|
||||
D(OP_DeleteItem)
|
||||
D(OP_Emote)
|
||||
D(OP_EnvDamage)
|
||||
D(OP_FaceChange)
|
||||
D(OP_FindPersonRequest)
|
||||
|
||||
@ -600,6 +600,34 @@ namespace SoD
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_Emote)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
Emote_Struct *emu = (Emote_Struct *)in->pBuffer;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToSoDTextLink(new_message, old_message);
|
||||
|
||||
//if (new_message.length() > 512) // length restricted in packet building function due vari-length name size (no nullterm)
|
||||
// new_message = new_message.substr(0, 512);
|
||||
|
||||
in->size = new_message.length() + 5;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->type);
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_ExpansionInfo)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(ExpansionInfo_Struct);
|
||||
@ -610,6 +638,55 @@ namespace SoD
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_FormattedMessage)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
FormattedMessage_Struct *emu = (FormattedMessage_Struct *)in->pBuffer;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
char *old_message_ptr = (char *)in->pBuffer;
|
||||
old_message_ptr += sizeof(FormattedMessage_Struct);
|
||||
|
||||
std::string old_message_array[9];
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (*old_message_ptr == 0) { break; }
|
||||
old_message_array[i] = old_message_ptr;
|
||||
old_message_ptr += old_message_array[i].length() + 1;
|
||||
}
|
||||
|
||||
uint32 new_message_size = 0;
|
||||
std::string new_message_array[9];
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (old_message_array[i].length() == 0) { break; }
|
||||
ServerToSoDTextLink(new_message_array[i], old_message_array[i]);
|
||||
new_message_size += new_message_array[i].length() + 1;
|
||||
}
|
||||
|
||||
in->size = sizeof(FormattedMessage_Struct) + new_message_size + 1;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->unknown0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->string_id);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->type);
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (new_message_array[i].length() == 0) { break; }
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message_array[i].c_str());
|
||||
}
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0);
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_GroundSpawn)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(Object_Struct);
|
||||
@ -2010,10 +2087,11 @@ namespace SoD
|
||||
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
|
||||
ServerToSoDTextLink(new_message, old_message);
|
||||
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = 25 + strlen(emu->sayer) + new_message.length();
|
||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
@ -2027,9 +2105,18 @@ namespace SoD
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
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());
|
||||
|
||||
@ -2096,6 +2183,49 @@ namespace SoD
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_TaskDescription)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
char *InBuffer = (char *)in->pBuffer;
|
||||
char *block_start = InBuffer;
|
||||
|
||||
InBuffer += sizeof(TaskDescriptionHeader_Struct);
|
||||
uint32 title_size = strlen(InBuffer) + 1;
|
||||
InBuffer += title_size;
|
||||
InBuffer += sizeof(TaskDescriptionData1_Struct);
|
||||
uint32 description_size = strlen(InBuffer) + 1;
|
||||
InBuffer += description_size;
|
||||
InBuffer += sizeof(TaskDescriptionData2_Struct);
|
||||
|
||||
std::string old_message = InBuffer; // start 'Reward' as string
|
||||
std::string new_message;
|
||||
ServerToSoDTextLink(new_message, old_message);
|
||||
|
||||
in->size = sizeof(TaskDescriptionHeader_Struct) + sizeof(TaskDescriptionData1_Struct)+
|
||||
sizeof(TaskDescriptionData2_Struct) + sizeof(TaskDescriptionTrailer_Struct)+
|
||||
title_size + description_size + new_message.length() + 1;
|
||||
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
memcpy(OutBuffer, block_start, (InBuffer - block_start));
|
||||
OutBuffer += (InBuffer - block_start);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
InBuffer += strlen(InBuffer) + 1;
|
||||
|
||||
memcpy(OutBuffer, InBuffer, sizeof(TaskDescriptionTrailer_Struct));
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_Track)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
@ -2917,6 +3047,27 @@ namespace SoD
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_Emote)
|
||||
{
|
||||
unsigned char *__eq_buffer = __packet->pBuffer;
|
||||
|
||||
std::string old_message = (char *)&__eq_buffer[4]; // unknown01 offset
|
||||
std::string new_message;
|
||||
SoDToServerTextLink(new_message, old_message);
|
||||
|
||||
__packet->size = sizeof(Emote_Struct);
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
|
||||
char *InBuffer = (char *)__packet->pBuffer;
|
||||
|
||||
memcpy(InBuffer, __eq_buffer, 4);
|
||||
InBuffer += 4;
|
||||
strcpy(InBuffer, new_message.substr(0, 1023).c_str());
|
||||
InBuffer[1023] = '\0';
|
||||
|
||||
delete[] __eq_buffer;
|
||||
}
|
||||
|
||||
DECODE(OP_FaceChange)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::FaceChange_Struct);
|
||||
@ -3862,76 +4013,76 @@ namespace SoD
|
||||
|
||||
static inline void ServerToSoDTextLink(std::string& sodTextLink, const std::string& serverTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) {
|
||||
if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) {
|
||||
sodTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(serverTextLink, delimiter);
|
||||
auto segments = SplitString(serverTextLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
std::string new_segment;
|
||||
if (segments[segment_iter].length() <= EmuConstants::TEXT_LINK_BODY_LENGTH) {
|
||||
sodTextLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
|
||||
// Idx: 0 1 6 11 16 21 26 31 36 37 41 43 48 (Source)
|
||||
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
|
||||
// SoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (50)
|
||||
// Diff: ^^^^^ ^
|
||||
|
||||
new_segment.append(segments[segment_iter].substr(0, 31).c_str());
|
||||
new_segment.append(segments[segment_iter].substr(36, 5).c_str());
|
||||
sodTextLink.push_back('\x12');
|
||||
sodTextLink.append(segments[segment_iter].substr(0, 31));
|
||||
sodTextLink.append(segments[segment_iter].substr(36, 5));
|
||||
|
||||
if (segments[segment_iter].substr(41, 1) == "0")
|
||||
new_segment.append(segments[segment_iter].substr(42, 1).c_str());
|
||||
if (segments[segment_iter][41] == '0')
|
||||
sodTextLink.push_back(segments[segment_iter][42]);
|
||||
else
|
||||
new_segment.append("F");
|
||||
sodTextLink.push_back('F');
|
||||
|
||||
new_segment.append(segments[segment_iter].substr(43).c_str());
|
||||
|
||||
sodTextLink.push_back(delimiter);
|
||||
sodTextLink.append(new_segment.c_str());
|
||||
sodTextLink.push_back(delimiter);
|
||||
sodTextLink.append(segments[segment_iter].substr(43));
|
||||
sodTextLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
sodTextLink.append(segments[segment_iter].c_str());
|
||||
sodTextLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SoDToServerTextLink(std::string& serverTextLink, const std::string& sodTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sodTextLink.find(delimiter) == std::string::npos)) {
|
||||
if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sodTextLink.find('\x12') == std::string::npos)) {
|
||||
serverTextLink = sodTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(sodTextLink, delimiter);
|
||||
auto segments = SplitString(sodTextLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
std::string new_segment;
|
||||
if (segments[segment_iter].length() <= consts::TEXT_LINK_BODY_LENGTH) {
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
|
||||
// Idx: 0 1 6 11 16 21 26 31 32 36 37 42 (Source)
|
||||
// SoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (50)
|
||||
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
|
||||
// Diff: ^^^^^ ^
|
||||
|
||||
new_segment.append(segments[segment_iter].substr(0, 31).c_str());
|
||||
new_segment.append("00000");
|
||||
new_segment.append(segments[segment_iter].substr(31, 5).c_str());
|
||||
new_segment.append("0");
|
||||
new_segment.append(segments[segment_iter].substr(36).c_str());
|
||||
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.append(new_segment.c_str());
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.push_back('\x12');
|
||||
serverTextLink.append(segments[segment_iter].substr(0, 31));
|
||||
serverTextLink.append("00000");
|
||||
serverTextLink.append(segments[segment_iter].substr(31, 5));
|
||||
serverTextLink.push_back('0');
|
||||
serverTextLink.append(segments[segment_iter].substr(36));
|
||||
serverTextLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[segment_iter].c_str());
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,7 +22,9 @@ E(OP_DzExpeditionList)
|
||||
E(OP_DzJoinExpeditionConfirm)
|
||||
E(OP_DzLeaderStatus)
|
||||
E(OP_DzMemberList)
|
||||
E(OP_Emote)
|
||||
E(OP_ExpansionInfo)
|
||||
E(OP_FormattedMessage)
|
||||
E(OP_GroundSpawn)
|
||||
E(OP_GroupCancelInvite)
|
||||
E(OP_GroupFollow)
|
||||
@ -61,6 +63,7 @@ E(OP_SpawnDoor)
|
||||
E(OP_SpecialMesg)
|
||||
E(OP_Stun)
|
||||
E(OP_TargetBuffs)
|
||||
E(OP_TaskDescription)
|
||||
E(OP_Track)
|
||||
E(OP_Trader)
|
||||
E(OP_TraderBuy)
|
||||
@ -90,6 +93,7 @@ D(OP_Consider)
|
||||
D(OP_ConsiderCorpse)
|
||||
D(OP_Consume)
|
||||
D(OP_DeleteItem)
|
||||
D(OP_Emote)
|
||||
D(OP_FaceChange)
|
||||
D(OP_FindPersonRequest)
|
||||
D(OP_GroupCancelInvite)
|
||||
|
||||
@ -587,6 +587,34 @@ namespace SoF
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_Emote)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
Emote_Struct *emu = (Emote_Struct *)in->pBuffer;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToSoFTextLink(new_message, old_message);
|
||||
|
||||
//if (new_message.length() > 512) // length restricted in packet building function due vari-length name size (no nullterm)
|
||||
// new_message = new_message.substr(0, 512);
|
||||
|
||||
in->size = new_message.length() + 5;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->type);
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_ExpansionInfo)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(ExpansionInfo_Struct);
|
||||
@ -597,6 +625,55 @@ namespace SoF
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_FormattedMessage)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
FormattedMessage_Struct *emu = (FormattedMessage_Struct *)in->pBuffer;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
char *old_message_ptr = (char *)in->pBuffer;
|
||||
old_message_ptr += sizeof(FormattedMessage_Struct);
|
||||
|
||||
std::string old_message_array[9];
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (*old_message_ptr == 0) { break; }
|
||||
old_message_array[i] = old_message_ptr;
|
||||
old_message_ptr += old_message_array[i].length() + 1;
|
||||
}
|
||||
|
||||
uint32 new_message_size = 0;
|
||||
std::string new_message_array[9];
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (old_message_array[i].length() == 0) { break; }
|
||||
ServerToSoFTextLink(new_message_array[i], old_message_array[i]);
|
||||
new_message_size += new_message_array[i].length() + 1;
|
||||
}
|
||||
|
||||
in->size = sizeof(FormattedMessage_Struct) + new_message_size + 1;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->unknown0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->string_id);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->type);
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (new_message_array[i].length() == 0) { break; }
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message_array[i].c_str());
|
||||
}
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0);
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_GroundSpawn)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(Object_Struct);
|
||||
@ -1656,10 +1733,11 @@ namespace SoF
|
||||
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
|
||||
ServerToSoFTextLink(new_message, old_message);
|
||||
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = 25 + strlen(emu->sayer) + new_message.length();
|
||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
@ -1673,9 +1751,18 @@ namespace SoF
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
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());
|
||||
|
||||
@ -1695,6 +1782,49 @@ namespace SoF
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_TaskDescription)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
char *InBuffer = (char *)in->pBuffer;
|
||||
char *block_start = InBuffer;
|
||||
|
||||
InBuffer += sizeof(TaskDescriptionHeader_Struct);
|
||||
uint32 title_size = strlen(InBuffer) + 1;
|
||||
InBuffer += title_size;
|
||||
InBuffer += sizeof(TaskDescriptionData1_Struct);
|
||||
uint32 description_size = strlen(InBuffer) + 1;
|
||||
InBuffer += description_size;
|
||||
InBuffer += sizeof(TaskDescriptionData2_Struct);
|
||||
|
||||
std::string old_message = InBuffer; // start 'Reward' as string
|
||||
std::string new_message;
|
||||
ServerToSoFTextLink(new_message, old_message);
|
||||
|
||||
in->size = sizeof(TaskDescriptionHeader_Struct) + sizeof(TaskDescriptionData1_Struct)+
|
||||
sizeof(TaskDescriptionData2_Struct) + sizeof(TaskDescriptionTrailer_Struct)+
|
||||
title_size + description_size + new_message.length() + 1;
|
||||
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
memcpy(OutBuffer, block_start, (InBuffer - block_start));
|
||||
OutBuffer += (InBuffer - block_start);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
InBuffer += strlen(InBuffer) + 1;
|
||||
|
||||
memcpy(OutBuffer, InBuffer, sizeof(TaskDescriptionTrailer_Struct));
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_Track)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
@ -2317,6 +2447,27 @@ namespace SoF
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_Emote)
|
||||
{
|
||||
unsigned char *__eq_buffer = __packet->pBuffer;
|
||||
|
||||
std::string old_message = (char *)&__eq_buffer[4]; // unknown01 offset
|
||||
std::string new_message;
|
||||
SoFToServerTextLink(new_message, old_message);
|
||||
|
||||
__packet->size = sizeof(Emote_Struct);
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
|
||||
char *InBuffer = (char *)__packet->pBuffer;
|
||||
|
||||
memcpy(InBuffer, __eq_buffer, 4);
|
||||
InBuffer += 4;
|
||||
strcpy(InBuffer, new_message.substr(0, 1023).c_str());
|
||||
InBuffer[1023] = '\0';
|
||||
|
||||
delete[] __eq_buffer;
|
||||
}
|
||||
|
||||
DECODE(OP_FaceChange)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::FaceChange_Struct);
|
||||
@ -3184,76 +3335,76 @@ namespace SoF
|
||||
|
||||
static inline void ServerToSoFTextLink(std::string& sofTextLink, const std::string& serverTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) {
|
||||
if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) {
|
||||
sofTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(serverTextLink, delimiter);
|
||||
auto segments = SplitString(serverTextLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
std::string new_segment;
|
||||
if (segments[segment_iter].length() <= EmuConstants::TEXT_LINK_BODY_LENGTH) {
|
||||
sofTextLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
|
||||
// Idx: 0 1 6 11 16 21 26 31 36 37 41 43 48 (Source)
|
||||
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
|
||||
// SoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (50)
|
||||
// Diff: ^^^^^ ^
|
||||
|
||||
new_segment.append(segments[segment_iter].substr(0, 31).c_str());
|
||||
new_segment.append(segments[segment_iter].substr(36, 5).c_str());
|
||||
sofTextLink.push_back('\x12');
|
||||
sofTextLink.append(segments[segment_iter].substr(0, 31));
|
||||
sofTextLink.append(segments[segment_iter].substr(36, 5));
|
||||
|
||||
if (segments[segment_iter].substr(41, 1) == "0")
|
||||
new_segment.append(segments[segment_iter].substr(42, 1).c_str());
|
||||
if (segments[segment_iter][41] == '0')
|
||||
sofTextLink.push_back(segments[segment_iter][42]);
|
||||
else
|
||||
new_segment.append("F");
|
||||
sofTextLink.push_back('F');
|
||||
|
||||
new_segment.append(segments[segment_iter].substr(43).c_str());
|
||||
|
||||
sofTextLink.push_back(delimiter);
|
||||
sofTextLink.append(new_segment.c_str());
|
||||
sofTextLink.push_back(delimiter);
|
||||
sofTextLink.append(segments[segment_iter].substr(43));
|
||||
sofTextLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
sofTextLink.append(segments[segment_iter].c_str());
|
||||
sofTextLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SoFToServerTextLink(std::string& serverTextLink, const std::string& sofTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sofTextLink.find(delimiter) == std::string::npos)) {
|
||||
if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sofTextLink.find('\x12') == std::string::npos)) {
|
||||
serverTextLink = sofTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(sofTextLink, delimiter);
|
||||
auto segments = SplitString(sofTextLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
std::string new_segment;
|
||||
if (segments[segment_iter].length() <= consts::TEXT_LINK_BODY_LENGTH) {
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
|
||||
// Idx: 0 1 6 11 16 21 26 31 32 36 37 42 (Source)
|
||||
// SoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (50)
|
||||
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
|
||||
// Diff: ^^^^^ ^
|
||||
|
||||
new_segment.append(segments[segment_iter].substr(0, 31).c_str());
|
||||
new_segment.append("00000");
|
||||
new_segment.append(segments[segment_iter].substr(31, 5).c_str());
|
||||
new_segment.append("0");
|
||||
new_segment.append(segments[segment_iter].substr(36).c_str());
|
||||
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.append(new_segment.c_str());
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.push_back('\x12');
|
||||
serverTextLink.append(segments[segment_iter].substr(0, 31));
|
||||
serverTextLink.append("00000");
|
||||
serverTextLink.append(segments[segment_iter].substr(31, 5));
|
||||
serverTextLink.push_back('0');
|
||||
serverTextLink.append(segments[segment_iter].substr(36));
|
||||
serverTextLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[segment_iter].c_str());
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,7 +23,9 @@ E(OP_DzExpeditionList)
|
||||
E(OP_DzJoinExpeditionConfirm)
|
||||
E(OP_DzLeaderStatus)
|
||||
E(OP_DzMemberList)
|
||||
E(OP_Emote)
|
||||
E(OP_ExpansionInfo)
|
||||
E(OP_FormattedMessage)
|
||||
E(OP_GroundSpawn)
|
||||
E(OP_GuildMemberList)
|
||||
E(OP_Illusion)
|
||||
@ -53,6 +55,7 @@ E(OP_SomeItemPacketMaybe)
|
||||
E(OP_SpawnDoor)
|
||||
E(OP_SpecialMesg)
|
||||
E(OP_Stun)
|
||||
E(OP_TaskDescription)
|
||||
E(OP_Track)
|
||||
E(OP_Trader)
|
||||
E(OP_TraderBuy)
|
||||
@ -79,6 +82,7 @@ D(OP_Consider)
|
||||
D(OP_ConsiderCorpse)
|
||||
D(OP_Consume)
|
||||
D(OP_DeleteItem)
|
||||
D(OP_Emote)
|
||||
D(OP_FaceChange)
|
||||
D(OP_FindPersonRequest)
|
||||
D(OP_GroupFollow)
|
||||
|
||||
@ -456,6 +456,83 @@ namespace Titanium
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_Emote)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
Emote_Struct *emu = (Emote_Struct *)in->pBuffer;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToTitaniumTextLink(new_message, old_message);
|
||||
|
||||
//if (new_message.length() > 512) // length restricted in packet building function due vari-length name size (no nullterm)
|
||||
// new_message = new_message.substr(0, 512);
|
||||
|
||||
in->size = new_message.length() + 5;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->type);
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_FormattedMessage)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
FormattedMessage_Struct *emu = (FormattedMessage_Struct *)in->pBuffer;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
char *old_message_ptr = (char *)in->pBuffer;
|
||||
old_message_ptr += sizeof(FormattedMessage_Struct);
|
||||
|
||||
std::string old_message_array[9];
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (*old_message_ptr == 0) { break; }
|
||||
old_message_array[i] = old_message_ptr;
|
||||
old_message_ptr += old_message_array[i].length() + 1;
|
||||
}
|
||||
|
||||
uint32 new_message_size = 0;
|
||||
std::string new_message_array[9];
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (old_message_array[i].length() == 0) { break; }
|
||||
ServerToTitaniumTextLink(new_message_array[i], old_message_array[i]);
|
||||
new_message_size += new_message_array[i].length() + 1;
|
||||
}
|
||||
|
||||
in->size = sizeof(FormattedMessage_Struct) + new_message_size + 1;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->unknown0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->string_id);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->type);
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (new_message_array[i].length() == 0) { break; }
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message_array[i].c_str());
|
||||
}
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0);
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_GuildMemberList)
|
||||
{
|
||||
//consume the packet
|
||||
@ -1118,10 +1195,11 @@ namespace Titanium
|
||||
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
|
||||
ServerToTitaniumTextLink(new_message, old_message);
|
||||
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = 25 + strlen(emu->sayer) + new_message.length();
|
||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
@ -1135,12 +1213,64 @@ namespace Titanium
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
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);
|
||||
}
|
||||
|
||||
ENCODE(OP_TaskDescription)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
char *InBuffer = (char *)in->pBuffer;
|
||||
char *block_start = InBuffer;
|
||||
|
||||
InBuffer += sizeof(TaskDescriptionHeader_Struct);
|
||||
uint32 title_size = strlen(InBuffer) + 1;
|
||||
InBuffer += title_size;
|
||||
InBuffer += sizeof(TaskDescriptionData1_Struct);
|
||||
uint32 description_size = strlen(InBuffer) + 1;
|
||||
InBuffer += description_size;
|
||||
InBuffer += sizeof(TaskDescriptionData2_Struct);
|
||||
|
||||
std::string old_message = InBuffer; // start 'Reward' as string
|
||||
std::string new_message;
|
||||
ServerToTitaniumTextLink(new_message, old_message);
|
||||
|
||||
in->size = sizeof(TaskDescriptionHeader_Struct) + sizeof(TaskDescriptionData1_Struct) +
|
||||
sizeof(TaskDescriptionData2_Struct) + sizeof(TaskDescriptionTrailer_Struct) +
|
||||
title_size + description_size + new_message.length() + 1;
|
||||
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
memcpy(OutBuffer, block_start, (InBuffer - block_start));
|
||||
OutBuffer += (InBuffer - block_start);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
InBuffer += strlen(InBuffer) + 1;
|
||||
|
||||
memcpy(OutBuffer, InBuffer, sizeof(TaskDescriptionTrailer_Struct));
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
@ -1518,6 +1648,27 @@ namespace Titanium
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_Emote)
|
||||
{
|
||||
unsigned char *__eq_buffer = __packet->pBuffer;
|
||||
|
||||
std::string old_message = (char *)&__eq_buffer[4]; // unknown01 offset
|
||||
std::string new_message;
|
||||
TitaniumToServerTextLink(new_message, old_message);
|
||||
|
||||
__packet->size = sizeof(Emote_Struct);
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
|
||||
char *InBuffer = (char *)__packet->pBuffer;
|
||||
|
||||
memcpy(InBuffer, __eq_buffer, 4);
|
||||
InBuffer += 4;
|
||||
strcpy(InBuffer, new_message.substr(0, 1023).c_str());
|
||||
InBuffer[1023] = '\0';
|
||||
|
||||
delete[] __eq_buffer;
|
||||
}
|
||||
|
||||
DECODE(OP_FaceChange)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::FaceChange_Struct);
|
||||
@ -1943,78 +2094,78 @@ namespace Titanium
|
||||
|
||||
static inline void ServerToTitaniumTextLink(std::string& titaniumTextLink, const std::string& serverTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) {
|
||||
if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) {
|
||||
titaniumTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(serverTextLink, delimiter);
|
||||
auto segments = SplitString(serverTextLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
std::string new_segment;
|
||||
if (segments[segment_iter].length() <= EmuConstants::TEXT_LINK_BODY_LENGTH) {
|
||||
titaniumTextLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
|
||||
// Idx: 0 1 6 11 16 21 26 31 36 37 41 43 48 (Source)
|
||||
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
|
||||
// 6.2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXXXXX (45)
|
||||
// Diff: ^^^^^ ^ ^^^^^
|
||||
|
||||
new_segment.append(segments[segment_iter].substr(0, 31).c_str());
|
||||
new_segment.append(segments[segment_iter].substr(36, 5).c_str());
|
||||
titaniumTextLink.push_back('\x12');
|
||||
titaniumTextLink.append(segments[segment_iter].substr(0, 31));
|
||||
titaniumTextLink.append(segments[segment_iter].substr(36, 5));
|
||||
|
||||
if (segments[segment_iter].substr(41, 1) == "0")
|
||||
new_segment.append(segments[segment_iter].substr(42, 1).c_str());
|
||||
if (segments[segment_iter][41] == '0')
|
||||
titaniumTextLink.push_back(segments[segment_iter][42]);
|
||||
else
|
||||
new_segment.append("F");
|
||||
titaniumTextLink.push_back('F');
|
||||
|
||||
new_segment.append(segments[segment_iter].substr(48).c_str());
|
||||
|
||||
titaniumTextLink.push_back(delimiter);
|
||||
titaniumTextLink.append(new_segment.c_str());
|
||||
titaniumTextLink.push_back(delimiter);
|
||||
titaniumTextLink.append(segments[segment_iter].substr(48));
|
||||
titaniumTextLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
titaniumTextLink.append(segments[segment_iter].c_str());
|
||||
titaniumTextLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void TitaniumToServerTextLink(std::string& serverTextLink, const std::string& titaniumTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (titaniumTextLink.find(delimiter) == std::string::npos)) {
|
||||
if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (titaniumTextLink.find('\x12') == std::string::npos)) {
|
||||
serverTextLink = titaniumTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(titaniumTextLink, delimiter);
|
||||
auto segments = SplitString(titaniumTextLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
std::string new_segment;
|
||||
if (segments[segment_iter].length() <= consts::TEXT_LINK_BODY_LENGTH) {
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
|
||||
// Idx: 0 1 6 11 16 21 26 31 32 36 37 (Source)
|
||||
// 6.2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXXXXX (45)
|
||||
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
|
||||
// Diff: ^^^^^ ^ ^^^^^
|
||||
|
||||
new_segment.append(segments[segment_iter].substr(0, 31).c_str());
|
||||
new_segment.append("00000");
|
||||
new_segment.append(segments[segment_iter].substr(31, 5).c_str());
|
||||
new_segment.append("0");
|
||||
new_segment.append(segments[segment_iter].substr(36, 1).c_str());
|
||||
new_segment.append("00000");
|
||||
new_segment.append(segments[segment_iter].substr(37).c_str());
|
||||
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.append(new_segment.c_str());
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.push_back('\x12');
|
||||
serverTextLink.append(segments[segment_iter].substr(0, 31));
|
||||
serverTextLink.append("00000");
|
||||
serverTextLink.append(segments[segment_iter].substr(31, 5));
|
||||
serverTextLink.push_back('0');
|
||||
serverTextLink.push_back(segments[segment_iter][36]);
|
||||
serverTextLink.append("00000");
|
||||
serverTextLink.append(segments[segment_iter].substr(37));
|
||||
serverTextLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[segment_iter].c_str());
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,6 +16,8 @@ E(OP_DzExpeditionList)
|
||||
E(OP_DzJoinExpeditionConfirm)
|
||||
E(OP_DzLeaderStatus)
|
||||
E(OP_DzMemberList)
|
||||
E(OP_Emote)
|
||||
E(OP_FormattedMessage)
|
||||
E(OP_GuildMemberLevelUpdate)
|
||||
E(OP_GuildMemberList)
|
||||
E(OP_Illusion)
|
||||
@ -37,6 +39,7 @@ E(OP_SendCharInfo)
|
||||
E(OP_SendAATable)
|
||||
E(OP_ShopPlayerSell)
|
||||
E(OP_SpecialMesg)
|
||||
E(OP_TaskDescription)
|
||||
E(OP_Track)
|
||||
E(OP_Trader)
|
||||
E(OP_TraderBuy)
|
||||
@ -55,6 +58,7 @@ D(OP_ChannelMessage)
|
||||
D(OP_CharacterCreate)
|
||||
D(OP_Consume)
|
||||
D(OP_DeleteItem)
|
||||
D(OP_Emote)
|
||||
D(OP_FaceChange)
|
||||
D(OP_InspectAnswer)
|
||||
D(OP_InspectRequest)
|
||||
|
||||
@ -744,6 +744,34 @@ namespace Underfoot
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_Emote)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
Emote_Struct *emu = (Emote_Struct *)in->pBuffer;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToUnderfootTextLink(new_message, old_message);
|
||||
|
||||
//if (new_message.length() > 512) // length restricted in packet building function due vari-length name size (no nullterm)
|
||||
// new_message = new_message.substr(0, 512);
|
||||
|
||||
in->size = new_message.length() + 5;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->type);
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_ExpansionInfo)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(ExpansionInfo_Struct);
|
||||
@ -754,6 +782,55 @@ namespace Underfoot
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_FormattedMessage)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
FormattedMessage_Struct *emu = (FormattedMessage_Struct *)in->pBuffer;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
char *old_message_ptr = (char *)in->pBuffer;
|
||||
old_message_ptr += sizeof(FormattedMessage_Struct);
|
||||
|
||||
std::string old_message_array[9];
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (*old_message_ptr == 0) { break; }
|
||||
old_message_array[i] = old_message_ptr;
|
||||
old_message_ptr += old_message_array[i].length() + 1;
|
||||
}
|
||||
|
||||
uint32 new_message_size = 0;
|
||||
std::string new_message_array[9];
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (old_message_array[i].length() == 0) { break; }
|
||||
ServerToUnderfootTextLink(new_message_array[i], old_message_array[i]);
|
||||
new_message_size += new_message_array[i].length() + 1;
|
||||
}
|
||||
|
||||
in->size = sizeof(FormattedMessage_Struct) + new_message_size + 1;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->unknown0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->string_id);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->type);
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (new_message_array[i].length() == 0) { break; }
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message_array[i].c_str());
|
||||
}
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0);
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_GroundSpawn)
|
||||
{
|
||||
// We are not encoding the spawn_id field here, or a size but it doesn't appear to matter.
|
||||
@ -2321,10 +2398,11 @@ namespace Underfoot
|
||||
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
|
||||
ServerToUnderfootTextLink(new_message, old_message);
|
||||
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = 25 + strlen(emu->sayer) + new_message.length();
|
||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
@ -2338,9 +2416,18 @@ namespace Underfoot
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
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());
|
||||
|
||||
@ -2362,6 +2449,49 @@ namespace Underfoot
|
||||
|
||||
ENCODE(OP_TargetBuffs) { ENCODE_FORWARD(OP_BuffCreate); }
|
||||
|
||||
ENCODE(OP_TaskDescription)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
char *InBuffer = (char *)in->pBuffer;
|
||||
char *block_start = InBuffer;
|
||||
|
||||
InBuffer += sizeof(TaskDescriptionHeader_Struct);
|
||||
uint32 title_size = strlen(InBuffer) + 1;
|
||||
InBuffer += title_size;
|
||||
InBuffer += sizeof(TaskDescriptionData1_Struct);
|
||||
uint32 description_size = strlen(InBuffer) + 1;
|
||||
InBuffer += description_size;
|
||||
InBuffer += sizeof(TaskDescriptionData2_Struct);
|
||||
|
||||
std::string old_message = InBuffer; // start 'Reward' as string
|
||||
std::string new_message;
|
||||
ServerToUnderfootTextLink(new_message, old_message);
|
||||
|
||||
in->size = sizeof(TaskDescriptionHeader_Struct) + sizeof(TaskDescriptionData1_Struct)+
|
||||
sizeof(TaskDescriptionData2_Struct) + sizeof(TaskDescriptionTrailer_Struct)+
|
||||
title_size + description_size + new_message.length() + 1;
|
||||
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
memcpy(OutBuffer, block_start, (InBuffer - block_start));
|
||||
OutBuffer += (InBuffer - block_start);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
InBuffer += strlen(InBuffer) + 1;
|
||||
|
||||
memcpy(OutBuffer, InBuffer, sizeof(TaskDescriptionTrailer_Struct));
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_Track)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
@ -3216,6 +3346,27 @@ namespace Underfoot
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_Emote)
|
||||
{
|
||||
unsigned char *__eq_buffer = __packet->pBuffer;
|
||||
|
||||
std::string old_message = (char *)&__eq_buffer[4]; // unknown01 offset
|
||||
std::string new_message;
|
||||
UnderfootToServerTextLink(new_message, old_message);
|
||||
|
||||
__packet->size = sizeof(Emote_Struct);
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
|
||||
char *InBuffer = (char *)__packet->pBuffer;
|
||||
|
||||
memcpy(InBuffer, __eq_buffer, 4);
|
||||
InBuffer += 4;
|
||||
strcpy(InBuffer, new_message.substr(0, 1023).c_str());
|
||||
InBuffer[1023] = '\0';
|
||||
|
||||
delete[] __eq_buffer;
|
||||
}
|
||||
|
||||
DECODE(OP_EnvDamage)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::EnvDamage2_Struct);
|
||||
@ -4165,76 +4316,76 @@ namespace Underfoot
|
||||
|
||||
static inline void ServerToUnderfootTextLink(std::string& underfootTextLink, const std::string& serverTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) {
|
||||
if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) {
|
||||
underfootTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(serverTextLink, delimiter);
|
||||
auto segments = SplitString(serverTextLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
std::string new_segment;
|
||||
if (segments[segment_iter].length() <= EmuConstants::TEXT_LINK_BODY_LENGTH) {
|
||||
underfootTextLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
|
||||
// Idx: 0 1 6 11 16 21 26 31 36 37 41 43 48 (Source)
|
||||
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
|
||||
// SoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (50)
|
||||
// Diff: ^^^^^ ^
|
||||
|
||||
new_segment.append(segments[segment_iter].substr(0, 31).c_str());
|
||||
new_segment.append(segments[segment_iter].substr(36, 5).c_str());
|
||||
underfootTextLink.push_back('\x12');
|
||||
underfootTextLink.append(segments[segment_iter].substr(0, 31));
|
||||
underfootTextLink.append(segments[segment_iter].substr(36, 5));
|
||||
|
||||
if (segments[segment_iter].substr(41, 1) == "0")
|
||||
new_segment.append(segments[segment_iter].substr(42, 1).c_str());
|
||||
if (segments[segment_iter][41] == '0')
|
||||
underfootTextLink.push_back(segments[segment_iter][42]);
|
||||
else
|
||||
new_segment.append("F");
|
||||
underfootTextLink.push_back('F');
|
||||
|
||||
new_segment.append(segments[segment_iter].substr(43).c_str());
|
||||
|
||||
underfootTextLink.push_back(delimiter);
|
||||
underfootTextLink.append(new_segment.c_str());
|
||||
underfootTextLink.push_back(delimiter);
|
||||
underfootTextLink.append(segments[segment_iter].substr(43));
|
||||
underfootTextLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
underfootTextLink.append(segments[segment_iter].c_str());
|
||||
underfootTextLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void UnderfootToServerTextLink(std::string& serverTextLink, const std::string& underfootTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (underfootTextLink.find(delimiter) == std::string::npos)) {
|
||||
if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (underfootTextLink.find('\x12') == std::string::npos)) {
|
||||
serverTextLink = underfootTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(underfootTextLink, delimiter);
|
||||
auto segments = SplitString(underfootTextLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
std::string new_segment;
|
||||
if (segments[segment_iter].length() <= consts::TEXT_LINK_BODY_LENGTH) {
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
|
||||
// Idx: 0 1 6 11 16 21 26 31 32 36 37 42 (Source)
|
||||
// SoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (50)
|
||||
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
|
||||
// Diff: ^^^^^ ^
|
||||
|
||||
new_segment.append(segments[segment_iter].substr(0, 31).c_str());
|
||||
new_segment.append("00000");
|
||||
new_segment.append(segments[segment_iter].substr(31, 5).c_str());
|
||||
new_segment.append("0");
|
||||
new_segment.append(segments[segment_iter].substr(36).c_str());
|
||||
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.append(new_segment.c_str());
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.push_back('\x12');
|
||||
serverTextLink.append(segments[segment_iter].substr(0, 31));
|
||||
serverTextLink.append("00000");
|
||||
serverTextLink.append(segments[segment_iter].substr(31, 5));
|
||||
serverTextLink.push_back('0');
|
||||
serverTextLink.append(segments[segment_iter].substr(36));
|
||||
serverTextLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[segment_iter].c_str());
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,9 @@ E(OP_DzExpeditionList)
|
||||
E(OP_DzJoinExpeditionConfirm)
|
||||
E(OP_DzLeaderStatus)
|
||||
E(OP_DzMemberList)
|
||||
E(OP_Emote)
|
||||
E(OP_ExpansionInfo)
|
||||
E(OP_FormattedMessage)
|
||||
E(OP_GroundSpawn)
|
||||
E(OP_GroupCancelInvite)
|
||||
E(OP_GroupFollow)
|
||||
@ -68,6 +70,7 @@ E(OP_SpawnDoor)
|
||||
E(OP_SpecialMesg)
|
||||
E(OP_Stun)
|
||||
E(OP_TargetBuffs)
|
||||
E(OP_TaskDescription)
|
||||
E(OP_Track)
|
||||
E(OP_Trader)
|
||||
E(OP_TraderBuy)
|
||||
@ -98,6 +101,7 @@ D(OP_ConsiderCorpse)
|
||||
D(OP_Consume)
|
||||
D(OP_Damage)
|
||||
D(OP_DeleteItem)
|
||||
D(OP_Emote)
|
||||
D(OP_EnvDamage)
|
||||
D(OP_FaceChange)
|
||||
D(OP_FindPersonRequest)
|
||||
|
||||
@ -105,9 +105,12 @@ bool SharedDatabase::SaveCursor(uint32 char_id, std::list<ItemInst*>::const_iter
|
||||
|
||||
int i = 8000;
|
||||
for(auto it = start; it != end; ++it, i++) {
|
||||
if (i > 8999) { break; } // shouldn't be anything in the queue that indexes this high
|
||||
ItemInst *inst = *it;
|
||||
if (!SaveInventory(char_id,inst,(i == 8000) ? MainCursor : i))
|
||||
return false;
|
||||
int16 use_slot = (i == 8000) ? MainCursor : i;
|
||||
if (!SaveInventory(char_id, inst, use_slot)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -166,8 +169,9 @@ bool SharedDatabase::SaveInventory(uint32 char_id, const ItemInst* inst, int16 s
|
||||
else
|
||||
return UpdateSharedBankSlot(char_id, inst, slot_id);
|
||||
}
|
||||
else if (!inst) // All other inventory
|
||||
return DeleteInventorySlot(char_id, slot_id);
|
||||
else if (!inst) { // All other inventory
|
||||
return DeleteInventorySlot(char_id, slot_id);
|
||||
}
|
||||
|
||||
return UpdateInventorySlot(char_id, inst, slot_id);
|
||||
}
|
||||
@ -176,11 +180,12 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, i
|
||||
// need to check 'inst' argument for valid pointer
|
||||
|
||||
uint32 augslot[EmuConstants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM };
|
||||
if (inst->IsType(ItemClassCommon))
|
||||
for(int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) {
|
||||
ItemInst *auginst=inst->GetItem(i);
|
||||
augslot[i]=(auginst && auginst->GetItem()) ? auginst->GetItem()->ID : NO_ITEM;
|
||||
if (inst->IsType(ItemClassCommon)) {
|
||||
for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) {
|
||||
ItemInst *auginst = inst->GetItem(i);
|
||||
augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : NO_ITEM;
|
||||
}
|
||||
}
|
||||
|
||||
uint16 charges = 0;
|
||||
if(inst->GetCharges() >= 0)
|
||||
@ -220,11 +225,12 @@ bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst,
|
||||
// need to check 'inst' argument for valid pointer
|
||||
|
||||
uint32 augslot[EmuConstants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM };
|
||||
if (inst->IsType(ItemClassCommon))
|
||||
for(int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) {
|
||||
ItemInst *auginst=inst->GetItem(i);
|
||||
augslot[i]=(auginst && auginst->GetItem()) ? auginst->GetItem()->ID : NO_ITEM;
|
||||
if (inst->IsType(ItemClassCommon)) {
|
||||
for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) {
|
||||
ItemInst *auginst = inst->GetItem(i);
|
||||
augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : NO_ITEM;
|
||||
}
|
||||
}
|
||||
|
||||
// Update/Insert item
|
||||
uint32 account_id = GetAccountIDByChar(char_id);
|
||||
@ -246,11 +252,12 @@ bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst,
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
// Save bag contents, if slot supports bag contents
|
||||
if (inst->IsType(ItemClassContainer) && Inventory::SupportsContainers(slot_id))
|
||||
if (inst->IsType(ItemClassContainer) && Inventory::SupportsContainers(slot_id)) {
|
||||
for (uint8 idx = SUB_BEGIN; idx < EmuConstants::ITEM_CONTAINER_SIZE; idx++) {
|
||||
const ItemInst* baginst = inst->GetItem(idx);
|
||||
SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx));
|
||||
}
|
||||
}
|
||||
|
||||
if (!results.Success()) {
|
||||
return false;
|
||||
@ -422,9 +429,8 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory* inv, bool is_charid) {
|
||||
ItemInst* inst = CreateBaseItem(item, charges);
|
||||
if (inst && item->ItemClass == ItemClassCommon) {
|
||||
for(int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) {
|
||||
if (aug[i]) {
|
||||
inst->PutAugment(this, i, aug[i]);
|
||||
}
|
||||
if (aug[i])
|
||||
inst->PutAugment(this, i, aug[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -562,10 +568,12 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory* inv) {
|
||||
else
|
||||
inst->SetCharges(charges);
|
||||
|
||||
if (item->ItemClass == ItemClassCommon)
|
||||
for(int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++)
|
||||
if (aug[i])
|
||||
inst->PutAugment(this, i, aug[i]);
|
||||
if (item->ItemClass == ItemClassCommon) {
|
||||
for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) {
|
||||
if (aug[i])
|
||||
inst->PutAugment(this, i, aug[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (slot_id >= 8000 && slot_id <= 8999)
|
||||
{
|
||||
@ -676,10 +684,12 @@ bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv)
|
||||
|
||||
inst->SetCharges(charges);
|
||||
|
||||
if (item->ItemClass == ItemClassCommon)
|
||||
for(int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++)
|
||||
if (aug[i])
|
||||
inst->PutAugment(this, i, aug[i]);
|
||||
if (item->ItemClass == ItemClassCommon) {
|
||||
for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) {
|
||||
if (aug[i])
|
||||
inst->PutAugment(this, i, aug[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (slot_id>=8000 && slot_id <= 8999)
|
||||
put_slot_id = inv->PushCursor(*inst);
|
||||
@ -1950,7 +1960,7 @@ void SharedDatabase::LoadCharacterInspectMessage(uint32 character_id, InspectMes
|
||||
std::string query = StringFormat("SELECT `inspect_message` FROM `character_inspect_messages` WHERE `id` = %u LIMIT 1", character_id);
|
||||
auto results = QueryDatabase(query);
|
||||
auto row = results.begin();
|
||||
memcpy(message, "", sizeof(InspectMessage_Struct));
|
||||
memset(message, '\0', sizeof(InspectMessage_Struct));
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
memcpy(message, row[0], sizeof(InspectMessage_Struct));
|
||||
}
|
||||
|
||||
@ -126,7 +126,7 @@ OP_GuildLeader=0x7e09
|
||||
OP_GuildDelete=0x3708
|
||||
OP_GuildInviteAccept=0x7053
|
||||
OP_GuildDemote=0x2d4e
|
||||
OP_GuildPromote=0x0000
|
||||
OP_GuildPromote=0x6a98
|
||||
OP_GuildPublicNote=0x5053
|
||||
OP_GuildManageBanker=0x748f
|
||||
OP_GuildBank=0x5134
|
||||
|
||||
@ -240,17 +240,17 @@ sub Exit{ }
|
||||
#::: Returns Tab Delimited MySQL Result from Command Line
|
||||
sub GetMySQLResult{
|
||||
my $run_query = $_[0];
|
||||
if($OS eq "Windows"){ return `"$path" --user $user --password="$pass" $db -N -B -e "$run_query"`; }
|
||||
if($OS eq "Windows"){ return `"$path" --host $host --user $user --password="$pass" $db -N -B -e "$run_query"`; }
|
||||
if($OS eq "Linux"){
|
||||
$run_query =~s/`//g;
|
||||
return `$path --user="$user" --password="$pass" $db -N -B -e "$run_query"`;
|
||||
return `$path --user="$user" --host $host --password="$pass" $db -N -B -e "$run_query"`;
|
||||
}
|
||||
}
|
||||
|
||||
sub GetMySQLResultFromFile{
|
||||
my $update_file = $_[0];
|
||||
if($OS eq "Windows"){ return `"$path" --user $user --password="$pass" --force $db < $update_file`; }
|
||||
if($OS eq "Linux"){ return `"$path" --user $user --password="$pass" --force $db < $update_file`; }
|
||||
if($OS eq "Windows"){ return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`; }
|
||||
if($OS eq "Linux"){ return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`; }
|
||||
}
|
||||
|
||||
#::: Gets Remote File based on URL (1st Arg), and saves to destination file (2nd Arg)
|
||||
|
||||
@ -194,7 +194,7 @@ CREATE TABLE `botguildmembers` (
|
||||
PRIMARY KEY (`char_id`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
DELIMITER //
|
||||
DELIMITER $$
|
||||
|
||||
CREATE FUNCTION `GetMobType` (mobname VARCHAR(64)) RETURNS CHAR(1)
|
||||
BEGIN
|
||||
@ -209,7 +209,7 @@ BEGIN
|
||||
END IF;
|
||||
|
||||
RETURN Result;
|
||||
END//
|
||||
END$$
|
||||
|
||||
DELIMITER ;
|
||||
|
||||
|
||||
@ -194,7 +194,7 @@ CREATE TABLE `botguildmembers` (
|
||||
PRIMARY KEY (`char_id`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
DELIMITER \\
|
||||
DELIMITER $$
|
||||
|
||||
CREATE FUNCTION `GetMobType` (mobname VARCHAR(64)) RETURNS CHAR(1)
|
||||
BEGIN
|
||||
@ -209,7 +209,7 @@ BEGIN
|
||||
END IF;
|
||||
|
||||
RETURN Result;
|
||||
END\\
|
||||
END$$
|
||||
|
||||
DELIMITER ;
|
||||
|
||||
|
||||
@ -109,6 +109,7 @@ SET(zone_sources
|
||||
trading.cpp
|
||||
trap.cpp
|
||||
tribute.cpp
|
||||
tune.cpp
|
||||
water_map.cpp
|
||||
water_map_v1.cpp
|
||||
water_map_v2.cpp
|
||||
|
||||
@ -2802,8 +2802,8 @@ void Client::Message_StringID(uint32 type, uint32 string_id, const char* message
|
||||
if (GetFilter(FilterDamageShields) == FilterHide && type == MT_DS)
|
||||
return;
|
||||
|
||||
int i, argcount, length;
|
||||
char *bufptr;
|
||||
int i = 0, argcount = 0, length = 0;
|
||||
char *bufptr = nullptr;
|
||||
const char *message_arg[9] = {0};
|
||||
|
||||
if(type==MT_Emote)
|
||||
@ -2815,7 +2815,6 @@ void Client::Message_StringID(uint32 type, uint32 string_id, const char* message
|
||||
return;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
message_arg[i++] = message1;
|
||||
message_arg[i++] = message2;
|
||||
message_arg[i++] = message3;
|
||||
@ -2826,10 +2825,12 @@ void Client::Message_StringID(uint32 type, uint32 string_id, const char* message
|
||||
message_arg[i++] = message8;
|
||||
message_arg[i++] = message9;
|
||||
|
||||
for(argcount = length = 0; message_arg[argcount]; argcount++)
|
||||
for(; message_arg[argcount]; ++argcount)
|
||||
length += strlen(message_arg[argcount]) + 1;
|
||||
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_FormattedMessage, length+13);
|
||||
length += 1;
|
||||
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_FormattedMessage, sizeof(FormattedMessage_Struct) + length);
|
||||
FormattedMessage_Struct *fm = (FormattedMessage_Struct *)outapp->pBuffer;
|
||||
fm->string_id = string_id;
|
||||
fm->type = type;
|
||||
@ -2840,6 +2841,8 @@ void Client::Message_StringID(uint32 type, uint32 string_id, const char* message
|
||||
bufptr += strlen(message_arg[i]) + 1;
|
||||
}
|
||||
|
||||
// since we're moving the pointer the 0 offset is correct
|
||||
bufptr[0] = '\0';
|
||||
|
||||
if(distance>0)
|
||||
entity_list.QueueCloseClients(this,outapp,false,distance);
|
||||
@ -2914,8 +2917,8 @@ void Client::FilteredMessage_StringID(Mob *sender, uint32 type, eqFilterType fil
|
||||
if (!FilteredMessageCheck(sender, filter))
|
||||
return;
|
||||
|
||||
int i, argcount, length;
|
||||
char *bufptr;
|
||||
int i = 0, argcount = 0, length = 0;
|
||||
char *bufptr = nullptr;
|
||||
const char *message_arg[9] = {0};
|
||||
|
||||
if (type == MT_Emote)
|
||||
@ -2926,7 +2929,6 @@ void Client::FilteredMessage_StringID(Mob *sender, uint32 type, eqFilterType fil
|
||||
return;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
message_arg[i++] = message1;
|
||||
message_arg[i++] = message2;
|
||||
message_arg[i++] = message3;
|
||||
@ -2937,10 +2939,12 @@ void Client::FilteredMessage_StringID(Mob *sender, uint32 type, eqFilterType fil
|
||||
message_arg[i++] = message8;
|
||||
message_arg[i++] = message9;
|
||||
|
||||
for (argcount = length = 0; message_arg[argcount]; argcount++)
|
||||
for (; message_arg[argcount]; ++argcount)
|
||||
length += strlen(message_arg[argcount]) + 1;
|
||||
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_FormattedMessage, length+13);
|
||||
length += 1;
|
||||
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_FormattedMessage, sizeof(FormattedMessage_Struct) + length);
|
||||
FormattedMessage_Struct *fm = (FormattedMessage_Struct *)outapp->pBuffer;
|
||||
fm->string_id = string_id;
|
||||
fm->type = type;
|
||||
@ -2950,6 +2954,9 @@ void Client::FilteredMessage_StringID(Mob *sender, uint32 type, eqFilterType fil
|
||||
bufptr += strlen(message_arg[i]) + 1;
|
||||
}
|
||||
|
||||
// since we're moving the pointer the 0 offset is correct
|
||||
bufptr[0] = '\0';
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
@ -1247,6 +1247,10 @@ public:
|
||||
|
||||
bool InterrogateInventory(Client* requester, bool log, bool silent, bool allowtrip, bool& error, bool autolog = true);
|
||||
|
||||
//Command #Tune functions
|
||||
virtual int32 Tune_GetMeleeMitDmg(Mob* GM, Mob *attacker, int32 damage, int32 minhit, float mit_rating, float atk_rating);
|
||||
int32 GetMeleeDamage(Mob* other, bool GetMinDamage = false);
|
||||
|
||||
protected:
|
||||
friend class Mob;
|
||||
void CalcItemBonuses(StatBonuses* newbon);
|
||||
|
||||
@ -1838,12 +1838,11 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
if (loaditems) { /* Dont load if a length error occurs */
|
||||
BulkSendInventoryItems();
|
||||
/* Send stuff on the cursor which isnt sent in bulk */
|
||||
iter_queue it;
|
||||
for (it = m_inv.cursor_begin(); it != m_inv.cursor_end(); ++it) {
|
||||
for (auto iter = m_inv.cursor_begin(); iter != m_inv.cursor_end(); ++iter) {
|
||||
/* First item cursor is sent in bulk inventory packet */
|
||||
if (it == m_inv.cursor_begin())
|
||||
if (iter == m_inv.cursor_begin())
|
||||
continue;
|
||||
const ItemInst *inst = *it;
|
||||
const ItemInst *inst = *iter;
|
||||
SendItemPacket(MainCursor, inst, ItemPacketSummonItem);
|
||||
}
|
||||
}
|
||||
@ -5462,13 +5461,13 @@ void Client::Handle_OP_Emote(const EQApplicationPacket *app)
|
||||
in->message[512] = '\0';
|
||||
len_msg = 512;
|
||||
}
|
||||
uint32 len_packet = sizeof(in->unknown01) + len_name
|
||||
uint32 len_packet = sizeof(in->type) + len_name
|
||||
+ len_msg + 1;
|
||||
|
||||
// Construct outgoing packet
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_Emote, len_packet);
|
||||
Emote_Struct* out = (Emote_Struct*)outapp->pBuffer;
|
||||
out->unknown01 = in->unknown01;
|
||||
out->type = in->type;
|
||||
memcpy(out->message, name, len_name);
|
||||
memcpy(&out->message[len_name], in->message, len_msg);
|
||||
|
||||
@ -7477,7 +7476,7 @@ void Client::Handle_OP_GuildInviteAccept(const EQApplicationPacket *app)
|
||||
|
||||
uint32 guildrank = gj->response;
|
||||
|
||||
if (GetClientVersion() == EQClientRoF)
|
||||
if (GetClientVersion() >= EQClientRoF)
|
||||
{
|
||||
if (gj->response == 8)
|
||||
{
|
||||
@ -7652,7 +7651,10 @@ void Client::Handle_OP_GuildPromote(const EQApplicationPacket *app)
|
||||
uint8 rank = gci.rank + 1;
|
||||
|
||||
if (rank > GUILD_OFFICER)
|
||||
{
|
||||
Message(0, "You cannot promote someone to be guild leader. You must use /guildleader.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Log.Out(Logs::Detail, Logs::Guilds, "Promoting %s (%d) from rank %s (%d) to %s (%d) in %s (%d)",
|
||||
|
||||
216
zone/command.cpp
216
zone/command.cpp
@ -425,7 +425,7 @@ int command_init(void) {
|
||||
command_add("open_shop", nullptr, 100, command_merchantopenshop) ||
|
||||
command_add("merchant_close_shop", "Closes a merchant shop", 100, command_merchantcloseshop) ||
|
||||
command_add("close_shop", nullptr, 100, command_merchantcloseshop) ||
|
||||
command_add("shownumhits", "Shows buffs numhits for yourself.", 0, command_shownumhits) ||
|
||||
command_add("tune", "Calculate ideal statical values related to combat.", 100, command_tune)
|
||||
command_add("crashtest", "- Crash the zoneserver", 255, command_crashtest) ||
|
||||
command_add("logtest", "Performs log performance testing.", 250, command_logtest) ||
|
||||
command_add("logs", "Manage anything to do with logs", 250, command_logs)
|
||||
@ -2628,7 +2628,7 @@ void command_peekinv(Client *c, const Seperator *sep)
|
||||
}
|
||||
else {
|
||||
int cursorDepth = 0;
|
||||
for (iter_queue it = targetClient->GetInv().cursor_begin(); (it != targetClient->GetInv().cursor_end()); ++it, ++cursorDepth) {
|
||||
for (auto it = targetClient->GetInv().cursor_begin(); (it != targetClient->GetInv().cursor_end()); ++it, ++cursorDepth) {
|
||||
inst_main = *it;
|
||||
item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem();
|
||||
linker.SetItemInst(inst_main);
|
||||
@ -6599,7 +6599,7 @@ void command_npcedit(Client *c, const Seperator *sep)
|
||||
"SET luclin_haircolor = %i, luclin_beardcolor = %i, "
|
||||
"luclin_hairstyle = %i, luclin_beard = %i, "
|
||||
"face = %i, drakkin_heritage = %i, "
|
||||
"drakkin_tattoo = %i, drakkin_details = %i, "
|
||||
"drakkin_tattoo = %i, drakkin_details = %i "
|
||||
"WHERE id = %i",
|
||||
target->GetHairColor(), target->GetBeardColor(),
|
||||
target->GetHairStyle(), target->GetBeard(),
|
||||
@ -10001,7 +10001,6 @@ void command_camerashake(Client *c, const Seperator *sep)
|
||||
if(sep->arg[1][0] && sep->arg[2][0])
|
||||
{
|
||||
ServerPacket *pack = new ServerPacket(ServerOP_CameraShake, sizeof(ServerCameraShake_Struct));
|
||||
memset(pack->pBuffer, 0, sizeof(pack->pBuffer));
|
||||
ServerCameraShake_Struct* scss = (ServerCameraShake_Struct*) pack->pBuffer;
|
||||
scss->duration = atoi(sep->arg[1]);
|
||||
scss->intensity = atoi(sep->arg[2]);
|
||||
@ -10389,6 +10388,215 @@ void command_shownumhits(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
void command_tune(Client *c, const Seperator *sep)
|
||||
{
|
||||
//Work in progress - Kayen
|
||||
|
||||
if(sep->arg[1][0] == '\0' || !strcasecmp(sep->arg[1], "help")) {
|
||||
c->Message(0, "Syntax: #tune [subcommand].");
|
||||
c->Message(0, "-- Tune System Commands --");
|
||||
c->Message(0, "-- Usage: Returning recommended combat statistical values based on a desired outcome.");
|
||||
c->Message(0, "-- Note: If targeted mob does not have a target (ie not engaged in combat), YOU will be considered the target.");
|
||||
c->Message(0, "-- Warning: The calculations done in this process are intense and can potentially cause zone crashes depending on parameters set, use with caution!");
|
||||
c->Message(0, "-- Below are OPTIONAL parameters.");
|
||||
c->Message(0, "-- Note: [interval] Determines how fast the stat being checked increases/decreases till it finds the best result. Default [ATK/AC 50][Acc/Avoid 10] ");
|
||||
c->Message(0, "-- Note: [loop_max] Determines how many iterations are done to increases/decreases the stat till it finds the best result. Default [ATK/AC 100][Acc/Avoid 1000]");
|
||||
c->Message(0, "-- Note: [Stat Override] Will override that stat on mob being checkd with the specified value. Default=0");
|
||||
c->Message(0, "-- Note: [Info Level] How much statistical detail is displayed[0 - 3]. Default=0 ");
|
||||
c->Message(0, "-- Note: Results are only approximations usually accurate to +/- 2 intervals.");
|
||||
|
||||
c->Message(0, "... ");
|
||||
c->Message(0, "...### Category A ### Target = ATTACKER ### YOU or Target's Target = DEFENDER ###");
|
||||
c->Message(0, "...### Category B ### Target = DEFENDER ### YOU or Target's Target = ATTACKER ###");
|
||||
c->Message(0, "... ");
|
||||
c->Message(0, "...#Returns recommended ATK adjustment +/- on ATTACKER that will result in an average mitigation pct on DEFENDER. ");
|
||||
c->Message(0, "...tune FindATK [A/B] [pct mitigation] [interval][loop_max][AC Overwride][Info Level]");
|
||||
c->Message(0, "... ");
|
||||
c->Message(0, "...#Returns recommended AC adjustment +/- on DEFENDER for an average mitigation pct from ATTACKER. ");
|
||||
c->Message(0, "...tune FindAC [A/B] [pct mitigation] [interval][loop_max][ATK Overwride][Info Level] ");
|
||||
c->Message(0, "... ");
|
||||
c->Message(0, "...#Returns recommended Accuracy adjustment +/- on ATTACKER that will result in a hit chance pct on DEFENDER. ");
|
||||
c->Message(0, "...tune FindAccuracy [A/B] [hit chance] [interval][loop_max][Avoidance Overwride][Info Level]");
|
||||
c->Message(0, "... ");
|
||||
c->Message(0, "...#Returns recommended Avoidance adjustment +/- on DEFENDER for in a hit chance pct from ATTACKER. ");
|
||||
c->Message(0, "...tune FindAvoidance [A/B] [pct mitigation] [interval][loop_max][Accuracy Overwride][Info Level] ");
|
||||
|
||||
return;
|
||||
}
|
||||
//Default is category A for attacker/defender settings, which then are swapped under category B.
|
||||
Mob* defender = c;
|
||||
Mob* attacker = c->GetTarget();
|
||||
|
||||
if (!attacker)
|
||||
{
|
||||
c->Message(0, "#Tune - Error no target selected. [#Tune help]");
|
||||
return;
|
||||
}
|
||||
|
||||
Mob* ttarget = attacker->GetTarget();
|
||||
|
||||
if (ttarget)
|
||||
defender = ttarget;
|
||||
|
||||
if(!strcasecmp(sep->arg[1], "FindATK"))
|
||||
{
|
||||
float pct_mitigation = atof(sep->arg[3]);
|
||||
int interval = atoi(sep->arg[4]);
|
||||
int max_loop = atoi(sep->arg[5]);
|
||||
int ac_override = atoi(sep->arg[6]);
|
||||
int info_level = atoi(sep->arg[7]);
|
||||
|
||||
if (!pct_mitigation)
|
||||
{
|
||||
c->Message(13, "#Tune - Error must enter the desired percent mitigation on defender. Ie. Defender to mitigate on average 20 pct of max damage.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!interval)
|
||||
interval = 50;
|
||||
if (!max_loop)
|
||||
max_loop = 100;
|
||||
if(!ac_override)
|
||||
ac_override = 0;
|
||||
if (!info_level)
|
||||
info_level = 1;
|
||||
|
||||
if(!strcasecmp(sep->arg[2], "A"))
|
||||
c->Tune_FindATKByPctMitigation(defender, attacker, pct_mitigation, interval, max_loop,ac_override,info_level);
|
||||
else if(!strcasecmp(sep->arg[2], "B"))
|
||||
c->Tune_FindATKByPctMitigation(attacker,defender, pct_mitigation, interval, max_loop,ac_override,info_level);
|
||||
else {
|
||||
c->Message(0, "#Tune - Error no category selcted. [#Tune help]");
|
||||
c->Message(0, "Usage #tune FindATK [A/B] [pct mitigation] [interval][loop_max][AC Overwride][Info Level] ");
|
||||
c->Message(0, "Example #tune FindATK A 60");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(!strcasecmp(sep->arg[1], "FindAC"))
|
||||
{
|
||||
float pct_mitigation = atof(sep->arg[3]);
|
||||
int interval = atoi(sep->arg[4]);
|
||||
int max_loop = atoi(sep->arg[5]);
|
||||
int atk_override = atoi(sep->arg[6]);
|
||||
int info_level = atoi(sep->arg[7]);
|
||||
|
||||
if (!pct_mitigation)
|
||||
{
|
||||
c->Message(13, "#Tune - Error must enter the desired percent mitigation on defender. Ie. Defender to mitigate on average 20 pct of max damage.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!interval)
|
||||
interval = 50;
|
||||
if (!max_loop)
|
||||
max_loop = 100;
|
||||
if(!atk_override)
|
||||
atk_override = 0;
|
||||
if (!info_level)
|
||||
info_level = 1;
|
||||
|
||||
if(!strcasecmp(sep->arg[2], "A"))
|
||||
c->Tune_FindACByPctMitigation(defender, attacker, pct_mitigation, interval, max_loop,atk_override,info_level);
|
||||
else if(!strcasecmp(sep->arg[2], "B"))
|
||||
c->Tune_FindACByPctMitigation(attacker, defender, pct_mitigation, interval, max_loop,atk_override,info_level);
|
||||
else {
|
||||
c->Message(0, "#Tune - Error no category selcted. [#Tune help]");
|
||||
c->Message(0, "Usage #tune FindAC [A/B] [pct mitigation] [interval][loop_max][ATK Overwride][Info Level] ");
|
||||
c->Message(0, "Example #tune FindAC A 60");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(!strcasecmp(sep->arg[1], "FindAccuracy"))
|
||||
{
|
||||
float hit_chance = atof(sep->arg[3]);
|
||||
int interval = atoi(sep->arg[4]);
|
||||
int max_loop = atoi(sep->arg[5]);
|
||||
int avoid_override = atoi(sep->arg[6]);
|
||||
int info_level = atoi(sep->arg[7]);
|
||||
|
||||
if (!hit_chance)
|
||||
{
|
||||
c->Message(10, "#Tune - Error must enter the desired percent mitigation on defender. Ie. Defender to mitigate on average 20 pct of max damage.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!interval)
|
||||
interval = 10;
|
||||
if (!max_loop)
|
||||
max_loop = 1000;
|
||||
if(!avoid_override)
|
||||
avoid_override = 0;
|
||||
if (!info_level)
|
||||
info_level = 1;
|
||||
|
||||
if (hit_chance > RuleR(Combat,MaxChancetoHit) || hit_chance < RuleR(Combat,MinChancetoHit))
|
||||
{
|
||||
c->Message(10, "#Tune - Error hit chance out of bounds. [Max %.2f Min .2f]", RuleR(Combat,MaxChancetoHit),RuleR(Combat,MinChancetoHit));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!strcasecmp(sep->arg[2], "A"))
|
||||
c->Tune_FindAccuaryByHitChance(defender, attacker, hit_chance, interval, max_loop,avoid_override,info_level);
|
||||
else if(!strcasecmp(sep->arg[2], "B"))
|
||||
c->Tune_FindAccuaryByHitChance(attacker, defender, hit_chance, interval, max_loop,avoid_override,info_level);
|
||||
else {
|
||||
c->Message(0, "#Tune - Error no category selcted. [#Tune help]");
|
||||
c->Message(0, "Usage #tune FindAcccuracy [A/B] [hit chance] [interval][loop_max][Avoidance Overwride][Info Level]");
|
||||
c->Message(0, "Exampled #tune FindAccuracy B 30");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(!strcasecmp(sep->arg[1], "FindAvoidance"))
|
||||
{
|
||||
float hit_chance = atof(sep->arg[3]);
|
||||
int interval = atoi(sep->arg[4]);
|
||||
int max_loop = atoi(sep->arg[5]);
|
||||
int acc_override = atoi(sep->arg[6]);
|
||||
int info_level = atoi(sep->arg[7]);
|
||||
|
||||
if (!hit_chance)
|
||||
{
|
||||
c->Message(0, "#Tune - Error must enter the desired hit chance on defender. Ie. Defender to have hit chance of 40 pct.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!interval)
|
||||
interval = 10;
|
||||
if (!max_loop)
|
||||
max_loop = 1000;
|
||||
if(!acc_override)
|
||||
acc_override = 0;
|
||||
if (!info_level)
|
||||
info_level = 1;
|
||||
|
||||
if (hit_chance > RuleR(Combat,MaxChancetoHit) || hit_chance < RuleR(Combat,MinChancetoHit))
|
||||
{
|
||||
c->Message(10, "#Tune - Error hit chance out of bounds. [Max %.2f Min .2f]", RuleR(Combat,MaxChancetoHit),RuleR(Combat,MinChancetoHit));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!strcasecmp(sep->arg[2], "A"))
|
||||
c->Tune_FindAvoidanceByHitChance(defender, attacker, hit_chance, interval, max_loop,acc_override, info_level);
|
||||
else if(!strcasecmp(sep->arg[2], "B"))
|
||||
c->Tune_FindAvoidanceByHitChance(attacker, defender, hit_chance, interval, max_loop,acc_override, info_level);
|
||||
else {
|
||||
c->Message(0, "#Tune - Error no category selcted. [#Tune help]");
|
||||
c->Message(0, "Usage #tune FindAvoidance [A/B] [hit chance] [interval][loop_max][Accuracy Overwride][Info Level]");
|
||||
c->Message(0, "Exampled #tune FindAvoidance B 30");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void command_logtest(Client *c, const Seperator *sep){
|
||||
clock_t t = std::clock(); /* Function timer start */
|
||||
if (sep->IsNumber(1)){
|
||||
|
||||
@ -322,6 +322,7 @@ void command_npctype_cache(Client *c, const Seperator *sep);
|
||||
void command_merchantopenshop(Client *c, const Seperator *sep);
|
||||
void command_merchantcloseshop(Client *c, const Seperator *sep);
|
||||
void command_shownumhits(Client *c, const Seperator *sep);
|
||||
void command_tune(Client *c, const Seperator *sep);
|
||||
void command_logtest(Client *c, const Seperator *sep);
|
||||
void command_logs(Client *c, const Seperator *sep);
|
||||
|
||||
|
||||
@ -364,9 +364,10 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
|
||||
// solar: TODO soulbound items need not be added to corpse, but they need
|
||||
// to go into the regular slots on the player, out of bags
|
||||
|
||||
// worn + inventory + cursor
|
||||
// possessions
|
||||
// TODO: accomodate soul-bound items
|
||||
std::list<uint32> removed_list;
|
||||
bool cursor = false;
|
||||
//bool cursor = false;
|
||||
for(i = MAIN_BEGIN; i < EmuConstants::MAP_POSSESSIONS_SIZE; i++) {
|
||||
if(i == MainAmmo && client->GetClientVersion() >= EQClientSoF) {
|
||||
item = client->GetInv().GetItem(MainPowerSource);
|
||||
@ -384,14 +385,18 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// This will either be re-enabled or deleted at some point. The client doesn't appear
|
||||
// to like to have items deleted from it's buffer..or, I just haven't figure out how -U
|
||||
// (Besides, the 'corpse' slots equal the size of MapPossessions..not MapPossessions + MapCorpse)
|
||||
|
||||
// cursor queue // (change to first client that supports 'death hover' mode, if not SoF.)
|
||||
if (!RuleB(Character, RespawnFromHover) || client->GetClientVersion() < EQClientSoF) {
|
||||
|
||||
// bumped starting assignment to 8001 because any in-memory 'slot 8000' item was moved above as 'slot 30'
|
||||
// this was mainly for client profile state reflection..should match db player inventory entries now.
|
||||
|
||||
iter_queue it;
|
||||
for (it = client->GetInv().cursor_begin(), i = 8001; it != client->GetInv().cursor_end(); ++it, i++) {
|
||||
i = 8001;
|
||||
for (auto it = client->GetInv().cursor_begin(); it != client->GetInv().cursor_end(); ++it, i++) {
|
||||
item = *it;
|
||||
if ((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent)) {
|
||||
std::list<uint32> slot_list = MoveItemToCorpse(client, item, i);
|
||||
@ -400,6 +405,7 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
database.TransactionBegin();
|
||||
if (removed_list.size() != 0) {
|
||||
@ -422,6 +428,7 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
|
||||
database.QueryDatabase(ss.str().c_str());
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (cursor) { // all cursor items should be on corpse (client < SoF or RespawnFromHover = false)
|
||||
while (!client->GetInv().CursorEmpty())
|
||||
client->DeleteItemInInventory(MainCursor, 0, false, false);
|
||||
@ -431,8 +438,13 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
|
||||
std::list<ItemInst*>::const_iterator finish = client->GetInv().cursor_end();
|
||||
database.SaveCursor(client->CharacterID(), start, finish);
|
||||
}
|
||||
#endif
|
||||
|
||||
client->CalcBonuses(); // will only affect offline profile viewing of dead characters..unneeded overhead
|
||||
auto start = client->GetInv().cursor_begin();
|
||||
auto finish = client->GetInv().cursor_end();
|
||||
database.SaveCursor(client->CharacterID(), start, finish);
|
||||
|
||||
client->CalcBonuses();
|
||||
client->Save();
|
||||
|
||||
IsRezzed(false);
|
||||
|
||||
@ -4621,3 +4621,10 @@ Mob *EntityList::GetTargetForVirus(Mob *spreader, int range)
|
||||
return TargetsInRange[zone->random.Int(0, TargetsInRange.size() - 1)];
|
||||
}
|
||||
|
||||
void EntityList::StopMobAI()
|
||||
{
|
||||
for (auto &mob : mob_list) {
|
||||
mob.second->AI_Stop();
|
||||
mob.second->AI_ShutDown();
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,6 +268,8 @@ public:
|
||||
Entity *GetEntityMob(const char *name);
|
||||
Entity *GetEntityCorpse(const char *name);
|
||||
|
||||
void StopMobAI();
|
||||
|
||||
void DescribeAggro(Client *towho, NPC *from_who, float dist, bool verbose);
|
||||
|
||||
void Message(uint32 to_guilddbid, uint32 type, const char* message, ...);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
5170
zone/maxskill.h
5170
zone/maxskill.h
File diff suppressed because it is too large
Load Diff
10
zone/mob.h
10
zone/mob.h
@ -924,6 +924,16 @@ public:
|
||||
void mod_spell_cast(uint16 spell_id, Mob* spelltar, bool reflect, bool use_resist_adjust, int16 resist_adjust, bool isproc);
|
||||
bool mod_will_aggro(Mob *attacker, Mob *on);
|
||||
|
||||
//Command #Tune functions
|
||||
int32 Tune_MeleeMitigation(Mob* GM, Mob *attacker, int32 damage, int32 minhit, ExtraAttackOptions *opts = nullptr, int Msg =0, int ac_override=0, int atk_override=0, int add_ac=0, int add_atk = 0);
|
||||
virtual int32 Tune_GetMeleeMitDmg(Mob* GM, Mob *attacker, int32 damage, int32 minhit, float mit_rating, float atk_rating);
|
||||
uint32 Tune_GetMeanDamage(Mob* GM, Mob *attacker, int32 damage, int32 minhit, ExtraAttackOptions *opts = nullptr, int Msg = 0,int ac_override=0, int atk_override=0, int add_ac=0, int add_atk = 0);
|
||||
void Tune_FindATKByPctMitigation(Mob* defender, Mob *attacker, float pct_mitigation, int interval = 50, int max_loop = 100, int ac_override=0,int Msg =0);
|
||||
void Tune_FindACByPctMitigation(Mob* defender, Mob *attacker, float pct_mitigation, int interval = 50, int max_loop = 100, int atk_override=0,int Msg =0);
|
||||
float Tune_CheckHitChance(Mob* defender, Mob* attacker, SkillUseTypes skillinuse, int Hand, int16 chance_mod, int Msg = 1,int acc_override=0, int avoid_override=0, int add_acc=0, int add_avoid = 0);
|
||||
void Tune_FindAccuaryByHitChance(Mob* defender, Mob *attacker, float hit_chance, int interval, int max_loop, int avoid_override, int Msg = 0);
|
||||
void Tune_FindAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_chance, int interval, int max_loop, int acc_override, int Msg = 0);
|
||||
|
||||
protected:
|
||||
void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillUseTypes attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic);
|
||||
static uint16 GetProcID(uint16 spell_id, uint8 effect_index);
|
||||
|
||||
@ -3472,14 +3472,16 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
|
||||
{
|
||||
effect_value = CalcSpellEffectValue(spell_id, i, caster_level, caster, ticsremaining);
|
||||
//Handle client cast DOTs here.
|
||||
if (caster && effect_value < 0 && IsDetrimentalSpell(spell_id)){
|
||||
if (caster && effect_value < 0){
|
||||
|
||||
if (caster->IsClient()){
|
||||
if (!caster->CastToClient()->GetFeigned())
|
||||
if (IsDetrimentalSpell(spell_id)){
|
||||
if (caster->IsClient()){
|
||||
if (!caster->CastToClient()->GetFeigned())
|
||||
AddToHateList(caster, -effect_value);
|
||||
}
|
||||
else if (!IsClient()) //Allow NPC's to generate hate if casted on other NPC's.
|
||||
AddToHateList(caster, -effect_value);
|
||||
}
|
||||
else if (!IsClient()) //Allow NPC's to generate hate if casted on other NPC's.
|
||||
AddToHateList(caster, -effect_value);
|
||||
|
||||
effect_value = caster->GetActDoTDamage(spell_id, effect_value, this);
|
||||
|
||||
@ -6569,33 +6571,32 @@ bool Mob::TrySpellProjectile(Mob* spell_target, uint16 spell_id, float speed){
|
||||
|
||||
DoAnim(anim, 0, true, IsClient() ? FilterPCSpells : FilterNPCSpells); //Override the default projectile animation.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::ResourceTap(int32 damage, uint16 spellid){
|
||||
void Mob::ResourceTap(int32 damage, uint16 spellid)
|
||||
{
|
||||
//'this' = caster
|
||||
if (!IsValidSpell(spellid))
|
||||
return;
|
||||
|
||||
for (int i = 0; i <= EFFECT_COUNT; i++)
|
||||
{
|
||||
if (spells[spellid].effectid[i] == SE_ResourceTap){
|
||||
|
||||
damage += (damage * spells[spellid].base[i])/100;
|
||||
for (int i = 0; i < EFFECT_COUNT; i++) {
|
||||
if (spells[spellid].effectid[i] == SE_ResourceTap) {
|
||||
damage += (damage * spells[spellid].base[i]) / 100;
|
||||
|
||||
if (spells[spellid].max[i] && (damage > spells[spellid].max[i]))
|
||||
damage = spells[spellid].max[i];
|
||||
|
||||
if (spells[spellid].base2[i] == 0){ //HP Tap
|
||||
if (spells[spellid].base2[i] == 0) { // HP Tap
|
||||
if (damage > 0)
|
||||
HealDamage(damage);
|
||||
else
|
||||
Damage(this, -damage,0, SkillEvocation,false);
|
||||
Damage(this, -damage, 0, SkillEvocation, false);
|
||||
}
|
||||
|
||||
if (spells[spellid].base2[i] == 1) //Mana Tap
|
||||
if (spells[spellid].base2[i] == 1) // Mana Tap
|
||||
SetMana(GetMana() + damage);
|
||||
|
||||
if (spells[spellid].base2[i] == 2 && IsClient()) //Endurance Tap
|
||||
if (spells[spellid].base2[i] == 2 && IsClient()) // Endurance Tap
|
||||
CastToClient()->SetEndurance(CastToClient()->GetEndurance() + damage);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2741,7 +2741,7 @@ void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, int SequenceN
|
||||
+ sizeof(TaskDescriptionData1_Struct) + strlen(Tasks[TaskID]->Description) + 1
|
||||
+ sizeof(TaskDescriptionData2_Struct) + 1 + sizeof(TaskDescriptionTrailer_Struct);
|
||||
|
||||
std::string RewardText;
|
||||
std::string reward_text;
|
||||
int ItemID = NOT_USED;
|
||||
|
||||
// If there is an item make the Reward text into a link to the item (only the first item if a list
|
||||
@ -2769,17 +2769,17 @@ void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, int SequenceN
|
||||
linker.SetProxyText(Tasks[TaskID]->Reward);
|
||||
|
||||
auto reward_link = linker.GenerateLink();
|
||||
RewardText += reward_link.c_str();
|
||||
reward_text.append(reward_link);
|
||||
}
|
||||
else {
|
||||
RewardText += Tasks[TaskID]->Reward;
|
||||
reward_text.append(Tasks[TaskID]->Reward);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
RewardText += Tasks[TaskID]->Reward;
|
||||
reward_text.append(Tasks[TaskID]->Reward);
|
||||
}
|
||||
PacketLength += strlen(RewardText.c_str()) + 1;
|
||||
PacketLength += reward_text.length() + 1;
|
||||
|
||||
char *Ptr;
|
||||
TaskDescriptionHeader_Struct* tdh;
|
||||
@ -2835,7 +2835,7 @@ void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, int SequenceN
|
||||
tdd2->unknown3 = 0x0000;
|
||||
Ptr = (char *) tdd2 + sizeof(TaskDescriptionData2_Struct);
|
||||
|
||||
sprintf(Ptr, "%s", RewardText.c_str());
|
||||
sprintf(Ptr, "%s", reward_text.c_str());
|
||||
Ptr = Ptr + strlen(Ptr) + 1;
|
||||
|
||||
tdt = (TaskDescriptionTrailer_Struct*)Ptr;
|
||||
|
||||
1089
zone/tune.cpp
Normal file
1089
zone/tune.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -670,15 +670,7 @@ void Zone::Shutdown(bool quite)
|
||||
if (!ZoneLoaded)
|
||||
return;
|
||||
|
||||
std::list<Mob*> mob_list;
|
||||
entity_list.GetMobList(mob_list);
|
||||
std::list<Mob*>::iterator mob_itr = mob_list.begin();
|
||||
while (mob_itr != mob_list.end()) {
|
||||
Mob* mob_inst = *mob_itr;
|
||||
mob_inst->AI_Stop();
|
||||
mob_inst->AI_ShutDown();
|
||||
++mob_itr;
|
||||
}
|
||||
entity_list.StopMobAI();
|
||||
|
||||
std::map<uint32,NPCType *>::iterator itr;
|
||||
while(zone->npctable.size()) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user