mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-28 13:01:31 +00:00
Merge branch 'master' into nats
# Conflicts: # world/client.cpp # zone/attack.cpp # zone/map.cpp # zone/map.h # zone/spells.cpp
This commit is contained in:
commit
2270bd267d
@ -1,5 +1,25 @@
|
||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||
-------------------------------------------------------
|
||||
== 03/07/2018 ==
|
||||
Uleat: Added command '#ucs' to force a reconnect to UCS server.
|
||||
- Works in place of client auto-reconnect packet in zones where feature is unsupported
|
||||
- Currently, you will need to manually re-join channels
|
||||
|
||||
== 03/04/2018 ==
|
||||
Uleat: Updated UCS versioning
|
||||
- SoF and higher clients have a new opcode identified (update your *.conf files)
|
||||
- Rework of previous ucs connectivity code
|
||||
- Unrelated: Zone::weatherSend() now takes an optional parameter for singular updates (as in client entering zone)
|
||||
-- prior to this, every client already in-zone received a weather update packet whenever a new client zoned in
|
||||
|
||||
== 02/18/2018 ==
|
||||
Uleat: Bug reporting fix and overhaul.
|
||||
- Fixed bug reporting for SoD+ clients
|
||||
- Added ability to disable bug reporting (set rule 'Bugs:ReportingSystemActive' to 'false')
|
||||
- Implemented a more detailed reporting system (set rule 'Bugs:UseOldReportingMethod' to 'false')
|
||||
-- New system is not currently compatible with script-based monitoring
|
||||
- Soft-removal of defunct 'Petition Bug' system
|
||||
|
||||
== 02/14/2018 ==
|
||||
mackal: Fix Heading -- Quests broken
|
||||
|
||||
|
||||
@ -18,3 +18,68 @@
|
||||
*/
|
||||
|
||||
#include "emu_constants.h"
|
||||
|
||||
|
||||
const char* EQEmu::bug::CategoryIDToCategoryName(CategoryID category_id) {
|
||||
switch (category_id) {
|
||||
case catVideo:
|
||||
return "Video";
|
||||
case catAudio:
|
||||
return "Audio";
|
||||
case catPathing:
|
||||
return "Pathing";
|
||||
case catQuest:
|
||||
return "Quest";
|
||||
case catTradeskills:
|
||||
return "Tradeskills";
|
||||
case catSpellStacking:
|
||||
return "Spell stacking";
|
||||
case catDoorsPortals:
|
||||
return "Doors/Portals";
|
||||
case catItems:
|
||||
return "Items";
|
||||
case catNPC:
|
||||
return "NPC";
|
||||
case catDialogs:
|
||||
return "Dialogs";
|
||||
case catLoNTCG:
|
||||
return "LoN - TCG";
|
||||
case catMercenaries:
|
||||
return "Mercenaries";
|
||||
case catOther:
|
||||
default:
|
||||
return "Other";
|
||||
}
|
||||
}
|
||||
|
||||
EQEmu::bug::CategoryID EQEmu::bug::CategoryNameToCategoryID(const char* category_name) {
|
||||
if (!category_name)
|
||||
return catOther;
|
||||
|
||||
if (!strcmp(category_name, "Video"))
|
||||
return catVideo;
|
||||
if (!strcmp(category_name, "Audio"))
|
||||
return catAudio;
|
||||
if (!strcmp(category_name, "Pathing"))
|
||||
return catPathing;
|
||||
if (!strcmp(category_name, "Quest"))
|
||||
return catQuest;
|
||||
if (!strcmp(category_name, "Tradeskills"))
|
||||
return catTradeskills;
|
||||
if (!strcmp(category_name, "Spell stacking"))
|
||||
return catSpellStacking;
|
||||
if (!strcmp(category_name, "Doors/Portals"))
|
||||
return catDoorsPortals;
|
||||
if (!strcmp(category_name, "Items"))
|
||||
return catItems;
|
||||
if (!strcmp(category_name, "NPC"))
|
||||
return catNPC;
|
||||
if (!strcmp(category_name, "Dialogs"))
|
||||
return catDialogs;
|
||||
if (!strcmp(category_name, "LoN - TCG"))
|
||||
return catLoNTCG;
|
||||
if (!strcmp(category_name, "Mercenaries"))
|
||||
return catMercenaries;
|
||||
|
||||
return catOther;
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
#include "emu_legacy.h"
|
||||
#include "emu_versions.h"
|
||||
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
namespace EQEmu
|
||||
@ -114,7 +114,11 @@ namespace EQEmu
|
||||
const EQEmu::versions::ClientVersion CharacterCreationClient = EQEmu::versions::ClientVersion::RoF2;
|
||||
const size_t CharacterCreationMax = RoF2::constants::CharacterCreationLimit;
|
||||
|
||||
const size_t SayLinkOpenerSize = 1;
|
||||
const size_t SayLinkBodySize = RoF2::constants::SayLinkBodySize;
|
||||
const size_t SayLinkTextSize = 256; // this may be varied until it breaks something (tested:374) - the others are constant
|
||||
const size_t SayLinkCloserSize = 1;
|
||||
const size_t SayLinkMaximumSize = (SayLinkOpenerSize + SayLinkBodySize + SayLinkTextSize + SayLinkCloserSize);
|
||||
|
||||
const int LongBuffs = RoF2::constants::LongBuffs;
|
||||
const int ShortBuffs = RoF2::constants::ShortBuffs;
|
||||
@ -126,6 +130,37 @@ namespace EQEmu
|
||||
|
||||
} /*constants*/
|
||||
|
||||
namespace bug {
|
||||
enum CategoryID : uint32 {
|
||||
catOther = 0,
|
||||
catVideo,
|
||||
catAudio,
|
||||
catPathing,
|
||||
catQuest,
|
||||
catTradeskills,
|
||||
catSpellStacking,
|
||||
catDoorsPortals,
|
||||
catItems,
|
||||
catNPC,
|
||||
catDialogs,
|
||||
catLoNTCG,
|
||||
catMercenaries
|
||||
};
|
||||
|
||||
enum OptionalInfoFlag : uint32 {
|
||||
infoNoOptionalInfo = 0x0,
|
||||
infoCanDuplicate = 0x1,
|
||||
infoCrashBug = 0x2,
|
||||
infoTargetInfo = 0x4,
|
||||
infoCharacterFlags = 0x8,
|
||||
infoUnknownValue = 0xFFFFFFF0
|
||||
};
|
||||
|
||||
const char* CategoryIDToCategoryName(CategoryID category_id);
|
||||
CategoryID CategoryNameToCategoryID(const char* category_name);
|
||||
|
||||
} // namespace bug
|
||||
|
||||
enum class CastingSlot : uint32 {
|
||||
Gem1 = 0,
|
||||
Gem2 = 1,
|
||||
|
||||
@ -175,8 +175,6 @@ namespace EQEmu
|
||||
|
||||
// POTION_BELT_SIZE sets maximum limit..active limit will need to be handled by the appropriate AA or spell (or item?)
|
||||
static const size_t POTION_BELT_ITEM_COUNT = 5;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 56;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -393,6 +393,7 @@ N(OP_PVPLeaderBoardReply),
|
||||
N(OP_PVPLeaderBoardRequest),
|
||||
N(OP_PVPStats),
|
||||
N(OP_QueryResponseThing),
|
||||
N(OP_QueryUCSServerStatus),
|
||||
N(OP_RaidInvite),
|
||||
N(OP_RaidJoin),
|
||||
N(OP_RaidUpdate),
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
namespace EQEmu
|
||||
{
|
||||
namespace versions {
|
||||
enum class ClientVersion {
|
||||
enum class ClientVersion : uint32 {
|
||||
Unknown = 0,
|
||||
Client62, // Build: 'Aug 4 2005 15:40:59'
|
||||
Titanium, // Build: 'Oct 31 2005 10:33:37'
|
||||
@ -72,7 +72,7 @@ namespace EQEmu
|
||||
uint32 ConvertClientVersionToExpansion(ClientVersion client_version);
|
||||
|
||||
|
||||
enum class MobVersion {
|
||||
enum class MobVersion : uint32 {
|
||||
Unknown = 0,
|
||||
Client62,
|
||||
Titanium,
|
||||
@ -121,6 +121,20 @@ namespace EQEmu
|
||||
ClientVersion ConvertOfflinePCMobVersionToClientVersion(MobVersion mob_version);
|
||||
MobVersion ConvertClientVersionToOfflinePCMobVersion(ClientVersion client_version);
|
||||
|
||||
|
||||
enum UCSVersion : char {
|
||||
ucsUnknown = '\0',
|
||||
ucsClient62Chat = 'A',
|
||||
ucsClient62Mail = 'a',
|
||||
ucsTitaniumChat = 'B',
|
||||
ucsTitaniumMail = 'b',
|
||||
ucsSoFCombined = 'C',
|
||||
ucsSoDCombined = 'D',
|
||||
ucsUFCombined = 'E',
|
||||
ucsRoFCombined = 'F',
|
||||
ucsRoF2Combined = 'G'
|
||||
};
|
||||
|
||||
} /*versions*/
|
||||
|
||||
} /*EQEmu*/
|
||||
|
||||
@ -280,7 +280,7 @@ union
|
||||
// horse: 0=brown, 1=white, 2=black, 3=tan
|
||||
};
|
||||
/*0340*/ uint32 spawnId; // Spawn Id
|
||||
/*0344*/ uint8 unknown0344[3];
|
||||
/*0344*/ float bounding_radius; // used in melee, overrides calc
|
||||
/*0347*/ uint8 IsMercenary;
|
||||
/*0348*/ EQEmu::TintProfile equipment_tint;
|
||||
/*0384*/ uint8 lfg; // 0=off, 1=lfg on
|
||||
@ -1253,21 +1253,22 @@ struct Action_Struct
|
||||
{
|
||||
/* 00 */ uint16 target; // id of target
|
||||
/* 02 */ uint16 source; // id of caster
|
||||
/* 04 */ uint16 level; // level of caster
|
||||
/* 06 */ uint16 instrument_mod;
|
||||
/* 08 */ uint32 bard_focus_id;
|
||||
/* 12 */ uint16 unknown16;
|
||||
// some kind of sequence that's the same in both actions
|
||||
// as well as the combat damage, to tie em together?
|
||||
/* 14 */ uint32 sequence;
|
||||
/* 18 */ uint32 unknown18;
|
||||
/* 22 */ uint8 type; // 231 (0xE7) for spells
|
||||
/* 23 */ uint32 unknown23;
|
||||
/* 04 */ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
|
||||
/* 06 */ uint32 instrument_mod; // OSX dump says base damage, spells use it for bard song (different from newer clients)
|
||||
/* 10 */ float force;
|
||||
/* 14 */ float hit_heading;
|
||||
/* 18 */ float hit_pitch;
|
||||
/* 22 */ uint8 type; // 231 (0xE7) for spells, skill
|
||||
/* 23 */ uint16 unknown23; // OSX says min_damage
|
||||
/* 25 */ uint16 unknown25; // OSX says tohit
|
||||
/* 27 */ uint16 spell; // spell id being cast
|
||||
/* 29 */ uint8 unknown29;
|
||||
/* 29 */ uint8 spell_level;
|
||||
// this field seems to be some sort of success flag, if it's 4
|
||||
/* 30 */ uint8 buff_unknown; // if this is 4, a buff icon is made
|
||||
/* 31 */
|
||||
/* 30 */ uint8 effect_flag; // if this is 4, a buff icon is made
|
||||
// newer clients have some data for setting LaunchSpellData when effect_flag & 4
|
||||
// /* 31 */ uint8 spell_gem;
|
||||
// /* 32 */ uint32 inventory_slot;
|
||||
// /* 36 */ uint32 item_cast_type;
|
||||
};
|
||||
|
||||
// this is what prints the You have been struck. and the regular
|
||||
@ -1277,12 +1278,12 @@ struct CombatDamage_Struct
|
||||
{
|
||||
/* 00 */ uint16 target;
|
||||
/* 02 */ uint16 source;
|
||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells, skill
|
||||
/* 05 */ uint16 spellid;
|
||||
/* 07 */ uint32 damage;
|
||||
/* 11 */ float force;
|
||||
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
|
||||
/* 19 */ float meleepush_z;
|
||||
/* 15 */ float hit_heading; // see above notes in Action_Struct
|
||||
/* 19 */ float hit_pitch;
|
||||
/* 23 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
|
||||
};
|
||||
|
||||
@ -3323,23 +3324,32 @@ struct GuildMakeLeader{
|
||||
char target[64];
|
||||
};
|
||||
|
||||
struct BugStruct{
|
||||
/*0000*/ char chartype[64];
|
||||
/*0064*/ char name[96];
|
||||
/*0160*/ char ui[128];
|
||||
/*0288*/ float x;
|
||||
/*0292*/ float y;
|
||||
/*0296*/ float z;
|
||||
/*0300*/ float heading;
|
||||
/*0304*/ uint32 unknown304;
|
||||
/*0308*/ char unknown308[160];
|
||||
/*0468*/ char target_name[64];
|
||||
/*0532*/ uint32 type;
|
||||
/*0536*/ char unknown536[2052];
|
||||
/*2584*/ char bug[2048];
|
||||
/*4632*/ char unknown4632[6];
|
||||
/*4638*/ char system_info[4094];
|
||||
struct BugReport_Struct {
|
||||
/*0000*/ uint32 category_id;
|
||||
/*0004*/ char category_name[64];
|
||||
/*0068*/ char reporter_name[64];
|
||||
/*0132*/ char unused_0132[32];
|
||||
/*0164*/ char ui_path[128];
|
||||
/*0292*/ float pos_x;
|
||||
/*0296*/ float pos_y;
|
||||
/*0300*/ float pos_z;
|
||||
/*0304*/ uint32 heading;
|
||||
/*0308*/ uint32 unused_0308;
|
||||
/*0312*/ uint32 time_played;
|
||||
/*0316*/ char padding_0316[8];
|
||||
/*0324*/ uint32 target_id;
|
||||
/*0328*/ char padding_0328[140];
|
||||
/*0468*/ uint32 unknown_0468; // seems to always be '0'
|
||||
/*0472*/ char target_name[64];
|
||||
/*0536*/ uint32 optional_info_mask;
|
||||
|
||||
// this looks like a butchered 8k buffer with 2 trailing dword fields
|
||||
/*0540*/ char unused_0540[2052];
|
||||
/*2592*/ char bug_report[2050];
|
||||
/*4642*/ char system_info[4098];
|
||||
/*8740*/
|
||||
};
|
||||
|
||||
struct Make_Pet_Struct { //Simple struct for getting pet info
|
||||
uint8 level;
|
||||
uint8 class_;
|
||||
@ -3366,20 +3376,21 @@ struct Ground_Spawn{
|
||||
struct Ground_Spawns {
|
||||
struct Ground_Spawn spawn[50]; //Assigned max number to allow
|
||||
};
|
||||
struct PetitionBug_Struct{
|
||||
uint32 petition_number;
|
||||
uint32 unknown4;
|
||||
char accountname[64];
|
||||
uint32 zoneid;
|
||||
char name[64];
|
||||
uint32 level;
|
||||
uint32 class_;
|
||||
uint32 race;
|
||||
uint32 unknown152[3];
|
||||
uint32 time;
|
||||
uint32 unknown168;
|
||||
char text[1028];
|
||||
};
|
||||
|
||||
//struct PetitionBug_Struct{
|
||||
// uint32 petition_number;
|
||||
// uint32 unknown4;
|
||||
// char accountname[64];
|
||||
// uint32 zoneid;
|
||||
// char name[64];
|
||||
// uint32 level;
|
||||
// uint32 class_;
|
||||
// uint32 race;
|
||||
// uint32 unknown152[3];
|
||||
// uint32 time;
|
||||
// uint32 unknown168;
|
||||
// char text[1028];
|
||||
//};
|
||||
|
||||
struct ApproveZone_Struct {
|
||||
char name[64];
|
||||
@ -5356,6 +5367,23 @@ struct AuraDestory_Struct {
|
||||
};
|
||||
// I think we can assume it's just action for 2, client doesn't seem to do anything with the rest of the data in that case
|
||||
|
||||
struct SayLinkBodyFrame_Struct {
|
||||
/*000*/ char ActionID[1];
|
||||
/*001*/ char ItemID[5];
|
||||
/*006*/ char Augment1[5];
|
||||
/*011*/ char Augment2[5];
|
||||
/*016*/ char Augment3[5];
|
||||
/*021*/ char Augment4[5];
|
||||
/*026*/ char Augment5[5];
|
||||
/*031*/ char Augment6[5];
|
||||
/*036*/ char IsEvolving[1];
|
||||
/*037*/ char EvolveGroup[4];
|
||||
/*041*/ char EvolveLevel[2];
|
||||
/*043*/ char OrnamentIcon[5];
|
||||
/*048*/ char Hash[8];
|
||||
/*056*/
|
||||
};
|
||||
|
||||
// Restore structure packing to default
|
||||
#pragma pack()
|
||||
|
||||
|
||||
@ -219,6 +219,9 @@ enum { //some random constants
|
||||
//the square of the maximum range at whihc you could possibly use NPC services (shop, tribute, etc)
|
||||
#define USE_NPC_RANGE2 200*200 //arbitrary right now
|
||||
|
||||
// Squared range for rampage 75.0 * 75.0 for now
|
||||
#define NPC_RAMPAGE_RANGE2 5625.0f
|
||||
|
||||
//the formula for experience for killing a mob.
|
||||
//level is the only valid variable to use
|
||||
#define EXP_FORMULA level*level*75*35/10
|
||||
|
||||
@ -242,6 +242,24 @@ int FloatToEQSpeedRun(float d)
|
||||
return static_cast<int>(d * 40.0f);
|
||||
}
|
||||
|
||||
float FixHeading(float in)
|
||||
{
|
||||
int i = 0;
|
||||
if (in >= 512.0f) {
|
||||
do {
|
||||
in -= 512.0f;
|
||||
} while (in >= 512.0f && i++ <= 5);
|
||||
}
|
||||
i = 0;
|
||||
if (in < 0.0f) {
|
||||
do {
|
||||
in += 512.0f;
|
||||
} while (in < 0.0f && i++ <= 5);
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
/*
|
||||
Heading of 0 points in the pure positive Y direction
|
||||
|
||||
|
||||
@ -66,6 +66,9 @@ int FloatToEQ10(float d);
|
||||
float EQSpeedRunToFloat(int d);
|
||||
int FloatToEQSpeedRun(float d);
|
||||
|
||||
// brings heading back into EQ angles range
|
||||
float FixHeading(float in);
|
||||
|
||||
uint32 SwapBits21and22(uint32 mask);
|
||||
uint32 Catch22(uint32 mask);
|
||||
|
||||
|
||||
@ -165,7 +165,7 @@ void EQ::Net::DaybreakConnectionManager::ProcessResend()
|
||||
{
|
||||
auto iter = m_connections.begin();
|
||||
while (iter != m_connections.end()) {
|
||||
auto connection = iter->second;
|
||||
auto &connection = iter->second;
|
||||
auto status = connection->m_status;
|
||||
|
||||
switch (status)
|
||||
@ -1397,4 +1397,4 @@ EQ::Net::SequenceOrder EQ::Net::DaybreakConnection::CompareSequence(uint16_t exp
|
||||
}
|
||||
|
||||
return SequencePast;
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,11 +57,11 @@ namespace RoF
|
||||
static inline uint32 RoFToServerTypelessSlot(structs::TypelessInventorySlot_Struct rofSlot);
|
||||
static inline uint32 RoFToServerCorpseSlot(uint32 rofCorpseSlot);
|
||||
|
||||
// server to client text link converter
|
||||
static inline void ServerToRoFTextLink(std::string& rofTextLink, const std::string& serverTextLink);
|
||||
// server to client say link converter
|
||||
static inline void ServerToRoFSayLink(std::string& rofSayLink, const std::string& serverSayLink);
|
||||
|
||||
// client to server text link converter
|
||||
static inline void RoFToServerTextLink(std::string& serverTextLink, const std::string& rofTextLink);
|
||||
// client to server say link converter
|
||||
static inline void RoFToServerSayLink(std::string& serverSayLink, const std::string& rofSayLink);
|
||||
|
||||
static inline CastingSlot ServerToRoFCastingSlot(EQEmu::CastingSlot slot);
|
||||
static inline EQEmu::CastingSlot RoFToServerCastingSlot(CastingSlot slot);
|
||||
@ -163,22 +163,23 @@ namespace RoF
|
||||
OUT(level);
|
||||
eq->unknown06 = 0;
|
||||
eq->instrument_mod = 1.0f + (emu->instrument_mod - 10) / 10.0f;
|
||||
eq->bard_focus_id = emu->bard_focus_id;
|
||||
eq->knockback_angle = emu->sequence;
|
||||
eq->unknown22 = 0;
|
||||
OUT(force);
|
||||
OUT(hit_heading);
|
||||
OUT(hit_pitch);
|
||||
OUT(type);
|
||||
eq->damage = 0;
|
||||
eq->unknown31 = 0;
|
||||
OUT(spell);
|
||||
eq->level2 = eq->level;
|
||||
eq->effect_flag = emu->buff_unknown;
|
||||
eq->unknown39 = 14;
|
||||
eq->unknown43 = 0;
|
||||
eq->unknown44 = 17;
|
||||
eq->unknown45 = 0;
|
||||
eq->unknown46 = -1;
|
||||
eq->unknown50 = 0;
|
||||
eq->unknown54 = 0;
|
||||
OUT(spell_level);
|
||||
OUT(effect_flag);
|
||||
eq->spell_gem = 0;
|
||||
eq->slot.Type = INVALID_INDEX;
|
||||
eq->slot.Unknown02 = 0;
|
||||
eq->slot.Slot = INVALID_INDEX;
|
||||
eq->slot.SubIndex = INVALID_INDEX;
|
||||
eq->slot.AugIndex = INVALID_INDEX;
|
||||
eq->slot.Unknown01 = 0;
|
||||
eq->item_cast_type = 0;
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@ -520,7 +521,7 @@ namespace RoF
|
||||
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToRoFTextLink(new_message, old_message);
|
||||
ServerToRoFSayLink(new_message, old_message);
|
||||
|
||||
//in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36;
|
||||
in->size = strlen(emu->sender) + strlen(emu->targetname) + new_message.length() + 39;
|
||||
@ -659,8 +660,8 @@ namespace RoF
|
||||
OUT(spellid);
|
||||
OUT(damage);
|
||||
OUT(force);
|
||||
OUT(meleepush_xy);
|
||||
OUT(meleepush_z);
|
||||
OUT(hit_heading);
|
||||
OUT(hit_pitch);
|
||||
OUT(special);
|
||||
|
||||
FINISH_ENCODE();
|
||||
@ -847,7 +848,7 @@ namespace RoF
|
||||
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToRoFTextLink(new_message, old_message);
|
||||
ServerToRoFSayLink(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);
|
||||
@ -899,7 +900,7 @@ namespace RoF
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (old_message_array[i].length() == 0) { break; }
|
||||
ServerToRoFTextLink(new_message_array[i], old_message_array[i]);
|
||||
ServerToRoFSayLink(new_message_array[i], old_message_array[i]);
|
||||
new_message_size += new_message_array[i].length() + 1;
|
||||
}
|
||||
|
||||
@ -3295,7 +3296,7 @@ namespace RoF
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
|
||||
ServerToRoFTextLink(new_message, old_message);
|
||||
ServerToRoFSayLink(new_message, old_message);
|
||||
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
||||
@ -3369,7 +3370,7 @@ namespace RoF
|
||||
|
||||
std::string old_message = InBuffer; // start 'Reward' as string
|
||||
std::string new_message;
|
||||
ServerToRoFTextLink(new_message, old_message);
|
||||
ServerToRoFSayLink(new_message, old_message);
|
||||
|
||||
in->size = sizeof(TaskDescriptionHeader_Struct) + sizeof(TaskDescriptionData1_Struct)+
|
||||
sizeof(TaskDescriptionData2_Struct) + sizeof(TaskDescriptionTrailer_Struct)+
|
||||
@ -4355,7 +4356,7 @@ namespace RoF
|
||||
|
||||
std::string old_message = InBuffer;
|
||||
std::string new_message;
|
||||
RoFToServerTextLink(new_message, old_message);
|
||||
RoFToServerSayLink(new_message, old_message);
|
||||
|
||||
//__packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1;
|
||||
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
|
||||
@ -4466,7 +4467,7 @@ namespace RoF
|
||||
IN(type);
|
||||
IN(spellid);
|
||||
IN(damage);
|
||||
IN(meleepush_xy);
|
||||
IN(hit_heading);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@ -4489,7 +4490,7 @@ namespace RoF
|
||||
|
||||
std::string old_message = (char *)&__eq_buffer[4]; // unknown01 offset
|
||||
std::string new_message;
|
||||
RoFToServerTextLink(new_message, old_message);
|
||||
RoFToServerSayLink(new_message, old_message);
|
||||
|
||||
__packet->size = sizeof(Emote_Struct);
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
@ -5916,19 +5917,19 @@ namespace RoF
|
||||
return (rofCorpseSlot - 1);
|
||||
}
|
||||
|
||||
static inline void ServerToRoFTextLink(std::string& rofTextLink, const std::string& serverTextLink)
|
||||
static inline void ServerToRoFSayLink(std::string& rofSayLink, const std::string& serverSayLink)
|
||||
{
|
||||
if ((constants::SayLinkBodySize == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) {
|
||||
rofTextLink = serverTextLink;
|
||||
if ((constants::SayLinkBodySize == EQEmu::constants::SayLinkBodySize) || (serverSayLink.find('\x12') == std::string::npos)) {
|
||||
rofSayLink = serverSayLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(serverTextLink, '\x12');
|
||||
auto segments = SplitString(serverSayLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
if (segments[segment_iter].length() <= EQEmu::legacy::TEXT_LINK_BODY_LENGTH) {
|
||||
rofTextLink.append(segments[segment_iter]);
|
||||
if (segments[segment_iter].length() <= EQEmu::constants::SayLinkBodySize) {
|
||||
rofSayLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
@ -5938,36 +5939,36 @@ namespace RoF
|
||||
// RoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (55)
|
||||
// Diff: ^
|
||||
|
||||
rofTextLink.push_back('\x12');
|
||||
rofTextLink.append(segments[segment_iter].substr(0, 41));
|
||||
rofSayLink.push_back('\x12');
|
||||
rofSayLink.append(segments[segment_iter].substr(0, 41));
|
||||
|
||||
if (segments[segment_iter][41] == '0')
|
||||
rofTextLink.push_back(segments[segment_iter][42]);
|
||||
rofSayLink.push_back(segments[segment_iter][42]);
|
||||
else
|
||||
rofTextLink.push_back('F');
|
||||
rofSayLink.push_back('F');
|
||||
|
||||
rofTextLink.append(segments[segment_iter].substr(43));
|
||||
rofTextLink.push_back('\x12');
|
||||
rofSayLink.append(segments[segment_iter].substr(43));
|
||||
rofSayLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
rofTextLink.append(segments[segment_iter]);
|
||||
rofSayLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void RoFToServerTextLink(std::string& serverTextLink, const std::string& rofTextLink)
|
||||
static inline void RoFToServerSayLink(std::string& serverSayLink, const std::string& rofSayLink)
|
||||
{
|
||||
if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == constants::SayLinkBodySize) || (rofTextLink.find('\x12') == std::string::npos)) {
|
||||
serverTextLink = rofTextLink;
|
||||
if ((EQEmu::constants::SayLinkBodySize == constants::SayLinkBodySize) || (rofSayLink.find('\x12') == std::string::npos)) {
|
||||
serverSayLink = rofSayLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(rofTextLink, '\x12');
|
||||
auto segments = SplitString(rofSayLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
if (segments[segment_iter].length() <= constants::SayLinkBodySize) {
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
serverSayLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
@ -5977,14 +5978,14 @@ namespace RoF
|
||||
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
|
||||
// Diff: ^
|
||||
|
||||
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');
|
||||
serverSayLink.push_back('\x12');
|
||||
serverSayLink.append(segments[segment_iter].substr(0, 41));
|
||||
serverSayLink.push_back('0');
|
||||
serverSayLink.append(segments[segment_iter].substr(41));
|
||||
serverSayLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
serverSayLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,11 +57,11 @@ namespace RoF2
|
||||
static inline uint32 RoF2ToServerTypelessSlot(structs::TypelessInventorySlot_Struct rof2Slot);
|
||||
static inline uint32 RoF2ToServerCorpseSlot(uint32 rof2CorpseSlot);
|
||||
|
||||
// server to client text link converter
|
||||
static inline void ServerToRoF2TextLink(std::string& rof2TextLink, const std::string& serverTextLink);
|
||||
// server to client say link converter
|
||||
static inline void ServerToRoF2SayLink(std::string& rof2SayLink, const std::string& serverSayLink);
|
||||
|
||||
// client to server text link converter
|
||||
static inline void RoF2ToServerTextLink(std::string& serverTextLink, const std::string& rof2TextLink);
|
||||
// client to server say link converter
|
||||
static inline void RoF2ToServerSayLink(std::string& serverSayLink, const std::string& rof2SayLink);
|
||||
|
||||
static inline CastingSlot ServerToRoF2CastingSlot(EQEmu::CastingSlot slot);
|
||||
static inline EQEmu::CastingSlot RoF2ToServerCastingSlot(CastingSlot slot);
|
||||
@ -232,22 +232,23 @@ namespace RoF2
|
||||
OUT(level);
|
||||
eq->unknown06 = 0;
|
||||
eq->instrument_mod = 1.0f + (emu->instrument_mod - 10) / 10.0f;
|
||||
eq->bard_focus_id = emu->bard_focus_id;
|
||||
eq->knockback_angle = emu->sequence;
|
||||
eq->unknown22 = 0;
|
||||
OUT(force);
|
||||
OUT(hit_heading);
|
||||
OUT(hit_pitch);
|
||||
OUT(type);
|
||||
eq->damage = 0;
|
||||
eq->unknown31 = 0;
|
||||
OUT(spell);
|
||||
eq->level2 = eq->level;
|
||||
eq->effect_flag = emu->buff_unknown;
|
||||
eq->unknown39 = 14;
|
||||
eq->unknown43 = 0;
|
||||
eq->unknown44 = 17;
|
||||
eq->unknown45 = 0;
|
||||
eq->unknown46 = -1;
|
||||
eq->unknown50 = 0;
|
||||
eq->unknown54 = 0;
|
||||
OUT(spell_level);
|
||||
OUT(effect_flag);
|
||||
eq->spell_gem = 0;
|
||||
eq->slot.Type = INVALID_INDEX;
|
||||
eq->slot.Unknown02 = 0;
|
||||
eq->slot.Slot = INVALID_INDEX;
|
||||
eq->slot.SubIndex = INVALID_INDEX;
|
||||
eq->slot.AugIndex = INVALID_INDEX;
|
||||
eq->slot.Unknown01 = 0;
|
||||
eq->item_cast_type = 0;
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@ -588,7 +589,7 @@ namespace RoF2
|
||||
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToRoF2TextLink(new_message, old_message);
|
||||
ServerToRoF2SayLink(new_message, old_message);
|
||||
|
||||
//in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36;
|
||||
in->size = strlen(emu->sender) + strlen(emu->targetname) + new_message.length() + 39;
|
||||
@ -727,8 +728,8 @@ namespace RoF2
|
||||
OUT(spellid);
|
||||
OUT(damage);
|
||||
OUT(force);
|
||||
OUT(meleepush_xy);
|
||||
OUT(meleepush_z);
|
||||
OUT(hit_heading);
|
||||
OUT(hit_pitch);
|
||||
OUT(special);
|
||||
|
||||
FINISH_ENCODE();
|
||||
@ -915,7 +916,7 @@ namespace RoF2
|
||||
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToRoF2TextLink(new_message, old_message);
|
||||
ServerToRoF2SayLink(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);
|
||||
@ -967,7 +968,7 @@ namespace RoF2
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (old_message_array[i].length() == 0) { break; }
|
||||
ServerToRoF2TextLink(new_message_array[i], old_message_array[i]);
|
||||
ServerToRoF2SayLink(new_message_array[i], old_message_array[i]);
|
||||
new_message_size += new_message_array[i].length() + 1;
|
||||
}
|
||||
|
||||
@ -3364,7 +3365,7 @@ namespace RoF2
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
|
||||
ServerToRoF2TextLink(new_message, old_message);
|
||||
ServerToRoF2SayLink(new_message, old_message);
|
||||
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
||||
@ -3438,7 +3439,7 @@ namespace RoF2
|
||||
|
||||
std::string old_message = InBuffer; // start 'Reward' as string
|
||||
std::string new_message;
|
||||
ServerToRoF2TextLink(new_message, old_message);
|
||||
ServerToRoF2SayLink(new_message, old_message);
|
||||
|
||||
in->size = sizeof(TaskDescriptionHeader_Struct) + sizeof(TaskDescriptionData1_Struct)+
|
||||
sizeof(TaskDescriptionData2_Struct) + sizeof(TaskDescriptionTrailer_Struct)+
|
||||
@ -4595,7 +4596,7 @@ namespace RoF2
|
||||
|
||||
std::string old_message = InBuffer;
|
||||
std::string new_message;
|
||||
RoF2ToServerTextLink(new_message, old_message);
|
||||
RoF2ToServerSayLink(new_message, old_message);
|
||||
|
||||
//__packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1;
|
||||
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
|
||||
@ -4706,7 +4707,7 @@ namespace RoF2
|
||||
IN(type);
|
||||
IN(spellid);
|
||||
IN(damage);
|
||||
IN(meleepush_xy);
|
||||
IN(hit_heading);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@ -4729,7 +4730,7 @@ namespace RoF2
|
||||
|
||||
std::string old_message = (char *)&__eq_buffer[4]; // unknown01 offset
|
||||
std::string new_message;
|
||||
RoF2ToServerTextLink(new_message, old_message);
|
||||
RoF2ToServerSayLink(new_message, old_message);
|
||||
|
||||
__packet->size = sizeof(Emote_Struct);
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
@ -6233,19 +6234,19 @@ namespace RoF2
|
||||
return (rof2CorpseSlot + EQEmu::legacy::CORPSE_BEGIN - 1);
|
||||
}
|
||||
|
||||
static inline void ServerToRoF2TextLink(std::string& rof2TextLink, const std::string& serverTextLink)
|
||||
static inline void ServerToRoF2SayLink(std::string& rof2SayLink, const std::string& serverSayLink)
|
||||
{
|
||||
if ((constants::SayLinkBodySize == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) {
|
||||
rof2TextLink = serverTextLink;
|
||||
if ((constants::SayLinkBodySize == EQEmu::constants::SayLinkBodySize) || (serverSayLink.find('\x12') == std::string::npos)) {
|
||||
rof2SayLink = serverSayLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(serverTextLink, '\x12');
|
||||
auto segments = SplitString(serverSayLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
if (segments[segment_iter].length() <= EQEmu::legacy::TEXT_LINK_BODY_LENGTH) {
|
||||
rof2TextLink.append(segments[segment_iter]);
|
||||
if (segments[segment_iter].length() <= EQEmu::constants::SayLinkBodySize) {
|
||||
rof2SayLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
@ -6255,29 +6256,29 @@ namespace RoF2
|
||||
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
|
||||
// Diff:
|
||||
|
||||
rof2TextLink.push_back('\x12');
|
||||
rof2TextLink.append(segments[segment_iter]);
|
||||
rof2TextLink.push_back('\x12');
|
||||
rof2SayLink.push_back('\x12');
|
||||
rof2SayLink.append(segments[segment_iter]);
|
||||
rof2SayLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
rof2TextLink.append(segments[segment_iter]);
|
||||
rof2SayLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void RoF2ToServerTextLink(std::string& serverTextLink, const std::string& rof2TextLink)
|
||||
static inline void RoF2ToServerSayLink(std::string& serverSayLink, const std::string& rof2SayLink)
|
||||
{
|
||||
if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == constants::SayLinkBodySize) || (rof2TextLink.find('\x12') == std::string::npos)) {
|
||||
serverTextLink = rof2TextLink;
|
||||
if ((EQEmu::constants::SayLinkBodySize == constants::SayLinkBodySize) || (rof2SayLink.find('\x12') == std::string::npos)) {
|
||||
serverSayLink = rof2SayLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(rof2TextLink, '\x12');
|
||||
auto segments = SplitString(rof2SayLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
if (segments[segment_iter].length() <= constants::SayLinkBodySize) {
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
serverSayLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
@ -6287,12 +6288,12 @@ namespace RoF2
|
||||
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
|
||||
// Diff:
|
||||
|
||||
serverTextLink.push_back('\x12');
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
serverTextLink.push_back('\x12');
|
||||
serverSayLink.push_back('\x12');
|
||||
serverSayLink.append(segments[segment_iter]);
|
||||
serverSayLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
serverSayLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -430,7 +430,7 @@ struct Spawn_Struct
|
||||
/*0000*/ //uint8 nullterm1; // hack to null terminate name
|
||||
/*0064*/ uint32 spawnId;
|
||||
/*0068*/ uint8 level;
|
||||
/*0069*/ float unknown1;
|
||||
/*0069*/ float bounding_radius; // used in melee, overrides calc
|
||||
/*0073*/ uint8 NPC; // 0=player,1=npc,2=pc corpse,3=npc corpse
|
||||
Spawn_Struct_Bitfields Bitfields;
|
||||
/*0000*/ uint8 otherData; // & 4 - has title, & 8 - has suffix, & 1 - it's a chest or untargetable
|
||||
@ -1462,17 +1462,17 @@ struct Action_Struct
|
||||
{
|
||||
/*00*/ uint16 target; // id of target
|
||||
/*02*/ uint16 source; // id of caster
|
||||
/*04*/ uint16 level; // level of caster - Seen 0
|
||||
/*06*/ uint32 unknown06;
|
||||
/*04*/ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
|
||||
/*06*/ uint32 unknown06; // OSX dump says base_damage, was used for bard mod too, this is 0'd :(
|
||||
/*10*/ float instrument_mod;
|
||||
/*14*/ uint32 bard_focus_id; // seen 0
|
||||
/*18*/ float knockback_angle; //seems to go from 0-512 then it rolls over again
|
||||
/*22*/ uint32 unknown22;
|
||||
/*26*/ uint8 type;
|
||||
/*27*/ uint32 damage;
|
||||
/*31*/ uint16 unknown31;
|
||||
/*14*/ float force;
|
||||
/*18*/ float hit_heading;
|
||||
/*22*/ float hit_pitch;
|
||||
/*26*/ uint8 type; // 231 (0xE7) for spells, skill
|
||||
/*27*/ uint32 damage; // OSX says min_damage
|
||||
/*31*/ uint16 unknown31; // OSX says tohit
|
||||
/*33*/ uint32 spell; // spell id being cast
|
||||
/*37*/ uint8 level2; // level of caster again? Or maybe the castee
|
||||
/*37*/ uint8 spell_level; // level of caster again? Or maybe the castee
|
||||
/*38*/ uint8 effect_flag; // if this is 4, the effect is valid: or if two are sent at the same time?
|
||||
/*39*/
|
||||
};
|
||||
@ -1484,25 +1484,21 @@ struct ActionAlt_Struct
|
||||
{
|
||||
/*00*/ uint16 target; // id of target
|
||||
/*02*/ uint16 source; // id of caster
|
||||
/*04*/ uint16 level; // level of caster - Seen 0
|
||||
/*06*/ uint32 unknown06;
|
||||
/*04*/ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
|
||||
/*06*/ uint32 unknown06; // OSX dump says base_damage, was used for bard mod too, this is 0'd :(
|
||||
/*10*/ float instrument_mod;
|
||||
/*14*/ uint32 bard_focus_id; // seen 0
|
||||
/*18*/ float knockback_angle; //seems to go from 0-512 then it rolls over again
|
||||
/*22*/ uint32 unknown22;
|
||||
/*26*/ uint8 type;
|
||||
/*27*/ uint32 damage;
|
||||
/*31*/ uint16 unknown31;
|
||||
/*14*/ float force;
|
||||
/*18*/ float hit_heading;
|
||||
/*22*/ float hit_pitch;
|
||||
/*26*/ uint8 type; // 231 (0xE7) for spells, skill
|
||||
/*27*/ uint32 damage; // OSX says min_damage
|
||||
/*31*/ uint16 unknown31; // OSX says tohit
|
||||
/*33*/ uint32 spell; // spell id being cast
|
||||
/*37*/ uint8 level2; // level of caster again? Or maybe the castee
|
||||
/*37*/ uint8 spell_level; // level of caster again? Or maybe the castee
|
||||
/*38*/ uint8 effect_flag; // if this is 4, the effect is valid: or if two are sent at the same time?
|
||||
/*39*/ uint32 unknown39; // New field to Underfoot - Seen 14
|
||||
/*43*/ uint8 unknown43; // New field to Underfoot - Seen 0
|
||||
/*44*/ uint8 unknown44; // New field to Underfoot - Seen 17
|
||||
/*45*/ uint8 unknown45; // New field to Underfoot - Seen 0
|
||||
/*46*/ int32 unknown46; // New field to Underfoot - Seen -1
|
||||
/*50*/ uint32 unknown50; // New field to Underfoot - Seen 0
|
||||
/*54*/ uint16 unknown54; // New field to Underfoot - Seen 0
|
||||
/*39*/ uint8 spell_gem;
|
||||
/*40*/ InventorySlot_Struct slot;
|
||||
/*52*/ uint32 item_cast_type; // ItemSpellTypes enum from MQ2
|
||||
/*56*/
|
||||
};
|
||||
|
||||
@ -1517,9 +1513,9 @@ struct CombatDamage_Struct
|
||||
/* 05 */ uint32 spellid;
|
||||
/* 09 */ int32 damage;
|
||||
/* 13 */ float force; // cd cc cc 3d
|
||||
/* 17 */ float meleepush_xy; // see above notes in Action_Struct
|
||||
/* 21 */ float meleepush_z;
|
||||
/* 25 */ uint8 unknown25; // was [9]
|
||||
/* 17 */ float hit_heading; // see above notes in Action_Struct
|
||||
/* 21 */ float hit_pitch;
|
||||
/* 25 */ uint8 secondary; // 0 for primary hand, 1 for secondary
|
||||
/* 26 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
|
||||
/* 30 */
|
||||
};
|
||||
@ -3605,21 +3601,6 @@ struct GuildSetRank_Struct
|
||||
/*80*/
|
||||
};
|
||||
|
||||
struct BugStruct{
|
||||
/*0000*/ char chartype[64];
|
||||
/*0064*/ char name[96];
|
||||
/*0160*/ char ui[128];
|
||||
/*0288*/ float x;
|
||||
/*0292*/ float y;
|
||||
/*0296*/ float z;
|
||||
/*0300*/ float heading;
|
||||
/*0304*/ uint32 unknown304;
|
||||
/*0308*/ uint32 type;
|
||||
/*0312*/ char unknown312[2144];
|
||||
/*2456*/ char bug[1024];
|
||||
/*3480*/ char placeholder[2];
|
||||
/*3482*/ char system_info[4098];
|
||||
};
|
||||
struct Make_Pet_Struct { //Simple struct for getting pet info
|
||||
uint8 level;
|
||||
uint8 class_;
|
||||
@ -3646,20 +3627,21 @@ struct Ground_Spawn{
|
||||
struct Ground_Spawns {
|
||||
struct Ground_Spawn spawn[50]; //Assigned max number to allow
|
||||
};
|
||||
struct PetitionBug_Struct{
|
||||
uint32 petition_number;
|
||||
uint32 unknown4;
|
||||
char accountname[64];
|
||||
uint32 zoneid;
|
||||
char name[64];
|
||||
uint32 level;
|
||||
uint32 class_;
|
||||
uint32 race;
|
||||
uint32 unknown152[3];
|
||||
uint32 time;
|
||||
uint32 unknown168;
|
||||
char text[1028];
|
||||
};
|
||||
|
||||
//struct PetitionBug_Struct{
|
||||
// uint32 petition_number;
|
||||
// uint32 unknown4;
|
||||
// char accountname[64];
|
||||
// uint32 zoneid;
|
||||
// char name[64];
|
||||
// uint32 level;
|
||||
// uint32 class_;
|
||||
// uint32 race;
|
||||
// uint32 unknown152[3];
|
||||
// uint32 time;
|
||||
// uint32 unknown168;
|
||||
// char text[1028];
|
||||
//};
|
||||
|
||||
struct ApproveZone_Struct {
|
||||
char name[64];
|
||||
@ -5103,6 +5085,23 @@ struct CrystalCountUpdate_Struct
|
||||
/*012*/ uint32 CareerEbonCrystals;
|
||||
};
|
||||
|
||||
struct SayLinkBodyFrame_Struct {
|
||||
/*000*/ char ActionID[1];
|
||||
/*001*/ char ItemID[5];
|
||||
/*006*/ char Augment1[5];
|
||||
/*011*/ char Augment2[5];
|
||||
/*016*/ char Augment3[5];
|
||||
/*021*/ char Augment4[5];
|
||||
/*026*/ char Augment5[5];
|
||||
/*031*/ char Augment6[5];
|
||||
/*036*/ char IsEvolving[1];
|
||||
/*037*/ char EvolveGroup[4];
|
||||
/*041*/ char EvolveLevel[2];
|
||||
/*043*/ char OrnamentIcon[5];
|
||||
/*048*/ char Hash[8];
|
||||
/*056*/
|
||||
};
|
||||
|
||||
}; /*structs*/
|
||||
|
||||
}; /*RoF2*/
|
||||
|
||||
@ -408,7 +408,7 @@ struct Spawn_Struct
|
||||
/*0000*/ //uint8 nullterm1; // hack to null terminate name
|
||||
/*0064*/ uint32 spawnId;
|
||||
/*0068*/ uint8 level;
|
||||
/*0069*/ float unknown1;
|
||||
/*0069*/ float bounding_radius; // used in melee, overrides calc
|
||||
/*0073*/ uint8 NPC; // 0=player,1=npc,2=pc corpse,3=npc corpse
|
||||
Spawn_Struct_Bitfields Bitfields;
|
||||
/*0000*/ uint8 otherData; // & 4 - has title, & 8 - has suffix, & 1 - it's a chest or untargetable
|
||||
@ -1450,17 +1450,17 @@ struct Action_Struct
|
||||
{
|
||||
/*00*/ uint16 target; // id of target
|
||||
/*02*/ uint16 source; // id of caster
|
||||
/*04*/ uint16 level; // level of caster - Seen 0
|
||||
/*06*/ uint32 unknown06;
|
||||
/*04*/ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
|
||||
/*06*/ uint32 unknown06; // OSX dump says base_damage, was used for bard mod too, this is 0'd :(
|
||||
/*10*/ float instrument_mod;
|
||||
/*14*/ uint32 bard_focus_id; // seen 0
|
||||
/*18*/ float knockback_angle; //seems to go from 0-512 then it rolls over again
|
||||
/*22*/ uint32 unknown22;
|
||||
/*26*/ uint8 type;
|
||||
/*27*/ uint32 damage;
|
||||
/*31*/ uint16 unknown31;
|
||||
/*14*/ float force;
|
||||
/*18*/ float hit_heading;
|
||||
/*22*/ float hit_pitch;
|
||||
/*26*/ uint8 type; // 231 (0xE7) for spells, skill
|
||||
/*27*/ uint32 damage; // OSX says min_damage
|
||||
/*31*/ uint16 unknown31; // OSX says tohit
|
||||
/*33*/ uint32 spell; // spell id being cast
|
||||
/*37*/ uint8 level2; // level of caster again? Or maybe the castee
|
||||
/*37*/ uint8 spell_level; // level of caster again? Or maybe the castee
|
||||
/*38*/ uint8 effect_flag; // if this is 4, the effect is valid: or if two are sent at the same time?
|
||||
/*39*/
|
||||
};
|
||||
@ -1472,25 +1472,21 @@ struct ActionAlt_Struct
|
||||
{
|
||||
/*00*/ uint16 target; // id of target
|
||||
/*02*/ uint16 source; // id of caster
|
||||
/*04*/ uint16 level; // level of caster - Seen 0
|
||||
/*06*/ uint32 unknown06;
|
||||
/*04*/ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
|
||||
/*06*/ uint32 unknown06; // OSX dump says base_damage, was used for bard mod too, this is 0'd :(
|
||||
/*10*/ float instrument_mod;
|
||||
/*14*/ uint32 bard_focus_id; // seen 0
|
||||
/*18*/ float knockback_angle; //seems to go from 0-512 then it rolls over again
|
||||
/*22*/ uint32 unknown22;
|
||||
/*26*/ uint8 type;
|
||||
/*27*/ uint32 damage;
|
||||
/*31*/ uint16 unknown31;
|
||||
/*14*/ float force;
|
||||
/*18*/ float hit_heading;
|
||||
/*22*/ float hit_pitch;
|
||||
/*26*/ uint8 type; // 231 (0xE7) for spells, skill
|
||||
/*27*/ uint32 damage; // OSX says min_damage
|
||||
/*31*/ uint16 unknown31; // OSX says tohit
|
||||
/*33*/ uint32 spell; // spell id being cast
|
||||
/*37*/ uint8 level2; // level of caster again? Or maybe the castee
|
||||
/*37*/ uint8 spell_level; // level of caster again? Or maybe the castee
|
||||
/*38*/ uint8 effect_flag; // if this is 4, the effect is valid: or if two are sent at the same time?
|
||||
/*39*/ uint32 unknown39; // New field to Underfoot - Seen 14
|
||||
/*43*/ uint8 unknown43; // New field to Underfoot - Seen 0
|
||||
/*44*/ uint8 unknown44; // New field to Underfoot - Seen 17
|
||||
/*45*/ uint8 unknown45; // New field to Underfoot - Seen 0
|
||||
/*46*/ int32 unknown46; // New field to Underfoot - Seen -1
|
||||
/*50*/ uint32 unknown50; // New field to Underfoot - Seen 0
|
||||
/*54*/ uint16 unknown54; // New field to Underfoot - Seen 0
|
||||
/*39*/ uint8 spell_gem;
|
||||
/*40*/ InventorySlot_Struct slot;
|
||||
/*52*/ uint32 item_cast_type; // ItemSpellTypes enum from MQ2
|
||||
/*56*/
|
||||
};
|
||||
|
||||
@ -1505,9 +1501,9 @@ struct CombatDamage_Struct
|
||||
/* 05 */ uint32 spellid;
|
||||
/* 09 */ int32 damage;
|
||||
/* 13 */ float force; // cd cc cc 3d
|
||||
/* 17 */ float meleepush_xy; // see above notes in Action_Struct
|
||||
/* 21 */ float meleepush_z;
|
||||
/* 25 */ uint8 unknown25; // was [9]
|
||||
/* 17 */ float hit_heading; // see above notes in Action_Struct
|
||||
/* 21 */ float hit_pitch;
|
||||
/* 25 */ uint8 secondary; // 0 for primary hand, 1 for secondary
|
||||
/* 26 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
|
||||
/* 30 */
|
||||
};
|
||||
@ -3545,21 +3541,6 @@ struct GuildSetRank_Struct
|
||||
/*80*/
|
||||
};
|
||||
|
||||
struct BugStruct{
|
||||
/*0000*/ char chartype[64];
|
||||
/*0064*/ char name[96];
|
||||
/*0160*/ char ui[128];
|
||||
/*0288*/ float x;
|
||||
/*0292*/ float y;
|
||||
/*0296*/ float z;
|
||||
/*0300*/ float heading;
|
||||
/*0304*/ uint32 unknown304;
|
||||
/*0308*/ uint32 type;
|
||||
/*0312*/ char unknown312[2144];
|
||||
/*2456*/ char bug[1024];
|
||||
/*3480*/ char placeholder[2];
|
||||
/*3482*/ char system_info[4098];
|
||||
};
|
||||
struct Make_Pet_Struct { //Simple struct for getting pet info
|
||||
uint8 level;
|
||||
uint8 class_;
|
||||
@ -3586,20 +3567,21 @@ struct Ground_Spawn{
|
||||
struct Ground_Spawns {
|
||||
struct Ground_Spawn spawn[50]; //Assigned max number to allow
|
||||
};
|
||||
struct PetitionBug_Struct{
|
||||
uint32 petition_number;
|
||||
uint32 unknown4;
|
||||
char accountname[64];
|
||||
uint32 zoneid;
|
||||
char name[64];
|
||||
uint32 level;
|
||||
uint32 class_;
|
||||
uint32 race;
|
||||
uint32 unknown152[3];
|
||||
uint32 time;
|
||||
uint32 unknown168;
|
||||
char text[1028];
|
||||
};
|
||||
|
||||
//struct PetitionBug_Struct{
|
||||
// uint32 petition_number;
|
||||
// uint32 unknown4;
|
||||
// char accountname[64];
|
||||
// uint32 zoneid;
|
||||
// char name[64];
|
||||
// uint32 level;
|
||||
// uint32 class_;
|
||||
// uint32 race;
|
||||
// uint32 unknown152[3];
|
||||
// uint32 time;
|
||||
// uint32 unknown168;
|
||||
// char text[1028];
|
||||
//};
|
||||
|
||||
struct ApproveZone_Struct {
|
||||
char name[64];
|
||||
@ -5020,6 +5002,23 @@ struct MercenaryMerchantRequest_Struct {
|
||||
struct MercenaryMerchantResponse_Struct {
|
||||
/*0000*/ uint32 ResponseType;
|
||||
/*0004*/
|
||||
};
|
||||
|
||||
struct SayLinkBodyFrame_Struct {
|
||||
/*000*/ char ActionID[1];
|
||||
/*001*/ char ItemID[5];
|
||||
/*006*/ char Augment1[5];
|
||||
/*011*/ char Augment2[5];
|
||||
/*016*/ char Augment3[5];
|
||||
/*021*/ char Augment4[5];
|
||||
/*026*/ char Augment5[5];
|
||||
/*031*/ char Augment6[5];
|
||||
/*036*/ char IsEvolving[1];
|
||||
/*037*/ char EvolveGroup[4];
|
||||
/*041*/ char EvolveLevel[1];
|
||||
/*042*/ char OrnamentIcon[5];
|
||||
/*047*/ char Hash[8];
|
||||
/*055*/
|
||||
};
|
||||
|
||||
}; /*structs*/
|
||||
|
||||
@ -53,11 +53,11 @@ namespace SoD
|
||||
static inline uint32 SoDToServerSlot(uint32 sodSlot);
|
||||
static inline uint32 SoDToServerCorpseSlot(uint32 sodCorpseSlot);
|
||||
|
||||
// server to client text link converter
|
||||
static inline void ServerToSoDTextLink(std::string& sodTextLink, const std::string& serverTextLink);
|
||||
// server to client say link converter
|
||||
static inline void ServerToSoDSayLink(std::string& sodSayLink, const std::string& serverSayLink);
|
||||
|
||||
// client to server text link converter
|
||||
static inline void SoDToServerTextLink(std::string& serverTextLink, const std::string& sodTextLink);
|
||||
// client to server say link converter
|
||||
static inline void SoDToServerSayLink(std::string& serverSayLink, const std::string& sodSayLink);
|
||||
|
||||
static inline CastingSlot ServerToSoDCastingSlot(EQEmu::CastingSlot slot);
|
||||
static inline EQEmu::CastingSlot SoDToServerCastingSlot(CastingSlot slot);
|
||||
@ -161,15 +161,14 @@ namespace SoD
|
||||
OUT(source);
|
||||
OUT(level);
|
||||
OUT(instrument_mod);
|
||||
eq->sequence = emu->sequence;
|
||||
OUT(force);
|
||||
OUT(hit_heading);
|
||||
OUT(hit_pitch);
|
||||
OUT(type);
|
||||
//OUT(damage);
|
||||
OUT(spell);
|
||||
eq->level2 = emu->level;
|
||||
OUT(buff_unknown); // if this is 4, a buff icon is made
|
||||
//eq->unknown0036 = -1;
|
||||
//eq->unknown0040 = -1;
|
||||
//eq->unknown0044 = -1;
|
||||
OUT(spell_level);
|
||||
OUT(effect_flag); // if this is 4, a buff icon is made
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@ -346,7 +345,7 @@ namespace SoD
|
||||
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToSoDTextLink(new_message, old_message);
|
||||
ServerToSoDSayLink(new_message, old_message);
|
||||
|
||||
in->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
|
||||
|
||||
@ -458,8 +457,8 @@ namespace SoD
|
||||
OUT(spellid);
|
||||
OUT(damage);
|
||||
OUT(force);
|
||||
OUT(meleepush_xy);
|
||||
OUT(meleepush_z);
|
||||
OUT(hit_heading);
|
||||
OUT(hit_pitch);
|
||||
OUT(special);
|
||||
|
||||
FINISH_ENCODE();
|
||||
@ -625,7 +624,7 @@ namespace SoD
|
||||
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToSoDTextLink(new_message, old_message);
|
||||
ServerToSoDSayLink(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);
|
||||
@ -677,7 +676,7 @@ namespace SoD
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (old_message_array[i].length() == 0) { break; }
|
||||
ServerToSoDTextLink(new_message_array[i], old_message_array[i]);
|
||||
ServerToSoDSayLink(new_message_array[i], old_message_array[i]);
|
||||
new_message_size += new_message_array[i].length() + 1;
|
||||
}
|
||||
|
||||
@ -2156,7 +2155,7 @@ namespace SoD
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
|
||||
ServerToSoDTextLink(new_message, old_message);
|
||||
ServerToSoDSayLink(new_message, old_message);
|
||||
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
||||
@ -2252,7 +2251,7 @@ namespace SoD
|
||||
|
||||
std::string old_message = InBuffer; // start 'Reward' as string
|
||||
std::string new_message;
|
||||
ServerToSoDTextLink(new_message, old_message);
|
||||
ServerToSoDSayLink(new_message, old_message);
|
||||
|
||||
in->size = sizeof(TaskDescriptionHeader_Struct) + sizeof(TaskDescriptionData1_Struct)+
|
||||
sizeof(TaskDescriptionData2_Struct) + sizeof(TaskDescriptionTrailer_Struct)+
|
||||
@ -2933,25 +2932,6 @@ namespace SoD
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_Bug)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::BugStruct);
|
||||
SETUP_DIRECT_DECODE(BugStruct, structs::BugStruct);
|
||||
|
||||
strn0cpy(emu->chartype, eq->chartype, sizeof(emu->chartype));
|
||||
strn0cpy(emu->name, eq->name, sizeof(emu->name));
|
||||
strn0cpy(emu->ui, eq->ui, sizeof(emu->ui));
|
||||
IN(x);
|
||||
IN(y);
|
||||
IN(z);
|
||||
IN(heading);
|
||||
strn0cpy(emu->target_name, eq->target_name, sizeof(emu->target_name));
|
||||
strn0cpy(emu->bug, eq->bug, sizeof(emu->bug));
|
||||
strn0cpy(emu->system_info, eq->system_info, sizeof(emu->system_info));
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_CastSpell)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::CastSpell_Struct);
|
||||
@ -2972,7 +2952,7 @@ namespace SoD
|
||||
|
||||
std::string old_message = (char *)&__eq_buffer[sizeof(ChannelMessage_Struct)];
|
||||
std::string new_message;
|
||||
SoDToServerTextLink(new_message, old_message);
|
||||
SoDToServerSayLink(new_message, old_message);
|
||||
|
||||
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
@ -3086,7 +3066,7 @@ namespace SoD
|
||||
|
||||
std::string old_message = (char *)&__eq_buffer[4]; // unknown01 offset
|
||||
std::string new_message;
|
||||
SoDToServerTextLink(new_message, old_message);
|
||||
SoDToServerSayLink(new_message, old_message);
|
||||
|
||||
__packet->size = sizeof(Emote_Struct);
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
@ -3936,19 +3916,19 @@ namespace SoD
|
||||
return (sodCorpseSlot - 1);
|
||||
}
|
||||
|
||||
static inline void ServerToSoDTextLink(std::string& sodTextLink, const std::string& serverTextLink)
|
||||
static inline void ServerToSoDSayLink(std::string& sodSayLink, const std::string& serverSayLink)
|
||||
{
|
||||
if ((constants::SayLinkBodySize == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) {
|
||||
sodTextLink = serverTextLink;
|
||||
if ((constants::SayLinkBodySize == EQEmu::constants::SayLinkBodySize) || (serverSayLink.find('\x12') == std::string::npos)) {
|
||||
sodSayLink = serverSayLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(serverTextLink, '\x12');
|
||||
auto segments = SplitString(serverSayLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
if (segments[segment_iter].length() <= EQEmu::legacy::TEXT_LINK_BODY_LENGTH) {
|
||||
sodTextLink.append(segments[segment_iter]);
|
||||
if (segments[segment_iter].length() <= EQEmu::constants::SayLinkBodySize) {
|
||||
sodSayLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
@ -3958,37 +3938,37 @@ namespace SoD
|
||||
// SoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (50)
|
||||
// Diff: ^^^^^ ^
|
||||
|
||||
sodTextLink.push_back('\x12');
|
||||
sodTextLink.append(segments[segment_iter].substr(0, 31));
|
||||
sodTextLink.append(segments[segment_iter].substr(36, 5));
|
||||
sodSayLink.push_back('\x12');
|
||||
sodSayLink.append(segments[segment_iter].substr(0, 31));
|
||||
sodSayLink.append(segments[segment_iter].substr(36, 5));
|
||||
|
||||
if (segments[segment_iter][41] == '0')
|
||||
sodTextLink.push_back(segments[segment_iter][42]);
|
||||
sodSayLink.push_back(segments[segment_iter][42]);
|
||||
else
|
||||
sodTextLink.push_back('F');
|
||||
sodSayLink.push_back('F');
|
||||
|
||||
sodTextLink.append(segments[segment_iter].substr(43));
|
||||
sodTextLink.push_back('\x12');
|
||||
sodSayLink.append(segments[segment_iter].substr(43));
|
||||
sodSayLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
sodTextLink.append(segments[segment_iter]);
|
||||
sodSayLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SoDToServerTextLink(std::string& serverTextLink, const std::string& sodTextLink)
|
||||
static inline void SoDToServerSayLink(std::string& serverSayLink, const std::string& sodSayLink)
|
||||
{
|
||||
if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == constants::SayLinkBodySize) || (sodTextLink.find('\x12') == std::string::npos)) {
|
||||
serverTextLink = sodTextLink;
|
||||
if ((EQEmu::constants::SayLinkBodySize == constants::SayLinkBodySize) || (sodSayLink.find('\x12') == std::string::npos)) {
|
||||
serverSayLink = sodSayLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(sodTextLink, '\x12');
|
||||
auto segments = SplitString(sodSayLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
if (segments[segment_iter].length() <= constants::SayLinkBodySize) {
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
serverSayLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
@ -3998,16 +3978,16 @@ namespace SoD
|
||||
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
|
||||
// Diff: ^^^^^ ^
|
||||
|
||||
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');
|
||||
serverSayLink.push_back('\x12');
|
||||
serverSayLink.append(segments[segment_iter].substr(0, 31));
|
||||
serverSayLink.append("00000");
|
||||
serverSayLink.append(segments[segment_iter].substr(31, 5));
|
||||
serverSayLink.push_back('0');
|
||||
serverSayLink.append(segments[segment_iter].substr(36));
|
||||
serverSayLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
serverSayLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,7 +104,6 @@ D(OP_AugmentInfo)
|
||||
D(OP_AugmentItem)
|
||||
D(OP_BazaarSearch)
|
||||
D(OP_Buff)
|
||||
D(OP_Bug)
|
||||
D(OP_CastSpell)
|
||||
D(OP_ChannelMessage)
|
||||
D(OP_CharacterCreate)
|
||||
|
||||
@ -292,7 +292,7 @@ struct Spawn_Struct
|
||||
/*0000*/ //uint8 nullterm1; // hack to null terminate name
|
||||
/*0064*/ uint32 spawnId;
|
||||
/*0068*/ uint8 level;
|
||||
/*0069*/ float unknown1;
|
||||
/*0069*/ float bounding_radius; // used in melee, overrides calc
|
||||
/*0073*/ uint8 NPC; // 0=player,1=npc,2=pc corpse,3=npc corpse
|
||||
Spawn_Struct_Bitfields Bitfields;
|
||||
/*0000*/ uint8 otherData; // & 4 - has title, & 8 - has suffix, & 1 - it's a chest or untargetable
|
||||
@ -1215,20 +1215,18 @@ struct Action_Struct
|
||||
{
|
||||
/* 00 */ uint16 target; // id of target
|
||||
/* 02 */ uint16 source; // id of caster
|
||||
/* 04 */ uint16 level; // level of caster
|
||||
/* 06 */ uint16 instrument_mod; // seems to be fixed to 0x0A
|
||||
/* 08 */ uint32 unknown08;
|
||||
/* 12 */ uint16 unknown16;
|
||||
// some kind of sequence that's the same in both actions
|
||||
// as well as the combat damage, to tie em together?
|
||||
/* 14 */ float sequence; // was uint32
|
||||
/* 18 */ uint32 unknown18;
|
||||
/* 22 */ uint8 type; // 231 (0xE7) for spells
|
||||
/* 23 */ uint32 unknown23;
|
||||
/* 04 */ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
|
||||
/* 06 */ uint32 instrument_mod; // OSX dump says base damage, spells use it for bard song (different from newer clients)
|
||||
/* 10 */ float force;
|
||||
/* 14 */ float hit_heading;
|
||||
/* 18 */ float hit_pitch;
|
||||
/* 22 */ uint8 type; // 231 (0xE7) for spells, skill
|
||||
/* 23 */ uint16 unknown23; // OSX says min_damage
|
||||
/* 25 */ uint16 unknown25; // OSX says tohit
|
||||
/* 27 */ uint16 spell; // spell id being cast
|
||||
/* 29 */ uint8 level2; // level of caster again? Or maybe the castee
|
||||
/* 29 */ uint8 spell_level; // level of caster again? Or maybe the castee
|
||||
// this field seems to be some sort of success flag, if it's 4
|
||||
/* 30 */ uint8 buff_unknown; // if this is 4, a buff icon is made
|
||||
/* 30 */ uint8 effect_flag; // if this is 4, a buff icon is made
|
||||
/* 31 */
|
||||
};
|
||||
|
||||
@ -1237,26 +1235,23 @@ struct Action_Struct
|
||||
// has to do with buff blocking??
|
||||
struct ActionAlt_Struct // ActionAlt_Struct - Size: 56 bytes
|
||||
{
|
||||
/*0000*/ uint16 target; // Target ID
|
||||
/*0002*/ uint16 source; // SourceID
|
||||
/*0004*/ uint16 level; // level of caster
|
||||
/*0006*/ uint16 instrument_mod; // seems to be fixed to 0x0A
|
||||
/*0008*/ uint32 unknown08;
|
||||
/*0012*/ uint16 unknown16;
|
||||
/*0014*/ uint32 sequence;
|
||||
/*0018*/ uint32 unknown18;
|
||||
/*0022*/ uint8 type; // Casts, Falls, Bashes, etc...
|
||||
/*0023*/ uint32 damage; // Amount of Damage
|
||||
/*0027*/ uint16 spell; // SpellID
|
||||
/*0029*/ uint8 unknown29;
|
||||
/*0030*/ uint8 buff_unknown; // if this is 4, a buff icon is made
|
||||
/*0031*/ uint32 unknown0031; // seen 00 00 00 00
|
||||
/*0035*/ uint8 unknown0035; // seen 00
|
||||
/*0036*/ uint32 unknown0036; // seen ff ff ff ff
|
||||
/*0040*/ uint32 unknown0040; // seen ff ff ff ff
|
||||
/*0044*/ uint32 unknown0044; // seen ff ff ff ff
|
||||
/*0048*/ uint32 unknown0048; // seen 00 00 00 00
|
||||
/*0052*/ uint32 unknown0052; // seen 00 00 00 00
|
||||
/*0000*/ uint16 target; // id of target
|
||||
/*0002*/ uint16 source; // id of caster
|
||||
/*0004*/ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
|
||||
/*0006*/ uint32 instrument_mod; // OSX dump says base damage, spells use it for bard song (different from newer clients)
|
||||
/*0010*/ float force;
|
||||
/*0014*/ float hit_heading;
|
||||
/*0018*/ float hit_pitch;
|
||||
/*0022*/ uint8 type; // 231 (0xE7) for spells, skill
|
||||
/*0023*/ uint16 unknown23; // OSX says min_damage
|
||||
/*0025*/ uint16 unknown25; // OSX says tohit
|
||||
/*0027*/ uint16 spell; // spell id being cast
|
||||
/*0029*/ uint8 spell_level; // level of caster again? Or maybe the castee
|
||||
// this field seems to be some sort of success flag, if it's 4
|
||||
/*0030*/ uint8 effect_flag; // if this is 4, a buff icon is made
|
||||
/*0031*/ uint8 spell_slot;
|
||||
/*0032*/ uint32 slot[5];
|
||||
/*0052*/ uint32 item_cast_type; // ItemSpellTypes enum from MQ2
|
||||
/*0056*/
|
||||
};
|
||||
|
||||
@ -1271,9 +1266,9 @@ struct CombatDamage_Struct
|
||||
/* 05 */ uint16 spellid;
|
||||
/* 07 */ int32 damage;
|
||||
/* 11 */ float force; // cd cc cc 3d
|
||||
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
|
||||
/* 19 */ float meleepush_z;
|
||||
/* 23 */ uint8 unknown23; // was [9]
|
||||
/* 15 */ float hit_heading; // see above notes in Action_Struct
|
||||
/* 19 */ float hit_pitch;
|
||||
/* 23 */ uint8 secondary; // 0 for primary hand, 1 for secondary
|
||||
/* 24 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
|
||||
/* 28 */
|
||||
};
|
||||
@ -3008,24 +3003,6 @@ struct GuildMakeLeader{
|
||||
char target[64];
|
||||
};
|
||||
|
||||
struct BugStruct{
|
||||
/*0000*/ uint32 type1; //seems to be just a different way of seeing type; seems to be ordered completely differently
|
||||
/*0004*/ char chartype[64];
|
||||
/*0068*/ char name[96];
|
||||
/*0164*/ char ui[128];
|
||||
/*0292*/ float x;
|
||||
/*0296*/ float y;
|
||||
/*0300*/ float z;
|
||||
/*0304*/ float heading;
|
||||
/*0308*/ uint32 unknown304;
|
||||
/*0312*/ char unknown308[160];
|
||||
/*0472*/ char target_name[64];
|
||||
/*0536*/ uint32 type;
|
||||
/*0540*/ char unknown536[2052];
|
||||
/*2588*/ char bug[2048];
|
||||
/*4636*/ char unknown4632[6];
|
||||
/*4642*/ char system_info[4094];
|
||||
};
|
||||
struct Make_Pet_Struct { //Simple struct for getting pet info
|
||||
uint8 level;
|
||||
uint8 class_;
|
||||
@ -3052,20 +3029,21 @@ struct Ground_Spawn{
|
||||
struct Ground_Spawns {
|
||||
struct Ground_Spawn spawn[50]; //Assigned max number to allow
|
||||
};
|
||||
struct PetitionBug_Struct{
|
||||
uint32 petition_number;
|
||||
uint32 unknown4;
|
||||
char accountname[64];
|
||||
uint32 zoneid;
|
||||
char name[64];
|
||||
uint32 level;
|
||||
uint32 class_;
|
||||
uint32 race;
|
||||
uint32 unknown152[3];
|
||||
uint32 time;
|
||||
uint32 unknown168;
|
||||
char text[1028];
|
||||
};
|
||||
|
||||
//struct PetitionBug_Struct{
|
||||
// uint32 petition_number;
|
||||
// uint32 unknown4;
|
||||
// char accountname[64];
|
||||
// uint32 zoneid;
|
||||
// char name[64];
|
||||
// uint32 level;
|
||||
// uint32 class_;
|
||||
// uint32 race;
|
||||
// uint32 unknown152[3];
|
||||
// uint32 time;
|
||||
// uint32 unknown168;
|
||||
// char text[1028];
|
||||
//};
|
||||
|
||||
struct ApproveZone_Struct {
|
||||
char name[64];
|
||||
@ -4402,6 +4380,22 @@ struct MercenaryAssign_Struct {
|
||||
/*0004*/ uint32 MercUnk01; //
|
||||
/*0008*/ uint32 MercUnk02; //
|
||||
/*0012*/
|
||||
};
|
||||
|
||||
struct SayLinkBodyFrame_Struct {
|
||||
/*000*/ char ActionID[1];
|
||||
/*001*/ char ItemID[5];
|
||||
/*006*/ char Augment1[5];
|
||||
/*011*/ char Augment2[5];
|
||||
/*016*/ char Augment3[5];
|
||||
/*021*/ char Augment4[5];
|
||||
/*026*/ char Augment5[5];
|
||||
/*031*/ char IsEvolving[1];
|
||||
/*032*/ char EvolveGroup[4];
|
||||
/*036*/ char EvolveLevel[1];
|
||||
/*037*/ char OrnamentIcon[5];
|
||||
/*042*/ char Hash[8];
|
||||
/*050*/
|
||||
};
|
||||
|
||||
}; /*structs*/
|
||||
|
||||
@ -53,11 +53,11 @@ namespace SoF
|
||||
static inline uint32 SoFToServerSlot(uint32 sofSlot);
|
||||
static inline uint32 SoFToServerCorpseSlot(uint32 sofCorpseSlot);
|
||||
|
||||
// server to client text link converter
|
||||
static inline void ServerToSoFTextLink(std::string& sofTextLink, const std::string& serverTextLink);
|
||||
// server to client say link converter
|
||||
static inline void ServerToSoFSayLink(std::string& sofSayLink, const std::string& serverSayLink);
|
||||
|
||||
// client to server text link converter
|
||||
static inline void SoFToServerTextLink(std::string& serverTextLink, const std::string& sofTextLink);
|
||||
// client to server say link converter
|
||||
static inline void SoFToServerSayLink(std::string& serverSayLink, const std::string& sofSayLink);
|
||||
|
||||
static inline CastingSlot ServerToSoFCastingSlot(EQEmu::CastingSlot slot);
|
||||
static inline EQEmu::CastingSlot SoFToServerCastingSlot(CastingSlot slot, uint32 itemlocation);
|
||||
@ -161,15 +161,14 @@ namespace SoF
|
||||
OUT(source);
|
||||
OUT(level);
|
||||
OUT(instrument_mod);
|
||||
eq->sequence = emu->sequence;
|
||||
OUT(force);
|
||||
OUT(hit_heading);
|
||||
OUT(hit_pitch);
|
||||
OUT(type);
|
||||
//OUT(damage);
|
||||
OUT(spell);
|
||||
eq->level2 = emu->level;
|
||||
OUT(buff_unknown); // if this is 4, a buff icon is made
|
||||
//eq->unknown0036 = -1;
|
||||
//eq->unknown0040 = -1;
|
||||
//eq->unknown0044 = -1;
|
||||
OUT(spell_level);
|
||||
OUT(effect_flag); // if this is 4, a buff icon is made
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@ -328,7 +327,7 @@ namespace SoF
|
||||
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToSoFTextLink(new_message, old_message);
|
||||
ServerToSoFSayLink(new_message, old_message);
|
||||
|
||||
in->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
|
||||
|
||||
@ -440,8 +439,8 @@ namespace SoF
|
||||
OUT(spellid);
|
||||
OUT(damage);
|
||||
OUT(force);
|
||||
OUT(meleepush_xy);
|
||||
OUT(meleepush_z);
|
||||
OUT(hit_heading);
|
||||
OUT(hit_pitch);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@ -613,7 +612,7 @@ namespace SoF
|
||||
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToSoFTextLink(new_message, old_message);
|
||||
ServerToSoFSayLink(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);
|
||||
@ -665,7 +664,7 @@ namespace SoF
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (old_message_array[i].length() == 0) { break; }
|
||||
ServerToSoFTextLink(new_message_array[i], old_message_array[i]);
|
||||
ServerToSoFSayLink(new_message_array[i], old_message_array[i]);
|
||||
new_message_size += new_message_array[i].length() + 1;
|
||||
}
|
||||
|
||||
@ -1814,7 +1813,7 @@ namespace SoF
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
|
||||
ServerToSoFTextLink(new_message, old_message);
|
||||
ServerToSoFSayLink(new_message, old_message);
|
||||
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
||||
@ -1882,7 +1881,7 @@ namespace SoF
|
||||
|
||||
std::string old_message = InBuffer; // start 'Reward' as string
|
||||
std::string new_message;
|
||||
ServerToSoFTextLink(new_message, old_message);
|
||||
ServerToSoFSayLink(new_message, old_message);
|
||||
|
||||
in->size = sizeof(TaskDescriptionHeader_Struct) + sizeof(TaskDescriptionData1_Struct)+
|
||||
sizeof(TaskDescriptionData2_Struct) + sizeof(TaskDescriptionTrailer_Struct)+
|
||||
@ -2385,6 +2384,17 @@ namespace SoF
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_Bug)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::BugReport_Struct);
|
||||
SETUP_DIRECT_DECODE(BugReport_Struct, structs::BugReport_Struct);
|
||||
|
||||
emu->category_id = EQEmu::bug::CategoryNameToCategoryID(eq->category_name);
|
||||
memcpy(emu->category_name, eq, sizeof(structs::BugReport_Struct));
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_CastSpell)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::CastSpell_Struct);
|
||||
@ -2404,7 +2414,7 @@ namespace SoF
|
||||
|
||||
std::string old_message = (char *)&__eq_buffer[sizeof(ChannelMessage_Struct)];
|
||||
std::string new_message;
|
||||
SoFToServerTextLink(new_message, old_message);
|
||||
SoFToServerSayLink(new_message, old_message);
|
||||
|
||||
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
@ -2518,7 +2528,7 @@ namespace SoF
|
||||
|
||||
std::string old_message = (char *)&__eq_buffer[4]; // unknown01 offset
|
||||
std::string new_message;
|
||||
SoFToServerTextLink(new_message, old_message);
|
||||
SoFToServerSayLink(new_message, old_message);
|
||||
|
||||
__packet->size = sizeof(Emote_Struct);
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
@ -3305,19 +3315,19 @@ namespace SoF
|
||||
return (sofCorpseSlot - 1);
|
||||
}
|
||||
|
||||
static inline void ServerToSoFTextLink(std::string& sofTextLink, const std::string& serverTextLink)
|
||||
static inline void ServerToSoFSayLink(std::string& sofSayLink, const std::string& serverSayLink)
|
||||
{
|
||||
if ((constants::SayLinkBodySize == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) {
|
||||
sofTextLink = serverTextLink;
|
||||
if ((constants::SayLinkBodySize == EQEmu::constants::SayLinkBodySize) || (serverSayLink.find('\x12') == std::string::npos)) {
|
||||
sofSayLink = serverSayLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(serverTextLink, '\x12');
|
||||
auto segments = SplitString(serverSayLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
if (segments[segment_iter].length() <= EQEmu::legacy::TEXT_LINK_BODY_LENGTH) {
|
||||
sofTextLink.append(segments[segment_iter]);
|
||||
if (segments[segment_iter].length() <= EQEmu::constants::SayLinkBodySize) {
|
||||
sofSayLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
@ -3327,37 +3337,37 @@ namespace SoF
|
||||
// SoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (50)
|
||||
// Diff: ^^^^^ ^
|
||||
|
||||
sofTextLink.push_back('\x12');
|
||||
sofTextLink.append(segments[segment_iter].substr(0, 31));
|
||||
sofTextLink.append(segments[segment_iter].substr(36, 5));
|
||||
sofSayLink.push_back('\x12');
|
||||
sofSayLink.append(segments[segment_iter].substr(0, 31));
|
||||
sofSayLink.append(segments[segment_iter].substr(36, 5));
|
||||
|
||||
if (segments[segment_iter][41] == '0')
|
||||
sofTextLink.push_back(segments[segment_iter][42]);
|
||||
sofSayLink.push_back(segments[segment_iter][42]);
|
||||
else
|
||||
sofTextLink.push_back('F');
|
||||
sofSayLink.push_back('F');
|
||||
|
||||
sofTextLink.append(segments[segment_iter].substr(43));
|
||||
sofTextLink.push_back('\x12');
|
||||
sofSayLink.append(segments[segment_iter].substr(43));
|
||||
sofSayLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
sofTextLink.append(segments[segment_iter]);
|
||||
sofSayLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SoFToServerTextLink(std::string& serverTextLink, const std::string& sofTextLink)
|
||||
static inline void SoFToServerSayLink(std::string& serverSayLink, const std::string& sofSayLink)
|
||||
{
|
||||
if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == constants::SayLinkBodySize) || (sofTextLink.find('\x12') == std::string::npos)) {
|
||||
serverTextLink = sofTextLink;
|
||||
if ((EQEmu::constants::SayLinkBodySize == constants::SayLinkBodySize) || (sofSayLink.find('\x12') == std::string::npos)) {
|
||||
serverSayLink = sofSayLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(sofTextLink, '\x12');
|
||||
auto segments = SplitString(sofSayLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
if (segments[segment_iter].length() <= constants::SayLinkBodySize) {
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
serverSayLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
@ -3367,16 +3377,16 @@ namespace SoF
|
||||
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
|
||||
// Diff: ^^^^^ ^
|
||||
|
||||
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');
|
||||
serverSayLink.push_back('\x12');
|
||||
serverSayLink.append(segments[segment_iter].substr(0, 31));
|
||||
serverSayLink.append("00000");
|
||||
serverSayLink.append(segments[segment_iter].substr(31, 5));
|
||||
serverSayLink.push_back('0');
|
||||
serverSayLink.append(segments[segment_iter].substr(36));
|
||||
serverSayLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
serverSayLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,6 +95,7 @@ D(OP_ApplyPoison)
|
||||
D(OP_AugmentInfo)
|
||||
D(OP_AugmentItem)
|
||||
D(OP_Buff)
|
||||
D(OP_Bug)
|
||||
D(OP_CastSpell)
|
||||
D(OP_ChannelMessage)
|
||||
D(OP_CharacterCreate)
|
||||
|
||||
@ -326,7 +326,8 @@ union
|
||||
/*0725*/ uint8 targetable; // 1 = Targetable 0 = Not Targetable (is_npc?)
|
||||
/*0726*/ uint8 unknown0726[4];
|
||||
/*0730*/ uint8 NPC; // 0=player,1=npc,2=pc corpse,3=npc corpse
|
||||
/*0731*/ uint8 unknown0731[11];
|
||||
/*0731*/ float bounding_radius; // used in melee, overrides calc
|
||||
/*0735*/ uint8 unknown0731[7];
|
||||
/*0742*/ uint8 targetable_with_hotkey;
|
||||
/*0743*/ signed padding00:12; // ***Placeholder
|
||||
signed x:19; // x coord
|
||||
@ -1214,20 +1215,18 @@ struct Action_Struct
|
||||
{
|
||||
/* 00 */ uint16 target; // id of target
|
||||
/* 02 */ uint16 source; // id of caster
|
||||
/* 04 */ uint16 level; // level of caster
|
||||
/* 06 */ uint16 instrument_mod; // seems to be fixed to 0x0A
|
||||
/* 08 */ uint32 unknown08;
|
||||
/* 12 */ uint16 unknown16;
|
||||
// some kind of sequence that's the same in both actions
|
||||
// as well as the combat damage, to tie em together?
|
||||
/* 14 */ float sequence; // was uint32
|
||||
/* 18 */ uint32 unknown18;
|
||||
/* 22 */ uint8 type; // 231 (0xE7) for spells
|
||||
/* 23 */ uint32 unknown23;
|
||||
/* 04 */ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
|
||||
/* 06 */ uint32 instrument_mod; // OSX dump says base damage, spells use it for bard song (different from newer clients)
|
||||
/* 10 */ float force;
|
||||
/* 14 */ float hit_heading;
|
||||
/* 18 */ float hit_pitch;
|
||||
/* 22 */ uint8 type; // 231 (0xE7) for spells, skill
|
||||
/* 23 */ uint16 unknown23; // OSX says min_damage
|
||||
/* 25 */ uint16 unknown25; // OSX says tohit
|
||||
/* 27 */ uint16 spell; // spell id being cast
|
||||
/* 29 */ uint8 level2; // level of caster again? Or maybe the castee
|
||||
/* 29 */ uint8 spell_level; // level of caster again? Or maybe the castee
|
||||
// this field seems to be some sort of success flag, if it's 4
|
||||
/* 30 */ uint8 buff_unknown; // if this is 4, a buff icon is made
|
||||
/* 30 */ uint8 effect_flag; // if this is 4, a buff icon is made
|
||||
/* 31 */
|
||||
};
|
||||
|
||||
@ -1236,26 +1235,23 @@ struct Action_Struct
|
||||
// has to do with buff blocking??
|
||||
struct ActionAlt_Struct // ActionAlt_Struct - Size: 56 bytes
|
||||
{
|
||||
/*0000*/ uint16 target; // Target ID
|
||||
/*0002*/ uint16 source; // SourceID
|
||||
/*0004*/ uint16 level; // level of caster
|
||||
/*0006*/ uint16 instrument_mod; // seems to be fixed to 0x0A
|
||||
/*0008*/ uint32 unknown08;
|
||||
/*0012*/ uint16 unknown16;
|
||||
/*0014*/ uint32 sequence;
|
||||
/*0018*/ uint32 unknown18;
|
||||
/*0022*/ uint8 type; // Casts, Falls, Bashes, etc...
|
||||
/*0023*/ uint32 damage; // Amount of Damage
|
||||
/*0027*/ uint16 spell; // SpellID
|
||||
/*0029*/ uint8 unknown29;
|
||||
/*0030*/ uint8 buff_unknown; // if this is 4, a buff icon is made
|
||||
/*0031*/ uint32 unknown0031; // seen 00 00 00 00
|
||||
/*0035*/ uint8 unknown0035; // seen 00
|
||||
/*0036*/ uint32 unknown0036; // seen ff ff ff ff
|
||||
/*0040*/ uint32 unknown0040; // seen ff ff ff ff
|
||||
/*0044*/ uint32 unknown0044; // seen ff ff ff ff
|
||||
/*0048*/ uint32 unknown0048; // seen 00 00 00 00
|
||||
/*0052*/ uint32 unknown0052; // seen 00 00 00 00
|
||||
/*0000*/ uint16 target; // id of target
|
||||
/*0002*/ uint16 source; // id of caster
|
||||
/*0004*/ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
|
||||
/*0006*/ uint32 instrument_mod; // OSX dump says base damage, spells use it for bard song (different from newer clients)
|
||||
/*0010*/ float force;
|
||||
/*0014*/ float hit_heading;
|
||||
/*0018*/ float hit_pitch;
|
||||
/*0022*/ uint8 type; // 231 (0xE7) for spells, skill
|
||||
/*0023*/ uint16 unknown23; // OSX says min_damage
|
||||
/*0025*/ uint16 unknown25; // OSX says tohit
|
||||
/*0027*/ uint16 spell; // spell id being cast
|
||||
/*0029*/ uint8 spell_level; // level of caster again? Or maybe the castee
|
||||
// this field seems to be some sort of success flag, if it's 4
|
||||
/*0030*/ uint8 effect_flag; // if this is 4, a buff icon is made
|
||||
/*0031*/ uint8 spell_slot;
|
||||
/*0032*/ uint32 slot[5];
|
||||
/*0052*/ uint32 item_cast_type; // ItemSpellTypes enum from MQ2
|
||||
/*0056*/
|
||||
};
|
||||
|
||||
@ -1270,9 +1266,10 @@ struct CombatDamage_Struct
|
||||
/* 05 */ uint16 spellid;
|
||||
/* 07 */ int32 damage;
|
||||
/* 11 */ float force; // cd cc cc 3d
|
||||
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
|
||||
/* 19 */ float meleepush_z;
|
||||
/* 23 */ uint8 unknown23[5]; // was [9] this appears unrelated to the stuff the other clients do here?
|
||||
/* 15 */ float hit_heading; // see above notes in Action_Struct
|
||||
/* 19 */ float hit_pitch;
|
||||
/* 23 */ uint8 secondary; // 0 for primary hand, 1 for secondary
|
||||
/* 24 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage, Report function doesn't seem to check this :P
|
||||
/* 28 */
|
||||
};
|
||||
|
||||
@ -2906,23 +2903,31 @@ struct GuildMakeLeader{
|
||||
char target[64];
|
||||
};
|
||||
|
||||
struct BugReport_Struct {
|
||||
/*0000*/ char category_name[64];
|
||||
/*0064*/ char character_name[64];
|
||||
/*0128*/ char unused_0128[32];
|
||||
/*0160*/ char ui_path[128];
|
||||
/*0288*/ float pos_x;
|
||||
/*0292*/ float pos_y;
|
||||
/*0296*/ float pos_z;
|
||||
/*0300*/ uint32 heading;
|
||||
/*0304*/ uint32 unused_0304;
|
||||
/*0308*/ uint32 time_played;
|
||||
/*0312*/ char padding_0312[8];
|
||||
/*0320*/ uint32 target_id;
|
||||
/*0324*/ char padding_0324[140];
|
||||
/*0464*/ uint32 unknown_0464; // seems to always be '0'
|
||||
/*0468*/ char target_name[64];
|
||||
/*0532*/ uint32 optional_info_mask;
|
||||
|
||||
|
||||
struct BugStruct{
|
||||
/*0000*/ char chartype[64];
|
||||
/*0064*/ char name[96];
|
||||
/*0160*/ char ui[128];
|
||||
/*0288*/ float x;
|
||||
/*0292*/ float y;
|
||||
/*0296*/ float z;
|
||||
/*0300*/ float heading;
|
||||
/*0304*/ uint32 unknown304;
|
||||
/*0308*/ uint32 type;
|
||||
/*0312*/ char unknown312[2144];
|
||||
/*2456*/ char bug[1024];
|
||||
/*3480*/ char placeholder[2];
|
||||
/*3482*/ char system_info[4098];
|
||||
// this looks like a butchered 8k buffer with 2 trailing dword fields
|
||||
/*0536*/ char unused_0536[2052];
|
||||
/*2588*/ char bug_report[2050];
|
||||
/*4638*/ char system_info[4098];
|
||||
/*8736*/
|
||||
};
|
||||
|
||||
struct Make_Pet_Struct { //Simple struct for getting pet info
|
||||
uint8 level;
|
||||
uint8 class_;
|
||||
@ -2949,20 +2954,21 @@ struct Ground_Spawn{
|
||||
struct Ground_Spawns {
|
||||
struct Ground_Spawn spawn[50]; //Assigned max number to allow
|
||||
};
|
||||
struct PetitionBug_Struct{
|
||||
uint32 petition_number;
|
||||
uint32 unknown4;
|
||||
char accountname[64];
|
||||
uint32 zoneid;
|
||||
char name[64];
|
||||
uint32 level;
|
||||
uint32 class_;
|
||||
uint32 race;
|
||||
uint32 unknown152[3];
|
||||
uint32 time;
|
||||
uint32 unknown168;
|
||||
char text[1028];
|
||||
};
|
||||
|
||||
//struct PetitionBug_Struct{
|
||||
// uint32 petition_number;
|
||||
// uint32 unknown4;
|
||||
// char accountname[64];
|
||||
// uint32 zoneid;
|
||||
// char name[64];
|
||||
// uint32 level;
|
||||
// uint32 class_;
|
||||
// uint32 race;
|
||||
// uint32 unknown152[3];
|
||||
// uint32 time;
|
||||
// uint32 unknown168;
|
||||
// char text[1028];
|
||||
//};
|
||||
|
||||
struct ApproveZone_Struct {
|
||||
char name[64];
|
||||
@ -4146,6 +4152,22 @@ struct AltCurrencySellItem_Struct {
|
||||
/*004*/ uint32 slot_id;
|
||||
/*006*/ uint32 charges;
|
||||
/*010*/ uint32 cost;
|
||||
};
|
||||
|
||||
struct SayLinkBodyFrame_Struct {
|
||||
/*000*/ char ActionID[1];
|
||||
/*001*/ char ItemID[5];
|
||||
/*006*/ char Augment1[5];
|
||||
/*011*/ char Augment2[5];
|
||||
/*016*/ char Augment3[5];
|
||||
/*021*/ char Augment4[5];
|
||||
/*026*/ char Augment5[5];
|
||||
/*031*/ char IsEvolving[1];
|
||||
/*032*/ char EvolveGroup[4];
|
||||
/*036*/ char EvolveLevel[1];
|
||||
/*037*/ char OrnamentIcon[5];
|
||||
/*042*/ char Hash[8];
|
||||
/*050*/
|
||||
};
|
||||
|
||||
}; /*structs*/
|
||||
|
||||
@ -52,11 +52,11 @@ namespace Titanium
|
||||
static inline uint32 TitaniumToServerSlot(int16 titaniumSlot);
|
||||
static inline uint32 TitaniumToServerCorpseSlot(int16 titaniumCorpseSlot);
|
||||
|
||||
// server to client text link converter
|
||||
static inline void ServerToTitaniumTextLink(std::string& titaniumTextLink, const std::string& serverTextLink);
|
||||
// server to client say link converter
|
||||
static inline void ServerToTitaniumSayLink(std::string& titaniumSayLink, const std::string& serverSayLink);
|
||||
|
||||
// client to server text link converter
|
||||
static inline void TitaniumToServerTextLink(std::string& serverTextLink, const std::string& titaniumTextLink);
|
||||
// client to server say link converter
|
||||
static inline void TitaniumToServerSayLink(std::string& serverSayLink, const std::string& titaniumSayLink);
|
||||
|
||||
static inline CastingSlot ServerToTitaniumCastingSlot(EQEmu::CastingSlot slot);
|
||||
static inline EQEmu::CastingSlot TitaniumToServerCastingSlot(CastingSlot slot, uint32 itemlocation);
|
||||
@ -164,11 +164,14 @@ namespace Titanium
|
||||
OUT(source);
|
||||
OUT(level);
|
||||
OUT(instrument_mod);
|
||||
OUT(sequence);
|
||||
OUT(force);
|
||||
OUT(hit_heading);
|
||||
OUT(hit_pitch);
|
||||
OUT(type);
|
||||
//OUT(damage);
|
||||
OUT(spell);
|
||||
OUT(buff_unknown); // if this is 4, a buff icon is made
|
||||
OUT(spell_level);
|
||||
OUT(effect_flag); // if this is 4, a buff icon is made
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@ -290,7 +293,7 @@ namespace Titanium
|
||||
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToTitaniumTextLink(new_message, old_message);
|
||||
ServerToTitaniumSayLink(new_message, old_message);
|
||||
|
||||
in->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
|
||||
|
||||
@ -358,8 +361,8 @@ namespace Titanium
|
||||
OUT(spellid);
|
||||
OUT(damage);
|
||||
OUT(force);
|
||||
OUT(meleepush_xy);
|
||||
OUT(meleepush_z);
|
||||
OUT(hit_heading);
|
||||
OUT(hit_pitch);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@ -532,7 +535,7 @@ namespace Titanium
|
||||
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToTitaniumTextLink(new_message, old_message);
|
||||
ServerToTitaniumSayLink(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);
|
||||
@ -574,7 +577,7 @@ namespace Titanium
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (old_message_array[i].length() == 0) { break; }
|
||||
ServerToTitaniumTextLink(new_message_array[i], old_message_array[i]);
|
||||
ServerToTitaniumSayLink(new_message_array[i], old_message_array[i]);
|
||||
new_message_size += new_message_array[i].length() + 1;
|
||||
}
|
||||
|
||||
@ -1402,7 +1405,7 @@ namespace Titanium
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
|
||||
ServerToTitaniumTextLink(new_message, old_message);
|
||||
ServerToTitaniumSayLink(new_message, old_message);
|
||||
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
||||
@ -1458,7 +1461,7 @@ namespace Titanium
|
||||
|
||||
std::string old_message = InBuffer; // start 'Reward' as string
|
||||
std::string new_message;
|
||||
ServerToTitaniumTextLink(new_message, old_message);
|
||||
ServerToTitaniumSayLink(new_message, old_message);
|
||||
|
||||
in->size = sizeof(TaskDescriptionHeader_Struct) + sizeof(TaskDescriptionData1_Struct) +
|
||||
sizeof(TaskDescriptionData2_Struct) + sizeof(TaskDescriptionTrailer_Struct) +
|
||||
@ -1789,6 +1792,17 @@ namespace Titanium
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_Bug)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::BugReport_Struct);
|
||||
SETUP_DIRECT_DECODE(BugReport_Struct, structs::BugReport_Struct);
|
||||
|
||||
emu->category_id = EQEmu::bug::CategoryNameToCategoryID(eq->category_name);
|
||||
memcpy(emu->category_name, eq, sizeof(structs::BugReport_Struct));
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_CastSpell)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::CastSpell_Struct);
|
||||
@ -1808,7 +1822,7 @@ namespace Titanium
|
||||
|
||||
std::string old_message = (char *)&__eq_buffer[sizeof(ChannelMessage_Struct)];
|
||||
std::string new_message;
|
||||
TitaniumToServerTextLink(new_message, old_message);
|
||||
TitaniumToServerSayLink(new_message, old_message);
|
||||
|
||||
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
@ -1880,7 +1894,7 @@ namespace Titanium
|
||||
|
||||
std::string old_message = (char *)&__eq_buffer[4]; // unknown01 offset
|
||||
std::string new_message;
|
||||
TitaniumToServerTextLink(new_message, old_message);
|
||||
TitaniumToServerSayLink(new_message, old_message);
|
||||
|
||||
__packet->size = sizeof(Emote_Struct);
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
@ -2474,19 +2488,19 @@ namespace Titanium
|
||||
return titaniumCorpseSlot;
|
||||
}
|
||||
|
||||
static inline void ServerToTitaniumTextLink(std::string& titaniumTextLink, const std::string& serverTextLink)
|
||||
static inline void ServerToTitaniumSayLink(std::string& titaniumSayLink, const std::string& serverSayLink)
|
||||
{
|
||||
if ((constants::SayLinkBodySize == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) {
|
||||
titaniumTextLink = serverTextLink;
|
||||
if ((constants::SayLinkBodySize == EQEmu::constants::SayLinkBodySize) || (serverSayLink.find('\x12') == std::string::npos)) {
|
||||
titaniumSayLink = serverSayLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(serverTextLink, '\x12');
|
||||
auto segments = SplitString(serverSayLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
if (segments[segment_iter].length() <= EQEmu::legacy::TEXT_LINK_BODY_LENGTH) {
|
||||
titaniumTextLink.append(segments[segment_iter]);
|
||||
if (segments[segment_iter].length() <= EQEmu::constants::SayLinkBodySize) {
|
||||
titaniumSayLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
@ -2496,37 +2510,37 @@ namespace Titanium
|
||||
// 6.2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXXXXX (45)
|
||||
// Diff: ^^^^^ ^ ^^^^^
|
||||
|
||||
titaniumTextLink.push_back('\x12');
|
||||
titaniumTextLink.append(segments[segment_iter].substr(0, 31));
|
||||
titaniumTextLink.append(segments[segment_iter].substr(36, 5));
|
||||
titaniumSayLink.push_back('\x12');
|
||||
titaniumSayLink.append(segments[segment_iter].substr(0, 31));
|
||||
titaniumSayLink.append(segments[segment_iter].substr(36, 5));
|
||||
|
||||
if (segments[segment_iter][41] == '0')
|
||||
titaniumTextLink.push_back(segments[segment_iter][42]);
|
||||
titaniumSayLink.push_back(segments[segment_iter][42]);
|
||||
else
|
||||
titaniumTextLink.push_back('F');
|
||||
titaniumSayLink.push_back('F');
|
||||
|
||||
titaniumTextLink.append(segments[segment_iter].substr(48));
|
||||
titaniumTextLink.push_back('\x12');
|
||||
titaniumSayLink.append(segments[segment_iter].substr(48));
|
||||
titaniumSayLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
titaniumTextLink.append(segments[segment_iter]);
|
||||
titaniumSayLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void TitaniumToServerTextLink(std::string& serverTextLink, const std::string& titaniumTextLink)
|
||||
static inline void TitaniumToServerSayLink(std::string& serverSayLink, const std::string& titaniumSayLink)
|
||||
{
|
||||
if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == constants::SayLinkBodySize) || (titaniumTextLink.find('\x12') == std::string::npos)) {
|
||||
serverTextLink = titaniumTextLink;
|
||||
if ((EQEmu::constants::SayLinkBodySize == constants::SayLinkBodySize) || (titaniumSayLink.find('\x12') == std::string::npos)) {
|
||||
serverSayLink = titaniumSayLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(titaniumTextLink, '\x12');
|
||||
auto segments = SplitString(titaniumSayLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
if (segments[segment_iter].length() <= constants::SayLinkBodySize) {
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
serverSayLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
@ -2536,18 +2550,18 @@ namespace Titanium
|
||||
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
|
||||
// Diff: ^^^^^ ^ ^^^^^
|
||||
|
||||
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');
|
||||
serverSayLink.push_back('\x12');
|
||||
serverSayLink.append(segments[segment_iter].substr(0, 31));
|
||||
serverSayLink.append("00000");
|
||||
serverSayLink.append(segments[segment_iter].substr(31, 5));
|
||||
serverSayLink.push_back('0');
|
||||
serverSayLink.push_back(segments[segment_iter][36]);
|
||||
serverSayLink.append("00000");
|
||||
serverSayLink.append(segments[segment_iter].substr(37));
|
||||
serverSayLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
serverSayLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,6 +78,7 @@ D(OP_AdventureMerchantSell)
|
||||
D(OP_ApplyPoison)
|
||||
D(OP_AugmentItem)
|
||||
D(OP_Buff)
|
||||
D(OP_Bug)
|
||||
D(OP_CastSpell)
|
||||
D(OP_ChannelMessage)
|
||||
D(OP_CharacterCreate)
|
||||
|
||||
@ -327,7 +327,7 @@ union
|
||||
// horse: 0=brown, 1=white, 2=black, 3=tan
|
||||
};
|
||||
/*0340*/ uint32 spawnId; // Spawn Id
|
||||
/*0344*/ uint8 unknown0344[4];
|
||||
/*0344*/ float bounding_radius; // used in melee, overrides calc
|
||||
/*0348*/ TintProfile equipment_tint;
|
||||
/*0384*/ uint8 lfg; // 0=off, 1=lfg on
|
||||
/*0385*/
|
||||
@ -1119,20 +1119,18 @@ struct Action_Struct
|
||||
{
|
||||
/* 00 */ uint16 target; // id of target
|
||||
/* 02 */ uint16 source; // id of caster
|
||||
/* 04 */ uint16 level; // level of caster
|
||||
/* 06 */ uint16 instrument_mod;
|
||||
/* 08 */ uint32 unknown08;
|
||||
/* 12 */ uint16 unknown16;
|
||||
// some kind of sequence that's the same in both actions
|
||||
// as well as the combat damage, to tie em together?
|
||||
/* 14 */ uint32 sequence;
|
||||
/* 18 */ uint32 unknown18;
|
||||
/* 22 */ uint8 type; // 231 (0xE7) for spells
|
||||
/* 23 */ uint32 unknown23;
|
||||
/* 04 */ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
|
||||
/* 06 */ uint32 instrument_mod; // OSX dump says base damage, spells use it for bard song (different from newer clients)
|
||||
/* 10 */ float force;
|
||||
/* 14 */ float hit_heading;
|
||||
/* 18 */ float hit_pitch;
|
||||
/* 22 */ uint8 type; // 231 (0xE7) for spells, skill
|
||||
/* 23 */ uint16 unknown23; // OSX says min_damage
|
||||
/* 25 */ uint16 unknown25; // OSX says tohit
|
||||
/* 27 */ uint16 spell; // spell id being cast
|
||||
/* 29 */ uint8 unknown29;
|
||||
/* 29 */ uint8 spell_level;
|
||||
// this field seems to be some sort of success flag, if it's 4
|
||||
/* 30 */ uint8 buff_unknown; // if this is 4, a buff icon is made
|
||||
/* 30 */ uint8 effect_flag; // if this is 4, a buff icon is made
|
||||
/* 31 */
|
||||
};
|
||||
|
||||
@ -1143,12 +1141,12 @@ struct CombatDamage_Struct
|
||||
{
|
||||
/* 00 */ uint16 target;
|
||||
/* 02 */ uint16 source;
|
||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
|
||||
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells, skill
|
||||
/* 05 */ uint16 spellid;
|
||||
/* 07 */ uint32 damage;
|
||||
/* 11 */ float force;
|
||||
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
|
||||
/* 19 */ float meleepush_z;
|
||||
/* 15 */ float hit_heading; // see above notes in Action_Struct
|
||||
/* 19 */ float hit_pitch;
|
||||
/* 23 */
|
||||
};
|
||||
|
||||
@ -2571,21 +2569,32 @@ struct GuildMakeLeader{
|
||||
char name[64];
|
||||
char target[64];
|
||||
};
|
||||
struct BugStruct{
|
||||
/*0000*/ char chartype[64];
|
||||
/*0064*/ char name[96];
|
||||
/*0160*/ char ui[128];
|
||||
/*0288*/ float x;
|
||||
/*0292*/ float y;
|
||||
/*0296*/ float z;
|
||||
/*0300*/ float heading;
|
||||
/*0304*/ uint32 unknown304;
|
||||
/*0308*/ uint32 type;
|
||||
/*0312*/ char unknown312[2144];
|
||||
/*2456*/ char bug[1024];
|
||||
/*3480*/ char placeholder[2];
|
||||
/*3482*/ char system_info[4098];
|
||||
|
||||
struct BugReport_Struct {
|
||||
/*0000*/ char category_name[64];
|
||||
/*0064*/ char character_name[64];
|
||||
/*0128*/ char unused_0128[32];
|
||||
/*0160*/ char ui_path[128];
|
||||
/*0288*/ float pos_x;
|
||||
/*0292*/ float pos_y;
|
||||
/*0296*/ float pos_z;
|
||||
/*0300*/ uint32 heading;
|
||||
/*0304*/ uint32 unused_0304;
|
||||
/*0308*/ uint32 time_played;
|
||||
/*0312*/ char padding_0312[8];
|
||||
/*0320*/ uint32 target_id;
|
||||
/*0324*/ char padding_0324[140];
|
||||
/*0464*/ uint32 unknown_0464; // seems to always be '0'
|
||||
/*0468*/ char target_name[64];
|
||||
/*0532*/ uint32 optional_info_mask;
|
||||
|
||||
// this looks like a butchered 8k buffer with 2 trailing dword fields
|
||||
/*0536*/ char unused_0536[2052];
|
||||
/*2588*/ char bug_report[2050];
|
||||
/*4638*/ char system_info[4098];
|
||||
/*8736*/
|
||||
};
|
||||
|
||||
struct Make_Pet_Struct { //Simple struct for getting pet info
|
||||
uint8 level;
|
||||
uint8 class_;
|
||||
@ -2612,20 +2621,21 @@ struct Ground_Spawn{
|
||||
struct Ground_Spawns {
|
||||
struct Ground_Spawn spawn[50]; //Assigned max number to allow
|
||||
};
|
||||
struct PetitionBug_Struct{
|
||||
uint32 petition_number;
|
||||
uint32 unknown4;
|
||||
char accountname[64];
|
||||
uint32 zoneid;
|
||||
char name[64];
|
||||
uint32 level;
|
||||
uint32 class_;
|
||||
uint32 race;
|
||||
uint32 unknown152[3];
|
||||
uint32 time;
|
||||
uint32 unknown168;
|
||||
char text[1028];
|
||||
};
|
||||
|
||||
//struct PetitionBug_Struct{
|
||||
// uint32 petition_number;
|
||||
// uint32 unknown4;
|
||||
// char accountname[64];
|
||||
// uint32 zoneid;
|
||||
// char name[64];
|
||||
// uint32 level;
|
||||
// uint32 class_;
|
||||
// uint32 race;
|
||||
// uint32 unknown152[3];
|
||||
// uint32 time;
|
||||
// uint32 unknown168;
|
||||
// char text[1028];
|
||||
//};
|
||||
|
||||
struct ApproveZone_Struct {
|
||||
char name[64];
|
||||
@ -3553,6 +3563,21 @@ struct LFGuild_GuildToggle_Struct
|
||||
// char ScrollName; // '0'
|
||||
//};
|
||||
|
||||
struct SayLinkBodyFrame_Struct {
|
||||
/*000*/ char ActionID[1];
|
||||
/*001*/ char ItemID[5];
|
||||
/*006*/ char Augment1[5];
|
||||
/*011*/ char Augment2[5];
|
||||
/*016*/ char Augment3[5];
|
||||
/*021*/ char Augment4[5];
|
||||
/*026*/ char Augment5[5];
|
||||
/*031*/ char IsEvolving[1];
|
||||
/*032*/ char EvolveGroup[4];
|
||||
/*036*/ char EvolveLevel[1];
|
||||
/*037*/ char Hash[8];
|
||||
/*045*/
|
||||
};
|
||||
|
||||
}; /*structs*/
|
||||
|
||||
}; /*Titanium*/
|
||||
|
||||
@ -53,11 +53,11 @@ namespace UF
|
||||
static inline uint32 UFToServerSlot(uint32 ufSlot);
|
||||
static inline uint32 UFToServerCorpseSlot(uint32 ufCorpseSlot);
|
||||
|
||||
// server to client text link converter
|
||||
static inline void ServerToUFTextLink(std::string& ufTextLink, const std::string& serverTextLink);
|
||||
// server to client say link converter
|
||||
static inline void ServerToUFSayLink(std::string& ufSayLink, const std::string& serverSayLink);
|
||||
|
||||
// client to server text link converter
|
||||
static inline void UFToServerTextLink(std::string& serverTextLink, const std::string& ufTextLink);
|
||||
// client to server say link converter
|
||||
static inline void UFToServerSayLink(std::string& serverSayLink, const std::string& ufSayLink);
|
||||
|
||||
static inline CastingSlot ServerToUFCastingSlot(EQEmu::CastingSlot slot);
|
||||
static inline EQEmu::CastingSlot UFToServerCastingSlot(CastingSlot slot);
|
||||
@ -161,29 +161,20 @@ namespace UF
|
||||
OUT(source);
|
||||
OUT(level);
|
||||
eq->instrument_mod = 1.0f + (emu->instrument_mod - 10) / 10.0f;
|
||||
eq->knockback_angle = emu->sequence;
|
||||
OUT(force);
|
||||
OUT(hit_heading);
|
||||
OUT(hit_pitch);
|
||||
OUT(type);
|
||||
OUT(spell);
|
||||
eq->level2 = eq->level;
|
||||
eq->effect_flag = emu->buff_unknown;
|
||||
eq->unknown37 = 0x01;
|
||||
eq->unknown44 = 0xFFFFFFFF;
|
||||
eq->unknown48 = 0xFFFFFFFF;
|
||||
eq->unknown52 = 0xFFFFFFFF;
|
||||
|
||||
/*OUT(target);
|
||||
OUT(source);
|
||||
OUT(level);
|
||||
OUT(instrument_mod);
|
||||
eq->sequence = emu->sequence;
|
||||
OUT(type);
|
||||
//OUT(damage);
|
||||
OUT(spell);
|
||||
eq->level2 = emu->level;
|
||||
OUT(buff_unknown); // if this is 4, a buff icon is made
|
||||
//eq->unknown0036 = -1;
|
||||
//eq->unknown0040 = -1;
|
||||
//eq->unknown0044 = -1;*/
|
||||
OUT(spell_level);
|
||||
OUT(effect_flag);
|
||||
eq->spell_gem = 0;
|
||||
eq->slot[0] = -1; // type
|
||||
eq->slot[1] = -1; // slot
|
||||
eq->slot[2] = -1; // sub index
|
||||
eq->slot[3] = -1; // aug index
|
||||
eq->slot[4] = -1; // unknown
|
||||
eq->item_cast_type = 0;
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@ -463,7 +454,7 @@ namespace UF
|
||||
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToUFTextLink(new_message, old_message);
|
||||
ServerToUFSayLink(new_message, old_message);
|
||||
|
||||
//in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36;
|
||||
in->size = strlen(emu->sender) + strlen(emu->targetname) + new_message.length() + 39;
|
||||
@ -586,8 +577,8 @@ namespace UF
|
||||
OUT(spellid);
|
||||
OUT(damage);
|
||||
OUT(force);
|
||||
OUT(meleepush_xy);
|
||||
OUT(meleepush_z);
|
||||
OUT(hit_heading);
|
||||
OUT(hit_pitch);
|
||||
OUT(special);
|
||||
|
||||
FINISH_ENCODE();
|
||||
@ -762,7 +753,7 @@ namespace UF
|
||||
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToUFTextLink(new_message, old_message);
|
||||
ServerToUFSayLink(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);
|
||||
@ -814,7 +805,7 @@ namespace UF
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (old_message_array[i].length() == 0) { break; }
|
||||
ServerToUFTextLink(new_message_array[i], old_message_array[i]);
|
||||
ServerToUFSayLink(new_message_array[i], old_message_array[i]);
|
||||
new_message_size += new_message_array[i].length() + 1;
|
||||
}
|
||||
|
||||
@ -2469,7 +2460,7 @@ namespace UF
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
|
||||
ServerToUFTextLink(new_message, old_message);
|
||||
ServerToUFSayLink(new_message, old_message);
|
||||
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
||||
@ -2539,7 +2530,7 @@ namespace UF
|
||||
|
||||
std::string old_message = InBuffer; // start 'Reward' as string
|
||||
std::string new_message;
|
||||
ServerToUFTextLink(new_message, old_message);
|
||||
ServerToUFSayLink(new_message, old_message);
|
||||
|
||||
in->size = sizeof(TaskDescriptionHeader_Struct) + sizeof(TaskDescriptionData1_Struct)+
|
||||
sizeof(TaskDescriptionData2_Struct) + sizeof(TaskDescriptionTrailer_Struct)+
|
||||
@ -3287,7 +3278,7 @@ namespace UF
|
||||
|
||||
std::string old_message = InBuffer;
|
||||
std::string new_message;
|
||||
UFToServerTextLink(new_message, old_message);
|
||||
UFToServerSayLink(new_message, old_message);
|
||||
|
||||
//__packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1;
|
||||
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
|
||||
@ -3398,7 +3389,7 @@ namespace UF
|
||||
IN(type);
|
||||
IN(spellid);
|
||||
IN(damage);
|
||||
IN(meleepush_xy);
|
||||
IN(hit_heading);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@ -3421,7 +3412,7 @@ namespace UF
|
||||
|
||||
std::string old_message = (char *)&__eq_buffer[4]; // unknown01 offset
|
||||
std::string new_message;
|
||||
UFToServerTextLink(new_message, old_message);
|
||||
UFToServerSayLink(new_message, old_message);
|
||||
|
||||
__packet->size = sizeof(Emote_Struct);
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
@ -4290,19 +4281,19 @@ namespace UF
|
||||
return (ufCorpseSlot - 1);
|
||||
}
|
||||
|
||||
static inline void ServerToUFTextLink(std::string& ufTextLink, const std::string& serverTextLink)
|
||||
static inline void ServerToUFSayLink(std::string& ufSayLink, const std::string& serverSayLink)
|
||||
{
|
||||
if ((constants::SayLinkBodySize == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) {
|
||||
ufTextLink = serverTextLink;
|
||||
if ((constants::SayLinkBodySize == EQEmu::constants::SayLinkBodySize) || (serverSayLink.find('\x12') == std::string::npos)) {
|
||||
ufSayLink = serverSayLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(serverTextLink, '\x12');
|
||||
auto segments = SplitString(serverSayLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
if (segments[segment_iter].length() <= EQEmu::legacy::TEXT_LINK_BODY_LENGTH) {
|
||||
ufTextLink.append(segments[segment_iter]);
|
||||
if (segments[segment_iter].length() <= EQEmu::constants::SayLinkBodySize) {
|
||||
ufSayLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
@ -4312,37 +4303,37 @@ namespace UF
|
||||
// SoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (50)
|
||||
// Diff: ^^^^^ ^
|
||||
|
||||
ufTextLink.push_back('\x12');
|
||||
ufTextLink.append(segments[segment_iter].substr(0, 31));
|
||||
ufTextLink.append(segments[segment_iter].substr(36, 5));
|
||||
ufSayLink.push_back('\x12');
|
||||
ufSayLink.append(segments[segment_iter].substr(0, 31));
|
||||
ufSayLink.append(segments[segment_iter].substr(36, 5));
|
||||
|
||||
if (segments[segment_iter][41] == '0')
|
||||
ufTextLink.push_back(segments[segment_iter][42]);
|
||||
ufSayLink.push_back(segments[segment_iter][42]);
|
||||
else
|
||||
ufTextLink.push_back('F');
|
||||
ufSayLink.push_back('F');
|
||||
|
||||
ufTextLink.append(segments[segment_iter].substr(43));
|
||||
ufTextLink.push_back('\x12');
|
||||
ufSayLink.append(segments[segment_iter].substr(43));
|
||||
ufSayLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
ufTextLink.append(segments[segment_iter]);
|
||||
ufSayLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void UFToServerTextLink(std::string& serverTextLink, const std::string& ufTextLink)
|
||||
static inline void UFToServerSayLink(std::string& serverSayLink, const std::string& ufSayLink)
|
||||
{
|
||||
if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == constants::SayLinkBodySize) || (ufTextLink.find('\x12') == std::string::npos)) {
|
||||
serverTextLink = ufTextLink;
|
||||
if ((EQEmu::constants::SayLinkBodySize == constants::SayLinkBodySize) || (ufSayLink.find('\x12') == std::string::npos)) {
|
||||
serverSayLink = ufSayLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(ufTextLink, '\x12');
|
||||
auto segments = SplitString(ufSayLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
if (segments[segment_iter].length() <= constants::SayLinkBodySize) {
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
serverSayLink.append(segments[segment_iter]);
|
||||
// TODO: log size mismatch error
|
||||
continue;
|
||||
}
|
||||
@ -4352,16 +4343,16 @@ namespace UF
|
||||
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
|
||||
// Diff: ^^^^^ ^
|
||||
|
||||
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');
|
||||
serverSayLink.push_back('\x12');
|
||||
serverSayLink.append(segments[segment_iter].substr(0, 31));
|
||||
serverSayLink.append("00000");
|
||||
serverSayLink.append(segments[segment_iter].substr(31, 5));
|
||||
serverSayLink.push_back('0');
|
||||
serverSayLink.append(segments[segment_iter].substr(36));
|
||||
serverSayLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[segment_iter]);
|
||||
serverSayLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -292,7 +292,7 @@ struct Spawn_Struct
|
||||
/*0000*/ //uint8 nullterm1; // hack to null terminate name
|
||||
/*0064*/ uint32 spawnId;
|
||||
/*0068*/ uint8 level;
|
||||
/*0069*/ float unknown1;
|
||||
/*0069*/ float bounding_radius; // used in melee, overrides calc
|
||||
/*0073*/ uint8 NPC; // 0=player,1=npc,2=pc corpse,3=npc corpse
|
||||
Spawn_Struct_Bitfields Bitfields;
|
||||
/*0000*/ uint8 otherData; // & 4 - has title, & 8 - has suffix, & 1 - it's a chest or untargetable
|
||||
@ -1252,19 +1252,19 @@ struct Action_Struct
|
||||
{
|
||||
/*00*/ uint16 target; // id of target
|
||||
/*02*/ uint16 source; // id of caster
|
||||
/*04*/ uint16 level; // level of caster - Seen 0
|
||||
/*06*/ uint32 unknown06;
|
||||
/*10*/ uint16 instrument_focus;
|
||||
/*12*/ uint16 unknown12; // seems to always be set to something and it doesn't change between casts except in special cases like changing instrument mods
|
||||
/*14*/ uint32 unknown14; // seen 0
|
||||
/*18*/ float knockback_angle; //seems to go from 0-512 then it rolls over again
|
||||
/*22*/ uint32 unknown22;
|
||||
/*26*/ uint8 type;
|
||||
/*27*/ uint32 damage;
|
||||
/*31*/ uint16 unknown31;
|
||||
/*04*/ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
|
||||
/*06*/ uint32 unknown06; // OSX dump says base_damage, was used for bard mod too, this is 0'd :(
|
||||
/*10*/ float instrument_mod;
|
||||
/*14*/ float force;
|
||||
/*18*/ float hit_heading;
|
||||
/*22*/ float hit_pitch;
|
||||
/*26*/ uint8 type; // 231 (0xE7) for spells, skill
|
||||
/*27*/ uint32 damage; // OSX says min_damage
|
||||
/*31*/ uint16 unknown31; // OSX says tohit
|
||||
/*33*/ uint16 spell; // spell id being cast
|
||||
/*35*/ uint8 level2; // level of caster again? Or maybe the castee
|
||||
/*35*/ uint8 spell_level; // level of caster again? Or maybe the castee
|
||||
/*36*/ uint8 effect_flag; // if this is 4, the effect is valid: or if two are sent at the same time?
|
||||
/*37*/
|
||||
};
|
||||
|
||||
|
||||
@ -1276,27 +1276,22 @@ struct ActionAlt_Struct
|
||||
{
|
||||
/*00*/ uint16 target; // id of target
|
||||
/*02*/ uint16 source; // id of caster
|
||||
/*04*/ uint16 level; // level of caster - Seen 0
|
||||
/*06*/ uint32 unknown06;
|
||||
/*04*/ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
|
||||
/*06*/ uint32 unknown06; // OSX dump says base_damage, was used for bard mod too, this is 0'd :(
|
||||
/*10*/ float instrument_mod;
|
||||
/*14*/ uint32 unknown14; // seen 0
|
||||
/*18*/ float knockback_angle; //seems to go from 0-512 then it rolls over again
|
||||
/*22*/ uint32 unknown22;
|
||||
/*26*/ uint8 type;
|
||||
/*27*/ uint32 damage;
|
||||
/*31*/ uint16 unknown31;
|
||||
/*14*/ float force;
|
||||
/*18*/ float hit_heading;
|
||||
/*22*/ float hit_pitch;
|
||||
/*26*/ uint8 type; // 231 (0xE7) for spells, skill
|
||||
/*27*/ uint32 damage; // OSX says min_damage
|
||||
/*31*/ uint16 unknown31; // OSX says tohit
|
||||
/*33*/ uint16 spell; // spell id being cast
|
||||
/*35*/ uint8 level2; // level of caster again? Or maybe the castee
|
||||
/*35*/ uint8 spell_level; // level of caster again? Or maybe the castee
|
||||
/*36*/ uint8 effect_flag; // if this is 4, the effect is valid: or if two are sent at the same time?
|
||||
/*37*/ uint32 unknown37; // New field to Underfoot - Seen 14
|
||||
/*41*/ uint8 unknown41; // New field to Underfoot - Seen 0
|
||||
/*42*/ uint8 unknown42; // New field to Underfoot - Seen 0
|
||||
/*43*/ uint8 unknown43; // New field to Underfoot - Seen 0
|
||||
/*44*/ uint32 unknown44; // New field to Underfoot - Seen 23
|
||||
/*48*/ uint32 unknown48; // New field to Underfoot - Seen -1
|
||||
/*52*/ uint32 unknown52; // New field to Underfoot - Seen -1
|
||||
/*56*/ uint32 unknown56; // New field to Underfoot - Seen 0
|
||||
/*60*/ uint32 unknown60; // New field to Underfoot - Seen 0
|
||||
/*37*/ uint8 spell_gem;
|
||||
/*38*/ uint8 padding38[2];
|
||||
/*40*/ uint32 slot[5];
|
||||
/*60*/ uint32 item_cast_type; // ItemSpellTypes enum from MQ2
|
||||
/*64*/
|
||||
};
|
||||
|
||||
@ -1311,9 +1306,9 @@ struct CombatDamage_Struct
|
||||
/* 05 */ uint16 spellid;
|
||||
/* 07 */ int32 damage;
|
||||
/* 11 */ float force; // cd cc cc 3d
|
||||
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
|
||||
/* 19 */ float meleepush_z;
|
||||
/* 23 */ uint8 unknown23; // was [9]
|
||||
/* 15 */ float hit_heading; // see above notes in Action_Struct
|
||||
/* 19 */ float hit_pitch;
|
||||
/* 23 */ uint8 secondary; // 0 for primary hand, 1 for secondary
|
||||
/* 24 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
|
||||
/* 28 */
|
||||
};
|
||||
@ -3060,23 +3055,6 @@ struct GuildMakeLeader{
|
||||
char target[64];
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct BugStruct{
|
||||
/*0000*/ char chartype[64];
|
||||
/*0064*/ char name[96];
|
||||
/*0160*/ char ui[128];
|
||||
/*0288*/ float x;
|
||||
/*0292*/ float y;
|
||||
/*0296*/ float z;
|
||||
/*0300*/ float heading;
|
||||
/*0304*/ uint32 unknown304;
|
||||
/*0308*/ uint32 type;
|
||||
/*0312*/ char unknown312[2144];
|
||||
/*2456*/ char bug[1024];
|
||||
/*3480*/ char placeholder[2];
|
||||
/*3482*/ char system_info[4098];
|
||||
};
|
||||
struct Make_Pet_Struct { //Simple struct for getting pet info
|
||||
uint8 level;
|
||||
uint8 class_;
|
||||
@ -3103,20 +3081,21 @@ struct Ground_Spawn{
|
||||
struct Ground_Spawns {
|
||||
struct Ground_Spawn spawn[50]; //Assigned max number to allow
|
||||
};
|
||||
struct PetitionBug_Struct{
|
||||
uint32 petition_number;
|
||||
uint32 unknown4;
|
||||
char accountname[64];
|
||||
uint32 zoneid;
|
||||
char name[64];
|
||||
uint32 level;
|
||||
uint32 class_;
|
||||
uint32 race;
|
||||
uint32 unknown152[3];
|
||||
uint32 time;
|
||||
uint32 unknown168;
|
||||
char text[1028];
|
||||
};
|
||||
|
||||
//struct PetitionBug_Struct{
|
||||
// uint32 petition_number;
|
||||
// uint32 unknown4;
|
||||
// char accountname[64];
|
||||
// uint32 zoneid;
|
||||
// char name[64];
|
||||
// uint32 level;
|
||||
// uint32 class_;
|
||||
// uint32 race;
|
||||
// uint32 unknown152[3];
|
||||
// uint32 time;
|
||||
// uint32 unknown168;
|
||||
// char text[1028];
|
||||
//};
|
||||
|
||||
struct ApproveZone_Struct {
|
||||
char name[64];
|
||||
@ -4505,6 +4484,22 @@ struct MercenaryAssign_Struct {
|
||||
/*0004*/ uint32 MercUnk01; //
|
||||
/*0008*/ uint32 MercUnk02; //
|
||||
/*0012*/
|
||||
};
|
||||
|
||||
struct SayLinkBodyFrame_Struct {
|
||||
/*000*/ char ActionID[1];
|
||||
/*001*/ char ItemID[5];
|
||||
/*006*/ char Augment1[5];
|
||||
/*011*/ char Augment2[5];
|
||||
/*016*/ char Augment3[5];
|
||||
/*021*/ char Augment4[5];
|
||||
/*026*/ char Augment5[5];
|
||||
/*031*/ char IsEvolving[1];
|
||||
/*032*/ char EvolveGroup[4];
|
||||
/*036*/ char EvolveLevel[1];
|
||||
/*037*/ char OrnamentIcon[5];
|
||||
/*042*/ char Hash[8];
|
||||
/*050*/
|
||||
};
|
||||
|
||||
}; /*structs*/
|
||||
|
||||
@ -156,6 +156,7 @@ RULE_BOOL(Character, UseOldBindWound, false) // Uses the original bind wound beh
|
||||
RULE_BOOL(Character, GrantHoTTOnCreate, false) // Grant Health of Target's Target leadership AA on character creation
|
||||
RULE_BOOL(Character, UseOldConSystem, false) // Grant Health of Target's Target leadership AA on character creation
|
||||
RULE_BOOL(Character, OPClientUpdateVisualDebug, false) // Shows a pulse and forward directional particle each time the client sends its position to server
|
||||
RULE_BOOL(Character, PetsUseReagents, true) //Pets use reagent on spells
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Mercs)
|
||||
@ -233,6 +234,7 @@ RULE_INT(World, TitaniumStartZoneID, -1) //Sets the Starting Zone for Titanium C
|
||||
RULE_INT(World, ExpansionSettings, 16383) // Sets the expansion settings for the server, This is sent on login to world and affects client expansion settings. Defaults to all expansions enabled up to TSS.
|
||||
RULE_BOOL(World, UseClientBasedExpansionSettings, true) // if true it will overrule World, ExpansionSettings and set someone's expansion based on the client they're using
|
||||
RULE_INT(World, PVPSettings, 0) // Sets the PVP settings for the server, 1 = Rallos Zek RuleSet, 2 = Tallon/Vallon Zek Ruleset, 4 = Sullon Zek Ruleset, 6 = Discord Ruleset, anything above 6 is the Discord Ruleset without the no-drop restrictions removed. TODO: Edit IsAttackAllowed in Zone to accomodate for these rules.
|
||||
RULE_INT(World, PVPMinLevel, 0) // minimum level to pvp
|
||||
RULE_BOOL (World, IsGMPetitionWindowEnabled, false)
|
||||
RULE_INT (World, FVNoDropFlag, 0) // Sets the Firiona Vie settings on the client. If set to 2, the flag will be set for GMs only, allowing trading of no-drop items.
|
||||
RULE_BOOL (World, IPLimitDisconnectAll, false)
|
||||
@ -400,6 +402,7 @@ RULE_BOOL(Spells, IgnoreSpellDmgLvlRestriction, false) // ignore the 5 level spr
|
||||
RULE_BOOL(Spells, AllowItemTGB, false) // TGB doesn't work with items on live, custom servers want it though
|
||||
RULE_BOOL(Spells, NPCInnateProcOverride, true) // NPC innate procs override the target type to single target.
|
||||
RULE_BOOL(Spells, OldRainTargets, false) // use old incorrectly implemented max targets for rains
|
||||
RULE_BOOL(Spells, NPCSpellPush, false) // enable spell push on NPCs
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Combat)
|
||||
@ -720,6 +723,12 @@ RULE_BOOL(Client, UseLiveFactionMessage, false) // Allows players to see faction
|
||||
RULE_BOOL(Client, UseLiveBlockedMessage, false) // Allows players to see faction adjustments like Live
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Bugs)
|
||||
RULE_BOOL(Bugs, ReportingSystemActive, true) // Activates bug reporting
|
||||
RULE_BOOL(Bugs, UseOldReportingMethod, true) // Forces the use of the old bug reporting system
|
||||
RULE_BOOL(Bugs, DumpTargetEntity, false) // Dumps the target entity, if one is provided
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
#undef RULE_CATEGORY
|
||||
#undef RULE_INT
|
||||
#undef RULE_REAL
|
||||
|
||||
@ -29,10 +29,10 @@
|
||||
bool EQEmu::saylink::DegenerateLinkBody(SayLinkBody_Struct& say_link_body_struct, const std::string& say_link_body)
|
||||
{
|
||||
memset(&say_link_body_struct, 0, sizeof(say_link_body_struct));
|
||||
if (say_link_body.length() != EQEmu::legacy::TEXT_LINK_BODY_LENGTH)
|
||||
if (say_link_body.length() != EQEmu::constants::SayLinkBodySize)
|
||||
return false;
|
||||
|
||||
say_link_body_struct.unknown_1 = (uint8)strtol(say_link_body.substr(0, 1).c_str(), nullptr, 16);
|
||||
say_link_body_struct.action_id = (uint8)strtol(say_link_body.substr(0, 1).c_str(), nullptr, 16);
|
||||
say_link_body_struct.item_id = (uint32)strtol(say_link_body.substr(1, 5).c_str(), nullptr, 16);
|
||||
say_link_body_struct.augment_1 = (uint32)strtol(say_link_body.substr(6, 5).c_str(), nullptr, 16);
|
||||
say_link_body_struct.augment_2 = (uint32)strtol(say_link_body.substr(11, 5).c_str(), nullptr, 16);
|
||||
@ -44,7 +44,7 @@ bool EQEmu::saylink::DegenerateLinkBody(SayLinkBody_Struct& say_link_body_struct
|
||||
say_link_body_struct.evolve_group = (uint32)strtol(say_link_body.substr(37, 4).c_str(), nullptr, 16);
|
||||
say_link_body_struct.evolve_level = (uint8)strtol(say_link_body.substr(41, 2).c_str(), nullptr, 16);
|
||||
say_link_body_struct.ornament_icon = (uint32)strtol(say_link_body.substr(43, 5).c_str(), nullptr, 16);
|
||||
say_link_body_struct.hash = (int)strtol(say_link_body.substr(48, 8).c_str(), nullptr, 16);
|
||||
say_link_body_struct.hash = (uint32)strtol(say_link_body.substr(48, 8).c_str(), nullptr, 16);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -53,7 +53,7 @@ bool EQEmu::saylink::GenerateLinkBody(std::string& say_link_body, const SayLinkB
|
||||
{
|
||||
say_link_body = StringFormat(
|
||||
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X",
|
||||
(0x0F & say_link_body_struct.unknown_1),
|
||||
(0x0F & say_link_body_struct.action_id),
|
||||
(0x000FFFFF & say_link_body_struct.item_id),
|
||||
(0x000FFFFF & say_link_body_struct.augment_1),
|
||||
(0x000FFFFF & say_link_body_struct.augment_2),
|
||||
@ -68,7 +68,7 @@ bool EQEmu::saylink::GenerateLinkBody(std::string& say_link_body, const SayLinkB
|
||||
(0xFFFFFFFF & say_link_body_struct.hash)
|
||||
);
|
||||
|
||||
if (say_link_body.length() != EQEmu::legacy::TEXT_LINK_BODY_LENGTH)
|
||||
if (say_link_body.length() != EQEmu::constants::SayLinkBodySize)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -79,7 +79,7 @@ EQEmu::SayLinkEngine::SayLinkEngine()
|
||||
Reset();
|
||||
}
|
||||
|
||||
std::string EQEmu::SayLinkEngine::GenerateLink()
|
||||
const std::string& EQEmu::SayLinkEngine::GenerateLink()
|
||||
{
|
||||
m_Link.clear();
|
||||
m_LinkBody.clear();
|
||||
@ -88,18 +88,26 @@ std::string EQEmu::SayLinkEngine::GenerateLink()
|
||||
generate_body();
|
||||
generate_text();
|
||||
|
||||
if ((m_LinkBody.length() == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) && (m_LinkText.length() > 0)) {
|
||||
if ((m_LinkBody.length() == EQEmu::constants::SayLinkBodySize) && (m_LinkText.length() > 0)) {
|
||||
m_Link.push_back(0x12);
|
||||
m_Link.append(m_LinkBody);
|
||||
m_Link.append(m_LinkText);
|
||||
m_Link.push_back(0x12);
|
||||
}
|
||||
|
||||
if ((m_Link.length() == 0) || (m_Link.length() > 250)) {
|
||||
if ((m_Link.length() == 0) || (m_Link.length() > (EQEmu::constants::SayLinkMaximumSize))) {
|
||||
m_Error = true;
|
||||
m_Link = "<LINKER ERROR>";
|
||||
Log(Logs::General, Logs::Error, "TextLink::GenerateLink() failed to generate a useable text link (LinkType: %i, Lengths: {link: %u, body: %u, text: %u})",
|
||||
m_LinkType, m_Link.length(), m_LinkBody.length(), m_LinkText.length());
|
||||
Log(Logs::General, Logs::Error, "SayLinkEngine::GenerateLink() failed to generate a useable say link");
|
||||
Log(Logs::General, Logs::Error, ">> LinkType: %i, Lengths: {link: %u(%u), body: %u(%u), text: %u(%u)}",
|
||||
m_LinkType,
|
||||
m_Link.length(),
|
||||
EQEmu::constants::SayLinkMaximumSize,
|
||||
m_LinkBody.length(),
|
||||
EQEmu::constants::SayLinkBodySize,
|
||||
m_LinkText.length(),
|
||||
EQEmu::constants::SayLinkTextSize
|
||||
);
|
||||
Log(Logs::General, Logs::Error, ">> LinkBody: %s", m_LinkBody.c_str());
|
||||
Log(Logs::General, Logs::Error, ">> LinkText: %s", m_LinkText.c_str());
|
||||
}
|
||||
@ -113,20 +121,10 @@ void EQEmu::SayLinkEngine::Reset()
|
||||
m_ItemData = nullptr;
|
||||
m_LootData = nullptr;
|
||||
m_ItemInst = nullptr;
|
||||
m_Proxy_unknown_1 = 0;
|
||||
m_ProxyItemID = 0;
|
||||
m_ProxyAugment1ID = 0;
|
||||
m_ProxyAugment2ID = 0;
|
||||
m_ProxyAugment3ID = 0;
|
||||
m_ProxyAugment4ID = 0;
|
||||
m_ProxyAugment5ID = 0;
|
||||
m_ProxyAugment6ID = 0;
|
||||
m_ProxyIsEvolving = 0;
|
||||
m_ProxyEvolveGroup = 0;
|
||||
m_ProxyEvolveLevel = 0;
|
||||
m_ProxyOrnamentIcon = 0;
|
||||
m_ProxyHash = 0;
|
||||
m_ProxyText = nullptr;
|
||||
|
||||
memset(&m_LinkBodyStruct, 0, sizeof(SayLinkBody_Struct));
|
||||
memset(&m_LinkProxyStruct, 0, sizeof(SayLinkProxy_Struct));
|
||||
|
||||
m_TaskUse = false;
|
||||
m_Link.clear();
|
||||
m_LinkBody.clear();
|
||||
@ -194,32 +192,32 @@ void EQEmu::SayLinkEngine::generate_body()
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_Proxy_unknown_1)
|
||||
m_LinkBodyStruct.unknown_1 = m_Proxy_unknown_1;
|
||||
if (m_ProxyItemID)
|
||||
m_LinkBodyStruct.item_id = m_ProxyItemID;
|
||||
if (m_ProxyAugment1ID)
|
||||
m_LinkBodyStruct.augment_1 = m_ProxyAugment1ID;
|
||||
if (m_ProxyAugment2ID)
|
||||
m_LinkBodyStruct.augment_2 = m_ProxyAugment2ID;
|
||||
if (m_ProxyAugment3ID)
|
||||
m_LinkBodyStruct.augment_3 = m_ProxyAugment3ID;
|
||||
if (m_ProxyAugment4ID)
|
||||
m_LinkBodyStruct.augment_4 = m_ProxyAugment4ID;
|
||||
if (m_ProxyAugment5ID)
|
||||
m_LinkBodyStruct.augment_5 = m_ProxyAugment5ID;
|
||||
if (m_ProxyAugment6ID)
|
||||
m_LinkBodyStruct.augment_6 = m_ProxyAugment6ID;
|
||||
if (m_ProxyIsEvolving)
|
||||
m_LinkBodyStruct.is_evolving = m_ProxyIsEvolving;
|
||||
if (m_ProxyEvolveGroup)
|
||||
m_LinkBodyStruct.evolve_group = m_ProxyEvolveGroup;
|
||||
if (m_ProxyEvolveLevel)
|
||||
m_LinkBodyStruct.evolve_level = m_ProxyEvolveLevel;
|
||||
if (m_ProxyOrnamentIcon)
|
||||
m_LinkBodyStruct.ornament_icon = m_ProxyOrnamentIcon;
|
||||
if (m_ProxyHash)
|
||||
m_LinkBodyStruct.hash = m_ProxyHash;
|
||||
if (m_LinkProxyStruct.action_id)
|
||||
m_LinkBodyStruct.action_id = m_LinkProxyStruct.action_id;
|
||||
if (m_LinkProxyStruct.item_id)
|
||||
m_LinkBodyStruct.item_id = m_LinkProxyStruct.item_id;
|
||||
if (m_LinkProxyStruct.augment_1)
|
||||
m_LinkBodyStruct.augment_1 = m_LinkProxyStruct.augment_1;
|
||||
if (m_LinkProxyStruct.augment_2)
|
||||
m_LinkBodyStruct.augment_2 = m_LinkProxyStruct.augment_2;
|
||||
if (m_LinkProxyStruct.augment_3)
|
||||
m_LinkBodyStruct.augment_3 = m_LinkProxyStruct.augment_3;
|
||||
if (m_LinkProxyStruct.augment_4)
|
||||
m_LinkBodyStruct.augment_4 = m_LinkProxyStruct.augment_4;
|
||||
if (m_LinkProxyStruct.augment_5)
|
||||
m_LinkBodyStruct.augment_5 = m_LinkProxyStruct.augment_5;
|
||||
if (m_LinkProxyStruct.augment_6)
|
||||
m_LinkBodyStruct.augment_6 = m_LinkProxyStruct.augment_6;
|
||||
if (m_LinkProxyStruct.is_evolving)
|
||||
m_LinkBodyStruct.is_evolving = m_LinkProxyStruct.is_evolving;
|
||||
if (m_LinkProxyStruct.evolve_group)
|
||||
m_LinkBodyStruct.evolve_group = m_LinkProxyStruct.evolve_group;
|
||||
if (m_LinkProxyStruct.evolve_level)
|
||||
m_LinkBodyStruct.evolve_level = m_LinkProxyStruct.evolve_level;
|
||||
if (m_LinkProxyStruct.ornament_icon)
|
||||
m_LinkBodyStruct.ornament_icon = m_LinkProxyStruct.ornament_icon;
|
||||
if (m_LinkProxyStruct.hash)
|
||||
m_LinkBodyStruct.hash = m_LinkProxyStruct.hash;
|
||||
|
||||
|
||||
if (m_TaskUse)
|
||||
@ -227,7 +225,7 @@ void EQEmu::SayLinkEngine::generate_body()
|
||||
|
||||
m_LinkBody = StringFormat(
|
||||
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X",
|
||||
(0x0F & m_LinkBodyStruct.unknown_1),
|
||||
(0x0F & m_LinkBodyStruct.action_id),
|
||||
(0x000FFFFF & m_LinkBodyStruct.item_id),
|
||||
(0x000FFFFF & m_LinkBodyStruct.augment_1),
|
||||
(0x000FFFFF & m_LinkBodyStruct.augment_2),
|
||||
@ -245,8 +243,8 @@ void EQEmu::SayLinkEngine::generate_body()
|
||||
|
||||
void EQEmu::SayLinkEngine::generate_text()
|
||||
{
|
||||
if (m_ProxyText != nullptr) {
|
||||
m_LinkText = m_ProxyText;
|
||||
if (m_LinkProxyStruct.text != nullptr) {
|
||||
m_LinkText = m_LinkProxyStruct.text;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@ namespace EQEmu
|
||||
} /*saylink*/
|
||||
|
||||
struct SayLinkBody_Struct {
|
||||
uint8 unknown_1; /* %1X */
|
||||
uint8 action_id; /* %1X */
|
||||
uint32 item_id; /* %05X */
|
||||
uint32 augment_1; /* %05X */
|
||||
uint32 augment_2; /* %05X */
|
||||
@ -56,13 +56,18 @@ namespace EQEmu
|
||||
uint32 augment_5; /* %05X */
|
||||
uint32 augment_6; /* %05X */
|
||||
uint8 is_evolving; /* %1X */
|
||||
uint32 evolve_group; /* %05X */
|
||||
uint32 evolve_group; /* %04X */
|
||||
uint8 evolve_level; /* %02X */
|
||||
uint32 ornament_icon; /* %05X */
|
||||
int hash; /* %08X */
|
||||
uint32 hash; /* %08X */
|
||||
};
|
||||
|
||||
struct SayLinkProxy_Struct : SayLinkBody_Struct {
|
||||
const char* text;
|
||||
};
|
||||
|
||||
class SayLinkEngine {
|
||||
// TODO: consider methods for direct 'saylink' assignments
|
||||
public:
|
||||
SayLinkEngine();
|
||||
|
||||
@ -72,29 +77,29 @@ namespace EQEmu
|
||||
void SetItemInst(const ItemInstance* item_inst) { m_ItemInst = item_inst; }
|
||||
|
||||
// mainly for saylinks..but, not limited to
|
||||
void SetProxyUnknown1(uint8 proxy_unknown_1) { m_Proxy_unknown_1 = proxy_unknown_1; }
|
||||
void SetProxyItemID(uint32 proxy_item_id) { m_ProxyItemID = proxy_item_id; }
|
||||
void SetProxyAugment1ID(uint32 proxy_augment_id) { m_ProxyAugment1ID = proxy_augment_id; }
|
||||
void SetProxyAugment2ID(uint32 proxy_augment_id) { m_ProxyAugment2ID = proxy_augment_id; }
|
||||
void SetProxyAugment3ID(uint32 proxy_augment_id) { m_ProxyAugment3ID = proxy_augment_id; }
|
||||
void SetProxyAugment4ID(uint32 proxy_augment_id) { m_ProxyAugment4ID = proxy_augment_id; }
|
||||
void SetProxyAugment5ID(uint32 proxy_augment_id) { m_ProxyAugment5ID = proxy_augment_id; }
|
||||
void SetProxyAugment6ID(uint32 proxy_augment_id) { m_ProxyAugment6ID = proxy_augment_id; }
|
||||
void SetProxyIsEvolving(uint8 proxy_is_evolving) { m_ProxyIsEvolving = proxy_is_evolving; }
|
||||
void SetProxyEvolveGroup(uint32 proxy_evolve_group) { m_ProxyEvolveGroup = proxy_evolve_group; }
|
||||
void SetProxyEvolveLevel(uint8 proxy_evolve_level) { m_ProxyEvolveLevel = proxy_evolve_level; }
|
||||
void SetProxyOrnamentIcon(uint32 proxy_ornament_icon) { m_ProxyOrnamentIcon = proxy_ornament_icon; }
|
||||
void SetProxyHash(int proxy_hash) { m_ProxyHash = proxy_hash; }
|
||||
void SetProxyActionID(uint8 proxy_action_id) { m_LinkProxyStruct.action_id = proxy_action_id; } // should always be '0'
|
||||
void SetProxyItemID(uint32 proxy_item_id) { m_LinkProxyStruct.item_id = proxy_item_id; }
|
||||
void SetProxyAugment1ID(uint32 proxy_augment_id) { m_LinkProxyStruct.augment_1 = proxy_augment_id; }
|
||||
void SetProxyAugment2ID(uint32 proxy_augment_id) { m_LinkProxyStruct.augment_2 = proxy_augment_id; }
|
||||
void SetProxyAugment3ID(uint32 proxy_augment_id) { m_LinkProxyStruct.augment_3 = proxy_augment_id; }
|
||||
void SetProxyAugment4ID(uint32 proxy_augment_id) { m_LinkProxyStruct.augment_4 = proxy_augment_id; }
|
||||
void SetProxyAugment5ID(uint32 proxy_augment_id) { m_LinkProxyStruct.augment_5 = proxy_augment_id; }
|
||||
void SetProxyAugment6ID(uint32 proxy_augment_id) { m_LinkProxyStruct.augment_6 = proxy_augment_id; }
|
||||
void SetProxyIsEvolving(uint8 proxy_is_evolving) { m_LinkProxyStruct.is_evolving = proxy_is_evolving; }
|
||||
void SetProxyEvolveGroup(uint32 proxy_evolve_group) { m_LinkProxyStruct.evolve_group = proxy_evolve_group; }
|
||||
void SetProxyEvolveLevel(uint8 proxy_evolve_level) { m_LinkProxyStruct.evolve_level = proxy_evolve_level; }
|
||||
void SetProxyOrnamentIcon(uint32 proxy_ornament_icon) { m_LinkProxyStruct.ornament_icon = proxy_ornament_icon; }
|
||||
void SetProxyHash(uint32 proxy_hash) { m_LinkProxyStruct.hash = proxy_hash; }
|
||||
|
||||
void SetProxyText(const char* proxy_text) { m_ProxyText = proxy_text; } // overrides standard text use
|
||||
void SetProxyText(const char* proxy_text) { m_LinkProxyStruct.text = proxy_text; } // overrides standard text use
|
||||
void SetTaskUse() { m_TaskUse = true; }
|
||||
|
||||
std::string GenerateLink();
|
||||
const std::string& GenerateLink();
|
||||
bool LinkError() { return m_Error; }
|
||||
|
||||
std::string Link() { return m_Link; } // contains full string format: '/12x' '<LinkBody>' '<LinkText>' '/12x'
|
||||
std::string LinkBody() { return m_LinkBody; } // contains string format: '<LinkBody>'
|
||||
std::string LinkText() { return m_LinkText; } // contains string format: '<LinkText>'
|
||||
const std::string& Link() { return m_Link; } // contains full string format: '\x12' '<LinkBody>' '<LinkText>' '\x12'
|
||||
const std::string& LinkBody() { return m_LinkBody; } // contains string format: '<LinkBody>'
|
||||
const std::string& LinkText() { return m_LinkText; } // contains string format: '<LinkText>'
|
||||
|
||||
void Reset();
|
||||
|
||||
@ -106,23 +111,9 @@ namespace EQEmu
|
||||
const ItemData* m_ItemData;
|
||||
const ServerLootItem_Struct* m_LootData;
|
||||
const ItemInstance* m_ItemInst;
|
||||
|
||||
uint8 m_Proxy_unknown_1;
|
||||
uint32 m_ProxyItemID;
|
||||
uint32 m_ProxyAugment1ID;
|
||||
uint32 m_ProxyAugment2ID;
|
||||
uint32 m_ProxyAugment3ID;
|
||||
uint32 m_ProxyAugment4ID;
|
||||
uint32 m_ProxyAugment5ID;
|
||||
uint32 m_ProxyAugment6ID;
|
||||
uint8 m_ProxyIsEvolving;
|
||||
uint32 m_ProxyEvolveGroup;
|
||||
uint8 m_ProxyEvolveLevel;
|
||||
uint32 m_ProxyOrnamentIcon;
|
||||
int m_ProxyHash;
|
||||
const char* m_ProxyText;
|
||||
bool m_TaskUse;
|
||||
SayLinkBody_Struct m_LinkBodyStruct;
|
||||
SayLinkProxy_Struct m_LinkProxyStruct;
|
||||
bool m_TaskUse;
|
||||
std::string m_Link;
|
||||
std::string m_LinkBody;
|
||||
std::string m_LinkText;
|
||||
|
||||
@ -190,6 +190,8 @@
|
||||
#define ServerOP_ReloadLogs 0x4010
|
||||
#define ServerOP_ReloadPerlExportSettings 0x4011
|
||||
#define ServerOP_CZSetEntityVariableByClientName 0x4012
|
||||
#define ServerOP_UCSServerStatusRequest 0x4013
|
||||
#define ServerOP_UCSServerStatusReply 0x4014
|
||||
/* Query Server OP Codes */
|
||||
#define ServerOP_QSPlayerLogTrades 0x5010
|
||||
#define ServerOP_QSPlayerLogHandins 0x5011
|
||||
@ -1278,6 +1280,17 @@ struct ServerRequestTellQueue_Struct {
|
||||
char name[64];
|
||||
};
|
||||
|
||||
struct UCSServerStatus_Struct {
|
||||
uint8 available; // non-zero=true, 0=false
|
||||
union {
|
||||
struct {
|
||||
uint16 port;
|
||||
uint16 unused;
|
||||
};
|
||||
uint32 timestamp;
|
||||
};
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#endif
|
||||
|
||||
@ -110,6 +110,41 @@ uint32 SharedDatabase::GetTotalTimeEntitledOnAccount(uint32 AccountID) {
|
||||
return EntitledTime;
|
||||
}
|
||||
|
||||
void SharedDatabase::SetMailKey(int CharID, int IPAddress, int MailKey)
|
||||
{
|
||||
char MailKeyString[17];
|
||||
|
||||
if (RuleB(Chat, EnableMailKeyIPVerification) == true)
|
||||
sprintf(MailKeyString, "%08X%08X", IPAddress, MailKey);
|
||||
else
|
||||
sprintf(MailKeyString, "%08X", MailKey);
|
||||
|
||||
std::string query = StringFormat("UPDATE character_data SET mailkey = '%s' WHERE id = '%i'",
|
||||
MailKeyString, CharID);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
Log(Logs::General, Logs::Error, "SharedDatabase::SetMailKey(%i, %s) : %s", CharID, MailKeyString, results.ErrorMessage().c_str());
|
||||
|
||||
}
|
||||
|
||||
std::string SharedDatabase::GetMailKey(int CharID, bool key_only)
|
||||
{
|
||||
std::string query = StringFormat("SELECT `mailkey` FROM `character_data` WHERE `id`='%i' LIMIT 1", CharID);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
Log(Logs::Detail, Logs::MySQLError, "Error retrieving mailkey from database: %s", results.ErrorMessage().c_str());
|
||||
return std::string();
|
||||
}
|
||||
|
||||
auto row = results.begin();
|
||||
std::string mail_key = row[0];
|
||||
|
||||
if (mail_key.length() > 8 && key_only)
|
||||
return mail_key.substr(8);
|
||||
else
|
||||
return mail_key;
|
||||
}
|
||||
|
||||
bool SharedDatabase::SaveCursor(uint32 char_id, std::list<EQEmu::ItemInstance*>::const_iterator &start, std::list<EQEmu::ItemInstance*>::const_iterator &end)
|
||||
{
|
||||
// Delete cursor items
|
||||
|
||||
@ -72,6 +72,8 @@ class SharedDatabase : public Database
|
||||
void SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* message);
|
||||
bool GetCommandSettings(std::map<std::string, std::pair<uint8, std::vector<std::string>>> &command_settings);
|
||||
uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID);
|
||||
void SetMailKey(int CharID, int IPAddress, int MailKey);
|
||||
std::string GetMailKey(int CharID, bool key_only = false);
|
||||
|
||||
/*
|
||||
Character InventoryProfile
|
||||
|
||||
@ -972,7 +972,6 @@ bool IsCastWhileInvis(uint16 spell_id);
|
||||
bool IsEffectIgnoredInStacking(int spa);
|
||||
|
||||
int CalcPetHp(int levelb, int classb, int STA = 75);
|
||||
const char *GetRandPetName();
|
||||
int GetSpellEffectDescNum(uint16 spell_id);
|
||||
DmgShieldType GetDamageShieldType(uint16 spell_id, int32 DSType = 0);
|
||||
bool DetrimentalSpellAllowsRest(uint16 spell_id);
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||
*/
|
||||
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9120
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9122
|
||||
#ifdef BOTS
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9018
|
||||
#else
|
||||
|
||||
@ -28,6 +28,10 @@
|
||||
extern Database database;
|
||||
extern uint32 ChatMessagesSent;
|
||||
|
||||
void ServerToClient45SayLink(std::string& clientSayLink, const std::string& serverSayLink);
|
||||
void ServerToClient50SayLink(std::string& clientSayLink, const std::string& serverSayLink);
|
||||
void ServerToClient55SayLink(std::string& clientSayLink, const std::string& serverSayLink);
|
||||
|
||||
ChatChannel::ChatChannel(std::string inName, std::string inOwner, std::string inPassword, bool inPermanent, int inMinimumStatus) :
|
||||
DeleteTimer(0) {
|
||||
|
||||
@ -384,6 +388,8 @@ void ChatChannel::SendMessageToChannel(std::string Message, Client* Sender) {
|
||||
|
||||
if(!Sender) return;
|
||||
|
||||
std::string cv_messages[EQEmu::versions::ClientVersionCount];
|
||||
|
||||
ChatMessagesSent++;
|
||||
|
||||
LinkedListIterator<Client*> iterator(ClientsInChannel);
|
||||
@ -398,7 +404,28 @@ void ChatChannel::SendMessageToChannel(std::string Message, Client* Sender) {
|
||||
{
|
||||
Log(Logs::Detail, Logs::UCS_Server, "Sending message to %s from %s",
|
||||
ChannelClient->GetName().c_str(), Sender->GetName().c_str());
|
||||
ChannelClient->SendChannelMessage(Name, Message, Sender);
|
||||
|
||||
if (cv_messages[static_cast<uint32>(ChannelClient->GetClientVersion())].length() == 0) {
|
||||
switch (ChannelClient->GetClientVersion()) {
|
||||
case EQEmu::versions::ClientVersion::Titanium:
|
||||
ServerToClient45SayLink(cv_messages[static_cast<uint32>(ChannelClient->GetClientVersion())], Message);
|
||||
break;
|
||||
case EQEmu::versions::ClientVersion::SoF:
|
||||
case EQEmu::versions::ClientVersion::SoD:
|
||||
case EQEmu::versions::ClientVersion::UF:
|
||||
ServerToClient50SayLink(cv_messages[static_cast<uint32>(ChannelClient->GetClientVersion())], Message);
|
||||
break;
|
||||
case EQEmu::versions::ClientVersion::RoF:
|
||||
ServerToClient55SayLink(cv_messages[static_cast<uint32>(ChannelClient->GetClientVersion())], Message);
|
||||
break;
|
||||
case EQEmu::versions::ClientVersion::RoF2:
|
||||
default:
|
||||
cv_messages[static_cast<uint32>(ChannelClient->GetClientVersion())] = Message;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ChannelClient->SendChannelMessage(Name, cv_messages[static_cast<uint32>(ChannelClient->GetClientVersion())], Sender);
|
||||
}
|
||||
|
||||
iterator.Advance();
|
||||
@ -655,3 +682,118 @@ std::string CapitaliseName(std::string inString) {
|
||||
return NormalisedName;
|
||||
}
|
||||
|
||||
void ServerToClient45SayLink(std::string& clientSayLink, const std::string& serverSayLink) {
|
||||
if (serverSayLink.find('\x12') == std::string::npos) {
|
||||
clientSayLink = serverSayLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(serverSayLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
if (segments[segment_iter].length() <= 56) {
|
||||
clientSayLink.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: ^^^^^ ^ ^^^^^
|
||||
|
||||
clientSayLink.push_back('\x12');
|
||||
clientSayLink.append(segments[segment_iter].substr(0, 31));
|
||||
clientSayLink.append(segments[segment_iter].substr(36, 5));
|
||||
|
||||
if (segments[segment_iter][41] == '0')
|
||||
clientSayLink.push_back(segments[segment_iter][42]);
|
||||
else
|
||||
clientSayLink.push_back('F');
|
||||
|
||||
clientSayLink.append(segments[segment_iter].substr(48));
|
||||
clientSayLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
clientSayLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServerToClient50SayLink(std::string& clientSayLink, const std::string& serverSayLink) {
|
||||
if (serverSayLink.find('\x12') == std::string::npos) {
|
||||
clientSayLink = serverSayLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(serverSayLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
if (segments[segment_iter].length() <= 56) {
|
||||
clientSayLink.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: ^^^^^ ^
|
||||
|
||||
clientSayLink.push_back('\x12');
|
||||
clientSayLink.append(segments[segment_iter].substr(0, 31));
|
||||
clientSayLink.append(segments[segment_iter].substr(36, 5));
|
||||
|
||||
if (segments[segment_iter][41] == '0')
|
||||
clientSayLink.push_back(segments[segment_iter][42]);
|
||||
else
|
||||
clientSayLink.push_back('F');
|
||||
|
||||
clientSayLink.append(segments[segment_iter].substr(43));
|
||||
clientSayLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
clientSayLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServerToClient55SayLink(std::string& clientSayLink, const std::string& serverSayLink) {
|
||||
if (serverSayLink.find('\x12') == std::string::npos) {
|
||||
clientSayLink = serverSayLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(serverSayLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
if (segments[segment_iter].length() <= 56) {
|
||||
clientSayLink.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: ^
|
||||
|
||||
clientSayLink.push_back('\x12');
|
||||
clientSayLink.append(segments[segment_iter].substr(0, 41));
|
||||
|
||||
if (segments[segment_iter][41] == '0')
|
||||
clientSayLink.push_back(segments[segment_iter][42]);
|
||||
else
|
||||
clientSayLink.push_back('F');
|
||||
|
||||
clientSayLink.append(segments[segment_iter].substr(43));
|
||||
clientSayLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
clientSayLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -513,6 +513,7 @@ Client::Client(std::shared_ptr<EQStreamInterface> eqs) {
|
||||
GlobalChatLimiterTimer = new Timer(RuleI(Chat, IntervalDurationMS));
|
||||
|
||||
TypeOfConnection = ConnectionTypeUnknown;
|
||||
ClientVersion_ = EQEmu::versions::ClientVersion::Unknown;
|
||||
|
||||
UnderfootOrLater = false;
|
||||
}
|
||||
@ -681,6 +682,7 @@ void Clientlist::Process()
|
||||
it = ClientChatConnections.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
}
|
||||
@ -2134,34 +2136,62 @@ void Client::SetConnectionType(char c) {
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 'S':
|
||||
{
|
||||
TypeOfConnection = ConnectionTypeCombined;
|
||||
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Combined (SoF/SoD)");
|
||||
break;
|
||||
}
|
||||
case 'U':
|
||||
{
|
||||
TypeOfConnection = ConnectionTypeCombined;
|
||||
UnderfootOrLater = true;
|
||||
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Combined (Underfoot+)");
|
||||
break;
|
||||
}
|
||||
case 'M':
|
||||
{
|
||||
TypeOfConnection = ConnectionTypeMail;
|
||||
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Mail (6.2 or Titanium client)");
|
||||
break;
|
||||
}
|
||||
case 'C':
|
||||
case EQEmu::versions::ucsTitaniumChat:
|
||||
{
|
||||
TypeOfConnection = ConnectionTypeChat;
|
||||
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Chat (6.2 or Titanium client)");
|
||||
ClientVersion_ = EQEmu::versions::ClientVersion::Titanium;
|
||||
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Chat (Titanium)");
|
||||
break;
|
||||
}
|
||||
case EQEmu::versions::ucsTitaniumMail:
|
||||
{
|
||||
TypeOfConnection = ConnectionTypeMail;
|
||||
ClientVersion_ = EQEmu::versions::ClientVersion::Titanium;
|
||||
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Mail (Titanium)");
|
||||
break;
|
||||
}
|
||||
case EQEmu::versions::ucsSoFCombined:
|
||||
{
|
||||
TypeOfConnection = ConnectionTypeCombined;
|
||||
ClientVersion_ = EQEmu::versions::ClientVersion::SoF;
|
||||
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Combined (SoF)");
|
||||
break;
|
||||
}
|
||||
case EQEmu::versions::ucsSoDCombined:
|
||||
{
|
||||
TypeOfConnection = ConnectionTypeCombined;
|
||||
ClientVersion_ = EQEmu::versions::ClientVersion::SoD;
|
||||
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Combined (SoD)");
|
||||
break;
|
||||
}
|
||||
case EQEmu::versions::ucsUFCombined:
|
||||
{
|
||||
TypeOfConnection = ConnectionTypeCombined;
|
||||
ClientVersion_ = EQEmu::versions::ClientVersion::UF;
|
||||
UnderfootOrLater = true;
|
||||
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Combined (Underfoot)");
|
||||
break;
|
||||
}
|
||||
case EQEmu::versions::ucsRoFCombined:
|
||||
{
|
||||
TypeOfConnection = ConnectionTypeCombined;
|
||||
ClientVersion_ = EQEmu::versions::ClientVersion::RoF;
|
||||
UnderfootOrLater = true;
|
||||
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Combined (RoF)");
|
||||
break;
|
||||
}
|
||||
case EQEmu::versions::ucsRoF2Combined:
|
||||
{
|
||||
TypeOfConnection = ConnectionTypeCombined;
|
||||
ClientVersion_ = EQEmu::versions::ClientVersion::RoF2;
|
||||
UnderfootOrLater = true;
|
||||
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Combined (RoF2)");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
TypeOfConnection = ConnectionTypeUnknown;
|
||||
ClientVersion_ = EQEmu::versions::ClientVersion::Unknown;
|
||||
Log(Logs::Detail, Logs::UCS_Server, "Connection type is unknown.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,8 +139,11 @@ public:
|
||||
std::string MailBoxName();
|
||||
int GetMailBoxNumber() { return CurrentMailBox; }
|
||||
int GetMailBoxNumber(std::string CharacterName);
|
||||
|
||||
void SetConnectionType(char c);
|
||||
ConnectionType GetConnectionType() { return TypeOfConnection; }
|
||||
EQEmu::versions::ClientVersion GetClientVersion() { return ClientVersion_; }
|
||||
|
||||
inline bool IsMailConnection() { return (TypeOfConnection == ConnectionTypeMail) || (TypeOfConnection == ConnectionTypeCombined); }
|
||||
void SendNotification(int MailBoxNumber, std::string From, std::string Subject, int MessageID);
|
||||
void ChangeMailBox(int NewMailBox);
|
||||
@ -167,7 +170,9 @@ private:
|
||||
Timer *GlobalChatLimiterTimer; //60 seconds
|
||||
int AttemptedMessages;
|
||||
bool ForceDisconnect;
|
||||
|
||||
ConnectionType TypeOfConnection;
|
||||
EQEmu::versions::ClientVersion ClientVersion_;
|
||||
bool UnderfootOrLater;
|
||||
};
|
||||
|
||||
@ -183,7 +188,6 @@ public:
|
||||
void ProcessOPMailCommand(Client *c, std::string CommandString);
|
||||
|
||||
private:
|
||||
|
||||
EQ::Net::EQStreamManager *chatsf;
|
||||
|
||||
std::list<Client*> ClientChatConnections;
|
||||
|
||||
@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "../common/misc_functions.h"
|
||||
#include "../common/packet_functions.h"
|
||||
#include "../common/md5.h"
|
||||
#include "../common/string_util.h"
|
||||
#include "worldserver.h"
|
||||
#include "clientlist.h"
|
||||
#include "ucsconfig.h"
|
||||
@ -41,6 +42,10 @@ extern Database database;
|
||||
|
||||
void ProcessMailTo(Client *c, std::string from, std::string subject, std::string message);
|
||||
|
||||
void Client45ToServerSayLink(std::string& serverSayLink, const std::string& clientSayLink);
|
||||
void Client50ToServerSayLink(std::string& serverSayLink, const std::string& clientSayLink);
|
||||
void Client55ToServerSayLink(std::string& serverSayLink, const std::string& clientSayLink);
|
||||
|
||||
WorldServer::WorldServer()
|
||||
{
|
||||
m_connection.reset(new EQ::Net::ServertalkClient(Config->WorldIP, Config->WorldTCPPort, false, "UCS", Config->SharedKey));
|
||||
@ -94,7 +99,26 @@ void WorldServer::ProcessMessage(uint16 opcode, EQ::Net::Packet &p)
|
||||
|
||||
if (Message[0] == ';')
|
||||
{
|
||||
c->SendChannelMessageByNumber(Message.substr(1, std::string::npos));
|
||||
std::string new_message;
|
||||
switch (c->GetClientVersion()) {
|
||||
case EQEmu::versions::ClientVersion::Titanium:
|
||||
Client45ToServerSayLink(new_message, Message.substr(1, std::string::npos));
|
||||
break;
|
||||
case EQEmu::versions::ClientVersion::SoF:
|
||||
case EQEmu::versions::ClientVersion::SoD:
|
||||
case EQEmu::versions::ClientVersion::UF:
|
||||
Client50ToServerSayLink(new_message, Message.substr(1, std::string::npos));
|
||||
break;
|
||||
case EQEmu::versions::ClientVersion::RoF:
|
||||
Client55ToServerSayLink(new_message, Message.substr(1, std::string::npos));
|
||||
break;
|
||||
case EQEmu::versions::ClientVersion::RoF2:
|
||||
default:
|
||||
new_message = Message.substr(1, std::string::npos);
|
||||
break;
|
||||
}
|
||||
|
||||
c->SendChannelMessageByNumber(new_message);
|
||||
}
|
||||
else if (Message[0] == '[')
|
||||
{
|
||||
@ -116,3 +140,108 @@ void WorldServer::ProcessMessage(uint16 opcode, EQ::Net::Packet &p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Client45ToServerSayLink(std::string& serverSayLink, const std::string& clientSayLink) {
|
||||
if (clientSayLink.find('\x12') == std::string::npos) {
|
||||
serverSayLink = clientSayLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(clientSayLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
if (segments[segment_iter].length() <= 45) {
|
||||
serverSayLink.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: ^^^^^ ^ ^^^^^
|
||||
|
||||
serverSayLink.push_back('\x12');
|
||||
serverSayLink.append(segments[segment_iter].substr(0, 31));
|
||||
serverSayLink.append("00000");
|
||||
serverSayLink.append(segments[segment_iter].substr(31, 5));
|
||||
serverSayLink.push_back('0');
|
||||
serverSayLink.push_back(segments[segment_iter][36]);
|
||||
serverSayLink.append("00000");
|
||||
serverSayLink.append(segments[segment_iter].substr(37));
|
||||
serverSayLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
serverSayLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Client50ToServerSayLink(std::string& serverSayLink, const std::string& clientSayLink) {
|
||||
if (clientSayLink.find('\x12') == std::string::npos) {
|
||||
serverSayLink = clientSayLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(clientSayLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
if (segments[segment_iter].length() <= 50) {
|
||||
serverSayLink.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: ^^^^^ ^
|
||||
|
||||
serverSayLink.push_back('\x12');
|
||||
serverSayLink.append(segments[segment_iter].substr(0, 31));
|
||||
serverSayLink.append("00000");
|
||||
serverSayLink.append(segments[segment_iter].substr(31, 5));
|
||||
serverSayLink.push_back('0');
|
||||
serverSayLink.append(segments[segment_iter].substr(36));
|
||||
serverSayLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
serverSayLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Client55ToServerSayLink(std::string& serverSayLink, const std::string& clientSayLink) {
|
||||
if (clientSayLink.find('\x12') == std::string::npos) {
|
||||
serverSayLink = clientSayLink;
|
||||
return;
|
||||
}
|
||||
|
||||
auto segments = SplitString(clientSayLink, '\x12');
|
||||
|
||||
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||
if (segment_iter & 1) {
|
||||
if (segments[segment_iter].length() <= 55) {
|
||||
serverSayLink.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: ^
|
||||
|
||||
serverSayLink.push_back('\x12');
|
||||
serverSayLink.append(segments[segment_iter].substr(0, 41));
|
||||
serverSayLink.push_back('0');
|
||||
serverSayLink.append(segments[segment_iter].substr(41));
|
||||
serverSayLink.push_back('\x12');
|
||||
}
|
||||
else {
|
||||
serverSayLink.append(segments[segment_iter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,6 +165,7 @@ OP_GMNameChange=0x3077 # Was 0x4434
|
||||
OP_GMLastName=0x4dd7 # Was 0x3077
|
||||
|
||||
# Misc Opcodes
|
||||
OP_QueryUCSServerStatus=0x6964
|
||||
OP_InspectRequest=0x23f1
|
||||
OP_InspectAnswer=0x5794
|
||||
OP_InspectMessageUpdate=0x3064
|
||||
|
||||
@ -164,6 +164,7 @@ OP_GMNameChange=0x035f
|
||||
OP_GMLastName=0x46ce
|
||||
|
||||
# Misc Opcodes
|
||||
OP_QueryUCSServerStatus=0x398f
|
||||
OP_InspectRequest=0x57bc
|
||||
OP_InspectAnswer=0x71ac
|
||||
OP_InspectMessageUpdate=0x4d25
|
||||
|
||||
@ -165,6 +165,7 @@ OP_GMKill=0x6685 # C
|
||||
OP_GMNameChange=0x565d # C
|
||||
OP_GMLastName=0x3563 # C
|
||||
|
||||
OP_QueryUCSServerStatus=0x4036
|
||||
OP_InspectAnswer=0x4938 # C
|
||||
OP_Action2=0x7e4d # C OP_Damage?
|
||||
OP_BeginCast=0x0d5a # C
|
||||
|
||||
@ -168,6 +168,7 @@ OP_GMKill=0x799c # C
|
||||
OP_GMNameChange=0x0f48 # C
|
||||
OP_GMLastName=0x7bfb # C
|
||||
|
||||
OP_QueryUCSServerStatus=0x4481
|
||||
OP_InspectAnswer=0x0c2b # C
|
||||
OP_BeginCast=0x0d5a # C
|
||||
OP_ColoredText=0x71bf # C
|
||||
|
||||
@ -121,17 +121,13 @@ if [[ "$OS" == "Debian" ]]; then
|
||||
apt-get $apt_options install libsodium18
|
||||
apt-get $apt_options install libjson-perl
|
||||
|
||||
# If libsodium18 isn't installed (Debian), let's download both that and the dev package and install them.
|
||||
if dpkg-query -s "libsodium18" 1>/dev/null 2>&1; then
|
||||
echo "Sodium library already installed."
|
||||
else
|
||||
wget http://ftp.us.debian.org/debian/pool/main/libs/libsodium/libsodium-dev_1.0.11-1~bpo8+1_amd64.deb -O /home/eqemu/libsodium-dev.deb
|
||||
wget http://ftp.us.debian.org/debian/pool/main/libs/libsodium/libsodium18_1.0.11-1~bpo8+1_amd64.deb -O /home/eqemu/libsodium18.deb
|
||||
dpkg -i /home/eqemu/libsodium*.deb
|
||||
# Cleanup after ourselves
|
||||
rm -f /home/eqemu/libsodium-dev.deb
|
||||
rm -f /home/eqemu/libsodium18.deb
|
||||
fi
|
||||
# Install libsodium
|
||||
wget http://ftp.us.debian.org/debian/pool/main/libs/libsodium/libsodium-dev_1.0.11-1~bpo8+1_amd64.deb -O /home/eqemu/libsodium-dev.deb
|
||||
wget http://ftp.us.debian.org/debian/pool/main/libs/libsodium/libsodium18_1.0.11-1~bpo8+1_amd64.deb -O /home/eqemu/libsodium18.deb
|
||||
dpkg -i /home/eqemu/libsodium*.deb
|
||||
# Cleanup after ourselves
|
||||
rm -f /home/eqemu/libsodium-dev.deb
|
||||
rm -f /home/eqemu/libsodium18.deb
|
||||
|
||||
#::: Install FTP for remote FTP access
|
||||
echo "proftpd-basic shared/proftpd/inetd_or_standalone select standalone" | debconf-set-selections
|
||||
|
||||
@ -374,6 +374,8 @@
|
||||
9118|2018_02_04_Charm_Stats.sql|SHOW COLUMNS FROM `npc_types` LIKE 'charm_ac'|empty|
|
||||
9119|2018_02_10_GlobalLoot.sql|SHOW TABLES LIKE 'global_loot'|empty|
|
||||
9120|2018_02_13_Heading.sql|SELECT value FROM variables WHERE varname = 'fixed_heading'|empty|
|
||||
9121|2018_02_18_bug_reports.sql|SHOW TABLES LIKE 'bug_reports'|empty|
|
||||
9122|2018_03_07_ucs_command.sql|SELECT * FROM `command_settings` WHERE `command` LIKE 'ucs'|empty|
|
||||
|
||||
# Upgrade conditions:
|
||||
# This won't be needed after this system is implemented, but it is used database that are not
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
UPDATE spawn2 SET heading = heading * 8.0 / 4.0;
|
||||
UPDATE grid_entries SET heading = heading * 8.0 / 4.0 WHERE heading <> -1;
|
||||
INSERT INTO variables (varname, value) VALUES ('fixed_heading', 1); -- hack
|
||||
INSERT INTO variables (varname, value, information) VALUES ('fixed_heading', 1, 'manifest heading fix hack'); -- hack
|
||||
|
||||
44
utils/sql/git/required/2018_02_18_bug_reports.sql
Normal file
44
utils/sql/git/required/2018_02_18_bug_reports.sql
Normal file
@ -0,0 +1,44 @@
|
||||
CREATE TABLE `bug_reports` (
|
||||
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`zone` VARCHAR(32) NOT NULL DEFAULT 'Unknown',
|
||||
`client_version_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`client_version_name` VARCHAR(24) NOT NULL DEFAULT 'Unknown',
|
||||
`account_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`character_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`character_name` VARCHAR(64) NOT NULL DEFAULT 'Unknown',
|
||||
`reporter_spoof` TINYINT(1) NOT NULL DEFAULT '1',
|
||||
`category_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`category_name` VARCHAR(64) NOT NULL DEFAULT 'Other',
|
||||
`reporter_name` VARCHAR(64) NOT NULL DEFAULT 'Unknown',
|
||||
`ui_path` VARCHAR(128) NOT NULL DEFAULT 'Unknown',
|
||||
`pos_x` FLOAT NOT NULL DEFAULT '0',
|
||||
`pos_y` FLOAT NOT NULL DEFAULT '0',
|
||||
`pos_z` FLOAT NOT NULL DEFAULT '0',
|
||||
`heading` INT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`time_played` INT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`target_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`target_name` VARCHAR(64) NOT NULL DEFAULT 'Unknown',
|
||||
`optional_info_mask` INT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`_can_duplicate` TINYINT(1) NOT NULL DEFAULT '0',
|
||||
`_crash_bug` TINYINT(1) NOT NULL DEFAULT '0',
|
||||
`_target_info` TINYINT(1) NOT NULL DEFAULT '0',
|
||||
`_character_flags` TINYINT(1) NOT NULL DEFAULT '0',
|
||||
`_unknown_value` TINYINT(1) NOT NULL DEFAULT '0',
|
||||
`bug_report` VARCHAR(1024) NOT NULL DEFAULT '',
|
||||
`system_info` VARCHAR(1024) NOT NULL DEFAULT '',
|
||||
`report_datetime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`bug_status` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`last_review` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`last_reviewer` VARCHAR(64) NOT NULL DEFAULT 'None',
|
||||
`reviewer_notes` VARCHAR(1024) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE INDEX `id` (`id`)
|
||||
)
|
||||
COLLATE='utf8_general_ci'
|
||||
ENGINE=InnoDB
|
||||
;
|
||||
|
||||
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES
|
||||
(1, 'Bugs:ReportingSystemActive', 'true', 'Activates bug reporting'),
|
||||
(1, 'Bugs:UseOldReportingMethod', 'true', 'Forces the use of the old bug reporting system'),
|
||||
(1, 'Bugs:DumpTargetEntity', 'false', 'Dumps the target entity, if one is provided');
|
||||
1
utils/sql/git/required/2018_03_07_ucs_command.sql
Normal file
1
utils/sql/git/required/2018_03_07_ucs_command.sql
Normal file
@ -0,0 +1 @@
|
||||
INSERT INTO `command_settings` VALUES ('ucs', '0', '');
|
||||
106
world/client.cpp
106
world/client.cpp
@ -84,8 +84,9 @@ extern LoginServerList loginserverlist;
|
||||
extern ClientList client_list;
|
||||
extern EQEmu::Random emu_random;
|
||||
extern uint32 numclients;
|
||||
extern volatile bool RunLoops;
|
||||
extern NatsManager nats;
|
||||
extern volatile bool RunLoops;
|
||||
extern volatile bool UCSServerAvailable_;
|
||||
|
||||
Client::Client(EQStreamInterface* ieqs)
|
||||
: autobootup_timeout(RuleI(World, ZoneAutobootTimeoutMS)),
|
||||
@ -894,53 +895,84 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
}
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
|
||||
|
||||
// set mailkey - used for duration of character session
|
||||
int MailKey = emu_random.Int(1, INT_MAX);
|
||||
|
||||
database.SetMailKey(charid, GetIP(), MailKey);
|
||||
if (UCSServerAvailable_) {
|
||||
const WorldConfig *Config = WorldConfig::get();
|
||||
std::string buffer;
|
||||
|
||||
char ConnectionType;
|
||||
EQEmu::versions::UCSVersion ConnectionType = EQEmu::versions::ucsUnknown;
|
||||
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater)
|
||||
ConnectionType = 'U';
|
||||
else if (m_ClientVersionBit & EQEmu::versions::bit_SoFAndLater)
|
||||
ConnectionType = 'S';
|
||||
else
|
||||
ConnectionType = 'C';
|
||||
// chat server packet
|
||||
switch (GetClientVersion()) {
|
||||
case EQEmu::versions::ClientVersion::Titanium:
|
||||
ConnectionType = EQEmu::versions::ucsTitaniumChat;
|
||||
break;
|
||||
case EQEmu::versions::ClientVersion::SoF:
|
||||
ConnectionType = EQEmu::versions::ucsSoFCombined;
|
||||
break;
|
||||
case EQEmu::versions::ClientVersion::SoD:
|
||||
ConnectionType = EQEmu::versions::ucsSoDCombined;
|
||||
break;
|
||||
case EQEmu::versions::ClientVersion::UF:
|
||||
ConnectionType = EQEmu::versions::ucsUFCombined;
|
||||
break;
|
||||
case EQEmu::versions::ClientVersion::RoF:
|
||||
ConnectionType = EQEmu::versions::ucsRoFCombined;
|
||||
break;
|
||||
case EQEmu::versions::ClientVersion::RoF2:
|
||||
ConnectionType = EQEmu::versions::ucsRoF2Combined;
|
||||
break;
|
||||
default:
|
||||
ConnectionType = EQEmu::versions::ucsUnknown;
|
||||
break;
|
||||
}
|
||||
|
||||
auto outapp2 = new EQApplicationPacket(OP_SetChatServer);
|
||||
char buffer[112];
|
||||
buffer = StringFormat("%s,%i,%s.%s,%c%08X",
|
||||
Config->ChatHost.c_str(),
|
||||
Config->ChatPort,
|
||||
Config->ShortName.c_str(),
|
||||
GetCharName(),
|
||||
ConnectionType,
|
||||
MailKey
|
||||
);
|
||||
|
||||
const WorldConfig *Config = WorldConfig::get();
|
||||
outapp = new EQApplicationPacket(OP_SetChatServer, (buffer.length() + 1));
|
||||
memcpy(outapp->pBuffer, buffer.c_str(), buffer.length());
|
||||
outapp->pBuffer[buffer.length()] = '\0';
|
||||
|
||||
sprintf(buffer,"%s,%i,%s.%s,%c%08X",
|
||||
Config->ChatHost.c_str(),
|
||||
Config->ChatPort,
|
||||
Config->ShortName.c_str(),
|
||||
this->GetCharName(), ConnectionType, MailKey
|
||||
);
|
||||
outapp2->size=strlen(buffer)+1;
|
||||
outapp2->pBuffer = new uchar[outapp2->size];
|
||||
memcpy(outapp2->pBuffer,buffer,outapp2->size);
|
||||
QueuePacket(outapp2);
|
||||
safe_delete(outapp2);
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
|
||||
outapp2 = new EQApplicationPacket(OP_SetChatServer2);
|
||||
// mail server packet
|
||||
switch (GetClientVersion()) {
|
||||
case EQEmu::versions::ClientVersion::Titanium:
|
||||
ConnectionType = EQEmu::versions::ucsTitaniumMail;
|
||||
break;
|
||||
default:
|
||||
// retain value from previous switch
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_TitaniumAndEarlier)
|
||||
ConnectionType = 'M';
|
||||
buffer = StringFormat("%s,%i,%s.%s,%c%08X",
|
||||
Config->MailHost.c_str(),
|
||||
Config->MailPort,
|
||||
Config->ShortName.c_str(),
|
||||
GetCharName(),
|
||||
ConnectionType,
|
||||
MailKey
|
||||
);
|
||||
|
||||
sprintf(buffer,"%s,%i,%s.%s,%c%08X",
|
||||
Config->MailHost.c_str(),
|
||||
Config->MailPort,
|
||||
Config->ShortName.c_str(),
|
||||
this->GetCharName(), ConnectionType, MailKey
|
||||
);
|
||||
outapp2->size=strlen(buffer)+1;
|
||||
outapp2->pBuffer = new uchar[outapp2->size];
|
||||
memcpy(outapp2->pBuffer,buffer,outapp2->size);
|
||||
QueuePacket(outapp2);
|
||||
safe_delete(outapp2);
|
||||
outapp = new EQApplicationPacket(OP_SetChatServer2, (buffer.length() + 1));
|
||||
memcpy(outapp->pBuffer, buffer.c_str(), buffer.length());
|
||||
outapp->pBuffer[buffer.length()] = '\0';
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
EnterWorld();
|
||||
|
||||
|
||||
@ -68,6 +68,7 @@ public:
|
||||
inline const char* GetLSKey() { if (cle) { return cle->GetLSKey(); } return "NOKEY"; }
|
||||
inline uint32 GetCharID() { return charid; }
|
||||
inline const char* GetCharName() { return char_name; }
|
||||
inline EQEmu::versions::ClientVersion GetClientVersion() { return m_ClientVersion; }
|
||||
inline ClientListEntry* GetCLE() { return cle; }
|
||||
inline void SetCLE(ClientListEntry* iCLE) { cle = iCLE; }
|
||||
private:
|
||||
|
||||
@ -465,6 +465,8 @@ int main(int argc, char** argv) {
|
||||
connection->Handle()->RemoteIP(), connection->Handle()->RemotePort(), connection->GetUUID());
|
||||
|
||||
UCSLink.SetConnection(connection);
|
||||
|
||||
zoneserver_list.UpdateUCSServerAvailable();
|
||||
});
|
||||
|
||||
server_connection->OnConnectionRemoved("UCS", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
||||
@ -472,6 +474,8 @@ int main(int argc, char** argv) {
|
||||
connection->GetUUID());
|
||||
|
||||
UCSLink.SetConnection(nullptr);
|
||||
|
||||
zoneserver_list.UpdateUCSServerAvailable(false);
|
||||
});
|
||||
|
||||
server_connection->OnConnectionIdentified("WebInterface", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
||||
|
||||
@ -516,23 +516,6 @@ void WorldDatabase::GetLauncherList(std::vector<std::string> &rl) {
|
||||
|
||||
}
|
||||
|
||||
void WorldDatabase::SetMailKey(int CharID, int IPAddress, int MailKey)
|
||||
{
|
||||
char MailKeyString[17];
|
||||
|
||||
if(RuleB(Chat, EnableMailKeyIPVerification) == true)
|
||||
sprintf(MailKeyString, "%08X%08X", IPAddress, MailKey);
|
||||
else
|
||||
sprintf(MailKeyString, "%08X", MailKey);
|
||||
|
||||
std::string query = StringFormat("UPDATE character_data SET mailkey = '%s' WHERE id = '%i'",
|
||||
MailKeyString, CharID);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
Log(Logs::General, Logs::Error, "WorldDatabase::SetMailKey(%i, %s) : %s", CharID, MailKeyString, results.ErrorMessage().c_str());
|
||||
|
||||
}
|
||||
|
||||
bool WorldDatabase::GetCharacterLevel(const char *name, int &level)
|
||||
{
|
||||
std::string query = StringFormat("SELECT level FROM character_data WHERE name = '%s'", name);
|
||||
|
||||
@ -34,7 +34,6 @@ public:
|
||||
int MoveCharacterToBind(int CharID, uint8 bindnum = 0);
|
||||
|
||||
void GetLauncherList(std::vector<std::string> &result);
|
||||
void SetMailKey(int CharID, int IPAddress, int MailKey);
|
||||
bool GetCharacterLevel(const char *name, int &level);
|
||||
|
||||
bool LoadCharacterCreateAllocations();
|
||||
|
||||
@ -32,6 +32,7 @@ extern uint32 numzones;
|
||||
extern bool holdzones;
|
||||
extern EQEmu::Random emu_random;
|
||||
extern WebInterfaceList web_interface;
|
||||
volatile bool UCSServerAvailable_ = false;
|
||||
void CatchSignal(int sig_num);
|
||||
|
||||
ZSList::ZSList()
|
||||
@ -669,6 +670,16 @@ void ZSList::GetZoneIDList(std::vector<uint32> &zones) {
|
||||
}
|
||||
}
|
||||
|
||||
void ZSList::UpdateUCSServerAvailable(bool ucss_available) {
|
||||
UCSServerAvailable_ = ucss_available;
|
||||
auto outapp = new ServerPacket(ServerOP_UCSServerStatusReply, sizeof(UCSServerStatus_Struct));
|
||||
auto ucsss = (UCSServerStatus_Struct*)outapp->pBuffer;
|
||||
ucsss->available = (ucss_available ? 1 : 0);
|
||||
ucsss->timestamp = Timer::GetCurrentTime();
|
||||
SendPacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
void ZSList::WorldShutDown(uint32 time, uint32 interval)
|
||||
{
|
||||
if (time > 0) {
|
||||
|
||||
@ -54,7 +54,8 @@ public:
|
||||
Timer* reminder;
|
||||
void NextGroupIDs(uint32 &start, uint32 &end);
|
||||
void SendLSZones();
|
||||
uint16 GetAvailableZonePort();
|
||||
uint16 GetAvailableZonePort();
|
||||
void UpdateUCSServerAvailable(bool ucss_available = true);
|
||||
|
||||
int GetZoneCount();
|
||||
void GetZoneIDList(std::vector<uint32> &zones);
|
||||
|
||||
@ -42,6 +42,7 @@ extern GroupLFPList LFPGroupList;
|
||||
extern ZSList zoneserver_list;
|
||||
extern LoginServerList loginserverlist;
|
||||
extern volatile bool RunLoops;
|
||||
extern volatile bool UCSServerAvailable_;
|
||||
extern AdventureManager adventure_manager;
|
||||
extern UCSConnection UCSLink;
|
||||
extern QueryServConnection QSLink;
|
||||
@ -1271,6 +1272,24 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
UCSLink.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
|
||||
case ServerOP_UCSServerStatusRequest:
|
||||
{
|
||||
auto ucsss = (UCSServerStatus_Struct*)pack->pBuffer;
|
||||
auto zs = zoneserver_list.FindByPort(ucsss->port);
|
||||
if (!zs)
|
||||
break;
|
||||
|
||||
auto outapp = new ServerPacket(ServerOP_UCSServerStatusReply, sizeof(UCSServerStatus_Struct));
|
||||
ucsss = (UCSServerStatus_Struct*)outapp->pBuffer;
|
||||
ucsss->available = (UCSServerAvailable_ ? 1 : 0);
|
||||
ucsss->timestamp = Timer::GetCurrentTime();
|
||||
zs->SendPacket(outapp);
|
||||
safe_delete(outapp);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ServerOP_QSSendQuery:
|
||||
case ServerOP_QueryServGeneric:
|
||||
case ServerOP_Speech:
|
||||
|
||||
@ -28,6 +28,7 @@ SET(zone_sources
|
||||
encounter.cpp
|
||||
entity.cpp
|
||||
exp.cpp
|
||||
fastmath.cpp
|
||||
fearpath.cpp
|
||||
forage.cpp
|
||||
groups.cpp
|
||||
@ -159,6 +160,7 @@ SET(zone_headers
|
||||
entity.h
|
||||
errmsg.h
|
||||
event_codes.h
|
||||
fastmath.h
|
||||
forage.h
|
||||
global_loot_manager.h
|
||||
groups.h
|
||||
|
||||
@ -33,6 +33,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "zone.h"
|
||||
#include "lua_parser.h"
|
||||
#include "nats_manager.h"
|
||||
#include "fastmath.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
@ -44,6 +45,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
extern QueryServ* QServ;
|
||||
extern WorldServer worldserver;
|
||||
extern FastMath g_Math;
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#define snprintf _snprintf
|
||||
@ -3614,26 +3616,35 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
|
||||
a->special = 2;
|
||||
else
|
||||
a->special = 0;
|
||||
a->meleepush_xy = attacker ? attacker->GetHeading() : 0.0f;
|
||||
a->hit_heading = attacker ? attacker->GetHeading() : 0.0f;
|
||||
if (RuleB(Combat, MeleePush) && damage > 0 && !IsRooted() &&
|
||||
(IsClient() || zone->random.Roll(RuleI(Combat, MeleePushChance)))) {
|
||||
a->force = EQEmu::skills::GetSkillMeleePushForce(skill_used);
|
||||
if (IsNPC()) {
|
||||
if (attacker->IsNPC())
|
||||
a->force = 0.0f; // 2013 change that disabled NPC vs NPC push
|
||||
else
|
||||
a->force *= 0.10f; // force against NPCs is divided by 10 I guess? ex bash is 0.3, parsed 0.03 against an NPC
|
||||
}
|
||||
// update NPC stuff
|
||||
auto new_pos = glm::vec3(m_Position.x + (a->force * std::cos(a->meleepush_xy) + m_Delta.x),
|
||||
m_Position.y + (a->force * std::sin(a->meleepush_xy) + m_Delta.y), m_Position.z);
|
||||
if (zone->zonemap && zone->zonemap->CheckLoS(glm::vec3(m_Position), new_pos)) { // If we have LoS on the new loc it should be reachable.
|
||||
if (IsNPC()) {
|
||||
// Is this adequate?
|
||||
if (a->force != 0.0f) {
|
||||
auto new_pos = glm::vec3(
|
||||
m_Position.x + (a->force * g_Math.FastSin(a->hit_heading) + m_Delta.x),
|
||||
m_Position.y + (a->force * g_Math.FastCos(a->hit_heading) + m_Delta.y), m_Position.z);
|
||||
if ((!IsNPC() || position_update_melee_push_timer.Check()) && zone->zonemap &&
|
||||
zone->zonemap->CheckLoS(
|
||||
glm::vec3(m_Position),
|
||||
new_pos)) { // If we have LoS on the new loc it should be reachable.
|
||||
if (IsNPC()) {
|
||||
// Is this adequate?
|
||||
|
||||
Teleport(new_pos);
|
||||
if (position_update_melee_push_timer.Check()) {
|
||||
Teleport(new_pos);
|
||||
SendPositionUpdate();
|
||||
}
|
||||
} else {
|
||||
a->force = 0.0f; // we couldn't move there, so lets not
|
||||
}
|
||||
}
|
||||
else {
|
||||
a->force = 0.0f; // we couldn't move there, so lets not
|
||||
}
|
||||
}
|
||||
|
||||
//Note: if players can become pets, they will not receive damage messages of their own
|
||||
|
||||
@ -616,6 +616,7 @@ bool Aura::Process()
|
||||
it = spawned_for.erase(it);
|
||||
}
|
||||
}
|
||||
safe_delete(app);
|
||||
}
|
||||
// TODO: waypoints?
|
||||
|
||||
@ -757,6 +758,8 @@ void Mob::MakeAura(uint16 spell_id)
|
||||
|
||||
auto npc = new Aura(npc_type, this, record);
|
||||
npc->SetAuraID(spell_id);
|
||||
if (trap)
|
||||
npc->TryMoveAlong(5.0f, 0.0f, false); // try to place 5 units in front
|
||||
entity_list.AddNPC(npc, false);
|
||||
|
||||
if (trap)
|
||||
|
||||
26
zone/bot.cpp
26
zone/bot.cpp
@ -3053,7 +3053,7 @@ void Bot::Depop() {
|
||||
NPC::Depop(false);
|
||||
}
|
||||
|
||||
void Bot::Spawn(Client* botCharacterOwner) {
|
||||
bool Bot::Spawn(Client* botCharacterOwner) {
|
||||
if(GetBotID() > 0 && _botOwnerCharacterID > 0 && botCharacterOwner && botCharacterOwner->CharacterID() == _botOwnerCharacterID) {
|
||||
// Rename the bot name to make sure that Mob::GetName() matches Mob::GetCleanName() so we dont have a bot named "Jesuschrist001"
|
||||
strcpy(name, GetCleanName());
|
||||
@ -3097,7 +3097,11 @@ void Bot::Spawn(Client* botCharacterOwner) {
|
||||
this->SendWearChange(materialFromSlot);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Deletes the inventory record for the specified item from the database for this bot.
|
||||
@ -3246,16 +3250,20 @@ void Bot::LoadAndSpawnAllZonedBots(Client* botOwner) {
|
||||
if(!ActiveBots.empty()) {
|
||||
for(std::list<uint32>::iterator itr = ActiveBots.begin(); itr != ActiveBots.end(); ++itr) {
|
||||
Bot* activeBot = Bot::LoadBot(*itr);
|
||||
if (!activeBot)
|
||||
continue;
|
||||
|
||||
if(activeBot) {
|
||||
activeBot->Spawn(botOwner);
|
||||
g->UpdatePlayer(activeBot);
|
||||
// follow the bot owner, not the group leader we just zoned with our owner.
|
||||
if(g->IsGroupMember(botOwner) && g->IsGroupMember(activeBot))
|
||||
activeBot->SetFollowID(botOwner->GetID());
|
||||
if (!activeBot->Spawn(botOwner)) {
|
||||
safe_delete(activeBot);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(activeBot && !botOwner->HasGroup())
|
||||
g->UpdatePlayer(activeBot);
|
||||
// follow the bot owner, not the group leader we just zoned with our owner.
|
||||
if (g->IsGroupMember(botOwner) && g->IsGroupMember(activeBot))
|
||||
activeBot->SetFollowID(botOwner->GetID());
|
||||
|
||||
if(!botOwner->HasGroup())
|
||||
database.SetGroupID(activeBot->GetCleanName(), 0, activeBot->GetBotID());
|
||||
}
|
||||
}
|
||||
@ -8886,6 +8894,8 @@ bool Bot::DyeArmor(int16 slot_id, uint32 rgb, bool all_flag, bool save_flag)
|
||||
|
||||
std::string Bot::CreateSayLink(Client* c, const char* message, const char* name)
|
||||
{
|
||||
// TODO: review
|
||||
|
||||
int saylink_size = strlen(message);
|
||||
char* escaped_string = new char[saylink_size * 2];
|
||||
|
||||
|
||||
@ -275,7 +275,7 @@ public:
|
||||
static bool IsValidRaceClassCombo(uint16 r, uint8 c);
|
||||
bool IsValidName();
|
||||
static bool IsValidName(std::string& name);
|
||||
void Spawn(Client* botCharacterOwner);
|
||||
bool Spawn(Client* botCharacterOwner);
|
||||
virtual void SetLevel(uint8 in_level, bool command = false);
|
||||
virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
|
||||
virtual bool Process();
|
||||
|
||||
@ -5049,7 +5049,11 @@ void bot_subcommand_bot_spawn(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
my_bot->Spawn(c);
|
||||
if (!my_bot->Spawn(c)) {
|
||||
c->Message(m_fail, "Failed to spawn bot '%s' (id: %i)", bot_name.c_str(), bot_id);
|
||||
safe_delete(my_bot);
|
||||
return;
|
||||
}
|
||||
|
||||
static const char* bot_spawn_message[16] = {
|
||||
"A solid weapon is my ally!", // WARRIOR / 'generic'
|
||||
@ -5805,18 +5809,22 @@ void bot_subcommand_botgroup_load(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
if (!leader_id) {
|
||||
c->Message(m_fail, "Can not locate bot-group leader id for '%s'", botgroup_name_arg.c_str());
|
||||
c->Message(m_fail, "Cannot locate bot-group leader id for '%s'", botgroup_name_arg.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
auto botgroup_leader = Bot::LoadBot(leader_id);
|
||||
if (!botgroup_leader) {
|
||||
c->Message(m_fail, "Could not spawn bot-group leader for '%s'", botgroup_name_arg.c_str());
|
||||
c->Message(m_fail, "Could not load bot-group leader for '%s'", botgroup_name_arg.c_str());
|
||||
safe_delete(botgroup_leader);
|
||||
return;
|
||||
}
|
||||
|
||||
botgroup_leader->Spawn(c);
|
||||
if (!botgroup_leader->Spawn(c)) {
|
||||
c->Message(m_fail, "Could not spawn bot-group leader %s for '%s'", botgroup_leader->GetName(), botgroup_name_arg.c_str());
|
||||
safe_delete(botgroup_leader);
|
||||
return;
|
||||
}
|
||||
|
||||
Group* group_inst = new Group(botgroup_leader);
|
||||
|
||||
@ -5835,7 +5843,12 @@ void bot_subcommand_botgroup_load(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
botgroup_member->Spawn(c);
|
||||
if (!botgroup_member->Spawn(c)) {
|
||||
c->Message(m_fail, "Could not spawn bot '%s' (id: %i)", botgroup_member->GetName(), member_iter);
|
||||
safe_delete(botgroup_member);
|
||||
return;
|
||||
}
|
||||
|
||||
Bot::AddBotToGroup(botgroup_member, group_inst);
|
||||
}
|
||||
|
||||
@ -7072,7 +7085,6 @@ void bot_subcommand_inventory_list(Client *c, const Seperator *sep)
|
||||
const EQEmu::ItemData* item = nullptr;
|
||||
bool is2Hweapon = false;
|
||||
|
||||
std::string item_link;
|
||||
EQEmu::SayLinkEngine linker;
|
||||
linker.SetLinkType(EQEmu::saylink::SayLinkItemInst);
|
||||
|
||||
@ -7093,8 +7105,7 @@ void bot_subcommand_inventory_list(Client *c, const Seperator *sep)
|
||||
}
|
||||
|
||||
linker.SetItemInst(inst);
|
||||
item_link = linker.GenerateLink();
|
||||
c->Message(m_message, "Using %s in my %s (slot %i)", item_link.c_str(), GetBotEquipSlotName(i), (i == 22 ? EQEmu::inventory::slotPowerSource : i));
|
||||
c->Message(m_message, "Using %s in my %s (slot %i)", linker.GenerateLink().c_str(), GetBotEquipSlotName(i), (i == 22 ? EQEmu::inventory::slotPowerSource : i));
|
||||
|
||||
++inventory_count;
|
||||
}
|
||||
@ -7237,8 +7248,8 @@ void bot_subcommand_inventory_window(Client *c, const Seperator *sep)
|
||||
|
||||
std::string window_text;
|
||||
//std::string item_link;
|
||||
//Client::TextLink linker;
|
||||
//linker.SetLinkType(linker.linkItemInst);
|
||||
//EQEmu::SayLinkEngine linker;
|
||||
//linker.SetLinkType(EQEmu::saylink::SayLinkItemInst);
|
||||
|
||||
for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= (EQEmu::legacy::EQUIPMENT_END + 1); ++i) {
|
||||
const EQEmu::ItemData* item = nullptr;
|
||||
|
||||
@ -273,7 +273,10 @@ bool BotDatabase::LoadBotID(const uint32 owner_id, const std::string& bot_name,
|
||||
if (!owner_id || bot_name.empty())
|
||||
return false;
|
||||
|
||||
query = StringFormat("SELECT `bot_id` FROM `bot_data` WHERE `name` = '%s' LIMIT 1", bot_name.c_str());
|
||||
query = StringFormat(
|
||||
"SELECT `bot_id` FROM `bot_data` WHERE `owner_id` = '%u' AND `name` = '%s' LIMIT 1",
|
||||
owner_id, bot_name.c_str()
|
||||
);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return false;
|
||||
|
||||
@ -254,7 +254,7 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
mercSlot = 0;
|
||||
InitializeMercInfo();
|
||||
SetMerc(0);
|
||||
|
||||
if (RuleI(World, PVPMinLevel) > 0 && level >= RuleI(World, PVPMinLevel) && m_pp.pvp == 0) SetPVP(true, false);
|
||||
logging_enabled = CLIENT_DEFAULT_LOGGING_ENABLED;
|
||||
|
||||
//for good measure:
|
||||
@ -337,6 +337,7 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
m_pp.InnateSkills[i] = InnateDisabled;
|
||||
|
||||
temp_pvp = false;
|
||||
is_client_moving = false;
|
||||
|
||||
AI_Init();
|
||||
}
|
||||
@ -7907,7 +7908,7 @@ void Client::GarbleMessage(char *message, uint8 variance)
|
||||
for (size_t i = 0; i < strlen(message); i++) {
|
||||
// Client expects hex values inside of a text link body
|
||||
if (message[i] == delimiter) {
|
||||
if (!(delimiter_count & 1)) { i += EQEmu::legacy::TEXT_LINK_BODY_LENGTH; }
|
||||
if (!(delimiter_count & 1)) { i += EQEmu::constants::SayLinkBodySize; }
|
||||
++delimiter_count;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -75,6 +75,7 @@ extern NatsManager nats;
|
||||
|
||||
typedef void (Client::*ClientPacketProc)(const EQApplicationPacket *app);
|
||||
|
||||
|
||||
//Use a map for connecting opcodes since it dosent get used a lot and is sparse
|
||||
std::map<uint32, ClientPacketProc> ConnectingOpcodes;
|
||||
//Use a static array for connected, for speed
|
||||
@ -318,6 +319,7 @@ void MapOpcodes()
|
||||
ConnectedOpcodes[OP_PurchaseLeadershipAA] = &Client::Handle_OP_PurchaseLeadershipAA;
|
||||
ConnectedOpcodes[OP_PVPLeaderBoardDetailsRequest] = &Client::Handle_OP_PVPLeaderBoardDetailsRequest;
|
||||
ConnectedOpcodes[OP_PVPLeaderBoardRequest] = &Client::Handle_OP_PVPLeaderBoardRequest;
|
||||
ConnectedOpcodes[OP_QueryUCSServerStatus] = &Client::Handle_OP_QueryUCSServerStatus;
|
||||
ConnectedOpcodes[OP_RaidInvite] = &Client::Handle_OP_RaidCommand;
|
||||
ConnectedOpcodes[OP_RandomReq] = &Client::Handle_OP_RandomReq;
|
||||
ConnectedOpcodes[OP_ReadBook] = &Client::Handle_OP_ReadBook;
|
||||
@ -794,7 +796,7 @@ void Client::CompleteConnect()
|
||||
}
|
||||
|
||||
if (zone)
|
||||
zone->weatherSend();
|
||||
zone->weatherSend(this);
|
||||
|
||||
TotalKarma = database.GetKarma(AccountID());
|
||||
SendDisciplineTimers();
|
||||
@ -2866,41 +2868,60 @@ void Client::Handle_OP_ApplyPoison(const EQApplicationPacket *app)
|
||||
DumpPacket(app);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 ApplyPoisonSuccessResult = 0;
|
||||
ApplyPoison_Struct* ApplyPoisonData = (ApplyPoison_Struct*)app->pBuffer;
|
||||
const EQEmu::ItemInstance* PrimaryWeapon = GetInv().GetItem(EQEmu::inventory::slotPrimary);
|
||||
const EQEmu::ItemInstance* SecondaryWeapon = GetInv().GetItem(EQEmu::inventory::slotSecondary);
|
||||
const EQEmu::ItemInstance* PoisonItemInstance = GetInv()[ApplyPoisonData->inventorySlot];
|
||||
const EQEmu::ItemData* poison=PoisonItemInstance->GetItem();
|
||||
const EQEmu::ItemData* primary=nullptr;
|
||||
const EQEmu::ItemData* secondary=nullptr;
|
||||
bool IsPoison = PoisonItemInstance &&
|
||||
(poison->ItemType == EQEmu::item::ItemTypePoison);
|
||||
|
||||
bool IsPoison = PoisonItemInstance && (PoisonItemInstance->GetItem()->ItemType == EQEmu::item::ItemTypePoison);
|
||||
|
||||
if (!IsPoison)
|
||||
{
|
||||
Log(Logs::Detail, Logs::Spells, "Item used to cast spell effect from a poison item was missing from inventory slot %d "
|
||||
"after casting, or is not a poison!", ApplyPoisonData->inventorySlot);
|
||||
|
||||
Message(0, "Error: item not found for inventory slot #%i or is not a poison", ApplyPoisonData->inventorySlot);
|
||||
if (PrimaryWeapon) {
|
||||
primary=PrimaryWeapon->GetItem();
|
||||
}
|
||||
else if (GetClass() == ROGUE)
|
||||
{
|
||||
if ((PrimaryWeapon && PrimaryWeapon->GetItem()->ItemType == EQEmu::item::ItemType1HPiercing) ||
|
||||
(SecondaryWeapon && SecondaryWeapon->GetItem()->ItemType == EQEmu::item::ItemType1HPiercing)) {
|
||||
float SuccessChance = (GetSkill(EQEmu::skills::SkillApplyPoison) + GetLevel()) / 400.0f;
|
||||
|
||||
if (SecondaryWeapon) {
|
||||
secondary=SecondaryWeapon->GetItem();
|
||||
}
|
||||
|
||||
if (IsPoison && GetClass() == ROGUE) {
|
||||
|
||||
// Live always checks for skillup, even when poison is too high
|
||||
CheckIncreaseSkill(EQEmu::skills::SkillApplyPoison, nullptr, 10);
|
||||
|
||||
if (poison->Proc.Level2 > GetLevel()) {
|
||||
// Poison is too high to apply.
|
||||
Message_StringID(clientMessageTradeskill, POISON_TOO_HIGH);
|
||||
}
|
||||
else if ((primary &&
|
||||
primary->ItemType == EQEmu::item::ItemType1HPiercing) ||
|
||||
(secondary &&
|
||||
secondary->ItemType == EQEmu::item::ItemType1HPiercing)) {
|
||||
|
||||
double ChanceRoll = zone->random.Real(0, 1);
|
||||
|
||||
CheckIncreaseSkill(EQEmu::skills::SkillApplyPoison, nullptr, 10);
|
||||
// Poisons that use this skill (old world poisons) almost
|
||||
// never fail to apply. I did 25 applies of a trivial 120+
|
||||
// poison with an apply skill of 48 and they all worked.
|
||||
// Also did 25 straight poisons at apply skill 248 for very
|
||||
// high end and they never failed.
|
||||
// Apply poison ranging from 1-9, 28/30 worked for a level 18..
|
||||
// Poisons that don't proc until a level higher than the
|
||||
// rogue simply won't apply at all, no skill check done.
|
||||
|
||||
if (ChanceRoll < SuccessChance) {
|
||||
if (ChanceRoll < (.9 + GetLevel()/1000)) {
|
||||
ApplyPoisonSuccessResult = 1;
|
||||
// NOTE: Someone may want to tweak the chance to proc the poison effect that is added to the weapon here.
|
||||
// My thinking was that DEX should be apart of the calculation.
|
||||
AddProcToWeapon(PoisonItemInstance->GetItem()->Proc.Effect, false, (GetDEX() / 100) + 103);
|
||||
AddProcToWeapon(poison->Proc.Effect, false,
|
||||
(GetDEX() / 100) + 103);
|
||||
}
|
||||
|
||||
DeleteItemInInventory(ApplyPoisonData->inventorySlot, 1, true);
|
||||
|
||||
Log(Logs::General, Logs::None, "Chance to Apply Poison was %f. Roll was %f. Result is %u.", SuccessChance, ChanceRoll, ApplyPoisonSuccessResult);
|
||||
}
|
||||
|
||||
// Live always deletes the item, success or failure. Even if too high.
|
||||
DeleteItemInInventory(ApplyPoisonData->inventorySlot, 1, true);
|
||||
}
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_ApplyPoison, nullptr, sizeof(ApplyPoison_Struct));
|
||||
@ -3965,12 +3986,23 @@ void Client::Handle_OP_BuffRemoveRequest(const EQApplicationPacket *app)
|
||||
|
||||
void Client::Handle_OP_Bug(const EQApplicationPacket *app)
|
||||
{
|
||||
if (app->size != sizeof(BugStruct))
|
||||
printf("Wrong size of BugStruct got %d expected %zu!\n", app->size, sizeof(BugStruct));
|
||||
else {
|
||||
BugStruct* bug = (BugStruct*)app->pBuffer;
|
||||
database.UpdateBug(bug);
|
||||
if (!RuleB(Bugs, ReportingSystemActive)) {
|
||||
Message(0, "Bug reporting is disabled on this server.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (app->size != sizeof(BugReport_Struct)) {
|
||||
printf("Wrong size of BugReport_Struct got %d expected %zu!\n", app->size, sizeof(BugReport_Struct));
|
||||
}
|
||||
else {
|
||||
BugReport_Struct* bug_report = (BugReport_Struct*)app->pBuffer;
|
||||
|
||||
if (RuleB(Bugs, UseOldReportingMethod))
|
||||
database.RegisterBug(bug_report);
|
||||
else
|
||||
database.RegisterBug(this, bug_report);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -6716,7 +6748,11 @@ void Client::Handle_OP_GroupFollow2(const EQApplicationPacket *app)
|
||||
// Inviter and Invitee are in the same zone
|
||||
if (inviter != nullptr && inviter->IsClient())
|
||||
{
|
||||
if (GroupFollow(inviter->CastToClient()))
|
||||
if (!inviter->CastToClient()->Connected())
|
||||
{
|
||||
Log(Logs::General, Logs::Error, "%s attempted to join group while leader %s was zoning.", GetName(), inviter->GetName());
|
||||
}
|
||||
else if (GroupFollow(inviter->CastToClient()))
|
||||
{
|
||||
strn0cpy(gf->name1, inviter->GetName(), sizeof(gf->name1));
|
||||
strn0cpy(gf->name2, GetName(), sizeof(gf->name2));
|
||||
@ -10573,11 +10609,8 @@ void Client::Handle_OP_Petition(const EQApplicationPacket *app)
|
||||
|
||||
void Client::Handle_OP_PetitionBug(const EQApplicationPacket *app)
|
||||
{
|
||||
if (app->size != sizeof(PetitionBug_Struct))
|
||||
printf("Wrong size of BugStruct! Expected: %zu, Got: %i\n", sizeof(PetitionBug_Struct), app->size);
|
||||
else {
|
||||
Message(0, "Petition Bugs are not supported, please use /bug.");
|
||||
}
|
||||
Message(0, "Petition Bugs are not supported, please use /bug.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -10997,6 +11030,84 @@ void Client::Handle_OP_PVPLeaderBoardRequest(const EQApplicationPacket *app)
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
void Client::Handle_OP_QueryUCSServerStatus(const EQApplicationPacket *app)
|
||||
{
|
||||
if (zone->IsUCSServerAvailable()) {
|
||||
EQApplicationPacket* outapp = nullptr;
|
||||
std::string buffer;
|
||||
|
||||
std::string MailKey = database.GetMailKey(CharacterID(), true);
|
||||
EQEmu::versions::UCSVersion ConnectionType = EQEmu::versions::ucsUnknown;
|
||||
|
||||
// chat server packet
|
||||
switch (ClientVersion()) {
|
||||
case EQEmu::versions::ClientVersion::Titanium:
|
||||
ConnectionType = EQEmu::versions::ucsTitaniumChat;
|
||||
break;
|
||||
case EQEmu::versions::ClientVersion::SoF:
|
||||
ConnectionType = EQEmu::versions::ucsSoFCombined;
|
||||
break;
|
||||
case EQEmu::versions::ClientVersion::SoD:
|
||||
ConnectionType = EQEmu::versions::ucsSoDCombined;
|
||||
break;
|
||||
case EQEmu::versions::ClientVersion::UF:
|
||||
ConnectionType = EQEmu::versions::ucsUFCombined;
|
||||
break;
|
||||
case EQEmu::versions::ClientVersion::RoF:
|
||||
ConnectionType = EQEmu::versions::ucsRoFCombined;
|
||||
break;
|
||||
case EQEmu::versions::ClientVersion::RoF2:
|
||||
ConnectionType = EQEmu::versions::ucsRoF2Combined;
|
||||
break;
|
||||
default:
|
||||
ConnectionType = EQEmu::versions::ucsUnknown;
|
||||
break;
|
||||
}
|
||||
|
||||
buffer = StringFormat("%s,%i,%s.%s,%c%s",
|
||||
Config->ChatHost.c_str(),
|
||||
Config->ChatPort,
|
||||
Config->ShortName.c_str(),
|
||||
GetName(),
|
||||
ConnectionType,
|
||||
MailKey.c_str()
|
||||
);
|
||||
|
||||
outapp = new EQApplicationPacket(OP_SetChatServer, (buffer.length() + 1));
|
||||
memcpy(outapp->pBuffer, buffer.c_str(), buffer.length());
|
||||
outapp->pBuffer[buffer.length()] = '\0';
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
|
||||
// mail server packet
|
||||
switch (ClientVersion()) {
|
||||
case EQEmu::versions::ClientVersion::Titanium:
|
||||
ConnectionType = EQEmu::versions::ucsTitaniumMail;
|
||||
break;
|
||||
default:
|
||||
// retain value from previous switch
|
||||
break;
|
||||
}
|
||||
|
||||
buffer = StringFormat("%s,%i,%s.%s,%c%s",
|
||||
Config->MailHost.c_str(),
|
||||
Config->MailPort,
|
||||
Config->ShortName.c_str(),
|
||||
GetName(),
|
||||
ConnectionType,
|
||||
MailKey.c_str()
|
||||
);
|
||||
|
||||
outapp = new EQApplicationPacket(OP_SetChatServer2, (buffer.length() + 1));
|
||||
memcpy(outapp->pBuffer, buffer.c_str(), buffer.length());
|
||||
outapp->pBuffer[buffer.length()] = '\0';
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app)
|
||||
{
|
||||
if (app->size < sizeof(RaidGeneral_Struct)) {
|
||||
|
||||
@ -228,6 +228,7 @@
|
||||
void Handle_OP_PurchaseLeadershipAA(const EQApplicationPacket *app);
|
||||
void Handle_OP_PVPLeaderBoardDetailsRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_PVPLeaderBoardRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_QueryUCSServerStatus(const EQApplicationPacket *app);
|
||||
void Handle_OP_RaidCommand(const EQApplicationPacket *app);
|
||||
void Handle_OP_RandomReq(const EQApplicationPacket *app);
|
||||
void Handle_OP_ReadBook(const EQApplicationPacket *app);
|
||||
|
||||
188
zone/command.cpp
188
zone/command.cpp
@ -391,6 +391,7 @@ int command_init(void)
|
||||
command_add("traindisc", "[level] - Trains all the disciplines usable by the target, up to level specified. (may freeze client for a few seconds)", 150, command_traindisc) ||
|
||||
command_add("trapinfo", "- Gets infomation about the traps currently spawned in the zone.", 81, command_trapinfo) ||
|
||||
command_add("tune", "Calculate ideal statical values related to combat.", 100, command_tune) ||
|
||||
command_add("ucs", "- Attempts to reconnect to the UCS server", 0, command_ucs) ||
|
||||
command_add("undyeme", "- Remove dye from all of your armor slots", 0, command_undyeme) ||
|
||||
command_add("unfreeze", "- Unfreeze your target", 80, command_unfreeze) ||
|
||||
command_add("unlock", "- Unlock the worldserver", 150, command_unlock) ||
|
||||
@ -2326,14 +2327,18 @@ void command_race(Client *c, const Seperator *sep)
|
||||
{
|
||||
Mob *t=c->CastToMob();
|
||||
|
||||
// Need to figure out max race for LoY/LDoN: going with upper bound of 500 now for testing
|
||||
if (sep->IsNumber(1) && atoi(sep->arg[1]) >= 0 && atoi(sep->arg[1]) <= 724) {
|
||||
if ((c->GetTarget()) && c->Admin() >= commandRaceOthers)
|
||||
t=c->GetTarget();
|
||||
t->SendIllusionPacket(atoi(sep->arg[1]));
|
||||
if (sep->IsNumber(1)) {
|
||||
auto race = atoi(sep->arg[1]);
|
||||
if ((race >= 0 && race <= 732) || (race >= 2253 && race <= 2259)) {
|
||||
if ((c->GetTarget()) && c->Admin() >= commandRaceOthers)
|
||||
t = c->GetTarget();
|
||||
t->SendIllusionPacket(race);
|
||||
} else {
|
||||
c->Message(0, "Usage: #race [0-732, 2253-2259] (0 for back to normal)");
|
||||
}
|
||||
} else {
|
||||
c->Message(0, "Usage: #race [0-732, 2253-2259] (0 for back to normal)");
|
||||
}
|
||||
else
|
||||
c->Message(0, "Usage: #race [0-724] (0 for back to normal)");
|
||||
}
|
||||
|
||||
void command_gender(Client *c, const Seperator *sep)
|
||||
@ -2553,7 +2558,7 @@ void command_peekinv(Client *c, const Seperator *sep)
|
||||
const EQEmu::ItemInstance* inst_main = nullptr;
|
||||
const EQEmu::ItemInstance* inst_sub = nullptr;
|
||||
const EQEmu::ItemData* item_data = nullptr;
|
||||
std::string item_link;
|
||||
|
||||
EQEmu::SayLinkEngine linker;
|
||||
linker.SetLinkType(EQEmu::saylink::SayLinkItemInst);
|
||||
|
||||
@ -2565,10 +2570,8 @@ void command_peekinv(Client *c, const Seperator *sep)
|
||||
item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem();
|
||||
linker.SetItemInst(inst_main);
|
||||
|
||||
item_link = linker.GenerateLink();
|
||||
|
||||
c->Message((item_data == nullptr), "WornSlot: %i, Item: %i (%s), Charges: %i",
|
||||
indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges()));
|
||||
indexMain, ((item_data == nullptr) ? 0 : item_data->ID), linker.GenerateLink().c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges()));
|
||||
}
|
||||
|
||||
if ((scopeWhere & peekWorn) && (targetClient->ClientVersion() >= EQEmu::versions::ClientVersion::SoF)) {
|
||||
@ -2576,10 +2579,8 @@ void command_peekinv(Client *c, const Seperator *sep)
|
||||
item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem();
|
||||
linker.SetItemInst(inst_main);
|
||||
|
||||
item_link = linker.GenerateLink();
|
||||
|
||||
c->Message((item_data == nullptr), "WornSlot: %i, Item: %i (%s), Charges: %i",
|
||||
EQEmu::inventory::slotPowerSource, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges()));
|
||||
EQEmu::inventory::slotPowerSource, ((item_data == nullptr) ? 0 : item_data->ID), linker.GenerateLink().c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges()));
|
||||
}
|
||||
|
||||
// inv
|
||||
@ -2588,20 +2589,16 @@ void command_peekinv(Client *c, const Seperator *sep)
|
||||
item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem();
|
||||
linker.SetItemInst(inst_main);
|
||||
|
||||
item_link = linker.GenerateLink();
|
||||
|
||||
c->Message((item_data == nullptr), "InvSlot: %i, Item: %i (%s), Charges: %i",
|
||||
indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges()));
|
||||
indexMain, ((item_data == nullptr) ? 0 : item_data->ID), linker.GenerateLink().c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges()));
|
||||
|
||||
for (uint8 indexSub = EQEmu::inventory::containerBegin; inst_main && inst_main->IsClassBag() && (indexSub < EQEmu::inventory::ContainerCount); ++indexSub) {
|
||||
inst_sub = inst_main->GetItem(indexSub);
|
||||
item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem();
|
||||
linker.SetItemInst(inst_sub);
|
||||
|
||||
item_link = linker.GenerateLink();
|
||||
|
||||
c->Message((item_data == nullptr), " InvBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i",
|
||||
EQEmu::InventoryProfile::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges()));
|
||||
EQEmu::InventoryProfile::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), linker.GenerateLink().c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2610,10 +2607,8 @@ void command_peekinv(Client *c, const Seperator *sep)
|
||||
if (targetClient->GetInv().CursorEmpty()) {
|
||||
linker.SetItemInst(nullptr);
|
||||
|
||||
item_link = linker.GenerateLink();
|
||||
|
||||
c->Message(1, "CursorSlot: %i, Item: %i (%s), Charges: %i",
|
||||
EQEmu::inventory::slotCursor, 0, item_link.c_str(), 0);
|
||||
EQEmu::inventory::slotCursor, 0, linker.GenerateLink().c_str(), 0);
|
||||
}
|
||||
else {
|
||||
int cursorDepth = 0;
|
||||
@ -2622,20 +2617,16 @@ void command_peekinv(Client *c, const Seperator *sep)
|
||||
item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem();
|
||||
linker.SetItemInst(inst_main);
|
||||
|
||||
item_link = linker.GenerateLink();
|
||||
|
||||
c->Message((item_data == nullptr), "CursorSlot: %i, Depth: %i, Item: %i (%s), Charges: %i",
|
||||
EQEmu::inventory::slotCursor, cursorDepth, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges()));
|
||||
EQEmu::inventory::slotCursor, cursorDepth, ((item_data == nullptr) ? 0 : item_data->ID), linker.GenerateLink().c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges()));
|
||||
|
||||
for (uint8 indexSub = EQEmu::inventory::containerBegin; (cursorDepth == 0) && inst_main && inst_main->IsClassBag() && (indexSub < EQEmu::inventory::ContainerCount); ++indexSub) {
|
||||
inst_sub = inst_main->GetItem(indexSub);
|
||||
item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem();
|
||||
linker.SetItemInst(inst_sub);
|
||||
|
||||
item_link = linker.GenerateLink();
|
||||
|
||||
c->Message((item_data == nullptr), " CursorBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i",
|
||||
EQEmu::InventoryProfile::CalcSlotId(EQEmu::inventory::slotCursor, indexSub), EQEmu::inventory::slotCursor, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges()));
|
||||
EQEmu::InventoryProfile::CalcSlotId(EQEmu::inventory::slotCursor, indexSub), EQEmu::inventory::slotCursor, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), linker.GenerateLink().c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2647,10 +2638,8 @@ void command_peekinv(Client *c, const Seperator *sep)
|
||||
item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem();
|
||||
linker.SetItemInst(inst_main);
|
||||
|
||||
item_link = linker.GenerateLink();
|
||||
|
||||
c->Message((item_data == nullptr), "TributeSlot: %i, Item: %i (%s), Charges: %i",
|
||||
indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges()));
|
||||
indexMain, ((item_data == nullptr) ? 0 : item_data->ID), linker.GenerateLink().c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges()));
|
||||
}
|
||||
|
||||
// bank
|
||||
@ -2659,20 +2648,16 @@ void command_peekinv(Client *c, const Seperator *sep)
|
||||
item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem();
|
||||
linker.SetItemInst(inst_main);
|
||||
|
||||
item_link = linker.GenerateLink();
|
||||
|
||||
c->Message((item_data == nullptr), "BankSlot: %i, Item: %i (%s), Charges: %i",
|
||||
indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges()));
|
||||
indexMain, ((item_data == nullptr) ? 0 : item_data->ID), linker.GenerateLink().c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges()));
|
||||
|
||||
for (uint8 indexSub = EQEmu::inventory::containerBegin; inst_main && inst_main->IsClassBag() && (indexSub < EQEmu::inventory::ContainerCount); ++indexSub) {
|
||||
inst_sub = inst_main->GetItem(indexSub);
|
||||
item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem();
|
||||
linker.SetItemInst(inst_sub);
|
||||
|
||||
item_link = linker.GenerateLink();
|
||||
|
||||
c->Message((item_data == nullptr), " BankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i",
|
||||
EQEmu::InventoryProfile::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges()));
|
||||
EQEmu::InventoryProfile::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), linker.GenerateLink().c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2681,20 +2666,16 @@ void command_peekinv(Client *c, const Seperator *sep)
|
||||
item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem();
|
||||
linker.SetItemInst(inst_main);
|
||||
|
||||
item_link = linker.GenerateLink();
|
||||
|
||||
c->Message((item_data == nullptr), "SharedBankSlot: %i, Item: %i (%s), Charges: %i",
|
||||
indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges()));
|
||||
indexMain, ((item_data == nullptr) ? 0 : item_data->ID), linker.GenerateLink().c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges()));
|
||||
|
||||
for (uint8 indexSub = EQEmu::inventory::containerBegin; inst_main && inst_main->IsClassBag() && (indexSub < EQEmu::inventory::ContainerCount); ++indexSub) {
|
||||
inst_sub = inst_main->GetItem(indexSub);
|
||||
item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem();
|
||||
linker.SetItemInst(inst_sub);
|
||||
|
||||
item_link = linker.GenerateLink();
|
||||
|
||||
c->Message((item_data == nullptr), " SharedBankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i",
|
||||
EQEmu::InventoryProfile::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges()));
|
||||
EQEmu::InventoryProfile::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), linker.GenerateLink().c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2704,20 +2685,16 @@ void command_peekinv(Client *c, const Seperator *sep)
|
||||
item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem();
|
||||
linker.SetItemInst(inst_main);
|
||||
|
||||
item_link = linker.GenerateLink();
|
||||
|
||||
c->Message((item_data == nullptr), "TradeSlot: %i, Item: %i (%s), Charges: %i",
|
||||
indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges()));
|
||||
indexMain, ((item_data == nullptr) ? 0 : item_data->ID), linker.GenerateLink().c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges()));
|
||||
|
||||
for (uint8 indexSub = EQEmu::inventory::containerBegin; inst_main && inst_main->IsClassBag() && (indexSub < EQEmu::inventory::ContainerCount); ++indexSub) {
|
||||
inst_sub = inst_main->GetItem(indexSub);
|
||||
item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem();
|
||||
linker.SetItemInst(inst_sub);
|
||||
|
||||
item_link = linker.GenerateLink();
|
||||
|
||||
c->Message((item_data == nullptr), " TradeBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i",
|
||||
EQEmu::InventoryProfile::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges()));
|
||||
EQEmu::InventoryProfile::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), linker.GenerateLink().c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2736,20 +2713,16 @@ void command_peekinv(Client *c, const Seperator *sep)
|
||||
item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem();
|
||||
linker.SetItemInst(inst_main);
|
||||
|
||||
item_link = linker.GenerateLink();
|
||||
|
||||
c->Message((item_data == nullptr), "WorldSlot: %i, Item: %i (%s), Charges: %i",
|
||||
(EQEmu::legacy::WORLD_BEGIN + indexMain), ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges()));
|
||||
(EQEmu::legacy::WORLD_BEGIN + indexMain), ((item_data == nullptr) ? 0 : item_data->ID), linker.GenerateLink().c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges()));
|
||||
|
||||
for (uint8 indexSub = EQEmu::inventory::containerBegin; inst_main && inst_main->IsType(EQEmu::item::ItemClassBag) && (indexSub < EQEmu::inventory::ContainerCount); ++indexSub) {
|
||||
inst_sub = inst_main->GetItem(indexSub);
|
||||
item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem();
|
||||
linker.SetItemInst(inst_sub);
|
||||
|
||||
item_link = linker.GenerateLink();
|
||||
|
||||
c->Message((item_data == nullptr), " WorldBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i",
|
||||
INVALID_INDEX, indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges()));
|
||||
INVALID_INDEX, indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), linker.GenerateLink().c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4404,9 +4377,7 @@ void command_iteminfo(Client *c, const Seperator *sep)
|
||||
linker.SetLinkType(EQEmu::saylink::SayLinkItemInst);
|
||||
linker.SetItemInst(inst);
|
||||
|
||||
auto item_link = linker.GenerateLink();
|
||||
|
||||
c->Message(0, "*** Item Info for [%s] ***", item_link.c_str());
|
||||
c->Message(0, "*** Item Info for [%s] ***", linker.GenerateLink().c_str());
|
||||
c->Message(0, ">> ID: %u, ItemUseType: %u, ItemClassType: %u", item->ID, item->ItemType, item->ItemClass);
|
||||
c->Message(0, ">> IDFile: '%s', IconID: %u", item->IDFile, item->Icon);
|
||||
c->Message(0, ">> Size: %u, Weight: %u, Price: %u, LDoNPrice: %u", item->Size, item->Weight, item->Price, item->LDoNPrice);
|
||||
@ -5550,9 +5521,9 @@ void command_summonitem(Client *c, const Seperator *sep)
|
||||
std::string cmd_msg = sep->msg;
|
||||
size_t link_open = cmd_msg.find('\x12');
|
||||
size_t link_close = cmd_msg.find_last_of('\x12');
|
||||
if (link_open != link_close && (cmd_msg.length() - link_open) > EQEmu::legacy::TEXT_LINK_BODY_LENGTH) {
|
||||
if (link_open != link_close && (cmd_msg.length() - link_open) > EQEmu::constants::SayLinkBodySize) {
|
||||
EQEmu::SayLinkBody_Struct link_body;
|
||||
EQEmu::saylink::DegenerateLinkBody(link_body, cmd_msg.substr(link_open + 1, EQEmu::legacy::TEXT_LINK_BODY_LENGTH));
|
||||
EQEmu::saylink::DegenerateLinkBody(link_body, cmd_msg.substr(link_open + 1, EQEmu::constants::SayLinkBodySize));
|
||||
itemid = link_body.item_id;
|
||||
}
|
||||
else if (!sep->IsNumber(1)) {
|
||||
@ -5661,7 +5632,6 @@ void command_itemsearch(Client *c, const Seperator *sep)
|
||||
const char *search_criteria=sep->argplus[1];
|
||||
|
||||
const EQEmu::ItemData* item = nullptr;
|
||||
std::string item_link;
|
||||
EQEmu::SayLinkEngine linker;
|
||||
linker.SetLinkType(EQEmu::saylink::SayLinkItemData);
|
||||
|
||||
@ -5670,9 +5640,7 @@ void command_itemsearch(Client *c, const Seperator *sep)
|
||||
if (item) {
|
||||
linker.SetItemData(item);
|
||||
|
||||
item_link = linker.GenerateLink();
|
||||
|
||||
c->Message(0, "%u: %s", item->ID, item_link.c_str());
|
||||
c->Message(0, "%u: %s", item->ID, linker.GenerateLink().c_str());
|
||||
}
|
||||
else {
|
||||
c->Message(0, "Item #%s not found", search_criteria);
|
||||
@ -5695,9 +5663,7 @@ void command_itemsearch(Client *c, const Seperator *sep)
|
||||
if (pdest != nullptr) {
|
||||
linker.SetItemData(item);
|
||||
|
||||
item_link = linker.GenerateLink();
|
||||
|
||||
c->Message(0, "%u: %s", item->ID, item_link.c_str());
|
||||
c->Message(0, "%u: %s", item->ID, linker.GenerateLink().c_str());
|
||||
|
||||
++count;
|
||||
}
|
||||
@ -7201,6 +7167,90 @@ void command_undye(Client *c, const Seperator *sep)
|
||||
}
|
||||
}
|
||||
|
||||
void command_ucs(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (!c)
|
||||
return;
|
||||
|
||||
Log(Logs::Detail, Logs::UCS_Server, "Character %s attempting ucs reconnect while ucs server is %savailable",
|
||||
c->GetName(), (zone->IsUCSServerAvailable() ? "" : "un"));
|
||||
|
||||
if (zone->IsUCSServerAvailable()) {
|
||||
EQApplicationPacket* outapp = nullptr;
|
||||
std::string buffer;
|
||||
|
||||
std::string MailKey = database.GetMailKey(c->CharacterID(), true);
|
||||
EQEmu::versions::UCSVersion ConnectionType = EQEmu::versions::ucsUnknown;
|
||||
|
||||
// chat server packet
|
||||
switch (c->ClientVersion()) {
|
||||
case EQEmu::versions::ClientVersion::Titanium:
|
||||
ConnectionType = EQEmu::versions::ucsTitaniumChat;
|
||||
break;
|
||||
case EQEmu::versions::ClientVersion::SoF:
|
||||
ConnectionType = EQEmu::versions::ucsSoFCombined;
|
||||
break;
|
||||
case EQEmu::versions::ClientVersion::SoD:
|
||||
ConnectionType = EQEmu::versions::ucsSoDCombined;
|
||||
break;
|
||||
case EQEmu::versions::ClientVersion::UF:
|
||||
ConnectionType = EQEmu::versions::ucsUFCombined;
|
||||
break;
|
||||
case EQEmu::versions::ClientVersion::RoF:
|
||||
ConnectionType = EQEmu::versions::ucsRoFCombined;
|
||||
break;
|
||||
case EQEmu::versions::ClientVersion::RoF2:
|
||||
ConnectionType = EQEmu::versions::ucsRoF2Combined;
|
||||
break;
|
||||
default:
|
||||
ConnectionType = EQEmu::versions::ucsUnknown;
|
||||
break;
|
||||
}
|
||||
|
||||
buffer = StringFormat("%s,%i,%s.%s,%c%s",
|
||||
Config->ChatHost.c_str(),
|
||||
Config->ChatPort,
|
||||
Config->ShortName.c_str(),
|
||||
c->GetName(),
|
||||
ConnectionType,
|
||||
MailKey.c_str()
|
||||
);
|
||||
|
||||
outapp = new EQApplicationPacket(OP_SetChatServer, (buffer.length() + 1));
|
||||
memcpy(outapp->pBuffer, buffer.c_str(), buffer.length());
|
||||
outapp->pBuffer[buffer.length()] = '\0';
|
||||
|
||||
c->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
|
||||
// mail server packet
|
||||
switch (c->ClientVersion()) {
|
||||
case EQEmu::versions::ClientVersion::Titanium:
|
||||
ConnectionType = EQEmu::versions::ucsTitaniumMail;
|
||||
break;
|
||||
default:
|
||||
// retain value from previous switch
|
||||
break;
|
||||
}
|
||||
|
||||
buffer = StringFormat("%s,%i,%s.%s,%c%s",
|
||||
Config->MailHost.c_str(),
|
||||
Config->MailPort,
|
||||
Config->ShortName.c_str(),
|
||||
c->GetName(),
|
||||
ConnectionType,
|
||||
MailKey.c_str()
|
||||
);
|
||||
|
||||
outapp = new EQApplicationPacket(OP_SetChatServer2, (buffer.length() + 1));
|
||||
memcpy(outapp->pBuffer, buffer.c_str(), buffer.length());
|
||||
outapp->pBuffer[buffer.length()] = '\0';
|
||||
|
||||
c->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
|
||||
void command_undyeme(Client *c, const Seperator *sep)
|
||||
{
|
||||
if(c) {
|
||||
@ -10839,7 +10889,7 @@ void command_hotfix(Client *c, const Seperator *sep) {
|
||||
}
|
||||
worldserver.SendPacket(&pack);
|
||||
|
||||
c->Message(0, "Hotfix applied");
|
||||
if (c) c->Message(0, "Hotfix applied");
|
||||
});
|
||||
|
||||
t1.detach();
|
||||
|
||||
@ -302,6 +302,7 @@ void command_titlesuffix(Client *c, const Seperator *sep);
|
||||
void command_traindisc(Client *c, const Seperator *sep);
|
||||
void command_trapinfo(Client* c, const Seperator *sep);
|
||||
void command_tune(Client *c, const Seperator *sep);
|
||||
void command_ucs(Client *c, const Seperator *sep);
|
||||
void command_undye(Client *c, const Seperator *sep);
|
||||
void command_undyeme(Client *c, const Seperator *sep);
|
||||
void command_unfreeze(Client *c, const Seperator *sep);
|
||||
|
||||
@ -1253,20 +1253,20 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app)
|
||||
linker.SetLinkType(EQEmu::saylink::SayLinkItemInst);
|
||||
linker.SetItemInst(inst);
|
||||
|
||||
auto item_link = linker.GenerateLink();
|
||||
linker.GenerateLink();
|
||||
|
||||
client->Message_StringID(MT_LootMessages, LOOTED_MESSAGE, item_link.c_str());
|
||||
client->Message_StringID(MT_LootMessages, LOOTED_MESSAGE, linker.Link().c_str());
|
||||
|
||||
if (!IsPlayerCorpse()) {
|
||||
Group *g = client->GetGroup();
|
||||
if (g != nullptr) {
|
||||
g->GroupMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE,
|
||||
client->GetName(), item_link.c_str());
|
||||
client->GetName(), linker.Link().c_str());
|
||||
} else {
|
||||
Raid *r = client->GetRaid();
|
||||
if (r != nullptr) {
|
||||
r->RaidMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE,
|
||||
client->GetName(), item_link.c_str());
|
||||
client->GetName(), linker.Link().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -831,6 +831,8 @@ void Client::SetLevel(uint8 set_level, bool command)
|
||||
SetHP(CalcMaxHP()); // Why not, lets give them a free heal
|
||||
}
|
||||
|
||||
if (RuleI(World, PVPMinLevel) > 0 && level >= RuleI(World, PVPMinLevel) && m_pp.pvp == 0) SetPVP(true);
|
||||
|
||||
DoTributeUpdate();
|
||||
SendHPUpdate();
|
||||
SetMana(CalcMaxMana());
|
||||
|
||||
35
zone/fastmath.cpp
Normal file
35
zone/fastmath.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
#if defined(_MSC_VER)
|
||||
#define _USE_MATH_DEFINES
|
||||
#endif
|
||||
#include <cmath>
|
||||
#include "fastmath.h"
|
||||
|
||||
FastMath g_Math;
|
||||
|
||||
// This should match EQ's sin/cos LUTs
|
||||
// Some values didn't match on linux, but they were the "same" float :P
|
||||
FastMath::FastMath()
|
||||
{
|
||||
int ci = 0;
|
||||
int si = 128;
|
||||
float res;
|
||||
do {
|
||||
res = std::cos(static_cast<float>(ci) * M_PI * 2 / 512);
|
||||
lut_cos[ci] = res;
|
||||
if (si == 512)
|
||||
si = 0;
|
||||
lut_sin[si] = res;
|
||||
++ci;
|
||||
++si;
|
||||
} while (ci < 512);
|
||||
|
||||
lut_sin[0] = 0.0f;
|
||||
lut_sin[128] = 1.0f;
|
||||
lut_sin[256] = 0.0f;
|
||||
lut_sin[384] = -1.0f;
|
||||
|
||||
lut_cos[0] = 1.0f;
|
||||
lut_cos[128] = 0.0f;
|
||||
lut_cos[384] = 0.0f;
|
||||
}
|
||||
|
||||
18
zone/fastmath.h
Normal file
18
zone/fastmath.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef FASTMATH_H
|
||||
#define FASTMATH_H
|
||||
|
||||
class FastMath
|
||||
{
|
||||
private:
|
||||
float lut_cos[512];
|
||||
float lut_sin[512];
|
||||
|
||||
public:
|
||||
FastMath();
|
||||
|
||||
inline float FastSin(float a) { return lut_sin[static_cast<int>(a) & 0x1ff]; }
|
||||
inline float FastCos(float a) { return lut_cos[static_cast<int>(a) & 0x1ff]; }
|
||||
|
||||
};
|
||||
|
||||
#endif /* !FASTMATH_H */
|
||||
@ -1329,7 +1329,7 @@ int Client::GetItemLinkHash(const EQEmu::ItemInstance* inst) {
|
||||
return hash;
|
||||
}
|
||||
|
||||
// This appears to still be in use... The core of this should be incorporated into class Client::TextLink
|
||||
// This appears to still be in use... The core of this should be incorporated into class EQEmu::SayLinkEngine
|
||||
void Client::SendItemLink(const EQEmu::ItemInstance* inst, bool send_to_all)
|
||||
{
|
||||
/*
|
||||
|
||||
@ -282,6 +282,16 @@ void Lua_Mob::GMMove(double x, double y, double z, double heading, bool send_upd
|
||||
self->GMMove(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(heading), send_update);
|
||||
}
|
||||
|
||||
void Lua_Mob::TryMoveAlong(float distance, float angle) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->TryMoveAlong(distance, angle);
|
||||
}
|
||||
|
||||
void Lua_Mob::TryMoveAlong(float distance, float angle, bool send) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->TryMoveAlong(distance, angle, send);
|
||||
}
|
||||
|
||||
bool Lua_Mob::HasProcs() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->HasProcs();
|
||||
@ -2197,6 +2207,8 @@ luabind::scope lua_register_mob() {
|
||||
.def("GMMove", (void(Lua_Mob::*)(double,double,double))&Lua_Mob::GMMove)
|
||||
.def("GMMove", (void(Lua_Mob::*)(double,double,double,double))&Lua_Mob::GMMove)
|
||||
.def("GMMove", (void(Lua_Mob::*)(double,double,double,double,bool))&Lua_Mob::GMMove)
|
||||
.def("TryMoveAlong", (void(Lua_Mob::*)(float,float))&Lua_Mob::TryMoveAlong)
|
||||
.def("TryMoveAlong", (void(Lua_Mob::*)(float,float,bool))&Lua_Mob::TryMoveAlong)
|
||||
.def("HasProcs", &Lua_Mob::HasProcs)
|
||||
.def("IsInvisible", (bool(Lua_Mob::*)(void))&Lua_Mob::IsInvisible)
|
||||
.def("IsInvisible", (bool(Lua_Mob::*)(Lua_Mob))&Lua_Mob::IsInvisible)
|
||||
|
||||
@ -74,6 +74,8 @@ public:
|
||||
void GMMove(double x, double y, double z);
|
||||
void GMMove(double x, double y, double z, double heading);
|
||||
void GMMove(double x, double y, double z, double heading, bool send_update);
|
||||
void TryMoveAlong(float distance, float heading);
|
||||
void TryMoveAlong(float distance, float heading, bool send);
|
||||
bool HasProcs();
|
||||
bool IsInvisible();
|
||||
bool IsInvisible(Lua_Mob other);
|
||||
|
||||
2065
zone/map.cpp
2065
zone/map.cpp
File diff suppressed because it is too large
Load Diff
@ -30,7 +30,7 @@
|
||||
#define BEST_Z_INVALID -99999
|
||||
|
||||
extern const ZoneConfig *Config;
|
||||
namespace EQEmu
|
||||
namespace EQEmu
|
||||
{
|
||||
class Map
|
||||
{
|
||||
@ -43,6 +43,7 @@ namespace EQEmu
|
||||
bool LineIntersectsZone(glm::vec3 start, glm::vec3 end, float step, glm::vec3 *result) const;
|
||||
bool LineIntersectsZoneNoZLeaps(glm::vec3 start, glm::vec3 end, float step_mag, glm::vec3 *result) const;
|
||||
bool CheckLoS(glm::vec3 myloc, glm::vec3 oloc) const;
|
||||
bool DoCollisionCheck(glm::vec3 myloc, glm::vec3 oloc, glm::vec3 &outnorm, float &distance) const;
|
||||
|
||||
#ifdef USE_MAP_MMFS
|
||||
bool Load(std::string filename, bool force_mmf_overwrite = false);
|
||||
@ -67,4 +68,4 @@ namespace EQEmu
|
||||
impl *imp;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@ -117,7 +117,7 @@ Mob::Mob(const char* in_name,
|
||||
fix_z_timer(300),
|
||||
fix_z_timer_engaged(100),
|
||||
attack_anim_timer(1000),
|
||||
position_update_melee_push_timer(1000),
|
||||
position_update_melee_push_timer(500),
|
||||
mHateListCleanup(6000)
|
||||
{
|
||||
targeted = 0;
|
||||
@ -395,6 +395,7 @@ Mob::Mob(const char* in_name,
|
||||
permarooted = (runspeed > 0) ? false : true;
|
||||
|
||||
movetimercompleted = false;
|
||||
ForcedMovement = 0;
|
||||
roamer = false;
|
||||
rooted = false;
|
||||
charmed = false;
|
||||
|
||||
@ -50,6 +50,8 @@ struct AuraRecord;
|
||||
struct NewSpawn_Struct;
|
||||
struct PlayerPositionUpdateServer_Struct;
|
||||
|
||||
const int COLLISION_BOX_SIZE = 4;
|
||||
|
||||
namespace EQEmu
|
||||
{
|
||||
struct ItemData;
|
||||
@ -578,6 +580,8 @@ public:
|
||||
void SetFlyMode(uint8 flymode);
|
||||
inline void Teleport(glm::vec3 NewPosition) { m_Position.x = NewPosition.x; m_Position.y = NewPosition.y;
|
||||
m_Position.z = NewPosition.z; };
|
||||
void TryMoveAlong(float distance, float angle, bool send = true);
|
||||
void ProcessForcedMovement();
|
||||
|
||||
//AI
|
||||
static uint32 GetLevelCon(uint8 mylevel, uint8 iOtherLevel);
|
||||
@ -1313,6 +1317,9 @@ protected:
|
||||
char lastname[64];
|
||||
|
||||
glm::vec4 m_Delta;
|
||||
// just locs around them to double check, if we do expand collision this should be cached on movement
|
||||
// ideally we should use real models, but this should be quick and work mostly
|
||||
glm::vec4 m_CollisionBox[COLLISION_BOX_SIZE];
|
||||
|
||||
EQEmu::LightSourceProfile m_Light;
|
||||
|
||||
@ -1423,6 +1430,7 @@ protected:
|
||||
std::unique_ptr<Timer> AI_movement_timer;
|
||||
std::unique_ptr<Timer> AI_target_check_timer;
|
||||
bool movetimercompleted;
|
||||
int8 ForcedMovement; // push
|
||||
bool permarooted;
|
||||
std::unique_ptr<Timer> AI_scan_area_timer;
|
||||
std::unique_ptr<Timer> AI_walking_timer;
|
||||
|
||||
124
zone/mob_ai.cpp
124
zone/mob_ai.cpp
@ -29,12 +29,16 @@
|
||||
#include "quest_parser_collection.h"
|
||||
#include "string_ids.h"
|
||||
#include "water_map.h"
|
||||
#include "fastmath.h"
|
||||
|
||||
#include <glm/gtx/projection.hpp>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <math.h>
|
||||
|
||||
extern EntityList entity_list;
|
||||
extern FastMath g_Math;
|
||||
|
||||
extern Zone *zone;
|
||||
|
||||
@ -918,29 +922,26 @@ void Client::AI_Process()
|
||||
}
|
||||
}
|
||||
|
||||
if(IsPet())
|
||||
{
|
||||
Mob* owner = GetOwner();
|
||||
if(owner == nullptr)
|
||||
if (IsPet()) {
|
||||
Mob *owner = GetOwner();
|
||||
if (owner == nullptr)
|
||||
return;
|
||||
|
||||
float dist = DistanceSquared(m_Position, owner->GetPosition());
|
||||
if (dist >= 400)
|
||||
{
|
||||
if(AI_movement_timer->Check())
|
||||
{
|
||||
int nspeed = (dist >= 5625 ? GetRunspeed() : GetWalkspeed());
|
||||
if (dist >= 202500) { // >= 450 distance
|
||||
Teleport(static_cast<glm::vec3>(owner->GetPosition()));
|
||||
SendPositionUpdate(); // this shouldn't happen a lot (and hard to make it) so lets not rate limit
|
||||
} else if (dist >= 400) { // >=20
|
||||
if (AI_movement_timer->Check()) {
|
||||
int nspeed = (dist >= 1225 ? GetRunspeed() : GetWalkspeed()); // >= 35
|
||||
animation = nspeed;
|
||||
nspeed *= 2;
|
||||
SetCurrentSpeed(nspeed);
|
||||
|
||||
CalculateNewPosition2(owner->GetX(), owner->GetY(), owner->GetZ(), nspeed);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(moved)
|
||||
{
|
||||
} else {
|
||||
if (moved) {
|
||||
SetCurrentSpeed(0);
|
||||
moved = false;
|
||||
}
|
||||
@ -949,6 +950,71 @@ void Client::AI_Process()
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::ProcessForcedMovement()
|
||||
{
|
||||
// we are being pushed, we will hijack this movement timer
|
||||
// this also needs to be done before casting to have a chance to interrupt
|
||||
// this flag won't be set if the mob can't be pushed (rooted etc)
|
||||
if (AI_movement_timer->Check()) {
|
||||
bool bPassed = true;
|
||||
auto z_off = GetZOffset();
|
||||
glm::vec3 normal;
|
||||
glm::vec3 new_pos = m_Position + m_Delta;
|
||||
|
||||
// no zone map = fucked
|
||||
if (zone->HasMap()) {
|
||||
// in front
|
||||
m_CollisionBox[0].x = m_Position.x + 3.0f * g_Math.FastSin(0.0f);
|
||||
m_CollisionBox[0].y = m_Position.y + 3.0f * g_Math.FastCos(0.0f);
|
||||
m_CollisionBox[0].z = m_Position.z + z_off;
|
||||
|
||||
// to right
|
||||
m_CollisionBox[1].x = m_Position.x + 3.0f * g_Math.FastSin(128.0f);
|
||||
m_CollisionBox[1].y = m_Position.y + 3.0f * g_Math.FastCos(128.0f);
|
||||
m_CollisionBox[1].z = m_Position.z + z_off;
|
||||
|
||||
// behind
|
||||
m_CollisionBox[2].x = m_Position.x + 3.0f * g_Math.FastSin(256.0f);
|
||||
m_CollisionBox[2].y = m_Position.y + 3.0f * g_Math.FastCos(256.0f);
|
||||
m_CollisionBox[2].z = m_Position.z + z_off;
|
||||
|
||||
// to left
|
||||
m_CollisionBox[3].x = m_Position.x + 3.0f * g_Math.FastSin(384.0f);
|
||||
m_CollisionBox[3].y = m_Position.y + 3.0f * g_Math.FastCos(384.0f);
|
||||
m_CollisionBox[3].z = m_Position.z + z_off;
|
||||
|
||||
// collision happened, need to move along the wall
|
||||
float distance = 0.0f, shortest = std::numeric_limits<float>::infinity();
|
||||
glm::vec3 tmp_nrm;
|
||||
for (auto &vec : m_CollisionBox) {
|
||||
if (zone->zonemap->DoCollisionCheck(vec, new_pos, tmp_nrm, distance)) {
|
||||
bPassed = false; // lets try with new projection next pass
|
||||
if (distance < shortest) {
|
||||
normal = tmp_nrm;
|
||||
shortest = distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bPassed) {
|
||||
ForcedMovement = 0;
|
||||
m_Delta = glm::vec4();
|
||||
Teleport(new_pos);
|
||||
SendPositionUpdate();
|
||||
pLastChange = Timer::GetCurrentTime();
|
||||
FixZ(); // so we teleport to the ground locally, we want the client to interpolate falling etc
|
||||
} else if (--ForcedMovement) {
|
||||
auto proj = glm::proj(static_cast<glm::vec3>(m_Delta), normal);
|
||||
m_Delta.x -= proj.x;
|
||||
m_Delta.y -= proj.y;
|
||||
m_Delta.z -= proj.z;
|
||||
} else {
|
||||
m_Delta = glm::vec4(); // well, we failed to find a spot to be forced to, lets give up
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::AI_Process() {
|
||||
if (!IsAIControlled())
|
||||
return;
|
||||
@ -956,6 +1022,7 @@ void Mob::AI_Process() {
|
||||
if (!(AI_think_timer->Check() || attack_timer.Check(false)))
|
||||
return;
|
||||
|
||||
|
||||
if (IsCasting())
|
||||
return;
|
||||
|
||||
@ -1428,10 +1495,10 @@ void Mob::AI_Process() {
|
||||
if (dist >= 400 || distz > 100)
|
||||
{
|
||||
int speed = GetWalkspeed();
|
||||
if (dist >= 5625)
|
||||
if (dist >= 1225) // 35
|
||||
speed = GetRunspeed();
|
||||
|
||||
if (distz > 100)
|
||||
if (dist >= 202500 || distz > 100) // dist >= 450
|
||||
{
|
||||
m_Position = ownerPos;
|
||||
SendPositionUpdate();
|
||||
@ -2074,15 +2141,34 @@ bool Mob::Rampage(ExtraAttackOptions *opts)
|
||||
if (m_target) {
|
||||
if (m_target == GetTarget())
|
||||
continue;
|
||||
if (CombatRange(m_target)) {
|
||||
if (DistanceSquaredNoZ(GetPosition(), m_target->GetPosition()) <= NPC_RAMPAGE_RANGE2) {
|
||||
ProcessAttackRounds(m_target, opts);
|
||||
index_hit++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (RuleB(Combat, RampageHitsTarget) && index_hit < rampage_targets)
|
||||
ProcessAttackRounds(GetTarget(), opts);
|
||||
if (RuleB(Combat, RampageHitsTarget)) {
|
||||
if (index_hit < rampage_targets)
|
||||
ProcessAttackRounds(GetTarget(), opts);
|
||||
} else { // let's do correct behavior here, if they set above rule we can assume they want non-live like behavior
|
||||
if (index_hit < rampage_targets) {
|
||||
// so we go over in reverse order and skip range check
|
||||
// lets do it this way to still support non-live-like >1 rampage targets
|
||||
// likely live is just a fall through of the last valid mob
|
||||
for (auto i = RampageArray.crbegin(); i != RampageArray.crend(); ++i) {
|
||||
if (index_hit >= rampage_targets)
|
||||
break;
|
||||
auto m_target = entity_list.GetMob(*i);
|
||||
if (m_target) {
|
||||
if (m_target == GetTarget())
|
||||
continue;
|
||||
ProcessAttackRounds(m_target, opts);
|
||||
index_hit++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_specialattacks = eSpecialAttacks::None;
|
||||
|
||||
|
||||
@ -679,7 +679,6 @@ void NatsManager::OnSpawnEvent(const EmuOpcode op, uint32 entity_id, Spawn_Struc
|
||||
event.set_equip_chest2(spawn->equip_chest2);
|
||||
event.set_mount_color(spawn->mount_color);
|
||||
event.set_spawnid(spawn->spawnId);
|
||||
event.set_unknown0344(*spawn->unknown0344);
|
||||
event.set_ismercenary(spawn->IsMercenary);
|
||||
//event.set_equipment_tint(spawn->equipment_tint);
|
||||
event.set_lfg(spawn->lfg);
|
||||
@ -800,8 +799,8 @@ void NatsManager::OnDamageEvent(uint32 entity_id, CombatDamage_Struct *cd) {
|
||||
event.set_spellid(cd->spellid);
|
||||
event.set_damage(cd->damage);
|
||||
event.set_force(cd->force);
|
||||
event.set_meleepush_xy(cd->meleepush_xy);
|
||||
event.set_meleepush_z(cd->meleepush_z);
|
||||
event.set_meleepush_xy(cd->hit_heading);
|
||||
event.set_meleepush_z(cd->hit_pitch);
|
||||
|
||||
if (!event.SerializeToString(&pubMessage)) { Log(Logs::General, Logs::NATS, "Failed to serialize message to string"); return; }
|
||||
auto finalEvent = eqproto::Event();
|
||||
|
||||
@ -583,9 +583,7 @@ void NPC::QueryLoot(Client* to)
|
||||
linker.SetLinkType(EQEmu::saylink::SayLinkLootItem);
|
||||
linker.SetLootData(*cur);
|
||||
|
||||
auto item_link = linker.GenerateLink();
|
||||
|
||||
to->Message(0, "%s, ID: %u, Level: (min: %u, max: %u)", item_link.c_str(), (*cur)->item_id, (*cur)->min_level, (*cur)->max_level);
|
||||
to->Message(0, "%s, ID: %u, Level: (min: %u, max: %u)", linker.GenerateLink().c_str(), (*cur)->item_id, (*cur)->min_level, (*cur)->max_level);
|
||||
}
|
||||
|
||||
to->Message(0, "%i items on %s.", x, GetName());
|
||||
@ -764,6 +762,10 @@ bool NPC::Process()
|
||||
reface_timer->Disable();
|
||||
}
|
||||
|
||||
// needs to be done before mez and stun
|
||||
if (ForcedMovement)
|
||||
ProcessForcedMovement();
|
||||
|
||||
if (IsMezzed())
|
||||
return true;
|
||||
|
||||
|
||||
@ -560,7 +560,8 @@ void PathManager::SpawnPathNodes()
|
||||
sprintf(npc_type->lastname, "%i", PathNodes[i].id);
|
||||
npc_type->cur_hp = 4000000;
|
||||
npc_type->max_hp = 4000000;
|
||||
npc_type->race = 151;
|
||||
npc_type->race = 2253;
|
||||
npc_type->size = 3.0f;
|
||||
npc_type->gender = 2;
|
||||
npc_type->class_ = 9;
|
||||
npc_type->deity= 1;
|
||||
@ -1377,7 +1378,7 @@ void PathManager::ShowPathNodeNeighbours(Client *c)
|
||||
Mob *m = entity_list.GetMob(Name);
|
||||
|
||||
if(m)
|
||||
m->SendIllusionPacket(151);
|
||||
m->ChangeSize(3.0f);
|
||||
}
|
||||
|
||||
std::stringstream Neighbours;
|
||||
@ -1401,7 +1402,7 @@ void PathManager::ShowPathNodeNeighbours(Client *c)
|
||||
Mob *m = entity_list.GetMob(Name);
|
||||
|
||||
if(m)
|
||||
m->SendIllusionPacket(46);
|
||||
m->ChangeSize(5.0f);
|
||||
}
|
||||
c->Message(0, "Neighbours: %s", Neighbours.str().c_str());
|
||||
}
|
||||
@ -1560,7 +1561,8 @@ int32 PathManager::AddNode(float x, float y, float z, float best_z, int32 reques
|
||||
sprintf(npc_type->lastname, "%i", new_id);
|
||||
npc_type->cur_hp = 4000000;
|
||||
npc_type->max_hp = 4000000;
|
||||
npc_type->race = 151;
|
||||
npc_type->race = 2253;
|
||||
npc_type->size = 3.0f;
|
||||
npc_type->gender = 2;
|
||||
npc_type->class_ = 9;
|
||||
npc_type->deity= 1;
|
||||
@ -1621,7 +1623,8 @@ int32 PathManager::AddNode(float x, float y, float z, float best_z, int32 reques
|
||||
sprintf(npc_type->lastname, "%i", new_id);
|
||||
npc_type->cur_hp = 4000000;
|
||||
npc_type->max_hp = 4000000;
|
||||
npc_type->race = 151;
|
||||
npc_type->race = 2253;
|
||||
npc_type->size = 3.0f;
|
||||
npc_type->gender = 2;
|
||||
npc_type->class_ = 9;
|
||||
npc_type->deity= 1;
|
||||
|
||||
114
zone/pets.cpp
114
zone/pets.cpp
@ -28,6 +28,8 @@
|
||||
#include "pets.h"
|
||||
#include "zonedb.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifdef BOTS
|
||||
#include "bot.h"
|
||||
#endif
|
||||
@ -38,82 +40,42 @@
|
||||
#endif
|
||||
|
||||
|
||||
const char *GetRandPetName()
|
||||
// need to pass in a char array of 64 chars
|
||||
void GetRandPetName(char *name)
|
||||
{
|
||||
static const char *petnames[] = { "Gabaner","Gabann","Gabantik","Gabarab","Gabarer","Gabarn","Gabartik",
|
||||
"Gabekab","Gabeker","Gabekn","Gaber","Gabn","Gabobab","Gabobn","Gabtik",
|
||||
"Ganer","Gann","Gantik","Garab","Garaner","Garann","Garantik","Gararn",
|
||||
"Garekn","Garer","Garn","Gartik","Gasaner","Gasann","Gasantik","Gasarer",
|
||||
"Gasartik","Gasekn","Gaser","Gebann","Gebantik","Gebarer","Gebarn","Gebartik",
|
||||
"Gebeker","Gebekn","Gebn","Gekab","Geker","Gekn","Genaner","Genann","Genantik",
|
||||
"Genarer","Genarn","Gener","Genn","Genobtik","Gibaner","Gibann","Gibantik",
|
||||
"Gibarn","Gibartik","Gibekn","Giber","Gibn","Gibobtik","Gibtik","Gobaber",
|
||||
"Gobaner","Gobann","Gobarn","Gobartik","Gober","Gobn","Gobober","Gobobn",
|
||||
"Gobobtik","Gobtik","Gonaner","Gonann","Gonantik","Gonarab","Gonarer",
|
||||
"Gonarn","Gonartik","Gonekab","Gonekn","Goner","Gonobtik","Gontik","Gotik",
|
||||
"Jabaner","Jabann","Jabantik","Jabarab","Jabarer","Jabarn","Jabartik",
|
||||
"Jabekab","Jabeker","Jabekn","Jaber","Jabn","Jabobtik","Jabtik","Janab",
|
||||
"Janer","Jann","Jantik","Jarab","Jaranab","Jaraner","Jararer","Jararn",
|
||||
"Jarartik","Jareker","Jarekn","Jarer","Jarn","Jarobn","Jarobtik","Jartik",
|
||||
"Jasab","Jasaner","Jasantik","Jasarer","Jasartik","Jasekab","Jaseker",
|
||||
"Jasekn","Jaser","Jasn","Jasobab","Jasober","Jastik","Jebanab","Jebann",
|
||||
"Jebantik","Jebarab","Jebarar","Jebarer","Jebarn","Jebartik","Jebeker",
|
||||
"Jebekn","Jeber","Jebobn","Jebtik","Jekab","Jeker","Jekn","Jenann",
|
||||
"Jenantik","Jenarer","Jeneker","Jenekn","Jentik","Jibaner","Jibann",
|
||||
"Jibantik","Jibarer","Jibarn","Jibartik","Jibeker","Jibn","Jibobn",
|
||||
"Jibtik","Jobab","Jobaner","Jobann","Jobantik","Jobarn","Jobartik",
|
||||
"Jobekab","Jobeker","Jober","Jobn","Jobtik","Jonanab","Jonaner",
|
||||
"Jonann","Jonantik","Jonarer","Jonarn","Jonartik","Jonekab","Joneker",
|
||||
"Jonekn","Joner","Jonn","Jonnarn","Jonober","Jonobn","Jonobtik","Jontik",
|
||||
"Kabanab","Kabaner","Kabann","Kabantik","Kabarer","Kabarn","Kabartik",
|
||||
"Kabeker","Kabekn","Kaber","Kabn","Kabober","Kabobn","Kabobtik","Kabtik",
|
||||
"Kanab","Kaner","Kann","Kantik","Karab","Karanab","Karaner","Karann",
|
||||
"Karantik","Kararer","Karartik","Kareker","Karer","Karn","Karobab","Karobn",
|
||||
"Kartik","Kasaner","Kasann","Kasarer","Kasartik","Kaseker","Kasekn","Kaser",
|
||||
"Kasn","Kasober","Kastik","Kebann","Kebantik","Kebarab","Kebartik","Kebeker",
|
||||
"Kebekn","Kebn","Kebobab","Kebtik","Kekab","Keker","Kekn","Kenab","Kenaner",
|
||||
"Kenantik","Kenarer","Kenarn","Keneker","Kener","Kenn","Kenobn","Kenobtik",
|
||||
"Kentik","Kibab","Kibaner","Kibantik","Kibarn","Kibartik","Kibekab","Kibeker",
|
||||
"Kibekn","Kibn","Kibobn","Kibobtik","Kobab","Kobanab","Kobaner","Kobann",
|
||||
"Kobantik","Kobarer","Kobarn","Kobartik","Kobeker","Kobekn","Kober","Kobn",
|
||||
"Kobober","Kobobn","Kobtik","Konanab","Konaner","Konann","Konantik","Konarab",
|
||||
"Konarer","Konarn","Konekab","Koneker","Konekn","Koner","Konn","Konobn",
|
||||
"Konobtik","Kontik","Labanab","Labaner","Labann","Labarab","Labarer",
|
||||
"Labarn","Labartik","Labeker","Labekn","Laner","Lann","Larab","Larantik",
|
||||
"Lararer","Lararn","Larartik","Lareker","Larer","Larn","Lartik","Lasaner",
|
||||
"Lasann","Lasarer","Laseker","Laser","Lasik","Lasn","Lastik","Lebaner",
|
||||
"Lebarer","Lebartik","Lebekn","Lebtik","Lekab","Lekn","Lenanab","Lenaner",
|
||||
"Lenann","Lenartik","Lenekab","Leneker","Lenekn","Lentik","Libab","Libaner",
|
||||
"Libann","Libantik","Libarer","Libarn","Libartik","Libeker","Libekn","Lobann",
|
||||
"Lobarab","Lobarn","Lobartik","Lobekn","Lobn","Lobober","Lobobn","Lobtik",
|
||||
"Lonaner","Lonann","Lonantik","Lonarab","Lonarer","Lonarn","Lonartik","Lonekn",
|
||||
"Loner","Lonobtik","Lontik","Vabanab","Vabaner","Vabann","Vabantik","Vabarer",
|
||||
"Vabarn","Vabartik","Vabeker","Vabekn","Vabtik","Vanikk","Vann","Varartik","Varn",
|
||||
"Vartik","Vasann","Vasantik","Vasarab","Vasarer","Vaseker","Vebaner","Vebantik",
|
||||
"Vebarab","Vebeker","Vebekn","Vebobn","Vekab","Veker","Venaner","Venantik","Venar",
|
||||
"Venarn","Vener","Ventik","Vibann","Vibantik","Viber","Vibobtik","Vobann",
|
||||
"Vobarer","Vobartik","Vobekn","Vober","Vobn","Vobtik","Vonaner","Vonann",
|
||||
"Vonantik","Vonarab","Vonarn","Vonartik","Voneker","Vonn","Xabanab","Xabaner",
|
||||
"Xabarer","Xabarn","Xabartik","Xabekab","Xabeker","Xabekn","Xaber","Xabober",
|
||||
"Xaner","Xann","Xarab","Xaranab","Xarann","Xarantik","Xararer","Xarartik","Xarer",
|
||||
"Xarn","Xartik","Xasaner","Xasann","Xasarab","Xasarn","Xasekab","Xaseker",
|
||||
"Xebarer","Xebarn","Xebeker","Xeber","Xebober","Xebtik","Xekab","Xeker",
|
||||
"Xekn","Xenann","Xenantik","Xenarer","Xenartik","Xenekn","Xener","Xenober",
|
||||
"Xentik","Xibantik","Xibarer","Xibekab","Xibeker","Xibobab","Xibober","Xibobn",
|
||||
"Xobaner","Xobann","Xobarab","Xobarn","Xobekab","Xobeker","Xobekn","Xober",
|
||||
"Xobn","Xobobn","Xobtik","Xonaner","Xonann","Xonantik","Xonarer","Xonartik",
|
||||
"Xonekab","Xoneker","Xonekn","Xoner","Xonober","Xtik","Zabaner","Zabantik",
|
||||
"Zabarab","Zabekab","Zabekn","Zaber","Zabn","Zabobab","Zabober","Zabtik",
|
||||
"Zaner","Zantik","Zarann","Zarantik","Zararn","Zarartik","Zareker","Zarekn",
|
||||
"Zarer","Zarn","Zarober","Zartik","Zasaner","Zasarer","Zaseker","Zasekn","Zasn",
|
||||
"Zebantik","Zebarer","Zebarn","Zebartik","Zebobab","Zekab","Zekn","Zenann",
|
||||
"Zenantik","Zenarer","Zenarn","Zenekab","Zeneker","Zenobtik","Zibanab","Zibaner",
|
||||
"Zibann","Zibarer","Zibartik","Zibekn","Zibn","Zibobn","Zobaner","Zobann",
|
||||
"Zobarn","Zober","Zobn","Zonanab","Zonaner","Zonann","Zonantik","Zonarer",
|
||||
"Zonartik","Zonobn","Zonobtik","Zontik","Ztik" };
|
||||
int r = zone->random.Int(0, (sizeof(petnames)/sizeof(const char *))-1);
|
||||
printf("Pet being created: %s\n",petnames[r]); // DO NOT COMMENT THIS OUT!
|
||||
return petnames[r];
|
||||
std::string temp;
|
||||
temp.reserve(64);
|
||||
// note these orders are used to make the exclusions cheap :P
|
||||
static const char *part1[] = {"G", "J", "K", "L", "V", "X", "Z"};
|
||||
static const char *part2[] = {nullptr, "ab", "ar", "as", "eb", "en", "ib", "ob", "on"};
|
||||
static const char *part3[] = {nullptr, "an", "ar", "ek", "ob"};
|
||||
static const char *part4[] = {"er", "ab", "n", "tik"};
|
||||
|
||||
const char *first = part1[zone->random.Int(0, (sizeof(part1) / sizeof(const char *)) - 1)];
|
||||
const char *second = part2[zone->random.Int(0, (sizeof(part2) / sizeof(const char *)) - 1)];
|
||||
const char *third = part3[zone->random.Int(0, (sizeof(part3) / sizeof(const char *)) - 1)];
|
||||
const char *fourth = part4[zone->random.Int(0, (sizeof(part4) / sizeof(const char *)) - 1)];
|
||||
|
||||
// if both of these are empty, we would get an illegally short name
|
||||
if (second == nullptr && third == nullptr)
|
||||
fourth = part4[(sizeof(part4) / sizeof(const char *)) - 1];
|
||||
|
||||
// "ektik" isn't allowed either I guess?
|
||||
if (third == part3[3] && fourth == part4[3])
|
||||
fourth = part4[zone->random.Int(0, (sizeof(part4) / sizeof(const char *)) - 2)];
|
||||
|
||||
// "Laser" isn't allowed either I guess?
|
||||
if (first == part1[3] && second == part2[3] && third == nullptr && fourth == part4[0])
|
||||
fourth = part4[zone->random.Int(1, (sizeof(part4) / sizeof(const char *)) - 2)];
|
||||
|
||||
temp += first;
|
||||
if (second != nullptr)
|
||||
temp += second;
|
||||
if (third != nullptr)
|
||||
temp += third;
|
||||
temp += fourth;
|
||||
|
||||
strn0cpy(name, temp.c_str(), 64);
|
||||
}
|
||||
|
||||
//not used anymore
|
||||
@ -325,7 +287,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
|
||||
} else if (record.petnaming == 4) {
|
||||
// Keep the DB name
|
||||
} else if (record.petnaming == 3 && IsClient()) {
|
||||
strcpy(npc_type->name, GetRandPetName());
|
||||
GetRandPetName(npc_type->name);
|
||||
} else if (record.petnaming == 5 && IsClient()) {
|
||||
strcpy(npc_type->name, this->GetName());
|
||||
npc_type->name[24] = '\0';
|
||||
|
||||
@ -1319,9 +1319,7 @@ void QuestManager::itemlink(int item_id) {
|
||||
linker.SetLinkType(EQEmu::saylink::SayLinkItemData);
|
||||
linker.SetItemData(item);
|
||||
|
||||
auto item_link = linker.GenerateLink();
|
||||
|
||||
initiator->Message(0, "%s tells you, %s", owner->GetCleanName(), item_link.c_str());
|
||||
initiator->Message(0, "%s tells you, %s", owner->GetCleanName(), linker.GenerateLink().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1989,8 +1987,8 @@ void QuestManager::npcfeature(char *feature, int setting)
|
||||
QuestManagerCurrentQuestVars();
|
||||
uint16 Race = owner->GetRace();
|
||||
uint8 Gender = owner->GetGender();
|
||||
uint8 Texture = 0xFF;
|
||||
uint8 HelmTexture = 0xFF;
|
||||
uint8 Texture = owner->GetTexture();
|
||||
uint8 HelmTexture = owner->GetHelmTexture();
|
||||
uint8 HairColor = owner->GetHairColor();
|
||||
uint8 BeardColor = owner->GetBeardColor();
|
||||
uint8 EyeColor1 = owner->GetEyeColor1();
|
||||
@ -2549,9 +2547,8 @@ const char* QuestManager::varlink(char* perltext, int item_id) {
|
||||
linker.SetLinkType(EQEmu::saylink::SayLinkItemData);
|
||||
linker.SetItemData(item);
|
||||
|
||||
auto item_link = linker.GenerateLink();
|
||||
strcpy(perltext, item_link.c_str()); // link length is currently ranged from 1 to 250 in TextLink::GenerateLink()
|
||||
|
||||
strcpy(perltext, linker.GenerateLink().c_str());
|
||||
|
||||
return perltext;
|
||||
}
|
||||
|
||||
@ -2773,8 +2770,7 @@ const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkNam
|
||||
linker.SetProxyAugment1ID(sayid);
|
||||
linker.SetProxyText(LinkName);
|
||||
|
||||
auto say_link = linker.GenerateLink();
|
||||
strcpy(Phrase, say_link.c_str()); // link length is currently ranged from 1 to 250 in TextLink::GenerateLink()
|
||||
strcpy(Phrase, linker.GenerateLink().c_str());
|
||||
|
||||
return Phrase;
|
||||
}
|
||||
|
||||
@ -1443,7 +1443,7 @@ void Mob::SendItemAnimation(Mob *to, const EQEmu::ItemData *item, EQEmu::skills:
|
||||
|
||||
//these angle and tilt used together seem to make the arrow/knife throw as straight as I can make it
|
||||
|
||||
as->launch_angle = CalculateHeadingToTarget(to->GetX(), to->GetY()) * 2;
|
||||
as->launch_angle = CalculateHeadingToTarget(to->GetX(), to->GetY());
|
||||
as->tilt = 125;
|
||||
as->arc = 50;
|
||||
|
||||
|
||||
@ -915,16 +915,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
action->source = caster ? caster->GetID() : GetID();
|
||||
action->level = 65;
|
||||
action->instrument_mod = 10;
|
||||
action->sequence = static_cast<uint32>((GetHeading() * 12345 / 2));
|
||||
action->hit_heading = GetHeading();
|
||||
action->type = 231;
|
||||
action->spell = spell_id;
|
||||
action->buff_unknown = 4;
|
||||
action->effect_flag = 4;
|
||||
|
||||
cd->target = action->target;
|
||||
cd->source = action->source;
|
||||
cd->type = action->type;
|
||||
cd->spellid = action->spell;
|
||||
cd->meleepush_xy = action->sequence;
|
||||
cd->hit_heading = action->hit_heading;
|
||||
|
||||
CastToClient()->QueuePacket(action_packet);
|
||||
if(caster && caster->IsClient() && caster != this)
|
||||
@ -967,16 +967,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
action->source = caster ? caster->GetID() : GetID();
|
||||
action->level = 65;
|
||||
action->instrument_mod = 10;
|
||||
action->sequence = static_cast<uint32>((GetHeading() * 12345 / 2));
|
||||
action->hit_heading = GetHeading();
|
||||
action->type = 231;
|
||||
action->spell = spell_id;
|
||||
action->buff_unknown = 4;
|
||||
action->effect_flag = 4;
|
||||
|
||||
cd->target = action->target;
|
||||
cd->source = action->source;
|
||||
cd->type = action->type;
|
||||
cd->spellid = action->spell;
|
||||
cd->meleepush_xy = action->sequence;
|
||||
cd->hit_heading = action->hit_heading;
|
||||
|
||||
CastToClient()->QueuePacket(action_packet);
|
||||
if(caster->IsClient() && caster != this)
|
||||
@ -1006,16 +1006,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
action->source = caster ? caster->GetID() : GetID();
|
||||
action->level = 65;
|
||||
action->instrument_mod = 10;
|
||||
action->sequence = static_cast<uint32>((GetHeading() * 12345 / 2));
|
||||
action->hit_heading = GetHeading();
|
||||
action->type = 231;
|
||||
action->spell = spell_id;
|
||||
action->buff_unknown = 4;
|
||||
action->effect_flag = 4;
|
||||
|
||||
cd->target = action->target;
|
||||
cd->source = action->source;
|
||||
cd->type = action->type;
|
||||
cd->spellid = action->spell;
|
||||
cd->meleepush_xy = action->sequence;
|
||||
cd->hit_heading = action->hit_heading;
|
||||
|
||||
CastToClient()->QueuePacket(action_packet);
|
||||
if(caster->IsClient() && caster != this)
|
||||
@ -2080,61 +2080,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
#ifdef SPELL_EFFECT_SPAM
|
||||
snprintf(effect_desc, _EDLEN, "Toss Up: %d", effect_value);
|
||||
#endif
|
||||
double toss_amt = (double)spells[spell_id].base[i];
|
||||
if(toss_amt < 0)
|
||||
toss_amt = -toss_amt;
|
||||
|
||||
if(IsNPC())
|
||||
{
|
||||
Stun(static_cast<int>(toss_amt));
|
||||
if (IsNPC()) {
|
||||
Damage(caster, std::abs(effect_value), spell_id, spell.skill, false, buffslot, false);
|
||||
}
|
||||
toss_amt = sqrt(toss_amt)-2.0;
|
||||
|
||||
if(toss_amt < 0.0)
|
||||
toss_amt = 0.0;
|
||||
|
||||
if(toss_amt > 20.0)
|
||||
toss_amt = 20.0;
|
||||
|
||||
if(IsClient())
|
||||
{
|
||||
CastToClient()->SetKnockBackExemption(true);
|
||||
}
|
||||
|
||||
double look_heading = GetHeading();
|
||||
look_heading /= 256;
|
||||
look_heading *= 360;
|
||||
look_heading += 180;
|
||||
if(look_heading > 360)
|
||||
look_heading -= 360;
|
||||
|
||||
//x and y are crossed mkay
|
||||
double new_x = spells[spell_id].pushback * sin(double(look_heading * 3.141592 / 180.0));
|
||||
double new_y = spells[spell_id].pushback * cos(double(look_heading * 3.141592 / 180.0));
|
||||
|
||||
auto outapp_push =
|
||||
new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
|
||||
PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)outapp_push->pBuffer;
|
||||
|
||||
spu->spawn_id = GetID();
|
||||
spu->x_pos = FloatToEQ19(GetX());
|
||||
spu->y_pos = FloatToEQ19(GetY());
|
||||
spu->z_pos = FloatToEQ19(GetZ());
|
||||
spu->delta_x = FloatToEQ13(new_x);
|
||||
spu->delta_y = FloatToEQ13(new_y);
|
||||
spu->delta_z = FloatToEQ13(toss_amt);
|
||||
spu->heading = FloatToEQ12(GetHeading());
|
||||
spu->padding0002 =0;
|
||||
spu->padding0006 =7;
|
||||
spu->padding0014 =0x7f;
|
||||
spu->padding0018 =0x5df27;
|
||||
spu->animation = 0;
|
||||
spu->delta_heading = FloatToEQ10(0);
|
||||
outapp_push->priority = 5;
|
||||
entity_list.QueueClients(this, outapp_push, true);
|
||||
if(IsClient())
|
||||
CastToClient()->FastQueuePacket(&outapp_push);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
122
zone/spells.cpp
122
zone/spells.cpp
@ -82,6 +82,7 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
#include "string_ids.h"
|
||||
#include "worldserver.h"
|
||||
#include "nats_manager.h"
|
||||
#include "fastmath.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
@ -106,6 +107,7 @@ extern Zone* zone;
|
||||
extern volatile bool is_zone_loaded;
|
||||
extern WorldServer worldserver;
|
||||
extern NatsManager nats;
|
||||
extern FastMath g_Math;
|
||||
|
||||
using EQEmu::CastingSlot;
|
||||
|
||||
@ -1213,7 +1215,10 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo
|
||||
|
||||
// handle the components for traditional casters
|
||||
else {
|
||||
if(c->GetInv().HasItem(component, component_count, invWhereWorn|invWherePersonal) == -1) // item not found
|
||||
if (!RuleB(Character, PetsUseReagents) && IsEffectInSpell(spell_id, SE_SummonPet)) {
|
||||
//bypass reagent cost
|
||||
}
|
||||
else if(c->GetInv().HasItem(component, component_count, invWhereWorn|invWherePersonal) == -1) // item not found
|
||||
{
|
||||
if (!missingreags)
|
||||
{
|
||||
@ -1243,6 +1248,9 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!RuleB(Character, PetsUseReagents) && IsEffectInSpell(spell_id, SE_SummonPet)) {
|
||||
//bypass reagent cost
|
||||
}
|
||||
else if (!bard_song_mode)
|
||||
{
|
||||
int noexpend;
|
||||
@ -2651,20 +2659,18 @@ void Mob::BardPulse(uint16 spell_id, Mob *caster) {
|
||||
action->source = caster->GetID();
|
||||
action->target = GetID();
|
||||
action->spell = spell_id;
|
||||
action->sequence = (uint32) (GetHeading()); // just some random number
|
||||
action->force = spells[spell_id].pushback;
|
||||
action->hit_heading = GetHeading();
|
||||
action->hit_pitch = spells[spell_id].pushup;
|
||||
action->instrument_mod = caster->GetInstrumentMod(spell_id);
|
||||
action->buff_unknown = 0;
|
||||
action->level = buffs[buffs_i].casterlevel;
|
||||
action->effect_flag = 0;
|
||||
action->spell_level = action->level = buffs[buffs_i].casterlevel;
|
||||
action->type = DamageTypeSpell;
|
||||
entity_list.QueueCloseClients(this, packet, false, RuleI(Range, SongMessages), 0, true, IsClient() ? FilterPCSpells : FilterNPCSpells);
|
||||
|
||||
action->buff_unknown = 4;
|
||||
action->effect_flag = 4;
|
||||
|
||||
if(IsEffectInSpell(spell_id, SE_TossUp))
|
||||
{
|
||||
action->buff_unknown = 0;
|
||||
}
|
||||
else if(spells[spell_id].pushback > 0 || spells[spell_id].pushup > 0)
|
||||
if(spells[spell_id].pushback != 0.0f || spells[spell_id].pushup != 0.0f)
|
||||
{
|
||||
if(IsClient())
|
||||
{
|
||||
@ -2672,38 +2678,6 @@ void Mob::BardPulse(uint16 spell_id, Mob *caster) {
|
||||
{
|
||||
CastToClient()->SetKnockBackExemption(true);
|
||||
|
||||
action->buff_unknown = 0;
|
||||
auto outapp_push = new EQApplicationPacket(
|
||||
OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
|
||||
PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)outapp_push->pBuffer;
|
||||
|
||||
double look_heading = caster->CalculateHeadingToTarget(GetX(), GetY());
|
||||
look_heading /= 256;
|
||||
look_heading *= 360;
|
||||
if(look_heading > 360)
|
||||
look_heading -= 360;
|
||||
|
||||
//x and y are crossed mkay
|
||||
double new_x = spells[spell_id].pushback * sin(double(look_heading * 3.141592 / 180.0));
|
||||
double new_y = spells[spell_id].pushback * cos(double(look_heading * 3.141592 / 180.0));
|
||||
|
||||
spu->spawn_id = GetID();
|
||||
spu->x_pos = FloatToEQ19(GetX());
|
||||
spu->y_pos = FloatToEQ19(GetY());
|
||||
spu->z_pos = FloatToEQ19(GetZ());
|
||||
spu->delta_x = FloatToEQ13(new_x);
|
||||
spu->delta_y = FloatToEQ13(new_y);
|
||||
spu->delta_z = FloatToEQ13(spells[spell_id].pushup);
|
||||
spu->heading = FloatToEQ12(GetHeading());
|
||||
spu->padding0002 =0;
|
||||
spu->padding0006 =7;
|
||||
spu->padding0014 =0x7f;
|
||||
spu->padding0018 =0x5df27;
|
||||
spu->animation = 0;
|
||||
spu->delta_heading = FloatToEQ10(0);
|
||||
outapp_push->priority = 6;
|
||||
entity_list.QueueClients(this, outapp_push, true);
|
||||
CastToClient()->FastQueuePacket(&outapp_push);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2724,7 +2698,9 @@ void Mob::BardPulse(uint16 spell_id, Mob *caster) {
|
||||
cd->source = action->source;
|
||||
cd->type = DamageTypeSpell;
|
||||
cd->spellid = action->spell;
|
||||
cd->meleepush_xy = action->sequence;
|
||||
cd->force = action->force;
|
||||
cd->hit_heading = action->hit_heading;
|
||||
cd->hit_pitch = action->hit_pitch;
|
||||
cd->damage = 0;
|
||||
if(!IsEffectInSpell(spell_id, SE_BindAffinity))
|
||||
{
|
||||
@ -3532,12 +3508,14 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
|
||||
action->target = spelltar->GetID();
|
||||
}
|
||||
|
||||
action->level = caster_level; // caster level, for animation only
|
||||
action->spell_level = action->level = caster_level; // caster level, for animation only
|
||||
action->type = 231; // 231 means a spell
|
||||
action->spell = spell_id;
|
||||
action->sequence = (uint32) (GetHeading()); // just some random number
|
||||
action->force = spells[spell_id].pushback;
|
||||
action->hit_heading = GetHeading();
|
||||
action->hit_pitch = spells[spell_id].pushup;
|
||||
action->instrument_mod = GetInstrumentMod(spell_id);
|
||||
action->buff_unknown = 0;
|
||||
action->effect_flag = 0;
|
||||
|
||||
if(spelltar != this && spelltar->IsClient()) // send to target
|
||||
spelltar->CastToClient()->QueuePacket(action_packet);
|
||||
@ -3964,53 +3942,21 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
|
||||
// NOTE: this is what causes the buff icon to appear on the client, if
|
||||
// this is a buff - but it sortof relies on the first packet.
|
||||
// the complete sequence is 2 actions and 1 damage message
|
||||
action->buff_unknown = 0x04; // this is a success flag
|
||||
action->effect_flag = 0x04; // this is a success flag
|
||||
|
||||
if(IsEffectInSpell(spell_id, SE_TossUp))
|
||||
{
|
||||
action->buff_unknown = 0;
|
||||
}
|
||||
else if(spells[spell_id].pushback > 0 || spells[spell_id].pushup > 0)
|
||||
if(spells[spell_id].pushback != 0.0f || spells[spell_id].pushup != 0.0f)
|
||||
{
|
||||
if(spelltar->IsClient())
|
||||
{
|
||||
if(!IsBuffSpell(spell_id))
|
||||
{
|
||||
spelltar->CastToClient()->SetKnockBackExemption(true);
|
||||
|
||||
action->buff_unknown = 0;
|
||||
auto outapp_push =
|
||||
new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
|
||||
PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)outapp_push->pBuffer;
|
||||
|
||||
double look_heading = CalculateHeadingToTarget(spelltar->GetX(), spelltar->GetY());
|
||||
look_heading /= 256;
|
||||
look_heading *= 360;
|
||||
if(look_heading > 360)
|
||||
look_heading -= 360;
|
||||
|
||||
//x and y are crossed mkay
|
||||
double new_x = spells[spell_id].pushback * sin(double(look_heading * 3.141592 / 180.0));
|
||||
double new_y = spells[spell_id].pushback * cos(double(look_heading * 3.141592 / 180.0));
|
||||
|
||||
spu->spawn_id = spelltar->GetID();
|
||||
spu->x_pos = FloatToEQ19(spelltar->GetX());
|
||||
spu->y_pos = FloatToEQ19(spelltar->GetY());
|
||||
spu->z_pos = FloatToEQ19(spelltar->GetZ());
|
||||
spu->delta_x = FloatToEQ13(new_x);
|
||||
spu->delta_y = FloatToEQ13(new_y);
|
||||
spu->delta_z = FloatToEQ13(spells[spell_id].pushup);
|
||||
spu->heading = FloatToEQ12(spelltar->GetHeading());
|
||||
spu->padding0002 =0;
|
||||
spu->padding0006 =7;
|
||||
spu->padding0014 =0x7f;
|
||||
spu->padding0018 =0x5df27;
|
||||
spu->animation = 0;
|
||||
spu->delta_heading = FloatToEQ10(0);
|
||||
outapp_push->priority = 6;
|
||||
entity_list.QueueClients(this, outapp_push, true);
|
||||
spelltar->CastToClient()->FastQueuePacket(&outapp_push);
|
||||
}
|
||||
} else if (RuleB(Spells, NPCSpellPush) && !spelltar->IsRooted() && spelltar->ForcedMovement == 0) {
|
||||
spelltar->m_Delta.x += action->force * g_Math.FastSin(action->hit_heading);
|
||||
spelltar->m_Delta.y += action->force * g_Math.FastCos(action->hit_heading);
|
||||
spelltar->m_Delta.z += action->hit_pitch;
|
||||
spelltar->ForcedMovement = 6;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4038,7 +3984,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
|
||||
cd->source = action->source;
|
||||
cd->type = action->type;
|
||||
cd->spellid = action->spell;
|
||||
cd->meleepush_xy = action->sequence;
|
||||
cd->force = action->force;
|
||||
cd->hit_heading = action->hit_heading;
|
||||
cd->hit_pitch = action->hit_pitch;
|
||||
cd->damage = 0;
|
||||
if(!IsEffectInSpell(spell_id, SE_BindAffinity)){
|
||||
entity_list.QueueCloseClients(
|
||||
@ -5722,7 +5670,7 @@ void Client::SendSpellAnim(uint16 targetid, uint16 spell_id)
|
||||
a->source = this->GetID();
|
||||
a->type = 231;
|
||||
a->spell = spell_id;
|
||||
a->sequence = 231;
|
||||
a->hit_heading = GetHeading();
|
||||
|
||||
app.priority = 1;
|
||||
entity_list.QueueCloseClients(this, &app, false, RuleI(Range, SpellParticles));
|
||||
|
||||
@ -120,6 +120,7 @@
|
||||
#define FAIL_DISARM_DETECTED_TRAP 370 //You fail to disarm the detected trap.
|
||||
#define LOOT_LORE_ERROR 371 //You cannot loot this Lore Item. You already have one.
|
||||
#define PICK_LORE 379 //You cannot pick up a lore item you already possess.
|
||||
#define POISON_TOO_HIGH 382 // This poison is too high level for you to apply.
|
||||
#define CONSENT_DENIED 390 //You do not have consent to summon that corpse.
|
||||
#define DISCIPLINE_RDY 393 //You are ready to use a new discipline now.
|
||||
#define CONSENT_INVALID_NAME 397 //Not a valid consent name.
|
||||
|
||||
@ -2804,8 +2804,7 @@ void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, int SequenceN
|
||||
if (strlen(Tasks[TaskID]->Reward) != 0)
|
||||
linker.SetProxyText(Tasks[TaskID]->Reward);
|
||||
|
||||
auto reward_link = linker.GenerateLink();
|
||||
reward_text.append(reward_link);
|
||||
reward_text.append(linker.GenerateLink());
|
||||
}
|
||||
else {
|
||||
reward_text.append(Tasks[TaskID]->Reward);
|
||||
|
||||
@ -218,7 +218,7 @@ void Trap::Trigger(Mob* trigger)
|
||||
int dmg = zone->random.Int(effectvalue, effectvalue2);
|
||||
trigger->SetHP(trigger->GetHP() - dmg);
|
||||
a->damage = dmg;
|
||||
a->meleepush_xy = zone->random.Int(0, 1234567);
|
||||
a->hit_heading = 0.0f;
|
||||
a->source = GetHiddenTrigger()!=nullptr ? GetHiddenTrigger()->GetID() : trigger->GetID();
|
||||
a->spellid = 0;
|
||||
a->target = trigger->GetID();
|
||||
|
||||
@ -29,10 +29,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "npc.h"
|
||||
#include "quest_parser_collection.h"
|
||||
#include "water_map.h"
|
||||
#include "fastmath.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
extern FastMath g_Math;
|
||||
|
||||
struct wp_distance
|
||||
{
|
||||
float dist;
|
||||
@ -990,6 +993,35 @@ float Mob::GetZOffset() const {
|
||||
return 0.2 * GetSize() * offset;
|
||||
}
|
||||
|
||||
// This function will try to move the mob along the relative angle a set distance
|
||||
// if it can't be moved, it will lower the distance and try again
|
||||
// If we want to move on like say a spawn, we can pass send as false
|
||||
void Mob::TryMoveAlong(float distance, float angle, bool send)
|
||||
{
|
||||
angle += GetHeading();
|
||||
angle = FixHeading(angle);
|
||||
|
||||
glm::vec3 tmp_pos;
|
||||
glm::vec3 new_pos = GetPosition();
|
||||
new_pos.x += distance * g_Math.FastSin(angle);
|
||||
new_pos.y += distance * g_Math.FastCos(angle);
|
||||
new_pos.z += GetZOffset();
|
||||
|
||||
if (zone->HasMap()) {
|
||||
auto new_z = zone->zonemap->FindClosestZ(new_pos, nullptr);
|
||||
if (new_z != BEST_Z_INVALID)
|
||||
new_pos.z = new_z;
|
||||
|
||||
if (zone->zonemap->LineIntersectsZone(GetPosition(), new_pos, 0.0f, &tmp_pos))
|
||||
new_pos = tmp_pos;
|
||||
}
|
||||
|
||||
new_pos.z = GetFixedZ(new_pos);
|
||||
Teleport(new_pos);
|
||||
if (send)
|
||||
SendPositionUpdate();
|
||||
}
|
||||
|
||||
int ZoneDatabase::GetHighestGrid(uint32 zoneid) {
|
||||
|
||||
std::string query = StringFormat("SELECT COALESCE(MAX(id), 0) FROM grid WHERE zoneid = %i", zoneid);
|
||||
|
||||
@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include <stdio.h>
|
||||
#include <iomanip>
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#include <process.h>
|
||||
@ -1813,6 +1814,13 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
|
||||
break;
|
||||
}
|
||||
case ServerOP_UCSServerStatusReply:
|
||||
{
|
||||
auto ucsss = (UCSServerStatus_Struct*)pack->pBuffer;
|
||||
if (zone)
|
||||
zone->SetUCSServerAvailable((ucsss->available != 0), ucsss->timestamp);
|
||||
break;
|
||||
}
|
||||
case ServerOP_CZSetEntityVariableByNPCTypeID:
|
||||
{
|
||||
CZSetEntVarByNPCTypeID_Struct* CZM = (CZSetEntVarByNPCTypeID_Struct*)pack->pBuffer;
|
||||
|
||||
@ -146,6 +146,8 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) {
|
||||
UpdateWindowTitle();
|
||||
zone->GetTimeSync();
|
||||
|
||||
zone->RequestUCSServerStatus();
|
||||
|
||||
/* Set Logging */
|
||||
|
||||
LogSys.StartFileLogs(StringFormat("%s_version_%u_inst_id_%u_port_%u", zone->GetShortName(), zone->GetInstanceVersion(), zone->GetInstanceID(), ZoneConfig::get()->ZonePort));
|
||||
@ -847,6 +849,9 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name)
|
||||
GuildBanks = new GuildBankManager;
|
||||
else
|
||||
GuildBanks = nullptr;
|
||||
|
||||
m_ucss_available = false;
|
||||
m_last_ucss_update = 0;
|
||||
}
|
||||
|
||||
Zone::~Zone() {
|
||||
@ -1863,14 +1868,17 @@ bool ZoneDatabase::GetDecayTimes(npcDecayTimes_Struct* npcCorpseDecayTimes) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Zone::weatherSend()
|
||||
void Zone::weatherSend(Client* client)
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_Weather, 8);
|
||||
if(zone_weather>0)
|
||||
outapp->pBuffer[0] = zone_weather-1;
|
||||
if(zone_weather>0)
|
||||
outapp->pBuffer[4] = zone->weather_intensity;
|
||||
entity_list.QueueClients(0, outapp);
|
||||
if (client)
|
||||
client->QueuePacket(outapp);
|
||||
else
|
||||
entity_list.QueueClients(0, outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
@ -2336,3 +2344,22 @@ void Zone::UpdateHotzone()
|
||||
is_hotzone = atoi(row[0]) == 0 ? false: true;
|
||||
}
|
||||
|
||||
void Zone::RequestUCSServerStatus() {
|
||||
auto outapp = new ServerPacket(ServerOP_UCSServerStatusRequest, sizeof(UCSServerStatus_Struct));
|
||||
auto ucsss = (UCSServerStatus_Struct*)outapp->pBuffer;
|
||||
ucsss->available = 0;
|
||||
ucsss->port = Config->ZonePort;
|
||||
ucsss->unused = 0;
|
||||
worldserver.SendPacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
void Zone::SetUCSServerAvailable(bool ucss_available, uint32 update_timestamp) {
|
||||
if (m_last_ucss_update == update_timestamp && m_ucss_available != ucss_available) {
|
||||
m_ucss_available = false;
|
||||
RequestUCSServerStatus();
|
||||
return;
|
||||
}
|
||||
if (m_last_ucss_update < update_timestamp)
|
||||
m_ucss_available = ucss_available;
|
||||
}
|
||||
|
||||
@ -224,7 +224,7 @@ public:
|
||||
void SetDate(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute);
|
||||
void SetTime(uint8 hour, uint8 minute, bool update_world = true);
|
||||
|
||||
void weatherSend();
|
||||
void weatherSend(Client* client = nullptr);
|
||||
bool CanBind() const { return(can_bind); }
|
||||
bool IsCity() const { return(is_city); }
|
||||
bool CanDoCombat() const { return(can_combat); }
|
||||
@ -275,6 +275,10 @@ public:
|
||||
inline void ShowZoneGlobalLoot(Client *to) { m_global_loot.ShowZoneGlobalLoot(to); }
|
||||
inline void ShowNPCGlobalLoot(Client *to, NPC *who) { m_global_loot.ShowNPCGlobalLoot(to, who); }
|
||||
|
||||
void RequestUCSServerStatus();
|
||||
void SetUCSServerAvailable(bool ucss_available, uint32 update_timestamp);
|
||||
bool IsUCSServerAvailable() { return m_ucss_available; }
|
||||
|
||||
// random object that provides random values for the zone
|
||||
EQEmu::Random random;
|
||||
|
||||
@ -355,6 +359,9 @@ private:
|
||||
Timer hotzone_timer;
|
||||
|
||||
GlobalLootManager m_global_loot;
|
||||
|
||||
bool m_ucss_available;
|
||||
uint32 m_last_ucss_update;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
291
zone/zonedb.cpp
291
zone/zonedb.cpp
@ -325,62 +325,260 @@ bool ZoneDatabase::logevents(const char* accountname,uint32 accountid,uint8 stat
|
||||
return true;
|
||||
}
|
||||
|
||||
void ZoneDatabase::RegisterBug(BugReport_Struct* bug_report) {
|
||||
if (!bug_report)
|
||||
return;
|
||||
|
||||
void ZoneDatabase::UpdateBug(BugStruct* bug) {
|
||||
|
||||
uint32 len = strlen(bug->bug);
|
||||
char* bugtext = nullptr;
|
||||
if(len > 0)
|
||||
{
|
||||
bugtext = new char[2*len+1];
|
||||
memset(bugtext, 0, 2*len+1);
|
||||
DoEscapeString(bugtext, bug->bug, len);
|
||||
size_t len = 0;
|
||||
char* name_ = nullptr;
|
||||
char* ui_ = nullptr;
|
||||
char* type_ = nullptr;
|
||||
char* target_ = nullptr;
|
||||
char* bug_ = nullptr;
|
||||
|
||||
len = strlen(bug_report->reporter_name);
|
||||
if (len) {
|
||||
if (len > 63) // check against db column size
|
||||
len = 63;
|
||||
name_ = new char[(2 * len + 1)];
|
||||
memset(name_, 0, (2 * len + 1));
|
||||
DoEscapeString(name_, bug_report->reporter_name, len);
|
||||
}
|
||||
|
||||
len = strlen(bug->ui);
|
||||
char* uitext = nullptr;
|
||||
if(len > 0)
|
||||
{
|
||||
uitext = new char[2*len+1];
|
||||
memset(uitext, 0, 2*len+1);
|
||||
DoEscapeString(uitext, bug->ui, len);
|
||||
len = strlen(bug_report->ui_path);
|
||||
if (len) {
|
||||
if (len > 127)
|
||||
len = 127;
|
||||
ui_ = new char[(2 * len + 1)];
|
||||
memset(ui_, 0, (2 * len + 1));
|
||||
DoEscapeString(ui_, bug_report->ui_path, len);
|
||||
}
|
||||
|
||||
len = strlen(bug->target_name);
|
||||
char* targettext = nullptr;
|
||||
if(len > 0)
|
||||
{
|
||||
targettext = new char[2*len+1];
|
||||
memset(targettext, 0, 2*len+1);
|
||||
DoEscapeString(targettext, bug->target_name, len);
|
||||
len = strlen(bug_report->category_name);
|
||||
if (len) {
|
||||
if (len > 63)
|
||||
len = 63;
|
||||
type_ = new char[(2 * len + 1)];
|
||||
memset(type_, 0, (2 * len + 1));
|
||||
DoEscapeString(type_, bug_report->category_name, len);
|
||||
}
|
||||
|
||||
//x and y are intentionally swapped because eq is inversexy coords
|
||||
std::string query = StringFormat("INSERT INTO bugs (zone, name, ui, x, y, z, type, flag, target, bug, date) "
|
||||
len = strlen(bug_report->target_name);
|
||||
if (len) {
|
||||
if (len > 63)
|
||||
len = 63;
|
||||
target_ = new char[(2 * len + 1)];
|
||||
memset(target_, 0, (2 * len + 1));
|
||||
DoEscapeString(target_, bug_report->target_name, len);
|
||||
}
|
||||
|
||||
len = strlen(bug_report->bug_report);
|
||||
if (len) {
|
||||
if (len > 1023)
|
||||
len = 1023;
|
||||
bug_ = new char[(2 * len + 1)];
|
||||
memset(bug_, 0, (2 * len + 1));
|
||||
DoEscapeString(bug_, bug_report->bug_report, len);
|
||||
}
|
||||
|
||||
//x and y are intentionally swapped because eq is inversexy coords //is this msg out-of-date or are the parameters wrong?
|
||||
std::string query = StringFormat(
|
||||
"INSERT INTO `bugs` (`zone`, `name`, `ui`, `x`, `y`, `z`, `type`, `flag`, `target`, `bug`, `date`) "
|
||||
"VALUES('%s', '%s', '%s', '%.2f', '%.2f', '%.2f', '%s', %d, '%s', '%s', CURDATE())",
|
||||
zone->GetShortName(), bug->name, uitext == nullptr ? "": uitext,
|
||||
bug->x, bug->y, bug->z, bug->chartype, bug->type, targettext == nullptr? "Unknown Target": targettext,
|
||||
bugtext==nullptr?"":bugtext);
|
||||
safe_delete_array(bugtext);
|
||||
safe_delete_array(uitext);
|
||||
safe_delete_array(targettext);
|
||||
zone->GetShortName(),
|
||||
(name_ ? name_ : ""),
|
||||
(ui_ ? ui_ : ""),
|
||||
bug_report->pos_x,
|
||||
bug_report->pos_y,
|
||||
bug_report->pos_z,
|
||||
(type_ ? type_ : ""),
|
||||
bug_report->optional_info_mask,
|
||||
(target_ ? target_ : "Unknown Target"),
|
||||
(bug_ ? bug_ : "")
|
||||
);
|
||||
safe_delete_array(name_);
|
||||
safe_delete_array(ui_);
|
||||
safe_delete_array(type_);
|
||||
safe_delete_array(target_);
|
||||
safe_delete_array(bug_);
|
||||
|
||||
QueryDatabase(query);
|
||||
}
|
||||
|
||||
void ZoneDatabase::UpdateBug(PetitionBug_Struct* bug){
|
||||
void ZoneDatabase::RegisterBug(Client* client, BugReport_Struct* bug_report) {
|
||||
if (!client || !bug_report)
|
||||
return;
|
||||
|
||||
uint32 len = strlen(bug->text);
|
||||
auto bugtext = new char[2 * len + 1];
|
||||
memset(bugtext, 0, 2*len+1);
|
||||
DoEscapeString(bugtext, bug->text, len);
|
||||
size_t len = 0;
|
||||
char* category_name_ = nullptr;
|
||||
char* reporter_name_ = nullptr;
|
||||
char* ui_path_ = nullptr;
|
||||
char* target_name_ = nullptr;
|
||||
char* bug_report_ = nullptr;
|
||||
char* system_info_ = nullptr;
|
||||
|
||||
std::string query = StringFormat("INSERT INTO bugs (type, name, bugtext, flag) "
|
||||
"VALUES('%s', '%s', '%s', %i)",
|
||||
"Petition", bug->name, bugtext, 25);
|
||||
safe_delete_array(bugtext);
|
||||
QueryDatabase(query);
|
||||
len = strlen(bug_report->category_name);
|
||||
if (len) {
|
||||
if (len > 63) // check against db column size
|
||||
len = 63;
|
||||
category_name_ = new char[(2 * len + 1)];
|
||||
memset(category_name_, 0, (2 * len + 1));
|
||||
DoEscapeString(category_name_, bug_report->category_name, len);
|
||||
}
|
||||
|
||||
len = strlen(bug_report->reporter_name);
|
||||
if (len) {
|
||||
if (len > 63)
|
||||
len = 63;
|
||||
reporter_name_ = new char[(2 * len + 1)];
|
||||
memset(reporter_name_, 0, (2 * len + 1));
|
||||
DoEscapeString(reporter_name_, bug_report->reporter_name, len);
|
||||
}
|
||||
|
||||
len = strlen(bug_report->ui_path);
|
||||
if (len) {
|
||||
if (len > 127)
|
||||
len = 127;
|
||||
ui_path_ = new char[(2 * len + 1)];
|
||||
memset(ui_path_, 0, (2 * len + 1));
|
||||
DoEscapeString(ui_path_, bug_report->ui_path, len);
|
||||
}
|
||||
|
||||
len = strlen(bug_report->target_name);
|
||||
if (len) {
|
||||
if (len > 63)
|
||||
len = 63;
|
||||
target_name_ = new char[(2 * len + 1)];
|
||||
memset(target_name_, 0, (2 * len + 1));
|
||||
DoEscapeString(target_name_, bug_report->target_name, len);
|
||||
}
|
||||
|
||||
len = strlen(bug_report->bug_report);
|
||||
if (len) {
|
||||
if (len > 1023)
|
||||
len = 1023;
|
||||
bug_report_ = new char[(2 * len + 1)];
|
||||
memset(bug_report_, 0, (2 * len + 1));
|
||||
DoEscapeString(bug_report_, bug_report->bug_report, len);
|
||||
}
|
||||
|
||||
len = strlen(bug_report->system_info);
|
||||
if (len) {
|
||||
if (len > 1023)
|
||||
len = 1023;
|
||||
system_info_ = new char[(2 * len + 1)];
|
||||
memset(system_info_, 0, (2 * len + 1));
|
||||
DoEscapeString(system_info_, bug_report->system_info, len);
|
||||
}
|
||||
|
||||
std::string query = StringFormat(
|
||||
"INSERT INTO `bug_reports` "
|
||||
"(`zone`,"
|
||||
" `client_version_id`,"
|
||||
" `client_version_name`,"
|
||||
" `account_id`,"
|
||||
" `character_id`,"
|
||||
" `character_name`,"
|
||||
" `reporter_spoof`,"
|
||||
" `category_id`,"
|
||||
" `category_name`,"
|
||||
" `reporter_name`,"
|
||||
" `ui_path`,"
|
||||
" `pos_x`,"
|
||||
" `pos_y`,"
|
||||
" `pos_z`,"
|
||||
" `heading`,"
|
||||
" `time_played`,"
|
||||
" `target_id`,"
|
||||
" `target_name`,"
|
||||
" `optional_info_mask`,"
|
||||
" `_can_duplicate`,"
|
||||
" `_crash_bug`,"
|
||||
" `_target_info`,"
|
||||
" `_character_flags`,"
|
||||
" `_unknown_value`,"
|
||||
" `bug_report`,"
|
||||
" `system_info`) "
|
||||
"VALUES "
|
||||
"('%s',"
|
||||
" '%u',"
|
||||
" '%s',"
|
||||
" '%u',"
|
||||
" '%u',"
|
||||
" '%s',"
|
||||
" '%u',"
|
||||
" '%u',"
|
||||
" '%s',"
|
||||
" '%s',"
|
||||
" '%s',"
|
||||
" '%1.1f',"
|
||||
" '%1.1f',"
|
||||
" '%1.1f',"
|
||||
" '%u',"
|
||||
" '%u',"
|
||||
" '%u',"
|
||||
" '%s',"
|
||||
" '%u',"
|
||||
" '%u',"
|
||||
" '%u',"
|
||||
" '%u',"
|
||||
" '%u',"
|
||||
" '%u',"
|
||||
" '%s',"
|
||||
" '%s')",
|
||||
zone->GetShortName(),
|
||||
client->ClientVersion(),
|
||||
EQEmu::versions::ClientVersionName(client->ClientVersion()),
|
||||
client->AccountID(),
|
||||
client->CharacterID(),
|
||||
client->GetName(),
|
||||
(strcmp(client->GetName(), reporter_name_) != 0 ? 1 : 0),
|
||||
bug_report->category_id,
|
||||
(category_name_ ? category_name_ : ""),
|
||||
(reporter_name_ ? reporter_name_ : ""),
|
||||
(ui_path_ ? ui_path_ : ""),
|
||||
bug_report->pos_x,
|
||||
bug_report->pos_y,
|
||||
bug_report->pos_z,
|
||||
bug_report->heading,
|
||||
bug_report->time_played,
|
||||
bug_report->target_id,
|
||||
(target_name_ ? target_name_ : ""),
|
||||
bug_report->optional_info_mask,
|
||||
((bug_report->optional_info_mask & EQEmu::bug::infoCanDuplicate) != 0 ? 1 : 0),
|
||||
((bug_report->optional_info_mask & EQEmu::bug::infoCrashBug) != 0 ? 1 : 0),
|
||||
((bug_report->optional_info_mask & EQEmu::bug::infoTargetInfo) != 0 ? 1 : 0),
|
||||
((bug_report->optional_info_mask & EQEmu::bug::infoCharacterFlags) != 0 ? 1 : 0),
|
||||
((bug_report->optional_info_mask & EQEmu::bug::infoUnknownValue) != 0 ? 1 : 0),
|
||||
(bug_report_ ? bug_report_ : ""),
|
||||
(system_info_ ? system_info_ : "")
|
||||
);
|
||||
safe_delete_array(category_name_);
|
||||
safe_delete_array(reporter_name_);
|
||||
safe_delete_array(ui_path_);
|
||||
safe_delete_array(target_name_);
|
||||
safe_delete_array(bug_report_);
|
||||
safe_delete_array(system_info_);
|
||||
|
||||
auto result = QueryDatabase(query);
|
||||
|
||||
// TODO: Entity dumping [RuleB(Bugs, DumpTargetEntity)]
|
||||
}
|
||||
|
||||
//void ZoneDatabase::UpdateBug(PetitionBug_Struct* bug) {
|
||||
//
|
||||
// uint32 len = strlen(bug->text);
|
||||
// auto bugtext = new char[2 * len + 1];
|
||||
// memset(bugtext, 0, 2 * len + 1);
|
||||
// DoEscapeString(bugtext, bug->text, len);
|
||||
//
|
||||
// std::string query = StringFormat("INSERT INTO bugs (type, name, bugtext, flag) "
|
||||
// "VALUES('%s', '%s', '%s', %i)",
|
||||
// "Petition", bug->name, bugtext, 25);
|
||||
// safe_delete_array(bugtext);
|
||||
// QueryDatabase(query);
|
||||
//}
|
||||
|
||||
bool ZoneDatabase::SetSpecialAttkFlag(uint8 id, const char* flag) {
|
||||
|
||||
std::string query = StringFormat("UPDATE npc_types SET npcspecialattks='%s' WHERE id = %i;", flag, id);
|
||||
@ -1425,6 +1623,8 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla
|
||||
if (account_id <= 0)
|
||||
return false;
|
||||
|
||||
std::string mail_key = database.GetMailKey(character_id);
|
||||
|
||||
clock_t t = std::clock(); /* Function timer start */
|
||||
std::string query = StringFormat(
|
||||
"REPLACE INTO `character_data` ("
|
||||
@ -1521,7 +1721,8 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla
|
||||
" e_aa_effects, "
|
||||
" e_percent_to_aa, "
|
||||
" e_expended_aa_spent, "
|
||||
" e_last_invsnapshot "
|
||||
" e_last_invsnapshot, "
|
||||
" mailkey "
|
||||
") "
|
||||
"VALUES ("
|
||||
"%u," // id " id, "
|
||||
@ -1617,7 +1818,8 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla
|
||||
"%u," // e_aa_effects
|
||||
"%u," // e_percent_to_aa
|
||||
"%u," // e_expended_aa_spent
|
||||
"%u" // e_last_invsnapshot
|
||||
"%u," // e_last_invsnapshot
|
||||
"'%s'" // mailkey mail_key
|
||||
")",
|
||||
character_id, // " id, "
|
||||
account_id, // " account_id, "
|
||||
@ -1712,7 +1914,8 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla
|
||||
m_epp->aa_effects,
|
||||
m_epp->perAA,
|
||||
m_epp->expended_aa,
|
||||
m_epp->last_invsnapshot_time
|
||||
m_epp->last_invsnapshot_time,
|
||||
mail_key.c_str()
|
||||
);
|
||||
auto results = database.QueryDatabase(query);
|
||||
Log(Logs::General, Logs::None, "ZoneDatabase::SaveCharacterData %i, done... Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC);
|
||||
|
||||
@ -442,8 +442,9 @@ public:
|
||||
bool DeleteMerc(uint32 merc_id);
|
||||
|
||||
/* Petitions */
|
||||
void UpdateBug(BugStruct* bug);
|
||||
void UpdateBug(PetitionBug_Struct* bug);
|
||||
void RegisterBug(BugReport_Struct* bug_report); // old method
|
||||
void RegisterBug(Client* client, BugReport_Struct* bug_report); // new method
|
||||
//void UpdateBug(PetitionBug_Struct* bug);
|
||||
void DeletePetitionFromDB(Petition* wpet);
|
||||
void UpdatePetitionToDB(Petition* wpet);
|
||||
void InsertPetitionToDB(Petition* wpet);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user