mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 13:41:31 +00:00
Merge pull request #871 from EQEmu/fix_OP_SpecialMesg
Fix issues with OP_SpecialMesg handling
This commit is contained in:
commit
186834594f
@ -75,6 +75,7 @@ public:
|
|||||||
uint32 ReadUInt32() { uint32 value = *(uint32 *)(pBuffer + _rpos); _rpos += sizeof(uint32); return value; }
|
uint32 ReadUInt32() { uint32 value = *(uint32 *)(pBuffer + _rpos); _rpos += sizeof(uint32); return value; }
|
||||||
uint32 ReadUInt32(uint32 Offset) const { uint32 value = *(uint32 *)(pBuffer + Offset); return value; }
|
uint32 ReadUInt32(uint32 Offset) const { uint32 value = *(uint32 *)(pBuffer + Offset); return value; }
|
||||||
void ReadString(char *str) { uint32 len = static_cast<uint32>(strlen((char *)(pBuffer + _rpos))) + 1; memcpy(str, pBuffer + _rpos, len); _rpos += len; }
|
void ReadString(char *str) { uint32 len = static_cast<uint32>(strlen((char *)(pBuffer + _rpos))) + 1; memcpy(str, pBuffer + _rpos, len); _rpos += len; }
|
||||||
|
void ReadString(std::string &str) { str = reinterpret_cast<char *>(pBuffer + _rpos); _rpos += str.length() + 1; }
|
||||||
void ReadString(char *str, uint32 Offset, uint32 MaxLength) const;
|
void ReadString(char *str, uint32 Offset, uint32 MaxLength) const;
|
||||||
|
|
||||||
uint32 GetWritePosition() { return _wpos; }
|
uint32 GetWritePosition() { return _wpos; }
|
||||||
|
|||||||
@ -87,6 +87,7 @@ typedef enum {
|
|||||||
_eaMaxAppearance
|
_eaMaxAppearance
|
||||||
} EmuAppearance;
|
} EmuAppearance;
|
||||||
|
|
||||||
|
#define MT_NPCQuestSay 10
|
||||||
// msg_type's for custom usercolors
|
// msg_type's for custom usercolors
|
||||||
#define MT_Say 256
|
#define MT_Say 256
|
||||||
#define MT_Tell 257
|
#define MT_Tell 257
|
||||||
|
|||||||
@ -1188,6 +1188,20 @@ struct SpecialMesg_Struct
|
|||||||
/*24*/ char message[1]; // What is being said?
|
/*24*/ char message[1]; // What is being said?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SpecialMesgHeader_Struct
|
||||||
|
{
|
||||||
|
/*00*/ char SpeakMode; // 2 shouts, 4 %1 %2, 3 %2, 5 tells group, 0 copy, default says
|
||||||
|
/*01*/ char JournalMode; // 1 and 2 go to journal
|
||||||
|
/*02*/ char language;
|
||||||
|
/*03*/ uint32 msg_type; // Color of text (see MT_*** below)
|
||||||
|
/*07*/ uint32 target_spawn_id; // Who is it being said to?
|
||||||
|
/*11*/ // speaker's name
|
||||||
|
/*xx*/ // unknown, location, client doesn't care
|
||||||
|
/*xx*/ // unknown
|
||||||
|
/*xx*/ // unknown
|
||||||
|
/*xx*/ // message
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** When somebody changes what they're wearing or give a pet a weapon (model changes)
|
** When somebody changes what they're wearing or give a pet a weapon (model changes)
|
||||||
** Length: 19 Bytes
|
** Length: 19 Bytes
|
||||||
|
|||||||
@ -3199,43 +3199,35 @@ namespace RoF
|
|||||||
EQApplicationPacket *in = *p;
|
EQApplicationPacket *in = *p;
|
||||||
*p = nullptr;
|
*p = nullptr;
|
||||||
|
|
||||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
SerializeBuffer buf(in->size);
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // language
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||||
|
|
||||||
unsigned char *__emu_buffer = in->pBuffer;
|
std::string name;
|
||||||
// break strlen optimizations!
|
in->ReadString(name); // NPC names max out at 63 chars
|
||||||
char *message = emu->sayer;
|
|
||||||
auto sayer_length = std::char_traits<char>::length(message);
|
|
||||||
message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats
|
|
||||||
|
|
||||||
std::string old_message = message;
|
buf.WriteString(name);
|
||||||
|
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
|
||||||
|
std::string old_message;
|
||||||
std::string new_message;
|
std::string new_message;
|
||||||
|
|
||||||
|
in->ReadString(old_message);
|
||||||
|
|
||||||
ServerToRoFSayLink(new_message, old_message);
|
ServerToRoFSayLink(new_message, old_message);
|
||||||
|
|
||||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
buf.WriteString(new_message);
|
||||||
in->size = sayer_length + new_message.length() + 25;
|
|
||||||
in->pBuffer = new unsigned char[in->size];
|
|
||||||
|
|
||||||
char *OutBuffer = (char *)in->pBuffer;
|
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
dest->FastQueuePacket(&outapp, ack_req);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
delete in;
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
|
||||||
|
|
||||||
// TODO: figure this shit out
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
|
||||||
|
|
||||||
delete[] __emu_buffer;
|
|
||||||
dest->FastQueuePacket(&in, ack_req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_Stun)
|
ENCODE(OP_Stun)
|
||||||
|
|||||||
@ -3266,43 +3266,35 @@ namespace RoF2
|
|||||||
EQApplicationPacket *in = *p;
|
EQApplicationPacket *in = *p;
|
||||||
*p = nullptr;
|
*p = nullptr;
|
||||||
|
|
||||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
SerializeBuffer buf(in->size);
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // language
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||||
|
|
||||||
unsigned char *__emu_buffer = in->pBuffer;
|
std::string name;
|
||||||
// break strlen optimizations!
|
in->ReadString(name); // NPC names max out at 63 chars
|
||||||
char *message = emu->sayer;
|
|
||||||
auto sayer_length = std::char_traits<char>::length(message);
|
|
||||||
message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats
|
|
||||||
|
|
||||||
std::string old_message = message;
|
buf.WriteString(name);
|
||||||
|
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
|
||||||
|
std::string old_message;
|
||||||
std::string new_message;
|
std::string new_message;
|
||||||
|
|
||||||
|
in->ReadString(old_message);
|
||||||
|
|
||||||
ServerToRoF2SayLink(new_message, old_message);
|
ServerToRoF2SayLink(new_message, old_message);
|
||||||
|
|
||||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
buf.WriteString(new_message);
|
||||||
in->size = sayer_length + new_message.length() + 25;
|
|
||||||
in->pBuffer = new unsigned char[in->size];
|
|
||||||
|
|
||||||
char *OutBuffer = (char *)in->pBuffer;
|
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
dest->FastQueuePacket(&outapp, ack_req);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
delete in;
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
|
||||||
|
|
||||||
// TODO: figure this shit out
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
|
||||||
|
|
||||||
delete[] __emu_buffer;
|
|
||||||
dest->FastQueuePacket(&in, ack_req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_Stun)
|
ENCODE(OP_Stun)
|
||||||
|
|||||||
@ -2069,43 +2069,35 @@ namespace SoD
|
|||||||
EQApplicationPacket *in = *p;
|
EQApplicationPacket *in = *p;
|
||||||
*p = nullptr;
|
*p = nullptr;
|
||||||
|
|
||||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
SerializeBuffer buf(in->size);
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // language
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||||
|
|
||||||
unsigned char *__emu_buffer = in->pBuffer;
|
std::string name;
|
||||||
// break strlen optimizations!
|
in->ReadString(name); // NPC names max out at 63 chars
|
||||||
char *message = emu->sayer;
|
|
||||||
auto sayer_length = std::char_traits<char>::length(message);
|
|
||||||
message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats
|
|
||||||
|
|
||||||
std::string old_message = message;
|
buf.WriteString(name);
|
||||||
|
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
|
||||||
|
std::string old_message;
|
||||||
std::string new_message;
|
std::string new_message;
|
||||||
|
|
||||||
|
in->ReadString(old_message);
|
||||||
|
|
||||||
ServerToSoDSayLink(new_message, old_message);
|
ServerToSoDSayLink(new_message, old_message);
|
||||||
|
|
||||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
buf.WriteString(new_message);
|
||||||
in->size = sayer_length + new_message.length() + 25;
|
|
||||||
in->pBuffer = new unsigned char[in->size];
|
|
||||||
|
|
||||||
char *OutBuffer = (char *)in->pBuffer;
|
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
dest->FastQueuePacket(&outapp, ack_req);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
delete in;
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
|
||||||
|
|
||||||
// TODO: figure this shit out
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
|
||||||
|
|
||||||
delete[] __emu_buffer;
|
|
||||||
dest->FastQueuePacket(&in, ack_req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_Stun)
|
ENCODE(OP_Stun)
|
||||||
|
|||||||
@ -1720,43 +1720,35 @@ namespace SoF
|
|||||||
EQApplicationPacket *in = *p;
|
EQApplicationPacket *in = *p;
|
||||||
*p = nullptr;
|
*p = nullptr;
|
||||||
|
|
||||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
SerializeBuffer buf(in->size);
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // language
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||||
|
|
||||||
unsigned char *__emu_buffer = in->pBuffer;
|
std::string name;
|
||||||
// break strlen optimizations!
|
in->ReadString(name);
|
||||||
char *message = emu->sayer;
|
|
||||||
auto sayer_length = std::char_traits<char>::length(message);
|
|
||||||
message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats
|
|
||||||
|
|
||||||
std::string old_message = message;
|
buf.WriteString(name);
|
||||||
|
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
|
||||||
|
std::string old_message;
|
||||||
std::string new_message;
|
std::string new_message;
|
||||||
|
|
||||||
|
in->ReadString(old_message);
|
||||||
|
|
||||||
ServerToSoFSayLink(new_message, old_message);
|
ServerToSoFSayLink(new_message, old_message);
|
||||||
|
|
||||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
buf.WriteString(new_message);
|
||||||
in->size = sayer_length + new_message.length() + 25;
|
|
||||||
in->pBuffer = new unsigned char[in->size];
|
|
||||||
|
|
||||||
char *OutBuffer = (char *)in->pBuffer;
|
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
dest->FastQueuePacket(&outapp, ack_req);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
delete in;
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
|
||||||
|
|
||||||
// TODO: figure this shit out
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
|
||||||
|
|
||||||
delete[] __emu_buffer;
|
|
||||||
dest->FastQueuePacket(&in, ack_req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_Stun)
|
ENCODE(OP_Stun)
|
||||||
|
|||||||
@ -1420,43 +1420,35 @@ namespace Titanium
|
|||||||
EQApplicationPacket *in = *p;
|
EQApplicationPacket *in = *p;
|
||||||
*p = nullptr;
|
*p = nullptr;
|
||||||
|
|
||||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
SerializeBuffer buf(in->size);
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // language
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||||
|
|
||||||
unsigned char *__emu_buffer = in->pBuffer;
|
std::string name;
|
||||||
// break strlen optimizations!
|
in->ReadString(name); // NPC names max out at 63 chars
|
||||||
char *message = emu->sayer;
|
|
||||||
auto sayer_length = std::char_traits<char>::length(message);
|
|
||||||
message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats
|
|
||||||
|
|
||||||
std::string old_message = message;
|
buf.WriteString(name);
|
||||||
|
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
|
||||||
|
std::string old_message;
|
||||||
std::string new_message;
|
std::string new_message;
|
||||||
|
|
||||||
|
in->ReadString(old_message);
|
||||||
|
|
||||||
ServerToTitaniumSayLink(new_message, old_message);
|
ServerToTitaniumSayLink(new_message, old_message);
|
||||||
|
|
||||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
buf.WriteString(new_message);
|
||||||
in->size = sayer_length + new_message.length() + 25;
|
|
||||||
in->pBuffer = new unsigned char[in->size];
|
|
||||||
|
|
||||||
char *OutBuffer = (char *)in->pBuffer;
|
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
dest->FastQueuePacket(&outapp, ack_req);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
delete in;
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
|
||||||
|
|
||||||
// TODO: figure this shit out
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
|
||||||
|
|
||||||
delete[] __emu_buffer;
|
|
||||||
dest->FastQueuePacket(&in, ack_req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_TaskDescription)
|
ENCODE(OP_TaskDescription)
|
||||||
|
|||||||
@ -2369,43 +2369,35 @@ namespace UF
|
|||||||
EQApplicationPacket *in = *p;
|
EQApplicationPacket *in = *p;
|
||||||
*p = nullptr;
|
*p = nullptr;
|
||||||
|
|
||||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
SerializeBuffer buf(in->size);
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // language
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||||
|
|
||||||
unsigned char *__emu_buffer = in->pBuffer;
|
std::string name;
|
||||||
// break strlen optimizations!
|
in->ReadString(name); // NPC names max out at 63 chars
|
||||||
char *message = emu->sayer;
|
|
||||||
auto sayer_length = std::char_traits<char>::length(message);
|
|
||||||
message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats
|
|
||||||
|
|
||||||
std::string old_message = message;
|
buf.WriteString(name);
|
||||||
|
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
|
||||||
|
std::string old_message;
|
||||||
std::string new_message;
|
std::string new_message;
|
||||||
|
|
||||||
|
in->ReadString(old_message);
|
||||||
|
|
||||||
ServerToUFSayLink(new_message, old_message);
|
ServerToUFSayLink(new_message, old_message);
|
||||||
|
|
||||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
buf.WriteString(new_message);
|
||||||
in->size = sayer_length + new_message.length() + 25;
|
|
||||||
in->pBuffer = new unsigned char[in->size];
|
|
||||||
|
|
||||||
char *OutBuffer = (char *)in->pBuffer;
|
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
dest->FastQueuePacket(&outapp, ack_req);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
delete in;
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
|
||||||
|
|
||||||
// TODO: figure this shit out
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
|
||||||
|
|
||||||
delete[] __emu_buffer;
|
|
||||||
dest->FastQueuePacket(&in, ack_req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_Stun)
|
ENCODE(OP_Stun)
|
||||||
|
|||||||
@ -1277,21 +1277,19 @@ void Client::Message(uint32 type, const char* message, ...) {
|
|||||||
vsnprintf(buffer, 4096, message, argptr);
|
vsnprintf(buffer, 4096, message, argptr);
|
||||||
va_end(argptr);
|
va_end(argptr);
|
||||||
|
|
||||||
size_t len = strlen(buffer);
|
SerializeBuffer buf(sizeof(SpecialMesgHeader_Struct) + 12 + 64 + 64);
|
||||||
|
buf.WriteInt8(static_cast<int8>(Journal::SpeakMode::Raw));
|
||||||
|
buf.WriteInt8(static_cast<int8>(Journal::Mode::None));
|
||||||
|
buf.WriteInt8(0); // language
|
||||||
|
buf.WriteUInt32(type);
|
||||||
|
buf.WriteUInt32(0); // target spawn ID used for journal filtering, ignored here
|
||||||
|
buf.WriteString(""); // send name, not applicable here
|
||||||
|
buf.WriteInt32(0); // location, client seems to ignore
|
||||||
|
buf.WriteInt32(0);
|
||||||
|
buf.WriteInt32(0);
|
||||||
|
buf.WriteString(buffer);
|
||||||
|
|
||||||
//client dosent like our packet all the time unless
|
auto app = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||||
//we make it really big, then it seems to not care that
|
|
||||||
//our header is malformed.
|
|
||||||
//len = 4096 - sizeof(SpecialMesg_Struct);
|
|
||||||
|
|
||||||
uint32 len_packet = sizeof(SpecialMesg_Struct)+len;
|
|
||||||
auto app = new EQApplicationPacket(OP_SpecialMesg, len_packet);
|
|
||||||
SpecialMesg_Struct* sm=(SpecialMesg_Struct*)app->pBuffer;
|
|
||||||
sm->header[0] = 0x00; // Header used for #emote style messages..
|
|
||||||
sm->header[1] = 0x00; // Play around with these to see other types
|
|
||||||
sm->header[2] = 0x00;
|
|
||||||
sm->msg_type = type;
|
|
||||||
memcpy(sm->message, buffer, len+1);
|
|
||||||
|
|
||||||
FastQueuePacket(&app);
|
FastQueuePacket(&app);
|
||||||
|
|
||||||
@ -1308,67 +1306,25 @@ void Client::FilteredMessage(Mob *sender, uint32 type, eqFilterType filter, cons
|
|||||||
vsnprintf(buffer, 4096, message, argptr);
|
vsnprintf(buffer, 4096, message, argptr);
|
||||||
va_end(argptr);
|
va_end(argptr);
|
||||||
|
|
||||||
size_t len = strlen(buffer);
|
SerializeBuffer buf(sizeof(SpecialMesgHeader_Struct) + 12 + 64 + 64);
|
||||||
|
buf.WriteInt8(static_cast<int8>(Journal::SpeakMode::Raw));
|
||||||
|
buf.WriteInt8(static_cast<int8>(Journal::Mode::None));
|
||||||
|
buf.WriteInt8(0); // language
|
||||||
|
buf.WriteUInt32(type);
|
||||||
|
buf.WriteUInt32(0); // target spawn ID used for journal filtering, ignored here
|
||||||
|
buf.WriteString(""); // send name, not applicable here
|
||||||
|
buf.WriteInt32(0); // location, client seems to ignore
|
||||||
|
buf.WriteInt32(0);
|
||||||
|
buf.WriteInt32(0);
|
||||||
|
buf.WriteString(buffer);
|
||||||
|
|
||||||
//client dosent like our packet all the time unless
|
auto app = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||||
//we make it really big, then it seems to not care that
|
|
||||||
//our header is malformed.
|
|
||||||
//len = 4096 - sizeof(SpecialMesg_Struct);
|
|
||||||
|
|
||||||
uint32 len_packet = sizeof(SpecialMesg_Struct) + len;
|
|
||||||
auto app = new EQApplicationPacket(OP_SpecialMesg, len_packet);
|
|
||||||
SpecialMesg_Struct* sm = (SpecialMesg_Struct*)app->pBuffer;
|
|
||||||
sm->header[0] = 0x00; // Header used for #emote style messages..
|
|
||||||
sm->header[1] = 0x00; // Play around with these to see other types
|
|
||||||
sm->header[2] = 0x00;
|
|
||||||
sm->msg_type = type;
|
|
||||||
memcpy(sm->message, buffer, len + 1);
|
|
||||||
|
|
||||||
FastQueuePacket(&app);
|
FastQueuePacket(&app);
|
||||||
|
|
||||||
safe_delete_array(buffer);
|
safe_delete_array(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::QuestJournalledMessage(const char *npcname, const char* message) {
|
|
||||||
|
|
||||||
// npcnames longer than 60 characters crash the client when they log back in
|
|
||||||
const int MaxNPCNameLength = 60;
|
|
||||||
// I assume there is an upper safe limit on the message length. Don't know what it is, but 4000 doesn't crash
|
|
||||||
// the client.
|
|
||||||
const int MaxMessageLength = 4000;
|
|
||||||
|
|
||||||
char OutNPCName[MaxNPCNameLength+1];
|
|
||||||
char OutMessage[MaxMessageLength+1];
|
|
||||||
|
|
||||||
// Apparently Visual C++ snprintf is not C99 compliant and doesn't put the null terminator
|
|
||||||
// in if the formatted string >= the maximum length, so we put it in.
|
|
||||||
//
|
|
||||||
snprintf(OutNPCName, MaxNPCNameLength, "%s", npcname); OutNPCName[MaxNPCNameLength]='\0';
|
|
||||||
snprintf(OutMessage, MaxMessageLength, "%s", message); OutMessage[MaxMessageLength]='\0';
|
|
||||||
|
|
||||||
uint32 len_packet = sizeof(SpecialMesg_Struct) + strlen(OutNPCName) + strlen(OutMessage);
|
|
||||||
auto app = new EQApplicationPacket(OP_SpecialMesg, len_packet);
|
|
||||||
SpecialMesg_Struct* sm=(SpecialMesg_Struct*)app->pBuffer;
|
|
||||||
|
|
||||||
sm->header[0] = 0;
|
|
||||||
sm->header[1] = 2;
|
|
||||||
sm->header[2] = 0;
|
|
||||||
sm->msg_type = 0x0a;
|
|
||||||
sm->target_spawn_id = GetID();
|
|
||||||
|
|
||||||
char *dest = &sm->sayer[0];
|
|
||||||
|
|
||||||
memcpy(dest, OutNPCName, strlen(OutNPCName) + 1);
|
|
||||||
|
|
||||||
dest = dest + strlen(OutNPCName) + 13;
|
|
||||||
|
|
||||||
memcpy(dest, OutMessage, strlen(OutMessage) + 1);
|
|
||||||
|
|
||||||
QueuePacket(app);
|
|
||||||
|
|
||||||
safe_delete(app);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::SetMaxHP() {
|
void Client::SetMaxHP() {
|
||||||
if(dead)
|
if(dead)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -341,7 +341,6 @@ public:
|
|||||||
void ChannelMessageSend(const char* from, const char* to, uint8 chan_num, uint8 language, uint8 lang_skill, const char* message, ...);
|
void ChannelMessageSend(const char* from, const char* to, uint8 chan_num, uint8 language, uint8 lang_skill, const char* message, ...);
|
||||||
void Message(uint32 type, const char* message, ...);
|
void Message(uint32 type, const char* message, ...);
|
||||||
void FilteredMessage(Mob *sender, uint32 type, eqFilterType filter, const char* message, ...);
|
void FilteredMessage(Mob *sender, uint32 type, eqFilterType filter, const char* message, ...);
|
||||||
void QuestJournalledMessage(const char *npcname, const char* message);
|
|
||||||
void VoiceMacroReceived(uint32 Type, char *Target, uint32 MacroNumber);
|
void VoiceMacroReceived(uint32 Type, char *Target, uint32 MacroNumber);
|
||||||
void SendSound();
|
void SendSound();
|
||||||
void LearnRecipe(uint32 recipeID);
|
void LearnRecipe(uint32 recipeID);
|
||||||
|
|||||||
@ -272,6 +272,31 @@ enum class LootRequestType : uint8 {
|
|||||||
AllowedPVPDefined,
|
AllowedPVPDefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace Journal {
|
||||||
|
enum class SpeakMode : uint8 {
|
||||||
|
Raw = 0, // this just uses the raw message
|
||||||
|
Say = 1, // prints with "%1 says,%2 '%3'" if in another language else "%1 says '%2'"
|
||||||
|
Shout = 2, // prints with "%1 shouts,%2 '%3'" if in another language else "%1 shouts '%2'"
|
||||||
|
EmoteAlt = 3, // prints "%2", this should just be the same as raw ...
|
||||||
|
Emote = 4, // prints "%1 %2" if message doesn't start with "\" or "@", else "%1%2"
|
||||||
|
Group = 5 // prints "%1 tells the group,%2 '%3'"
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Mode : uint8 {
|
||||||
|
None = 0,
|
||||||
|
Log1 = 1, // 1 and 2 log to journal
|
||||||
|
Log2 = 2, // our current code uses 2
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Options {
|
||||||
|
SpeakMode speak_mode;
|
||||||
|
Mode journal_mode;
|
||||||
|
int8 language;
|
||||||
|
uint32 message_type;
|
||||||
|
uint32 target_spawn_id; // who the message is talking to (limits journaling)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
//this is our internal representation of the BUFF struct, can put whatever we want in it
|
//this is our internal representation of the BUFF struct, can put whatever we want in it
|
||||||
struct Buffs_Struct {
|
struct Buffs_Struct {
|
||||||
uint16 spellid;
|
uint16 spellid;
|
||||||
|
|||||||
@ -155,12 +155,31 @@ XS(XS__say); // prototype to pass -Wmissing-prototypes
|
|||||||
XS(XS__say) {
|
XS(XS__say) {
|
||||||
dXSARGS;
|
dXSARGS;
|
||||||
|
|
||||||
if (items == 1)
|
Journal::Options opts;
|
||||||
quest_manager.say(SvPV_nolen(ST(0)));
|
// we currently default to these
|
||||||
else if (items == 2)
|
opts.speak_mode = Journal::SpeakMode::Say;
|
||||||
quest_manager.say(SvPV_nolen(ST(0)), (int) SvIV(ST(1)));
|
opts.journal_mode = Journal::Mode::Log2;
|
||||||
else
|
opts.language = 0;
|
||||||
Perl_croak(aTHX_ "Usage: quest::say(string message, int language_id])");
|
opts.message_type = MT_NPCQuestSay;
|
||||||
|
if (items == 0 || items > 5) {
|
||||||
|
Perl_croak(aTHX_ "Usage: quest::say(string message, [int language_id], [int message_type], [int speak_mode], [int journal_mode])");
|
||||||
|
} else if (items == 2) {
|
||||||
|
opts.language = (int)SvIV(ST(1));
|
||||||
|
} else if (items == 3) {
|
||||||
|
opts.language = (int)SvIV(ST(1));
|
||||||
|
opts.message_type = (int)SvIV(ST(2));
|
||||||
|
} else if (items == 4) {
|
||||||
|
opts.language = (int)SvIV(ST(1));
|
||||||
|
opts.message_type = (int)SvIV(ST(2));
|
||||||
|
opts.speak_mode = (Journal::SpeakMode)SvIV(ST(3));
|
||||||
|
} else if (items == 5) {
|
||||||
|
opts.language = (int)SvIV(ST(1));
|
||||||
|
opts.message_type = (int)SvIV(ST(2));
|
||||||
|
opts.speak_mode = (Journal::SpeakMode)SvIV(ST(3));
|
||||||
|
opts.journal_mode = (Journal::Mode)SvIV(ST(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
quest_manager.say(SvPV_nolen(ST(0)), opts);
|
||||||
|
|
||||||
XSRETURN_EMPTY;
|
XSRETURN_EMPTY;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3733,24 +3733,26 @@ bool Entity::CheckCoordLosNoZLeaps(float cur_x, float cur_y, float cur_z,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EntityList::QuestJournalledSayClose(Mob *sender, Client *QuestInitiator,
|
void EntityList::QuestJournalledSayClose(Mob *sender, Client *QuestInitiator,
|
||||||
float dist, const char* mobname, const char* message)
|
float dist, const char* mobname, const char* message, Journal::Options &opts)
|
||||||
{
|
{
|
||||||
Client *c = nullptr;
|
SerializeBuffer buf(sizeof(SpecialMesgHeader_Struct) + 12 + 64 + 64);
|
||||||
float dist2 = dist * dist;
|
|
||||||
|
|
||||||
// Send the message to the quest initiator such that the client will enter it into the NPC Quest Journal
|
buf.WriteInt8(static_cast<int8>(opts.speak_mode));
|
||||||
if (QuestInitiator) {
|
buf.WriteInt8(static_cast<int8>(opts.journal_mode));
|
||||||
auto buf = new char[strlen(mobname) + strlen(message) + 10];
|
buf.WriteInt8(opts.language);
|
||||||
sprintf(buf, "%s says, '%s'", mobname, message);
|
buf.WriteInt32(opts.message_type);
|
||||||
QuestInitiator->QuestJournalledMessage(mobname, buf);
|
buf.WriteInt32(opts.target_spawn_id);
|
||||||
safe_delete_array(buf);
|
buf.WriteString(mobname);
|
||||||
}
|
buf.WriteInt32(0); // location, client doesn't seem to do anything with this
|
||||||
// Use the old method for all other nearby clients
|
buf.WriteInt32(0);
|
||||||
for (auto it = client_list.begin(); it != client_list.end(); ++it) {
|
buf.WriteInt32(0);
|
||||||
c = it->second;
|
buf.WriteString(message);
|
||||||
if(c && (c != QuestInitiator) && DistanceSquared(c->GetPosition(), sender->GetPosition()) <= dist2)
|
|
||||||
c->Message_StringID(10, GENERIC_SAY, mobname, message);
|
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||||
}
|
|
||||||
|
// client only bothers logging if target spawn ID matches, safe to send to everyone
|
||||||
|
QueueCloseClients(sender, outapp, false, dist);
|
||||||
|
delete outapp;
|
||||||
}
|
}
|
||||||
|
|
||||||
Corpse *EntityList::GetClosestCorpse(Mob *sender, const char *Name)
|
Corpse *EntityList::GetClosestCorpse(Mob *sender, const char *Name)
|
||||||
|
|||||||
@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include "position.h"
|
#include "position.h"
|
||||||
#include "zonedump.h"
|
#include "zonedump.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
class Encounter;
|
class Encounter;
|
||||||
class Beacon;
|
class Beacon;
|
||||||
@ -337,7 +338,7 @@ public:
|
|||||||
void SendNimbusEffects(Client *c);
|
void SendNimbusEffects(Client *c);
|
||||||
void SendUntargetable(Client *c);
|
void SendUntargetable(Client *c);
|
||||||
void DuelMessage(Mob* winner, Mob* loser, bool flee);
|
void DuelMessage(Mob* winner, Mob* loser, bool flee);
|
||||||
void QuestJournalledSayClose(Mob *sender, Client *QuestIntiator, float dist, const char* mobname, const char* message);
|
void QuestJournalledSayClose(Mob *sender, Client *QuestIntiator, float dist, const char* mobname, const char* message, Journal::Options &opts);
|
||||||
void GroupMessage(uint32 gid, const char *from, const char *message);
|
void GroupMessage(uint32 gid, const char *from, const char *message);
|
||||||
void ExpeditionWarning(uint32 minutes_left);
|
void ExpeditionWarning(uint32 minutes_left);
|
||||||
|
|
||||||
|
|||||||
@ -36,6 +36,8 @@ struct BodyTypes { };
|
|||||||
struct Filters { };
|
struct Filters { };
|
||||||
struct MessageTypes { };
|
struct MessageTypes { };
|
||||||
struct Rule { };
|
struct Rule { };
|
||||||
|
struct Journal_SpeakMode { };
|
||||||
|
struct Journal_Mode { };
|
||||||
|
|
||||||
struct lua_registered_event {
|
struct lua_registered_event {
|
||||||
std::string encounter_name;
|
std::string encounter_name;
|
||||||
@ -2232,6 +2234,7 @@ luabind::scope lua_register_message_types() {
|
|||||||
return luabind::class_<MessageTypes>("MT")
|
return luabind::class_<MessageTypes>("MT")
|
||||||
.enum_("constants")
|
.enum_("constants")
|
||||||
[
|
[
|
||||||
|
luabind::value("NPCQuestSay", MT_NPCQuestSay),
|
||||||
luabind::value("Say", MT_Say),
|
luabind::value("Say", MT_Say),
|
||||||
luabind::value("Tell", MT_Tell),
|
luabind::value("Tell", MT_Tell),
|
||||||
luabind::value("Group", MT_Group),
|
luabind::value("Group", MT_Group),
|
||||||
@ -2362,4 +2365,27 @@ luabind::scope lua_register_ruleb() {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
luabind::scope lua_register_journal_speakmode() {
|
||||||
|
return luabind::class_<Journal_SpeakMode>("SpeakMode")
|
||||||
|
.enum_("constants")
|
||||||
|
[
|
||||||
|
luabind::value("Raw", static_cast<int>(Journal::SpeakMode::Raw)),
|
||||||
|
luabind::value("Say", static_cast<int>(Journal::SpeakMode::Say)),
|
||||||
|
luabind::value("Shout", static_cast<int>(Journal::SpeakMode::Shout)),
|
||||||
|
luabind::value("EmoteAlt", static_cast<int>(Journal::SpeakMode::EmoteAlt)),
|
||||||
|
luabind::value("Emote", static_cast<int>(Journal::SpeakMode::Emote)),
|
||||||
|
luabind::value("Group", static_cast<int>(Journal::SpeakMode::Group))
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::scope lua_register_journal_mode() {
|
||||||
|
return luabind::class_<Journal_Mode>("JournalMode")
|
||||||
|
.enum_("constants")
|
||||||
|
[
|
||||||
|
luabind::value("None", static_cast<int>(Journal::Mode::None)),
|
||||||
|
luabind::value("Log1", static_cast<int>(Journal::Mode::Log1)),
|
||||||
|
luabind::value("Log2", static_cast<int>(Journal::Mode::Log2))
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -19,6 +19,8 @@ luabind::scope lua_register_rules_const();
|
|||||||
luabind::scope lua_register_rulei();
|
luabind::scope lua_register_rulei();
|
||||||
luabind::scope lua_register_ruler();
|
luabind::scope lua_register_ruler();
|
||||||
luabind::scope lua_register_ruleb();
|
luabind::scope lua_register_ruleb();
|
||||||
|
luabind::scope lua_register_journal_speakmode();
|
||||||
|
luabind::scope lua_register_journal_mode();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -760,7 +760,65 @@ void Lua_Mob::Say(const char* message, int language) {
|
|||||||
|
|
||||||
void Lua_Mob::QuestSay(Lua_Client client, const char *message) {
|
void Lua_Mob::QuestSay(Lua_Client client, const char *message) {
|
||||||
Lua_Safe_Call_Void();
|
Lua_Safe_Call_Void();
|
||||||
self->QuestJournalledSay(client, message);
|
Journal::Options journal_opts;
|
||||||
|
journal_opts.speak_mode = Journal::SpeakMode::Say;
|
||||||
|
journal_opts.journal_mode = RuleB(NPC, EnableNPCQuestJournal) ? Journal::Mode::Log2 : Journal::Mode::None;
|
||||||
|
journal_opts.language = 0;
|
||||||
|
journal_opts.message_type = MT_NPCQuestSay;
|
||||||
|
journal_opts.target_spawn_id = 0;
|
||||||
|
self->QuestJournalledSay(client, message, journal_opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Mob::QuestSay(Lua_Client client, const char *message, luabind::adl::object opts) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
|
||||||
|
Journal::Options journal_opts;
|
||||||
|
// defaults
|
||||||
|
journal_opts.speak_mode = Journal::SpeakMode::Say;
|
||||||
|
journal_opts.journal_mode = Journal::Mode::Log2;
|
||||||
|
journal_opts.language = 0;
|
||||||
|
journal_opts.message_type = MT_NPCQuestSay;
|
||||||
|
journal_opts.target_spawn_id = 0;
|
||||||
|
|
||||||
|
if (luabind::type(opts) == LUA_TTABLE) {
|
||||||
|
auto cur = opts["speak_mode"];
|
||||||
|
if (luabind::type(cur) != LUA_TNIL) {
|
||||||
|
try {
|
||||||
|
journal_opts.speak_mode = static_cast<Journal::SpeakMode>(luabind::object_cast<int>(cur));
|
||||||
|
} catch (luabind::cast_failed) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = opts["journal_mode"];
|
||||||
|
if (luabind::type(cur) != LUA_TNIL) {
|
||||||
|
try {
|
||||||
|
journal_opts.journal_mode = static_cast<Journal::Mode>(luabind::object_cast<int>(cur));
|
||||||
|
} catch (luabind::cast_failed) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = opts["language"];
|
||||||
|
if (luabind::type(cur) != LUA_TNIL) {
|
||||||
|
try {
|
||||||
|
journal_opts.language = luabind::object_cast<int>(cur);
|
||||||
|
} catch (luabind::cast_failed) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = opts["message_type"];
|
||||||
|
if (luabind::type(cur) != LUA_TNIL) {
|
||||||
|
try {
|
||||||
|
journal_opts.message_type = luabind::object_cast<int>(cur);
|
||||||
|
} catch (luabind::cast_failed) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if rule disables it, we override provided
|
||||||
|
if (!RuleB(NPC, EnableNPCQuestJournal))
|
||||||
|
journal_opts.journal_mode = Journal::Mode::None;
|
||||||
|
|
||||||
|
self->QuestJournalledSay(client, message, journal_opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lua_Mob::Shout(const char *message) {
|
void Lua_Mob::Shout(const char *message) {
|
||||||
@ -2331,7 +2389,8 @@ luabind::scope lua_register_mob() {
|
|||||||
.def("Message_StringID", &Lua_Mob::Message_StringID)
|
.def("Message_StringID", &Lua_Mob::Message_StringID)
|
||||||
.def("Say", (void(Lua_Mob::*)(const char*))& Lua_Mob::Say)
|
.def("Say", (void(Lua_Mob::*)(const char*))& Lua_Mob::Say)
|
||||||
.def("Say", (void(Lua_Mob::*)(const char*, int))& Lua_Mob::Say)
|
.def("Say", (void(Lua_Mob::*)(const char*, int))& Lua_Mob::Say)
|
||||||
.def("QuestSay", &Lua_Mob::QuestSay)
|
.def("QuestSay", (void(Lua_Mob::*)(Lua_Client,const char *))&Lua_Mob::QuestSay)
|
||||||
|
.def("QuestSay", (void(Lua_Mob::*)(Lua_Client,const char *,luabind::adl::object))&Lua_Mob::QuestSay)
|
||||||
.def("Shout", (void(Lua_Mob::*)(const char*))& Lua_Mob::Shout)
|
.def("Shout", (void(Lua_Mob::*)(const char*))& Lua_Mob::Shout)
|
||||||
.def("Shout", (void(Lua_Mob::*)(const char*, int))& Lua_Mob::Shout)
|
.def("Shout", (void(Lua_Mob::*)(const char*, int))& Lua_Mob::Shout)
|
||||||
.def("Emote", &Lua_Mob::Emote)
|
.def("Emote", &Lua_Mob::Emote)
|
||||||
|
|||||||
@ -170,6 +170,7 @@ public:
|
|||||||
void Say(const char *message);
|
void Say(const char *message);
|
||||||
void Say(const char* message, int language);
|
void Say(const char* message, int language);
|
||||||
void QuestSay(Lua_Client client, const char *message);
|
void QuestSay(Lua_Client client, const char *message);
|
||||||
|
void QuestSay(Lua_Client client, const char *message, luabind::adl::object opts);
|
||||||
void Shout(const char *message);
|
void Shout(const char *message);
|
||||||
void Shout(const char* message, int language);
|
void Shout(const char* message, int language);
|
||||||
void Emote(const char *message);
|
void Emote(const char *message);
|
||||||
|
|||||||
@ -1102,7 +1102,9 @@ void LuaParser::MapFunctions(lua_State *L) {
|
|||||||
lua_register_rules_const(),
|
lua_register_rules_const(),
|
||||||
lua_register_rulei(),
|
lua_register_rulei(),
|
||||||
lua_register_ruler(),
|
lua_register_ruler(),
|
||||||
lua_register_ruleb()
|
lua_register_ruleb(),
|
||||||
|
lua_register_journal_speakmode(),
|
||||||
|
lua_register_journal_mode()
|
||||||
];
|
];
|
||||||
|
|
||||||
} catch(std::exception &ex) {
|
} catch(std::exception &ex) {
|
||||||
|
|||||||
@ -2911,9 +2911,13 @@ void Mob::Emote(const char *format, ...)
|
|||||||
GENERIC_EMOTE, GetCleanName(), buf);
|
GENERIC_EMOTE, GetCleanName(), buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::QuestJournalledSay(Client *QuestInitiator, const char *str)
|
void Mob::QuestJournalledSay(Client *QuestInitiator, const char *str, Journal::Options &opts)
|
||||||
{
|
{
|
||||||
entity_list.QuestJournalledSayClose(this, QuestInitiator, 200, GetCleanName(), str);
|
// just in case
|
||||||
|
if (opts.target_spawn_id == 0 && QuestInitiator)
|
||||||
|
opts.target_spawn_id = QuestInitiator->GetID();
|
||||||
|
|
||||||
|
entity_list.QuestJournalledSayClose(this, QuestInitiator, 200, GetCleanName(), str, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *Mob::GetCleanName()
|
const char *Mob::GetCleanName()
|
||||||
|
|||||||
@ -744,7 +744,7 @@ public:
|
|||||||
const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0);
|
const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0);
|
||||||
void Shout(const char *format, ...);
|
void Shout(const char *format, ...);
|
||||||
void Emote(const char *format, ...);
|
void Emote(const char *format, ...);
|
||||||
void QuestJournalledSay(Client *QuestInitiator, const char *str);
|
void QuestJournalledSay(Client *QuestInitiator, const char *str, Journal::Options &opts);
|
||||||
int32 GetItemStat(uint32 itemid, const char *identifier);
|
int32 GetItemStat(uint32 itemid, const char *identifier);
|
||||||
|
|
||||||
int16 CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, bool best_focus=false);
|
int16 CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, bool best_focus=false);
|
||||||
|
|||||||
@ -154,30 +154,19 @@ void QuestManager::echo(int colour, const char *str) {
|
|||||||
entity_list.MessageClose(initiator, false, 200, colour, str);
|
entity_list.MessageClose(initiator, false, 200, colour, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuestManager::say(const char *str) {
|
void QuestManager::say(const char *str, Journal::Options &opts) {
|
||||||
QuestManagerCurrentQuestVars();
|
QuestManagerCurrentQuestVars();
|
||||||
if (!owner) {
|
if (!owner) {
|
||||||
Log(Logs::General, Logs::Quests, "QuestManager::say called with nullptr owner. Probably syntax error in quest file.");
|
Log(Logs::General, Logs::Quests, "QuestManager::say called with nullptr owner. Probably syntax error in quest file.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(RuleB(NPC, EnableNPCQuestJournal) && initiator) {
|
if (!RuleB(NPC, EnableNPCQuestJournal))
|
||||||
owner->QuestJournalledSay(initiator, str);
|
opts.journal_mode = Journal::Mode::None;
|
||||||
|
if (initiator) {
|
||||||
|
opts.target_spawn_id = initiator->GetID();
|
||||||
|
owner->QuestJournalledSay(initiator, str, opts);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
owner->Say(str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QuestManager::say(const char *str, uint8 language) {
|
|
||||||
QuestManagerCurrentQuestVars();
|
|
||||||
if (!owner) {
|
|
||||||
Log(Logs::General, Logs::Quests, "QuestManager::say called with nullptr owner. Probably syntax error in quest file.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
entity_list.ChannelMessage(owner, 8, language, str);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -62,8 +62,7 @@ public:
|
|||||||
|
|
||||||
//quest functions
|
//quest functions
|
||||||
void echo(int colour, const char *str);
|
void echo(int colour, const char *str);
|
||||||
void say(const char *str);
|
void say(const char *str, Journal::Options &opts);
|
||||||
void say(const char *str, uint8 language);
|
|
||||||
void me(const char *str);
|
void me(const char *str);
|
||||||
void summonitem(uint32 itemid, int16 charges = -1);
|
void summonitem(uint32 itemid, int16 charges = -1);
|
||||||
void write(const char *file, const char *str);
|
void write(const char *file, const char *str);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user