From 3dec02881a2b272292639cf26757d63c182cd09b Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 15 Nov 2016 01:37:58 -0500 Subject: [PATCH] Revamp Buff slots Server side we now have 63 total buff slots for clients They match RoF/RoF2 and are mapped as 42 long, 20 short, 1 disc The player is limited to what their clients supports, so Tit players can have 25 buffs and 12 songs, while other can have more When you log in, we only load up to the max your client supports, the rest of the buffs are thrown away Also changed is the default Max Buff slots for NPCs, they now match Tit (60) If you are thinking about raising that, here are what some other clients support Tit - SoF 60, SoD - UF 85, RoF - RoF2 97 (although UI only has 85 slots, you can edit it if you want more) Also SoD+ the pet limits match the NPC limits. This will increase memory usage a bit, but I don't see a solution to that Plus I think most people want this. --- common/emu_constants.h | 8 ++++ common/eq_limits.cpp | 68 +++++++++++++++++++++++++++++--- common/eq_limits.h | 7 ++++ common/patches/rof.cpp | 60 +++++++++++++++++----------- common/patches/rof2.cpp | 67 +++++++++++++++++-------------- common/patches/rof2_limits.h | 8 ++++ common/patches/rof_limits.h | 8 ++++ common/patches/sod.cpp | 35 ++++++++++++++-- common/patches/sod_limits.h | 8 ++++ common/patches/sof.cpp | 33 +++++++++++++++- common/patches/sof_limits.h | 8 ++++ common/patches/titanium.cpp | 33 +++++++++++++++- common/patches/titanium_limits.h | 8 ++++ common/patches/uf.cpp | 55 ++++++++++++++++---------- common/patches/uf_limits.h | 40 +++++++++++-------- common/ruletypes.h | 10 ++--- zone/client.h | 8 ++-- zone/spells.cpp | 4 +- zone/zonedb.cpp | 3 +- 19 files changed, 358 insertions(+), 113 deletions(-) diff --git a/common/emu_constants.h b/common/emu_constants.h index 9e44976a8..e156fe98a 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -116,6 +116,14 @@ namespace EQEmu const size_t SayLinkBodySize = RoF2::constants::SayLinkBodySize; + const int LongBuffs = RoF2::constants::LongBuffs; + const int ShortBuffs = RoF2::constants::ShortBuffs; + const int DiscBuffs = RoF2::constants::DiscBuffs; + const int TotalBuffs = RoF2::constants::TotalBuffs; + const int NPCBuffs = RoF2::constants::NPCBuffs; + const int PetBuffs = RoF2::constants::PetBuffs; + const int MercBuffs = RoF2::constants::MercBuffs; + } /*constants*/ enum class CastingSlot : uint32 { diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index 1c0140811..ce94c4359 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -24,28 +24,84 @@ static const EQEmu::constants::LookupEntry constants_lookup_entries[EQEmu::versions::ClientVersionCount] = { { + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, ClientUnknown::Null }, { + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, Client62::Null }, { - Titanium::constants::CharacterCreationLimit + Titanium::constants::CharacterCreationLimit, + Titanium::constants::LongBuffs, + Titanium::constants::ShortBuffs, + Titanium::constants::DiscBuffs, + Titanium::constants::TotalBuffs, + Titanium::constants::NPCBuffs, + Titanium::constants::PetBuffs, + Titanium::constants::MercBuffs }, { - SoF::constants::CharacterCreationLimit + SoF::constants::CharacterCreationLimit, + SoF::constants::LongBuffs, + SoF::constants::ShortBuffs, + SoF::constants::DiscBuffs, + SoF::constants::TotalBuffs, + SoF::constants::NPCBuffs, + SoF::constants::PetBuffs, + SoF::constants::MercBuffs }, { - SoD::constants::CharacterCreationLimit + SoD::constants::CharacterCreationLimit, + SoD::constants::LongBuffs, + SoD::constants::ShortBuffs, + SoD::constants::DiscBuffs, + SoD::constants::TotalBuffs, + SoD::constants::NPCBuffs, + SoD::constants::PetBuffs, + SoD::constants::MercBuffs }, { - UF::constants::CharacterCreationLimit + UF::constants::CharacterCreationLimit, + UF::constants::LongBuffs, + UF::constants::ShortBuffs, + UF::constants::DiscBuffs, + UF::constants::TotalBuffs, + UF::constants::NPCBuffs, + UF::constants::PetBuffs, + UF::constants::MercBuffs }, { - RoF::constants::CharacterCreationLimit + RoF::constants::CharacterCreationLimit, + RoF::constants::LongBuffs, + RoF::constants::ShortBuffs, + RoF::constants::DiscBuffs, + RoF::constants::TotalBuffs, + RoF::constants::NPCBuffs, + RoF::constants::PetBuffs, + RoF::constants::MercBuffs }, { - RoF2::constants::CharacterCreationLimit + RoF2::constants::CharacterCreationLimit, + RoF2::constants::LongBuffs, + RoF2::constants::ShortBuffs, + RoF2::constants::DiscBuffs, + RoF2::constants::TotalBuffs, + RoF2::constants::NPCBuffs, + RoF2::constants::PetBuffs, + RoF2::constants::MercBuffs } }; diff --git a/common/eq_limits.h b/common/eq_limits.h index 72d710998..252d23053 100644 --- a/common/eq_limits.h +++ b/common/eq_limits.h @@ -38,6 +38,13 @@ namespace EQEmu class LookupEntry { public: size_t CharacterCreationLimit; + int LongBuffs; + int ShortBuffs; + int DiscBuffs; + int TotalBuffs; + int NPCBuffs; + int PetBuffs; + int MercBuffs; }; const LookupEntry* Lookup(versions::ClientVersion client_version); diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 5793e6392..980a4f4ed 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -66,6 +66,9 @@ namespace RoF static inline CastingSlot ServerToRoFCastingSlot(EQEmu::CastingSlot slot); static inline EQEmu::CastingSlot RoFToServerCastingSlot(CastingSlot slot); + static inline int ServerToRoFBuffSlot(int index); + static inline int RoFToServerBuffSlot(int index); + void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already @@ -423,15 +426,8 @@ namespace RoF OUT(buff.y); OUT(buff.x); OUT(buff.z); - uint16 buffslot = emu->slotid; - // Not sure if this is needs amending for RoF yet. - if (buffslot >= 25) - { - buffslot += 17; - } - // TODO: implement slot_data stuff - eq->slotid = buffslot; + eq->slotid = ServerToRoFBuffSlot(emu->slotid); if (emu->bufffade == 1) eq->bufffade = 1; @@ -447,10 +443,10 @@ namespace RoF outapp->WriteUInt32(0); // tic timer outapp->WriteUInt8(0); // Type of OP_BuffCreate packet ? outapp->WriteUInt16(1); // 1 buff in this packet - outapp->WriteUInt32(buffslot); + outapp->WriteUInt32(eq->slotid); outapp->WriteUInt32(0xffffffff); // SpellID (0xffff to remove) outapp->WriteUInt32(0); // Duration - outapp->WriteUInt32(0); // ? + outapp->WriteUInt32(0); // numhits outapp->WriteUInt8(0); // Caster name outapp->WriteUInt8(0); // Type } @@ -474,17 +470,9 @@ namespace RoF __packet->WriteUInt8(emu->all_buffs); // 1 indicates all buffs on the player (0 to add or remove a single buff) __packet->WriteUInt16(emu->count); - for (uint16 i = 0; i < emu->count; ++i) + for (int i = 0; i < emu->count; ++i) { - uint16 buffslot = emu->entries[i].buff_slot; - if (emu->type == 0) { // only correct for self packets - if (emu->entries[i].buff_slot >= 25) - buffslot += 17; - if (buffslot == 54) - buffslot = 62; - } - - __packet->WriteUInt32(buffslot); + __packet->WriteUInt32(emu->type == 0 ? ServerToRoFBuffSlot(emu->entries[i].buff_slot) : emu->entries[i].buff_slot); __packet->WriteUInt32(emu->entries[i].spell_id); __packet->WriteUInt32(emu->entries[i].tics_remaining); __packet->WriteUInt32(emu->entries[i].num_hits); // Unknown @@ -4312,7 +4300,7 @@ namespace RoF IN(buff.unknown003); IN(buff.spellid); IN(buff.duration); - IN(slotid); + emu->slotid = RoFToServerBuffSlot(eq->slotid); IN(bufffade); FINISH_DIRECT_DECODE(); @@ -4325,7 +4313,7 @@ namespace RoF DECODE_LENGTH_EXACT(structs::BuffRemoveRequest_Struct); SETUP_DIRECT_DECODE(BuffRemoveRequest_Struct, structs::BuffRemoveRequest_Struct); - emu->SlotID = (eq->SlotID < 42) ? eq->SlotID : (eq->SlotID - 17); + emu->SlotID = RoFToServerBuffSlot(eq->SlotID); IN(EntityID); @@ -6084,4 +6072,32 @@ namespace RoF return EQEmu::CastingSlot::Discipline; } } + + // these should be optimized out for RoF since they should all boil down to return index :P + // but lets leave it here for future proofing + static inline int ServerToRoFBuffSlot(int index) + { + // we're a disc + if (index >= EQEmu::constants::LongBuffs + EQEmu::constants::ShortBuffs) + return index - EQEmu::constants::LongBuffs - EQEmu::constants::ShortBuffs + + constants::LongBuffs + constants::ShortBuffs; + // we're a song + if (index >= EQEmu::constants::LongBuffs) + return index - EQEmu::constants::LongBuffs + constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } + + static inline int RoFToServerBuffSlot(int index) + { + // we're a disc + if (index >= constants::LongBuffs + constants::ShortBuffs) + return index - constants::LongBuffs - constants::ShortBuffs + EQEmu::constants::LongBuffs + + EQEmu::constants::ShortBuffs; + // we're a song + if (index >= constants::LongBuffs) + return index - constants::LongBuffs + EQEmu::constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } } /*RoF*/ diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index c19203d8a..d14008e93 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -66,6 +66,9 @@ namespace RoF2 static inline CastingSlot ServerToRoF2CastingSlot(EQEmu::CastingSlot slot); static inline EQEmu::CastingSlot RoF2ToServerCastingSlot(CastingSlot slot); + static inline int ServerToRoF2BuffSlot(int index); + static inline int RoF2ToServerBuffSlot(int index); + void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already @@ -492,18 +495,7 @@ namespace RoF2 OUT(buff.y); OUT(buff.x); OUT(buff.z); - uint16 buffslot = emu->slotid; - // Not sure if this is needs amending for RoF2 yet. - if (buffslot >= 25) - { - buffslot += 17; - } - // TODO: We should really just deal with these "server side" - // so we can have clients not limited to other clients. - // This fixes discs, songs were changed to 20 - if (buffslot == 54) - buffslot = 62; - eq->slotid = buffslot; + eq->slotid = ServerToRoF2BuffSlot(emu->slotid); // TODO: implement slot_data stuff if (emu->bufffade == 1) eq->bufffade = 1; @@ -519,10 +511,10 @@ namespace RoF2 outapp->WriteUInt32(0); // tic timer outapp->WriteUInt8(0); // Type of OP_BuffCreate packet ? outapp->WriteUInt16(1); // 1 buff in this packet - outapp->WriteUInt32(buffslot); + outapp->WriteUInt32(eq->slotid); outapp->WriteUInt32(0xffffffff); // SpellID (0xffff to remove) outapp->WriteUInt32(0); // Duration - outapp->WriteUInt32(0); // ? + outapp->WriteUInt32(0); // numhits outapp->WriteUInt8(0); // Caster name outapp->WriteUInt8(0); // Type } @@ -546,20 +538,9 @@ namespace RoF2 __packet->WriteUInt8(emu->all_buffs); // 1 indicates all buffs on the player (0 to add or remove a single buff) __packet->WriteUInt16(emu->count); - for (uint16 i = 0; i < emu->count; ++i) + for (int i = 0; i < emu->count; ++i) { - uint16 buffslot = emu->entries[i].buff_slot; - if (emu->type == 0) { // only correct for self packets - if (emu->entries[i].buff_slot >= 25) - buffslot += 17; - // TODO: We should really just deal with these "server side" - // so we can have clients not limited to other clients. - // This fixes discs, songs were changed to 20 - if (buffslot == 54) - buffslot = 62; - } - - __packet->WriteUInt32(buffslot); + __packet->WriteUInt32(emu->type == 0 ? ServerToRoF2BuffSlot(emu->entries[i].buff_slot) : emu->entries[i].buff_slot); __packet->WriteUInt32(emu->entries[i].spell_id); __packet->WriteUInt32(emu->entries[i].tics_remaining); __packet->WriteUInt32(emu->entries[i].num_hits); // Unknown @@ -4550,7 +4531,7 @@ namespace RoF2 IN(buff.unknown003); IN(buff.spellid); IN(buff.duration); - IN(slotid); + emu->slotid = RoF2ToServerBuffSlot(eq->slotid); IN(bufffade); FINISH_DIRECT_DECODE(); @@ -4563,7 +4544,7 @@ namespace RoF2 DECODE_LENGTH_EXACT(structs::BuffRemoveRequest_Struct); SETUP_DIRECT_DECODE(BuffRemoveRequest_Struct, structs::BuffRemoveRequest_Struct); - emu->SlotID = (eq->SlotID < 42) ? eq->SlotID : (eq->SlotID - 17); + emu->SlotID = RoF2ToServerBuffSlot(eq->SlotID); IN(EntityID); @@ -6388,4 +6369,32 @@ namespace RoF2 return EQEmu::CastingSlot::Discipline; } } + + // these should be optimized out for RoF2 since they should all boil down to return index :P + // but lets leave it here for future proofing + static inline int ServerToRoF2BuffSlot(int index) + { + // we're a disc + if (index >= EQEmu::constants::LongBuffs + EQEmu::constants::ShortBuffs) + return index - EQEmu::constants::LongBuffs - EQEmu::constants::ShortBuffs + + constants::LongBuffs + constants::ShortBuffs; + // we're a song + if (index >= EQEmu::constants::LongBuffs) + return index - EQEmu::constants::LongBuffs + constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } + + static inline int RoF2ToServerBuffSlot(int index) + { + // we're a disc + if (index >= constants::LongBuffs + constants::ShortBuffs) + return index - constants::LongBuffs - constants::ShortBuffs + EQEmu::constants::LongBuffs + + EQEmu::constants::ShortBuffs; + // we're a song + if (index >= constants::LongBuffs) + return index - constants::LongBuffs + EQEmu::constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } } /*RoF2*/ diff --git a/common/patches/rof2_limits.h b/common/patches/rof2_limits.h index fb2f997ca..6f4e649ff 100644 --- a/common/patches/rof2_limits.h +++ b/common/patches/rof2_limits.h @@ -277,6 +277,14 @@ namespace RoF2 const size_t SayLinkBodySize = 56; + const int LongBuffs = 42; + const int ShortBuffs = 20; + const int DiscBuffs = 1; + const int TotalBuffs = LongBuffs + ShortBuffs + DiscBuffs; + const int NPCBuffs = 97; + const int PetBuffs = NPCBuffs; + const int MercBuffs = LongBuffs; + } /*constants*/ namespace behavior { diff --git a/common/patches/rof_limits.h b/common/patches/rof_limits.h index ed0b9a6d0..952d14b20 100644 --- a/common/patches/rof_limits.h +++ b/common/patches/rof_limits.h @@ -268,6 +268,14 @@ namespace RoF const size_t SayLinkBodySize = 55; + const int LongBuffs = 42; + const int ShortBuffs = 20; + const int DiscBuffs = 1; + const int TotalBuffs = LongBuffs + ShortBuffs + DiscBuffs; + const int NPCBuffs = 97; + const int PetBuffs = NPCBuffs; + const int MercBuffs = LongBuffs; + } /*constants*/ namespace behavior { diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 330f7ee20..a3872e9c9 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -62,6 +62,9 @@ namespace SoD static inline CastingSlot ServerToSoDCastingSlot(EQEmu::CastingSlot slot); static inline EQEmu::CastingSlot SoDToServerCastingSlot(CastingSlot slot); + static inline int ServerToSoDBuffSlot(int index); + static inline int SoDToServerBuffSlot(int index); + void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already @@ -315,7 +318,7 @@ namespace SoD OUT(buff.duration); OUT(buff.counters); OUT(buff.player_id); - OUT(slotid); + eq->slotid = ServerToSoDBuffSlot(emu->slotid); OUT(bufffade); FINISH_ENCODE(); @@ -2921,8 +2924,8 @@ namespace SoD IN(buff.bard_modifier); IN(buff.spellid); IN(buff.duration); - IN(buff.counters) - IN(slotid); + IN(buff.counters); + emu->slotid = SoDToServerBuffSlot(eq->slotid); IN(bufffade); FINISH_DIRECT_DECODE(); @@ -4088,4 +4091,30 @@ namespace SoD return EQEmu::CastingSlot::Discipline; } } + + static inline int ServerToSoDBuffSlot(int index) + { + // we're a disc + if (index >= EQEmu::constants::LongBuffs + EQEmu::constants::ShortBuffs) + return index - EQEmu::constants::LongBuffs - EQEmu::constants::ShortBuffs + + constants::LongBuffs + constants::ShortBuffs; + // we're a song + if (index >= EQEmu::constants::LongBuffs) + return index - EQEmu::constants::LongBuffs + constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } + + static inline int SoDToServerBuffSlot(int index) + { + // we're a disc + if (index >= constants::LongBuffs + constants::ShortBuffs) + return index - constants::LongBuffs - constants::ShortBuffs + EQEmu::constants::LongBuffs + + EQEmu::constants::ShortBuffs; + // we're a song + if (index >= constants::LongBuffs) + return index - constants::LongBuffs + EQEmu::constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } } /*SoD*/ diff --git a/common/patches/sod_limits.h b/common/patches/sod_limits.h index fa2c29317..8f8031a3d 100644 --- a/common/patches/sod_limits.h +++ b/common/patches/sod_limits.h @@ -295,6 +295,14 @@ namespace SoD const size_t SayLinkBodySize = 50; + const int LongBuffs = 25; + const int ShortBuffs = 15; + const int DiscBuffs = 1; + const int TotalBuffs = LongBuffs + ShortBuffs + DiscBuffs; + const int NPCBuffs = 85; + const int PetBuffs = NPCBuffs; + const int MercBuffs = LongBuffs; + } /*constants*/ namespace behavior { diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 59e0edb5f..9009979ef 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -62,6 +62,9 @@ namespace SoF static inline CastingSlot ServerToSoFCastingSlot(EQEmu::CastingSlot slot); static inline EQEmu::CastingSlot SoFToServerCastingSlot(CastingSlot slot, uint32 itemlocation); + static inline int ServerToSoFBuffSlot(int index); + static inline int SoFToServerBuffSlot(int index); + void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already @@ -297,7 +300,7 @@ namespace SoF OUT(buff.duration); OUT(buff.counters); OUT(buff.player_id); - OUT(slotid); + eq->slotid = ServerToSoFBuffSlot(emu->slotid); OUT(bufffade); FINISH_ENCODE(); @@ -2375,7 +2378,7 @@ namespace SoF IN(buff.duration); IN(buff.counters); IN(buff.player_id); - IN(slotid); + emu->slotid = SoFToServerBuffSlot(eq->slotid); IN(bufffade); FINISH_DIRECT_DECODE(); @@ -3461,4 +3464,30 @@ namespace SoF return EQEmu::CastingSlot::Discipline; } } + + static inline int ServerToSoFBuffSlot(int index) + { + // we're a disc + if (index >= EQEmu::constants::LongBuffs + EQEmu::constants::ShortBuffs) + return index - EQEmu::constants::LongBuffs - EQEmu::constants::ShortBuffs + + constants::LongBuffs + constants::ShortBuffs; + // we're a song + if (index >= EQEmu::constants::LongBuffs) + return index - EQEmu::constants::LongBuffs + constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } + + static inline int SoFToServerBuffSlot(int index) + { + // we're a disc + if (index >= constants::LongBuffs + constants::ShortBuffs) + return index - constants::LongBuffs - constants::ShortBuffs + EQEmu::constants::LongBuffs + + EQEmu::constants::ShortBuffs; + // we're a song + if (index >= constants::LongBuffs) + return index - constants::LongBuffs + EQEmu::constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } } /*SoF*/ diff --git a/common/patches/sof_limits.h b/common/patches/sof_limits.h index 575df39ba..d34197a90 100644 --- a/common/patches/sof_limits.h +++ b/common/patches/sof_limits.h @@ -295,6 +295,14 @@ namespace SoF const size_t SayLinkBodySize = 50; + const int LongBuffs = 25; + const int ShortBuffs = 15; + const int DiscBuffs = 1; + const int TotalBuffs = LongBuffs + ShortBuffs + DiscBuffs; + const int NPCBuffs = 60; + const int PetBuffs = 30; + const int MercBuffs = 0; + } /*constants*/ namespace behavior { diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 286d09d1b..1c7033186 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -61,6 +61,9 @@ namespace Titanium static inline CastingSlot ServerToTitaniumCastingSlot(EQEmu::CastingSlot slot); static inline EQEmu::CastingSlot TitaniumToServerCastingSlot(CastingSlot slot, uint32 itemlocation); + static inline int ServerToTitaniumBuffSlot(int index); + static inline int TitaniumToServerBuffSlot(int index); + void Register(EQStreamIdentifier &into) { auto Config = EQEmuConfig::get(); @@ -270,7 +273,7 @@ namespace Titanium OUT(buff.duration); OUT(buff.counters); OUT(buff.player_id); - OUT(slotid); + eq->slotid = ServerToTitaniumBuffSlot(emu->slotid); OUT(bufffade); FINISH_ENCODE(); @@ -1779,7 +1782,7 @@ namespace Titanium IN(buff.duration); IN(buff.counters); IN(buff.player_id); - IN(slotid); + emu->slotid = TitaniumToServerBuffSlot(eq->slotid); IN(bufffade); FINISH_DIRECT_DECODE(); @@ -2632,4 +2635,30 @@ namespace Titanium return EQEmu::CastingSlot::Discipline; } } + + static inline int ServerToTitaniumBuffSlot(int index) + { + // we're a disc + if (index >= EQEmu::constants::LongBuffs + EQEmu::constants::ShortBuffs) + return index - EQEmu::constants::LongBuffs - EQEmu::constants::ShortBuffs + + constants::LongBuffs + constants::ShortBuffs; + // we're a song + if (index >= EQEmu::constants::LongBuffs) + return index - EQEmu::constants::LongBuffs + constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } + + static inline int TitaniumToServerBuffSlot(int index) + { + // we're a disc + if (index >= constants::LongBuffs + constants::ShortBuffs) + return index - constants::LongBuffs - constants::ShortBuffs + EQEmu::constants::LongBuffs + + EQEmu::constants::ShortBuffs; + // we're a song + if (index >= constants::LongBuffs) + return index - constants::LongBuffs + EQEmu::constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } } /*Titanium*/ diff --git a/common/patches/titanium_limits.h b/common/patches/titanium_limits.h index e631f8492..3266ade6f 100644 --- a/common/patches/titanium_limits.h +++ b/common/patches/titanium_limits.h @@ -294,6 +294,14 @@ namespace Titanium const size_t SayLinkBodySize = 45; + const int LongBuffs = 25; + const int ShortBuffs = 12; + const int DiscBuffs = 1; + const int TotalBuffs = LongBuffs + ShortBuffs + DiscBuffs; + const int NPCBuffs = 60; + const int PetBuffs = 30; + const int MercBuffs = 0; + } /*constants*/ namespace behavior { diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 92be237b1..061444bea 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -62,6 +62,9 @@ namespace UF static inline CastingSlot ServerToUFCastingSlot(EQEmu::CastingSlot slot); static inline EQEmu::CastingSlot UFToServerCastingSlot(CastingSlot slot); + static inline int ServerToUFBuffSlot(int index); + static inline int UFToServerBuffSlot(int index); + void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already @@ -377,17 +380,8 @@ namespace UF OUT(buff.spellid); OUT(buff.duration); OUT(buff.num_hits); - uint16 buffslot = emu->slotid; - if (buffslot >= 25 && buffslot < 37) - { - buffslot += 5; - } - else if (buffslot >= 37) - { - buffslot += 14; - } // TODO: implement slot_data stuff - eq->slotid = buffslot; + eq->slotid = ServerToUFBuffSlot(emu->slotid); OUT(bufffade); // Live (October 2011) sends a 2 rather than 0 when a buff is created, but it doesn't seem to matter. FINISH_ENCODE(); @@ -407,17 +401,9 @@ namespace UF __packet->WriteUInt8(emu->all_buffs); // 1 = all buffs, 0 = 1 buff __packet->WriteUInt16(emu->count); - for (uint16 i = 0; i < emu->count; ++i) + for (int i = 0; i < emu->count; ++i) { - uint16 buffslot = emu->entries[i].buff_slot; - if (emu->type == 0) { // only correct for self packets - if (emu->entries[i].buff_slot >= 25 && emu->entries[i].buff_slot < 37) - buffslot += 5; - else if (emu->entries[i].buff_slot >= 37) - buffslot += 14; - } - - __packet->WriteUInt32(buffslot); + __packet->WriteUInt32(emu->type == 0 ? ServerToUFBuffSlot(emu->entries[i].buff_slot) : emu->entries[i].buff_slot); __packet->WriteUInt32(emu->entries[i].spell_id); __packet->WriteUInt32(emu->entries[i].tics_remaining); __packet->WriteUInt32(emu->entries[i].num_hits); @@ -3236,6 +3222,7 @@ namespace UF IN(buff.unknown003); IN(buff.spellid); IN(buff.duration); + emu->slotid = UFToServerBuffSlot(eq->slotid); IN(slotid); IN(bufffade); @@ -3249,7 +3236,7 @@ namespace UF DECODE_LENGTH_EXACT(structs::BuffRemoveRequest_Struct); SETUP_DIRECT_DECODE(BuffRemoveRequest_Struct, structs::BuffRemoveRequest_Struct); - emu->SlotID = (eq->SlotID < 30) ? eq->SlotID : (eq->SlotID - 5); + emu->SlotID = UFToServerBuffSlot(eq->SlotID); IN(EntityID); @@ -4453,4 +4440,30 @@ namespace UF return EQEmu::CastingSlot::Discipline; } } + + static inline int ServerToUFBuffSlot(int index) + { + // we're a disc + if (index >= EQEmu::constants::LongBuffs + EQEmu::constants::ShortBuffs) + return index - EQEmu::constants::LongBuffs - EQEmu::constants::ShortBuffs + + constants::LongBuffs + constants::ShortBuffs; + // we're a song + if (index >= EQEmu::constants::LongBuffs) + return index - EQEmu::constants::LongBuffs + constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } + + static inline int UFToServerBuffSlot(int index) + { + // we're a disc + if (index >= constants::LongBuffs + constants::ShortBuffs) + return index - constants::LongBuffs - constants::ShortBuffs + EQEmu::constants::LongBuffs + + EQEmu::constants::ShortBuffs; + // we're a song + if (index >= constants::LongBuffs) + return index - constants::LongBuffs + EQEmu::constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } } /*UF*/ diff --git a/common/patches/uf_limits.h b/common/patches/uf_limits.h index 2e799ac0c..719fcc394 100644 --- a/common/patches/uf_limits.h +++ b/common/patches/uf_limits.h @@ -64,7 +64,7 @@ namespace UF InvTypeOther, InvTypeCount }; - + } /*invtype*/ namespace invslot { @@ -115,21 +115,21 @@ namespace UF const int GeneralBegin = PossessionsGeneral1; const int GeneralEnd = PossessionsGeneral8; const int GeneralCount = (GeneralEnd - GeneralBegin + 1); - + } /*invslot*/ namespace invbag { inline EQEmu::versions::ClientVersion GetInvBagRef() { return EQEmu::versions::ClientVersion::UF; } enum : int { InvBagInvalid = -1, InvBagBegin }; - + } /*invbag*/ namespace invaug { inline EQEmu::versions::ClientVersion GetInvAugRef() { return EQEmu::versions::ClientVersion::UF; } enum : int { InvAugInvalid = -1, InvAugBegin }; - + } /*invaug*/ namespace item { @@ -148,27 +148,27 @@ namespace UF ItemPacketCharmUpdate = 110, ItemPacket11 = 111 }; - + } /*item*/ namespace profile { inline EQEmu::versions::ClientVersion GetProfileRef() { return EQEmu::versions::ClientVersion::UF; } - + } /*profile*/ namespace constants { inline EQEmu::versions::ClientVersion GetConstantsRef() { return EQEmu::versions::ClientVersion::UF; } - + } /*constants*/ namespace behavior { inline EQEmu::versions::ClientVersion GetBehaviorRef() { return EQEmu::versions::ClientVersion::UF; } - + } /*behavior*/ namespace skills { inline EQEmu::versions::ClientVersion GetSkillsRef() { return EQEmu::versions::ClientVersion::UF; } - + } /*skills*/ @@ -208,7 +208,7 @@ namespace UF extern const char* GetInvTypeName(int inv_type); extern bool IsInvTypePersistent(int inv_type); - + } /*invtype*/ namespace invslot { @@ -237,7 +237,7 @@ namespace UF extern const char* GetInvPossessionsSlotName(int inv_slot); extern const char* GetInvCorpseSlotName(int inv_slot); extern const char* GetInvSlotName(int inv_type, int inv_slot); - + } /*invslot*/ namespace invbag { @@ -264,7 +264,7 @@ namespace UF const int TradeBagsEnd = (TradeBagsBegin + TradeBagsSize) - 1; extern const char* GetInvBagIndexName(int bag_index); - + } /*invbag*/ namespace invaug { @@ -288,24 +288,32 @@ namespace UF const size_t PotionBeltSize = 5; const size_t SkillArraySize = 100; - + } /*profile*/ namespace constants { const size_t CharacterCreationLimit = 12; const size_t SayLinkBodySize = 50; - + + const int LongBuffs = 30; + const int ShortBuffs = 20; + const int DiscBuffs = 1; + const int TotalBuffs = LongBuffs + ShortBuffs + DiscBuffs; + const int NPCBuffs = 85; + const int PetBuffs = NPCBuffs; + const int MercBuffs = LongBuffs; + } /*constants*/ namespace behavior { const bool CoinHasWeight = false; - + } /*behavior*/ namespace skills { const size_t LastUsableSkill = EQEmu::skills::SkillTripleAttack; - + } /*skills*/ }; /*UF*/ diff --git a/common/ruletypes.h b/common/ruletypes.h index 0f424072d..9a18ff063 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -333,11 +333,11 @@ RULE_INT(Spells, SacrificeMinLevel, 46) //first level Sacrifice will work on RULE_INT(Spells, SacrificeMaxLevel, 69) //last level Sacrifice will work on RULE_INT(Spells, SacrificeItemID, 9963) //Item ID of the item Sacrifice will return (defaults to an EE) RULE_BOOL(Spells, EnableSpellGlobals, false) // If Enabled, spells check the spell_globals table and compare character data from the quest globals before allowing that spell to scribe with scribespells -RULE_INT(Spells, MaxBuffSlotsNPC, 25) -RULE_INT(Spells, MaxSongSlotsNPC, 10) -RULE_INT(Spells, MaxDiscSlotsNPC, 1) -RULE_INT(Spells, MaxTotalSlotsNPC, 36) -RULE_INT(Spells, MaxTotalSlotsPET, 30) // do not set this higher than 25 until the player profile is removed from the blob +RULE_INT(Spells, MaxBuffSlotsNPC, 60) // default to Tit's limit +RULE_INT(Spells, MaxSongSlotsNPC, 0) // NPCs don't have songs ... +RULE_INT(Spells, MaxDiscSlotsNPC, 0) // NPCs don't have discs ... +RULE_INT(Spells, MaxTotalSlotsNPC, 60) // default to Tit's limit +RULE_INT(Spells, MaxTotalSlotsPET, 30) // default to Tit's limit RULE_BOOL (Spells, EnableBlockedBuffs, true) RULE_INT(Spells, ReflectType, 1) //0 = disabled, 1 = single target player spells only, 2 = all player spells, 3 = all single target spells, 4 = all spells RULE_INT(Spells, VirusSpreadDistance, 30) // The distance a viral spell will jump to its next victim diff --git a/zone/client.h b/zone/client.h index c7973de18..5b2c0a939 100644 --- a/zone/client.h +++ b/zone/client.h @@ -509,10 +509,10 @@ public: virtual int GetCurrentBuffSlots() const; virtual int GetCurrentSongSlots() const; virtual int GetCurrentDiscSlots() const { return 1; } - virtual int GetMaxBuffSlots() const { return 25; } - virtual int GetMaxSongSlots() const { return 12; } - virtual int GetMaxDiscSlots() const { return 1; } - virtual int GetMaxTotalSlots() const { return 38; } + virtual int GetMaxBuffSlots() const { return EQEmu::constants::LongBuffs; } + virtual int GetMaxSongSlots() const { return EQEmu::constants::ShortBuffs; } + virtual int GetMaxDiscSlots() const { return EQEmu::constants::DiscBuffs; } + virtual int GetMaxTotalSlots() const { return EQEmu::constants::TotalBuffs; } virtual uint32 GetFirstBuffSlot(bool disc, bool song); virtual uint32 GetLastBuffSlot(bool disc, bool song); virtual void InitializeBuffSlots(); diff --git a/zone/spells.cpp b/zone/spells.cpp index 6b875c96f..3b232f9cd 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5534,12 +5534,12 @@ int Client::GetCurrentBuffSlots() const numbuffs++; if (GetLevel() > 74) numbuffs++; - return EQEmu::ClampUpper(numbuffs, GetMaxBuffSlots()); + return EQEmu::ClampUpper(numbuffs, EQEmu::constants::Lookup(m_ClientVersion)->LongBuffs); } int Client::GetCurrentSongSlots() const { - return 12; // AAs dont affect this + return EQEmu::constants::Lookup(m_ClientVersion)->ShortBuffs; // AAs dont affect this } void Client::InitializeBuffSlots() diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 8bf2e4d31..c4fcfc55f 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -3122,7 +3122,8 @@ void ZoneDatabase::LoadBuffs(Client *client) buffs[slot_id].instrument_mod = instrument_mod; } - max_slots = client->GetMaxBuffSlots(); + // We load up to the most our client supports + max_slots = EQEmu::constants::Lookup(client->ClientVersion())->LongBuffs; for (int index = 0; index < max_slots; ++index) { if (!IsValidSpell(buffs[index].spellid)) continue;