mirror of
https://github.com/EQEmu/Server.git
synced 2026-01-20 15:03:52 +00:00
commit
8be23a1214
@ -1,6 +1,59 @@
|
||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||
-------------------------------------------------------
|
||||
|
||||
== 1/26/2019 ==
|
||||
Uleat: Fix for class Bot not honoring NPCType data reference
|
||||
- Fixes bots not moving on spawn/grouping issue
|
||||
- Report any issues with non movement-related behavior
|
||||
|
||||
== 1/24/2019 ==
|
||||
Uleat: Extended server spellbook entries to RoF2 standard and added per-client restriction of spell id max
|
||||
- Bumped server spellbook entry capacity to 720 spells
|
||||
- Server keeps all 'learned' spells as found
|
||||
-- Access is limited by the clients' limitations of spellbook capacities and max spell ids
|
||||
-- This is done to avoid losing spells by switching from newer clients to older ones
|
||||
-- Existing behavior is kept in place for illegal access conditions
|
||||
- Each client is still restricted to its spellbook capacity (400, 480, 480, 720, 720, 720 - respectively)
|
||||
- Each client is restricted to its max supported spell id (9999, 15999, 23000, 28000, 45000, 45000 - respectively)
|
||||
- Please report any abnormal behavior so it may be addressed
|
||||
Uleat: Removed server-side checksum of player profile..wasted calculation since it's performed again in all translators
|
||||
|
||||
== 1/20/2019 ==
|
||||
Uleat: Added 'spells' entry to EQDictionary
|
||||
Akkadius:
|
||||
- [Command] Extended #goto via #goto <player_name> -
|
||||
- This will work cross zone, cross instance, in zone etc.
|
||||
- It works on top of the original #goto (target) and #goto x y z
|
||||
- [Command] Implemented server side #who Example: https://bit.ly/2TZ2hvI
|
||||
- Searches can be filtered by
|
||||
- Account Name
|
||||
- Base Class Name
|
||||
- Guild Name
|
||||
- IP
|
||||
- Player Name
|
||||
- Race Name
|
||||
- Zone Short Name
|
||||
- Features a clickable (Goto) saylink that will bring you directly to a player regardless of
|
||||
whether or not they are in an instance
|
||||
- [Command] Implemented: #gmzone [zone_short_name] [zone_version=0] [identifier=gmzone]
|
||||
- Zones to a private GM instance
|
||||
- Example: https://i.imgur.com/qswdrzO.gif
|
||||
- [NPC] Fix issue where NPC's clip into the world and the client interprets them at 0,0,0
|
||||
- This issue would show itself when NPC's would bunch up by a zone-in
|
||||
|
||||
== 1/15/2019 ==
|
||||
Uleat: Activated per-expansion support for active inventory slot addressing
|
||||
- Server honors expansions that alter bank size and power source, general9 and general10 slots
|
||||
- Server honors gm flag behaviors for the active inventory slots of each client
|
||||
|
||||
== 1/11/2019 ==
|
||||
Uleat: Modified rules system to ignore all runtime modifications of 'World:ExpansionSettings' and 'World:UseClientBasedExpansionSettings' fields.
|
||||
- These fields are no longer allowed to be changed during server runtime through the command system
|
||||
- Major syncronization issues between server and clients result when these fields are altered in-game
|
||||
- It is not recommended to update these fields via sql queries while the server is in operation
|
||||
- Failure to observe these warnings will result in abhorant behavior and loss of items
|
||||
- Modify these fields during server operation at your own risk!
|
||||
|
||||
== 1/4/2019 ==
|
||||
Akkadius: [Scaling] Global base scaling data has been updated in new database binary revision
|
||||
|
||||
|
||||
1052
common/classes.cpp
1052
common/classes.cpp
File diff suppressed because it is too large
Load Diff
@ -217,7 +217,7 @@ namespace Convert {
|
||||
/*0245*/ uint8 guildbanker;
|
||||
/*0246*/ uint8 unknown0246[6]; //
|
||||
/*0252*/ uint32 intoxication;
|
||||
/*0256*/ uint32 spellSlotRefresh[MAX_PP_REF_MEMSPELL]; //in ms
|
||||
/*0256*/ uint32 spellSlotRefresh[9]; //in ms
|
||||
/*0292*/ uint32 abilitySlotRefresh;
|
||||
/*0296*/ uint8 haircolor; // Player hair color
|
||||
/*0297*/ uint8 beardcolor; // Player beard color
|
||||
@ -256,9 +256,9 @@ namespace Convert {
|
||||
/*2505*/ uint8 unknown2541[47]; // ?
|
||||
/*2552*/ uint8 languages[MAX_PP_LANGUAGE];
|
||||
/*2580*/ uint8 unknown2616[4];
|
||||
/*2584*/ uint32 spell_book[MAX_PP_REF_SPELLBOOK];
|
||||
/*2584*/ uint32 spell_book[480];
|
||||
/*4504*/ uint8 unknown4540[128]; // Was [428] all 0xff
|
||||
/*4632*/ uint32 mem_spells[MAX_PP_REF_MEMSPELL];
|
||||
/*4632*/ uint32 mem_spells[9];
|
||||
/*4668*/ uint8 unknown4704[32]; //
|
||||
/*4700*/ float y; // Player y position
|
||||
/*4704*/ float x; // Player x position
|
||||
@ -1360,7 +1360,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
/* Run Spell Convert */
|
||||
first_entry = 0; rquery = "";
|
||||
for (i = 0; i < MAX_PP_REF_SPELLBOOK; i++){
|
||||
for (i = 0; i < 480; i++){
|
||||
if (pp->spell_book[i] > 0 && pp->spell_book[i] != 4294967295 && pp->spell_book[i] < 40000 && pp->spell_book[i] != 1){
|
||||
if (first_entry != 1){
|
||||
rquery = StringFormat("REPLACE INTO `character_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->spell_book[i]);
|
||||
@ -1372,7 +1372,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
/* Run Max Memmed Spell Convert */
|
||||
first_entry = 0; rquery = "";
|
||||
for (i = 0; i < MAX_PP_REF_MEMSPELL; i++){
|
||||
for (i = 0; i < 9; i++){
|
||||
if (pp->mem_spells[i] > 0 && pp->mem_spells[i] != 65535 && pp->mem_spells[i] != 4294967295){
|
||||
if (first_entry != 1){
|
||||
rquery = StringFormat("REPLACE INTO `character_memmed_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->mem_spells[i]);
|
||||
|
||||
@ -38,16 +38,23 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @param instance_id
|
||||
* @param char_id
|
||||
* @return
|
||||
*/
|
||||
bool Database::AddClientToInstance(uint16 instance_id, uint32 char_id)
|
||||
{
|
||||
std::string query = StringFormat(
|
||||
"REPLACE INTO `instance_list_player` (id, charid) "
|
||||
"VALUES "
|
||||
"(%lu, %lu)",
|
||||
(unsigned long)instance_id,
|
||||
(unsigned long)char_id
|
||||
);
|
||||
(unsigned long) instance_id,
|
||||
(unsigned long) char_id
|
||||
);
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
return results.Success();
|
||||
}
|
||||
|
||||
|
||||
@ -131,6 +131,9 @@ namespace EQEmu
|
||||
const int16 CORPSE_BEGIN = invslot::slotGeneral1;
|
||||
const int16 CORPSE_END = CORPSE_BEGIN + invslot::slotCursor;
|
||||
|
||||
using RoF2::invslot::EQUIPMENT_BITMASK;
|
||||
using RoF2::invslot::GENERAL_BITMASK;
|
||||
using RoF2::invslot::CURSOR_BITMASK;
|
||||
using RoF2::invslot::POSSESSIONS_BITMASK;
|
||||
using RoF2::invslot::CORPSE_BITMASK;
|
||||
|
||||
@ -188,6 +191,7 @@ namespace EQEmu
|
||||
namespace constants {
|
||||
const EQEmu::versions::ClientVersion CHARACTER_CREATION_CLIENT = EQEmu::versions::ClientVersion::Titanium;
|
||||
|
||||
using RoF2::constants::EXPANSION;
|
||||
using RoF2::constants::EXPANSION_BIT;
|
||||
using RoF2::constants::EXPANSIONS_MASK;
|
||||
|
||||
@ -199,14 +203,6 @@ namespace EQEmu
|
||||
const size_t SAY_LINK_CLOSER_SIZE = 1;
|
||||
const size_t SAY_LINK_MAXIMUM_SIZE = (SAY_LINK_OPENER_SIZE + SAY_LINK_BODY_SIZE + SAY_LINK_TEXT_SIZE + SAY_LINK_CLOSER_SIZE);
|
||||
|
||||
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*/
|
||||
|
||||
namespace profile {
|
||||
@ -224,6 +220,42 @@ namespace EQEmu
|
||||
|
||||
} // namespace behavior
|
||||
|
||||
namespace spells {
|
||||
enum class CastingSlot : uint32 { // hybrid declaration
|
||||
Gem1 = 0,
|
||||
Gem2 = 1,
|
||||
Gem3 = 2,
|
||||
Gem4 = 3,
|
||||
Gem5 = 4,
|
||||
Gem6 = 5,
|
||||
Gem7 = 6,
|
||||
Gem8 = 7,
|
||||
Gem9 = 8,
|
||||
Gem10 = 9,
|
||||
Gem11 = 10,
|
||||
Gem12 = 11,
|
||||
MaxGems = 12,
|
||||
Ability = 20, // HT/LoH for Tit
|
||||
PotionBelt = 21, // Tit uses a different slot for PB
|
||||
Item = 22,
|
||||
Discipline = 23,
|
||||
AltAbility = 0xFF
|
||||
};
|
||||
|
||||
using RoF2::spells::SPELL_ID_MAX;
|
||||
using RoF2::spells::SPELLBOOK_SIZE;
|
||||
using UF::spells::SPELL_GEM_COUNT; // RoF+ clients define more than UF client..but, they are not valid beyond UF
|
||||
|
||||
using RoF2::spells::LONG_BUFFS;
|
||||
using RoF2::spells::SHORT_BUFFS;
|
||||
using RoF2::spells::DISC_BUFFS;
|
||||
using RoF2::spells::TOTAL_BUFFS;
|
||||
using RoF2::spells::NPC_BUFFS;
|
||||
using RoF2::spells::PET_BUFFS;
|
||||
using RoF2::spells::MERC_BUFFS;
|
||||
|
||||
} // namespace spells
|
||||
|
||||
namespace bug {
|
||||
enum CategoryID : uint32 {
|
||||
catOther = 0,
|
||||
@ -255,27 +287,6 @@ namespace EQEmu
|
||||
|
||||
} // namespace bug
|
||||
|
||||
enum class CastingSlot : uint32 {
|
||||
Gem1 = 0,
|
||||
Gem2 = 1,
|
||||
Gem3 = 2,
|
||||
Gem4 = 3,
|
||||
Gem5 = 4,
|
||||
Gem6 = 5,
|
||||
Gem7 = 6,
|
||||
Gem8 = 7,
|
||||
Gem9 = 8,
|
||||
Gem10 = 9,
|
||||
Gem11 = 10,
|
||||
Gem12 = 11,
|
||||
MaxGems = 12,
|
||||
Ability = 20, // HT/LoH for Tit
|
||||
PotionBelt = 21, // Tit uses a different slot for PB
|
||||
Item = 22,
|
||||
Discipline = 23,
|
||||
AltAbility = 0xFF
|
||||
};
|
||||
|
||||
} /*EQEmu*/
|
||||
|
||||
#endif /*COMMON_EMU_CONSTANTS_H*/
|
||||
|
||||
@ -70,7 +70,10 @@ namespace EntityLimits
|
||||
} // namespace invtype
|
||||
|
||||
namespace invslot {
|
||||
const uint64 POSSESSIONS_BITMASK = 0x00000000007FFFFF; // based on 34-slot count (RoF+)
|
||||
const uint64 EQUIPMENT_BITMASK = 0x00000000007FFFFF;
|
||||
const uint64 GENERAL_BITMASK = 0x0000000000000000;
|
||||
const uint64 CURSOR_BITMASK = 0x0000000000000000;
|
||||
const uint64 POSSESSIONS_BITMASK = (EQUIPMENT_BITMASK | GENERAL_BITMASK | CURSOR_BITMASK); // based on 34-slot count (RoF+)
|
||||
|
||||
} // namespace invslot
|
||||
|
||||
|
||||
@ -342,56 +342,224 @@ EQEmu::versions::MobVersion EQEmu::versions::ConvertClientVersionToOfflinePCMobV
|
||||
}
|
||||
}
|
||||
|
||||
const char* EQEmu::expansions::ExpansionName(uint32 expansion_bit)
|
||||
const char* EQEmu::expansions::ExpansionName(Expansion expansion)
|
||||
{
|
||||
switch (expansion_bit) {
|
||||
case expansions::bitEverQuest:
|
||||
switch (expansion) {
|
||||
case Expansion::EverQuest:
|
||||
return "EverQuest";
|
||||
case expansions::bitRoK:
|
||||
case Expansion::RoK:
|
||||
return "The Ruins of Kunark";
|
||||
case expansions::bitSoV:
|
||||
case Expansion::SoV:
|
||||
return "The Scars of Velious";
|
||||
case expansions::bitSoL:
|
||||
case Expansion::SoL:
|
||||
return "The Shadows of Luclin";
|
||||
case expansions::bitPoP:
|
||||
case Expansion::PoP:
|
||||
return "The Planes of Power";
|
||||
case expansions::bitLoY:
|
||||
case Expansion::LoY:
|
||||
return "The Legacy of Ykesha";
|
||||
case expansions::bitLDoN:
|
||||
case Expansion::LDoN:
|
||||
return "Lost Dungeons of Norrath";
|
||||
case expansions::bitGoD:
|
||||
case Expansion::GoD:
|
||||
return "Gates of Discord";
|
||||
case expansions::bitOoW:
|
||||
case Expansion::OoW:
|
||||
return "Omens of War";
|
||||
case expansions::bitDoN:
|
||||
case Expansion::DoN:
|
||||
return "Dragons of Norrath";
|
||||
case expansions::bitDoD:
|
||||
case Expansion::DoD:
|
||||
return "Depths of Darkhollow";
|
||||
case expansions::bitPoR:
|
||||
case Expansion::PoR:
|
||||
return "Prophecy of Ro";
|
||||
case expansions::bitTSS:
|
||||
case Expansion::TSS:
|
||||
return "The Serpent's Spine";
|
||||
case expansions::bitTBS:
|
||||
case Expansion::TBS:
|
||||
return "The Buried Sea";
|
||||
case expansions::bitSoF:
|
||||
case Expansion::SoF:
|
||||
return "Secrets of Faydwer";
|
||||
case expansions::bitSoD:
|
||||
case Expansion::SoD:
|
||||
return "Seeds of Destruction";
|
||||
case expansions::bitUF:
|
||||
case Expansion::UF:
|
||||
return "Underfoot";
|
||||
case expansions::bitHoT:
|
||||
case Expansion::HoT:
|
||||
return "House of Thule";
|
||||
case expansions::bitVoA:
|
||||
case Expansion::VoA:
|
||||
return "Veil of Alaris";
|
||||
case expansions::bitRoF:
|
||||
case Expansion::RoF:
|
||||
return "Rain of Fear";
|
||||
case expansions::bitCotF:
|
||||
case Expansion::CotF:
|
||||
return "Call of the Forsaken";
|
||||
default:
|
||||
return "Invalid Expansion";
|
||||
}
|
||||
}
|
||||
|
||||
const char* EQEmu::expansions::ExpansionName(uint32 expansion_bit)
|
||||
{
|
||||
return ExpansionName(ConvertExpansionBitToExpansion(expansion_bit));
|
||||
}
|
||||
|
||||
uint32 EQEmu::expansions::ConvertExpansionToExpansionBit(Expansion expansion)
|
||||
{
|
||||
switch (expansion) {
|
||||
case Expansion::RoK:
|
||||
return bitRoK;
|
||||
case Expansion::SoV:
|
||||
return bitSoV;
|
||||
case Expansion::SoL:
|
||||
return bitSoL;
|
||||
case Expansion::PoP:
|
||||
return bitPoP;
|
||||
case Expansion::LoY:
|
||||
return bitLoY;
|
||||
case Expansion::LDoN:
|
||||
return bitLDoN;
|
||||
case Expansion::GoD:
|
||||
return bitGoD;
|
||||
case Expansion::OoW:
|
||||
return bitOoW;
|
||||
case Expansion::DoN:
|
||||
return bitDoN;
|
||||
case Expansion::DoD:
|
||||
return bitDoD;
|
||||
case Expansion::PoR:
|
||||
return bitPoR;
|
||||
case Expansion::TSS:
|
||||
return bitTSS;
|
||||
case Expansion::TBS:
|
||||
return bitTBS;
|
||||
case Expansion::SoF:
|
||||
return bitSoF;
|
||||
case Expansion::SoD:
|
||||
return bitSoD;
|
||||
case Expansion::UF:
|
||||
return bitUF;
|
||||
case Expansion::HoT:
|
||||
return bitHoT;
|
||||
case Expansion::VoA:
|
||||
return bitVoA;
|
||||
case Expansion::RoF:
|
||||
return bitRoF;
|
||||
case Expansion::CotF:
|
||||
return bitCotF;
|
||||
default:
|
||||
return bitEverQuest;
|
||||
}
|
||||
}
|
||||
|
||||
EQEmu::expansions::Expansion EQEmu::expansions::ConvertExpansionBitToExpansion(uint32 expansion_bit)
|
||||
{
|
||||
switch (expansion_bit) {
|
||||
case bitRoK:
|
||||
return Expansion::RoK;
|
||||
case bitSoV:
|
||||
return Expansion::SoV;
|
||||
case bitSoL:
|
||||
return Expansion::SoL;
|
||||
case bitPoP:
|
||||
return Expansion::PoP;
|
||||
case bitLoY:
|
||||
return Expansion::LoY;
|
||||
case bitLDoN:
|
||||
return Expansion::LDoN;
|
||||
case bitGoD:
|
||||
return Expansion::GoD;
|
||||
case bitOoW:
|
||||
return Expansion::OoW;
|
||||
case bitDoN:
|
||||
return Expansion::DoN;
|
||||
case bitDoD:
|
||||
return Expansion::DoD;
|
||||
case bitPoR:
|
||||
return Expansion::PoR;
|
||||
case bitTSS:
|
||||
return Expansion::TSS;
|
||||
case bitTBS:
|
||||
return Expansion::TBS;
|
||||
case bitSoF:
|
||||
return Expansion::SoF;
|
||||
case bitSoD:
|
||||
return Expansion::SoD;
|
||||
case bitUF:
|
||||
return Expansion::UF;
|
||||
case bitHoT:
|
||||
return Expansion::HoT;
|
||||
case bitVoA:
|
||||
return Expansion::VoA;
|
||||
case bitRoF:
|
||||
return Expansion::RoF;
|
||||
case bitCotF:
|
||||
return Expansion::CotF;
|
||||
default:
|
||||
return Expansion::EverQuest;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 EQEmu::expansions::ConvertExpansionToExpansionMask(Expansion expansion)
|
||||
{
|
||||
switch (expansion) {
|
||||
case Expansion::RoK:
|
||||
return maskRoK;
|
||||
case Expansion::SoV:
|
||||
return maskSoV;
|
||||
case Expansion::SoL:
|
||||
return maskSoL;
|
||||
case Expansion::PoP:
|
||||
return maskPoP;
|
||||
case Expansion::LoY:
|
||||
return maskLoY;
|
||||
case Expansion::LDoN:
|
||||
return maskLDoN;
|
||||
case Expansion::GoD:
|
||||
return maskGoD;
|
||||
case Expansion::OoW:
|
||||
return maskOoW;
|
||||
case Expansion::DoN:
|
||||
return maskDoN;
|
||||
case Expansion::DoD:
|
||||
return maskDoD;
|
||||
case Expansion::PoR:
|
||||
return maskPoR;
|
||||
case Expansion::TSS:
|
||||
return maskTSS;
|
||||
case Expansion::TBS:
|
||||
return maskTBS;
|
||||
case Expansion::SoF:
|
||||
return maskSoF;
|
||||
case Expansion::SoD:
|
||||
return maskSoD;
|
||||
case Expansion::UF:
|
||||
return maskUF;
|
||||
case Expansion::HoT:
|
||||
return maskHoT;
|
||||
case Expansion::VoA:
|
||||
return maskVoA;
|
||||
case Expansion::RoF:
|
||||
return maskRoF;
|
||||
case Expansion::CotF:
|
||||
return maskCotF;
|
||||
default:
|
||||
return maskEverQuest;
|
||||
}
|
||||
}
|
||||
|
||||
EQEmu::expansions::Expansion EQEmu::expansions::ConvertClientVersionToExpansion(versions::ClientVersion client_version)
|
||||
{
|
||||
switch (client_version) {
|
||||
case versions::ClientVersion::Titanium:
|
||||
return expansions::Expansion::PoR;
|
||||
case versions::ClientVersion::SoF:
|
||||
return expansions::Expansion::SoF;
|
||||
case versions::ClientVersion::SoD:
|
||||
return expansions::Expansion::SoD;
|
||||
case versions::ClientVersion::UF:
|
||||
return expansions::Expansion::UF;
|
||||
case versions::ClientVersion::RoF:
|
||||
case versions::ClientVersion::RoF2:
|
||||
return expansions::Expansion::RoF;
|
||||
default:
|
||||
return expansions::Expansion::EverQuest;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 EQEmu::expansions::ConvertClientVersionToExpansionBit(versions::ClientVersion client_version)
|
||||
{
|
||||
switch (client_version) {
|
||||
|
||||
@ -137,6 +137,30 @@ namespace EQEmu
|
||||
} /*versions*/
|
||||
|
||||
namespace expansions {
|
||||
enum class Expansion : uint32 {
|
||||
EverQuest = 0,
|
||||
RoK,
|
||||
SoV,
|
||||
SoL,
|
||||
PoP,
|
||||
LoY,
|
||||
LDoN,
|
||||
GoD,
|
||||
OoW,
|
||||
DoN,
|
||||
DoD,
|
||||
PoR,
|
||||
TSS,
|
||||
TBS,
|
||||
SoF,
|
||||
SoD,
|
||||
UF,
|
||||
HoT,
|
||||
VoA,
|
||||
RoF,
|
||||
CotF
|
||||
};
|
||||
|
||||
enum ExpansionBitmask : uint32 {
|
||||
bitEverQuest = 0x00000000,
|
||||
bitRoK = 0x00000001,
|
||||
@ -182,7 +206,12 @@ namespace EQEmu
|
||||
maskCotF = 0x000FFFFF
|
||||
};
|
||||
|
||||
const char* ExpansionName(Expansion expansion);
|
||||
const char* ExpansionName(uint32 expansion_bit);
|
||||
uint32 ConvertExpansionToExpansionBit(Expansion expansion);
|
||||
Expansion ConvertExpansionBitToExpansion(uint32 expansion_bit);
|
||||
uint32 ConvertExpansionToExpansionMask(Expansion expansion);
|
||||
Expansion ConvertClientVersionToExpansion(versions::ClientVersion client_version);
|
||||
uint32 ConvertClientVersionToExpansionBit(versions::ClientVersion client_version);
|
||||
uint32 ConvertClientVersionToExpansionMask(versions::ClientVersion client_version);
|
||||
|
||||
|
||||
@ -19,19 +19,31 @@
|
||||
|
||||
#include "emu_constants.h"
|
||||
#include "emu_limits.h"
|
||||
#include "rulesys.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
static const EQEmu::constants::LookupEntry constants_lookup_entries[EQEmu::versions::ClientVersionCount] =
|
||||
static bool global_dictionary_init = false;
|
||||
void EQEmu::InitializeDynamicLookups() {
|
||||
if (global_dictionary_init == true)
|
||||
return;
|
||||
|
||||
constants::InitializeDynamicLookups();
|
||||
inventory::InitializeDynamicLookups();
|
||||
behavior::InitializeDynamicLookups();
|
||||
spells::InitializeDynamicLookups();
|
||||
|
||||
global_dictionary_init = true;
|
||||
}
|
||||
|
||||
static std::unique_ptr<EQEmu::constants::LookupEntry> constants_dynamic_nongm_lookup_entries[EQEmu::versions::ClientVersionCount];
|
||||
static std::unique_ptr<EQEmu::constants::LookupEntry> constants_dynamic_gm_lookup_entries[EQEmu::versions::ClientVersionCount];
|
||||
static const EQEmu::constants::LookupEntry constants_static_lookup_entries[EQEmu::versions::ClientVersionCount] =
|
||||
{
|
||||
/*[ClientVersion::Unknown] =*/
|
||||
EQEmu::constants::LookupEntry(
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL,
|
||||
EQEmu::expansions::Expansion::EverQuest,
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL,
|
||||
@ -39,13 +51,7 @@ static const EQEmu::constants::LookupEntry constants_lookup_entries[EQEmu::versi
|
||||
),
|
||||
/*[ClientVersion::Client62] =*/
|
||||
EQEmu::constants::LookupEntry(
|
||||
Client62::INULL,
|
||||
Client62::INULL,
|
||||
Client62::INULL,
|
||||
Client62::INULL,
|
||||
Client62::INULL,
|
||||
Client62::INULL,
|
||||
Client62::INULL,
|
||||
EQEmu::expansions::Expansion::EverQuest,
|
||||
Client62::INULL,
|
||||
Client62::INULL,
|
||||
Client62::INULL,
|
||||
@ -53,96 +59,100 @@ static const EQEmu::constants::LookupEntry constants_lookup_entries[EQEmu::versi
|
||||
),
|
||||
/*[ClientVersion::Titanium] =*/
|
||||
EQEmu::constants::LookupEntry(
|
||||
Titanium::constants::EXPANSION,
|
||||
Titanium::constants::EXPANSION_BIT,
|
||||
Titanium::constants::EXPANSIONS_MASK,
|
||||
Titanium::constants::CHARACTER_CREATION_LIMIT,
|
||||
Titanium::constants::SAY_LINK_BODY_SIZE,
|
||||
Titanium::constants::LongBuffs,
|
||||
Titanium::constants::ShortBuffs,
|
||||
Titanium::constants::DiscBuffs,
|
||||
Titanium::constants::TotalBuffs,
|
||||
Titanium::constants::NPCBuffs,
|
||||
Titanium::constants::PetBuffs,
|
||||
Titanium::constants::MercBuffs
|
||||
Titanium::constants::SAY_LINK_BODY_SIZE
|
||||
),
|
||||
/*[ClientVersion::SoF] =*/
|
||||
EQEmu::constants::LookupEntry(
|
||||
SoF::constants::EXPANSION,
|
||||
SoF::constants::EXPANSION_BIT,
|
||||
SoF::constants::EXPANSIONS_MASK,
|
||||
SoF::constants::CHARACTER_CREATION_LIMIT,
|
||||
SoF::constants::SAY_LINK_BODY_SIZE,
|
||||
SoF::constants::LongBuffs,
|
||||
SoF::constants::ShortBuffs,
|
||||
SoF::constants::DiscBuffs,
|
||||
SoF::constants::TotalBuffs,
|
||||
SoF::constants::NPCBuffs,
|
||||
SoF::constants::PetBuffs,
|
||||
SoF::constants::MercBuffs
|
||||
SoF::constants::SAY_LINK_BODY_SIZE
|
||||
),
|
||||
/*[ClientVersion::SoD] =*/
|
||||
EQEmu::constants::LookupEntry(
|
||||
SoD::constants::EXPANSION,
|
||||
SoD::constants::EXPANSION_BIT,
|
||||
SoD::constants::EXPANSIONS_MASK,
|
||||
SoD::constants::CHARACTER_CREATION_LIMIT,
|
||||
SoD::constants::SAY_LINK_BODY_SIZE,
|
||||
SoD::constants::LongBuffs,
|
||||
SoD::constants::ShortBuffs,
|
||||
SoD::constants::DiscBuffs,
|
||||
SoD::constants::TotalBuffs,
|
||||
SoD::constants::NPCBuffs,
|
||||
SoD::constants::PetBuffs,
|
||||
SoD::constants::MercBuffs
|
||||
SoD::constants::SAY_LINK_BODY_SIZE
|
||||
),
|
||||
/*[ClientVersion::UF] =*/
|
||||
EQEmu::constants::LookupEntry(
|
||||
UF::constants::EXPANSION,
|
||||
UF::constants::EXPANSION_BIT,
|
||||
UF::constants::EXPANSIONS_MASK,
|
||||
UF::constants::CHARACTER_CREATION_LIMIT,
|
||||
UF::constants::SAY_LINK_BODY_SIZE,
|
||||
UF::constants::LongBuffs,
|
||||
UF::constants::ShortBuffs,
|
||||
UF::constants::DiscBuffs,
|
||||
UF::constants::TotalBuffs,
|
||||
UF::constants::NPCBuffs,
|
||||
UF::constants::PetBuffs,
|
||||
UF::constants::MercBuffs
|
||||
UF::constants::SAY_LINK_BODY_SIZE
|
||||
),
|
||||
/*[ClientVersion::RoF] =*/
|
||||
EQEmu::constants::LookupEntry(
|
||||
RoF::constants::EXPANSION,
|
||||
RoF::constants::EXPANSION_BIT,
|
||||
RoF::constants::EXPANSIONS_MASK,
|
||||
RoF::constants::CHARACTER_CREATION_LIMIT,
|
||||
RoF::constants::SAY_LINK_BODY_SIZE,
|
||||
RoF::constants::LongBuffs,
|
||||
RoF::constants::ShortBuffs,
|
||||
RoF::constants::DiscBuffs,
|
||||
RoF::constants::TotalBuffs,
|
||||
RoF::constants::NPCBuffs,
|
||||
RoF::constants::PetBuffs,
|
||||
RoF::constants::MercBuffs
|
||||
RoF::constants::SAY_LINK_BODY_SIZE
|
||||
),
|
||||
/*[ClientVersion::RoF2] =*/
|
||||
EQEmu::constants::LookupEntry(
|
||||
RoF2::constants::EXPANSION,
|
||||
RoF2::constants::EXPANSION_BIT,
|
||||
RoF2::constants::EXPANSIONS_MASK,
|
||||
RoF2::constants::CHARACTER_CREATION_LIMIT,
|
||||
RoF2::constants::SAY_LINK_BODY_SIZE,
|
||||
RoF2::constants::LongBuffs,
|
||||
RoF2::constants::ShortBuffs,
|
||||
RoF2::constants::DiscBuffs,
|
||||
RoF2::constants::TotalBuffs,
|
||||
RoF2::constants::NPCBuffs,
|
||||
RoF2::constants::PetBuffs,
|
||||
RoF2::constants::MercBuffs
|
||||
RoF2::constants::SAY_LINK_BODY_SIZE
|
||||
)
|
||||
};
|
||||
|
||||
const EQEmu::constants::LookupEntry* EQEmu::constants::Lookup(versions::ClientVersion client_version)
|
||||
{
|
||||
return &constants_lookup_entries[static_cast<int>(versions::ValidateClientVersion(client_version))];
|
||||
static bool constants_dictionary_init = false;
|
||||
void EQEmu::constants::InitializeDynamicLookups() {
|
||||
if (constants_dictionary_init == true)
|
||||
return;
|
||||
constants_dictionary_init = true;
|
||||
|
||||
if (RuleB(World, UseClientBasedExpansionSettings))
|
||||
return;
|
||||
|
||||
// use static references for now
|
||||
}
|
||||
|
||||
static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versions::MobVersionCount] =
|
||||
const EQEmu::constants::LookupEntry* EQEmu::constants::DynamicLookup(versions::ClientVersion client_version, bool gm_flag)
|
||||
{
|
||||
if (gm_flag)
|
||||
return DynamicGMLookup(client_version);
|
||||
else
|
||||
return DynamicNonGMLookup(client_version);
|
||||
}
|
||||
|
||||
const EQEmu::constants::LookupEntry* EQEmu::constants::DynamicNonGMLookup(versions::ClientVersion client_version)
|
||||
{
|
||||
client_version = versions::ValidateClientVersion(client_version);
|
||||
if (constants_dynamic_nongm_lookup_entries[static_cast<int>(client_version)])
|
||||
return constants_dynamic_nongm_lookup_entries[static_cast<int>(client_version)].get();
|
||||
|
||||
return &constants_static_lookup_entries[static_cast<int>(client_version)];
|
||||
}
|
||||
|
||||
const EQEmu::constants::LookupEntry* EQEmu::constants::DynamicGMLookup(versions::ClientVersion client_version)
|
||||
{
|
||||
client_version = versions::ValidateClientVersion(client_version);
|
||||
if (constants_dynamic_gm_lookup_entries[static_cast<int>(client_version)])
|
||||
return constants_dynamic_gm_lookup_entries[static_cast<int>(client_version)].get();
|
||||
|
||||
return &constants_static_lookup_entries[static_cast<int>(client_version)];
|
||||
}
|
||||
|
||||
const EQEmu::constants::LookupEntry* EQEmu::constants::StaticLookup(versions::ClientVersion client_version)
|
||||
{
|
||||
return &constants_static_lookup_entries[static_cast<int>(versions::ValidateClientVersion(client_version))];
|
||||
}
|
||||
|
||||
static std::unique_ptr<EQEmu::inventory::LookupEntry> inventory_dynamic_nongm_lookup_entries[EQEmu::versions::MobVersionCount];
|
||||
static std::unique_ptr<EQEmu::inventory::LookupEntry> inventory_dynamic_gm_lookup_entries[EQEmu::versions::MobVersionCount];
|
||||
static const EQEmu::inventory::LookupEntry inventory_static_lookup_entries[EQEmu::versions::MobVersionCount] =
|
||||
{
|
||||
/*[MobVersion::Unknown] =*/
|
||||
EQEmu::inventory::LookupEntry(
|
||||
@ -158,6 +168,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
ClientUnknown::INULL
|
||||
),
|
||||
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL,
|
||||
@ -182,6 +195,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
Client62::INULL
|
||||
),
|
||||
|
||||
Client62::INULL,
|
||||
Client62::INULL,
|
||||
Client62::INULL,
|
||||
Client62::INULL,
|
||||
Client62::INULL,
|
||||
Client62::INULL,
|
||||
@ -206,6 +222,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
Titanium::invtype::OTHER_SIZE
|
||||
),
|
||||
|
||||
Titanium::invslot::EQUIPMENT_BITMASK,
|
||||
Titanium::invslot::GENERAL_BITMASK,
|
||||
Titanium::invslot::CURSOR_BITMASK,
|
||||
Titanium::invslot::POSSESSIONS_BITMASK,
|
||||
Titanium::invslot::CORPSE_BITMASK,
|
||||
Titanium::invbag::SLOT_COUNT,
|
||||
@ -230,6 +249,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
SoF::invtype::OTHER_SIZE
|
||||
),
|
||||
|
||||
SoF::invslot::EQUIPMENT_BITMASK,
|
||||
SoF::invslot::GENERAL_BITMASK,
|
||||
SoF::invslot::CURSOR_BITMASK,
|
||||
SoF::invslot::POSSESSIONS_BITMASK,
|
||||
SoF::invslot::CORPSE_BITMASK,
|
||||
SoF::invbag::SLOT_COUNT,
|
||||
@ -254,6 +276,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
SoD::invtype::OTHER_SIZE
|
||||
),
|
||||
|
||||
SoD::invslot::EQUIPMENT_BITMASK,
|
||||
SoD::invslot::GENERAL_BITMASK,
|
||||
SoD::invslot::CURSOR_BITMASK,
|
||||
SoD::invslot::POSSESSIONS_BITMASK,
|
||||
SoD::invslot::CORPSE_BITMASK,
|
||||
SoD::invbag::SLOT_COUNT,
|
||||
@ -278,6 +303,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
UF::invtype::OTHER_SIZE
|
||||
),
|
||||
|
||||
UF::invslot::EQUIPMENT_BITMASK,
|
||||
UF::invslot::GENERAL_BITMASK,
|
||||
UF::invslot::CURSOR_BITMASK,
|
||||
UF::invslot::POSSESSIONS_BITMASK,
|
||||
UF::invslot::CORPSE_BITMASK,
|
||||
UF::invbag::SLOT_COUNT,
|
||||
@ -302,6 +330,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
RoF::invtype::OTHER_SIZE
|
||||
),
|
||||
|
||||
RoF::invslot::EQUIPMENT_BITMASK,
|
||||
RoF::invslot::GENERAL_BITMASK,
|
||||
RoF::invslot::CURSOR_BITMASK,
|
||||
RoF::invslot::POSSESSIONS_BITMASK,
|
||||
RoF::invslot::CORPSE_BITMASK,
|
||||
RoF::invbag::SLOT_COUNT,
|
||||
@ -326,6 +357,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
RoF2::invtype::OTHER_SIZE
|
||||
),
|
||||
|
||||
RoF2::invslot::EQUIPMENT_BITMASK,
|
||||
RoF2::invslot::GENERAL_BITMASK,
|
||||
RoF2::invslot::CURSOR_BITMASK,
|
||||
RoF2::invslot::POSSESSIONS_BITMASK,
|
||||
RoF2::invslot::CORPSE_BITMASK,
|
||||
RoF2::invbag::SLOT_COUNT,
|
||||
@ -350,6 +384,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
EntityLimits::NPC::INULL
|
||||
),
|
||||
|
||||
EntityLimits::NPC::INULL,
|
||||
EntityLimits::NPC::INULL,
|
||||
EntityLimits::NPC::INULL,
|
||||
EntityLimits::NPC::INULL,
|
||||
EntityLimits::NPC::INULL,
|
||||
0, //EQEmu::inventory::ContainerCount, /*ItemBagSize,*/
|
||||
@ -374,6 +411,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
EntityLimits::NPCMerchant::INULL
|
||||
),
|
||||
|
||||
EntityLimits::NPCMerchant::INULL,
|
||||
EntityLimits::NPCMerchant::INULL,
|
||||
EntityLimits::NPCMerchant::INULL,
|
||||
EntityLimits::NPCMerchant::INULL,
|
||||
EntityLimits::NPCMerchant::INULL,
|
||||
0, //EQEmu::inventory::ContainerCount, /*ItemBagSize,*/
|
||||
@ -398,6 +438,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
EntityLimits::Merc::INULL
|
||||
),
|
||||
|
||||
EntityLimits::Merc::INULL,
|
||||
EntityLimits::Merc::INULL,
|
||||
EntityLimits::Merc::INULL,
|
||||
EntityLimits::Merc::INULL,
|
||||
EntityLimits::Merc::INULL,
|
||||
0, //EQEmu::inventory::ContainerCount, /*ItemBagSize,*/
|
||||
@ -422,6 +465,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
EntityLimits::Bot::INULL
|
||||
),
|
||||
|
||||
EntityLimits::Bot::invslot::EQUIPMENT_BITMASK,
|
||||
EntityLimits::Bot::invslot::GENERAL_BITMASK,
|
||||
EntityLimits::Bot::invslot::CURSOR_BITMASK,
|
||||
EntityLimits::Bot::invslot::POSSESSIONS_BITMASK,
|
||||
EntityLimits::Bot::INULL,
|
||||
0, //EQEmu::inventory::ContainerCount, /*ItemBagSize,*/
|
||||
@ -446,6 +492,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
EntityLimits::ClientPet::INULL
|
||||
),
|
||||
|
||||
EntityLimits::ClientPet::INULL,
|
||||
EntityLimits::ClientPet::INULL,
|
||||
EntityLimits::ClientPet::INULL,
|
||||
EntityLimits::ClientPet::INULL,
|
||||
EntityLimits::ClientPet::INULL,
|
||||
0, //EQEmu::inventory::ContainerCount, /*ItemBagSize,*/
|
||||
@ -470,6 +519,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
EntityLimits::NPCPet::INULL
|
||||
),
|
||||
|
||||
EntityLimits::NPCPet::INULL,
|
||||
EntityLimits::NPCPet::INULL,
|
||||
EntityLimits::NPCPet::INULL,
|
||||
EntityLimits::NPCPet::INULL,
|
||||
EntityLimits::NPCPet::INULL,
|
||||
0, //EQEmu::inventory::ContainerCount, /*ItemBagSize,*/
|
||||
@ -494,6 +546,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
EntityLimits::MercPet::INULL
|
||||
),
|
||||
|
||||
EntityLimits::MercPet::INULL,
|
||||
EntityLimits::MercPet::INULL,
|
||||
EntityLimits::MercPet::INULL,
|
||||
EntityLimits::MercPet::INULL,
|
||||
EntityLimits::MercPet::INULL,
|
||||
0, //EQEmu::inventory::ContainerCount, /*ItemBagSize,*/
|
||||
@ -518,6 +573,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
EntityLimits::BotPet::INULL
|
||||
),
|
||||
|
||||
EntityLimits::BotPet::INULL,
|
||||
EntityLimits::BotPet::INULL,
|
||||
EntityLimits::BotPet::INULL,
|
||||
EntityLimits::BotPet::INULL,
|
||||
EntityLimits::BotPet::INULL,
|
||||
0, //EQEmu::inventory::ContainerCount, /*ItemBagSize,*/
|
||||
@ -542,6 +600,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
Titanium::INULL
|
||||
),
|
||||
|
||||
Titanium::INULL,
|
||||
Titanium::INULL,
|
||||
Titanium::INULL,
|
||||
Titanium::INULL,
|
||||
Titanium::INULL,
|
||||
Titanium::invbag::SLOT_COUNT,
|
||||
@ -566,6 +627,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
SoF::INULL
|
||||
),
|
||||
|
||||
SoF::INULL,
|
||||
SoF::INULL,
|
||||
SoF::INULL,
|
||||
SoF::INULL,
|
||||
SoF::INULL,
|
||||
SoF::invbag::SLOT_COUNT,
|
||||
@ -590,6 +654,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
SoD::INULL
|
||||
),
|
||||
|
||||
SoD::INULL,
|
||||
SoD::INULL,
|
||||
SoD::INULL,
|
||||
SoD::INULL,
|
||||
SoD::INULL,
|
||||
SoD::invbag::SLOT_COUNT,
|
||||
@ -614,6 +681,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
UF::INULL
|
||||
),
|
||||
|
||||
UF::INULL,
|
||||
UF::INULL,
|
||||
UF::INULL,
|
||||
UF::INULL,
|
||||
UF::INULL,
|
||||
UF::invbag::SLOT_COUNT,
|
||||
@ -638,6 +708,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
RoF::INULL
|
||||
),
|
||||
|
||||
RoF::INULL,
|
||||
RoF::INULL,
|
||||
RoF::INULL,
|
||||
RoF::INULL,
|
||||
RoF::INULL,
|
||||
RoF::invbag::SLOT_COUNT,
|
||||
@ -662,6 +735,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
RoF2::INULL
|
||||
),
|
||||
|
||||
RoF2::INULL,
|
||||
RoF2::INULL,
|
||||
RoF2::INULL,
|
||||
RoF2::INULL,
|
||||
RoF2::INULL,
|
||||
RoF2::invbag::SLOT_COUNT,
|
||||
@ -674,12 +750,217 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi
|
||||
)
|
||||
};
|
||||
|
||||
const EQEmu::inventory::LookupEntry* EQEmu::inventory::Lookup(versions::MobVersion mob_version)
|
||||
{
|
||||
return &inventory_lookup_entries[static_cast<int>(versions::ValidateMobVersion(mob_version))];
|
||||
static bool inventory_dictionary_init = false;
|
||||
void EQEmu::inventory::InitializeDynamicLookups() {
|
||||
if (inventory_dictionary_init == true)
|
||||
return;
|
||||
inventory_dictionary_init = true;
|
||||
|
||||
// server is configured for static definitions
|
||||
if (RuleB(World, UseClientBasedExpansionSettings))
|
||||
return;
|
||||
|
||||
// Notes:
|
||||
// - Currently, there are only 3 known expansions that affect inventory-related settings in the clients..
|
||||
// -- Expansion::PoR "Prophecy of Ro" - toggles between 24 (set) and 16 (clear) bank slots
|
||||
// -- Expansion::TBS "The Buried Sea" - toggles slotPowerSource activated (set) and deactivated (clear)
|
||||
// -- Expansion::HoT "House of Thule" - toggles slotGeneral9/slotGeneral10 activated (set) and deactivated (clear)
|
||||
// - Corspe size does not appear to reflect loss of active possessions slots
|
||||
// - Inspect size does not appear to reflect loss of active equipment slots
|
||||
// - Bank size is not overridden by GM flag when expansion bit is (clear)
|
||||
// - Power Source slot is enabled, but not activated, by GM flag when expansion bit is (clear) (RoF+ only)
|
||||
// - General9 and General10 slots are activated by GM flag when expansion bit is (clear)
|
||||
// - Obviously, the client must support the expansion to allow any (set) or override condition
|
||||
|
||||
const uint32 dynamic_check_mask =
|
||||
(
|
||||
EQEmu::expansions::bitPoR |
|
||||
EQEmu::expansions::bitTBS |
|
||||
EQEmu::expansions::bitHoT
|
||||
);
|
||||
|
||||
// if all of the above expansion bits are present, then static references will suffice
|
||||
if ((dynamic_check_mask & RuleI(World, ExpansionSettings)) == dynamic_check_mask)
|
||||
return;
|
||||
|
||||
// Dynamic Lookups (promotive methodology) (all mob versions allowed)
|
||||
for (uint32 iter = static_cast<uint32>(EQEmu::versions::MobVersion::Unknown); iter <= static_cast<uint32>(EQEmu::versions::LastPCMobVersion); ++iter) {
|
||||
// no need to dynamic this condition since it is the lowest compatibility standard
|
||||
if ((dynamic_check_mask & ~constants_static_lookup_entries[iter].ExpansionsMask) == dynamic_check_mask)
|
||||
continue;
|
||||
|
||||
// only client versions whose supported expansions are affected need to be considered
|
||||
if ((constants_static_lookup_entries[iter].ExpansionsMask & RuleI(World, ExpansionSettings)) == constants_static_lookup_entries[iter].ExpansionsMask)
|
||||
continue;
|
||||
|
||||
// direct manipulation of lookup indices is safe so long as (int)ClientVersion::<mob> == (int)MobVersion::<mob>
|
||||
inventory_dynamic_nongm_lookup_entries[iter] = std::unique_ptr<LookupEntry>(new LookupEntry(inventory_static_lookup_entries[iter]));
|
||||
|
||||
// clamp affected fields to the lowest standard
|
||||
inventory_dynamic_nongm_lookup_entries[iter]->InventoryTypeSize.Bank = Titanium::invtype::BANK_SIZE; // bank size
|
||||
inventory_dynamic_nongm_lookup_entries[iter]->EquipmentBitmask = Titanium::invslot::EQUIPMENT_BITMASK; // power source
|
||||
inventory_dynamic_nongm_lookup_entries[iter]->GeneralBitmask = Titanium::invslot::GENERAL_BITMASK; // general size
|
||||
inventory_dynamic_nongm_lookup_entries[iter]->PossessionsBitmask = 0; // we'll fix later
|
||||
inventory_dynamic_nongm_lookup_entries[iter]->CorpseBitmask = 0; // we'll fix later
|
||||
|
||||
if (RuleI(World, ExpansionSettings) & EQEmu::expansions::bitPoR) {
|
||||
// update bank size
|
||||
if (constants_static_lookup_entries[iter].ExpansionsMask & EQEmu::expansions::bitPoR)
|
||||
inventory_dynamic_nongm_lookup_entries[iter]->InventoryTypeSize.Bank = SoF::invtype::BANK_SIZE;
|
||||
}
|
||||
|
||||
if (RuleI(World, ExpansionSettings) & EQEmu::expansions::bitTBS) {
|
||||
// update power source
|
||||
if (constants_static_lookup_entries[iter].ExpansionsMask & EQEmu::expansions::bitTBS)
|
||||
inventory_dynamic_nongm_lookup_entries[iter]->EquipmentBitmask = SoF::invslot::EQUIPMENT_BITMASK;
|
||||
}
|
||||
|
||||
if (RuleI(World, ExpansionSettings) & EQEmu::expansions::bitHoT) {
|
||||
// update general size
|
||||
if (constants_static_lookup_entries[iter].ExpansionsMask & EQEmu::expansions::bitHoT)
|
||||
inventory_dynamic_nongm_lookup_entries[iter]->GeneralBitmask = RoF::invslot::GENERAL_BITMASK;
|
||||
}
|
||||
|
||||
// fixup possessions bitmask
|
||||
inventory_dynamic_nongm_lookup_entries[iter]->PossessionsBitmask =
|
||||
(
|
||||
inventory_dynamic_nongm_lookup_entries[iter]->EquipmentBitmask |
|
||||
inventory_dynamic_nongm_lookup_entries[iter]->GeneralBitmask |
|
||||
inventory_dynamic_nongm_lookup_entries[iter]->CursorBitmask
|
||||
);
|
||||
|
||||
// fixup corpse bitmask
|
||||
inventory_dynamic_nongm_lookup_entries[iter]->CorpseBitmask =
|
||||
(
|
||||
inventory_dynamic_nongm_lookup_entries[iter]->GeneralBitmask |
|
||||
inventory_dynamic_nongm_lookup_entries[iter]->CursorBitmask |
|
||||
(inventory_dynamic_nongm_lookup_entries[iter]->EquipmentBitmask << 34)
|
||||
);
|
||||
|
||||
// expansion-related fields are now updated and all other fields reflect the static entry values
|
||||
}
|
||||
|
||||
// Dynamic GM Lookups (demotive methodology) (client-linked mob versions only)
|
||||
for (uint32 iter = static_cast<uint32>(EQEmu::versions::MobVersion::Unknown); iter <= static_cast<uint32>(EQEmu::versions::LastPCMobVersion); ++iter) {
|
||||
// no need to dynamic this condition since it is the lowest compatibility standard
|
||||
if ((dynamic_check_mask & ~constants_static_lookup_entries[iter].ExpansionsMask) == dynamic_check_mask)
|
||||
continue;
|
||||
|
||||
// only client versions whose supported expansions are affected need to be considered
|
||||
if ((constants_static_lookup_entries[iter].ExpansionsMask & RuleI(World, ExpansionSettings)) == constants_static_lookup_entries[iter].ExpansionsMask)
|
||||
continue;
|
||||
|
||||
// special case gm exclusions based on known behaviors
|
||||
switch (iter) {
|
||||
case static_cast<uint32>(versions::MobVersion::RoF2) :
|
||||
case static_cast<uint32>(versions::MobVersion::RoF) :
|
||||
// if bank size is not altered on these clients, then static will suffice
|
||||
// (we already know these clients support this expansion...)
|
||||
if (RuleI(World, ExpansionSettings) & expansions::bitPoR)
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// direct manipulation of lookup indices is safe so long as (int)ClientVersion::<client> == (int)MobVersion::<client>
|
||||
inventory_dynamic_gm_lookup_entries[iter] = std::unique_ptr<LookupEntry>(new LookupEntry(inventory_static_lookup_entries[iter]));
|
||||
|
||||
inventory_dynamic_gm_lookup_entries[iter]->PossessionsBitmask = 0; // we'll fix later
|
||||
inventory_dynamic_gm_lookup_entries[iter]->CorpseBitmask = 0; // we'll fix later
|
||||
|
||||
if (~RuleI(World, ExpansionSettings) & EQEmu::expansions::bitPoR) {
|
||||
// update bank size
|
||||
if (constants_static_lookup_entries[iter].ExpansionsMask & EQEmu::expansions::bitPoR)
|
||||
inventory_dynamic_gm_lookup_entries[iter]->InventoryTypeSize.Bank = Titanium::invtype::BANK_SIZE;
|
||||
}
|
||||
|
||||
if (~RuleI(World, ExpansionSettings) & EQEmu::expansions::bitTBS) {
|
||||
// update power source
|
||||
switch (iter) {
|
||||
case versions::bitUF:
|
||||
case versions::bitSoD:
|
||||
case versions::bitSoF:
|
||||
// gm flag does not override expansion-based behavior
|
||||
// (we already know that only these clients support this behavior)
|
||||
inventory_dynamic_gm_lookup_entries[iter]->EquipmentBitmask = Titanium::invslot::EQUIPMENT_BITMASK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (~RuleI(World, ExpansionSettings) & EQEmu::expansions::bitHoT) {
|
||||
// update general size
|
||||
switch (iter) {
|
||||
case versions::bitUF:
|
||||
case versions::bitSoD:
|
||||
case versions::bitSoF:
|
||||
// gm flag does not override expansion-based behavior
|
||||
// (we already know that only these clients support this behavior)
|
||||
inventory_dynamic_gm_lookup_entries[iter]->GeneralBitmask = Titanium::invslot::GENERAL_BITMASK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// fixup possessions bitmask
|
||||
inventory_dynamic_gm_lookup_entries[iter]->PossessionsBitmask =
|
||||
(
|
||||
inventory_dynamic_gm_lookup_entries[iter]->EquipmentBitmask |
|
||||
inventory_dynamic_gm_lookup_entries[iter]->GeneralBitmask |
|
||||
inventory_dynamic_gm_lookup_entries[iter]->CursorBitmask
|
||||
);
|
||||
|
||||
// fixup corpse bitmask
|
||||
inventory_dynamic_gm_lookup_entries[iter]->CorpseBitmask =
|
||||
(
|
||||
inventory_dynamic_gm_lookup_entries[iter]->GeneralBitmask |
|
||||
inventory_dynamic_gm_lookup_entries[iter]->CursorBitmask |
|
||||
(inventory_dynamic_gm_lookup_entries[iter]->EquipmentBitmask << 34)
|
||||
);
|
||||
|
||||
// expansion-related fields are now updated and all other fields reflect the static entry values
|
||||
}
|
||||
|
||||
// only client versions that require a change from their static definitions have been given a dynamic (gm) lookup entry
|
||||
}
|
||||
|
||||
static const EQEmu::behavior::LookupEntry behavior_lookup_entries[EQEmu::versions::MobVersionCount] =
|
||||
const EQEmu::inventory::LookupEntry* EQEmu::inventory::DynamicLookup(versions::MobVersion mob_version, bool gm_flag)
|
||||
{
|
||||
if (gm_flag)
|
||||
return DynamicGMLookup(mob_version);
|
||||
else
|
||||
return DynamicNonGMLookup(mob_version);
|
||||
}
|
||||
|
||||
const EQEmu::inventory::LookupEntry* EQEmu::inventory::DynamicNonGMLookup(versions::MobVersion mob_version)
|
||||
{
|
||||
mob_version = versions::ValidateMobVersion(mob_version);
|
||||
if (inventory_dynamic_nongm_lookup_entries[static_cast<int>(mob_version)])
|
||||
return inventory_dynamic_nongm_lookup_entries[static_cast<int>(mob_version)].get();
|
||||
|
||||
return &inventory_static_lookup_entries[static_cast<int>(mob_version)];
|
||||
}
|
||||
|
||||
const EQEmu::inventory::LookupEntry* EQEmu::inventory::DynamicGMLookup(versions::MobVersion mob_version)
|
||||
{
|
||||
mob_version = versions::ValidateMobVersion(mob_version);
|
||||
if (inventory_dynamic_gm_lookup_entries[static_cast<int>(mob_version)])
|
||||
return inventory_dynamic_gm_lookup_entries[static_cast<int>(mob_version)].get();
|
||||
|
||||
return &inventory_static_lookup_entries[static_cast<int>(mob_version)];
|
||||
}
|
||||
|
||||
const EQEmu::inventory::LookupEntry* EQEmu::inventory::StaticLookup(versions::MobVersion mob_version)
|
||||
{
|
||||
return &inventory_static_lookup_entries[static_cast<int>(versions::ValidateMobVersion(mob_version))];
|
||||
}
|
||||
|
||||
static std::unique_ptr<EQEmu::behavior::LookupEntry> behavior_dynamic_nongm_lookup_entries[EQEmu::versions::MobVersionCount];
|
||||
static std::unique_ptr<EQEmu::behavior::LookupEntry> behavior_dynamic_gm_lookup_entries[EQEmu::versions::MobVersionCount];
|
||||
static const EQEmu::behavior::LookupEntry behavior_static_lookup_entries[EQEmu::versions::MobVersionCount] =
|
||||
{
|
||||
/*[MobVersion::Unknown] =*/
|
||||
EQEmu::behavior::LookupEntry(
|
||||
@ -771,7 +1052,198 @@ static const EQEmu::behavior::LookupEntry behavior_lookup_entries[EQEmu::version
|
||||
)
|
||||
};
|
||||
|
||||
const EQEmu::behavior::LookupEntry* EQEmu::behavior::Lookup(versions::MobVersion mob_version)
|
||||
{
|
||||
return &behavior_lookup_entries[static_cast<int>(versions::ValidateMobVersion(mob_version))];
|
||||
static bool behavior_dictionary_init = false;
|
||||
void EQEmu::behavior::InitializeDynamicLookups() {
|
||||
if (behavior_dictionary_init == true)
|
||||
return;
|
||||
behavior_dictionary_init = true;
|
||||
|
||||
if (RuleB(World, UseClientBasedExpansionSettings))
|
||||
return;
|
||||
|
||||
// use static references for now
|
||||
}
|
||||
|
||||
const EQEmu::behavior::LookupEntry* EQEmu::behavior::DynamicLookup(versions::MobVersion mob_version, bool gm_flag)
|
||||
{
|
||||
if (gm_flag)
|
||||
return DynamicGMLookup(mob_version);
|
||||
else
|
||||
return DynamicNonGMLookup(mob_version);
|
||||
}
|
||||
|
||||
const EQEmu::behavior::LookupEntry* EQEmu::behavior::DynamicNonGMLookup(versions::MobVersion mob_version)
|
||||
{
|
||||
mob_version = versions::ValidateMobVersion(mob_version);
|
||||
if (behavior_dynamic_nongm_lookup_entries[static_cast<int>(mob_version)])
|
||||
return behavior_dynamic_nongm_lookup_entries[static_cast<int>(mob_version)].get();
|
||||
|
||||
return &behavior_static_lookup_entries[static_cast<int>(mob_version)];
|
||||
}
|
||||
|
||||
const EQEmu::behavior::LookupEntry* EQEmu::behavior::DynamicGMLookup(versions::MobVersion mob_version)
|
||||
{
|
||||
mob_version = versions::ValidateMobVersion(mob_version);
|
||||
if (behavior_dynamic_gm_lookup_entries[static_cast<int>(mob_version)])
|
||||
return behavior_dynamic_gm_lookup_entries[static_cast<int>(mob_version)].get();
|
||||
|
||||
return &behavior_static_lookup_entries[static_cast<int>(mob_version)];
|
||||
}
|
||||
|
||||
const EQEmu::behavior::LookupEntry* EQEmu::behavior::StaticLookup(versions::MobVersion mob_version)
|
||||
{
|
||||
return &behavior_static_lookup_entries[static_cast<int>(versions::ValidateMobVersion(mob_version))];
|
||||
}
|
||||
|
||||
static std::unique_ptr<EQEmu::spells::LookupEntry> spells_dynamic_nongm_lookup_entries[EQEmu::versions::ClientVersionCount];
|
||||
static std::unique_ptr<EQEmu::spells::LookupEntry> spells_dynamic_gm_lookup_entries[EQEmu::versions::ClientVersionCount];
|
||||
static const EQEmu::spells::LookupEntry spells_static_lookup_entries[EQEmu::versions::ClientVersionCount] =
|
||||
{
|
||||
/*[ClientVersion::Unknown] =*/
|
||||
EQEmu::spells::LookupEntry(
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL,
|
||||
ClientUnknown::INULL
|
||||
),
|
||||
/*[ClientVersion::Client62] =*/
|
||||
EQEmu::spells::LookupEntry(
|
||||
Client62::INULL,
|
||||
Client62::INULL,
|
||||
Client62::INULL,
|
||||
Client62::INULL,
|
||||
Client62::INULL,
|
||||
Client62::INULL,
|
||||
Client62::INULL,
|
||||
Client62::INULL,
|
||||
Client62::INULL,
|
||||
Client62::INULL
|
||||
),
|
||||
/*[ClientVersion::Titanium] =*/
|
||||
EQEmu::spells::LookupEntry(
|
||||
Titanium::spells::SPELL_ID_MAX,
|
||||
Titanium::spells::SPELLBOOK_SIZE,
|
||||
Titanium::spells::SPELL_GEM_COUNT,
|
||||
Titanium::spells::LONG_BUFFS,
|
||||
Titanium::spells::SHORT_BUFFS,
|
||||
Titanium::spells::DISC_BUFFS,
|
||||
Titanium::spells::TOTAL_BUFFS,
|
||||
Titanium::spells::NPC_BUFFS,
|
||||
Titanium::spells::PET_BUFFS,
|
||||
Titanium::spells::MERC_BUFFS
|
||||
),
|
||||
/*[ClientVersion::SoF] =*/
|
||||
EQEmu::spells::LookupEntry(
|
||||
SoF::spells::SPELL_ID_MAX,
|
||||
SoF::spells::SPELLBOOK_SIZE,
|
||||
SoF::spells::SPELL_GEM_COUNT,
|
||||
SoF::spells::LONG_BUFFS,
|
||||
SoF::spells::SHORT_BUFFS,
|
||||
SoF::spells::DISC_BUFFS,
|
||||
SoF::spells::TOTAL_BUFFS,
|
||||
SoF::spells::NPC_BUFFS,
|
||||
SoF::spells::PET_BUFFS,
|
||||
SoF::spells::MERC_BUFFS
|
||||
),
|
||||
/*[ClientVersion::SoD] =*/
|
||||
EQEmu::spells::LookupEntry(
|
||||
SoD::spells::SPELL_ID_MAX,
|
||||
SoD::spells::SPELLBOOK_SIZE,
|
||||
SoD::spells::SPELL_GEM_COUNT,
|
||||
SoD::spells::LONG_BUFFS,
|
||||
SoD::spells::SHORT_BUFFS,
|
||||
SoD::spells::DISC_BUFFS,
|
||||
SoD::spells::TOTAL_BUFFS,
|
||||
SoD::spells::NPC_BUFFS,
|
||||
SoD::spells::PET_BUFFS,
|
||||
SoD::spells::MERC_BUFFS
|
||||
),
|
||||
/*[ClientVersion::UF] =*/
|
||||
EQEmu::spells::LookupEntry(
|
||||
UF::spells::SPELL_ID_MAX,
|
||||
SoD::spells::SPELLBOOK_SIZE,
|
||||
UF::spells::SPELL_GEM_COUNT,
|
||||
UF::spells::LONG_BUFFS,
|
||||
UF::spells::SHORT_BUFFS,
|
||||
UF::spells::DISC_BUFFS,
|
||||
UF::spells::TOTAL_BUFFS,
|
||||
UF::spells::NPC_BUFFS,
|
||||
UF::spells::PET_BUFFS,
|
||||
UF::spells::MERC_BUFFS
|
||||
),
|
||||
/*[ClientVersion::RoF] =*/
|
||||
EQEmu::spells::LookupEntry(
|
||||
RoF::spells::SPELL_ID_MAX,
|
||||
SoD::spells::SPELLBOOK_SIZE,
|
||||
UF::spells::SPELL_GEM_COUNT, // client translators are setup to allow the max value a client supports..however, the top 4 indices are not valid in this case
|
||||
RoF::spells::LONG_BUFFS,
|
||||
RoF::spells::SHORT_BUFFS,
|
||||
RoF::spells::DISC_BUFFS,
|
||||
RoF::spells::TOTAL_BUFFS,
|
||||
RoF::spells::NPC_BUFFS,
|
||||
RoF::spells::PET_BUFFS,
|
||||
RoF::spells::MERC_BUFFS
|
||||
),
|
||||
/*[ClientVersion::RoF2] =*/
|
||||
EQEmu::spells::LookupEntry(
|
||||
RoF2::spells::SPELL_ID_MAX,
|
||||
SoD::spells::SPELLBOOK_SIZE,
|
||||
UF::spells::SPELL_GEM_COUNT, // client translators are setup to allow the max value a client supports..however, the top 4 indices are not valid in this case
|
||||
RoF2::spells::LONG_BUFFS,
|
||||
RoF2::spells::SHORT_BUFFS,
|
||||
RoF2::spells::DISC_BUFFS,
|
||||
RoF2::spells::TOTAL_BUFFS,
|
||||
RoF2::spells::NPC_BUFFS,
|
||||
RoF2::spells::PET_BUFFS,
|
||||
RoF2::spells::MERC_BUFFS
|
||||
)
|
||||
};
|
||||
|
||||
static bool spells_dictionary_init = false;
|
||||
void EQEmu::spells::InitializeDynamicLookups() {
|
||||
if (spells_dictionary_init == true)
|
||||
return;
|
||||
spells_dictionary_init = true;
|
||||
|
||||
if (RuleB(World, UseClientBasedExpansionSettings))
|
||||
return;
|
||||
|
||||
// use static references for now
|
||||
}
|
||||
|
||||
const EQEmu::spells::LookupEntry* EQEmu::spells::DynamicLookup(versions::ClientVersion client_version, bool gm_flag)
|
||||
{
|
||||
if (gm_flag)
|
||||
return DynamicGMLookup(client_version);
|
||||
else
|
||||
return DynamicNonGMLookup(client_version);
|
||||
}
|
||||
|
||||
const EQEmu::spells::LookupEntry* EQEmu::spells::DynamicNonGMLookup(versions::ClientVersion client_version)
|
||||
{
|
||||
client_version = versions::ValidateClientVersion(client_version);
|
||||
if (spells_dynamic_nongm_lookup_entries[static_cast<int>(client_version)])
|
||||
return spells_dynamic_nongm_lookup_entries[static_cast<int>(client_version)].get();
|
||||
|
||||
return &spells_static_lookup_entries[static_cast<int>(client_version)];
|
||||
}
|
||||
|
||||
const EQEmu::spells::LookupEntry* EQEmu::spells::DynamicGMLookup(versions::ClientVersion client_version)
|
||||
{
|
||||
client_version = versions::ValidateClientVersion(client_version);
|
||||
if (spells_dynamic_gm_lookup_entries[static_cast<int>(client_version)])
|
||||
return spells_dynamic_gm_lookup_entries[static_cast<int>(client_version)].get();
|
||||
|
||||
return &spells_static_lookup_entries[static_cast<int>(client_version)];
|
||||
}
|
||||
|
||||
const EQEmu::spells::LookupEntry* EQEmu::spells::StaticLookup(versions::ClientVersion client_version)
|
||||
{
|
||||
return &spells_static_lookup_entries[static_cast<int>(versions::ValidateClientVersion(client_version))];
|
||||
}
|
||||
|
||||
@ -33,48 +33,38 @@
|
||||
|
||||
namespace EQEmu
|
||||
{
|
||||
void InitializeDynamicLookups();
|
||||
|
||||
namespace constants {
|
||||
struct LookupEntry {
|
||||
EQEmu::expansions::Expansion Expansion;
|
||||
uint32 ExpansionBit;
|
||||
uint32 ExpansionsMask;
|
||||
int16 CharacterCreationLimit;
|
||||
size_t SayLinkBodySize;
|
||||
int LongBuffs;
|
||||
int ShortBuffs;
|
||||
int DiscBuffs;
|
||||
int TotalBuffs;
|
||||
int NPCBuffs;
|
||||
int PetBuffs;
|
||||
int MercBuffs;
|
||||
|
||||
|
||||
LookupEntry(const LookupEntry *lookup_entry) { }
|
||||
LookupEntry(
|
||||
EQEmu::expansions::Expansion Expansion,
|
||||
uint32 ExpansionBit,
|
||||
uint32 ExpansionsMask,
|
||||
int16 CharacterCreationLimit,
|
||||
size_t SayLinkBodySize,
|
||||
int LongBuffs,
|
||||
int ShortBuffs,
|
||||
int DiscBuffs,
|
||||
int TotalBuffs,
|
||||
int NPCBuffs,
|
||||
int PetBuffs,
|
||||
int MercBuffs
|
||||
size_t SayLinkBodySize
|
||||
) :
|
||||
Expansion(Expansion),
|
||||
ExpansionBit(ExpansionBit),
|
||||
ExpansionsMask(ExpansionsMask),
|
||||
CharacterCreationLimit(CharacterCreationLimit),
|
||||
SayLinkBodySize(SayLinkBodySize),
|
||||
LongBuffs(LongBuffs),
|
||||
ShortBuffs(ShortBuffs),
|
||||
DiscBuffs(DiscBuffs),
|
||||
TotalBuffs(TotalBuffs),
|
||||
NPCBuffs(NPCBuffs),
|
||||
PetBuffs(PetBuffs),
|
||||
MercBuffs(MercBuffs)
|
||||
SayLinkBodySize(SayLinkBodySize)
|
||||
{ }
|
||||
};
|
||||
|
||||
const LookupEntry* Lookup(versions::ClientVersion client_version);
|
||||
void InitializeDynamicLookups();
|
||||
|
||||
const LookupEntry* DynamicLookup(versions::ClientVersion client_version, bool gm_flag);
|
||||
const LookupEntry* DynamicNonGMLookup(versions::ClientVersion client_version);
|
||||
const LookupEntry* DynamicGMLookup(versions::ClientVersion client_version);
|
||||
const LookupEntry* StaticLookup(versions::ClientVersion client_version);
|
||||
|
||||
} /*constants*/
|
||||
|
||||
@ -83,7 +73,7 @@ namespace EQEmu
|
||||
// note: 'PossessionsBitmask' needs to be attuned to the client version with the highest number
|
||||
// of possessions slots and 'InventoryTypeSize[typePossessions]' should reflect the same count
|
||||
// with translators adjusting for valid slot indices. Server-side validations will be performed
|
||||
// against 'PossessionsBitmask' (note: the same applies to Corpse type size and bitmask)
|
||||
// against 'PossessionsBitmask' (note: the same applies to CorpseBitmask..size is not dependent)
|
||||
|
||||
struct InventoryTypeSize_Struct { // should reflect count and naming conventions referenced in emu_constants.h
|
||||
int16 Possessions, Bank, SharedBank;
|
||||
@ -124,6 +114,9 @@ namespace EQEmu
|
||||
int16 InventoryTypeSizeArray[25]; // should reflect EQEmu::invtype::TYPE_COUNT referenced in emu_constants.h
|
||||
};
|
||||
|
||||
uint64 EquipmentBitmask;
|
||||
uint64 GeneralBitmask;
|
||||
uint64 CursorBitmask;
|
||||
uint64 PossessionsBitmask;
|
||||
uint64 CorpseBitmask;
|
||||
int16 BagSlotCount;
|
||||
@ -134,8 +127,12 @@ namespace EQEmu
|
||||
bool ConcatenateInvTypeLimbo;
|
||||
bool AllowOverLevelEquipment;
|
||||
|
||||
LookupEntry(const LookupEntry *lookup_entry) { }
|
||||
LookupEntry(
|
||||
InventoryTypeSize_Struct InventoryTypeSize,
|
||||
uint64 EquipmentBitmask,
|
||||
uint64 GeneralBitmask,
|
||||
uint64 CursorBitmask,
|
||||
uint64 PossessionsBitmask,
|
||||
uint64 CorpseBitmask,
|
||||
int16 BagSlotCount,
|
||||
@ -146,6 +143,9 @@ namespace EQEmu
|
||||
bool AllowOverLevelEquipment
|
||||
) :
|
||||
InventoryTypeSize(InventoryTypeSize),
|
||||
EquipmentBitmask(EquipmentBitmask),
|
||||
GeneralBitmask(GeneralBitmask),
|
||||
CursorBitmask(CursorBitmask),
|
||||
PossessionsBitmask(PossessionsBitmask),
|
||||
CorpseBitmask(CorpseBitmask),
|
||||
BagSlotCount(BagSlotCount),
|
||||
@ -157,7 +157,12 @@ namespace EQEmu
|
||||
{ }
|
||||
};
|
||||
|
||||
const LookupEntry* Lookup(versions::MobVersion mob_version);
|
||||
void InitializeDynamicLookups();
|
||||
|
||||
const LookupEntry* DynamicLookup(versions::MobVersion mob_version, bool gm_flag);
|
||||
const LookupEntry* DynamicNonGMLookup(versions::MobVersion mob_version);
|
||||
const LookupEntry* DynamicGMLookup(versions::MobVersion mob_version);
|
||||
const LookupEntry* StaticLookup(versions::MobVersion mob_version);
|
||||
|
||||
} /*inventory*/
|
||||
|
||||
@ -165,6 +170,7 @@ namespace EQEmu
|
||||
struct LookupEntry {
|
||||
bool CoinHasWeight;
|
||||
|
||||
LookupEntry(const LookupEntry *lookup_entry) { }
|
||||
LookupEntry(
|
||||
bool CoinHasWeight
|
||||
) :
|
||||
@ -172,10 +178,64 @@ namespace EQEmu
|
||||
{ }
|
||||
};
|
||||
|
||||
const LookupEntry* Lookup(versions::MobVersion mob_version);
|
||||
void InitializeDynamicLookups();
|
||||
|
||||
const LookupEntry* DynamicLookup(versions::MobVersion mob_version, bool gm_flag);
|
||||
const LookupEntry* DynamicNonGMLookup(versions::MobVersion mob_version);
|
||||
const LookupEntry* DynamicGMLookup(versions::MobVersion mob_version);
|
||||
const LookupEntry* StaticLookup(versions::MobVersion mob_version);
|
||||
|
||||
} /*behavior*/
|
||||
|
||||
namespace spells {
|
||||
struct LookupEntry {
|
||||
int SpellIdMax;
|
||||
int SpellbookSize;
|
||||
int SpellGemCount;
|
||||
|
||||
int LongBuffs;
|
||||
int ShortBuffs;
|
||||
int DiscBuffs;
|
||||
int TotalBuffs;
|
||||
int NPCBuffs;
|
||||
int PetBuffs;
|
||||
int MercBuffs;
|
||||
|
||||
LookupEntry(const LookupEntry *lookup_entry) { }
|
||||
LookupEntry(
|
||||
int SpellIdMax,
|
||||
int SpellbookSize,
|
||||
int SpellGemCount,
|
||||
int LongBuffs,
|
||||
int ShortBuffs,
|
||||
int DiscBuffs,
|
||||
int TotalBuffs,
|
||||
int NPCBuffs,
|
||||
int PetBuffs,
|
||||
int MercBuffs
|
||||
) :
|
||||
SpellIdMax(SpellIdMax),
|
||||
SpellbookSize(SpellbookSize),
|
||||
SpellGemCount(SpellGemCount),
|
||||
LongBuffs(LongBuffs),
|
||||
ShortBuffs(ShortBuffs),
|
||||
DiscBuffs(DiscBuffs),
|
||||
TotalBuffs(TotalBuffs),
|
||||
NPCBuffs(NPCBuffs),
|
||||
PetBuffs(PetBuffs),
|
||||
MercBuffs(MercBuffs)
|
||||
{ }
|
||||
};
|
||||
|
||||
void InitializeDynamicLookups();
|
||||
|
||||
const LookupEntry* DynamicLookup(versions::ClientVersion client_version, bool gm_flag);
|
||||
const LookupEntry* DynamicNonGMLookup(versions::ClientVersion client_version);
|
||||
const LookupEntry* DynamicGMLookup(versions::ClientVersion client_version);
|
||||
const LookupEntry* StaticLookup(versions::ClientVersion client_version);
|
||||
|
||||
} /*spells*/
|
||||
|
||||
} /*EQEmu*/
|
||||
|
||||
namespace ClientUnknown
|
||||
|
||||
@ -852,10 +852,6 @@ struct SuspendedMinion_Struct
|
||||
** OpCode: 0x006a
|
||||
*/
|
||||
static const uint32 MAX_PP_LANGUAGE = 28;
|
||||
static const uint32 MAX_PP_SPELLBOOK = 480; // Set for all functions
|
||||
static const uint32 MAX_PP_MEMSPELL = static_cast<uint32>(EQEmu::CastingSlot::MaxGems); // Set to latest client so functions can work right -- 12
|
||||
static const uint32 MAX_PP_REF_SPELLBOOK = 480; // Set for Player Profile size retain
|
||||
static const uint32 MAX_PP_REF_MEMSPELL = 9; // Set for Player Profile size retain
|
||||
|
||||
static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size
|
||||
static const uint32 MAX_PP_INNATE_SKILL = 25;
|
||||
@ -913,7 +909,7 @@ sed -e 's/_t//g' -e 's/MAX_AA/MAX_PP_AA_ARRAY/g' \
|
||||
|
||||
struct PlayerProfile_Struct
|
||||
{
|
||||
/*0000*/ uint32 checksum; // Checksum from CRC32::SetEQChecksum
|
||||
// /*0000*/ uint32 checksum; // Checksum from CRC32::SetEQChecksum
|
||||
/*0004*/ char name[64]; // Name of player sizes not right
|
||||
/*0068*/ char last_name[32]; // Last name of player sizes not right
|
||||
/*0100*/ uint32 gender; // Player Gender - 0 Male, 1 Female
|
||||
@ -935,7 +931,7 @@ struct PlayerProfile_Struct
|
||||
/*0245*/ uint8 guildbanker;
|
||||
/*0246*/ uint8 unknown0246[6]; //
|
||||
/*0252*/ uint32 intoxication;
|
||||
/*0256*/ uint32 spellSlotRefresh[MAX_PP_MEMSPELL]; //in ms
|
||||
/*0256*/ uint32 spellSlotRefresh[EQEmu::spells::SPELL_GEM_COUNT]; //in ms
|
||||
/*0292*/ uint32 abilitySlotRefresh;
|
||||
/*0296*/ uint8 haircolor; // Player hair color
|
||||
/*0297*/ uint8 beardcolor; // Player beard color
|
||||
@ -974,9 +970,9 @@ struct PlayerProfile_Struct
|
||||
/*2505*/ uint8 unknown2541[47]; // ?
|
||||
/*2552*/ uint8 languages[MAX_PP_LANGUAGE];
|
||||
/*2580*/ uint8 unknown2616[4];
|
||||
/*2584*/ uint32 spell_book[MAX_PP_REF_SPELLBOOK];
|
||||
/*2584*/ uint32 spell_book[EQEmu::spells::SPELLBOOK_SIZE];
|
||||
/*4504*/ uint8 unknown4540[128]; // Was [428] all 0xff
|
||||
/*4632*/ uint32 mem_spells[MAX_PP_MEMSPELL];
|
||||
/*4632*/ uint32 mem_spells[EQEmu::spells::SPELL_GEM_COUNT];
|
||||
/*4668*/ uint8 unknown4704[32]; //
|
||||
/*4700*/ float y; // Player y position
|
||||
/*4704*/ float x; // Player x position
|
||||
@ -1095,6 +1091,18 @@ struct PlayerProfile_Struct
|
||||
/*19559*/ uint8 unknown19595[5]; // ***Placeholder (6/29/2005)
|
||||
/*19564*/ uint32 RestTimer;
|
||||
/*19568*/
|
||||
|
||||
// All player profile packets are translated and this overhead is ignored in out-bound packets
|
||||
PlayerProfile_Struct() : m_player_profile_version(EQEmu::versions::MobVersion::Unknown) { }
|
||||
|
||||
EQEmu::versions::MobVersion PlayerProfileVersion() { return m_player_profile_version; }
|
||||
void SetPlayerProfileVersion(EQEmu::versions::MobVersion mob_version) { m_player_profile_version = EQEmu::versions::ValidateMobVersion(mob_version); }
|
||||
void SetPlayerProfileVersion(EQEmu::versions::ClientVersion client_version) { SetPlayerProfileVersion(EQEmu::versions::ConvertClientVersionToMobVersion(client_version)); }
|
||||
|
||||
private:
|
||||
// No need for gm flag since pp already has one
|
||||
// No need for lookup pointer since this struct is not tied to any one system
|
||||
EQEmu::versions::MobVersion m_player_profile_version;
|
||||
};
|
||||
|
||||
|
||||
@ -4373,7 +4381,7 @@ struct AnnoyingZoneUnknown_Struct {
|
||||
};
|
||||
|
||||
struct LoadSpellSet_Struct {
|
||||
uint32 spell[MAX_PP_MEMSPELL]; // 0xFFFFFFFF if no action, slot number if to unmem starting at 0
|
||||
uint32 spell[EQEmu::spells::SPELL_GEM_COUNT]; // 0xFFFFFFFF if no action, slot number if to unmem starting at 0
|
||||
uint32 unknown; //there seems to be an extra field in this packet...
|
||||
};
|
||||
|
||||
|
||||
@ -119,19 +119,15 @@ EQEmu::InventoryProfile::~InventoryProfile()
|
||||
m_trade.clear();
|
||||
}
|
||||
|
||||
bool EQEmu::InventoryProfile::SetInventoryVersion(versions::MobVersion inventory_version) {
|
||||
if (!m_mob_version_set) {
|
||||
m_mob_version = versions::ValidateMobVersion(inventory_version);
|
||||
m_lookup = inventory::Lookup(m_mob_version);
|
||||
m_mob_version_set = true;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
m_lookup = inventory::Lookup(versions::MobVersion::Unknown);
|
||||
Log(Logs::General, Logs::Error, "InventoryVersion set request after initial set (old: %u, new: %u)",
|
||||
static_cast<uint32>(m_mob_version), static_cast<uint32>(inventory_version));
|
||||
return false;
|
||||
}
|
||||
void EQEmu::InventoryProfile::SetInventoryVersion(versions::MobVersion inventory_version) {
|
||||
m_mob_version = versions::ValidateMobVersion(inventory_version);
|
||||
SetGMInventory(m_gm_inventory);
|
||||
}
|
||||
|
||||
void EQEmu::InventoryProfile::SetGMInventory(bool gmi_flag) {
|
||||
m_gm_inventory = gmi_flag;
|
||||
|
||||
m_lookup = inventory::DynamicLookup(m_mob_version, gmi_flag);
|
||||
}
|
||||
|
||||
void EQEmu::InventoryProfile::CleanDirty() {
|
||||
@ -1092,7 +1088,7 @@ bool EQEmu::InventoryProfile::SupportsClickCasting(int16 slot_id)
|
||||
return true;
|
||||
}
|
||||
else if (slot_id >= invbag::GENERAL_BAGS_BEGIN && slot_id <= invbag::GENERAL_BAGS_END) {
|
||||
if (inventory::Lookup(m_mob_version)->AllowClickCastFromBag)
|
||||
if (inventory::StaticLookup(m_mob_version)->AllowClickCastFromBag)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -87,15 +87,18 @@ namespace EQEmu
|
||||
|
||||
InventoryProfile() {
|
||||
m_mob_version = versions::MobVersion::Unknown;
|
||||
m_mob_version_set = false;
|
||||
m_lookup = inventory::Lookup(versions::MobVersion::Unknown);
|
||||
m_gm_inventory = false;
|
||||
m_lookup = inventory::StaticLookup(versions::MobVersion::Unknown);
|
||||
}
|
||||
~InventoryProfile();
|
||||
|
||||
bool SetInventoryVersion(versions::MobVersion inventory_version);
|
||||
bool SetInventoryVersion(versions::ClientVersion client_version) { return SetInventoryVersion(versions::ConvertClientVersionToMobVersion(client_version)); }
|
||||
void SetInventoryVersion(versions::MobVersion inventory_version);
|
||||
void SetInventoryVersion(versions::ClientVersion client_version) { SetInventoryVersion(versions::ConvertClientVersionToMobVersion(client_version)); }
|
||||
|
||||
versions::MobVersion InventoryVersion() { return m_mob_version; }
|
||||
void SetGMInventory(bool gmi_flag);
|
||||
bool GMInventory() const { return m_gm_inventory; }
|
||||
|
||||
versions::MobVersion InventoryVersion() const { return m_mob_version; }
|
||||
|
||||
const inventory::LookupEntry* GetLookup() const { return m_lookup; }
|
||||
|
||||
@ -222,7 +225,7 @@ namespace EQEmu
|
||||
private:
|
||||
// Active mob version
|
||||
versions::MobVersion m_mob_version;
|
||||
bool m_mob_version_set;
|
||||
bool m_gm_inventory;
|
||||
const inventory::LookupEntry* m_lookup;
|
||||
};
|
||||
}
|
||||
|
||||
@ -65,8 +65,8 @@ namespace RoF
|
||||
// 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);
|
||||
static inline spells::CastingSlot ServerToRoFCastingSlot(EQEmu::spells::CastingSlot slot);
|
||||
static inline EQEmu::spells::CastingSlot RoFToServerCastingSlot(spells::CastingSlot slot);
|
||||
|
||||
static inline int ServerToRoFBuffSlot(int index);
|
||||
static inline int RoFToServerBuffSlot(int index);
|
||||
@ -502,7 +502,7 @@ namespace RoF
|
||||
ENCODE_LENGTH_EXACT(CastSpell_Struct);
|
||||
SETUP_DIRECT_ENCODE(CastSpell_Struct, structs::CastSpell_Struct);
|
||||
|
||||
eq->slot = static_cast<uint32>(ServerToRoFCastingSlot(static_cast<EQEmu::CastingSlot>(emu->slot)));
|
||||
eq->slot = static_cast<uint32>(ServerToRoFCastingSlot(static_cast<EQEmu::spells::CastingSlot>(emu->slot)));
|
||||
|
||||
OUT(spell_id);
|
||||
eq->inventory_slot = ServerToRoFSlot(emu->inventoryslot);
|
||||
@ -2124,33 +2124,44 @@ namespace RoF
|
||||
outapp->WriteUInt32(0);
|
||||
}
|
||||
|
||||
outapp->WriteUInt32(structs::MAX_PP_SPELLBOOK); // Spellbook slots
|
||||
outapp->WriteUInt32(spells::SPELLBOOK_SIZE); // Spellbook slots
|
||||
|
||||
for (uint32 r = 0; r < MAX_PP_SPELLBOOK; r++)
|
||||
{
|
||||
outapp->WriteUInt32(emu->spell_book[r]);
|
||||
if (spells::SPELLBOOK_SIZE <= EQEmu::spells::SPELLBOOK_SIZE) {
|
||||
for (uint32 r = 0; r < spells::SPELLBOOK_SIZE; r++) {
|
||||
if (emu->spell_book[r] <= spells::SPELL_ID_MAX)
|
||||
outapp->WriteUInt32(emu->spell_book[r]);
|
||||
else
|
||||
outapp->WriteUInt32(0xFFFFFFFFU);
|
||||
}
|
||||
}
|
||||
// zeroes for the rest of the spellbook slots
|
||||
for (uint32 r = 0; r < structs::MAX_PP_SPELLBOOK - MAX_PP_SPELLBOOK; r++)
|
||||
{
|
||||
outapp->WriteUInt32(0xFFFFFFFFU);
|
||||
else {
|
||||
for (uint32 r = 0; r < EQEmu::spells::SPELLBOOK_SIZE; r++) {
|
||||
if (emu->spell_book[r] <= spells::SPELL_ID_MAX)
|
||||
outapp->WriteUInt32(emu->spell_book[r]);
|
||||
else
|
||||
outapp->WriteUInt32(0xFFFFFFFFU);
|
||||
}
|
||||
// invalidate the rest of the spellbook slots
|
||||
for (uint32 r = EQEmu::spells::SPELLBOOK_SIZE; r < spells::SPELLBOOK_SIZE; r++) {
|
||||
outapp->WriteUInt32(0xFFFFFFFFU);
|
||||
}
|
||||
}
|
||||
|
||||
outapp->WriteUInt32(structs::MAX_PP_MEMSPELL); // Memorised spell slots
|
||||
outapp->WriteUInt32(spells::SPELL_GEM_COUNT); // Memorised spell slots
|
||||
|
||||
for (uint32 r = 0; r < MAX_PP_MEMSPELL; r++) // first 12
|
||||
for (uint32 r = 0; r < EQEmu::spells::SPELL_GEM_COUNT; r++) // first 12
|
||||
{
|
||||
outapp->WriteUInt32(emu->mem_spells[r]);
|
||||
}
|
||||
// zeroes for the rest of the slots -- the other 4 which don't work at all!
|
||||
for (uint32 r = 0; r < structs::MAX_PP_MEMSPELL - MAX_PP_MEMSPELL; r++)
|
||||
for (uint32 r = 0; r < spells::SPELL_GEM_COUNT - EQEmu::spells::SPELL_GEM_COUNT; r++)
|
||||
{
|
||||
outapp->WriteUInt32(0xFFFFFFFFU);
|
||||
}
|
||||
|
||||
outapp->WriteUInt32(13); // gem refresh count
|
||||
|
||||
for (uint32 r = 0; r < MAX_PP_MEMSPELL; r++)
|
||||
for (uint32 r = 0; r < EQEmu::spells::SPELL_GEM_COUNT; r++)
|
||||
{
|
||||
outapp->WriteUInt32(emu->spellSlotRefresh[r]); // spell gem refresh
|
||||
}
|
||||
@ -2334,7 +2345,8 @@ namespace RoF
|
||||
outapp->WriteUInt32(emu->lastlogin);
|
||||
outapp->WriteUInt32(emu->timePlayedMin);
|
||||
outapp->WriteUInt32(emu->timeentitledonaccount);
|
||||
outapp->WriteUInt32(0x0007ffff); // Expansion bitmask
|
||||
outapp->WriteUInt32(emu->expansions);
|
||||
//outapp->WriteUInt32(0x0007ffff); // Expansion bitmask
|
||||
|
||||
outapp->WriteUInt32(structs::MAX_PP_LANGUAGE);
|
||||
|
||||
@ -4220,7 +4232,7 @@ namespace RoF
|
||||
DECODE_LENGTH_EXACT(structs::CastSpell_Struct);
|
||||
SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct);
|
||||
|
||||
emu->slot = static_cast<uint32>(RoFToServerCastingSlot(static_cast<CastingSlot>(eq->slot)));
|
||||
emu->slot = static_cast<uint32>(RoFToServerCastingSlot(static_cast<spells::CastingSlot>(eq->slot)));
|
||||
|
||||
IN(spell_id);
|
||||
emu->inventoryslot = RoFToServerSlot(eq->inventory_slot);
|
||||
@ -4737,7 +4749,7 @@ namespace RoF
|
||||
DECODE_LENGTH_EXACT(structs::LoadSpellSet_Struct);
|
||||
SETUP_DIRECT_DECODE(LoadSpellSet_Struct, structs::LoadSpellSet_Struct);
|
||||
|
||||
for (unsigned int i = 0; i < MAX_PP_MEMSPELL; ++i)
|
||||
for (unsigned int i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; ++i)
|
||||
{
|
||||
if (eq->spell[i] == 0)
|
||||
emu->spell[i] = 0xFFFFFFFF;
|
||||
@ -6086,80 +6098,80 @@ namespace RoF
|
||||
}
|
||||
}
|
||||
|
||||
static inline CastingSlot ServerToRoFCastingSlot(EQEmu::CastingSlot slot)
|
||||
static inline spells::CastingSlot ServerToRoFCastingSlot(EQEmu::spells::CastingSlot slot)
|
||||
{
|
||||
switch (slot) {
|
||||
case EQEmu::CastingSlot::Gem1:
|
||||
return CastingSlot::Gem1;
|
||||
case EQEmu::CastingSlot::Gem2:
|
||||
return CastingSlot::Gem2;
|
||||
case EQEmu::CastingSlot::Gem3:
|
||||
return CastingSlot::Gem3;
|
||||
case EQEmu::CastingSlot::Gem4:
|
||||
return CastingSlot::Gem4;
|
||||
case EQEmu::CastingSlot::Gem5:
|
||||
return CastingSlot::Gem5;
|
||||
case EQEmu::CastingSlot::Gem6:
|
||||
return CastingSlot::Gem6;
|
||||
case EQEmu::CastingSlot::Gem7:
|
||||
return CastingSlot::Gem7;
|
||||
case EQEmu::CastingSlot::Gem8:
|
||||
return CastingSlot::Gem8;
|
||||
case EQEmu::CastingSlot::Gem9:
|
||||
return CastingSlot::Gem9;
|
||||
case EQEmu::CastingSlot::Gem10:
|
||||
return CastingSlot::Gem10;
|
||||
case EQEmu::CastingSlot::Gem11:
|
||||
return CastingSlot::Gem11;
|
||||
case EQEmu::CastingSlot::Gem12:
|
||||
return CastingSlot::Gem12;
|
||||
case EQEmu::CastingSlot::Item:
|
||||
case EQEmu::CastingSlot::PotionBelt:
|
||||
return CastingSlot::Item;
|
||||
case EQEmu::CastingSlot::Discipline:
|
||||
return CastingSlot::Discipline;
|
||||
case EQEmu::CastingSlot::AltAbility:
|
||||
return CastingSlot::AltAbility;
|
||||
case EQEmu::spells::CastingSlot::Gem1:
|
||||
return spells::CastingSlot::Gem1;
|
||||
case EQEmu::spells::CastingSlot::Gem2:
|
||||
return spells::CastingSlot::Gem2;
|
||||
case EQEmu::spells::CastingSlot::Gem3:
|
||||
return spells::CastingSlot::Gem3;
|
||||
case EQEmu::spells::CastingSlot::Gem4:
|
||||
return spells::CastingSlot::Gem4;
|
||||
case EQEmu::spells::CastingSlot::Gem5:
|
||||
return spells::CastingSlot::Gem5;
|
||||
case EQEmu::spells::CastingSlot::Gem6:
|
||||
return spells::CastingSlot::Gem6;
|
||||
case EQEmu::spells::CastingSlot::Gem7:
|
||||
return spells::CastingSlot::Gem7;
|
||||
case EQEmu::spells::CastingSlot::Gem8:
|
||||
return spells::CastingSlot::Gem8;
|
||||
case EQEmu::spells::CastingSlot::Gem9:
|
||||
return spells::CastingSlot::Gem9;
|
||||
case EQEmu::spells::CastingSlot::Gem10:
|
||||
return spells::CastingSlot::Gem10;
|
||||
case EQEmu::spells::CastingSlot::Gem11:
|
||||
return spells::CastingSlot::Gem11;
|
||||
case EQEmu::spells::CastingSlot::Gem12:
|
||||
return spells::CastingSlot::Gem12;
|
||||
case EQEmu::spells::CastingSlot::Item:
|
||||
case EQEmu::spells::CastingSlot::PotionBelt:
|
||||
return spells::CastingSlot::Item;
|
||||
case EQEmu::spells::CastingSlot::Discipline:
|
||||
return spells::CastingSlot::Discipline;
|
||||
case EQEmu::spells::CastingSlot::AltAbility:
|
||||
return spells::CastingSlot::AltAbility;
|
||||
default: // we shouldn't have any issues with other slots ... just return something
|
||||
return CastingSlot::Discipline;
|
||||
return spells::CastingSlot::Discipline;
|
||||
}
|
||||
}
|
||||
|
||||
static inline EQEmu::CastingSlot RoFToServerCastingSlot(CastingSlot slot)
|
||||
static inline EQEmu::spells::CastingSlot RoFToServerCastingSlot(spells::CastingSlot slot)
|
||||
{
|
||||
switch (slot) {
|
||||
case CastingSlot::Gem1:
|
||||
return EQEmu::CastingSlot::Gem1;
|
||||
case CastingSlot::Gem2:
|
||||
return EQEmu::CastingSlot::Gem2;
|
||||
case CastingSlot::Gem3:
|
||||
return EQEmu::CastingSlot::Gem3;
|
||||
case CastingSlot::Gem4:
|
||||
return EQEmu::CastingSlot::Gem4;
|
||||
case CastingSlot::Gem5:
|
||||
return EQEmu::CastingSlot::Gem5;
|
||||
case CastingSlot::Gem6:
|
||||
return EQEmu::CastingSlot::Gem6;
|
||||
case CastingSlot::Gem7:
|
||||
return EQEmu::CastingSlot::Gem7;
|
||||
case CastingSlot::Gem8:
|
||||
return EQEmu::CastingSlot::Gem8;
|
||||
case CastingSlot::Gem9:
|
||||
return EQEmu::CastingSlot::Gem9;
|
||||
case CastingSlot::Gem10:
|
||||
return EQEmu::CastingSlot::Gem10;
|
||||
case CastingSlot::Gem11:
|
||||
return EQEmu::CastingSlot::Gem11;
|
||||
case CastingSlot::Gem12:
|
||||
return EQEmu::CastingSlot::Gem12;
|
||||
case CastingSlot::Discipline:
|
||||
return EQEmu::CastingSlot::Discipline;
|
||||
case CastingSlot::Item:
|
||||
return EQEmu::CastingSlot::Item;
|
||||
case CastingSlot::AltAbility:
|
||||
return EQEmu::CastingSlot::AltAbility;
|
||||
case spells::CastingSlot::Gem1:
|
||||
return EQEmu::spells::CastingSlot::Gem1;
|
||||
case spells::CastingSlot::Gem2:
|
||||
return EQEmu::spells::CastingSlot::Gem2;
|
||||
case spells::CastingSlot::Gem3:
|
||||
return EQEmu::spells::CastingSlot::Gem3;
|
||||
case spells::CastingSlot::Gem4:
|
||||
return EQEmu::spells::CastingSlot::Gem4;
|
||||
case spells::CastingSlot::Gem5:
|
||||
return EQEmu::spells::CastingSlot::Gem5;
|
||||
case spells::CastingSlot::Gem6:
|
||||
return EQEmu::spells::CastingSlot::Gem6;
|
||||
case spells::CastingSlot::Gem7:
|
||||
return EQEmu::spells::CastingSlot::Gem7;
|
||||
case spells::CastingSlot::Gem8:
|
||||
return EQEmu::spells::CastingSlot::Gem8;
|
||||
case spells::CastingSlot::Gem9:
|
||||
return EQEmu::spells::CastingSlot::Gem9;
|
||||
case spells::CastingSlot::Gem10:
|
||||
return EQEmu::spells::CastingSlot::Gem10;
|
||||
case spells::CastingSlot::Gem11:
|
||||
return EQEmu::spells::CastingSlot::Gem11;
|
||||
case spells::CastingSlot::Gem12:
|
||||
return EQEmu::spells::CastingSlot::Gem12;
|
||||
case spells::CastingSlot::Discipline:
|
||||
return EQEmu::spells::CastingSlot::Discipline;
|
||||
case spells::CastingSlot::Item:
|
||||
return EQEmu::spells::CastingSlot::Item;
|
||||
case spells::CastingSlot::AltAbility:
|
||||
return EQEmu::spells::CastingSlot::AltAbility;
|
||||
default: // we shouldn't have any issues with other slots ... just return something
|
||||
return EQEmu::CastingSlot::Discipline;
|
||||
return EQEmu::spells::CastingSlot::Discipline;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6168,12 +6180,12 @@ namespace RoF
|
||||
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;
|
||||
if (index >= EQEmu::spells::LONG_BUFFS + EQEmu::spells::SHORT_BUFFS)
|
||||
return index - EQEmu::spells::LONG_BUFFS - EQEmu::spells::SHORT_BUFFS +
|
||||
spells::LONG_BUFFS + spells::SHORT_BUFFS;
|
||||
// we're a song
|
||||
if (index >= EQEmu::constants::LongBuffs)
|
||||
return index - EQEmu::constants::LongBuffs + constants::LongBuffs;
|
||||
if (index >= EQEmu::spells::LONG_BUFFS)
|
||||
return index - EQEmu::spells::LONG_BUFFS + spells::LONG_BUFFS;
|
||||
// we're a normal buff
|
||||
return index; // as long as we guard against bad slots server side, we should be fine
|
||||
}
|
||||
@ -6181,12 +6193,12 @@ namespace RoF
|
||||
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;
|
||||
if (index >= spells::LONG_BUFFS + spells::SHORT_BUFFS)
|
||||
return index - spells::LONG_BUFFS - spells::SHORT_BUFFS + EQEmu::spells::LONG_BUFFS +
|
||||
EQEmu::spells::SHORT_BUFFS;
|
||||
// we're a song
|
||||
if (index >= constants::LongBuffs)
|
||||
return index - constants::LongBuffs + EQEmu::constants::LongBuffs;
|
||||
if (index >= spells::LONG_BUFFS)
|
||||
return index - spells::LONG_BUFFS + EQEmu::spells::LONG_BUFFS;
|
||||
// we're a normal buff
|
||||
return index; // as long as we guard against bad slots server side, we should be fine
|
||||
}
|
||||
|
||||
@ -50,24 +50,6 @@ namespace RoF
|
||||
#include "rof_ops.h"
|
||||
};
|
||||
|
||||
enum class CastingSlot : uint32 {
|
||||
Gem1 = 0,
|
||||
Gem2 = 1,
|
||||
Gem3 = 2,
|
||||
Gem4 = 3,
|
||||
Gem5 = 4,
|
||||
Gem6 = 5,
|
||||
Gem7 = 6,
|
||||
Gem8 = 7,
|
||||
Gem9 = 8,
|
||||
Gem10 = 9,
|
||||
Gem11 = 10,
|
||||
Gem12 = 11,
|
||||
Item = 12,
|
||||
Discipline = 13,
|
||||
AltAbility = 0xFF
|
||||
};
|
||||
|
||||
}; /*RoF*/
|
||||
|
||||
#endif /*COMMON_ROF_H*/
|
||||
|
||||
@ -65,8 +65,8 @@ namespace RoF2
|
||||
// client to server say link converter
|
||||
static inline void RoF2ToServerSayLink(std::string &server_saylink, const std::string &rof2_saylink);
|
||||
|
||||
static inline CastingSlot ServerToRoF2CastingSlot(EQEmu::CastingSlot slot);
|
||||
static inline EQEmu::CastingSlot RoF2ToServerCastingSlot(CastingSlot slot);
|
||||
static inline spells::CastingSlot ServerToRoF2CastingSlot(EQEmu::spells::CastingSlot slot);
|
||||
static inline EQEmu::spells::CastingSlot RoF2ToServerCastingSlot(spells::CastingSlot slot);
|
||||
|
||||
static inline int ServerToRoF2BuffSlot(int index);
|
||||
static inline int RoF2ToServerBuffSlot(int index);
|
||||
@ -570,7 +570,7 @@ namespace RoF2
|
||||
ENCODE_LENGTH_EXACT(CastSpell_Struct);
|
||||
SETUP_DIRECT_ENCODE(CastSpell_Struct, structs::CastSpell_Struct);
|
||||
|
||||
eq->slot = static_cast<uint32>(ServerToRoF2CastingSlot(static_cast<EQEmu::CastingSlot>(emu->slot)));
|
||||
eq->slot = static_cast<uint32>(ServerToRoF2CastingSlot(static_cast<EQEmu::spells::CastingSlot>(emu->slot)));
|
||||
|
||||
OUT(spell_id);
|
||||
eq->inventory_slot = ServerToRoF2Slot(emu->inventoryslot);
|
||||
@ -2200,33 +2200,44 @@ namespace RoF2
|
||||
outapp->WriteUInt32(0);
|
||||
}
|
||||
|
||||
outapp->WriteUInt32(structs::MAX_PP_SPELLBOOK); // Spellbook slots
|
||||
outapp->WriteUInt32(spells::SPELLBOOK_SIZE); // Spellbook slots
|
||||
|
||||
for (uint32 r = 0; r < MAX_PP_SPELLBOOK; r++)
|
||||
{
|
||||
outapp->WriteUInt32(emu->spell_book[r]);
|
||||
if (spells::SPELLBOOK_SIZE <= EQEmu::spells::SPELLBOOK_SIZE) {
|
||||
for (uint32 r = 0; r < spells::SPELLBOOK_SIZE; r++) {
|
||||
if (emu->spell_book[r] <= spells::SPELL_ID_MAX)
|
||||
outapp->WriteUInt32(emu->spell_book[r]);
|
||||
else
|
||||
outapp->WriteUInt32(0xFFFFFFFFU);
|
||||
}
|
||||
}
|
||||
// zeroes for the rest of the spellbook slots
|
||||
for (uint32 r = 0; r < structs::MAX_PP_SPELLBOOK - MAX_PP_SPELLBOOK; r++)
|
||||
{
|
||||
outapp->WriteUInt32(0xFFFFFFFFU);
|
||||
else {
|
||||
for (uint32 r = 0; r < EQEmu::spells::SPELLBOOK_SIZE; r++) {
|
||||
if (emu->spell_book[r] <= spells::SPELL_ID_MAX)
|
||||
outapp->WriteUInt32(emu->spell_book[r]);
|
||||
else
|
||||
outapp->WriteUInt32(0xFFFFFFFFU);
|
||||
}
|
||||
// invalidate the rest of the spellbook slots
|
||||
for (uint32 r = EQEmu::spells::SPELLBOOK_SIZE; r < spells::SPELLBOOK_SIZE; r++) {
|
||||
outapp->WriteUInt32(0xFFFFFFFFU);
|
||||
}
|
||||
}
|
||||
|
||||
outapp->WriteUInt32(structs::MAX_PP_MEMSPELL); // Memorised spell slots
|
||||
outapp->WriteUInt32(spells::SPELL_GEM_COUNT); // Memorised spell slots
|
||||
|
||||
for (uint32 r = 0; r < MAX_PP_MEMSPELL; r++) // write first 12
|
||||
for (uint32 r = 0; r < EQEmu::spells::SPELL_GEM_COUNT; r++) // write first 12
|
||||
{
|
||||
outapp->WriteUInt32(emu->mem_spells[r]);
|
||||
}
|
||||
// zeroes for the rest of the slots the other 4, which actually don't work on the client at all :D
|
||||
for (uint32 r = 0; r < structs::MAX_PP_MEMSPELL - MAX_PP_MEMSPELL; r++)
|
||||
for (uint32 r = 0; r < spells::SPELL_GEM_COUNT - EQEmu::spells::SPELL_GEM_COUNT; r++)
|
||||
{
|
||||
outapp->WriteUInt32(0xFFFFFFFFU);
|
||||
}
|
||||
|
||||
outapp->WriteUInt32(13); // gem refresh counts
|
||||
|
||||
for (uint32 r = 0; r < MAX_PP_MEMSPELL; r++)
|
||||
for (uint32 r = 0; r < EQEmu::spells::SPELL_GEM_COUNT; r++)
|
||||
{
|
||||
outapp->WriteUInt32(emu->spellSlotRefresh[r]); // spell gem refresh
|
||||
}
|
||||
@ -4460,7 +4471,7 @@ namespace RoF2
|
||||
DECODE_LENGTH_EXACT(structs::CastSpell_Struct);
|
||||
SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct);
|
||||
|
||||
emu->slot = static_cast<uint32>(RoF2ToServerCastingSlot(static_cast<CastingSlot>(eq->slot)));
|
||||
emu->slot = static_cast<uint32>(RoF2ToServerCastingSlot(static_cast<spells::CastingSlot>(eq->slot)));
|
||||
|
||||
IN(spell_id);
|
||||
emu->inventoryslot = RoF2ToServerSlot(eq->inventory_slot);
|
||||
@ -4976,7 +4987,7 @@ namespace RoF2
|
||||
DECODE_LENGTH_EXACT(structs::LoadSpellSet_Struct);
|
||||
SETUP_DIRECT_DECODE(LoadSpellSet_Struct, structs::LoadSpellSet_Struct);
|
||||
|
||||
for (unsigned int i = 0; i < MAX_PP_MEMSPELL; ++i)
|
||||
for (unsigned int i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; ++i)
|
||||
{
|
||||
if (eq->spell[i] == 0)
|
||||
emu->spell[i] = 0xFFFFFFFF;
|
||||
@ -6342,80 +6353,80 @@ namespace RoF2
|
||||
}
|
||||
}
|
||||
|
||||
static inline CastingSlot ServerToRoF2CastingSlot(EQEmu::CastingSlot slot)
|
||||
static inline spells::CastingSlot ServerToRoF2CastingSlot(EQEmu::spells::CastingSlot slot)
|
||||
{
|
||||
switch (slot) {
|
||||
case EQEmu::CastingSlot::Gem1:
|
||||
return CastingSlot::Gem1;
|
||||
case EQEmu::CastingSlot::Gem2:
|
||||
return CastingSlot::Gem2;
|
||||
case EQEmu::CastingSlot::Gem3:
|
||||
return CastingSlot::Gem3;
|
||||
case EQEmu::CastingSlot::Gem4:
|
||||
return CastingSlot::Gem4;
|
||||
case EQEmu::CastingSlot::Gem5:
|
||||
return CastingSlot::Gem5;
|
||||
case EQEmu::CastingSlot::Gem6:
|
||||
return CastingSlot::Gem6;
|
||||
case EQEmu::CastingSlot::Gem7:
|
||||
return CastingSlot::Gem7;
|
||||
case EQEmu::CastingSlot::Gem8:
|
||||
return CastingSlot::Gem8;
|
||||
case EQEmu::CastingSlot::Gem9:
|
||||
return CastingSlot::Gem9;
|
||||
case EQEmu::CastingSlot::Gem10:
|
||||
return CastingSlot::Gem10;
|
||||
case EQEmu::CastingSlot::Gem11:
|
||||
return CastingSlot::Gem11;
|
||||
case EQEmu::CastingSlot::Gem12:
|
||||
return CastingSlot::Gem12;
|
||||
case EQEmu::CastingSlot::Item:
|
||||
case EQEmu::CastingSlot::PotionBelt:
|
||||
return CastingSlot::Item;
|
||||
case EQEmu::CastingSlot::Discipline:
|
||||
return CastingSlot::Discipline;
|
||||
case EQEmu::CastingSlot::AltAbility:
|
||||
return CastingSlot::AltAbility;
|
||||
case EQEmu::spells::CastingSlot::Gem1:
|
||||
return spells::CastingSlot::Gem1;
|
||||
case EQEmu::spells::CastingSlot::Gem2:
|
||||
return spells::CastingSlot::Gem2;
|
||||
case EQEmu::spells::CastingSlot::Gem3:
|
||||
return spells::CastingSlot::Gem3;
|
||||
case EQEmu::spells::CastingSlot::Gem4:
|
||||
return spells::CastingSlot::Gem4;
|
||||
case EQEmu::spells::CastingSlot::Gem5:
|
||||
return spells::CastingSlot::Gem5;
|
||||
case EQEmu::spells::CastingSlot::Gem6:
|
||||
return spells::CastingSlot::Gem6;
|
||||
case EQEmu::spells::CastingSlot::Gem7:
|
||||
return spells::CastingSlot::Gem7;
|
||||
case EQEmu::spells::CastingSlot::Gem8:
|
||||
return spells::CastingSlot::Gem8;
|
||||
case EQEmu::spells::CastingSlot::Gem9:
|
||||
return spells::CastingSlot::Gem9;
|
||||
case EQEmu::spells::CastingSlot::Gem10:
|
||||
return spells::CastingSlot::Gem10;
|
||||
case EQEmu::spells::CastingSlot::Gem11:
|
||||
return spells::CastingSlot::Gem11;
|
||||
case EQEmu::spells::CastingSlot::Gem12:
|
||||
return spells::CastingSlot::Gem12;
|
||||
case EQEmu::spells::CastingSlot::Item:
|
||||
case EQEmu::spells::CastingSlot::PotionBelt:
|
||||
return spells::CastingSlot::Item;
|
||||
case EQEmu::spells::CastingSlot::Discipline:
|
||||
return spells::CastingSlot::Discipline;
|
||||
case EQEmu::spells::CastingSlot::AltAbility:
|
||||
return spells::CastingSlot::AltAbility;
|
||||
default: // we shouldn't have any issues with other slots ... just return something
|
||||
return CastingSlot::Discipline;
|
||||
return spells::CastingSlot::Discipline;
|
||||
}
|
||||
}
|
||||
|
||||
static inline EQEmu::CastingSlot RoF2ToServerCastingSlot(CastingSlot slot)
|
||||
static inline EQEmu::spells::CastingSlot RoF2ToServerCastingSlot(spells::CastingSlot slot)
|
||||
{
|
||||
switch (slot) {
|
||||
case CastingSlot::Gem1:
|
||||
return EQEmu::CastingSlot::Gem1;
|
||||
case CastingSlot::Gem2:
|
||||
return EQEmu::CastingSlot::Gem2;
|
||||
case CastingSlot::Gem3:
|
||||
return EQEmu::CastingSlot::Gem3;
|
||||
case CastingSlot::Gem4:
|
||||
return EQEmu::CastingSlot::Gem4;
|
||||
case CastingSlot::Gem5:
|
||||
return EQEmu::CastingSlot::Gem5;
|
||||
case CastingSlot::Gem6:
|
||||
return EQEmu::CastingSlot::Gem6;
|
||||
case CastingSlot::Gem7:
|
||||
return EQEmu::CastingSlot::Gem7;
|
||||
case CastingSlot::Gem8:
|
||||
return EQEmu::CastingSlot::Gem8;
|
||||
case CastingSlot::Gem9:
|
||||
return EQEmu::CastingSlot::Gem9;
|
||||
case CastingSlot::Gem10:
|
||||
return EQEmu::CastingSlot::Gem10;
|
||||
case CastingSlot::Gem11:
|
||||
return EQEmu::CastingSlot::Gem11;
|
||||
case CastingSlot::Gem12:
|
||||
return EQEmu::CastingSlot::Gem12;
|
||||
case CastingSlot::Discipline:
|
||||
return EQEmu::CastingSlot::Discipline;
|
||||
case CastingSlot::Item:
|
||||
return EQEmu::CastingSlot::Item;
|
||||
case CastingSlot::AltAbility:
|
||||
return EQEmu::CastingSlot::AltAbility;
|
||||
case spells::CastingSlot::Gem1:
|
||||
return EQEmu::spells::CastingSlot::Gem1;
|
||||
case spells::CastingSlot::Gem2:
|
||||
return EQEmu::spells::CastingSlot::Gem2;
|
||||
case spells::CastingSlot::Gem3:
|
||||
return EQEmu::spells::CastingSlot::Gem3;
|
||||
case spells::CastingSlot::Gem4:
|
||||
return EQEmu::spells::CastingSlot::Gem4;
|
||||
case spells::CastingSlot::Gem5:
|
||||
return EQEmu::spells::CastingSlot::Gem5;
|
||||
case spells::CastingSlot::Gem6:
|
||||
return EQEmu::spells::CastingSlot::Gem6;
|
||||
case spells::CastingSlot::Gem7:
|
||||
return EQEmu::spells::CastingSlot::Gem7;
|
||||
case spells::CastingSlot::Gem8:
|
||||
return EQEmu::spells::CastingSlot::Gem8;
|
||||
case spells::CastingSlot::Gem9:
|
||||
return EQEmu::spells::CastingSlot::Gem9;
|
||||
case spells::CastingSlot::Gem10:
|
||||
return EQEmu::spells::CastingSlot::Gem10;
|
||||
case spells::CastingSlot::Gem11:
|
||||
return EQEmu::spells::CastingSlot::Gem11;
|
||||
case spells::CastingSlot::Gem12:
|
||||
return EQEmu::spells::CastingSlot::Gem12;
|
||||
case spells::CastingSlot::Discipline:
|
||||
return EQEmu::spells::CastingSlot::Discipline;
|
||||
case spells::CastingSlot::Item:
|
||||
return EQEmu::spells::CastingSlot::Item;
|
||||
case spells::CastingSlot::AltAbility:
|
||||
return EQEmu::spells::CastingSlot::AltAbility;
|
||||
default: // we shouldn't have any issues with other slots ... just return something
|
||||
return EQEmu::CastingSlot::Discipline;
|
||||
return EQEmu::spells::CastingSlot::Discipline;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6424,12 +6435,12 @@ namespace RoF2
|
||||
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;
|
||||
if (index >= EQEmu::spells::LONG_BUFFS + EQEmu::spells::SHORT_BUFFS)
|
||||
return index - EQEmu::spells::LONG_BUFFS - EQEmu::spells::SHORT_BUFFS +
|
||||
spells::LONG_BUFFS + spells::SHORT_BUFFS;
|
||||
// we're a song
|
||||
if (index >= EQEmu::constants::LongBuffs)
|
||||
return index - EQEmu::constants::LongBuffs + constants::LongBuffs;
|
||||
if (index >= EQEmu::spells::LONG_BUFFS)
|
||||
return index - EQEmu::spells::LONG_BUFFS + spells::LONG_BUFFS;
|
||||
// we're a normal buff
|
||||
return index; // as long as we guard against bad slots server side, we should be fine
|
||||
}
|
||||
@ -6437,12 +6448,12 @@ namespace RoF2
|
||||
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;
|
||||
if (index >= spells::LONG_BUFFS + spells::SHORT_BUFFS)
|
||||
return index - spells::LONG_BUFFS - spells::SHORT_BUFFS + EQEmu::spells::LONG_BUFFS +
|
||||
EQEmu::spells::SHORT_BUFFS;
|
||||
// we're a song
|
||||
if (index >= constants::LongBuffs)
|
||||
return index - constants::LongBuffs + EQEmu::constants::LongBuffs;
|
||||
if (index >= spells::LONG_BUFFS)
|
||||
return index - spells::LONG_BUFFS + EQEmu::spells::LONG_BUFFS;
|
||||
// we're a normal buff
|
||||
return index; // as long as we guard against bad slots server side, we should be fine
|
||||
}
|
||||
|
||||
@ -50,24 +50,6 @@ namespace RoF2
|
||||
#include "rof2_ops.h"
|
||||
};
|
||||
|
||||
enum class CastingSlot : uint32 {
|
||||
Gem1 = 0,
|
||||
Gem2 = 1,
|
||||
Gem3 = 2,
|
||||
Gem4 = 3,
|
||||
Gem5 = 4,
|
||||
Gem6 = 5,
|
||||
Gem7 = 6,
|
||||
Gem8 = 7,
|
||||
Gem9 = 8,
|
||||
Gem10 = 9,
|
||||
Gem11 = 10,
|
||||
Gem12 = 11,
|
||||
Item = 12,
|
||||
Discipline = 13,
|
||||
AltAbility = 0xFF
|
||||
};
|
||||
|
||||
}; /*RoF2*/
|
||||
|
||||
#endif /*COMMON_ROF2_H*/
|
||||
|
||||
@ -183,8 +183,12 @@ namespace RoF2
|
||||
const int16 CORPSE_BEGIN = invslot::slotGeneral1;
|
||||
const int16 CORPSE_END = invslot::slotGeneral1 + invslot::slotCursor;
|
||||
|
||||
const uint64 POSSESSIONS_BITMASK = 0x00000003FFFFFFFF; // based on 34-slot count (RoF+)
|
||||
const uint64 CORPSE_BITMASK = 0x01FFFFFFFF800000; // based on 34-slot count (RoF+)
|
||||
const uint64 EQUIPMENT_BITMASK = 0x00000000007FFFFF;
|
||||
const uint64 GENERAL_BITMASK = 0x00000001FF800000;
|
||||
const uint64 CURSOR_BITMASK = 0x0000000200000000;
|
||||
const uint64 POSSESSIONS_BITMASK = (EQUIPMENT_BITMASK | GENERAL_BITMASK | CURSOR_BITMASK); // based on 34-slot count (RoF+)
|
||||
const uint64 CORPSE_BITMASK = (GENERAL_BITMASK | CURSOR_BITMASK | (EQUIPMENT_BITMASK << 34)); // based on 34-slot count (RoF+)
|
||||
|
||||
|
||||
const char* GetInvPossessionsSlotName(int16 inv_slot);
|
||||
const char* GetInvSlotName(int16 inv_type, int16 inv_slot);
|
||||
@ -259,6 +263,7 @@ namespace RoF2
|
||||
namespace constants {
|
||||
inline EQEmu::versions::ClientVersion GetConstantsRef() { return EQEmu::versions::ClientVersion::RoF2; }
|
||||
|
||||
const EQEmu::expansions::Expansion EXPANSION = EQEmu::expansions::Expansion::RoF;
|
||||
const uint32 EXPANSION_BIT = EQEmu::expansions::bitRoF;
|
||||
const uint32 EXPANSIONS_MASK = EQEmu::expansions::maskRoF;
|
||||
|
||||
@ -266,14 +271,6 @@ namespace RoF2
|
||||
|
||||
const size_t SAY_LINK_BODY_SIZE = 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 {
|
||||
@ -290,6 +287,42 @@ namespace RoF2
|
||||
|
||||
} /*skills*/
|
||||
|
||||
namespace spells {
|
||||
inline EQEmu::versions::ClientVersion GetSkillsRef() { return EQEmu::versions::ClientVersion::RoF2; }
|
||||
|
||||
enum class CastingSlot : uint32 {
|
||||
Gem1 = 0,
|
||||
Gem2 = 1,
|
||||
Gem3 = 2,
|
||||
Gem4 = 3,
|
||||
Gem5 = 4,
|
||||
Gem6 = 5,
|
||||
Gem7 = 6,
|
||||
Gem8 = 7,
|
||||
Gem9 = 8,
|
||||
Gem10 = 9,
|
||||
Gem11 = 10,
|
||||
Gem12 = 11,
|
||||
MaxGems = 16, // fallacy..only 12 slot are useable...
|
||||
Item = 12,
|
||||
Discipline = 13,
|
||||
AltAbility = 0xFF
|
||||
};
|
||||
|
||||
const int SPELL_ID_MAX = 45000;
|
||||
const int SPELLBOOK_SIZE = 720;
|
||||
const int SPELL_GEM_COUNT = static_cast<uint32>(CastingSlot::MaxGems);
|
||||
|
||||
const int LONG_BUFFS = 42;
|
||||
const int SHORT_BUFFS = 20;
|
||||
const int DISC_BUFFS = 1;
|
||||
const int TOTAL_BUFFS = LONG_BUFFS + SHORT_BUFFS + DISC_BUFFS;
|
||||
const int NPC_BUFFS = 97;
|
||||
const int PET_BUFFS = NPC_BUFFS;
|
||||
const int MERC_BUFFS = LONG_BUFFS;
|
||||
|
||||
} /*spells*/
|
||||
|
||||
}; /*RoF2*/
|
||||
|
||||
#endif /*COMMON_ROF2_LIMITS_H*/
|
||||
|
||||
@ -128,8 +128,7 @@ static const uint32 MAX_NUMBER_GUILDS = 1500;
|
||||
|
||||
// Used primarily in the Player Profile:
|
||||
static const uint32 MAX_PP_LANGUAGE = 32; // was 25
|
||||
static const uint32 MAX_PP_SPELLBOOK = 720; // was 480
|
||||
static const uint32 MAX_PP_MEMSPELL = 16; // was 12
|
||||
|
||||
static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size
|
||||
static const uint32 MAX_PP_INNATE_SKILL = 25;
|
||||
static const uint32 MAX_PP_AA_ARRAY = 300;
|
||||
@ -1167,9 +1166,9 @@ union
|
||||
/*06092*/ uint32 timestamp2_count; // Seen 100
|
||||
/*06096*/ uint32 timestamps2[100]; // Unknown Unix Timestamps - maybe Skill related?
|
||||
/*06496*/ uint32 spell_book_count; // Seen 720
|
||||
/*06500*/ uint32 spell_book[MAX_PP_SPELLBOOK]; // List of the Spells in spellbook 720 = 90 pages [2880 bytes]
|
||||
/*06500*/ uint32 spell_book[spells::SPELLBOOK_SIZE]; // List of the Spells in spellbook 720 = 90 pages [2880 bytes]
|
||||
/*09380*/ uint32 mem_spell_count; // Seen 16
|
||||
/*09384*/ int32 mem_spells[MAX_PP_MEMSPELL]; // [16] List of spells memorized - First 12 are set or -1 and last 4 are 0s
|
||||
/*09384*/ int32 mem_spells[spells::SPELL_GEM_COUNT]; // [16] List of spells memorized - First 12 are set or -1 and last 4 are 0s
|
||||
/*09448*/ uint32 unknown16_count; // Seen 13
|
||||
/*09452*/ uint32 unknown_rof16[13]; // Possibly spell or buff related
|
||||
/*09504*/ uint8 unknown_rof17; // Seen 0 or 8
|
||||
|
||||
@ -181,8 +181,12 @@ namespace RoF
|
||||
const int16 CORPSE_BEGIN = invslot::slotGeneral1;
|
||||
const int16 CORPSE_END = invslot::slotGeneral1 + invslot::slotCursor;
|
||||
|
||||
const uint64 POSSESSIONS_BITMASK = 0x00000003FFFFFFFF; // based on 34-slot count (RoF+)
|
||||
const uint64 CORPSE_BITMASK = 0x01FFFFFFFF800000; // based on 34-slot count (RoF+)
|
||||
const uint64 EQUIPMENT_BITMASK = 0x00000000007FFFFF;
|
||||
const uint64 GENERAL_BITMASK = 0x00000001FF800000;
|
||||
const uint64 CURSOR_BITMASK = 0x0000000200000000;
|
||||
const uint64 POSSESSIONS_BITMASK = (EQUIPMENT_BITMASK | GENERAL_BITMASK | CURSOR_BITMASK); // based on 34-slot count (RoF+)
|
||||
const uint64 CORPSE_BITMASK = (GENERAL_BITMASK | CURSOR_BITMASK | (EQUIPMENT_BITMASK << 34)); // based on 34-slot count (RoF+)
|
||||
|
||||
|
||||
const char* GetInvPossessionsSlotName(int16 inv_slot);
|
||||
const char* GetInvSlotName(int16 inv_type, int16 inv_slot);
|
||||
@ -250,6 +254,7 @@ namespace RoF
|
||||
namespace constants {
|
||||
inline EQEmu::versions::ClientVersion GetConstantsRef() { return EQEmu::versions::ClientVersion::RoF; }
|
||||
|
||||
const EQEmu::expansions::Expansion EXPANSION = EQEmu::expansions::Expansion::RoF;
|
||||
const uint32 EXPANSION_BIT = EQEmu::expansions::bitRoF;
|
||||
const uint32 EXPANSIONS_MASK = EQEmu::expansions::maskRoF;
|
||||
|
||||
@ -257,14 +262,6 @@ namespace RoF
|
||||
|
||||
const size_t SAY_LINK_BODY_SIZE = 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 {
|
||||
@ -281,6 +278,42 @@ namespace RoF
|
||||
|
||||
} /*skills*/
|
||||
|
||||
namespace spells {
|
||||
inline EQEmu::versions::ClientVersion GetSkillsRef() { return EQEmu::versions::ClientVersion::RoF; }
|
||||
|
||||
enum class CastingSlot : uint32 {
|
||||
Gem1 = 0,
|
||||
Gem2 = 1,
|
||||
Gem3 = 2,
|
||||
Gem4 = 3,
|
||||
Gem5 = 4,
|
||||
Gem6 = 5,
|
||||
Gem7 = 6,
|
||||
Gem8 = 7,
|
||||
Gem9 = 8,
|
||||
Gem10 = 9,
|
||||
Gem11 = 10,
|
||||
Gem12 = 11,
|
||||
MaxGems = 16, // fallacy..only 12 slots are useable
|
||||
Item = 12,
|
||||
Discipline = 13,
|
||||
AltAbility = 0xFF
|
||||
};
|
||||
|
||||
const int SPELL_ID_MAX = 45000;
|
||||
const int SPELLBOOK_SIZE = 720;
|
||||
const int SPELL_GEM_COUNT = static_cast<uint32>(CastingSlot::MaxGems);
|
||||
|
||||
const int LONG_BUFFS = 42;
|
||||
const int SHORT_BUFFS = 20;
|
||||
const int DISC_BUFFS = 1;
|
||||
const int TOTAL_BUFFS = LONG_BUFFS + SHORT_BUFFS + DISC_BUFFS;
|
||||
const int NPC_BUFFS = 97;
|
||||
const int PET_BUFFS = NPC_BUFFS;
|
||||
const int MERC_BUFFS = LONG_BUFFS;
|
||||
|
||||
} /*spells*/
|
||||
|
||||
}; /*RoF*/
|
||||
|
||||
#endif /*COMMON_ROF_LIMITS_H*/
|
||||
|
||||
@ -128,8 +128,7 @@ static const uint32 MAX_NUMBER_GUILDS = 1500;
|
||||
|
||||
// Used primarily in the Player Profile:
|
||||
static const uint32 MAX_PP_LANGUAGE = 32; // was 25
|
||||
static const uint32 MAX_PP_SPELLBOOK = 720; // was 480
|
||||
static const uint32 MAX_PP_MEMSPELL = 16; // was 12
|
||||
|
||||
static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size
|
||||
static const uint32 MAX_PP_INNATE_SKILL = 25;
|
||||
static const uint32 MAX_PP_AA_ARRAY = 300;
|
||||
@ -1108,9 +1107,9 @@ union
|
||||
/*06092*/ uint32 timestamp2_count; // Seen 100
|
||||
/*06096*/ uint32 timestamps2[100]; // Unknown Unix Timestamps - maybe Skill related?
|
||||
/*06496*/ uint32 spell_book_count; // Seen 720
|
||||
/*06500*/ uint32 spell_book[MAX_PP_SPELLBOOK]; // List of the Spells in spellbook 720 = 90 pages [2880 bytes]
|
||||
/*06500*/ uint32 spell_book[spells::SPELLBOOK_SIZE]; // List of the Spells in spellbook 720 = 90 pages [2880 bytes]
|
||||
/*09380*/ uint32 mem_spell_count; // Seen 16
|
||||
/*09384*/ int32 mem_spells[MAX_PP_MEMSPELL]; // [16] List of spells memorized - First 12 are set or -1 and last 4 are 0s
|
||||
/*09384*/ int32 mem_spells[spells::SPELL_GEM_COUNT]; // [16] List of spells memorized - First 12 are set or -1 and last 4 are 0s
|
||||
/*09448*/ uint32 unknown16_count; // Seen 13
|
||||
/*09452*/ uint32 unknown_rof16[13]; // Possibly spell or buff related
|
||||
/*09504*/ uint8 unknown_rof17; // Seen 0 or 8
|
||||
|
||||
@ -59,8 +59,8 @@ namespace SoD
|
||||
// client to server say link converter
|
||||
static inline void SoDToServerSayLink(std::string &server_saylink, const std::string &sod_saylink);
|
||||
|
||||
static inline CastingSlot ServerToSoDCastingSlot(EQEmu::CastingSlot slot);
|
||||
static inline EQEmu::CastingSlot SoDToServerCastingSlot(CastingSlot slot);
|
||||
static inline spells::CastingSlot ServerToSoDCastingSlot(EQEmu::spells::CastingSlot slot);
|
||||
static inline EQEmu::spells::CastingSlot SoDToServerCastingSlot(spells::CastingSlot slot);
|
||||
|
||||
static inline int ServerToSoDBuffSlot(int index);
|
||||
static inline int SoDToServerBuffSlot(int index);
|
||||
@ -1452,7 +1452,7 @@ namespace SoD
|
||||
}
|
||||
OUT(deity);
|
||||
OUT(intoxication);
|
||||
OUT_array(spellSlotRefresh, structs::MAX_PP_MEMSPELL);
|
||||
OUT_array(spellSlotRefresh, spells::SPELL_GEM_COUNT);
|
||||
OUT(abilitySlotRefresh);
|
||||
OUT(points); // Relocation Test
|
||||
// OUT(unknown0166[4]);
|
||||
@ -1492,9 +1492,28 @@ namespace SoD
|
||||
OUT(WIS);
|
||||
OUT(face);
|
||||
// OUT(unknown02264[47]);
|
||||
OUT_array(spell_book, structs::MAX_PP_SPELLBOOK);
|
||||
|
||||
if (spells::SPELLBOOK_SIZE <= EQEmu::spells::SPELLBOOK_SIZE) {
|
||||
for (uint32 r = 0; r < spells::SPELLBOOK_SIZE; r++) {
|
||||
if (emu->spell_book[r] <= spells::SPELL_ID_MAX)
|
||||
eq->spell_book[r] = emu->spell_book[r];
|
||||
else
|
||||
eq->spell_book[r] = 0xFFFFFFFFU;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (uint32 r = 0; r < EQEmu::spells::SPELLBOOK_SIZE; r++) {
|
||||
if (emu->spell_book[r] <= spells::SPELL_ID_MAX)
|
||||
eq->spell_book[r] = emu->spell_book[r];
|
||||
else
|
||||
eq->spell_book[r] = 0xFFFFFFFFU;
|
||||
}
|
||||
// invalidate the rest of the spellbook slots
|
||||
memset(&eq->spell_book[EQEmu::spells::SPELLBOOK_SIZE], 0xFF, (sizeof(uint32) * (spells::SPELLBOOK_SIZE - EQEmu::spells::SPELLBOOK_SIZE)));
|
||||
}
|
||||
|
||||
// OUT(unknown4184[128]);
|
||||
OUT_array(mem_spells, structs::MAX_PP_MEMSPELL);
|
||||
OUT_array(mem_spells, spells::SPELL_GEM_COUNT);
|
||||
// OUT(unknown04396[32]);
|
||||
OUT(platinum);
|
||||
OUT(gold);
|
||||
@ -2842,7 +2861,7 @@ namespace SoD
|
||||
DECODE_LENGTH_EXACT(structs::CastSpell_Struct);
|
||||
SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct);
|
||||
|
||||
emu->slot = static_cast<uint32>(SoDToServerCastingSlot(static_cast<CastingSlot>(eq->slot)));
|
||||
emu->slot = static_cast<uint32>(SoDToServerCastingSlot(static_cast<spells::CastingSlot>(eq->slot)));
|
||||
IN(slot);
|
||||
IN(spell_id);
|
||||
emu->inventoryslot = SoDToServerSlot(eq->inventoryslot);
|
||||
@ -3136,9 +3155,9 @@ namespace SoD
|
||||
DECODE_LENGTH_EXACT(structs::LoadSpellSet_Struct);
|
||||
SETUP_DIRECT_DECODE(LoadSpellSet_Struct, structs::LoadSpellSet_Struct);
|
||||
|
||||
for (int i = 0; i < structs::MAX_PP_MEMSPELL; ++i)
|
||||
for (int i = 0; i < spells::SPELL_GEM_COUNT; ++i)
|
||||
emu->spell[i] = eq->spell[i];
|
||||
for (int i = structs::MAX_PP_MEMSPELL; i < MAX_PP_MEMSPELL; ++i)
|
||||
for (int i = spells::SPELL_GEM_COUNT; i < EQEmu::spells::SPELL_GEM_COUNT; ++i)
|
||||
emu->spell[i] = 0xFFFFFFFF;
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
@ -4021,84 +4040,84 @@ namespace SoD
|
||||
}
|
||||
}
|
||||
|
||||
static inline CastingSlot ServerToSoDCastingSlot(EQEmu::CastingSlot slot)
|
||||
static inline spells::CastingSlot ServerToSoDCastingSlot(EQEmu::spells::CastingSlot slot)
|
||||
{
|
||||
switch (slot) {
|
||||
case EQEmu::CastingSlot::Gem1:
|
||||
return CastingSlot::Gem1;
|
||||
case EQEmu::CastingSlot::Gem2:
|
||||
return CastingSlot::Gem2;
|
||||
case EQEmu::CastingSlot::Gem3:
|
||||
return CastingSlot::Gem3;
|
||||
case EQEmu::CastingSlot::Gem4:
|
||||
return CastingSlot::Gem4;
|
||||
case EQEmu::CastingSlot::Gem5:
|
||||
return CastingSlot::Gem5;
|
||||
case EQEmu::CastingSlot::Gem6:
|
||||
return CastingSlot::Gem6;
|
||||
case EQEmu::CastingSlot::Gem7:
|
||||
return CastingSlot::Gem7;
|
||||
case EQEmu::CastingSlot::Gem8:
|
||||
return CastingSlot::Gem8;
|
||||
case EQEmu::CastingSlot::Gem9:
|
||||
return CastingSlot::Gem9;
|
||||
case EQEmu::CastingSlot::Gem10:
|
||||
return CastingSlot::Gem10;
|
||||
case EQEmu::CastingSlot::Item:
|
||||
case EQEmu::CastingSlot::PotionBelt:
|
||||
return CastingSlot::Item;
|
||||
case EQEmu::CastingSlot::Discipline:
|
||||
return CastingSlot::Discipline;
|
||||
case EQEmu::CastingSlot::AltAbility:
|
||||
return CastingSlot::AltAbility;
|
||||
case EQEmu::spells::CastingSlot::Gem1:
|
||||
return spells::CastingSlot::Gem1;
|
||||
case EQEmu::spells::CastingSlot::Gem2:
|
||||
return spells::CastingSlot::Gem2;
|
||||
case EQEmu::spells::CastingSlot::Gem3:
|
||||
return spells::CastingSlot::Gem3;
|
||||
case EQEmu::spells::CastingSlot::Gem4:
|
||||
return spells::CastingSlot::Gem4;
|
||||
case EQEmu::spells::CastingSlot::Gem5:
|
||||
return spells::CastingSlot::Gem5;
|
||||
case EQEmu::spells::CastingSlot::Gem6:
|
||||
return spells::CastingSlot::Gem6;
|
||||
case EQEmu::spells::CastingSlot::Gem7:
|
||||
return spells::CastingSlot::Gem7;
|
||||
case EQEmu::spells::CastingSlot::Gem8:
|
||||
return spells::CastingSlot::Gem8;
|
||||
case EQEmu::spells::CastingSlot::Gem9:
|
||||
return spells::CastingSlot::Gem9;
|
||||
case EQEmu::spells::CastingSlot::Gem10:
|
||||
return spells::CastingSlot::Gem10;
|
||||
case EQEmu::spells::CastingSlot::Item:
|
||||
case EQEmu::spells::CastingSlot::PotionBelt:
|
||||
return spells::CastingSlot::Item;
|
||||
case EQEmu::spells::CastingSlot::Discipline:
|
||||
return spells::CastingSlot::Discipline;
|
||||
case EQEmu::spells::CastingSlot::AltAbility:
|
||||
return spells::CastingSlot::AltAbility;
|
||||
default: // we shouldn't have any issues with other slots ... just return something
|
||||
return CastingSlot::Discipline;
|
||||
return spells::CastingSlot::Discipline;
|
||||
}
|
||||
}
|
||||
|
||||
static inline EQEmu::CastingSlot SoDToServerCastingSlot(CastingSlot slot)
|
||||
static inline EQEmu::spells::CastingSlot SoDToServerCastingSlot(spells::CastingSlot slot)
|
||||
{
|
||||
switch (slot) {
|
||||
case CastingSlot::Gem1:
|
||||
return EQEmu::CastingSlot::Gem1;
|
||||
case CastingSlot::Gem2:
|
||||
return EQEmu::CastingSlot::Gem2;
|
||||
case CastingSlot::Gem3:
|
||||
return EQEmu::CastingSlot::Gem3;
|
||||
case CastingSlot::Gem4:
|
||||
return EQEmu::CastingSlot::Gem4;
|
||||
case CastingSlot::Gem5:
|
||||
return EQEmu::CastingSlot::Gem5;
|
||||
case CastingSlot::Gem6:
|
||||
return EQEmu::CastingSlot::Gem6;
|
||||
case CastingSlot::Gem7:
|
||||
return EQEmu::CastingSlot::Gem7;
|
||||
case CastingSlot::Gem8:
|
||||
return EQEmu::CastingSlot::Gem8;
|
||||
case CastingSlot::Gem9:
|
||||
return EQEmu::CastingSlot::Gem9;
|
||||
case CastingSlot::Gem10:
|
||||
return EQEmu::CastingSlot::Gem10;
|
||||
case CastingSlot::Discipline:
|
||||
return EQEmu::CastingSlot::Discipline;
|
||||
case CastingSlot::Item:
|
||||
return EQEmu::CastingSlot::Item;
|
||||
case CastingSlot::AltAbility:
|
||||
return EQEmu::CastingSlot::AltAbility;
|
||||
case spells::CastingSlot::Gem1:
|
||||
return EQEmu::spells::CastingSlot::Gem1;
|
||||
case spells::CastingSlot::Gem2:
|
||||
return EQEmu::spells::CastingSlot::Gem2;
|
||||
case spells::CastingSlot::Gem3:
|
||||
return EQEmu::spells::CastingSlot::Gem3;
|
||||
case spells::CastingSlot::Gem4:
|
||||
return EQEmu::spells::CastingSlot::Gem4;
|
||||
case spells::CastingSlot::Gem5:
|
||||
return EQEmu::spells::CastingSlot::Gem5;
|
||||
case spells::CastingSlot::Gem6:
|
||||
return EQEmu::spells::CastingSlot::Gem6;
|
||||
case spells::CastingSlot::Gem7:
|
||||
return EQEmu::spells::CastingSlot::Gem7;
|
||||
case spells::CastingSlot::Gem8:
|
||||
return EQEmu::spells::CastingSlot::Gem8;
|
||||
case spells::CastingSlot::Gem9:
|
||||
return EQEmu::spells::CastingSlot::Gem9;
|
||||
case spells::CastingSlot::Gem10:
|
||||
return EQEmu::spells::CastingSlot::Gem10;
|
||||
case spells::CastingSlot::Discipline:
|
||||
return EQEmu::spells::CastingSlot::Discipline;
|
||||
case spells::CastingSlot::Item:
|
||||
return EQEmu::spells::CastingSlot::Item;
|
||||
case spells::CastingSlot::AltAbility:
|
||||
return EQEmu::spells::CastingSlot::AltAbility;
|
||||
default: // we shouldn't have any issues with other slots ... just return something
|
||||
return EQEmu::CastingSlot::Discipline;
|
||||
return EQEmu::spells::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;
|
||||
if (index >= EQEmu::spells::LONG_BUFFS + EQEmu::spells::SHORT_BUFFS)
|
||||
return index - EQEmu::spells::LONG_BUFFS - EQEmu::spells::SHORT_BUFFS +
|
||||
spells::LONG_BUFFS + spells::SHORT_BUFFS;
|
||||
// we're a song
|
||||
if (index >= EQEmu::constants::LongBuffs)
|
||||
return index - EQEmu::constants::LongBuffs + constants::LongBuffs;
|
||||
if (index >= EQEmu::spells::LONG_BUFFS)
|
||||
return index - EQEmu::spells::LONG_BUFFS + spells::LONG_BUFFS;
|
||||
// we're a normal buff
|
||||
return index; // as long as we guard against bad slots server side, we should be fine
|
||||
}
|
||||
@ -4106,12 +4125,12 @@ namespace SoD
|
||||
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;
|
||||
if (index >= spells::LONG_BUFFS + spells::SHORT_BUFFS)
|
||||
return index - spells::LONG_BUFFS - spells::SHORT_BUFFS + EQEmu::spells::LONG_BUFFS +
|
||||
EQEmu::spells::SHORT_BUFFS;
|
||||
// we're a song
|
||||
if (index >= constants::LongBuffs)
|
||||
return index - constants::LongBuffs + EQEmu::constants::LongBuffs;
|
||||
if (index >= spells::LONG_BUFFS)
|
||||
return index - spells::LONG_BUFFS + EQEmu::spells::LONG_BUFFS;
|
||||
// we're a normal buff
|
||||
return index; // as long as we guard against bad slots server side, we should be fine
|
||||
}
|
||||
|
||||
@ -50,22 +50,6 @@ namespace SoD
|
||||
#include "sod_ops.h"
|
||||
};
|
||||
|
||||
enum class CastingSlot : uint32 {
|
||||
Gem1 = 0,
|
||||
Gem2 = 1,
|
||||
Gem3 = 2,
|
||||
Gem4 = 3,
|
||||
Gem5 = 4,
|
||||
Gem6 = 5,
|
||||
Gem7 = 6,
|
||||
Gem8 = 7,
|
||||
Gem9 = 8,
|
||||
Gem10 = 9,
|
||||
Item = 10,
|
||||
Discipline = 11,
|
||||
AltAbility = 0xFF
|
||||
};
|
||||
|
||||
}; /*SoD*/
|
||||
|
||||
#endif /*COMMON_SOD_H*/
|
||||
|
||||
@ -191,8 +191,12 @@ namespace SoD
|
||||
const int16 CORPSE_BEGIN = invslot::slotGeneral1;
|
||||
const int16 CORPSE_END = invslot::slotGeneral1 + invslot::slotCursor;
|
||||
|
||||
const uint64 POSSESSIONS_BITMASK = 0x000000027FFFFFFF; // based on 34-slot count (RoF+)
|
||||
const uint64 CORPSE_BITMASK = 0x01FFFFFE7F800000; // based on 34-slot count (RoF+)
|
||||
const uint64 EQUIPMENT_BITMASK = 0x00000000007FFFFF;
|
||||
const uint64 GENERAL_BITMASK = 0x000000007F800000;
|
||||
const uint64 CURSOR_BITMASK = 0x0000000200000000;
|
||||
const uint64 POSSESSIONS_BITMASK = (EQUIPMENT_BITMASK | GENERAL_BITMASK | CURSOR_BITMASK); // based on 34-slot count (RoF+)
|
||||
const uint64 CORPSE_BITMASK = (GENERAL_BITMASK | CURSOR_BITMASK | (EQUIPMENT_BITMASK << 34)); // based on 34-slot count (RoF+)
|
||||
|
||||
|
||||
const char* GetInvPossessionsSlotName(int16 inv_slot);
|
||||
const char* GetInvCorpseSlotName(int16 inv_slot);
|
||||
@ -277,6 +281,7 @@ namespace SoD
|
||||
namespace constants {
|
||||
inline EQEmu::versions::ClientVersion GetConstantsRef() { return EQEmu::versions::ClientVersion::SoD; }
|
||||
|
||||
const EQEmu::expansions::Expansion EXPANSION = EQEmu::expansions::Expansion::SoD;
|
||||
const uint32 EXPANSION_BIT = EQEmu::expansions::bitSoD;
|
||||
const uint32 EXPANSIONS_MASK = EQEmu::expansions::maskSoD;
|
||||
|
||||
@ -284,14 +289,6 @@ namespace SoD
|
||||
|
||||
const size_t SAY_LINK_BODY_SIZE = 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 {
|
||||
@ -308,6 +305,40 @@ namespace SoD
|
||||
|
||||
} /*skills*/
|
||||
|
||||
namespace spells {
|
||||
inline EQEmu::versions::ClientVersion GetSkillsRef() { return EQEmu::versions::ClientVersion::SoD; }
|
||||
|
||||
enum class CastingSlot : uint32 {
|
||||
Gem1 = 0,
|
||||
Gem2 = 1,
|
||||
Gem3 = 2,
|
||||
Gem4 = 3,
|
||||
Gem5 = 4,
|
||||
Gem6 = 5,
|
||||
Gem7 = 6,
|
||||
Gem8 = 7,
|
||||
Gem9 = 8,
|
||||
Gem10 = 9,
|
||||
MaxGems = 10,
|
||||
Item = 10,
|
||||
Discipline = 11,
|
||||
AltAbility = 0xFF
|
||||
};
|
||||
|
||||
const int SPELL_ID_MAX = 23000;
|
||||
const int SPELLBOOK_SIZE = 480;
|
||||
const int SPELL_GEM_COUNT = static_cast<uint32>(CastingSlot::MaxGems);
|
||||
|
||||
const int LONG_BUFFS = 25;
|
||||
const int SHORT_BUFFS = 15;
|
||||
const int DISC_BUFFS = 1;
|
||||
const int TOTAL_BUFFS = LONG_BUFFS + SHORT_BUFFS + DISC_BUFFS;
|
||||
const int NPC_BUFFS = 85;
|
||||
const int PET_BUFFS = NPC_BUFFS;
|
||||
const int MERC_BUFFS = LONG_BUFFS;
|
||||
|
||||
} /*spells*/
|
||||
|
||||
}; /*SoD*/
|
||||
|
||||
#endif /*COMMON_SOD_LIMITS_H*/
|
||||
|
||||
@ -815,8 +815,7 @@ struct BindStruct {
|
||||
** OpCode: 0x006a
|
||||
*/
|
||||
static const uint32 MAX_PP_LANGUAGE = 25; //
|
||||
static const uint32 MAX_PP_SPELLBOOK = 480; // Confirmed 60 pages on Live now
|
||||
static const uint32 MAX_PP_MEMSPELL = 10; //was 9 now 10 on Live
|
||||
|
||||
static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size
|
||||
static const uint32 MAX_PP_INNATE_SKILL = 25;
|
||||
static const uint32 MAX_PP_AA_ARRAY = 300; //was 299
|
||||
@ -885,7 +884,7 @@ struct PlayerProfile_Struct
|
||||
/*00060*/ BindStruct binds[5]; // Bind points (primary is first)
|
||||
/*00160*/ uint32 deity; // deity
|
||||
/*00164*/ uint32 intoxication; // Alcohol level (in ticks till sober?)
|
||||
/*00168*/ uint32 spellSlotRefresh[MAX_PP_MEMSPELL]; // Refresh time (millis) - 4 Octets Each
|
||||
/*00168*/ uint32 spellSlotRefresh[spells::SPELL_GEM_COUNT]; // Refresh time (millis) - 4 Octets Each
|
||||
/*00208*/ uint32 abilitySlotRefresh;
|
||||
/*00212*/ uint8 haircolor; // Player hair color
|
||||
/*00213*/ uint8 beardcolor; // Player beard color
|
||||
@ -911,9 +910,9 @@ struct PlayerProfile_Struct
|
||||
/*04172*/ uint8 unknown04172[28]; //
|
||||
/*04200*/ uint8 face; // Player face
|
||||
/*04201*/ uint8 unknown02264[147]; // was [175]
|
||||
/*04348*/ uint32 spell_book[MAX_PP_SPELLBOOK]; // List of the Spells in spellbook 480 = 60 pages [1920]
|
||||
/*04348*/ uint32 spell_book[spells::SPELLBOOK_SIZE]; // List of the Spells in spellbook 480 = 60 pages [1920]
|
||||
/*06268*/ uint8 unknown4184[128]; // was [164] Seen -1
|
||||
/*06396*/ uint32 mem_spells[MAX_PP_MEMSPELL]; // List of spells memorized
|
||||
/*06396*/ uint32 mem_spells[spells::SPELL_GEM_COUNT]; // List of spells memorized
|
||||
/*06436*/ uint8 unknown04396[28]; //#### uint8 unknown04396[32]; in Titanium ####[28]
|
||||
/*06464*/ uint32 platinum; // Platinum Pieces on player
|
||||
/*06468*/ uint32 gold; // Gold Pieces on player
|
||||
@ -3846,7 +3845,7 @@ struct AnnoyingZoneUnknown_Struct {
|
||||
};
|
||||
|
||||
struct LoadSpellSet_Struct {
|
||||
uint32 spell[MAX_PP_MEMSPELL]; // 0xFFFFFFFF if no action, slot number if to unmem starting at 0
|
||||
uint32 spell[spells::SPELL_GEM_COUNT]; // 0xFFFFFFFF if no action, slot number if to unmem starting at 0
|
||||
uint32 unknown; //there seems to be an extra field in this packet...
|
||||
};
|
||||
|
||||
|
||||
@ -59,8 +59,8 @@ namespace SoF
|
||||
// client to server say link converter
|
||||
static inline void SoFToServerSayLink(std::string &server_saylink, const std::string &sof_saylink);
|
||||
|
||||
static inline CastingSlot ServerToSoFCastingSlot(EQEmu::CastingSlot slot);
|
||||
static inline EQEmu::CastingSlot SoFToServerCastingSlot(CastingSlot slot, uint32 item_location);
|
||||
static inline spells::CastingSlot ServerToSoFCastingSlot(EQEmu::spells::CastingSlot slot);
|
||||
static inline EQEmu::spells::CastingSlot SoFToServerCastingSlot(spells::CastingSlot slot, uint32 item_location);
|
||||
|
||||
static inline int ServerToSoFBuffSlot(int index);
|
||||
static inline int SoFToServerBuffSlot(int index);
|
||||
@ -956,7 +956,7 @@ namespace SoF
|
||||
|
||||
// Since HT/LoH are translated up, we need to translate down only for memSpellSpellbar case
|
||||
if (emu->scribing == 3)
|
||||
eq->slot = static_cast<uint32>(ServerToSoFCastingSlot(static_cast<EQEmu::CastingSlot>(emu->slot)));
|
||||
eq->slot = static_cast<uint32>(ServerToSoFCastingSlot(static_cast<EQEmu::spells::CastingSlot>(emu->slot)));
|
||||
else
|
||||
OUT(slot);
|
||||
OUT(spell_id);
|
||||
@ -1116,7 +1116,7 @@ namespace SoF
|
||||
}
|
||||
OUT(deity);
|
||||
OUT(intoxication);
|
||||
OUT_array(spellSlotRefresh, structs::MAX_PP_MEMSPELL);
|
||||
OUT_array(spellSlotRefresh, spells::SPELL_GEM_COUNT);
|
||||
OUT(abilitySlotRefresh);
|
||||
OUT(points); // Relocation Test
|
||||
// OUT(unknown0166[4]);
|
||||
@ -1156,9 +1156,28 @@ namespace SoF
|
||||
OUT(WIS);
|
||||
OUT(face);
|
||||
// OUT(unknown02264[47]);
|
||||
OUT_array(spell_book, structs::MAX_PP_SPELLBOOK);
|
||||
|
||||
if (spells::SPELLBOOK_SIZE <= EQEmu::spells::SPELLBOOK_SIZE) {
|
||||
for (uint32 r = 0; r < spells::SPELLBOOK_SIZE; r++) {
|
||||
if (emu->spell_book[r] <= spells::SPELL_ID_MAX)
|
||||
eq->spell_book[r] = emu->spell_book[r];
|
||||
else
|
||||
eq->spell_book[r] = 0xFFFFFFFFU;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (uint32 r = 0; r < EQEmu::spells::SPELLBOOK_SIZE; r++) {
|
||||
if (emu->spell_book[r] <= spells::SPELL_ID_MAX)
|
||||
eq->spell_book[r] = emu->spell_book[r];
|
||||
else
|
||||
eq->spell_book[r] = 0xFFFFFFFFU;
|
||||
}
|
||||
// invalidate the rest of the spellbook slots
|
||||
memset(&eq->spell_book[EQEmu::spells::SPELLBOOK_SIZE], 0xFF, (sizeof(uint32) * (spells::SPELLBOOK_SIZE - EQEmu::spells::SPELLBOOK_SIZE)));
|
||||
}
|
||||
|
||||
// OUT(unknown4184[128]);
|
||||
OUT_array(mem_spells, structs::MAX_PP_MEMSPELL);
|
||||
OUT_array(mem_spells, spells::SPELL_GEM_COUNT);
|
||||
// OUT(unknown04396[32]);
|
||||
OUT(platinum);
|
||||
OUT(gold);
|
||||
@ -2298,7 +2317,7 @@ namespace SoF
|
||||
DECODE_LENGTH_EXACT(structs::CastSpell_Struct);
|
||||
SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct);
|
||||
|
||||
emu->slot = static_cast<uint32>(SoFToServerCastingSlot(static_cast<CastingSlot>(eq->slot), eq->inventoryslot));
|
||||
emu->slot = static_cast<uint32>(SoFToServerCastingSlot(static_cast<spells::CastingSlot>(eq->slot), eq->inventoryslot));
|
||||
IN(spell_id);
|
||||
emu->inventoryslot = SoFToServerSlot(eq->inventoryslot);
|
||||
IN(target_id);
|
||||
@ -2540,9 +2559,9 @@ namespace SoF
|
||||
DECODE_LENGTH_EXACT(structs::LoadSpellSet_Struct);
|
||||
SETUP_DIRECT_DECODE(LoadSpellSet_Struct, structs::LoadSpellSet_Struct);
|
||||
|
||||
for (int i = 0; i < structs::MAX_PP_MEMSPELL; ++i)
|
||||
for (int i = 0; i < spells::SPELL_GEM_COUNT; ++i)
|
||||
IN(spell[i]);
|
||||
for (int i = structs::MAX_PP_MEMSPELL; i < MAX_PP_MEMSPELL; ++i)
|
||||
for (int i = spells::SPELL_GEM_COUNT; i < EQEmu::spells::SPELL_GEM_COUNT; ++i)
|
||||
emu->spell[i] = 0xFFFFFFFF;
|
||||
|
||||
IN(unknown);
|
||||
@ -3419,84 +3438,84 @@ namespace SoF
|
||||
}
|
||||
}
|
||||
|
||||
static inline CastingSlot ServerToSoFCastingSlot(EQEmu::CastingSlot slot) {
|
||||
static inline spells::CastingSlot ServerToSoFCastingSlot(EQEmu::spells::CastingSlot slot) {
|
||||
switch (slot) {
|
||||
case EQEmu::CastingSlot::Gem1:
|
||||
return CastingSlot::Gem1;
|
||||
case EQEmu::CastingSlot::Gem2:
|
||||
return CastingSlot::Gem2;
|
||||
case EQEmu::CastingSlot::Gem3:
|
||||
return CastingSlot::Gem3;
|
||||
case EQEmu::CastingSlot::Gem4:
|
||||
return CastingSlot::Gem4;
|
||||
case EQEmu::CastingSlot::Gem5:
|
||||
return CastingSlot::Gem5;
|
||||
case EQEmu::CastingSlot::Gem6:
|
||||
return CastingSlot::Gem6;
|
||||
case EQEmu::CastingSlot::Gem7:
|
||||
return CastingSlot::Gem7;
|
||||
case EQEmu::CastingSlot::Gem8:
|
||||
return CastingSlot::Gem8;
|
||||
case EQEmu::CastingSlot::Gem9:
|
||||
return CastingSlot::Gem9;
|
||||
case EQEmu::CastingSlot::Item:
|
||||
return CastingSlot::Item;
|
||||
case EQEmu::CastingSlot::PotionBelt:
|
||||
return CastingSlot::PotionBelt;
|
||||
case EQEmu::CastingSlot::Discipline:
|
||||
return CastingSlot::Discipline;
|
||||
case EQEmu::CastingSlot::AltAbility:
|
||||
return CastingSlot::AltAbility;
|
||||
case EQEmu::spells::CastingSlot::Gem1:
|
||||
return spells::CastingSlot::Gem1;
|
||||
case EQEmu::spells::CastingSlot::Gem2:
|
||||
return spells::CastingSlot::Gem2;
|
||||
case EQEmu::spells::CastingSlot::Gem3:
|
||||
return spells::CastingSlot::Gem3;
|
||||
case EQEmu::spells::CastingSlot::Gem4:
|
||||
return spells::CastingSlot::Gem4;
|
||||
case EQEmu::spells::CastingSlot::Gem5:
|
||||
return spells::CastingSlot::Gem5;
|
||||
case EQEmu::spells::CastingSlot::Gem6:
|
||||
return spells::CastingSlot::Gem6;
|
||||
case EQEmu::spells::CastingSlot::Gem7:
|
||||
return spells::CastingSlot::Gem7;
|
||||
case EQEmu::spells::CastingSlot::Gem8:
|
||||
return spells::CastingSlot::Gem8;
|
||||
case EQEmu::spells::CastingSlot::Gem9:
|
||||
return spells::CastingSlot::Gem9;
|
||||
case EQEmu::spells::CastingSlot::Item:
|
||||
return spells::CastingSlot::Item;
|
||||
case EQEmu::spells::CastingSlot::PotionBelt:
|
||||
return spells::CastingSlot::PotionBelt;
|
||||
case EQEmu::spells::CastingSlot::Discipline:
|
||||
return spells::CastingSlot::Discipline;
|
||||
case EQEmu::spells::CastingSlot::AltAbility:
|
||||
return spells::CastingSlot::AltAbility;
|
||||
default: // we shouldn't have any issues with other slots ... just return something
|
||||
return CastingSlot::Discipline;
|
||||
return spells::CastingSlot::Discipline;
|
||||
}
|
||||
}
|
||||
|
||||
static inline EQEmu::CastingSlot SoFToServerCastingSlot(CastingSlot slot, uint32 item_location) {
|
||||
static inline EQEmu::spells::CastingSlot SoFToServerCastingSlot(spells::CastingSlot slot, uint32 item_location) {
|
||||
switch (slot) {
|
||||
case CastingSlot::Gem1:
|
||||
return EQEmu::CastingSlot::Gem1;
|
||||
case CastingSlot::Gem2:
|
||||
return EQEmu::CastingSlot::Gem2;
|
||||
case CastingSlot::Gem3:
|
||||
return EQEmu::CastingSlot::Gem3;
|
||||
case CastingSlot::Gem4:
|
||||
return EQEmu::CastingSlot::Gem4;
|
||||
case CastingSlot::Gem5:
|
||||
return EQEmu::CastingSlot::Gem5;
|
||||
case CastingSlot::Gem6:
|
||||
return EQEmu::CastingSlot::Gem6;
|
||||
case CastingSlot::Gem7:
|
||||
return EQEmu::CastingSlot::Gem7;
|
||||
case CastingSlot::Gem8:
|
||||
return EQEmu::CastingSlot::Gem8;
|
||||
case CastingSlot::Gem9:
|
||||
return EQEmu::CastingSlot::Gem9;
|
||||
case CastingSlot::Ability:
|
||||
return EQEmu::CastingSlot::Ability;
|
||||
case spells::CastingSlot::Gem1:
|
||||
return EQEmu::spells::CastingSlot::Gem1;
|
||||
case spells::CastingSlot::Gem2:
|
||||
return EQEmu::spells::CastingSlot::Gem2;
|
||||
case spells::CastingSlot::Gem3:
|
||||
return EQEmu::spells::CastingSlot::Gem3;
|
||||
case spells::CastingSlot::Gem4:
|
||||
return EQEmu::spells::CastingSlot::Gem4;
|
||||
case spells::CastingSlot::Gem5:
|
||||
return EQEmu::spells::CastingSlot::Gem5;
|
||||
case spells::CastingSlot::Gem6:
|
||||
return EQEmu::spells::CastingSlot::Gem6;
|
||||
case spells::CastingSlot::Gem7:
|
||||
return EQEmu::spells::CastingSlot::Gem7;
|
||||
case spells::CastingSlot::Gem8:
|
||||
return EQEmu::spells::CastingSlot::Gem8;
|
||||
case spells::CastingSlot::Gem9:
|
||||
return EQEmu::spells::CastingSlot::Gem9;
|
||||
case spells::CastingSlot::Ability:
|
||||
return EQEmu::spells::CastingSlot::Ability;
|
||||
// Tit uses 10 for item and discipline casting, but items have a valid location
|
||||
case CastingSlot::Item:
|
||||
case spells::CastingSlot::Item:
|
||||
if (item_location == INVALID_INDEX)
|
||||
return EQEmu::CastingSlot::Discipline;
|
||||
return EQEmu::spells::CastingSlot::Discipline;
|
||||
else
|
||||
return EQEmu::CastingSlot::Item;
|
||||
case CastingSlot::PotionBelt:
|
||||
return EQEmu::CastingSlot::PotionBelt;
|
||||
case CastingSlot::AltAbility:
|
||||
return EQEmu::CastingSlot::AltAbility;
|
||||
return EQEmu::spells::CastingSlot::Item;
|
||||
case spells::CastingSlot::PotionBelt:
|
||||
return EQEmu::spells::CastingSlot::PotionBelt;
|
||||
case spells::CastingSlot::AltAbility:
|
||||
return EQEmu::spells::CastingSlot::AltAbility;
|
||||
default: // we shouldn't have any issues with other slots ... just return something
|
||||
return EQEmu::CastingSlot::Discipline;
|
||||
return EQEmu::spells::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;
|
||||
if (index >= EQEmu::spells::LONG_BUFFS + EQEmu::spells::SHORT_BUFFS)
|
||||
return index - EQEmu::spells::LONG_BUFFS - EQEmu::spells::SHORT_BUFFS +
|
||||
spells::LONG_BUFFS + spells::SHORT_BUFFS;
|
||||
// we're a song
|
||||
if (index >= EQEmu::constants::LongBuffs)
|
||||
return index - EQEmu::constants::LongBuffs + constants::LongBuffs;
|
||||
if (index >= EQEmu::spells::LONG_BUFFS)
|
||||
return index - EQEmu::spells::LONG_BUFFS + spells::LONG_BUFFS;
|
||||
// we're a normal buff
|
||||
return index; // as long as we guard against bad slots server side, we should be fine
|
||||
}
|
||||
@ -3504,12 +3523,12 @@ namespace SoF
|
||||
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;
|
||||
if (index >= spells::LONG_BUFFS + spells::SHORT_BUFFS)
|
||||
return index - spells::LONG_BUFFS - spells::SHORT_BUFFS + EQEmu::spells::LONG_BUFFS +
|
||||
EQEmu::spells::SHORT_BUFFS;
|
||||
// we're a song
|
||||
if (index >= constants::LongBuffs)
|
||||
return index - constants::LongBuffs + EQEmu::constants::LongBuffs;
|
||||
if (index >= spells::LONG_BUFFS)
|
||||
return index - spells::LONG_BUFFS + EQEmu::spells::LONG_BUFFS;
|
||||
// we're a normal buff
|
||||
return index; // as long as we guard against bad slots server side, we should be fine
|
||||
}
|
||||
|
||||
@ -50,23 +50,6 @@ namespace SoF
|
||||
#include "sof_ops.h"
|
||||
};
|
||||
|
||||
enum class CastingSlot : uint32 {
|
||||
Gem1 = 0,
|
||||
Gem2 = 1,
|
||||
Gem3 = 2,
|
||||
Gem4 = 3,
|
||||
Gem5 = 4,
|
||||
Gem6 = 5,
|
||||
Gem7 = 6,
|
||||
Gem8 = 7,
|
||||
Gem9 = 8,
|
||||
Ability = 9,
|
||||
Item = 10,
|
||||
Discipline = 10,
|
||||
PotionBelt = 11,
|
||||
AltAbility = 0xFF
|
||||
};
|
||||
|
||||
}; /*SoF*/
|
||||
|
||||
#endif /*COMMON_SOF_H*/
|
||||
|
||||
@ -191,8 +191,12 @@ namespace SoF
|
||||
const int16 CORPSE_BEGIN = invslot::slotGeneral1;
|
||||
const int16 CORPSE_END = invslot::slotGeneral1 + invslot::slotCursor;
|
||||
|
||||
const uint64 POSSESSIONS_BITMASK = 0x000000027FFFFFFF; // based on 34-slot count (RoF+)
|
||||
const uint64 CORPSE_BITMASK = 0x01FFFFFE7F800000; // based on 34-slot count (RoF+)
|
||||
const uint64 EQUIPMENT_BITMASK = 0x00000000007FFFFF;
|
||||
const uint64 GENERAL_BITMASK = 0x000000007F800000;
|
||||
const uint64 CURSOR_BITMASK = 0x0000000200000000;
|
||||
const uint64 POSSESSIONS_BITMASK = (EQUIPMENT_BITMASK | GENERAL_BITMASK | CURSOR_BITMASK); // based on 34-slot count (RoF+)
|
||||
const uint64 CORPSE_BITMASK = (GENERAL_BITMASK | CURSOR_BITMASK | (EQUIPMENT_BITMASK << 34)); // based on 34-slot count (RoF+)
|
||||
|
||||
|
||||
const char* GetInvPossessionsSlotName(int16 inv_slot);
|
||||
const char* GetInvCorpseSlotName(int16 inv_slot);
|
||||
@ -277,6 +281,7 @@ namespace SoF
|
||||
namespace constants {
|
||||
inline EQEmu::versions::ClientVersion GetConstantsRef() { return EQEmu::versions::ClientVersion::SoF; }
|
||||
|
||||
const EQEmu::expansions::Expansion EXPANSION = EQEmu::expansions::Expansion::SoF;
|
||||
const uint32 EXPANSION_BIT = EQEmu::expansions::bitSoF;
|
||||
const uint32 EXPANSIONS_MASK = EQEmu::expansions::maskSoF;
|
||||
|
||||
@ -284,14 +289,6 @@ namespace SoF
|
||||
|
||||
const size_t SAY_LINK_BODY_SIZE = 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 {
|
||||
@ -308,6 +305,41 @@ namespace SoF
|
||||
|
||||
} /*skills*/
|
||||
|
||||
namespace spells {
|
||||
inline EQEmu::versions::ClientVersion GetSkillsRef() { return EQEmu::versions::ClientVersion::SoF; }
|
||||
|
||||
enum class CastingSlot : uint32 {
|
||||
Gem1 = 0,
|
||||
Gem2 = 1,
|
||||
Gem3 = 2,
|
||||
Gem4 = 3,
|
||||
Gem5 = 4,
|
||||
Gem6 = 5,
|
||||
Gem7 = 6,
|
||||
Gem8 = 7,
|
||||
Gem9 = 8,
|
||||
MaxGems = 9,
|
||||
Ability = 9,
|
||||
Item = 10,
|
||||
Discipline = 10,
|
||||
PotionBelt = 11,
|
||||
AltAbility = 0xFF
|
||||
};
|
||||
|
||||
const int SPELL_ID_MAX = 15999;
|
||||
const int SPELLBOOK_SIZE = 480;
|
||||
const int SPELL_GEM_COUNT = static_cast<uint32>(CastingSlot::MaxGems);
|
||||
|
||||
const int LONG_BUFFS = 25;
|
||||
const int SHORT_BUFFS = 15;
|
||||
const int DISC_BUFFS = 1;
|
||||
const int TOTAL_BUFFS = LONG_BUFFS + SHORT_BUFFS + DISC_BUFFS;
|
||||
const int NPC_BUFFS = 60;
|
||||
const int PET_BUFFS = 30;
|
||||
const int MERC_BUFFS = 0;
|
||||
|
||||
} /*spells*/
|
||||
|
||||
}; /*SoF*/
|
||||
|
||||
#endif /*COMMON_SOF_LIMITS_H*/
|
||||
|
||||
@ -816,8 +816,7 @@ struct BindStruct {
|
||||
** OpCode: 0x006a
|
||||
*/
|
||||
static const uint32 MAX_PP_LANGUAGE = 25; //
|
||||
static const uint32 MAX_PP_SPELLBOOK = 480; // Confirmed 60 pages on Live now
|
||||
static const uint32 MAX_PP_MEMSPELL = 10; //was 9 now 10 on Live
|
||||
|
||||
static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size
|
||||
static const uint32 MAX_PP_INNATE_SKILL = 25;
|
||||
static const uint32 MAX_PP_AA_ARRAY = 300; //was 299
|
||||
@ -886,7 +885,7 @@ struct PlayerProfile_Struct //23576 Octets
|
||||
/*00060*/ BindStruct binds[5]; // Bind points (primary is first)
|
||||
/*00160*/ uint32 deity; // deity
|
||||
/*00164*/ uint32 intoxication; // Alcohol level (in ticks till sober?)
|
||||
/*00168*/ uint32 spellSlotRefresh[MAX_PP_MEMSPELL]; // Refresh time (millis) - 4 Octets Each
|
||||
/*00168*/ uint32 spellSlotRefresh[spells::SPELL_GEM_COUNT]; // Refresh time (millis) - 4 Octets Each
|
||||
/*00208*/ uint32 abilitySlotRefresh;
|
||||
/*00212*/ uint8 haircolor; // Player hair color
|
||||
/*00213*/ uint8 beardcolor; // Player beard color
|
||||
@ -911,9 +910,9 @@ struct PlayerProfile_Struct //23576 Octets
|
||||
/*04168*/ uint32 WIS; // Wisdom - 46 00 00 00 - 70
|
||||
/*04172*/ uint8 face; // Player face
|
||||
/*04173*/ uint8 unknown02264[147]; // was [139]
|
||||
/*04312*/ uint32 spell_book[MAX_PP_SPELLBOOK]; // List of the Spells in spellbook 480 = 60 pages
|
||||
/*04312*/ uint32 spell_book[spells::SPELLBOOK_SIZE]; // List of the Spells in spellbook 480 = 60 pages
|
||||
/*06232*/ uint8 unknown4184[128]; // was [136]
|
||||
/*06396*/ uint32 mem_spells[MAX_PP_MEMSPELL]; // List of spells memorized
|
||||
/*06396*/ uint32 mem_spells[spells::SPELL_GEM_COUNT]; // List of spells memorized
|
||||
/*06436*/ uint8 unknown04396[28]; //#### uint8 unknown04396[32]; in Titanium ####[28]
|
||||
/*06464*/ uint32 platinum; // Platinum Pieces on player
|
||||
/*06468*/ uint32 gold; // Gold Pieces on player
|
||||
@ -3769,7 +3768,7 @@ struct AnnoyingZoneUnknown_Struct {
|
||||
};
|
||||
|
||||
struct LoadSpellSet_Struct {
|
||||
uint32 spell[MAX_PP_MEMSPELL];
|
||||
uint32 spell[spells::SPELL_GEM_COUNT];
|
||||
uint32 unknown;
|
||||
};
|
||||
|
||||
|
||||
@ -58,8 +58,8 @@ namespace Titanium
|
||||
// client to server say link converter
|
||||
static inline void TitaniumToServerSayLink(std::string &server_saylink, const std::string &titanium_saylink);
|
||||
|
||||
static inline CastingSlot ServerToTitaniumCastingSlot(EQEmu::CastingSlot slot);
|
||||
static inline EQEmu::CastingSlot TitaniumToServerCastingSlot(CastingSlot slot, uint32 item_location);
|
||||
static inline spells::CastingSlot ServerToTitaniumCastingSlot(EQEmu::spells::CastingSlot slot);
|
||||
static inline EQEmu::spells::CastingSlot TitaniumToServerCastingSlot(spells::CastingSlot slot, uint32 item_location);
|
||||
|
||||
static inline int ServerToTitaniumBuffSlot(int index);
|
||||
static inline int TitaniumToServerBuffSlot(int index);
|
||||
@ -890,7 +890,7 @@ namespace Titanium
|
||||
|
||||
// Since HT/LoH are translated up, we need to translate down only for memSpellSpellbar case
|
||||
if (emu->scribing == 3)
|
||||
eq->slot = static_cast<uint32>(ServerToTitaniumCastingSlot(static_cast<EQEmu::CastingSlot>(emu->slot)));
|
||||
eq->slot = static_cast<uint32>(ServerToTitaniumCastingSlot(static_cast<EQEmu::spells::CastingSlot>(emu->slot)));
|
||||
else
|
||||
OUT(slot);
|
||||
OUT(spell_id);
|
||||
@ -981,7 +981,7 @@ namespace Titanium
|
||||
}
|
||||
OUT(deity);
|
||||
OUT(intoxication);
|
||||
OUT_array(spellSlotRefresh, structs::MAX_PP_MEMSPELL);
|
||||
OUT_array(spellSlotRefresh, spells::SPELL_GEM_COUNT);
|
||||
OUT(abilitySlotRefresh);
|
||||
OUT(haircolor);
|
||||
OUT(beardcolor);
|
||||
@ -1012,9 +1012,28 @@ namespace Titanium
|
||||
OUT(WIS);
|
||||
OUT(face);
|
||||
// OUT(unknown02264[47]);
|
||||
OUT_array(spell_book, structs::MAX_PP_SPELLBOOK);
|
||||
|
||||
if (spells::SPELLBOOK_SIZE <= EQEmu::spells::SPELLBOOK_SIZE) {
|
||||
for (uint32 r = 0; r < spells::SPELLBOOK_SIZE; r++) {
|
||||
if (emu->spell_book[r] <= spells::SPELL_ID_MAX)
|
||||
eq->spell_book[r] = emu->spell_book[r];
|
||||
else
|
||||
eq->spell_book[r] = 0xFFFFFFFFU;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (uint32 r = 0; r < EQEmu::spells::SPELLBOOK_SIZE; r++) {
|
||||
if (emu->spell_book[r] <= spells::SPELL_ID_MAX)
|
||||
eq->spell_book[r] = emu->spell_book[r];
|
||||
else
|
||||
eq->spell_book[r] = 0xFFFFFFFFU;
|
||||
}
|
||||
// invalidate the rest of the spellbook slots
|
||||
memset(&eq->spell_book[EQEmu::spells::SPELLBOOK_SIZE], 0xFF, (sizeof(uint32) * (spells::SPELLBOOK_SIZE - EQEmu::spells::SPELLBOOK_SIZE)));
|
||||
}
|
||||
|
||||
// OUT(unknown4184[448]);
|
||||
OUT_array(mem_spells, structs::MAX_PP_MEMSPELL);
|
||||
OUT_array(mem_spells, spells::SPELL_GEM_COUNT);
|
||||
// OUT(unknown04396[32]);
|
||||
OUT(platinum);
|
||||
OUT(gold);
|
||||
@ -1815,7 +1834,7 @@ namespace Titanium
|
||||
DECODE_LENGTH_EXACT(structs::CastSpell_Struct);
|
||||
SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct);
|
||||
|
||||
emu->slot = static_cast<uint32>(TitaniumToServerCastingSlot(static_cast<CastingSlot>(eq->slot), eq->inventoryslot));
|
||||
emu->slot = static_cast<uint32>(TitaniumToServerCastingSlot(static_cast<spells::CastingSlot>(eq->slot), eq->inventoryslot));
|
||||
IN(spell_id);
|
||||
emu->inventoryslot = TitaniumToServerSlot(eq->inventoryslot);
|
||||
IN(target_id);
|
||||
@ -2003,9 +2022,9 @@ namespace Titanium
|
||||
DECODE_LENGTH_EXACT(structs::LoadSpellSet_Struct);
|
||||
SETUP_DIRECT_DECODE(LoadSpellSet_Struct, structs::LoadSpellSet_Struct);
|
||||
|
||||
for (int i = 0; i < structs::MAX_PP_MEMSPELL; ++i)
|
||||
for (int i = 0; i < spells::SPELL_GEM_COUNT; ++i)
|
||||
IN(spell[i]);
|
||||
for (int i = structs::MAX_PP_MEMSPELL; i < MAX_PP_MEMSPELL; ++i)
|
||||
for (int i = spells::SPELL_GEM_COUNT; i < EQEmu::spells::SPELL_GEM_COUNT; ++i)
|
||||
emu->spell[i] = 0xFFFFFFFF;
|
||||
|
||||
IN(unknown);
|
||||
@ -2721,85 +2740,85 @@ namespace Titanium
|
||||
}
|
||||
}
|
||||
|
||||
static inline CastingSlot ServerToTitaniumCastingSlot(EQEmu::CastingSlot slot) {
|
||||
static inline spells::CastingSlot ServerToTitaniumCastingSlot(EQEmu::spells::CastingSlot slot) {
|
||||
switch (slot) {
|
||||
case EQEmu::CastingSlot::Gem1:
|
||||
return CastingSlot::Gem1;
|
||||
case EQEmu::CastingSlot::Gem2:
|
||||
return CastingSlot::Gem2;
|
||||
case EQEmu::CastingSlot::Gem3:
|
||||
return CastingSlot::Gem3;
|
||||
case EQEmu::CastingSlot::Gem4:
|
||||
return CastingSlot::Gem4;
|
||||
case EQEmu::CastingSlot::Gem5:
|
||||
return CastingSlot::Gem5;
|
||||
case EQEmu::CastingSlot::Gem6:
|
||||
return CastingSlot::Gem6;
|
||||
case EQEmu::CastingSlot::Gem7:
|
||||
return CastingSlot::Gem7;
|
||||
case EQEmu::CastingSlot::Gem8:
|
||||
return CastingSlot::Gem8;
|
||||
case EQEmu::CastingSlot::Gem9:
|
||||
return CastingSlot::Gem9;
|
||||
case EQEmu::CastingSlot::Item:
|
||||
return CastingSlot::Item;
|
||||
case EQEmu::CastingSlot::PotionBelt:
|
||||
return CastingSlot::PotionBelt;
|
||||
case EQEmu::CastingSlot::Discipline:
|
||||
return CastingSlot::Discipline;
|
||||
case EQEmu::CastingSlot::AltAbility:
|
||||
return CastingSlot::AltAbility;
|
||||
case EQEmu::spells::CastingSlot::Gem1:
|
||||
return spells::CastingSlot::Gem1;
|
||||
case EQEmu::spells::CastingSlot::Gem2:
|
||||
return spells::CastingSlot::Gem2;
|
||||
case EQEmu::spells::CastingSlot::Gem3:
|
||||
return spells::CastingSlot::Gem3;
|
||||
case EQEmu::spells::CastingSlot::Gem4:
|
||||
return spells::CastingSlot::Gem4;
|
||||
case EQEmu::spells::CastingSlot::Gem5:
|
||||
return spells::CastingSlot::Gem5;
|
||||
case EQEmu::spells::CastingSlot::Gem6:
|
||||
return spells::CastingSlot::Gem6;
|
||||
case EQEmu::spells::CastingSlot::Gem7:
|
||||
return spells::CastingSlot::Gem7;
|
||||
case EQEmu::spells::CastingSlot::Gem8:
|
||||
return spells::CastingSlot::Gem8;
|
||||
case EQEmu::spells::CastingSlot::Gem9:
|
||||
return spells::CastingSlot::Gem9;
|
||||
case EQEmu::spells::CastingSlot::Item:
|
||||
return spells::CastingSlot::Item;
|
||||
case EQEmu::spells::CastingSlot::PotionBelt:
|
||||
return spells::CastingSlot::PotionBelt;
|
||||
case EQEmu::spells::CastingSlot::Discipline:
|
||||
return spells::CastingSlot::Discipline;
|
||||
case EQEmu::spells::CastingSlot::AltAbility:
|
||||
return spells::CastingSlot::AltAbility;
|
||||
default: // we shouldn't have any issues with other slots ... just return something
|
||||
return CastingSlot::Discipline;
|
||||
return spells::CastingSlot::Discipline;
|
||||
}
|
||||
}
|
||||
|
||||
static inline EQEmu::CastingSlot TitaniumToServerCastingSlot(CastingSlot slot, uint32 item_location) {
|
||||
static inline EQEmu::spells::CastingSlot TitaniumToServerCastingSlot(spells::CastingSlot slot, uint32 item_location) {
|
||||
switch (slot) {
|
||||
case CastingSlot::Gem1:
|
||||
return EQEmu::CastingSlot::Gem1;
|
||||
case CastingSlot::Gem2:
|
||||
return EQEmu::CastingSlot::Gem2;
|
||||
case CastingSlot::Gem3:
|
||||
return EQEmu::CastingSlot::Gem3;
|
||||
case CastingSlot::Gem4:
|
||||
return EQEmu::CastingSlot::Gem4;
|
||||
case CastingSlot::Gem5:
|
||||
return EQEmu::CastingSlot::Gem5;
|
||||
case CastingSlot::Gem6:
|
||||
return EQEmu::CastingSlot::Gem6;
|
||||
case CastingSlot::Gem7:
|
||||
return EQEmu::CastingSlot::Gem7;
|
||||
case CastingSlot::Gem8:
|
||||
return EQEmu::CastingSlot::Gem8;
|
||||
case CastingSlot::Gem9:
|
||||
return EQEmu::CastingSlot::Gem9;
|
||||
case CastingSlot::Ability:
|
||||
return EQEmu::CastingSlot::Ability;
|
||||
case spells::CastingSlot::Gem1:
|
||||
return EQEmu::spells::CastingSlot::Gem1;
|
||||
case spells::CastingSlot::Gem2:
|
||||
return EQEmu::spells::CastingSlot::Gem2;
|
||||
case spells::CastingSlot::Gem3:
|
||||
return EQEmu::spells::CastingSlot::Gem3;
|
||||
case spells::CastingSlot::Gem4:
|
||||
return EQEmu::spells::CastingSlot::Gem4;
|
||||
case spells::CastingSlot::Gem5:
|
||||
return EQEmu::spells::CastingSlot::Gem5;
|
||||
case spells::CastingSlot::Gem6:
|
||||
return EQEmu::spells::CastingSlot::Gem6;
|
||||
case spells::CastingSlot::Gem7:
|
||||
return EQEmu::spells::CastingSlot::Gem7;
|
||||
case spells::CastingSlot::Gem8:
|
||||
return EQEmu::spells::CastingSlot::Gem8;
|
||||
case spells::CastingSlot::Gem9:
|
||||
return EQEmu::spells::CastingSlot::Gem9;
|
||||
case spells::CastingSlot::Ability:
|
||||
return EQEmu::spells::CastingSlot::Ability;
|
||||
// Tit uses 10 for item and discipline casting, but items have a valid location
|
||||
case CastingSlot::Item:
|
||||
case spells::CastingSlot::Item:
|
||||
if (item_location == INVALID_INDEX)
|
||||
return EQEmu::CastingSlot::Discipline;
|
||||
return EQEmu::spells::CastingSlot::Discipline;
|
||||
else
|
||||
return EQEmu::CastingSlot::Item;
|
||||
case CastingSlot::PotionBelt:
|
||||
return EQEmu::CastingSlot::PotionBelt;
|
||||
case CastingSlot::AltAbility:
|
||||
return EQEmu::CastingSlot::AltAbility;
|
||||
return EQEmu::spells::CastingSlot::Item;
|
||||
case spells::CastingSlot::PotionBelt:
|
||||
return EQEmu::spells::CastingSlot::PotionBelt;
|
||||
case spells::CastingSlot::AltAbility:
|
||||
return EQEmu::spells::CastingSlot::AltAbility;
|
||||
default: // we shouldn't have any issues with other slots ... just return something
|
||||
return EQEmu::CastingSlot::Discipline;
|
||||
return EQEmu::spells::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;
|
||||
if (index >= EQEmu::spells::LONG_BUFFS + EQEmu::spells::SHORT_BUFFS)
|
||||
return index - EQEmu::spells::LONG_BUFFS - EQEmu::spells::SHORT_BUFFS +
|
||||
spells::LONG_BUFFS + spells::SHORT_BUFFS;
|
||||
// we're a song
|
||||
if (index >= EQEmu::constants::LongBuffs)
|
||||
return index - EQEmu::constants::LongBuffs + constants::LongBuffs;
|
||||
if (index >= EQEmu::spells::LONG_BUFFS)
|
||||
return index - EQEmu::spells::LONG_BUFFS + spells::LONG_BUFFS;
|
||||
// we're a normal buff
|
||||
return index; // as long as we guard against bad slots server side, we should be fine
|
||||
}
|
||||
@ -2807,12 +2826,12 @@ namespace Titanium
|
||||
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;
|
||||
if (index >= spells::LONG_BUFFS + spells::SHORT_BUFFS)
|
||||
return index - spells::LONG_BUFFS - spells::SHORT_BUFFS + EQEmu::spells::LONG_BUFFS +
|
||||
EQEmu::spells::SHORT_BUFFS;
|
||||
// we're a song
|
||||
if (index >= constants::LongBuffs)
|
||||
return index - constants::LongBuffs + EQEmu::constants::LongBuffs;
|
||||
if (index >= spells::LONG_BUFFS)
|
||||
return index - spells::LONG_BUFFS + EQEmu::spells::LONG_BUFFS;
|
||||
// we're a normal buff
|
||||
return index; // as long as we guard against bad slots server side, we should be fine
|
||||
}
|
||||
|
||||
@ -50,23 +50,6 @@ namespace Titanium
|
||||
#include "titanium_ops.h"
|
||||
};
|
||||
|
||||
enum class CastingSlot : uint32 {
|
||||
Gem1 = 0,
|
||||
Gem2 = 1,
|
||||
Gem3 = 2,
|
||||
Gem4 = 3,
|
||||
Gem5 = 4,
|
||||
Gem6 = 5,
|
||||
Gem7 = 6,
|
||||
Gem8 = 7,
|
||||
Gem9 = 8,
|
||||
Ability = 9,
|
||||
Item = 10,
|
||||
Discipline = 10,
|
||||
PotionBelt = 11,
|
||||
AltAbility = 0xFF
|
||||
};
|
||||
|
||||
}; /*Titanium*/
|
||||
|
||||
#endif /*COMMON_TITANIUM_H*/
|
||||
|
||||
@ -190,8 +190,12 @@ namespace Titanium
|
||||
const int16 CORPSE_BEGIN = invslot::slotGeneral1;
|
||||
const int16 CORPSE_END = invslot::slotGeneral1 + invslot::slotCursor;
|
||||
|
||||
const uint64 POSSESSIONS_BITMASK = 0x000000027FDFFFFF; // based on 34-slot count (RoF+)
|
||||
const uint64 CORPSE_BITMASK = 0x017FFFFE7F800000; // based on 34-slot count (RoF+)
|
||||
const uint64 EQUIPMENT_BITMASK = 0x00000000005FFFFF;
|
||||
const uint64 GENERAL_BITMASK = 0x000000007F800000;
|
||||
const uint64 CURSOR_BITMASK = 0x0000000200000000;
|
||||
const uint64 POSSESSIONS_BITMASK = (EQUIPMENT_BITMASK | GENERAL_BITMASK | CURSOR_BITMASK); // based on 34-slot count (RoF+)
|
||||
const uint64 CORPSE_BITMASK = (GENERAL_BITMASK | CURSOR_BITMASK | (EQUIPMENT_BITMASK << 34)); // based on 34-slot count (RoF+)
|
||||
|
||||
|
||||
const char* GetInvPossessionsSlotName(int16 inv_slot);
|
||||
const char* GetInvCorpseSlotName(int16 inv_slot);
|
||||
@ -276,21 +280,14 @@ namespace Titanium
|
||||
namespace constants {
|
||||
inline EQEmu::versions::ClientVersion GetConstantsRef() { return EQEmu::versions::ClientVersion::Titanium; }
|
||||
|
||||
const uint32 EXPANSION_BIT = EQEmu::expansions::bitPoR;
|
||||
const uint32 EXPANSIONS_MASK = EQEmu::expansions::maskPoR;
|
||||
const EQEmu::expansions::Expansion EXPANSION = EQEmu::expansions::Expansion::DoD; // Someone had this as PoR in another section...
|
||||
const uint32 EXPANSION_BIT = EQEmu::expansions::bitDoD;
|
||||
const uint32 EXPANSIONS_MASK = EQEmu::expansions::maskDoD;
|
||||
|
||||
const size_t CHARACTER_CREATION_LIMIT = 8; // Hard-coded in client - DO NOT ALTER
|
||||
|
||||
const size_t SAY_LINK_BODY_SIZE = 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 {
|
||||
@ -307,6 +304,41 @@ namespace Titanium
|
||||
|
||||
} /*skills*/
|
||||
|
||||
namespace spells {
|
||||
inline EQEmu::versions::ClientVersion GetSkillsRef() { return EQEmu::versions::ClientVersion::Titanium; }
|
||||
|
||||
enum class CastingSlot : uint32 {
|
||||
Gem1 = 0,
|
||||
Gem2 = 1,
|
||||
Gem3 = 2,
|
||||
Gem4 = 3,
|
||||
Gem5 = 4,
|
||||
Gem6 = 5,
|
||||
Gem7 = 6,
|
||||
Gem8 = 7,
|
||||
Gem9 = 8,
|
||||
MaxGems = 9,
|
||||
Ability = 9,
|
||||
Item = 10,
|
||||
Discipline = 10,
|
||||
PotionBelt = 11,
|
||||
AltAbility = 0xFF
|
||||
};
|
||||
|
||||
const int SPELL_ID_MAX = 9999;
|
||||
const int SPELLBOOK_SIZE = 400;
|
||||
const int SPELL_GEM_COUNT = static_cast<uint32>(CastingSlot::MaxGems);
|
||||
|
||||
const int LONG_BUFFS = 25;
|
||||
const int SHORT_BUFFS = 12;
|
||||
const int DISC_BUFFS = 1;
|
||||
const int TOTAL_BUFFS = LONG_BUFFS + SHORT_BUFFS + DISC_BUFFS;
|
||||
const int NPC_BUFFS = 60;
|
||||
const int PET_BUFFS = 30;
|
||||
const int MERC_BUFFS = 0;
|
||||
|
||||
} /*spells*/
|
||||
|
||||
}; /*Titanium*/
|
||||
|
||||
#endif /*COMMON_TITANIUM_LIMITS_H*/
|
||||
|
||||
@ -754,8 +754,7 @@ struct BindStruct {
|
||||
** OpCode: 0x006a
|
||||
*/
|
||||
static const uint32 MAX_PP_LANGUAGE = 28;
|
||||
static const uint32 MAX_PP_SPELLBOOK = 400;
|
||||
static const uint32 MAX_PP_MEMSPELL = 9;
|
||||
|
||||
static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size
|
||||
static const uint32 MAX_PP_INNATE_SKILL = 25;
|
||||
static const uint32 MAX_PP_AA_ARRAY = 240;
|
||||
@ -824,7 +823,7 @@ struct PlayerProfile_Struct
|
||||
/*00024*/ BindStruct binds[5]; // Bind points (primary is first)
|
||||
/*00124*/ uint32 deity; // deity
|
||||
/*00128*/ uint32 intoxication; // Alcohol level (in ticks till sober?)
|
||||
/*00132*/ uint32 spellSlotRefresh[MAX_PP_MEMSPELL]; // Refresh time (millis)
|
||||
/*00132*/ uint32 spellSlotRefresh[spells::SPELL_GEM_COUNT]; // Refresh time (millis)
|
||||
/*00168*/ uint32 abilitySlotRefresh;
|
||||
/*00172*/ uint8 haircolor; // Player hair color
|
||||
/*00173*/ uint8 beardcolor; // Player beard color
|
||||
@ -849,9 +848,9 @@ struct PlayerProfile_Struct
|
||||
/*02260*/ uint32 WIS; // Wisdom
|
||||
/*02264*/ uint8 face; // Player face
|
||||
/*02265*/ uint8 unknown02264[47];
|
||||
/*02312*/ uint32 spell_book[MAX_PP_SPELLBOOK]; // List of the Spells in spellbook
|
||||
/*02312*/ uint32 spell_book[spells::SPELLBOOK_SIZE]; // List of the Spells in spellbook
|
||||
/*03912*/ uint8 unknown4184[448]; // all 0xff after last spell
|
||||
/*04360*/ uint32 mem_spells[MAX_PP_MEMSPELL]; // List of spells memorized
|
||||
/*04360*/ uint32 mem_spells[spells::SPELL_GEM_COUNT]; // List of spells memorized
|
||||
/*04396*/ uint8 unknown04396[32];
|
||||
/*04428*/ uint32 platinum; // Platinum Pieces on player
|
||||
/*04432*/ uint32 gold; // Gold Pieces on player
|
||||
@ -3271,7 +3270,7 @@ struct AnnoyingZoneUnknown_Struct {
|
||||
};
|
||||
|
||||
struct LoadSpellSet_Struct {
|
||||
uint32 spell[MAX_PP_MEMSPELL];
|
||||
uint32 spell[spells::SPELL_GEM_COUNT];
|
||||
uint32 unknown;
|
||||
};
|
||||
|
||||
|
||||
@ -59,8 +59,8 @@ namespace UF
|
||||
// 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);
|
||||
static inline spells::CastingSlot ServerToUFCastingSlot(EQEmu::spells::CastingSlot slot);
|
||||
static inline EQEmu::spells::CastingSlot UFToServerCastingSlot(spells::CastingSlot slot);
|
||||
|
||||
static inline int ServerToUFBuffSlot(int index);
|
||||
static inline int UFToServerBuffSlot(int index);
|
||||
@ -1682,7 +1682,7 @@ namespace UF
|
||||
}
|
||||
OUT(deity);
|
||||
OUT(intoxication);
|
||||
OUT_array(spellSlotRefresh, structs::MAX_PP_MEMSPELL);
|
||||
OUT_array(spellSlotRefresh, spells::SPELL_GEM_COUNT);
|
||||
OUT(abilitySlotRefresh);
|
||||
OUT(points); // Relocation Test
|
||||
// OUT(unknown0166[4]);
|
||||
@ -1724,10 +1724,28 @@ namespace UF
|
||||
OUT(WIS);
|
||||
OUT(face);
|
||||
// OUT(unknown02264[47]);
|
||||
memset(eq->spell_book, 0xFF, sizeof(uint32)* structs::MAX_PP_SPELLBOOK);
|
||||
OUT_array(spell_book, 480U);
|
||||
|
||||
if (spells::SPELLBOOK_SIZE <= EQEmu::spells::SPELLBOOK_SIZE) {
|
||||
for (uint32 r = 0; r < spells::SPELLBOOK_SIZE; r++) {
|
||||
if (emu->spell_book[r] <= spells::SPELL_ID_MAX)
|
||||
eq->spell_book[r] = emu->spell_book[r];
|
||||
else
|
||||
eq->spell_book[r] = 0xFFFFFFFFU;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (uint32 r = 0; r < EQEmu::spells::SPELLBOOK_SIZE; r++) {
|
||||
if (emu->spell_book[r] <= spells::SPELL_ID_MAX)
|
||||
eq->spell_book[r] = emu->spell_book[r];
|
||||
else
|
||||
eq->spell_book[r] = 0xFFFFFFFFU;
|
||||
}
|
||||
// invalidate the rest of the spellbook slots
|
||||
memset(&eq->spell_book[EQEmu::spells::SPELLBOOK_SIZE], 0xFF, (sizeof(uint32) * (spells::SPELLBOOK_SIZE - EQEmu::spells::SPELLBOOK_SIZE)));
|
||||
}
|
||||
|
||||
// OUT(unknown4184[128]);
|
||||
OUT_array(mem_spells, structs::MAX_PP_MEMSPELL);
|
||||
OUT_array(mem_spells, spells::SPELL_GEM_COUNT);
|
||||
// OUT(unknown04396[32]);
|
||||
OUT(platinum);
|
||||
OUT(gold);
|
||||
@ -3142,7 +3160,7 @@ namespace UF
|
||||
DECODE_LENGTH_EXACT(structs::CastSpell_Struct);
|
||||
SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct);
|
||||
|
||||
emu->slot = static_cast<uint32>(UFToServerCastingSlot(static_cast<CastingSlot>(eq->slot)));
|
||||
emu->slot = static_cast<uint32>(UFToServerCastingSlot(static_cast<spells::CastingSlot>(eq->slot)));
|
||||
|
||||
IN(spell_id);
|
||||
emu->inventoryslot = UFToServerSlot(eq->inventoryslot);
|
||||
@ -3491,7 +3509,7 @@ namespace UF
|
||||
DECODE_LENGTH_EXACT(structs::LoadSpellSet_Struct);
|
||||
SETUP_DIRECT_DECODE(LoadSpellSet_Struct, structs::LoadSpellSet_Struct);
|
||||
|
||||
for (unsigned int i = 0; i < MAX_PP_MEMSPELL; ++i)
|
||||
for (unsigned int i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; ++i)
|
||||
if (eq->spell[i] == 0)
|
||||
emu->spell[i] = 0xFFFFFFFF;
|
||||
else
|
||||
@ -4380,92 +4398,92 @@ namespace UF
|
||||
}
|
||||
}
|
||||
|
||||
static inline CastingSlot ServerToUFCastingSlot(EQEmu::CastingSlot slot)
|
||||
static inline spells::CastingSlot ServerToUFCastingSlot(EQEmu::spells::CastingSlot slot)
|
||||
{
|
||||
switch (slot) {
|
||||
case EQEmu::CastingSlot::Gem1:
|
||||
return CastingSlot::Gem1;
|
||||
case EQEmu::CastingSlot::Gem2:
|
||||
return CastingSlot::Gem2;
|
||||
case EQEmu::CastingSlot::Gem3:
|
||||
return CastingSlot::Gem3;
|
||||
case EQEmu::CastingSlot::Gem4:
|
||||
return CastingSlot::Gem4;
|
||||
case EQEmu::CastingSlot::Gem5:
|
||||
return CastingSlot::Gem5;
|
||||
case EQEmu::CastingSlot::Gem6:
|
||||
return CastingSlot::Gem6;
|
||||
case EQEmu::CastingSlot::Gem7:
|
||||
return CastingSlot::Gem7;
|
||||
case EQEmu::CastingSlot::Gem8:
|
||||
return CastingSlot::Gem8;
|
||||
case EQEmu::CastingSlot::Gem9:
|
||||
return CastingSlot::Gem9;
|
||||
case EQEmu::CastingSlot::Gem10:
|
||||
return CastingSlot::Gem10;
|
||||
case EQEmu::CastingSlot::Gem11:
|
||||
return CastingSlot::Gem11;
|
||||
case EQEmu::CastingSlot::Gem12:
|
||||
return CastingSlot::Gem12;
|
||||
case EQEmu::CastingSlot::Item:
|
||||
case EQEmu::CastingSlot::PotionBelt:
|
||||
return CastingSlot::Item;
|
||||
case EQEmu::CastingSlot::Discipline:
|
||||
return CastingSlot::Discipline;
|
||||
case EQEmu::CastingSlot::AltAbility:
|
||||
return CastingSlot::AltAbility;
|
||||
case EQEmu::spells::CastingSlot::Gem1:
|
||||
return spells::CastingSlot::Gem1;
|
||||
case EQEmu::spells::CastingSlot::Gem2:
|
||||
return spells::CastingSlot::Gem2;
|
||||
case EQEmu::spells::CastingSlot::Gem3:
|
||||
return spells::CastingSlot::Gem3;
|
||||
case EQEmu::spells::CastingSlot::Gem4:
|
||||
return spells::CastingSlot::Gem4;
|
||||
case EQEmu::spells::CastingSlot::Gem5:
|
||||
return spells::CastingSlot::Gem5;
|
||||
case EQEmu::spells::CastingSlot::Gem6:
|
||||
return spells::CastingSlot::Gem6;
|
||||
case EQEmu::spells::CastingSlot::Gem7:
|
||||
return spells::CastingSlot::Gem7;
|
||||
case EQEmu::spells::CastingSlot::Gem8:
|
||||
return spells::CastingSlot::Gem8;
|
||||
case EQEmu::spells::CastingSlot::Gem9:
|
||||
return spells::CastingSlot::Gem9;
|
||||
case EQEmu::spells::CastingSlot::Gem10:
|
||||
return spells::CastingSlot::Gem10;
|
||||
case EQEmu::spells::CastingSlot::Gem11:
|
||||
return spells::CastingSlot::Gem11;
|
||||
case EQEmu::spells::CastingSlot::Gem12:
|
||||
return spells::CastingSlot::Gem12;
|
||||
case EQEmu::spells::CastingSlot::Item:
|
||||
case EQEmu::spells::CastingSlot::PotionBelt:
|
||||
return spells::CastingSlot::Item;
|
||||
case EQEmu::spells::CastingSlot::Discipline:
|
||||
return spells::CastingSlot::Discipline;
|
||||
case EQEmu::spells::CastingSlot::AltAbility:
|
||||
return spells::CastingSlot::AltAbility;
|
||||
default: // we shouldn't have any issues with other slots ... just return something
|
||||
return CastingSlot::Discipline;
|
||||
return spells::CastingSlot::Discipline;
|
||||
}
|
||||
}
|
||||
|
||||
static inline EQEmu::CastingSlot UFToServerCastingSlot(CastingSlot slot)
|
||||
static inline EQEmu::spells::CastingSlot UFToServerCastingSlot(spells::CastingSlot slot)
|
||||
{
|
||||
switch (slot) {
|
||||
case CastingSlot::Gem1:
|
||||
return EQEmu::CastingSlot::Gem1;
|
||||
case CastingSlot::Gem2:
|
||||
return EQEmu::CastingSlot::Gem2;
|
||||
case CastingSlot::Gem3:
|
||||
return EQEmu::CastingSlot::Gem3;
|
||||
case CastingSlot::Gem4:
|
||||
return EQEmu::CastingSlot::Gem4;
|
||||
case CastingSlot::Gem5:
|
||||
return EQEmu::CastingSlot::Gem5;
|
||||
case CastingSlot::Gem6:
|
||||
return EQEmu::CastingSlot::Gem6;
|
||||
case CastingSlot::Gem7:
|
||||
return EQEmu::CastingSlot::Gem7;
|
||||
case CastingSlot::Gem8:
|
||||
return EQEmu::CastingSlot::Gem8;
|
||||
case CastingSlot::Gem9:
|
||||
return EQEmu::CastingSlot::Gem9;
|
||||
case CastingSlot::Gem10:
|
||||
return EQEmu::CastingSlot::Gem10;
|
||||
case CastingSlot::Gem11:
|
||||
return EQEmu::CastingSlot::Gem11;
|
||||
case CastingSlot::Gem12:
|
||||
return EQEmu::CastingSlot::Gem12;
|
||||
case CastingSlot::Discipline:
|
||||
return EQEmu::CastingSlot::Discipline;
|
||||
case CastingSlot::Item:
|
||||
return EQEmu::CastingSlot::Item;
|
||||
case CastingSlot::AltAbility:
|
||||
return EQEmu::CastingSlot::AltAbility;
|
||||
case spells::CastingSlot::Gem1:
|
||||
return EQEmu::spells::CastingSlot::Gem1;
|
||||
case spells::CastingSlot::Gem2:
|
||||
return EQEmu::spells::CastingSlot::Gem2;
|
||||
case spells::CastingSlot::Gem3:
|
||||
return EQEmu::spells::CastingSlot::Gem3;
|
||||
case spells::CastingSlot::Gem4:
|
||||
return EQEmu::spells::CastingSlot::Gem4;
|
||||
case spells::CastingSlot::Gem5:
|
||||
return EQEmu::spells::CastingSlot::Gem5;
|
||||
case spells::CastingSlot::Gem6:
|
||||
return EQEmu::spells::CastingSlot::Gem6;
|
||||
case spells::CastingSlot::Gem7:
|
||||
return EQEmu::spells::CastingSlot::Gem7;
|
||||
case spells::CastingSlot::Gem8:
|
||||
return EQEmu::spells::CastingSlot::Gem8;
|
||||
case spells::CastingSlot::Gem9:
|
||||
return EQEmu::spells::CastingSlot::Gem9;
|
||||
case spells::CastingSlot::Gem10:
|
||||
return EQEmu::spells::CastingSlot::Gem10;
|
||||
case spells::CastingSlot::Gem11:
|
||||
return EQEmu::spells::CastingSlot::Gem11;
|
||||
case spells::CastingSlot::Gem12:
|
||||
return EQEmu::spells::CastingSlot::Gem12;
|
||||
case spells::CastingSlot::Discipline:
|
||||
return EQEmu::spells::CastingSlot::Discipline;
|
||||
case spells::CastingSlot::Item:
|
||||
return EQEmu::spells::CastingSlot::Item;
|
||||
case spells::CastingSlot::AltAbility:
|
||||
return EQEmu::spells::CastingSlot::AltAbility;
|
||||
default: // we shouldn't have any issues with other slots ... just return something
|
||||
return EQEmu::CastingSlot::Discipline;
|
||||
return EQEmu::spells::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;
|
||||
if (index >= EQEmu::spells::LONG_BUFFS + EQEmu::spells::SHORT_BUFFS)
|
||||
return index - EQEmu::spells::LONG_BUFFS - EQEmu::spells::SHORT_BUFFS +
|
||||
spells::LONG_BUFFS + spells::SHORT_BUFFS;
|
||||
// we're a song
|
||||
if (index >= EQEmu::constants::LongBuffs)
|
||||
return index - EQEmu::constants::LongBuffs + constants::LongBuffs;
|
||||
if (index >= EQEmu::spells::LONG_BUFFS)
|
||||
return index - EQEmu::spells::LONG_BUFFS + spells::LONG_BUFFS;
|
||||
// we're a normal buff
|
||||
return index; // as long as we guard against bad slots server side, we should be fine
|
||||
}
|
||||
@ -4473,12 +4491,12 @@ namespace UF
|
||||
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;
|
||||
if (index >= spells::LONG_BUFFS + spells::SHORT_BUFFS)
|
||||
return index - spells::LONG_BUFFS - spells::SHORT_BUFFS + EQEmu::spells::LONG_BUFFS +
|
||||
EQEmu::spells::SHORT_BUFFS;
|
||||
// we're a song
|
||||
if (index >= constants::LongBuffs)
|
||||
return index - constants::LongBuffs + EQEmu::constants::LongBuffs;
|
||||
if (index >= spells::LONG_BUFFS)
|
||||
return index - spells::LONG_BUFFS + EQEmu::spells::LONG_BUFFS;
|
||||
// we're a normal buff
|
||||
return index; // as long as we guard against bad slots server side, we should be fine
|
||||
}
|
||||
|
||||
@ -50,24 +50,6 @@ namespace UF
|
||||
#include "uf_ops.h"
|
||||
};
|
||||
|
||||
enum class CastingSlot : uint32 {
|
||||
Gem1 = 0,
|
||||
Gem2 = 1,
|
||||
Gem3 = 2,
|
||||
Gem4 = 3,
|
||||
Gem5 = 4,
|
||||
Gem6 = 5,
|
||||
Gem7 = 6,
|
||||
Gem8 = 7,
|
||||
Gem9 = 8,
|
||||
Gem10 = 9,
|
||||
Gem11 = 10,
|
||||
Gem12 = 11,
|
||||
Item = 12,
|
||||
Discipline = 13,
|
||||
AltAbility = 0xFF
|
||||
};
|
||||
|
||||
}; /*UF*/
|
||||
|
||||
#endif /*COMMON_UF_H*/
|
||||
|
||||
@ -191,8 +191,12 @@ namespace UF
|
||||
const int16 CORPSE_BEGIN = invslot::slotGeneral1;
|
||||
const int16 CORPSE_END = invslot::slotGeneral1 + invslot::slotCursor;
|
||||
|
||||
const uint64 POSSESSIONS_BITMASK = 0x000000027FFFFFFF; // based on 34-slot count (RoF+)
|
||||
const uint64 CORPSE_BITMASK = 0x01FFFFFE7F800000; // based on 34-slot count (RoF+)
|
||||
const uint64 EQUIPMENT_BITMASK = 0x00000000007FFFFF;
|
||||
const uint64 GENERAL_BITMASK = 0x000000007F800000;
|
||||
const uint64 CURSOR_BITMASK = 0x0000000200000000;
|
||||
const uint64 POSSESSIONS_BITMASK = (EQUIPMENT_BITMASK | GENERAL_BITMASK | CURSOR_BITMASK); // based on 34-slot count (RoF+)
|
||||
const uint64 CORPSE_BITMASK = (GENERAL_BITMASK | CURSOR_BITMASK | (EQUIPMENT_BITMASK << 34)); // based on 34-slot count (RoF+)
|
||||
|
||||
|
||||
const char* GetInvPossessionsSlotName(int16 inv_slot);
|
||||
const char* GetInvCorpseSlotName(int16 inv_slot);
|
||||
@ -278,6 +282,7 @@ namespace UF
|
||||
namespace constants {
|
||||
inline EQEmu::versions::ClientVersion GetConstantsRef() { return EQEmu::versions::ClientVersion::UF; }
|
||||
|
||||
const EQEmu::expansions::Expansion EXPANSION = EQEmu::expansions::Expansion::UF;
|
||||
const uint32 EXPANSION_BIT = EQEmu::expansions::bitUF;
|
||||
const uint32 EXPANSIONS_MASK = EQEmu::expansions::maskUF;
|
||||
|
||||
@ -285,14 +290,6 @@ namespace UF
|
||||
|
||||
const size_t SAY_LINK_BODY_SIZE = 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 {
|
||||
@ -309,6 +306,42 @@ namespace UF
|
||||
|
||||
} /*skills*/
|
||||
|
||||
namespace spells {
|
||||
inline EQEmu::versions::ClientVersion GetSkillsRef() { return EQEmu::versions::ClientVersion::UF; }
|
||||
|
||||
enum class CastingSlot : uint32 {
|
||||
Gem1 = 0,
|
||||
Gem2 = 1,
|
||||
Gem3 = 2,
|
||||
Gem4 = 3,
|
||||
Gem5 = 4,
|
||||
Gem6 = 5,
|
||||
Gem7 = 6,
|
||||
Gem8 = 7,
|
||||
Gem9 = 8,
|
||||
Gem10 = 9,
|
||||
Gem11 = 10,
|
||||
Gem12 = 11,
|
||||
MaxGems = 12,
|
||||
Item = 12,
|
||||
Discipline = 13,
|
||||
AltAbility = 0xFF
|
||||
};
|
||||
|
||||
const int SPELL_ID_MAX = 28000;
|
||||
const int SPELLBOOK_SIZE = 720;
|
||||
const int SPELL_GEM_COUNT = static_cast<uint32>(CastingSlot::MaxGems);
|
||||
|
||||
const int LONG_BUFFS = 30;
|
||||
const int SHORT_BUFFS = 20;
|
||||
const int DISC_BUFFS = 1;
|
||||
const int TOTAL_BUFFS = LONG_BUFFS + SHORT_BUFFS + DISC_BUFFS;
|
||||
const int NPC_BUFFS = 85;
|
||||
const int PET_BUFFS = NPC_BUFFS;
|
||||
const int MERC_BUFFS = LONG_BUFFS;
|
||||
|
||||
} /*spells*/
|
||||
|
||||
}; /*UF*/
|
||||
|
||||
#endif /*COMMON_UF_LIMITS_H*/
|
||||
|
||||
@ -845,8 +845,7 @@ struct BindStruct {
|
||||
** OpCode: 0x006a
|
||||
*/
|
||||
static const uint32 MAX_PP_LANGUAGE = 25; //
|
||||
static const uint32 MAX_PP_SPELLBOOK = 720; // Confirmed 60 pages on Underfoot now
|
||||
static const uint32 MAX_PP_MEMSPELL = 12; //was 9 now 10 on Underfoot
|
||||
|
||||
static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size
|
||||
static const uint32 MAX_PP_INNATE_SKILL = 25;
|
||||
static const uint32 MAX_PP_AA_ARRAY = 300; //was 299
|
||||
@ -916,7 +915,7 @@ struct PlayerProfile_Struct
|
||||
/*00060*/ BindStruct binds[5]; // Bind points (primary is first)
|
||||
/*00160*/ uint32 deity; // deity
|
||||
/*00164*/ uint32 intoxication; // Alcohol level (in ticks till sober?)
|
||||
/*00168*/ uint32 spellSlotRefresh[MAX_PP_MEMSPELL]; // Refresh time (millis) - 4 Octets Each
|
||||
/*00168*/ uint32 spellSlotRefresh[spells::SPELL_GEM_COUNT]; // Refresh time (millis) - 4 Octets Each
|
||||
/*00208*/ uint8 unknown00208[6]; // Seen 00 00 00 00 00 00 00 00 00 00 00 00 02 01
|
||||
/*00222*/ uint32 abilitySlotRefresh;
|
||||
/*00226*/ uint8 haircolor; // Player hair color
|
||||
@ -943,8 +942,8 @@ struct PlayerProfile_Struct
|
||||
/*04188*/ uint8 unknown04188[28]; //
|
||||
/*04216*/ uint8 face; // Player face - Actually uint32?
|
||||
/*04217*/ uint8 unknown04217[147]; // was [175]
|
||||
/*04364*/ uint32 spell_book[MAX_PP_SPELLBOOK]; // List of the Spells in spellbook 720 = 90 pages [2880] was [1920]
|
||||
/*07244*/ uint32 mem_spells[MAX_PP_MEMSPELL]; // List of spells memorized
|
||||
/*04364*/ uint32 spell_book[spells::SPELLBOOK_SIZE]; // List of the Spells in spellbook 720 = 90 pages [2880] was [1920]
|
||||
/*07244*/ uint32 mem_spells[spells::SPELL_GEM_COUNT]; // List of spells memorized
|
||||
/*07284*/ uint8 unknown07284[20]; //#### uint8 unknown04396[32]; in Titanium ####[28]
|
||||
/*07312*/ uint32 platinum; // Platinum Pieces on player
|
||||
/*07316*/ uint32 gold; // Gold Pieces on player
|
||||
@ -3907,7 +3906,7 @@ struct AnnoyingZoneUnknown_Struct {
|
||||
};
|
||||
|
||||
struct LoadSpellSet_Struct {
|
||||
uint8 spell[MAX_PP_MEMSPELL]; // 0 if no action
|
||||
uint8 spell[spells::SPELL_GEM_COUNT]; // 0 if no action
|
||||
uint32 unknown; // there seems to be an extra field in this packet...
|
||||
};
|
||||
|
||||
|
||||
@ -61,7 +61,7 @@ RuleManager::RuleManager()
|
||||
: m_activeRuleset(0),
|
||||
m_activeName("default")
|
||||
{
|
||||
ResetRules();
|
||||
ResetRules(false);
|
||||
}
|
||||
|
||||
RuleManager::CategoryType RuleManager::FindCategory(const char *catname) {
|
||||
@ -126,7 +126,7 @@ bool RuleManager::GetRule(const char *rule_name, std::string &return_value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Database *database, bool db_save) {
|
||||
bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Database *database, bool db_save, bool reload) {
|
||||
if(rule_name == nullptr || rule_value == nullptr)
|
||||
return(false);
|
||||
|
||||
@ -135,6 +135,13 @@ bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Databas
|
||||
if(!_FindRule(rule_name, type, index))
|
||||
return(false);
|
||||
|
||||
if (reload) {
|
||||
if (strcasecmp(rule_name, "World:ExpansionSettings") == 0)
|
||||
return(false);
|
||||
if (strcasecmp(rule_name, "World:UseClientBasedExpansionSettings") == 0)
|
||||
return(false);
|
||||
}
|
||||
|
||||
switch(type) {
|
||||
case IntRule:
|
||||
m_RuleIntValues[index] = atoi(rule_value);
|
||||
@ -160,7 +167,16 @@ bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Databas
|
||||
return(true);
|
||||
}
|
||||
|
||||
void RuleManager::ResetRules() {
|
||||
void RuleManager::ResetRules(bool reload) {
|
||||
std::string expansion1;
|
||||
std::string expansion2;
|
||||
|
||||
// these rules must not change during server runtime
|
||||
if (reload) {
|
||||
GetRule("World:ExpansionSettings", expansion1);
|
||||
GetRule("World:UseClientBasedExpansionSettings", expansion2);
|
||||
}
|
||||
|
||||
Log(Logs::Detail, Logs::Rules, "Resetting running rules to default values");
|
||||
#define RULE_INT(cat, rule, default_value) \
|
||||
m_RuleIntValues[ Int__##rule ] = default_value;
|
||||
@ -169,6 +185,12 @@ void RuleManager::ResetRules() {
|
||||
#define RULE_BOOL(cat, rule, default_value) \
|
||||
m_RuleBoolValues[ Bool__##rule ] = default_value;
|
||||
#include "ruletypes.h"
|
||||
|
||||
// restore these rules to their pre-reset values
|
||||
if (reload) {
|
||||
SetRule("World:ExpansionSettings", expansion1.c_str(), nullptr, false, false);
|
||||
SetRule("World:UseClientBasedExpansionSettings", expansion2.c_str(), nullptr, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
bool RuleManager::_FindRule(const char *rule_name, RuleType &type_into, uint16 &index_into) {
|
||||
@ -235,7 +257,7 @@ void RuleManager::SaveRules(Database *database, const char *ruleset_name) {
|
||||
}
|
||||
}
|
||||
|
||||
bool RuleManager::LoadRules(Database *database, const char *ruleset_name) {
|
||||
bool RuleManager::LoadRules(Database *database, const char *ruleset_name, bool reload) {
|
||||
|
||||
int ruleset_id = this->GetRulesetID(database, ruleset_name);
|
||||
if (ruleset_id < 0) {
|
||||
@ -269,7 +291,7 @@ bool RuleManager::LoadRules(Database *database, const char *ruleset_name) {
|
||||
return false;
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
if (!SetRule(row[0], row[1], nullptr, false))
|
||||
if (!SetRule(row[0], row[1], nullptr, false, reload))
|
||||
Log(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]);
|
||||
}
|
||||
|
||||
@ -279,7 +301,7 @@ bool RuleManager::LoadRules(Database *database, const char *ruleset_name) {
|
||||
return false;
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
if (!SetRule(row[0], row[1], nullptr, false))
|
||||
if (!SetRule(row[0], row[1], nullptr, false, reload))
|
||||
Log(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]);
|
||||
|
||||
return true;
|
||||
@ -288,6 +310,11 @@ bool RuleManager::LoadRules(Database *database, const char *ruleset_name) {
|
||||
void RuleManager::_SaveRule(Database *database, RuleType type, uint16 index) {
|
||||
char value_string[100];
|
||||
|
||||
if (type == IntRule && strcasecmp(_GetRuleName(type, index), "World:ExpansionSettings") == 0)
|
||||
return;
|
||||
if (type == BoolRule && strcasecmp(_GetRuleName(type, index), "World:UseClientBasedExpansionSettings") == 0)
|
||||
return;
|
||||
|
||||
switch (type) {
|
||||
case IntRule:
|
||||
sprintf(value_string, "%d", m_RuleIntValues[index]);
|
||||
|
||||
@ -102,7 +102,7 @@ public:
|
||||
bool ListRules(const char *catname, std::vector<const char *> &into);
|
||||
bool ListCategories(std::vector<const char *> &into);
|
||||
bool GetRule(const char *rule_name, std::string &ret_val);
|
||||
bool SetRule(const char *rule_name, const char *rule_value, Database *db = nullptr, bool db_save = false);
|
||||
bool SetRule(const char *rule_name, const char *rule_value, Database *db = nullptr, bool db_save = false, bool reload = false);
|
||||
|
||||
int GetActiveRulesetID() const { return(m_activeRuleset); }
|
||||
const char *GetActiveRuleset() const { return(m_activeName.c_str()); }
|
||||
@ -110,8 +110,8 @@ public:
|
||||
static std::string GetRulesetName(Database *db, int id);
|
||||
static bool ListRulesets(Database *db, std::map<int, std::string> &into);
|
||||
|
||||
void ResetRules();
|
||||
bool LoadRules(Database *db, const char *ruleset = nullptr);
|
||||
void ResetRules(bool reload = false);
|
||||
bool LoadRules(Database *db, const char *ruleset = nullptr, bool reload = false);
|
||||
void SaveRules(Database *db, const char *ruleset = nullptr);
|
||||
|
||||
private:
|
||||
|
||||
@ -720,9 +720,12 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQEmu::InventoryProfile *inv)
|
||||
if (cv_conflict) {
|
||||
char char_name[64] = "";
|
||||
GetCharName(char_id, char_name);
|
||||
Log(Logs::Moderate, Logs::Client_Login,
|
||||
"ClientVersion conflict during inventory load at zone entry for '%s' (charid: %u, inver: %s)",
|
||||
char_name, char_id, EQEmu::versions::MobVersionName(inv->InventoryVersion())
|
||||
Log(Logs::General, Logs::Error,
|
||||
"ClientVersion/Expansion conflict during inventory load at zone entry for '%s' (charid: %u, inver: %s, gmi: %s)",
|
||||
char_name,
|
||||
char_id,
|
||||
EQEmu::versions::MobVersionName(inv->InventoryVersion()),
|
||||
(inv->GMInventory() ? "true" : "false")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||
*/
|
||||
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9134
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9135
|
||||
#ifdef BOTS
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9021
|
||||
#else
|
||||
|
||||
@ -102,19 +102,23 @@ int main() {
|
||||
|
||||
char tmp[64];
|
||||
|
||||
// ucs has no 'reload rules' handler
|
||||
if (database.GetVariable("RuleSet", tmp, sizeof(tmp)-1)) {
|
||||
Log(Logs::General, Logs::UCS_Server, "Loading rule set '%s'", tmp);
|
||||
if(!RuleManager::Instance()->LoadRules(&database, tmp)) {
|
||||
if(!RuleManager::Instance()->LoadRules(&database, tmp, false)) {
|
||||
Log(Logs::General, Logs::UCS_Server, "Failed to load ruleset '%s', falling back to defaults.", tmp);
|
||||
}
|
||||
} else {
|
||||
if(!RuleManager::Instance()->LoadRules(&database, "default")) {
|
||||
if(!RuleManager::Instance()->LoadRules(&database, "default", false)) {
|
||||
Log(Logs::General, Logs::UCS_Server, "No rule set configured, using default rules");
|
||||
} else {
|
||||
Log(Logs::General, Logs::UCS_Server, "Loaded default rule set 'default'", tmp);
|
||||
}
|
||||
}
|
||||
|
||||
EQEmu::InitializeDynamicLookups();
|
||||
Log(Logs::General, Logs::UCS_Server, "Initialized dynamic dictionary entries");
|
||||
|
||||
database.ExpireMail();
|
||||
|
||||
if(Config->ChatPort != Config->MailPort)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -388,6 +388,7 @@
|
||||
9132|2018_12_16_global_base_scaling.sql|SHOW TABLES LIKE 'npc_scale_global_base'|empty|
|
||||
9133|2018_11_25_StuckBehavior.sql|SHOW COLUMNS FROM `npc_types` LIKE 'stuck_behavior'|empty|
|
||||
9134|2019_01_04_update_global_base_scaling.sql|SELECT * FROM db_version WHERE version >= 9134|empty|
|
||||
9135|2019_01_10_multi_version_spawns.sql|SHOW COLUMNS FROM `spawn2` LIKE 'version'|contains|unsigned|
|
||||
|
||||
# Upgrade conditions:
|
||||
# This won't be needed after this system is implemented, but it is used database that are not
|
||||
|
||||
@ -0,0 +1 @@
|
||||
ALTER TABLE `spawn2` MODIFY `version` SMALLINT(5) SIGNED NOT NULL DEFAULT '0';
|
||||
@ -171,10 +171,13 @@ void Client::SendEnterWorld(std::string name)
|
||||
void Client::SendExpansionInfo() {
|
||||
auto outapp = new EQApplicationPacket(OP_ExpansionInfo, sizeof(ExpansionInfo_Struct));
|
||||
ExpansionInfo_Struct *eis = (ExpansionInfo_Struct*)outapp->pBuffer;
|
||||
if(RuleB(World, UseClientBasedExpansionSettings)) {
|
||||
|
||||
// need to rework .. not until full scope of change is accounted for, though
|
||||
if (RuleB(World, UseClientBasedExpansionSettings)) {
|
||||
eis->Expansions = EQEmu::expansions::ConvertClientVersionToExpansionMask(eqs->ClientVersion());
|
||||
} else {
|
||||
eis->Expansions = (RuleI(World, ExpansionSettings));
|
||||
}
|
||||
else {
|
||||
eis->Expansions = RuleI(World, ExpansionSettings);
|
||||
}
|
||||
|
||||
QueuePacket(outapp);
|
||||
@ -211,7 +214,7 @@ void Client::SendMaxCharCreate() {
|
||||
auto outapp = new EQApplicationPacket(OP_SendMaxCharacters, sizeof(MaxCharacters_Struct));
|
||||
MaxCharacters_Struct* mc = (MaxCharacters_Struct*)outapp->pBuffer;
|
||||
|
||||
mc->max_chars = EQEmu::constants::Lookup(m_ClientVersion)->CharacterCreationLimit;
|
||||
mc->max_chars = EQEmu::constants::StaticLookup(m_ClientVersion)->CharacterCreationLimit;
|
||||
if (mc->max_chars > EQEmu::constants::CHARACTER_CREATION_LIMIT)
|
||||
mc->max_chars = EQEmu::constants::CHARACTER_CREATION_LIMIT;
|
||||
|
||||
@ -765,7 +768,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
// This can probably be moved outside and have another method return requested info (don't forget to remove the #include "../common/shareddb.h" above)
|
||||
// (This is a literal translation of the original process..I don't see why it can't be changed to a single-target query over account iteration)
|
||||
if (!is_player_zoning) {
|
||||
size_t character_limit = EQEmu::constants::Lookup(eqs->ClientVersion())->CharacterCreationLimit;
|
||||
size_t character_limit = EQEmu::constants::StaticLookup(eqs->ClientVersion())->CharacterCreationLimit;
|
||||
if (character_limit > EQEmu::constants::CHARACTER_CREATION_LIMIT) { character_limit = EQEmu::constants::CHARACTER_CREATION_LIMIT; }
|
||||
if (eqs->ClientVersion() == EQEmu::versions::ClientVersion::Titanium) { character_limit = Titanium::constants::CHARACTER_CREATION_LIMIT; }
|
||||
|
||||
@ -1442,7 +1445,11 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
|
||||
PlayerProfile_Struct pp;
|
||||
ExtendedProfile_Struct ext;
|
||||
EQEmu::InventoryProfile inv;
|
||||
|
||||
pp.SetPlayerProfileVersion(EQEmu::versions::ConvertClientVersionToMobVersion(EQEmu::versions::ConvertClientVersionBitToClientVersion(m_ClientVersionBit)));
|
||||
inv.SetInventoryVersion(EQEmu::versions::ConvertClientVersionBitToClientVersion(m_ClientVersionBit));
|
||||
inv.SetGMInventory(false); // character cannot have gm flag at this point
|
||||
|
||||
time_t bday = time(nullptr);
|
||||
char startzone[50]={0};
|
||||
uint32 i;
|
||||
@ -1522,12 +1529,9 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
|
||||
|
||||
// strcpy(pp.servername, WorldConfig::get()->ShortName.c_str());
|
||||
|
||||
|
||||
for (i = 0; i < MAX_PP_REF_SPELLBOOK; i++)
|
||||
pp.spell_book[i] = 0xFFFFFFFF;
|
||||
|
||||
for(i = 0; i < MAX_PP_MEMSPELL; i++)
|
||||
pp.mem_spells[i] = 0xFFFFFFFF;
|
||||
memset(pp.spell_book, 0xFF, (sizeof(uint32) * EQEmu::spells::SPELLBOOK_SIZE));
|
||||
|
||||
memset(pp.mem_spells, 0xFF, (sizeof(uint32) * EQEmu::spells::SPELL_GEM_COUNT));
|
||||
|
||||
for(i = 0; i < BUFF_COUNT; i++)
|
||||
pp.buffs[i].spellid = 0xFFFF;
|
||||
|
||||
@ -336,18 +336,21 @@ int main(int argc, char** argv) {
|
||||
std::string tmp;
|
||||
if (database.GetVariable("RuleSet", tmp)) {
|
||||
Log(Logs::General, Logs::World_Server, "Loading rule set '%s'", tmp.c_str());
|
||||
if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str())) {
|
||||
if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str(), false)) {
|
||||
Log(Logs::General, Logs::World_Server, "Failed to load ruleset '%s', falling back to defaults.", tmp.c_str());
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!RuleManager::Instance()->LoadRules(&database, "default")) {
|
||||
if (!RuleManager::Instance()->LoadRules(&database, "default", false)) {
|
||||
Log(Logs::General, Logs::World_Server, "No rule set configured, using default rules");
|
||||
}
|
||||
else {
|
||||
Log(Logs::General, Logs::World_Server, "Loaded default rule set 'default'", tmp.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
EQEmu::InitializeDynamicLookups();
|
||||
Log(Logs::General, Logs::World_Server, "Initialized dynamic dictionary entries");
|
||||
}
|
||||
|
||||
if (RuleB(World, ClearTempMerchantlist)) {
|
||||
@ -622,4 +625,4 @@ void CheckForServerScript(bool force_download) {
|
||||
system("wget -N --no-check-certificate --quiet -O eqemu_server.pl https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou
|
||||
{
|
||||
/* Set Character Creation Limit */
|
||||
EQEmu::versions::ClientVersion client_version = EQEmu::versions::ConvertClientVersionBitToClientVersion(clientVersionBit);
|
||||
size_t character_limit = EQEmu::constants::Lookup(client_version)->CharacterCreationLimit;
|
||||
size_t character_limit = EQEmu::constants::StaticLookup(client_version)->CharacterCreationLimit;
|
||||
|
||||
// Validate against absolute server max
|
||||
if (character_limit > EQEmu::constants::CHARACTER_CREATION_LIMIT)
|
||||
@ -97,7 +97,11 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou
|
||||
CharacterSelectEntry_Struct *cse = (CharacterSelectEntry_Struct *)buff_ptr;
|
||||
PlayerProfile_Struct pp;
|
||||
EQEmu::InventoryProfile inv;
|
||||
|
||||
pp.SetPlayerProfileVersion(EQEmu::versions::ConvertClientVersionToMobVersion(client_version));
|
||||
inv.SetInventoryVersion(client_version);
|
||||
inv.SetGMInventory(true); // charsel can not interact with items..but, no harm in setting to full expansion support
|
||||
|
||||
uint32 character_id = (uint32)atoi(row[0]);
|
||||
uint8 has_home = 0;
|
||||
uint8 has_bind = 0;
|
||||
|
||||
@ -814,12 +814,12 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
}
|
||||
case ServerOP_ReloadRules: {
|
||||
zoneserver_list.SendPacket(pack);
|
||||
RuleManager::Instance()->LoadRules(&database, "default");
|
||||
RuleManager::Instance()->LoadRules(&database, "default", true);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ReloadRulesWorld:
|
||||
{
|
||||
RuleManager::Instance()->LoadRules(&database, "default");
|
||||
RuleManager::Instance()->LoadRules(&database, "default", true);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ReloadPerlExportSettings:
|
||||
|
||||
@ -1221,12 +1221,12 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) {
|
||||
|
||||
// Bards can cast instant cast AAs while they are casting another song
|
||||
if(spells[rank->spell].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) {
|
||||
if(!SpellFinished(rank->spell, entity_list.GetMob(target_id), EQEmu::CastingSlot::AltAbility, spells[rank->spell].mana, -1, spells[rank->spell].ResistDiff, false)) {
|
||||
if(!SpellFinished(rank->spell, entity_list.GetMob(target_id), EQEmu::spells::CastingSlot::AltAbility, spells[rank->spell].mana, -1, spells[rank->spell].ResistDiff, false)) {
|
||||
return;
|
||||
}
|
||||
ExpendAlternateAdvancementCharge(ability->id);
|
||||
} else {
|
||||
if(!CastSpell(rank->spell, target_id, EQEmu::CastingSlot::AltAbility, -1, -1, 0, -1, rank->spell_type + pTimerAAStart, cooldown, nullptr, rank->id)) {
|
||||
if(!CastSpell(rank->spell, target_id, EQEmu::spells::CastingSlot::AltAbility, -1, -1, 0, -1, rank->spell_type + pTimerAAStart, cooldown, nullptr, rank->id)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1526,7 +1526,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
|
||||
IsValidSpell(aabonuses.SkillAttackProc[2])) {
|
||||
float chance = aabonuses.SkillAttackProc[0] / 1000.0f;
|
||||
if (zone->random.Roll(chance))
|
||||
SpellFinished(aabonuses.SkillAttackProc[2], other, EQEmu::CastingSlot::Item, 0, -1,
|
||||
SpellFinished(aabonuses.SkillAttackProc[2], other, EQEmu::spells::CastingSlot::Item, 0, -1,
|
||||
spells[aabonuses.SkillAttackProc[2]].ResistDiff);
|
||||
}
|
||||
other->Damage(this, my_hit.damage_done, SPELL_UNKNOWN, my_hit.skill, true, -1, false, m_specialattacks);
|
||||
@ -2130,7 +2130,7 @@ void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, EQEmu::skills::Skill
|
||||
if (IsLDoNTrapped())
|
||||
{
|
||||
Message_StringID(13, LDON_ACCIDENT_SETOFF2);
|
||||
SpellFinished(GetLDoNTrapSpellID(), other, EQEmu::CastingSlot::Item, 0, -1, spells[GetLDoNTrapSpellID()].ResistDiff, false);
|
||||
SpellFinished(GetLDoNTrapSpellID(), other, EQEmu::spells::CastingSlot::Item, 0, -1, spells[GetLDoNTrapSpellID()].ResistDiff, false);
|
||||
SetLDoNTrapSpellID(0);
|
||||
SetLDoNTrapped(false);
|
||||
SetLDoNTrapDetected(false);
|
||||
@ -5038,7 +5038,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac
|
||||
hit.damage_done = headshot;
|
||||
}
|
||||
else if (GetClass() == RANGER && GetLevel() > 50) { // no double dmg on headshot
|
||||
if (defender->IsNPC() && !defender->IsMoving() && !defender->IsRooted()) {
|
||||
if ((defender->IsNPC() && !defender->IsMoving() && !defender->IsRooted()) || !RuleB(Combat, ArcheryBonusRequiresStationary)) {
|
||||
hit.damage_done *= 2;
|
||||
Message_StringID(MT_CritMelee, BOW_DOUBLE_DAMAGE);
|
||||
}
|
||||
|
||||
472
zone/bot.cpp
472
zone/bot.cpp
@ -29,7 +29,9 @@
|
||||
extern volatile bool is_zone_loaded;
|
||||
|
||||
// This constructor is used during the bot create command
|
||||
Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm::vec4(), Ground, false), rest_timer(1) {
|
||||
Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm::vec4(), Ground, false), rest_timer(1), ping_timer(1) {
|
||||
GiveNPCTypeData(npcTypeData);
|
||||
|
||||
if(botOwner) {
|
||||
this->SetBotOwner(botOwner);
|
||||
this->_botOwnerCharacterID = botOwner->CharacterID();
|
||||
@ -39,29 +41,30 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm
|
||||
}
|
||||
|
||||
m_inv.SetInventoryVersion(EQEmu::versions::MobVersion::Bot);
|
||||
m_inv.SetGMInventory(false); // bot expansions are not currently implemented (defaults to static)
|
||||
|
||||
_guildRank = 0;
|
||||
_guildId = 0;
|
||||
_lastTotalPlayTime = 0;
|
||||
_startTotalPlayTime = time(&_startTotalPlayTime);
|
||||
_lastZoneId = 0;
|
||||
_baseMR = npcTypeData.MR;
|
||||
_baseCR = npcTypeData.CR;
|
||||
_baseDR = npcTypeData.DR;
|
||||
_baseFR = npcTypeData.FR;
|
||||
_basePR = npcTypeData.PR;
|
||||
_baseCorrup = npcTypeData.Corrup;
|
||||
_baseAC = npcTypeData.AC;
|
||||
_baseSTR = npcTypeData.STR;
|
||||
_baseSTA = npcTypeData.STA;
|
||||
_baseDEX = npcTypeData.DEX;
|
||||
_baseAGI = npcTypeData.AGI;
|
||||
_baseINT = npcTypeData.INT;
|
||||
_baseWIS = npcTypeData.WIS;
|
||||
_baseCHA = npcTypeData.CHA;
|
||||
_baseATK = npcTypeData.ATK;
|
||||
_baseRace = npcTypeData.race;
|
||||
_baseGender = npcTypeData.gender;
|
||||
_baseMR = npcTypeData->MR;
|
||||
_baseCR = npcTypeData->CR;
|
||||
_baseDR = npcTypeData->DR;
|
||||
_baseFR = npcTypeData->FR;
|
||||
_basePR = npcTypeData->PR;
|
||||
_baseCorrup = npcTypeData->Corrup;
|
||||
_baseAC = npcTypeData->AC;
|
||||
_baseSTR = npcTypeData->STR;
|
||||
_baseSTA = npcTypeData->STA;
|
||||
_baseDEX = npcTypeData->DEX;
|
||||
_baseAGI = npcTypeData->AGI;
|
||||
_baseINT = npcTypeData->INT;
|
||||
_baseWIS = npcTypeData->WIS;
|
||||
_baseCHA = npcTypeData->CHA;
|
||||
_baseATK = npcTypeData->ATK;
|
||||
_baseRace = npcTypeData->race;
|
||||
_baseGender = npcTypeData->gender;
|
||||
RestRegenHP = 0;
|
||||
RestRegenMana = 0;
|
||||
RestRegenEndurance = 0;
|
||||
@ -79,6 +82,7 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm
|
||||
SetShowHelm(true);
|
||||
SetPauseAI(false);
|
||||
rest_timer.Disable();
|
||||
ping_timer.Disable();
|
||||
SetFollowDistance(BOT_FOLLOW_DISTANCE_DEFAULT);
|
||||
if (IsCasterClass(GetClass()))
|
||||
SetStopMeleeLevel((uint8)RuleI(Bots, CasterStopMeleeLevel));
|
||||
@ -103,9 +107,11 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm
|
||||
}
|
||||
|
||||
// This constructor is used when the bot is loaded out of the database
|
||||
Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType npcTypeData)
|
||||
: NPC(&npcTypeData, nullptr, glm::vec4(), Ground, false), rest_timer(1)
|
||||
Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType *npcTypeData)
|
||||
: NPC(npcTypeData, nullptr, glm::vec4(), Ground, false), rest_timer(1), ping_timer(1)
|
||||
{
|
||||
GiveNPCTypeData(npcTypeData);
|
||||
|
||||
this->_botOwnerCharacterID = botOwnerCharacterID;
|
||||
if(this->_botOwnerCharacterID > 0)
|
||||
this->SetBotOwner(entity_list.GetClientByCharID(this->_botOwnerCharacterID));
|
||||
@ -113,6 +119,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
|
||||
auto bot_owner = GetBotOwner();
|
||||
|
||||
m_inv.SetInventoryVersion(EQEmu::versions::MobVersion::Bot);
|
||||
m_inv.SetGMInventory(false); // bot expansions are not currently implemented (defaults to static)
|
||||
|
||||
_guildRank = 0;
|
||||
_guildId = 0;
|
||||
@ -120,25 +127,25 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
|
||||
_startTotalPlayTime = time(&_startTotalPlayTime);
|
||||
_lastZoneId = lastZoneId;
|
||||
berserk = false;
|
||||
_baseMR = npcTypeData.MR;
|
||||
_baseCR = npcTypeData.CR;
|
||||
_baseDR = npcTypeData.DR;
|
||||
_baseFR = npcTypeData.FR;
|
||||
_basePR = npcTypeData.PR;
|
||||
_baseCorrup = npcTypeData.Corrup;
|
||||
_baseAC = npcTypeData.AC;
|
||||
_baseSTR = npcTypeData.STR;
|
||||
_baseSTA = npcTypeData.STA;
|
||||
_baseDEX = npcTypeData.DEX;
|
||||
_baseAGI = npcTypeData.AGI;
|
||||
_baseINT = npcTypeData.INT;
|
||||
_baseWIS = npcTypeData.WIS;
|
||||
_baseCHA = npcTypeData.CHA;
|
||||
_baseATK = npcTypeData.ATK;
|
||||
_baseRace = npcTypeData.race;
|
||||
_baseGender = npcTypeData.gender;
|
||||
current_hp = npcTypeData.current_hp;
|
||||
current_mana = npcTypeData.Mana;
|
||||
_baseMR = npcTypeData->MR;
|
||||
_baseCR = npcTypeData->CR;
|
||||
_baseDR = npcTypeData->DR;
|
||||
_baseFR = npcTypeData->FR;
|
||||
_basePR = npcTypeData->PR;
|
||||
_baseCorrup = npcTypeData->Corrup;
|
||||
_baseAC = npcTypeData->AC;
|
||||
_baseSTR = npcTypeData->STR;
|
||||
_baseSTA = npcTypeData->STA;
|
||||
_baseDEX = npcTypeData->DEX;
|
||||
_baseAGI = npcTypeData->AGI;
|
||||
_baseINT = npcTypeData->INT;
|
||||
_baseWIS = npcTypeData->WIS;
|
||||
_baseCHA = npcTypeData->CHA;
|
||||
_baseATK = npcTypeData->ATK;
|
||||
_baseRace = npcTypeData->race;
|
||||
_baseGender = npcTypeData->gender;
|
||||
current_hp = npcTypeData->current_hp;
|
||||
current_mana = npcTypeData->Mana;
|
||||
RestRegenHP = 0;
|
||||
RestRegenMana = 0;
|
||||
RestRegenEndurance = 0;
|
||||
@ -160,6 +167,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
|
||||
SetPauseAI(false);
|
||||
|
||||
rest_timer.Disable();
|
||||
ping_timer.Disable();
|
||||
SetFollowDistance(BOT_FOLLOW_DISTANCE_DEFAULT);
|
||||
if (IsCasterClass(GetClass()))
|
||||
SetStopMeleeLevel((uint8)RuleI(Bots, CasterStopMeleeLevel));
|
||||
@ -311,112 +319,252 @@ bool Bot::IsStanding() {
|
||||
return result;
|
||||
}
|
||||
|
||||
NPCType Bot::FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender, float size, uint32 face, uint32 hairStyle, uint32 hairColor, uint32 eyeColor, uint32 eyeColor2, uint32 beardColor, uint32 beard, uint32 drakkinHeritage, uint32 drakkinTattoo, uint32 drakkinDetails, int32 hp, int32 mana, int32 mr, int32 cr, int32 dr, int32 fr, int32 pr, int32 corrup, int32 ac, uint32 str, uint32 sta, uint32 dex, uint32 agi, uint32 _int, uint32 wis, uint32 cha, uint32 attack) {
|
||||
NPCType BotNPCType;
|
||||
int CopyLength = 0;
|
||||
CopyLength = botName.copy(BotNPCType.name, 63);
|
||||
BotNPCType.name[CopyLength] = '\0';
|
||||
CopyLength = 0;
|
||||
CopyLength = botLastName.copy(BotNPCType.lastname, 69);
|
||||
BotNPCType.lastname[CopyLength] = '\0';
|
||||
CopyLength = 0;
|
||||
BotNPCType.npc_spells_id = botSpellsID;
|
||||
BotNPCType.level = botLevel;
|
||||
BotNPCType.race = botRace;
|
||||
BotNPCType.class_ = botClass;
|
||||
BotNPCType.gender = gender;
|
||||
BotNPCType.size = size;
|
||||
BotNPCType.luclinface = face;
|
||||
BotNPCType.hairstyle = hairStyle;
|
||||
BotNPCType.haircolor = hairColor;
|
||||
BotNPCType.eyecolor1 = eyeColor;
|
||||
BotNPCType.eyecolor2 = eyeColor2;
|
||||
BotNPCType.beardcolor = beardColor;
|
||||
BotNPCType.beard = beard;
|
||||
BotNPCType.drakkin_heritage = drakkinHeritage;
|
||||
BotNPCType.drakkin_tattoo = drakkinTattoo;
|
||||
BotNPCType.drakkin_details = drakkinDetails;
|
||||
BotNPCType.current_hp = hp;
|
||||
BotNPCType.Mana = mana;
|
||||
BotNPCType.MR = mr;
|
||||
BotNPCType.CR = cr;
|
||||
BotNPCType.DR = dr;
|
||||
BotNPCType.FR = fr;
|
||||
BotNPCType.PR = pr;
|
||||
BotNPCType.Corrup = corrup;
|
||||
BotNPCType.AC = ac;
|
||||
BotNPCType.STR = str;
|
||||
BotNPCType.STA = sta;
|
||||
BotNPCType.DEX = dex;
|
||||
BotNPCType.AGI = agi;
|
||||
BotNPCType.INT = _int;
|
||||
BotNPCType.WIS = wis;
|
||||
BotNPCType.CHA = cha;
|
||||
BotNPCType.ATK = attack;
|
||||
BotNPCType.npc_id = 0;
|
||||
BotNPCType.texture = 0;
|
||||
BotNPCType.d_melee_texture1 = 0;
|
||||
BotNPCType.d_melee_texture2 = 0;
|
||||
BotNPCType.qglobal = false;
|
||||
BotNPCType.attack_speed = 0;
|
||||
BotNPCType.runspeed = 0.7f;
|
||||
BotNPCType.bodytype = 1;
|
||||
BotNPCType.findable = 0;
|
||||
BotNPCType.hp_regen = 1;
|
||||
BotNPCType.mana_regen = 1;
|
||||
BotNPCType.maxlevel = botLevel;
|
||||
BotNPCType.light = 0; // due to the way that bots are coded..this is sent post-spawn
|
||||
return BotNPCType;
|
||||
NPCType *Bot::FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender, float size, uint32 face, uint32 hairStyle, uint32 hairColor, uint32 eyeColor, uint32 eyeColor2, uint32 beardColor, uint32 beard, uint32 drakkinHeritage, uint32 drakkinTattoo, uint32 drakkinDetails, int32 hp, int32 mana, int32 mr, int32 cr, int32 dr, int32 fr, int32 pr, int32 corrup, int32 ac, uint32 str, uint32 sta, uint32 dex, uint32 agi, uint32 _int, uint32 wis, uint32 cha, uint32 attack) {
|
||||
auto bot_npc_type = new NPCType{ 0 };
|
||||
int copy_length = 0;
|
||||
|
||||
copy_length = botName.copy(bot_npc_type->name, 63);
|
||||
bot_npc_type->name[copy_length] = '\0';
|
||||
copy_length = 0;
|
||||
|
||||
copy_length = botLastName.copy(bot_npc_type->lastname, 69);
|
||||
bot_npc_type->lastname[copy_length] = '\0';
|
||||
copy_length = 0;
|
||||
|
||||
bot_npc_type->current_hp = hp;
|
||||
bot_npc_type->max_hp = hp;
|
||||
bot_npc_type->size = size;
|
||||
bot_npc_type->runspeed = 0.7f;
|
||||
bot_npc_type->gender = gender;
|
||||
bot_npc_type->race = botRace;
|
||||
bot_npc_type->class_ = botClass;
|
||||
bot_npc_type->bodytype = 1;
|
||||
bot_npc_type->deity = EQEmu::deity::DeityAgnostic;
|
||||
bot_npc_type->level = botLevel;
|
||||
//bot_npc_type->npc_id = 0;
|
||||
//bot_npc_type->texture = 0;
|
||||
//bot_npc_type->helmtexture = 0;
|
||||
//bot_npc_type->herosforgemodel = 0;
|
||||
//bot_npc_type->loottable_id = 0;
|
||||
bot_npc_type->npc_spells_id = botSpellsID;
|
||||
//bot_npc_type->npc_spells_effects_id = 0;
|
||||
//bot_npc_type->npc_faction_id = 0;
|
||||
//bot_npc_type->merchanttype = 0;
|
||||
//bot_npc_type->alt_currency_type = 0;
|
||||
//bot_npc_type->adventure_template = 0;
|
||||
//bot_npc_type->trap_template = 0;
|
||||
//bot_npc_type->light = 0;
|
||||
bot_npc_type->AC = ac;
|
||||
bot_npc_type->Mana = mana;
|
||||
bot_npc_type->ATK = attack;
|
||||
bot_npc_type->STR = str;
|
||||
bot_npc_type->STA = sta;
|
||||
bot_npc_type->DEX = dex;
|
||||
bot_npc_type->AGI = agi;
|
||||
bot_npc_type->INT = _int;
|
||||
bot_npc_type->WIS = wis;
|
||||
bot_npc_type->CHA = cha;
|
||||
bot_npc_type->MR = mr;
|
||||
bot_npc_type->FR = fr;
|
||||
bot_npc_type->CR = cr;
|
||||
bot_npc_type->PR = pr;
|
||||
bot_npc_type->DR = dr;
|
||||
bot_npc_type->Corrup = corrup;
|
||||
//bot_npc_type->PhR = 0;
|
||||
bot_npc_type->haircolor = hairColor;
|
||||
bot_npc_type->beardcolor = beardColor;
|
||||
bot_npc_type->eyecolor1 = eyeColor;
|
||||
bot_npc_type->eyecolor2 = eyeColor2;
|
||||
bot_npc_type->hairstyle = hairStyle;
|
||||
bot_npc_type->luclinface = face;
|
||||
bot_npc_type->beard = beard;
|
||||
bot_npc_type->drakkin_heritage = drakkinHeritage;
|
||||
bot_npc_type->drakkin_tattoo = drakkinTattoo;
|
||||
bot_npc_type->drakkin_details = drakkinDetails;
|
||||
//bot_npc_type->armor_tint = { 0 };
|
||||
//bot_npc_type->min_dmg = 0;
|
||||
//bot_npc_type->max_dmg = 0;
|
||||
//bot_npc_type->charm_ac = 0;
|
||||
//bot_npc_type->charm_min_dmg = 0;
|
||||
//bot_npc_type->charm_max_dmg = 0;
|
||||
//bot_npc_type->charm_attack_delay = 0;
|
||||
//bot_npc_type->charm_accuracy_rating = 0;
|
||||
//bot_npc_type->charm_avoidance_rating = 0;
|
||||
//bot_npc_type->charm_atk = 0;
|
||||
//bot_npc_type->attack_count = 0;
|
||||
//*bot_npc_type->special_abilities = { 0 };
|
||||
//bot_npc_type->d_melee_texture1 = 0;
|
||||
//bot_npc_type->d_melee_texture2 = 0;
|
||||
//*bot_npc_type->ammo_idfile = { 0 };
|
||||
//bot_npc_type->prim_melee_type = 0;
|
||||
//bot_npc_type->sec_melee_type = 0;
|
||||
//bot_npc_type->ranged_type = 0;
|
||||
bot_npc_type->hp_regen = 1;
|
||||
bot_npc_type->mana_regen = 1;
|
||||
//bot_npc_type->aggroradius = 0;
|
||||
//bot_npc_type->assistradius = 0;
|
||||
//bot_npc_type->see_invis = 0;
|
||||
//bot_npc_type->see_invis_undead = false;
|
||||
//bot_npc_type->see_hide = false;
|
||||
//bot_npc_type->see_improved_hide = false;
|
||||
//bot_npc_type->qglobal = false;
|
||||
//bot_npc_type->npc_aggro = false;
|
||||
//bot_npc_type->spawn_limit = 0;
|
||||
//bot_npc_type->mount_color = 0;
|
||||
//bot_npc_type->attack_speed = 0.0f;
|
||||
//bot_npc_type->attack_delay = 0;
|
||||
//bot_npc_type->accuracy_rating = 0;
|
||||
//bot_npc_type->avoidance_rating = 0;
|
||||
//bot_npc_type->findable = false;
|
||||
bot_npc_type->trackable = true;
|
||||
//bot_npc_type->slow_mitigation = 0;
|
||||
bot_npc_type->maxlevel = botLevel;
|
||||
//bot_npc_type->scalerate = 0;
|
||||
//bot_npc_type->private_corpse = false;
|
||||
//bot_npc_type->unique_spawn_by_name = false;
|
||||
//bot_npc_type->underwater = false;
|
||||
//bot_npc_type->emoteid = 0;
|
||||
//bot_npc_type->spellscale = 0.0f;
|
||||
//bot_npc_type->healscale = 0.0f;
|
||||
//bot_npc_type->no_target_hotkey = false;
|
||||
//bot_npc_type->raid_target = false;
|
||||
//bot_npc_type->armtexture = 0;
|
||||
//bot_npc_type->bracertexture = 0;
|
||||
//bot_npc_type->handtexture = 0;
|
||||
//bot_npc_type->legtexture = 0;
|
||||
//bot_npc_type->feettexture = 0;
|
||||
//bot_npc_type->ignore_despawn = false;
|
||||
bot_npc_type->show_name = true;
|
||||
//bot_npc_type->untargetable = false;
|
||||
bot_npc_type->skip_global_loot = true;
|
||||
//bot_npc_type->rare_spawn = false;
|
||||
bot_npc_type->stuck_behavior = Ground;
|
||||
|
||||
return bot_npc_type;
|
||||
}
|
||||
|
||||
NPCType Bot::CreateDefaultNPCTypeStructForBot(std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender) {
|
||||
NPCType Result;
|
||||
int CopyLength = 0;
|
||||
CopyLength = botName.copy(Result.name, 63);
|
||||
Result.name[CopyLength] = '\0';
|
||||
CopyLength = 0;
|
||||
CopyLength = botLastName.copy(Result.lastname, 69);
|
||||
Result.lastname[CopyLength] = '\0';
|
||||
CopyLength = 0;
|
||||
Result.level = botLevel;
|
||||
Result.race = botRace;
|
||||
Result.class_ = botClass;
|
||||
Result.gender = gender;
|
||||
// default values
|
||||
Result.maxlevel = botLevel;
|
||||
Result.size = 6.0;
|
||||
Result.npc_id = 0;
|
||||
Result.current_hp = 0;
|
||||
Result.drakkin_details = 0;
|
||||
Result.drakkin_heritage = 0;
|
||||
Result.drakkin_tattoo = 0;
|
||||
Result.runspeed = 0.7f;
|
||||
Result.bodytype = 1;
|
||||
Result.findable = 0;
|
||||
Result.hp_regen = 1;
|
||||
Result.mana_regen = 1;
|
||||
Result.texture = 0;
|
||||
Result.d_melee_texture1 = 0;
|
||||
Result.d_melee_texture2 = 0;
|
||||
Result.qglobal = false;
|
||||
Result.npc_spells_id = 0;
|
||||
Result.attack_speed = 0;
|
||||
Result.STR = 75;
|
||||
Result.STA = 75;
|
||||
Result.DEX = 75;
|
||||
Result.AGI = 75;
|
||||
Result.WIS = 75;
|
||||
Result.INT = 75;
|
||||
Result.CHA = 75;
|
||||
Result.ATK = 75;
|
||||
Result.MR = 25;
|
||||
Result.FR = 25;
|
||||
Result.DR = 15;
|
||||
Result.PR = 15;
|
||||
Result.CR = 25;
|
||||
Result.Corrup = 15;
|
||||
Result.AC = 12;
|
||||
return Result;
|
||||
NPCType *Bot::CreateDefaultNPCTypeStructForBot(std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender) {
|
||||
auto bot_npc_type = new NPCType{ 0 };
|
||||
int copy_length = 0;
|
||||
|
||||
copy_length = botName.copy(bot_npc_type->name, 63);
|
||||
bot_npc_type->name[copy_length] = '\0';
|
||||
copy_length = 0;
|
||||
|
||||
copy_length = botLastName.copy(bot_npc_type->lastname, 69);
|
||||
bot_npc_type->lastname[copy_length] = '\0';
|
||||
copy_length = 0;
|
||||
|
||||
//bot_npc_type->current_hp = 0;
|
||||
//bot_npc_type->max_hp = 0;
|
||||
bot_npc_type->size = 6.0f;
|
||||
bot_npc_type->runspeed = 0.7f;
|
||||
bot_npc_type->gender = gender;
|
||||
bot_npc_type->race = botRace;
|
||||
bot_npc_type->class_ = botClass;
|
||||
bot_npc_type->bodytype = 1;
|
||||
bot_npc_type->deity = EQEmu::deity::DeityAgnostic;
|
||||
bot_npc_type->level = botLevel;
|
||||
//bot_npc_type->npc_id = 0;
|
||||
//bot_npc_type->texture = 0;
|
||||
//bot_npc_type->helmtexture = 0;
|
||||
//bot_npc_type->herosforgemodel = 0;
|
||||
//bot_npc_type->loottable_id = 0;
|
||||
//bot_npc_type->npc_spells_id = 0;
|
||||
//bot_npc_type->npc_spells_effects_id = 0;
|
||||
//bot_npc_type->npc_faction_id = 0;
|
||||
//bot_npc_type->merchanttype = 0;
|
||||
//bot_npc_type->alt_currency_type = 0;
|
||||
//bot_npc_type->adventure_template = 0;
|
||||
//bot_npc_type->trap_template = 0;
|
||||
//bot_npc_type->light = 0;
|
||||
bot_npc_type->AC = 12;
|
||||
//bot_npc_type->Mana = 0;
|
||||
bot_npc_type->ATK = 75;
|
||||
bot_npc_type->STR = 75;
|
||||
bot_npc_type->STA = 75;
|
||||
bot_npc_type->DEX = 75;
|
||||
bot_npc_type->AGI = 75;
|
||||
bot_npc_type->INT = 75;
|
||||
bot_npc_type->WIS = 75;
|
||||
bot_npc_type->CHA = 75;
|
||||
bot_npc_type->MR = 25;
|
||||
bot_npc_type->FR = 25;
|
||||
bot_npc_type->CR = 25;
|
||||
bot_npc_type->PR = 15;
|
||||
bot_npc_type->DR = 15;
|
||||
bot_npc_type->Corrup = 15;
|
||||
//bot_npc_type->PhR = 0;
|
||||
//bot_npc_type->haircolor = 0;
|
||||
//bot_npc_type->beardcolor = 0;
|
||||
//bot_npc_type->eyecolor1 = 0;
|
||||
//bot_npc_type->eyecolor2 = 0;
|
||||
//bot_npc_type->hairstyle = 0;
|
||||
//bot_npc_type->luclinface = 0;
|
||||
//bot_npc_type->beard = 0;
|
||||
//bot_npc_type->drakkin_heritage = 0;
|
||||
//bot_npc_type->drakkin_tattoo = 0;
|
||||
//bot_npc_type->drakkin_details = 0;
|
||||
//bot_npc_type->armor_tint = { 0 };
|
||||
//bot_npc_type->min_dmg = 0;
|
||||
//bot_npc_type->max_dmg = 0;
|
||||
//bot_npc_type->charm_ac = 0;
|
||||
//bot_npc_type->charm_min_dmg = 0;
|
||||
//bot_npc_type->charm_max_dmg = 0;
|
||||
//bot_npc_type->charm_attack_delay = 0;
|
||||
//bot_npc_type->charm_accuracy_rating = 0;
|
||||
//bot_npc_type->charm_avoidance_rating = 0;
|
||||
//bot_npc_type->charm_atk = 0;
|
||||
//bot_npc_type->attack_count = 0;
|
||||
//*bot_npc_type->special_abilities = { 0 };
|
||||
//bot_npc_type->d_melee_texture1 = 0;
|
||||
//bot_npc_type->d_melee_texture2 = 0;
|
||||
//*bot_npc_type->ammo_idfile = { 0 };
|
||||
//bot_npc_type->prim_melee_type = 0;
|
||||
//bot_npc_type->sec_melee_type = 0;
|
||||
//bot_npc_type->ranged_type = 0;
|
||||
bot_npc_type->hp_regen = 1;
|
||||
bot_npc_type->mana_regen = 1;
|
||||
//bot_npc_type->aggroradius = 0;
|
||||
//bot_npc_type->assistradius = 0;
|
||||
//bot_npc_type->see_invis = 0;
|
||||
//bot_npc_type->see_invis_undead = false;
|
||||
//bot_npc_type->see_hide = false;
|
||||
//bot_npc_type->see_improved_hide = false;
|
||||
//bot_npc_type->qglobal = false;
|
||||
//bot_npc_type->npc_aggro = false;
|
||||
//bot_npc_type->spawn_limit = 0;
|
||||
//bot_npc_type->mount_color = 0;
|
||||
//bot_npc_type->attack_speed = 0.0f;
|
||||
//bot_npc_type->attack_delay = 0;
|
||||
//bot_npc_type->accuracy_rating = 0;
|
||||
//bot_npc_type->avoidance_rating = 0;
|
||||
//bot_npc_type->findable = false;
|
||||
bot_npc_type->trackable = true;
|
||||
//bot_npc_type->slow_mitigation = 0;
|
||||
bot_npc_type->maxlevel = botLevel;
|
||||
//bot_npc_type->scalerate = 0;
|
||||
//bot_npc_type->private_corpse = false;
|
||||
//bot_npc_type->unique_spawn_by_name = false;
|
||||
//bot_npc_type->underwater = false;
|
||||
//bot_npc_type->emoteid = 0;
|
||||
//bot_npc_type->spellscale = 0.0f;
|
||||
//bot_npc_type->healscale = 0.0f;
|
||||
//bot_npc_type->no_target_hotkey = false;
|
||||
//bot_npc_type->raid_target = false;
|
||||
//bot_npc_type->armtexture = 0;
|
||||
//bot_npc_type->bracertexture = 0;
|
||||
//bot_npc_type->handtexture = 0;
|
||||
//bot_npc_type->legtexture = 0;
|
||||
//bot_npc_type->feettexture = 0;
|
||||
//bot_npc_type->ignore_despawn = false;
|
||||
bot_npc_type->show_name = true;
|
||||
//bot_npc_type->untargetable = false;
|
||||
bot_npc_type->skip_global_loot = true;
|
||||
//bot_npc_type->rare_spawn = false;
|
||||
bot_npc_type->stuck_behavior = Ground;
|
||||
|
||||
return bot_npc_type;
|
||||
}
|
||||
|
||||
void Bot::GenerateBaseStats()
|
||||
@ -1868,6 +2016,9 @@ bool Bot::Process() {
|
||||
if (IsStunned() || IsMezzed())
|
||||
return true;
|
||||
|
||||
if (!IsMoving() && ping_timer.Check())
|
||||
SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0);
|
||||
|
||||
// Bot AI
|
||||
AI_Process();
|
||||
return true;
|
||||
@ -3109,6 +3260,7 @@ bool Bot::Spawn(Client* botCharacterOwner) {
|
||||
// Load pet
|
||||
LoadPet();
|
||||
SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0);
|
||||
ping_timer.Start(8000);
|
||||
// there is something askew with spawn struct appearance fields...
|
||||
// I re-enabled this until I can sort it out
|
||||
uint32 itemID = 0;
|
||||
@ -6261,7 +6413,7 @@ void Bot::DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster) {
|
||||
Mob::DoBuffTic(buff, slot, caster);
|
||||
}
|
||||
|
||||
bool Bot::CastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot, int32 cast_time, int32 mana_cost,
|
||||
bool Bot::CastSpell(uint16 spell_id, uint16 target_id, EQEmu::spells::CastingSlot slot, int32 cast_time, int32 mana_cost,
|
||||
uint32* oSpellWillFinish, uint32 item_slot, int16 *resist_adjust, uint32 aa_id) {
|
||||
bool Result = false;
|
||||
if(zone && !zone->IsSpellBlocked(spell_id, glm::vec3(GetPosition()))) {
|
||||
@ -6301,7 +6453,7 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot,
|
||||
return false;
|
||||
}
|
||||
|
||||
if(slot < EQEmu::CastingSlot::MaxGems && !CheckFizzle(spell_id)) {
|
||||
if(slot < EQEmu::spells::CastingSlot::MaxGems && !CheckFizzle(spell_id)) {
|
||||
int fizzle_msg = IsBardSong(spell_id) ? MISS_NOTE : SPELL_FIZZLE;
|
||||
InterruptSpell(fizzle_msg, 0x121, spell_id);
|
||||
|
||||
@ -6315,7 +6467,7 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot,
|
||||
Log(Logs::Detail, Logs::Spells, "Casting a new spell/song while singing a song. Killing old song %d.", bardsong);
|
||||
bardsong = 0;
|
||||
bardsong_target_id = 0;
|
||||
bardsong_slot = EQEmu::CastingSlot::Gem1;
|
||||
bardsong_slot = EQEmu::spells::CastingSlot::Gem1;
|
||||
bardsong_timer.Disable();
|
||||
}
|
||||
|
||||
@ -6445,7 +6597,7 @@ bool Bot::IsImmuneToSpell(uint16 spell_id, Mob *caster) {
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool Bot::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, EQEmu::CastingSlot slot) {
|
||||
bool Bot::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, EQEmu::spells::CastingSlot slot) {
|
||||
bool Result = false;
|
||||
SpellTargetType targetType = spells[spell_id].targettype;
|
||||
if(targetType == ST_GroupClientAndPet) {
|
||||
@ -6458,7 +6610,7 @@ bool Bot::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool Bot::DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, uint32 aa_id) {
|
||||
bool Bot::DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::spells::CastingSlot slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, uint32 aa_id) {
|
||||
bool Result = false;
|
||||
if(GetClass() == BARD)
|
||||
cast_time = 0;
|
||||
@ -6562,7 +6714,7 @@ void Bot::GenerateSpecialAttacks() {
|
||||
SetSpecialAbility(SPECATK_TRIPLE, 1);
|
||||
}
|
||||
|
||||
bool Bot::DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool& stopLogic) {
|
||||
bool Bot::DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQEmu::spells::CastingSlot slot, bool& stopLogic) {
|
||||
if(GetClass() == BARD) {
|
||||
if(!ApplyNextBardPulse(bardsong, this, bardsong_slot))
|
||||
InterruptSpell(SONG_ENDS_ABRUPTLY, 0x121, bardsong);
|
||||
@ -6572,7 +6724,7 @@ bool Bot::DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQEmu::Cast
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool& stopLogic) {
|
||||
bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQEmu::spells::CastingSlot slot, bool& stopLogic) {
|
||||
if(spellTarget) {
|
||||
if(IsGrouped() && (spellTarget->IsBot() || spellTarget->IsClient()) && RuleB(Bots, GroupBuffing)) {
|
||||
bool noGroupSpell = false;
|
||||
@ -6584,7 +6736,7 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQEmu::
|
||||
bool spelltypeequal = ((spelltype == 2) || (spelltype == 16) || (spelltype == 32));
|
||||
bool spelltypetargetequal = ((spelltype == 8) && (spells[thespell].targettype == ST_Self));
|
||||
bool spelltypeclassequal = ((spelltype == 1024) && (GetClass() == SHAMAN));
|
||||
bool slotequal = (slot == EQEmu::CastingSlot::Item);
|
||||
bool slotequal = (slot == EQEmu::spells::CastingSlot::Item);
|
||||
if(spellequal || slotequal) {
|
||||
if((spelltypeequal || spelltypetargetequal) || spelltypeclassequal || slotequal) {
|
||||
if(((spells[thespell].effectid[0] == 0) && (spells[thespell].base[0] < 0)) &&
|
||||
@ -6623,7 +6775,7 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQEmu::
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bot::DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool& stopLogic) {
|
||||
bool Bot::DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQEmu::spells::CastingSlot slot, bool& stopLogic) {
|
||||
bool isMainGroupMGB = false;
|
||||
if(isMainGroupMGB && (GetClass() != BARD)) {
|
||||
BotGroupSay(this, "MGB %s", spells[spell_id].name);
|
||||
@ -8706,7 +8858,7 @@ bool Bot::UseDiscipline(uint32 spell_id, uint32 target) {
|
||||
if(IsCasting())
|
||||
InterruptSpell();
|
||||
|
||||
CastSpell(spell_id, target, EQEmu::CastingSlot::Discipline);
|
||||
CastSpell(spell_id, target, EQEmu::spells::CastingSlot::Discipline);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -8930,4 +9082,18 @@ std::string Bot::CreateSayLink(Client* c, const char* message, const char* name)
|
||||
return saylink;
|
||||
}
|
||||
|
||||
void Bot::StopMoving() {
|
||||
if (!ping_timer.Enabled())
|
||||
ping_timer.Start(8000);
|
||||
|
||||
Mob::StopMoving();
|
||||
}
|
||||
|
||||
void Bot::StopMoving(float new_heading) {
|
||||
if (!ping_timer.Enabled())
|
||||
ping_timer.Start(8000);
|
||||
|
||||
Mob::StopMoving(new_heading);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
30
zone/bot.h
30
zone/bot.h
@ -250,8 +250,8 @@ public:
|
||||
};
|
||||
|
||||
// Class Constructors
|
||||
Bot(NPCType npcTypeData, Client* botOwner);
|
||||
Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType npcTypeData);
|
||||
Bot(NPCType *npcTypeData, Client* botOwner);
|
||||
Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType *npcTypeData);
|
||||
|
||||
//abstract virtual function implementations requird by base abstract class
|
||||
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill);
|
||||
@ -322,9 +322,9 @@ public:
|
||||
virtual void SetAttackTimer();
|
||||
uint32 GetClassHPFactor();
|
||||
virtual int32 CalcMaxHP();
|
||||
bool DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool &stopLogic);
|
||||
bool DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool &stopLogic);
|
||||
bool DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool &stopLogic);
|
||||
bool DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQEmu::spells::CastingSlot slot, bool &stopLogic);
|
||||
bool DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQEmu::spells::CastingSlot slot, bool &stopLogic);
|
||||
bool DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQEmu::spells::CastingSlot slot, bool &stopLogic);
|
||||
void SendBotArcheryWearChange(uint8 material_slot, uint32 material, uint32 color);
|
||||
void Camp(bool databaseSave = true);
|
||||
virtual void AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false, bool pet_command = false);
|
||||
@ -337,9 +337,12 @@ public:
|
||||
void Stand();
|
||||
bool IsSitting();
|
||||
bool IsStanding();
|
||||
int GetBotWalkspeed() const { return (int)((float)_GetWalkSpeed() * 1.786f); } // 1.25 / 0.7 = 1.7857142857142857142857142857143
|
||||
int GetBotRunspeed() const { return (int)((float)_GetRunSpeed() * 1.786f); }
|
||||
int GetBotFearSpeed() const { return (int)((float)_GetFearSpeed() * 1.786f); }
|
||||
virtual int GetWalkspeed() const { return (int)((float)_GetWalkSpeed() * 1.785714f); } // 1.25 / 0.7 = 1.7857142857142857142857142857143
|
||||
virtual int GetRunspeed() const { return (int)((float)_GetRunSpeed() * 1.785714f); }
|
||||
virtual void WalkTo(float x, float y, float z);
|
||||
virtual void RunTo(float x, float y, float z);
|
||||
virtual void StopMoving();
|
||||
virtual void StopMoving(float new_heading);
|
||||
bool UseDiscipline(uint32 spell_id, uint32 target);
|
||||
uint8 GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets);
|
||||
bool GetNeedsCured(Mob *tar);
|
||||
@ -425,12 +428,12 @@ public:
|
||||
virtual float GetAOERange(uint16 spell_id);
|
||||
virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100);
|
||||
virtual void DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster = nullptr);
|
||||
virtual bool CastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0,
|
||||
virtual bool CastSpell(uint16 spell_id, uint16 target_id, EQEmu::spells::CastingSlot slot = EQEmu::spells::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0,
|
||||
uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr, uint32 aa_id = 0);
|
||||
virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar);
|
||||
virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster);
|
||||
virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, EQEmu::CastingSlot slot);
|
||||
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 aa_id = 0);
|
||||
virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, EQEmu::spells::CastingSlot slot);
|
||||
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::spells::CastingSlot slot = EQEmu::spells::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 aa_id = 0);
|
||||
|
||||
// Bot Equipment & Inventory Class Methods
|
||||
void BotTradeSwapItem(Client* client, int16 lootSlot, const EQEmu::ItemInstance* inst, const EQEmu::ItemInstance* inst_swap, uint32 equipableSlots, std::string* errorMessage, bool swap = true);
|
||||
@ -494,7 +497,7 @@ public:
|
||||
static BotSpell GetBestBotSpellForCure(Bot* botCaster, Mob* target);
|
||||
static BotSpell GetBestBotSpellForResistDebuff(Bot* botCaster, Mob* target);
|
||||
|
||||
static NPCType CreateDefaultNPCTypeStructForBot(std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender);
|
||||
static NPCType *CreateDefaultNPCTypeStructForBot(std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender);
|
||||
|
||||
// Static Bot Group Methods
|
||||
static bool AddBotToGroup(Bot* bot, Group* group);
|
||||
@ -656,7 +659,7 @@ public:
|
||||
virtual void BotRangedAttack(Mob* other);
|
||||
|
||||
// Publicized private functions
|
||||
static NPCType FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender, float size, uint32 face, uint32 hairStyle, uint32 hairColor, uint32 eyeColor, uint32 eyeColor2, uint32 beardColor, uint32 beard, uint32 drakkinHeritage, uint32 drakkinTattoo, uint32 drakkinDetails, int32 hp, int32 mana, int32 mr, int32 cr, int32 dr, int32 fr, int32 pr, int32 corrup, int32 ac, uint32 str, uint32 sta, uint32 dex, uint32 agi, uint32 _int, uint32 wis, uint32 cha, uint32 attack);
|
||||
static NPCType *FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender, float size, uint32 face, uint32 hairStyle, uint32 hairColor, uint32 eyeColor, uint32 eyeColor2, uint32 beardColor, uint32 beard, uint32 drakkinHeritage, uint32 drakkinTattoo, uint32 drakkinDetails, int32 hp, int32 mana, int32 mr, int32 cr, int32 dr, int32 fr, int32 pr, int32 corrup, int32 ac, uint32 str, uint32 sta, uint32 dex, uint32 agi, uint32 _int, uint32 wis, uint32 cha, uint32 attack);
|
||||
void BotRemoveEquipItem(int16 slot);
|
||||
void RemoveBotItemBySlot(uint32 slotID, std::string* errorMessage);
|
||||
uint32 GetTotalPlayTime();
|
||||
@ -730,6 +733,7 @@ private:
|
||||
unsigned int RestRegenMana;
|
||||
unsigned int RestRegenEndurance;
|
||||
Timer rest_timer;
|
||||
Timer ping_timer;
|
||||
int32 base_end;
|
||||
int32 cur_end;
|
||||
int32 max_end;
|
||||
|
||||
@ -7707,16 +7707,7 @@ uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_clas
|
||||
return bot_id;
|
||||
}
|
||||
|
||||
auto DefaultNPCTypeStruct = Bot::CreateDefaultNPCTypeStructForBot(
|
||||
bot_name.c_str(),
|
||||
"",
|
||||
bot_owner->GetLevel(),
|
||||
bot_race,
|
||||
bot_class,
|
||||
bot_gender
|
||||
);
|
||||
|
||||
auto my_bot = new Bot(DefaultNPCTypeStruct, bot_owner);
|
||||
auto my_bot = new Bot(Bot::CreateDefaultNPCTypeStructForBot(bot_name.c_str(), "", bot_owner->GetLevel(), bot_race, bot_class, bot_gender), bot_owner);
|
||||
|
||||
if (!my_bot->Save()) {
|
||||
bot_owner->Message(m_unknown, "Failed to create '%s' due to unknown cause", my_bot->GetCleanName());
|
||||
@ -7774,7 +7765,7 @@ bool helper_cast_standard_spell(Bot* casting_bot, Mob* target_mob, int spell_id,
|
||||
if (annouce_cast)
|
||||
Bot::BotGroupSay(casting_bot, "Attempting to cast '%s' on %s", spells[spell_id].name, target_mob->GetCleanName());
|
||||
|
||||
return casting_bot->CastSpell(spell_id, target_mob->GetID(), EQEmu::CastingSlot::Gem2, -1, -1, dont_root_before);
|
||||
return casting_bot->CastSpell(spell_id, target_mob->GetID(), EQEmu::spells::CastingSlot::Gem2, -1, -1, dont_root_before);
|
||||
}
|
||||
|
||||
bool helper_command_alias_fail(Client *bot_owner, const char* command_handler, const char *alias, const char *command)
|
||||
|
||||
@ -357,8 +357,8 @@ bool BotDatabase::LoadBot(const uint32 bot_id, Bot*& loaded_bot)
|
||||
|
||||
// TODO: Consider removing resists and basic attributes from the load query above since we're using defaultNPCType values instead
|
||||
auto row = results.begin();
|
||||
NPCType defaultNPCTypeStruct = Bot::CreateDefaultNPCTypeStructForBot(std::string(row[2]), std::string(row[3]), atoi(row[10]), atoi(row[8]), atoi(row[9]), atoi(row[7]));
|
||||
NPCType tempNPCStruct = Bot::FillNPCTypeStruct(
|
||||
auto defaultNPCTypeStruct = Bot::CreateDefaultNPCTypeStructForBot(std::string(row[2]), std::string(row[3]), atoi(row[10]), atoi(row[8]), atoi(row[9]), atoi(row[7]));
|
||||
auto tempNPCStruct = Bot::FillNPCTypeStruct(
|
||||
atoi(row[1]),
|
||||
std::string(row[2]),
|
||||
std::string(row[3]),
|
||||
@ -379,21 +379,21 @@ bool BotDatabase::LoadBot(const uint32 bot_id, Bot*& loaded_bot)
|
||||
atoi(row[25]),
|
||||
atoi(row[28]),
|
||||
atoi(row[29]),
|
||||
defaultNPCTypeStruct.MR,
|
||||
defaultNPCTypeStruct.CR,
|
||||
defaultNPCTypeStruct.DR,
|
||||
defaultNPCTypeStruct.FR,
|
||||
defaultNPCTypeStruct.PR,
|
||||
defaultNPCTypeStruct.Corrup,
|
||||
defaultNPCTypeStruct.AC,
|
||||
defaultNPCTypeStruct.STR,
|
||||
defaultNPCTypeStruct.STA,
|
||||
defaultNPCTypeStruct.DEX,
|
||||
defaultNPCTypeStruct.AGI,
|
||||
defaultNPCTypeStruct.INT,
|
||||
defaultNPCTypeStruct.WIS,
|
||||
defaultNPCTypeStruct.CHA,
|
||||
defaultNPCTypeStruct.ATK
|
||||
defaultNPCTypeStruct->MR,
|
||||
defaultNPCTypeStruct->CR,
|
||||
defaultNPCTypeStruct->DR,
|
||||
defaultNPCTypeStruct->FR,
|
||||
defaultNPCTypeStruct->PR,
|
||||
defaultNPCTypeStruct->Corrup,
|
||||
defaultNPCTypeStruct->AC,
|
||||
defaultNPCTypeStruct->STR,
|
||||
defaultNPCTypeStruct->STA,
|
||||
defaultNPCTypeStruct->DEX,
|
||||
defaultNPCTypeStruct->AGI,
|
||||
defaultNPCTypeStruct->INT,
|
||||
defaultNPCTypeStruct->WIS,
|
||||
defaultNPCTypeStruct->CHA,
|
||||
defaultNPCTypeStruct->ATK
|
||||
);
|
||||
|
||||
loaded_bot = new Bot(bot_id, atoi(row[0]), atoi(row[1]), atof(row[14]), atoi(row[6]), tempNPCStruct);
|
||||
|
||||
@ -2077,6 +2077,7 @@ bool Client::ChangeFirstName(const char* in_firstname, const char* gmname)
|
||||
|
||||
void Client::SetGM(bool toggle) {
|
||||
m_pp.gm = toggle ? 1 : 0;
|
||||
m_inv.SetGMInventory((bool)m_pp.gm);
|
||||
Message(13, "You are %s a GM.", m_pp.gm ? "now" : "no longer");
|
||||
SendAppearancePacket(AT_GM, m_pp.gm);
|
||||
Save();
|
||||
@ -2639,6 +2640,11 @@ bool Client::CheckAccess(int16 iDBLevel, int16 iDefaultLevel) {
|
||||
}
|
||||
|
||||
void Client::MemorizeSpell(uint32 slot,uint32 spellid,uint32 scribing){
|
||||
if (slot < 0 || slot >= EQEmu::spells::DynamicLookup(ClientVersion(), GetGM())->SpellbookSize)
|
||||
return;
|
||||
if ((spellid < 3 || spellid > EQEmu::spells::DynamicLookup(ClientVersion(), GetGM())->SpellIdMax) && spellid != 0xFFFFFFFF)
|
||||
return;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_MemorizeSpell, sizeof(MemorizeSpell_Struct));
|
||||
MemorizeSpell_Struct* mss=(MemorizeSpell_Struct*)outapp->pBuffer;
|
||||
mss->scribing=scribing;
|
||||
@ -4949,7 +4955,7 @@ void Client::HandleLDoNOpen(NPC *target)
|
||||
if(target->GetLDoNTrapSpellID() != 0)
|
||||
{
|
||||
Message_StringID(13, LDON_ACCIDENT_SETOFF2);
|
||||
target->SpellFinished(target->GetLDoNTrapSpellID(), this, EQEmu::CastingSlot::Item, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff);
|
||||
target->SpellFinished(target->GetLDoNTrapSpellID(), this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff);
|
||||
target->SetLDoNTrapSpellID(0);
|
||||
target->SetLDoNTrapped(false);
|
||||
target->SetLDoNTrapDetected(false);
|
||||
@ -5071,7 +5077,7 @@ void Client::HandleLDoNDisarm(NPC *target, uint16 skill, uint8 type)
|
||||
break;
|
||||
case -1:
|
||||
Message_StringID(13, LDON_ACCIDENT_SETOFF2);
|
||||
target->SpellFinished(target->GetLDoNTrapSpellID(), this, EQEmu::CastingSlot::Item, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff);
|
||||
target->SpellFinished(target->GetLDoNTrapSpellID(), this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff);
|
||||
target->SetLDoNTrapSpellID(0);
|
||||
target->SetLDoNTrapped(false);
|
||||
target->SetLDoNTrapDetected(false);
|
||||
@ -5090,7 +5096,7 @@ void Client::HandleLDoNPickLock(NPC *target, uint16 skill, uint8 type)
|
||||
if(target->IsLDoNTrapped())
|
||||
{
|
||||
Message_StringID(13, LDON_ACCIDENT_SETOFF2);
|
||||
target->SpellFinished(target->GetLDoNTrapSpellID(), this, EQEmu::CastingSlot::Item, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff);
|
||||
target->SpellFinished(target->GetLDoNTrapSpellID(), this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff);
|
||||
target->SetLDoNTrapSpellID(0);
|
||||
target->SetLDoNTrapped(false);
|
||||
target->SetLDoNTrapDetected(false);
|
||||
@ -9074,3 +9080,55 @@ void Client::SetSecondaryWeaponOrnamentation(uint32 model_id)
|
||||
Message(15, "Your secondary weapon appearance has been modified");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used in #goto <player_name>
|
||||
*
|
||||
* @param player_name
|
||||
*/
|
||||
bool Client::GotoPlayer(std::string player_name)
|
||||
{
|
||||
std::string query = StringFormat(
|
||||
"SELECT"
|
||||
" character_data.zone_id,"
|
||||
" character_data.zone_instance,"
|
||||
" character_data.x,"
|
||||
" character_data.y,"
|
||||
" character_data.z,"
|
||||
" character_data.heading "
|
||||
"FROM"
|
||||
" character_data "
|
||||
"WHERE"
|
||||
" TRUE"
|
||||
" AND character_data.name = '%s'"
|
||||
" AND character_data.last_login > (UNIX_TIMESTAMP() - 600) LIMIT 1", player_name.c_str());
|
||||
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
auto zone_id = static_cast<uint32>(atoi(row[0]));
|
||||
auto instance_id = static_cast<uint16>(atoi(row[1]));
|
||||
auto x = static_cast<float>(atof(row[2]));
|
||||
auto y = static_cast<float>(atof(row[3]));
|
||||
auto z = static_cast<float>(atof(row[4]));
|
||||
auto heading = static_cast<float>(atof(row[5]));
|
||||
|
||||
if (instance_id > 0 && !database.CheckInstanceExists(instance_id)) {
|
||||
this->Message(15, "Instance no longer exists...");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (instance_id > 0) {
|
||||
database.AddClientToInstance(instance_id, this->CharacterID());
|
||||
}
|
||||
|
||||
this->MovePC(zone_id, instance_id, x, y, z, heading);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -255,6 +255,8 @@ public:
|
||||
void SetPrimaryWeaponOrnamentation(uint32 model_id);
|
||||
void SetSecondaryWeaponOrnamentation(uint32 model_id);
|
||||
|
||||
bool GotoPlayer(std::string player_name);
|
||||
|
||||
//abstract virtual function implementations required by base abstract class
|
||||
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill);
|
||||
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None);
|
||||
@ -557,10 +559,10 @@ public:
|
||||
virtual int GetCurrentBuffSlots() const;
|
||||
virtual int GetCurrentSongSlots() const;
|
||||
virtual int GetCurrentDiscSlots() const { return 1; }
|
||||
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 int GetMaxBuffSlots() const { return EQEmu::spells::LONG_BUFFS; }
|
||||
virtual int GetMaxSongSlots() const { return EQEmu::spells::SHORT_BUFFS; }
|
||||
virtual int GetMaxDiscSlots() const { return EQEmu::spells::DISC_BUFFS; }
|
||||
virtual int GetMaxTotalSlots() const { return EQEmu::spells::TOTAL_BUFFS; }
|
||||
virtual uint32 GetFirstBuffSlot(bool disc, bool song);
|
||||
virtual uint32 GetLastBuffSlot(bool disc, bool song);
|
||||
virtual void InitializeBuffSlots();
|
||||
|
||||
@ -838,7 +838,7 @@ uint32 Client::CalcCurrentWeight()
|
||||
This is the ONLY instance I have seen where the client is hard coded to particular Item IDs to set a certain property for an item. It is very odd.
|
||||
*/
|
||||
// SoD+ client has no weight for coin
|
||||
if (EQEmu::behavior::Lookup(EQEmu::versions::ConvertClientVersionToMobVersion(ClientVersion()))->CoinHasWeight) {
|
||||
if (EQEmu::behavior::StaticLookup(EQEmu::versions::ConvertClientVersionToMobVersion(ClientVersion()))->CoinHasWeight) {
|
||||
Total += (m_pp.platinum + m_pp.gold + m_pp.silver + m_pp.copper) / 4;
|
||||
}
|
||||
float Packrat = (float)spellbonuses.Packrat + (float)aabonuses.Packrat + (float)itembonuses.Packrat;
|
||||
|
||||
@ -530,10 +530,14 @@ void Client::CompleteConnect()
|
||||
SendAppearancePacket(AT_GuildID, GuildID(), false);
|
||||
SendAppearancePacket(AT_GuildRank, rank, false);
|
||||
}
|
||||
for (uint32 spellInt = 0; spellInt < MAX_PP_REF_SPELLBOOK; spellInt++) {
|
||||
if (m_pp.spell_book[spellInt] < 3 || m_pp.spell_book[spellInt] > 50000)
|
||||
|
||||
// moved to dbload and translators since we iterate there also .. keep m_pp values whatever they are when they get here
|
||||
/*const auto sbs = EQEmu::spells::DynamicLookup(ClientVersion(), GetGM())->SpellbookSize;
|
||||
for (uint32 spellInt = 0; spellInt < sbs; ++spellInt) {
|
||||
if (m_pp.spell_book[spellInt] < 3 || m_pp.spell_book[spellInt] > EQEmu::spells::SPELL_ID_MAX)
|
||||
m_pp.spell_book[spellInt] = 0xFFFFFFFF;
|
||||
}
|
||||
}*/
|
||||
|
||||
//SendAATable();
|
||||
|
||||
if (GetHideMe()) Message(13, "[GM] You are currently hidden to all clients");
|
||||
@ -809,6 +813,16 @@ void Client::CompleteConnect()
|
||||
std::string event_desc = StringFormat("Connect :: Logged into zoneid:%i instid:%i", this->GetZoneID(), this->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_Connect_State, this->CharacterID(), event_desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update last login since this doesn't get updated until a late save later so we can update online status
|
||||
*/
|
||||
database.QueryDatabase(
|
||||
StringFormat(
|
||||
"UPDATE `character_data` SET `last_login` = UNIX_TIMESTAMP() WHERE id = %u",
|
||||
this->CharacterID()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (zone) {
|
||||
@ -1144,8 +1158,8 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
SetClientVersion(Connection()->ClientVersion());
|
||||
m_ClientVersionBit = EQEmu::versions::ConvertClientVersionToClientVersionBit(Connection()->ClientVersion());
|
||||
|
||||
bool siv = m_inv.SetInventoryVersion(m_ClientVersion);
|
||||
Log(Logs::General, Logs::None, "%s inventory version to %s(%i)", (siv ? "Succeeded in setting" : "Failed to set"), ClientVersionName(m_ClientVersion), m_ClientVersion);
|
||||
m_pp.SetPlayerProfileVersion(m_ClientVersion);
|
||||
m_inv.SetInventoryVersion(m_ClientVersion);
|
||||
|
||||
/* Antighost code
|
||||
tmp var is so the search doesnt find this object
|
||||
@ -1185,7 +1199,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
uint32 cid = CharacterID();
|
||||
character_id = cid; /* Global character_id reference */
|
||||
|
||||
/* Flush and reload factions */
|
||||
/* Flush and reload factions */
|
||||
database.RemoveTempFactions(this);
|
||||
database.LoadCharacterFactionValues(cid, factionvalues);
|
||||
|
||||
@ -1222,6 +1236,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
m_pp.platinum_shared = database.GetSharedPlatinum(this->AccountID());
|
||||
|
||||
database.ClearOldRecastTimestamps(cid); /* Clear out our old recast timestamps to keep the DB clean */
|
||||
// set to full support in case they're a gm with items in disabled expansion slots..but, have their gm flag off...
|
||||
// item loss will occur when they use the 'empty' slots, if this is not done
|
||||
m_inv.SetGMInventory(true);
|
||||
loaditems = database.GetInventory(cid, &m_inv); /* Load Character Inventory */
|
||||
database.LoadCharacterBandolier(cid, &m_pp); /* Load Character Bandolier */
|
||||
database.LoadCharacterBindPoint(cid, &m_pp); /* Load Character Bind */
|
||||
@ -1238,7 +1255,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
database.LoadCharacterLeadershipAA(cid, &m_pp); /* Load Character Leadership AA's */
|
||||
database.LoadCharacterTribute(cid, &m_pp); /* Load CharacterTribute */
|
||||
|
||||
/* Load AdventureStats */
|
||||
/* Load AdventureStats */
|
||||
AdventureStats_Struct as;
|
||||
if (database.GetAdventureStats(cid, &as))
|
||||
{
|
||||
@ -1397,6 +1414,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
if (m_pp.ldon_points_tak < 0 || m_pp.ldon_points_tak > 2000000000) { m_pp.ldon_points_tak = 0; }
|
||||
if (m_pp.ldon_points_available < 0 || m_pp.ldon_points_available > 2000000000) { m_pp.ldon_points_available = 0; }
|
||||
|
||||
// need to rework .. not until full scope of change is accounted for, though
|
||||
if (RuleB(World, UseClientBasedExpansionSettings)) {
|
||||
m_pp.expansions = EQEmu::expansions::ConvertClientVersionToExpansionMask(ClientVersion());
|
||||
}
|
||||
@ -1409,7 +1427,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
}
|
||||
|
||||
if (SPDAT_RECORDS > 0) {
|
||||
for (uint32 z = 0; z<MAX_PP_MEMSPELL; z++) {
|
||||
for (uint32 z = 0; z < EQEmu::spells::SPELL_GEM_COUNT; z++) {
|
||||
if (m_pp.mem_spells[z] >= (uint32)SPDAT_RECORDS)
|
||||
UnmemSpell(z, false);
|
||||
}
|
||||
@ -1516,6 +1534,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
Bot::LoadAndSpawnAllZonedBots(this);
|
||||
#endif
|
||||
|
||||
m_inv.SetGMInventory((bool)m_pp.gm); // set to current gm state for calc
|
||||
CalcBonuses();
|
||||
if (RuleB(Zone, EnableLoggedOffReplenishments) &&
|
||||
time(nullptr) - m_pp.lastlogin >= RuleI(Zone, MinOfflineTimeToReplenishments)) {
|
||||
@ -1540,7 +1559,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
}
|
||||
|
||||
/* Load Spell Slot Refresh from Currently Memoried Spells */
|
||||
for (unsigned int i = 0; i < MAX_PP_MEMSPELL; ++i)
|
||||
for (unsigned int i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; ++i)
|
||||
if (IsValidSpell(m_pp.mem_spells[i]))
|
||||
m_pp.spellSlotRefresh[i] = p_timers.GetRemainingTime(pTimerSpellStart + m_pp.mem_spells[i]) * 1000;
|
||||
|
||||
@ -1573,8 +1592,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
if ((m_pp.RestTimer > RuleI(Character, RestRegenTimeToActivate)) && (m_pp.RestTimer > RuleI(Character, RestRegenRaidTimeToActivate)))
|
||||
m_pp.RestTimer = 0;
|
||||
|
||||
/* This checksum should disappear once dynamic structs are in... each struct strategy will do it */
|
||||
CRC32::SetEQChecksum((unsigned char*)&m_pp, sizeof(PlayerProfile_Struct) - 4);
|
||||
/* This checksum should disappear once dynamic structs are in... each struct strategy will do it */ // looks to be in place now
|
||||
//CRC32::SetEQChecksum((unsigned char*)&m_pp, sizeof(PlayerProfile_Struct) - sizeof(m_pp.m_player_profile_version) - 4);
|
||||
// m_pp.checksum = 0; // All server out-bound player profile packets are now translated - no need to waste cycles calculating this...
|
||||
|
||||
outapp = new EQApplicationPacket(OP_PlayerProfile, sizeof(PlayerProfile_Struct));
|
||||
|
||||
@ -1639,6 +1659,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
this is not quite where live sends inventory, they do it after tribute
|
||||
*/
|
||||
if (loaditems) { /* Dont load if a length error occurs */
|
||||
if (admin >= minStatusToBeGM)
|
||||
m_inv.SetGMInventory(true); // set to true to allow expansion-restricted packets through
|
||||
|
||||
BulkSendInventoryItems();
|
||||
/* Send stuff on the cursor which isnt sent in bulk */
|
||||
for (auto iter = m_inv.cursor_cbegin(); iter != m_inv.cursor_cend(); ++iter) {
|
||||
@ -1648,6 +1671,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
const EQEmu::ItemInstance *inst = *iter;
|
||||
SendItemPacket(EQEmu::invslot::slotCursor, inst, ItemPacketLimbo);
|
||||
}
|
||||
|
||||
// this is kinda hackish atm..this process needs to be realigned to allow a contiguous flow
|
||||
m_inv.SetGMInventory((bool)m_pp.gm); // reset back to current gm state
|
||||
}
|
||||
|
||||
/* Task Packets */
|
||||
@ -3996,7 +4022,7 @@ void Client::Handle_OP_CancelTrade(const EQApplicationPacket *app)
|
||||
|
||||
void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
|
||||
{
|
||||
using EQEmu::CastingSlot;
|
||||
using EQEmu::spells::CastingSlot;
|
||||
if (app->size != sizeof(CastSpell_Struct)) {
|
||||
std::cout << "Wrong size: OP_CastSpell, size=" << app->size << ", expected " << sizeof(CastSpell_Struct) << std::endl;
|
||||
return;
|
||||
@ -4017,14 +4043,14 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
|
||||
/* Memorized Spell */
|
||||
if (m_pp.mem_spells[castspell->slot] && m_pp.mem_spells[castspell->slot] == castspell->spell_id) {
|
||||
uint16 spell_to_cast = 0;
|
||||
if (castspell->slot < MAX_PP_MEMSPELL) {
|
||||
if (castspell->slot < EQEmu::spells::SPELL_GEM_COUNT) {
|
||||
spell_to_cast = m_pp.mem_spells[castspell->slot];
|
||||
if (spell_to_cast != castspell->spell_id) {
|
||||
InterruptSpell(castspell->spell_id); //CHEATER!!!
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (castspell->slot >= MAX_PP_MEMSPELL) {
|
||||
else if (castspell->slot >= EQEmu::spells::SPELL_GEM_COUNT) {
|
||||
InterruptSpell();
|
||||
return;
|
||||
}
|
||||
@ -5243,7 +5269,7 @@ void Client::Handle_OP_DeleteSpell(const EQApplicationPacket *app)
|
||||
EQApplicationPacket* outapp = app->Copy();
|
||||
DeleteSpell_Struct* dss = (DeleteSpell_Struct*)outapp->pBuffer;
|
||||
|
||||
if (dss->spell_slot < 0 || dss->spell_slot > int(MAX_PP_SPELLBOOK))
|
||||
if (dss->spell_slot < 0 || dss->spell_slot >= EQEmu::spells::DynamicLookup(ClientVersion(), GetGM())->SpellbookSize)
|
||||
return;
|
||||
|
||||
if (m_pp.spell_book[dss->spell_slot] != SPELLBOOK_UNKNOWN) {
|
||||
@ -8441,7 +8467,7 @@ void Client::Handle_OP_ItemPreview(const EQApplicationPacket *app)
|
||||
|
||||
void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
|
||||
{
|
||||
using EQEmu::CastingSlot;
|
||||
using EQEmu::spells::CastingSlot;
|
||||
if (app->size != sizeof(ItemVerifyRequest_Struct))
|
||||
{
|
||||
Log(Logs::General, Logs::Error, "OP size error: OP_ItemVerifyRequest expected:%i got:%i", sizeof(ItemVerifyRequest_Struct), app->size);
|
||||
@ -9167,7 +9193,7 @@ void Client::Handle_OP_LoadSpellSet(const EQApplicationPacket *app)
|
||||
}
|
||||
int i;
|
||||
LoadSpellSet_Struct* ss = (LoadSpellSet_Struct*)app->pBuffer;
|
||||
for (i = 0; i<MAX_PP_MEMSPELL; i++) {
|
||||
for (i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; i++) {
|
||||
if (ss->spell[i] != 0xFFFFFFFF)
|
||||
UnmemSpell(i, true);
|
||||
}
|
||||
@ -13317,7 +13343,10 @@ void Client::Handle_OP_SwapSpell(const EQApplicationPacket *app)
|
||||
const SwapSpell_Struct* swapspell = (const SwapSpell_Struct*)app->pBuffer;
|
||||
int swapspelltemp;
|
||||
|
||||
if (swapspell->from_slot < 0 || swapspell->from_slot > MAX_PP_SPELLBOOK || swapspell->to_slot < 0 || swapspell->to_slot > MAX_PP_SPELLBOOK)
|
||||
const auto sbs = EQEmu::spells::DynamicLookup(ClientVersion(), GetGM())->SpellbookSize;
|
||||
if (swapspell->from_slot < 0 || swapspell->from_slot >= sbs)
|
||||
return;
|
||||
if (swapspell->to_slot < 0 || swapspell->to_slot >= sbs)
|
||||
return;
|
||||
|
||||
swapspelltemp = m_pp.spell_book[swapspell->from_slot];
|
||||
|
||||
330
zone/command.cpp
330
zone/command.cpp
@ -219,6 +219,7 @@ int command_init(void)
|
||||
command_add("globalview", "Lists all qglobals in cache if you were to do a quest with this target.", 80, command_globalview) ||
|
||||
command_add("gm", "- Turn player target's or your GM flag on or off", 80, command_gm) ||
|
||||
command_add("gmspeed", "[on/off] - Turn GM speed hack on/off for you or your player target", 100, command_gmspeed) ||
|
||||
command_add("gmzone", "[zone_short_name] [zone_version=0] [identifier=gmzone] - Zones to a private GM instance", 100, command_gmzone) ||
|
||||
command_add("goto", "[x] [y] [z] - Teleport to the provided coordinates or to your target", 10, command_goto) ||
|
||||
command_add("grid", "[add/delete] [grid_num] [wandertype] [pausetype] - Create/delete a wandering grid", 170, command_grid) ||
|
||||
command_add("guild", "- Guild manipulation commands. Use argument help for more info.", 10, command_guild) ||
|
||||
@ -413,6 +414,7 @@ int command_init(void)
|
||||
command_add("viewpetition", "[petition number] - View a petition", 20, command_viewpetition) ||
|
||||
command_add("wc", "[wear slot] [material] - Sends an OP_WearChange for your target", 200, command_wc) ||
|
||||
command_add("weather", "[0/1/2/3] (Off/Rain/Snow/Manual) - Change the weather", 80, command_weather) ||
|
||||
command_add("who", "[search]", 20, command_who) ||
|
||||
command_add("worldshutdown", "- Shut down world and all zones", 200, command_worldshutdown) ||
|
||||
command_add("wp", "[add/delete] [grid_num] [pause] [wp_num] [-h] - Add/delete a waypoint to/from a wandering grid", 170, command_wp) ||
|
||||
command_add("wpadd", "[pause] [-h] - Add your current location as a waypoint to your NPC target's AI path", 170, command_wpadd) ||
|
||||
@ -2262,10 +2264,12 @@ void command_sendzonespawns(Client *c, const Seperator *sep)
|
||||
|
||||
void command_zsave(Client *c, const Seperator *sep)
|
||||
{
|
||||
if(zone->SaveZoneCFG())
|
||||
if (zone->SaveZoneCFG()) {
|
||||
c->Message(13, "Zone header saved successfully.");
|
||||
else
|
||||
}
|
||||
else {
|
||||
c->Message(13, "ERROR: Zone header data was NOT saved.");
|
||||
}
|
||||
}
|
||||
|
||||
void command_dbspawn2(Client *c, const Seperator *sep)
|
||||
@ -2609,14 +2613,14 @@ void command_castspell(Client *c, const Seperator *sep)
|
||||
else
|
||||
if (c->GetTarget() == 0)
|
||||
if(c->Admin() >= commandInstacast)
|
||||
c->SpellFinished(spellid, 0, EQEmu::CastingSlot::Item, 0, -1, spells[spellid].ResistDiff);
|
||||
c->SpellFinished(spellid, 0, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spellid].ResistDiff);
|
||||
else
|
||||
c->CastSpell(spellid, 0, EQEmu::CastingSlot::Item, 0);
|
||||
c->CastSpell(spellid, 0, EQEmu::spells::CastingSlot::Item, 0);
|
||||
else
|
||||
if(c->Admin() >= commandInstacast)
|
||||
c->SpellFinished(spellid, c->GetTarget(), EQEmu::CastingSlot::Item, 0, -1, spells[spellid].ResistDiff);
|
||||
c->SpellFinished(spellid, c->GetTarget(), EQEmu::spells::CastingSlot::Item, 0, -1, spells[spellid].ResistDiff);
|
||||
else
|
||||
c->CastSpell(spellid, c->GetTarget()->GetID(), EQEmu::CastingSlot::Item, 0);
|
||||
c->CastSpell(spellid, c->GetTarget()->GetID(), EQEmu::spells::CastingSlot::Item, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4426,18 +4430,94 @@ void command_fixmob(Client *c, const Seperator *sep)
|
||||
|
||||
void command_gmspeed(Client *c, const Seperator *sep)
|
||||
{
|
||||
bool state=atobool(sep->arg[1]);
|
||||
Client *t=c;
|
||||
bool state = atobool(sep->arg[1]);
|
||||
Client *t = c;
|
||||
|
||||
if(c->GetTarget() && c->GetTarget()->IsClient())
|
||||
t=c->GetTarget()->CastToClient();
|
||||
|
||||
if(sep->arg[1][0] != 0) {
|
||||
database.SetGMSpeed(t->AccountID(), state?1:0);
|
||||
c->Message(0, "Turning GMSpeed %s for %s (zone to take effect)", state?"On":"Off", t->GetName());
|
||||
if (c->GetTarget() && c->GetTarget()->IsClient()) {
|
||||
t = c->GetTarget()->CastToClient();
|
||||
}
|
||||
else
|
||||
|
||||
if (sep->arg[1][0] != 0) {
|
||||
database.SetGMSpeed(t->AccountID(), state ? 1 : 0);
|
||||
c->Message(0, "Turning GMSpeed %s for %s (zone to take effect)", state ? "On" : "Off", t->GetName());
|
||||
}
|
||||
else {
|
||||
c->Message(0, "Usage: #gmspeed [on/off]");
|
||||
}
|
||||
}
|
||||
|
||||
void command_gmzone(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (!sep->arg[1]) {
|
||||
c->Message(0, "Usage");
|
||||
c->Message(0, "-------");
|
||||
c->Message(0, "#gmzone [zone_short_name] [zone_version=0]");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string zone_short_name_string = sep->arg[1];
|
||||
const char *zone_short_name = sep->arg[1];
|
||||
auto zone_version = static_cast<uint32>(sep->arg[2] ? atoi(sep->arg[2]) : 0);
|
||||
std::string identifier = "gmzone";
|
||||
uint32 zone_id = database.GetZoneID(zone_short_name);
|
||||
uint32 duration = 100000000;
|
||||
uint16 instance_id = 0;
|
||||
|
||||
if (zone_id == 0) {
|
||||
c->Message(13, "Invalid zone specified");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sep->arg[3] && sep->arg[3][0]) {
|
||||
identifier = sep->arg[3];
|
||||
}
|
||||
|
||||
std::string bucket_key = StringFormat("%s-%s-instance", zone_short_name, identifier.c_str());
|
||||
std::string existing_zone_instance = DataBucket::GetData(bucket_key);
|
||||
|
||||
if (existing_zone_instance.length() > 0) {
|
||||
instance_id = std::stoi(existing_zone_instance);
|
||||
|
||||
c->Message(15, "Found already created instance (%s) (%u)", zone_short_name, instance_id);
|
||||
}
|
||||
|
||||
if (instance_id == 0) {
|
||||
if (!database.GetUnusedInstanceID(instance_id)) {
|
||||
c->Message(13, "Server was unable to find a free instance id.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!database.CreateInstance(instance_id, zone_id, zone_version, duration)) {
|
||||
c->Message(13, "Server was unable to create a new instance.");
|
||||
return;
|
||||
}
|
||||
|
||||
c->Message(15, "New private GM instance %s was created with id %lu.", zone_short_name, (unsigned long) instance_id);
|
||||
DataBucket::SetData(bucket_key, std::to_string(instance_id));
|
||||
}
|
||||
|
||||
if (instance_id > 0) {
|
||||
float target_x = -1, target_y = -1, target_z = -1;
|
||||
int16 min_status = 0;
|
||||
uint8 min_level = 0;
|
||||
|
||||
if (!database.GetSafePoints(
|
||||
zone_short_name,
|
||||
zone_version,
|
||||
&target_x,
|
||||
&target_y,
|
||||
&target_z,
|
||||
&min_status,
|
||||
&min_level
|
||||
)) {
|
||||
c->Message(13, "Failed to find safe coordinates for specified zone");
|
||||
}
|
||||
|
||||
c->Message(15, "Zoning to private GM instance (%s) (%u)", zone_short_name, instance_id);
|
||||
|
||||
c->AssignToInstance(instance_id);
|
||||
c->MovePC(zone_id, instance_id, target_x, target_y, target_z, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void command_title(Client *c, const Seperator *sep)
|
||||
@ -4620,7 +4700,7 @@ void command_memspell(Client *c, const Seperator *sep)
|
||||
{
|
||||
slot = atoi(sep->arg[1]) - 1;
|
||||
spell_id = atoi(sep->arg[2]);
|
||||
if (slot > MAX_PP_MEMSPELL || spell_id >= SPDAT_RECORDS)
|
||||
if (slot > EQEmu::spells::SPELL_GEM_COUNT || spell_id >= SPDAT_RECORDS)
|
||||
{
|
||||
c->Message(0, "Error: #MemSpell: Arguement out of range");
|
||||
}
|
||||
@ -5180,7 +5260,15 @@ void command_killallnpcs(Client *c, const Seperator *sep)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entity->IsInvisible() || !entity->IsAttackAllowed(c)) {
|
||||
bool is_not_attackable =
|
||||
(
|
||||
entity->IsInvisible() ||
|
||||
!entity->IsAttackAllowed(c) ||
|
||||
entity->GetRace() == 127 ||
|
||||
entity->GetRace() == 240
|
||||
);
|
||||
|
||||
if (is_not_attackable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -5349,13 +5437,65 @@ void command_loc(Client *c, const Seperator *sep)
|
||||
|
||||
void command_goto(Client *c, const Seperator *sep)
|
||||
{
|
||||
// goto function
|
||||
if (sep->arg[1][0] == '\0' && c->GetTarget())
|
||||
c->MovePC(zone->GetZoneID(), zone->GetInstanceID(), c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ(), c->GetTarget()->GetHeading());
|
||||
else if (!(sep->IsNumber(1) && sep->IsNumber(2) && sep->IsNumber(3)))
|
||||
/**
|
||||
* Goto via target and no args
|
||||
*/
|
||||
if (sep->arg[1][0] == '\0' && c->GetTarget()) {
|
||||
c->MovePC(
|
||||
zone->GetZoneID(),
|
||||
zone->GetInstanceID(),
|
||||
c->GetTarget()->GetX(),
|
||||
c->GetTarget()->GetY(),
|
||||
c->GetTarget()->GetZ(),
|
||||
c->GetTarget()->GetHeading());
|
||||
}
|
||||
|
||||
/**
|
||||
* Goto via player name
|
||||
*/
|
||||
else if (!sep->IsNumber(1) && sep->arg[1]) {
|
||||
|
||||
/**
|
||||
* Find them in zone first
|
||||
*/
|
||||
const char *player_name = sep->arg[1];
|
||||
std::string player_name_string = sep->arg[1];
|
||||
Client *client = entity_list.GetClientByName(player_name);
|
||||
if (client) {
|
||||
c->MovePC(
|
||||
zone->GetZoneID(),
|
||||
zone->GetInstanceID(),
|
||||
client->GetX(),
|
||||
client->GetY(),
|
||||
client->GetZ(),
|
||||
client->GetHeading());
|
||||
|
||||
c->Message(15, "Goto player '%s' same zone", player_name_string.c_str());
|
||||
}
|
||||
else if (c->GotoPlayer(player_name_string)) {
|
||||
c->Message(15, "Goto player '%s' different zone", player_name_string.c_str());
|
||||
}
|
||||
else {
|
||||
c->Message(15, "Player '%s' not found", player_name_string.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Goto via x y z
|
||||
*/
|
||||
else if (sep->IsNumber(1) && sep->IsNumber(2) && sep->IsNumber(3)) {
|
||||
c->MovePC(
|
||||
zone->GetZoneID(),
|
||||
zone->GetInstanceID(),
|
||||
atof(sep->arg[1]),
|
||||
atof(sep->arg[2]),
|
||||
atof(sep->arg[3]),
|
||||
c->GetHeading());
|
||||
}
|
||||
else {
|
||||
c->Message(0, "Usage: #goto [x y z]");
|
||||
else
|
||||
c->MovePC(zone->GetZoneID(), zone->GetInstanceID(), atof(sep->arg[1]), atof(sep->arg[2]), atof(sep->arg[3]), c->GetHeading());
|
||||
c->Message(0, "Usage: #goto [player_name]");
|
||||
}
|
||||
}
|
||||
|
||||
void command_iteminfo(Client *c, const Seperator *sep)
|
||||
@ -6301,7 +6441,15 @@ void command_scribespells(Client *c, const Seperator *sep)
|
||||
c->Message(0, "Scribing spells for %s.", t->GetName());
|
||||
Log(Logs::General, Logs::Normal, "Scribe spells request for %s from %s, levels: %u -> %u", t->GetName(), c->GetName(), min_level, max_level);
|
||||
|
||||
for(curspell = 0, book_slot = t->GetNextAvailableSpellBookSlot(), count = 0; curspell < SPDAT_RECORDS && book_slot < MAX_PP_SPELLBOOK; curspell++, book_slot = t->GetNextAvailableSpellBookSlot(book_slot))
|
||||
for (
|
||||
curspell = 0,
|
||||
book_slot = t->GetNextAvailableSpellBookSlot(),
|
||||
count = 0; // ;
|
||||
curspell < SPDAT_RECORDS &&
|
||||
book_slot < EQEmu::spells::SPELLBOOK_SIZE; // ;
|
||||
curspell++,
|
||||
book_slot = t->GetNextAvailableSpellBookSlot(book_slot)
|
||||
)
|
||||
{
|
||||
if
|
||||
(
|
||||
@ -8345,7 +8493,7 @@ void command_rules(Client *c, const Seperator *sep) {
|
||||
c->Message(0, "(%d) %s", cur->first, cur->second.c_str());
|
||||
}
|
||||
} else if(!strcasecmp(sep->arg[1], "reload")) {
|
||||
RuleManager::Instance()->LoadRules(&database, RuleManager::Instance()->GetActiveRuleset());
|
||||
RuleManager::Instance()->LoadRules(&database, RuleManager::Instance()->GetActiveRuleset(), true);
|
||||
c->Message(0, "The active ruleset (%s (%d)) has been reloaded", RuleManager::Instance()->GetActiveRuleset(),
|
||||
RuleManager::Instance()->GetActiveRulesetID());
|
||||
} else if(!strcasecmp(sep->arg[1], "switch")) {
|
||||
@ -8361,7 +8509,7 @@ void command_rules(Client *c, const Seperator *sep) {
|
||||
}
|
||||
|
||||
//TODO: we likely want to reload this ruleset everywhere...
|
||||
RuleManager::Instance()->LoadRules(&database, sep->arg[2]);
|
||||
RuleManager::Instance()->LoadRules(&database, sep->arg[2], true);
|
||||
|
||||
c->Message(0, "The selected ruleset has been changed to (%s (%d)) and reloaded locally", sep->arg[2], rsid);
|
||||
} else if(!strcasecmp(sep->arg[1], "load")) {
|
||||
@ -8371,7 +8519,7 @@ void command_rules(Client *c, const Seperator *sep) {
|
||||
c->Message(13, "Unknown rule set '%s'", sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
RuleManager::Instance()->LoadRules(&database, sep->arg[2]);
|
||||
RuleManager::Instance()->LoadRules(&database, sep->arg[2], true);
|
||||
c->Message(0, "Loaded ruleset '%s' (%d) locally", sep->arg[2], rsid);
|
||||
} else if(!strcasecmp(sep->arg[1], "store")) {
|
||||
if(sep->argnum == 1) {
|
||||
@ -8395,9 +8543,9 @@ void command_rules(Client *c, const Seperator *sep) {
|
||||
return;
|
||||
}
|
||||
} else if(!strcasecmp(sep->arg[1], "reset")) {
|
||||
RuleManager::Instance()->ResetRules();
|
||||
RuleManager::Instance()->ResetRules(true);
|
||||
c->Message(0, "The running ruleset has been set to defaults");
|
||||
|
||||
|
||||
} else if(!strcasecmp(sep->arg[1], "get")) {
|
||||
if(sep->argnum != 2) {
|
||||
c->Message(13, "Invalid argument count, see help.");
|
||||
@ -8414,7 +8562,7 @@ void command_rules(Client *c, const Seperator *sep) {
|
||||
c->Message(13, "Invalid argument count, see help.");
|
||||
return;
|
||||
}
|
||||
if(!RuleManager::Instance()->SetRule(sep->arg[2], sep->arg[3])) {
|
||||
if(!RuleManager::Instance()->SetRule(sep->arg[2], sep->arg[3], nullptr, false, true)) {
|
||||
c->Message(13, "Failed to modify rule");
|
||||
} else {
|
||||
c->Message(0, "Rule modified locally.");
|
||||
@ -8424,7 +8572,7 @@ void command_rules(Client *c, const Seperator *sep) {
|
||||
c->Message(13, "Invalid argument count, see help.");
|
||||
return;
|
||||
}
|
||||
if(!RuleManager::Instance()->SetRule(sep->arg[2], sep->arg[3], &database, true)) {
|
||||
if(!RuleManager::Instance()->SetRule(sep->arg[2], sep->arg[3], &database, true, true)) {
|
||||
c->Message(13, "Failed to modify rule");
|
||||
} else {
|
||||
c->Message(0, "Rule modified locally and in the database.");
|
||||
@ -11785,6 +11933,126 @@ void command_scale(Client *c, const Seperator *sep)
|
||||
}
|
||||
}
|
||||
|
||||
void command_who(Client *c, const Seperator *sep)
|
||||
{
|
||||
std::string query =
|
||||
"SELECT\n"
|
||||
" character_data.account_id,\n"
|
||||
" character_data.name,\n"
|
||||
" character_data.zone_id,\n"
|
||||
" COALESCE((select zone.short_name from zone where zoneidnumber = character_data.zone_id LIMIT 1), \"Not Found\") as zone_name,\n"
|
||||
" character_data.zone_instance,\n"
|
||||
" COALESCE((select guilds.name from guilds where id = ((select guild_id from guild_members where char_id = character_data.id))), \"\") as guild_name,\n"
|
||||
" character_data.level,\n"
|
||||
" character_data.race,\n"
|
||||
" character_data.class,\n"
|
||||
" COALESCE((select account.status from account where account.id = character_data.account_id LIMIT 1), 0) as account_status,\n"
|
||||
" COALESCE((select account.name from account where account.id = character_data.account_id LIMIT 1), \"\") as account_name,\n"
|
||||
" COALESCE((select account_ip.ip from account_ip where account_ip.accid = character_data.account_id ORDER BY account_ip.lastused DESC LIMIT 1), \"\") as account_ip\n"
|
||||
"FROM\n"
|
||||
" character_data\n"
|
||||
"WHERE\n"
|
||||
" last_login > (UNIX_TIMESTAMP() - 600)\n"
|
||||
"ORDER BY character_data.name;";
|
||||
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return;
|
||||
|
||||
if (results.RowCount() == 0) {
|
||||
c->Message(15, "No results found");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string search_string;
|
||||
|
||||
if (sep->arg[1]) {
|
||||
search_string = str_tolower(sep->arg[1]);
|
||||
}
|
||||
|
||||
int found_count = 0;
|
||||
|
||||
c->Message(5, "Players in EverQuest");
|
||||
c->Message(5, "--------------------");
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
auto account_id = static_cast<uint32>(atoi(row[0]));
|
||||
std::string player_name = row[1];
|
||||
auto zone_id = static_cast<uint32>(atoi(row[2]));
|
||||
std::string zone_short_name = row[3];
|
||||
auto zone_instance = static_cast<uint32>(atoi(row[4]));
|
||||
std::string guild_name = row[5];
|
||||
auto player_level = static_cast<uint32>(atoi(row[6]));
|
||||
auto player_race = static_cast<uint32>(atoi(row[7]));
|
||||
auto player_class = static_cast<uint32>(atoi(row[8]));
|
||||
auto account_status = static_cast<uint32>(atoi(row[9]));
|
||||
std::string account_name = row[10];
|
||||
std::string account_ip = row[11];
|
||||
|
||||
std::string base_class_name = GetClassIDName(static_cast<uint8>(player_class), 1);
|
||||
std::string displayed_race_name = GetRaceIDName(static_cast<uint16>(player_race));
|
||||
|
||||
if (search_string.length() > 0) {
|
||||
bool found_search_term =
|
||||
(
|
||||
str_tolower(player_name).find(search_string) != std::string::npos ||
|
||||
str_tolower(zone_short_name).find(search_string) != std::string::npos ||
|
||||
str_tolower(displayed_race_name).find(search_string) != std::string::npos ||
|
||||
str_tolower(base_class_name).find(search_string) != std::string::npos ||
|
||||
str_tolower(guild_name).find(search_string) != std::string::npos ||
|
||||
str_tolower(account_name).find(search_string) != std::string::npos ||
|
||||
str_tolower(account_ip).find(search_string) != std::string::npos
|
||||
);
|
||||
|
||||
if (!found_search_term) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
std::string displayed_guild_name;
|
||||
if (guild_name.length() > 0) {
|
||||
displayed_guild_name = EQEmu::SayLinkEngine::GenerateQuestSaylink(
|
||||
StringFormat(
|
||||
"#who \"%s\"",
|
||||
guild_name.c_str()),
|
||||
false,
|
||||
StringFormat("<%s>", guild_name.c_str())
|
||||
);
|
||||
}
|
||||
|
||||
std::string goto_saylink = EQEmu::SayLinkEngine::GenerateQuestSaylink(
|
||||
StringFormat("#goto %s", player_name.c_str()), false, "Goto"
|
||||
);
|
||||
|
||||
std::string display_class_name = GetClassIDName(static_cast<uint8>(player_class), static_cast<uint8>(player_level));
|
||||
|
||||
c->Message(
|
||||
5, "%s[%u %s] %s (%s) %s ZONE: %s (%u) (%s) (%s) (%s)",
|
||||
(account_status > 0 ? "* GM * " : ""),
|
||||
player_level,
|
||||
EQEmu::SayLinkEngine::GenerateQuestSaylink(StringFormat("#who %s", base_class_name.c_str()), false, display_class_name).c_str(),
|
||||
player_name.c_str(),
|
||||
EQEmu::SayLinkEngine::GenerateQuestSaylink(StringFormat("#who %s", displayed_race_name.c_str()), false, displayed_race_name).c_str(),
|
||||
displayed_guild_name.c_str(),
|
||||
EQEmu::SayLinkEngine::GenerateQuestSaylink(StringFormat("#who %s", zone_short_name.c_str()), false, zone_short_name).c_str(),
|
||||
zone_instance,
|
||||
goto_saylink.c_str(),
|
||||
EQEmu::SayLinkEngine::GenerateQuestSaylink(StringFormat("#who %s", account_name.c_str()), false, account_name).c_str(),
|
||||
EQEmu::SayLinkEngine::GenerateQuestSaylink(StringFormat("#who %s", account_ip.c_str()), false, account_ip).c_str()
|
||||
);
|
||||
|
||||
found_count++;
|
||||
}
|
||||
|
||||
std::string message = (
|
||||
found_count > 0 ?
|
||||
StringFormat("There is %i player(s) in EverQuest", found_count).c_str() :
|
||||
"There are no players in EverQuest that match those who filters."
|
||||
);
|
||||
|
||||
c->Message(5, message.c_str());
|
||||
}
|
||||
|
||||
// All new code added to command.cpp should be BEFORE this comment line. Do no append code to this file below the BOTS code block.
|
||||
#ifdef BOTS
|
||||
#include "bot_command.h"
|
||||
|
||||
@ -117,6 +117,7 @@ void command_givemoney(Client *c, const Seperator *sep);
|
||||
void command_globalview(Client* c, const Seperator *sep);
|
||||
void command_gm(Client *c, const Seperator *sep);
|
||||
void command_gmspeed(Client *c, const Seperator *sep);
|
||||
void command_gmzone(Client *c, const Seperator *sep);
|
||||
void command_goto(Client *c, const Seperator *sep);
|
||||
void command_grid(Client *c, const Seperator *sep);
|
||||
void command_guild(Client *c, const Seperator *sep);
|
||||
@ -325,6 +326,7 @@ void command_viewnpctype(Client *c, const Seperator *sep);
|
||||
void command_viewpetition(Client *c, const Seperator *sep);
|
||||
void command_wc(Client *c, const Seperator *sep);
|
||||
void command_weather(Client *c, const Seperator *sep);
|
||||
void command_who(Client *c, const Seperator *sep);
|
||||
void command_worldshutdown(Client *c, const Seperator *sep);
|
||||
void command_wp(Client *c, const Seperator *sep);
|
||||
void command_wpadd(Client *c, const Seperator *sep);
|
||||
|
||||
@ -1374,7 +1374,7 @@ void Corpse::QueryLoot(Client* to) {
|
||||
cur = itemlist.begin();
|
||||
end = itemlist.end();
|
||||
|
||||
int corpselootlimit = EQEmu::inventory::Lookup(EQEmu::versions::ConvertClientVersionToMobVersion(to->ClientVersion()))->InventoryTypeSize.Corpse;
|
||||
int corpselootlimit = to->GetInv().GetLookup()->InventoryTypeSize.Corpse;
|
||||
|
||||
for(; cur != end; ++cur) {
|
||||
ServerLootItem_Struct* sitem = *cur;
|
||||
|
||||
@ -643,9 +643,9 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
|
||||
}
|
||||
|
||||
if (reduced_recast > 0)
|
||||
CastSpell(spell_id, target, EQEmu::CastingSlot::Discipline, -1, -1, 0, -1, (uint32)DiscTimer, reduced_recast);
|
||||
CastSpell(spell_id, target, EQEmu::spells::CastingSlot::Discipline, -1, -1, 0, -1, (uint32)DiscTimer, reduced_recast);
|
||||
else{
|
||||
CastSpell(spell_id, target, EQEmu::CastingSlot::Discipline);
|
||||
CastSpell(spell_id, target, EQEmu::spells::CastingSlot::Discipline);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -653,7 +653,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
|
||||
}
|
||||
else
|
||||
{
|
||||
CastSpell(spell_id, target, EQEmu::CastingSlot::Discipline);
|
||||
CastSpell(spell_id, target, EQEmu::spells::CastingSlot::Discipline);
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
@ -3622,6 +3622,36 @@ XS(XS__UpdateZoneHeader) {
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS__set_rule);
|
||||
XS(XS__set_rule) {
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: quest::set_rule(string rule_name, string rule_value)");
|
||||
|
||||
std::string rule_name = (std::string) SvPV_nolen(ST(0));
|
||||
std::string rule_value = (std::string) SvPV_nolen(ST(1));
|
||||
RuleManager::Instance()->SetRule(rule_name.c_str(), rule_value.c_str());
|
||||
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS__get_rule);
|
||||
XS(XS__get_rule) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: quest::get_rule(string rule_name)");
|
||||
|
||||
dXSTARG;
|
||||
std::string rule_name = (std::string) SvPV_nolen(ST(0));
|
||||
std::string rule_value;
|
||||
RuleManager::Instance()->GetRule(rule_name.c_str(), rule_value);
|
||||
|
||||
sv_setpv(TARG, rule_value.c_str());
|
||||
XSprePUSH;
|
||||
PUSHTARG;
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS__get_data);
|
||||
XS(XS__get_data) {
|
||||
dXSARGS;
|
||||
@ -3734,6 +3764,8 @@ EXTERN_C XS(boot_quest) {
|
||||
newXS(strcpy(buf, "GetTimeSeconds"), XS__GetTimeSeconds, file);
|
||||
newXS(strcpy(buf, "GetZoneID"), XS__GetZoneID, file);
|
||||
newXS(strcpy(buf, "GetZoneLongName"), XS__GetZoneLongName, file);
|
||||
newXS(strcpy(buf, "set_rule"), XS__set_rule, file);
|
||||
newXS(strcpy(buf, "get_rule"), XS__get_rule, file);
|
||||
newXS(strcpy(buf, "get_data"), XS__get_data, file);
|
||||
newXS(strcpy(buf, "get_data_expires"), XS__get_data_expires, file);
|
||||
newXS(strcpy(buf, "set_data"), XS__set_data, file);
|
||||
|
||||
@ -650,8 +650,6 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue)
|
||||
|
||||
parse->EventNPC(EVENT_SPAWN, npc, nullptr, "", 0);
|
||||
|
||||
npc->FixZ();
|
||||
|
||||
uint16 emoteid = npc->GetEmoteID();
|
||||
if (emoteid != 0)
|
||||
npc->DoNPCEmote(ONSPAWN, emoteid);
|
||||
|
||||
@ -814,6 +814,16 @@ std::string lua_say_link(const char *phrase) {
|
||||
return quest_manager.saylink(text, false, text);
|
||||
}
|
||||
|
||||
void lua_set_rule(std::string rule_name, std::string rule_value) {
|
||||
RuleManager::Instance()->SetRule(rule_name.c_str(), rule_value.c_str());
|
||||
}
|
||||
|
||||
std::string lua_get_rule(std::string rule_name) {
|
||||
std::string rule_value;
|
||||
RuleManager::Instance()->GetRule(rule_name.c_str(), rule_value);
|
||||
return rule_value;
|
||||
}
|
||||
|
||||
std::string lua_get_data(std::string bucket_key) {
|
||||
return DataBucket::GetData(bucket_key);
|
||||
}
|
||||
@ -1687,6 +1697,8 @@ luabind::scope lua_register_general() {
|
||||
luabind::def("say_link", (std::string(*)(const char*,bool,const char*))&lua_say_link),
|
||||
luabind::def("say_link", (std::string(*)(const char*,bool))&lua_say_link),
|
||||
luabind::def("say_link", (std::string(*)(const char*))&lua_say_link),
|
||||
luabind::def("set_rule", (void(*)(std::string, std::string))&lua_set_rule),
|
||||
luabind::def("get_rule", (std::string(*)(std::string))&lua_get_rule),
|
||||
luabind::def("get_data", (std::string(*)(std::string))&lua_get_data),
|
||||
luabind::def("get_data_expires", (std::string(*)(std::string))&lua_get_data_expires),
|
||||
luabind::def("set_data", (void(*)(std::string, std::string))&lua_set_data),
|
||||
|
||||
@ -770,28 +770,28 @@ bool Lua_Mob::CastSpell(int spell_id, int target_id) {
|
||||
|
||||
bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::CastingSlot>(slot));
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::spells::CastingSlot>(slot));
|
||||
}
|
||||
|
||||
bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::CastingSlot>(slot), cast_time);
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::spells::CastingSlot>(slot), cast_time);
|
||||
}
|
||||
|
||||
bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, int mana_cost) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::CastingSlot>(slot), cast_time, mana_cost);
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::spells::CastingSlot>(slot), cast_time, mana_cost);
|
||||
}
|
||||
|
||||
bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, int mana_cost, int item_slot) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::CastingSlot>(slot), cast_time, mana_cost, nullptr, static_cast<uint32>(item_slot));
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::spells::CastingSlot>(slot), cast_time, mana_cost, nullptr, static_cast<uint32>(item_slot));
|
||||
}
|
||||
|
||||
bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, int mana_cost, int item_slot, int timer,
|
||||
int timer_duration) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::CastingSlot>(slot), cast_time, mana_cost, nullptr, static_cast<uint32>(item_slot),
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::spells::CastingSlot>(slot), cast_time, mana_cost, nullptr, static_cast<uint32>(item_slot),
|
||||
static_cast<uint32>(timer), static_cast<uint32>(timer_duration));
|
||||
}
|
||||
|
||||
@ -800,7 +800,7 @@ bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, in
|
||||
Lua_Safe_Call_Bool();
|
||||
int16 res = resist_adjust;
|
||||
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::CastingSlot>(slot), cast_time, mana_cost, nullptr, static_cast<uint32>(item_slot),
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::spells::CastingSlot>(slot), cast_time, mana_cost, nullptr, static_cast<uint32>(item_slot),
|
||||
static_cast<uint32>(timer), static_cast<uint32>(timer_duration), &res);
|
||||
}
|
||||
|
||||
@ -811,27 +811,27 @@ bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target) {
|
||||
|
||||
bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target, int slot) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->SpellFinished(spell_id, target, static_cast<EQEmu::CastingSlot>(slot));
|
||||
return self->SpellFinished(spell_id, target, static_cast<EQEmu::spells::CastingSlot>(slot));
|
||||
}
|
||||
|
||||
bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target, int slot, int mana_used) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->SpellFinished(spell_id, target, static_cast<EQEmu::CastingSlot>(slot), mana_used);
|
||||
return self->SpellFinished(spell_id, target, static_cast<EQEmu::spells::CastingSlot>(slot), mana_used);
|
||||
}
|
||||
|
||||
bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target, int slot, int mana_used, uint32 inventory_slot) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->SpellFinished(spell_id, target, static_cast<EQEmu::CastingSlot>(slot), mana_used, inventory_slot);
|
||||
return self->SpellFinished(spell_id, target, static_cast<EQEmu::spells::CastingSlot>(slot), mana_used, inventory_slot);
|
||||
}
|
||||
|
||||
bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target, int slot, int mana_used, uint32 inventory_slot, int resist_adjust) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->SpellFinished(spell_id, target, static_cast<EQEmu::CastingSlot>(slot), mana_used, inventory_slot, resist_adjust);
|
||||
return self->SpellFinished(spell_id, target, static_cast<EQEmu::spells::CastingSlot>(slot), mana_used, inventory_slot, resist_adjust);
|
||||
}
|
||||
|
||||
bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target, int slot, int mana_used, uint32 inventory_slot, int resist_adjust, bool proc) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->SpellFinished(spell_id, target, static_cast<EQEmu::CastingSlot>(slot), mana_used, inventory_slot, resist_adjust, proc);
|
||||
return self->SpellFinished(spell_id, target, static_cast<EQEmu::spells::CastingSlot>(slot), mana_used, inventory_slot, resist_adjust, proc);
|
||||
}
|
||||
|
||||
void Lua_Mob::SendBeginCast(int spell_id, int cast_time) {
|
||||
|
||||
@ -1993,7 +1993,7 @@ bool Merc::AIDoSpellCast(uint16 spellid, Mob* tar, int32 mana_cost, uint32* oDon
|
||||
SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0);
|
||||
SetMoving(false);
|
||||
|
||||
result = CastSpell(spellid, tar->GetID(), EQEmu::CastingSlot::Gem2, -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, 0);
|
||||
result = CastSpell(spellid, tar->GetID(), EQEmu::spells::CastingSlot::Gem2, -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, 0);
|
||||
|
||||
if(IsCasting() && IsSitting())
|
||||
Stand();
|
||||
@ -4045,7 +4045,7 @@ bool Merc::UseDiscipline(int32 spell_id, int32 target) {
|
||||
if(IsCasting())
|
||||
InterruptSpell();
|
||||
|
||||
CastSpell(spell_id, target, EQEmu::CastingSlot::Discipline);
|
||||
CastSpell(spell_id, target, EQEmu::spells::CastingSlot::Discipline);
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
53
zone/mob.cpp
53
zone/mob.cpp
@ -1663,15 +1663,10 @@ void Mob::ShowBuffList(Client* client) {
|
||||
}
|
||||
|
||||
void Mob::GMMove(float x, float y, float z, float heading, bool SendUpdate) {
|
||||
if (IsCorpse() || (IsClient() && !IsAIControlled())) {
|
||||
m_Position.x = x;
|
||||
m_Position.y = y;
|
||||
m_Position.z = z;
|
||||
mMovementManager->SendCommandToClients(this, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeAny);
|
||||
}
|
||||
else {
|
||||
Teleport(glm::vec4(x, y, z, heading));
|
||||
}
|
||||
m_Position.x = x;
|
||||
m_Position.y = y;
|
||||
m_Position.z = z;
|
||||
mMovementManager->SendCommandToClients(this, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeAny);
|
||||
|
||||
if (IsNPC()) {
|
||||
CastToNPC()->SaveGuardSpot(glm::vec4(x, y, z, heading));
|
||||
@ -3128,12 +3123,12 @@ void Mob::ExecWeaponProc(const EQEmu::ItemInstance *inst, uint16 spell_id, Mob *
|
||||
twinproc = true;
|
||||
|
||||
if (IsBeneficialSpell(spell_id) && (!IsNPC() || (IsNPC() && CastToNPC()->GetInnateProcSpellID() != spell_id))) { // NPC innate procs don't take this path ever
|
||||
SpellFinished(spell_id, this, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff, true, level_override);
|
||||
SpellFinished(spell_id, this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff, true, level_override);
|
||||
if(twinproc)
|
||||
SpellOnTarget(spell_id, this, false, false, 0, true, level_override);
|
||||
}
|
||||
else if(!(on->IsClient() && on->CastToClient()->dead)) { //dont proc on dead clients
|
||||
SpellFinished(spell_id, on, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff, true, level_override);
|
||||
SpellFinished(spell_id, on, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff, true, level_override);
|
||||
if(twinproc)
|
||||
SpellOnTarget(spell_id, on, false, false, 0, true, level_override);
|
||||
}
|
||||
@ -3470,7 +3465,7 @@ void Mob::TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger)
|
||||
trigger_spell_id = CastToClient()->CalcAAFocus(focusTriggerOnCast, *rank, spell_id);
|
||||
|
||||
if (IsValidSpell(trigger_spell_id) && GetTarget())
|
||||
SpellFinished(trigger_spell_id, GetTarget(), EQEmu::CastingSlot::Item, 0, -1,
|
||||
SpellFinished(trigger_spell_id, GetTarget(), EQEmu::spells::CastingSlot::Item, 0, -1,
|
||||
spells[trigger_spell_id].ResistDiff);
|
||||
}
|
||||
|
||||
@ -3478,7 +3473,7 @@ void Mob::TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger)
|
||||
trigger_spell_id = CalcFocusEffect(focusTriggerOnCast, focus_spell, spell_id);
|
||||
|
||||
if (IsValidSpell(trigger_spell_id) && GetTarget()) {
|
||||
SpellFinished(trigger_spell_id, GetTarget(), EQEmu::CastingSlot::Item, 0, -1,
|
||||
SpellFinished(trigger_spell_id, GetTarget(), EQEmu::spells::CastingSlot::Item, 0, -1,
|
||||
spells[trigger_spell_id].ResistDiff);
|
||||
CheckNumHitsRemaining(NumHit::MatchingSpells, -1, focus_spell);
|
||||
}
|
||||
@ -3509,7 +3504,7 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect)
|
||||
{
|
||||
// If we trigger an effect then its over.
|
||||
if (IsValidSpell(spells[spell_id].base2[i])){
|
||||
SpellFinished(spells[spell_id].base2[i], target, EQEmu::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff);
|
||||
SpellFinished(spells[spell_id].base2[i], target, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -3528,7 +3523,7 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect)
|
||||
if(zone->random.Int(0, 100) <= spells[spell_id].base[effect])
|
||||
{
|
||||
if (IsValidSpell(spells[spell_id].base2[effect])){
|
||||
SpellFinished(spells[spell_id].base2[effect], target, EQEmu::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[effect]].ResistDiff);
|
||||
SpellFinished(spells[spell_id].base2[effect], target, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[effect]].ResistDiff);
|
||||
return true; //Only trigger once of these per spell effect.
|
||||
}
|
||||
}
|
||||
@ -3605,7 +3600,7 @@ void Mob::TryTriggerOnValueAmount(bool IsHP, bool IsMana, bool IsEndur, bool IsP
|
||||
}
|
||||
|
||||
if (use_spell){
|
||||
SpellFinished(spells[spell_id].base[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
SpellFinished(spells[spell_id].base[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
|
||||
if(!TryFadeEffect(e))
|
||||
BuffFadeBySlot(e);
|
||||
@ -3633,7 +3628,7 @@ void Mob::TryTwincast(Mob *caster, Mob *target, uint32 spell_id)
|
||||
if(zone->random.Roll(focus))
|
||||
{
|
||||
Message(MT_Spells,"You twincast %s!",spells[spell_id].name);
|
||||
SpellFinished(spell_id, target, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
SpellFinished(spell_id, target, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3651,7 +3646,7 @@ void Mob::TryTwincast(Mob *caster, Mob *target, uint32 spell_id)
|
||||
{
|
||||
if(zone->random.Roll(focus))
|
||||
{
|
||||
SpellFinished(spell_id, target, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
SpellFinished(spell_id, target, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3779,10 +3774,10 @@ bool Mob::TryFadeEffect(int slot)
|
||||
if(IsValidSpell(spell_id))
|
||||
{
|
||||
if (IsBeneficialSpell(spell_id)) {
|
||||
SpellFinished(spell_id, this, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
SpellFinished(spell_id, this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
}
|
||||
else if(!(IsClient() && CastToClient()->dead)) {
|
||||
SpellFinished(spell_id, this, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
SpellFinished(spell_id, this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -3816,7 +3811,7 @@ void Mob::TrySympatheticProc(Mob *target, uint32 spell_id)
|
||||
SpellFinished(focus_trigger, target);
|
||||
|
||||
else
|
||||
SpellFinished(focus_trigger, this, EQEmu::CastingSlot::Item, 0, -1, spells[focus_trigger].ResistDiff);
|
||||
SpellFinished(focus_trigger, this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[focus_trigger].ResistDiff);
|
||||
}
|
||||
// For detrimental spells, if the triggered spell is beneficial, then it will land on the caster
|
||||
// if the triggered spell is also detrimental, then it will land on the target
|
||||
@ -3826,7 +3821,7 @@ void Mob::TrySympatheticProc(Mob *target, uint32 spell_id)
|
||||
SpellFinished(focus_trigger, this);
|
||||
|
||||
else
|
||||
SpellFinished(focus_trigger, target, EQEmu::CastingSlot::Item, 0, -1, spells[focus_trigger].ResistDiff);
|
||||
SpellFinished(focus_trigger, target, EQEmu::spells::CastingSlot::Item, 0, -1, spells[focus_trigger].ResistDiff);
|
||||
}
|
||||
|
||||
CheckNumHitsRemaining(NumHit::MatchingSpells, -1, focus_spell);
|
||||
@ -4475,7 +4470,7 @@ void Mob::TrySpellOnKill(uint8 level, uint16 spell_id)
|
||||
if (IsValidSpell(spells[spell_id].base2[i]) && spells[spell_id].max[i] <= level)
|
||||
{
|
||||
if(zone->random.Roll(spells[spell_id].base[i]))
|
||||
SpellFinished(spells[spell_id].base2[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff);
|
||||
SpellFinished(spells[spell_id].base2[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4490,17 +4485,17 @@ void Mob::TrySpellOnKill(uint8 level, uint16 spell_id)
|
||||
|
||||
if(aabonuses.SpellOnKill[i] && IsValidSpell(aabonuses.SpellOnKill[i]) && (level >= aabonuses.SpellOnKill[i + 2])) {
|
||||
if(zone->random.Roll(static_cast<int>(aabonuses.SpellOnKill[i + 1])))
|
||||
SpellFinished(aabonuses.SpellOnKill[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff);
|
||||
SpellFinished(aabonuses.SpellOnKill[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff);
|
||||
}
|
||||
|
||||
if(itembonuses.SpellOnKill[i] && IsValidSpell(itembonuses.SpellOnKill[i]) && (level >= itembonuses.SpellOnKill[i + 2])){
|
||||
if(zone->random.Roll(static_cast<int>(itembonuses.SpellOnKill[i + 1])))
|
||||
SpellFinished(itembonuses.SpellOnKill[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff);
|
||||
SpellFinished(itembonuses.SpellOnKill[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff);
|
||||
}
|
||||
|
||||
if(spellbonuses.SpellOnKill[i] && IsValidSpell(spellbonuses.SpellOnKill[i]) && (level >= spellbonuses.SpellOnKill[i + 2])) {
|
||||
if(zone->random.Roll(static_cast<int>(spellbonuses.SpellOnKill[i + 1])))
|
||||
SpellFinished(spellbonuses.SpellOnKill[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff);
|
||||
SpellFinished(spellbonuses.SpellOnKill[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff);
|
||||
}
|
||||
|
||||
}
|
||||
@ -4517,19 +4512,19 @@ bool Mob::TrySpellOnDeath()
|
||||
for(int i = 0; i < MAX_SPELL_TRIGGER*2; i+=2) {
|
||||
if(IsClient() && aabonuses.SpellOnDeath[i] && IsValidSpell(aabonuses.SpellOnDeath[i])) {
|
||||
if(zone->random.Roll(static_cast<int>(aabonuses.SpellOnDeath[i + 1]))) {
|
||||
SpellFinished(aabonuses.SpellOnDeath[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[aabonuses.SpellOnDeath[i]].ResistDiff);
|
||||
SpellFinished(aabonuses.SpellOnDeath[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[aabonuses.SpellOnDeath[i]].ResistDiff);
|
||||
}
|
||||
}
|
||||
|
||||
if(itembonuses.SpellOnDeath[i] && IsValidSpell(itembonuses.SpellOnDeath[i])) {
|
||||
if(zone->random.Roll(static_cast<int>(itembonuses.SpellOnDeath[i + 1]))) {
|
||||
SpellFinished(itembonuses.SpellOnDeath[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[itembonuses.SpellOnDeath[i]].ResistDiff);
|
||||
SpellFinished(itembonuses.SpellOnDeath[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[itembonuses.SpellOnDeath[i]].ResistDiff);
|
||||
}
|
||||
}
|
||||
|
||||
if(spellbonuses.SpellOnDeath[i] && IsValidSpell(spellbonuses.SpellOnDeath[i])) {
|
||||
if(zone->random.Roll(static_cast<int>(spellbonuses.SpellOnDeath[i + 1]))) {
|
||||
SpellFinished(spellbonuses.SpellOnDeath[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[spellbonuses.SpellOnDeath[i]].ResistDiff);
|
||||
SpellFinished(spellbonuses.SpellOnDeath[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spellbonuses.SpellOnDeath[i]].ResistDiff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
30
zone/mob.h
30
zone/mob.h
@ -278,7 +278,7 @@ public:
|
||||
|
||||
//Song
|
||||
bool UseBardSpellLogic(uint16 spell_id = 0xffff, int slot = -1);
|
||||
bool ApplyNextBardPulse(uint16 spell_id, Mob *spell_target, EQEmu::CastingSlot slot);
|
||||
bool ApplyNextBardPulse(uint16 spell_id, Mob *spell_target, EQEmu::spells::CastingSlot slot);
|
||||
void BardPulse(uint16 spell_id, Mob *caster);
|
||||
|
||||
//Spell
|
||||
@ -309,24 +309,24 @@ public:
|
||||
void SendSpellBarEnable(uint16 spellid);
|
||||
void ZeroCastingVars();
|
||||
virtual void SpellProcess();
|
||||
virtual bool CastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, int32 casttime = -1,
|
||||
virtual bool CastSpell(uint16 spell_id, uint16 target_id, EQEmu::spells::CastingSlot slot = EQEmu::spells::CastingSlot::Item, int32 casttime = -1,
|
||||
int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF,
|
||||
uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, int16 *resist_adjust = nullptr,
|
||||
uint32 aa_id = 0);
|
||||
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, int32 casttime = -1,
|
||||
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::spells::CastingSlot slot = EQEmu::spells::CastingSlot::Item, int32 casttime = -1,
|
||||
int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF,
|
||||
uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, int16 resist_adjust = 0,
|
||||
uint32 aa_id = 0);
|
||||
void CastedSpellFinished(uint16 spell_id, uint32 target_id, EQEmu::CastingSlot slot, uint16 mana_used,
|
||||
void CastedSpellFinished(uint16 spell_id, uint32 target_id, EQEmu::spells::CastingSlot slot, uint16 mana_used,
|
||||
uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0);
|
||||
bool SpellFinished(uint16 spell_id, Mob *target, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, uint16 mana_used = 0,
|
||||
bool SpellFinished(uint16 spell_id, Mob *target, EQEmu::spells::CastingSlot slot = EQEmu::spells::CastingSlot::Item, uint16 mana_used = 0,
|
||||
uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0, bool isproc = false, int level_override = -1);
|
||||
void SendBeginCast(uint16 spell_id, uint32 casttime);
|
||||
virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect = false,
|
||||
bool use_resist_adjust = false, int16 resist_adjust = 0, bool isproc = false, int level_override = -1);
|
||||
virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100, int level_override = -1);
|
||||
virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center,
|
||||
CastAction_type &CastAction, EQEmu::CastingSlot slot, bool isproc = false);
|
||||
CastAction_type &CastAction, EQEmu::spells::CastingSlot slot, bool isproc = false);
|
||||
virtual bool CheckFizzle(uint16 spell_id);
|
||||
virtual bool CheckSpellLevelRestriction(uint16 spell_id);
|
||||
virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster);
|
||||
@ -576,8 +576,8 @@ public:
|
||||
virtual void SetMoving(bool move) { moving = move; m_Delta = glm::vec4(); }
|
||||
virtual void GoToBind(uint8 bindnum = 0) { }
|
||||
virtual void Gate(uint8 bindnum = 0);
|
||||
int GetWalkspeed() const { return(_GetWalkSpeed()); }
|
||||
int GetRunspeed() const { return(_GetRunSpeed()); }
|
||||
virtual int GetWalkspeed() const { return(_GetWalkSpeed()); }
|
||||
virtual int GetRunspeed() const { return(_GetRunSpeed()); }
|
||||
int GetBaseRunspeed() const { return base_runspeed; }
|
||||
int GetBaseWalkspeed() const { return base_walkspeed; }
|
||||
int GetBaseFearSpeed() const { return base_fearspeed; }
|
||||
@ -589,8 +589,8 @@ public:
|
||||
void MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct* spu);
|
||||
void MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu);
|
||||
void SentPositionPacket(float dx, float dy, float dz, float dh, int anim, bool send_to_self = false);
|
||||
void StopMoving();
|
||||
void StopMoving(float new_heading);
|
||||
virtual void StopMoving();
|
||||
virtual void StopMoving(float new_heading);
|
||||
void SetSpawned() { spawned = true; };
|
||||
bool Spawned() { return spawned; };
|
||||
virtual bool ShouldISpawnFor(Client *c) { return true; }
|
||||
@ -998,8 +998,8 @@ public:
|
||||
|
||||
inline bool CheckAggro(Mob* other) {return hate_list.IsEntOnHateList(other);}
|
||||
float CalculateHeadingToTarget(float in_x, float in_y) { return HeadingAngleToMob(in_x, in_y); }
|
||||
void WalkTo(float x, float y, float z);
|
||||
void RunTo(float x, float y, float z);
|
||||
virtual void WalkTo(float x, float y, float z);
|
||||
virtual void RunTo(float x, float y, float z);
|
||||
void NavigateTo(float x, float y, float z);
|
||||
void RotateTo(float new_heading);
|
||||
void RotateToWalking(float new_heading);
|
||||
@ -1375,7 +1375,7 @@ protected:
|
||||
int attacked_count;
|
||||
bool delaytimer;
|
||||
uint16 casting_spell_targetid;
|
||||
EQEmu::CastingSlot casting_spell_slot;
|
||||
EQEmu::spells::CastingSlot casting_spell_slot;
|
||||
uint16 casting_spell_mana;
|
||||
uint32 casting_spell_inventory_slot;
|
||||
uint32 casting_spell_timer;
|
||||
@ -1385,7 +1385,7 @@ protected:
|
||||
uint32 casting_spell_aa_id;
|
||||
bool casting_spell_checks;
|
||||
uint16 bardsong;
|
||||
EQEmu::CastingSlot bardsong_slot;
|
||||
EQEmu::spells::CastingSlot bardsong_slot;
|
||||
uint32 bardsong_target_id;
|
||||
|
||||
bool ActiveProjectileATK;
|
||||
@ -1538,7 +1538,7 @@ protected:
|
||||
glm::vec3 m_TargetRing;
|
||||
|
||||
// we might want to do this differently, we gotta do max NPC buffs ... which is 97
|
||||
uint32 m_spellHitsLeft[EQEmu::constants::TotalBuffs]; // Used to track which spells will have their numhits incremented when spell finishes casting
|
||||
uint32 m_spellHitsLeft[EQEmu::spells::TOTAL_BUFFS]; // Used to track which spells will have their numhits incremented when spell finishes casting
|
||||
GravityBehavior flymode;
|
||||
bool m_targetable;
|
||||
int QGVarDuration(const char *fmt);
|
||||
|
||||
@ -375,7 +375,7 @@ bool NPC::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgain
|
||||
#endif
|
||||
casting_spell_AIindex = i;
|
||||
|
||||
return CastSpell(AIspells[i].spellid, tar->GetID(), EQEmu::CastingSlot::Gem2, AIspells[i].manacost == -2 ? 0 : -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, &(AIspells[i].resist_adjust));
|
||||
return CastSpell(AIspells[i].spellid, tar->GetID(), EQEmu::spells::CastingSlot::Gem2, AIspells[i].manacost == -2 ? 0 : -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, &(AIspells[i].resist_adjust));
|
||||
}
|
||||
|
||||
bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float iRange, uint32 iSpellTypes) {
|
||||
@ -688,11 +688,11 @@ void Client::AI_SpellCast()
|
||||
}
|
||||
|
||||
uint32 spell_to_cast = 0xFFFFFFFF;
|
||||
EQEmu::CastingSlot slot_to_use = EQEmu::CastingSlot::Item;
|
||||
EQEmu::spells::CastingSlot slot_to_use = EQEmu::spells::CastingSlot::Item;
|
||||
if(valid_spells.size() == 1)
|
||||
{
|
||||
spell_to_cast = valid_spells[0];
|
||||
slot_to_use = static_cast<EQEmu::CastingSlot>(slots[0]);
|
||||
slot_to_use = static_cast<EQEmu::spells::CastingSlot>(slots[0]);
|
||||
}
|
||||
else if(valid_spells.empty())
|
||||
{
|
||||
@ -702,7 +702,7 @@ void Client::AI_SpellCast()
|
||||
{
|
||||
uint32 idx = zone->random.Int(0, (valid_spells.size()-1));
|
||||
spell_to_cast = valid_spells[idx];
|
||||
slot_to_use = static_cast<EQEmu::CastingSlot>(slots[idx]);
|
||||
slot_to_use = static_cast<EQEmu::spells::CastingSlot>(slots[idx]);
|
||||
}
|
||||
|
||||
if(IsMezSpell(spell_to_cast) || IsFearSpell(spell_to_cast))
|
||||
|
||||
@ -817,7 +817,7 @@ void Mob::DisplayInfo(Mob *mob)
|
||||
NPCCommandsMenu(client, npc);
|
||||
}
|
||||
|
||||
std::cout << "Window Length: " << window_text.length() << std::endl;
|
||||
// std::cout << "Window Length: " << window_text.length() << std::endl;
|
||||
|
||||
if (client->GetDisplayMobInfoWindow()) {
|
||||
client->SendFullPopup(
|
||||
|
||||
@ -759,7 +759,7 @@ void MobMovementManager::FillCommandStruct(PlayerPositionUpdateServer_Struct *sp
|
||||
spu->delta_y = FloatToEQ13(dy);
|
||||
spu->delta_z = FloatToEQ13(dz);
|
||||
spu->delta_heading = FloatToEQ10(dh);
|
||||
spu->animation = anim;
|
||||
spu->animation = (m->IsBot() ? (int)((float)anim / 1.785714f) : anim);
|
||||
}
|
||||
|
||||
void MobMovementManager::UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mode)
|
||||
|
||||
@ -362,18 +362,21 @@ int main(int argc, char** argv) {
|
||||
std::string tmp;
|
||||
if (database.GetVariable("RuleSet", tmp)) {
|
||||
Log(Logs::General, Logs::Zone_Server, "Loading rule set '%s'", tmp.c_str());
|
||||
if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str())) {
|
||||
if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str(), false)) {
|
||||
Log(Logs::General, Logs::Error, "Failed to load ruleset '%s', falling back to defaults.", tmp.c_str());
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!RuleManager::Instance()->LoadRules(&database, "default")) {
|
||||
if (!RuleManager::Instance()->LoadRules(&database, "default", false)) {
|
||||
Log(Logs::General, Logs::Zone_Server, "No rule set configured, using default rules");
|
||||
}
|
||||
else {
|
||||
Log(Logs::General, Logs::Zone_Server, "Loaded default rule set 'default'", tmp.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
EQEmu::InitializeDynamicLookups();
|
||||
Log(Logs::General, Logs::Zone_Server, "Initialized dynamic dictionary entries");
|
||||
}
|
||||
|
||||
#ifdef BOTS
|
||||
|
||||
@ -1388,7 +1388,7 @@ uint32 ZoneDatabase::DeleteSpawnRemoveFromNPCTypeTable(const char *zone, uint32
|
||||
uint32 spawngroupID = 0;
|
||||
|
||||
std::string query = StringFormat("SELECT id, spawngroupID FROM spawn2 WHERE zone = '%s' "
|
||||
"AND version = %u AND spawngroupID = %i",
|
||||
"AND (version = %u OR version = -1) AND spawngroupID = %i",
|
||||
zone, zone_version, spawn->GetSp2());
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
|
||||
@ -3737,7 +3737,7 @@ XS(XS_Mob_CastSpell) {
|
||||
Mob *THIS;
|
||||
uint16 spell_id = (uint16) SvUV(ST(1));
|
||||
uint16 target_id = (uint16) SvUV(ST(2));
|
||||
EQEmu::CastingSlot slot;
|
||||
EQEmu::spells::CastingSlot slot;
|
||||
int32 casttime;
|
||||
int32 mana_cost;
|
||||
int16 resist_adjust;
|
||||
@ -3751,9 +3751,9 @@ XS(XS_Mob_CastSpell) {
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
if (items < 4)
|
||||
slot = EQEmu::CastingSlot::Item;
|
||||
slot = EQEmu::spells::CastingSlot::Item;
|
||||
else {
|
||||
slot = static_cast<EQEmu::CastingSlot>(SvUV(ST(3)));
|
||||
slot = static_cast<EQEmu::spells::CastingSlot>(SvUV(ST(3)));
|
||||
}
|
||||
|
||||
if (items < 5)
|
||||
@ -3827,7 +3827,7 @@ XS(XS_Mob_SpellFinished) {
|
||||
resist_diff = spells[spell_id].ResistDiff;
|
||||
}
|
||||
|
||||
THIS->SpellFinished(spell_id, spell_target, EQEmu::CastingSlot::Item, mana_cost, -1, resist_diff);
|
||||
THIS->SpellFinished(spell_id, spell_target, EQEmu::spells::CastingSlot::Item, mana_cost, -1, resist_diff);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
@ -371,14 +371,14 @@ void QuestManager::castspell(int spell_id, int target_id) {
|
||||
if (owner) {
|
||||
Mob *tgt = entity_list.GetMob(target_id);
|
||||
if(tgt != nullptr)
|
||||
owner->SpellFinished(spell_id, tgt, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
owner->SpellFinished(spell_id, tgt, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
}
|
||||
}
|
||||
|
||||
void QuestManager::selfcast(int spell_id) {
|
||||
QuestManagerCurrentQuestVars();
|
||||
if (initiator)
|
||||
initiator->SpellFinished(spell_id, initiator, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
initiator->SpellFinished(spell_id, initiator, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
}
|
||||
|
||||
void QuestManager::addloot(int item_id, int charges, bool equipitem, int aug1, int aug2, int aug3, int aug4, int aug5, int aug6) {
|
||||
@ -984,8 +984,15 @@ uint16 QuestManager::scribespells(uint8 max_level, uint8 min_level) {
|
||||
bool SpellGlobalCheckResult = 0;
|
||||
bool SpellBucketCheckResult = 0;
|
||||
|
||||
|
||||
for(spell_id = 0, book_slot = initiator->GetNextAvailableSpellBookSlot(), count = 0; spell_id < SPDAT_RECORDS && book_slot < MAX_PP_SPELLBOOK; spell_id++, book_slot = initiator->GetNextAvailableSpellBookSlot(book_slot))
|
||||
for (
|
||||
spell_id = 0,
|
||||
book_slot = initiator->GetNextAvailableSpellBookSlot(),
|
||||
count = 0; // ;
|
||||
spell_id < SPDAT_RECORDS &&
|
||||
book_slot < EQEmu::spells::SPELLBOOK_SIZE; // ;
|
||||
spell_id++,
|
||||
book_slot = initiator->GetNextAvailableSpellBookSlot(book_slot)
|
||||
)
|
||||
{
|
||||
if
|
||||
(
|
||||
@ -2135,8 +2142,7 @@ bool QuestManager::createBot(const char *name, const char *lastname, uint8 level
|
||||
return false;
|
||||
}
|
||||
|
||||
NPCType DefaultNPCTypeStruct = Bot::CreateDefaultNPCTypeStructForBot(name, lastname, level, race, botclass, gender);
|
||||
Bot* NewBot = new Bot(DefaultNPCTypeStruct, initiator);
|
||||
Bot* NewBot = new Bot(Bot::CreateDefaultNPCTypeStructForBot(name, lastname, level, race, botclass, gender), initiator);
|
||||
|
||||
if(NewBot)
|
||||
{
|
||||
|
||||
@ -488,7 +488,7 @@ bool ZoneDatabase::PopulateZoneSpawnListClose(uint32 zoneid, LinkedList<Spawn2*>
|
||||
"animation "
|
||||
"FROM "
|
||||
"spawn2 "
|
||||
"WHERE zone = '%s' AND version = %u",
|
||||
"WHERE zone = '%s' AND (version = %u OR version = -1) ",
|
||||
zone_name,
|
||||
version
|
||||
);
|
||||
@ -592,7 +592,7 @@ bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList<Spawn2*> &spa
|
||||
"animation "
|
||||
"FROM "
|
||||
"spawn2 "
|
||||
"WHERE zone = '%s' AND version = %u",
|
||||
"WHERE zone = '%s' AND (version = %u OR version = -1)",
|
||||
zone_name,
|
||||
version
|
||||
);
|
||||
|
||||
@ -197,7 +197,7 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32
|
||||
IsValidSpell(aabonuses.SkillAttackProc[2])) {
|
||||
float chance = aabonuses.SkillAttackProc[0] / 1000.0f;
|
||||
if (zone->random.Roll(chance))
|
||||
SpellFinished(aabonuses.SkillAttackProc[2], who, EQEmu::CastingSlot::Item, 0, -1,
|
||||
SpellFinished(aabonuses.SkillAttackProc[2], who, EQEmu::spells::CastingSlot::Item, 0, -1,
|
||||
spells[aabonuses.SkillAttackProc[2]].ResistDiff);
|
||||
}
|
||||
|
||||
@ -2156,7 +2156,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob *other, uint16 weapon_damage, EQEmu::skills:
|
||||
IsValidSpell(aabonuses.SkillAttackProc[2])) {
|
||||
float chance = aabonuses.SkillAttackProc[0] / 1000.0f;
|
||||
if (zone->random.Roll(chance))
|
||||
SpellFinished(aabonuses.SkillAttackProc[2], other, EQEmu::CastingSlot::Item, 0, -1,
|
||||
SpellFinished(aabonuses.SkillAttackProc[2], other, EQEmu::spells::CastingSlot::Item, 0, -1,
|
||||
spells[aabonuses.SkillAttackProc[2]].ResistDiff);
|
||||
}
|
||||
|
||||
|
||||
@ -2470,7 +2470,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
case SE_FcTimerRefresh:
|
||||
{
|
||||
if(IsClient()) {
|
||||
for(unsigned int i =0 ; i < MAX_PP_MEMSPELL; ++i) {
|
||||
for (unsigned int i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; ++i) {
|
||||
if(IsValidSpell(CastToClient()->m_pp.mem_spells[i])) {
|
||||
if (CalcFocusEffect(focusFcTimerRefresh, spell_id, CastToClient()->m_pp.mem_spells[i])){
|
||||
CastToClient()->m_pp.spellSlotRefresh[i] = 1;
|
||||
@ -2739,7 +2739,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
|
||||
if (caster && IsValidSpell(spells[spell_id].base2[i])){
|
||||
if(zone->random.Roll(spells[spell_id].base[i]))
|
||||
caster->SpellFinished(spells[spell_id].base2[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff);
|
||||
caster->SpellFinished(spells[spell_id].base2[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -3662,7 +3662,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster)
|
||||
case SE_CastOnFadeEffectNPC:
|
||||
case SE_CastOnFadeEffectAlways: {
|
||||
if (buff.ticsremaining == 0) {
|
||||
SpellFinished(spells[buff.spellid].base[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[spells[buff.spellid].base[i]].ResistDiff);
|
||||
SpellFinished(spells[buff.spellid].base[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spells[buff.spellid].base[i]].ResistDiff);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -5100,7 +5100,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
|
||||
|
||||
if (Caston_spell_id) {
|
||||
if (IsValidSpell(Caston_spell_id) && (Caston_spell_id != spell_id))
|
||||
SpellFinished(Caston_spell_id, this, EQEmu::CastingSlot::Item, 0, -1, spells[Caston_spell_id].ResistDiff);
|
||||
SpellFinished(Caston_spell_id, this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[Caston_spell_id].ResistDiff);
|
||||
}
|
||||
|
||||
return (value * lvlModifier / 100);
|
||||
@ -6663,10 +6663,10 @@ void Mob::TryTriggerThreshHold(int32 damage, int effect_id, Mob* attacker){
|
||||
if (IsValidSpell(spell_id)) {
|
||||
|
||||
if (IsBeneficialSpell(spell_id))
|
||||
SpellFinished(spell_id, this, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
SpellFinished(spell_id, this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
|
||||
else if(attacker)
|
||||
SpellFinished(spell_id, attacker, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
SpellFinished(spell_id, attacker, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,7 +107,7 @@ extern volatile bool is_zone_loaded;
|
||||
extern WorldServer worldserver;
|
||||
extern FastMath g_Math;
|
||||
|
||||
using EQEmu::CastingSlot;
|
||||
using EQEmu::spells::CastingSlot;
|
||||
|
||||
// this is run constantly for every mob
|
||||
void Mob::SpellProcess()
|
||||
@ -4968,7 +4968,7 @@ void Client::MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message)
|
||||
|
||||
void Client::MemSpell(uint16 spell_id, int slot, bool update_client)
|
||||
{
|
||||
if(slot >= MAX_PP_MEMSPELL || slot < 0)
|
||||
if(slot >= EQEmu::spells::SPELL_GEM_COUNT || slot < 0)
|
||||
return;
|
||||
|
||||
if(update_client)
|
||||
@ -4990,7 +4990,7 @@ void Client::MemSpell(uint16 spell_id, int slot, bool update_client)
|
||||
|
||||
void Client::UnmemSpell(int slot, bool update_client)
|
||||
{
|
||||
if(slot > MAX_PP_MEMSPELL || slot < 0)
|
||||
if(slot > EQEmu::spells::SPELL_GEM_COUNT || slot < 0)
|
||||
return;
|
||||
|
||||
Log(Logs::Detail, Logs::Spells, "Spell %d forgotten from slot %d", m_pp.mem_spells[slot], slot);
|
||||
@ -5006,7 +5006,7 @@ void Client::UnmemSpell(int slot, bool update_client)
|
||||
|
||||
void Client::UnmemSpellBySpellID(int32 spell_id)
|
||||
{
|
||||
for(int i = 0; i < MAX_PP_MEMSPELL; i++) {
|
||||
for(int i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; i++) {
|
||||
if(m_pp.mem_spells[i] == spell_id) {
|
||||
UnmemSpell(i, true);
|
||||
break;
|
||||
@ -5018,14 +5018,14 @@ void Client::UnmemSpellAll(bool update_client)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < MAX_PP_MEMSPELL; i++)
|
||||
for(i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; i++)
|
||||
if(m_pp.mem_spells[i] != 0xFFFFFFFF)
|
||||
UnmemSpell(i, update_client);
|
||||
}
|
||||
|
||||
void Client::ScribeSpell(uint16 spell_id, int slot, bool update_client)
|
||||
{
|
||||
if(slot >= MAX_PP_SPELLBOOK || slot < 0)
|
||||
if(slot >= EQEmu::spells::SPELLBOOK_SIZE || slot < 0)
|
||||
return;
|
||||
|
||||
if(update_client)
|
||||
@ -5046,14 +5046,14 @@ void Client::ScribeSpell(uint16 spell_id, int slot, bool update_client)
|
||||
|
||||
void Client::UnscribeSpell(int slot, bool update_client)
|
||||
{
|
||||
if(slot >= MAX_PP_SPELLBOOK || slot < 0)
|
||||
if(slot >= EQEmu::spells::SPELLBOOK_SIZE || slot < 0)
|
||||
return;
|
||||
|
||||
Log(Logs::Detail, Logs::Spells, "Spell %d erased from spell book slot %d", m_pp.spell_book[slot], slot);
|
||||
m_pp.spell_book[slot] = 0xFFFFFFFF;
|
||||
|
||||
database.DeleteCharacterSpell(this->CharacterID(), m_pp.spell_book[slot], slot);
|
||||
if(update_client)
|
||||
if(update_client && slot < EQEmu::spells::DynamicLookup(ClientVersion(), GetGM())->SpellbookSize)
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_DeleteSpell, sizeof(DeleteSpell_Struct));
|
||||
DeleteSpell_Struct* del = (DeleteSpell_Struct*)outapp->pBuffer;
|
||||
@ -5066,9 +5066,7 @@ void Client::UnscribeSpell(int slot, bool update_client)
|
||||
|
||||
void Client::UnscribeSpellAll(bool update_client)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < MAX_PP_SPELLBOOK; i++)
|
||||
for(int i = 0; i < EQEmu::spells::SPELLBOOK_SIZE; i++)
|
||||
{
|
||||
if(m_pp.spell_book[i] != 0xFFFFFFFF)
|
||||
UnscribeSpell(i, update_client);
|
||||
@ -5102,7 +5100,7 @@ void Client::UntrainDiscAll(bool update_client)
|
||||
}
|
||||
|
||||
int Client::GetNextAvailableSpellBookSlot(int starting_slot) {
|
||||
for (int i = starting_slot; i < MAX_PP_SPELLBOOK; i++) { //using starting_slot should help speed this up when we're iterating through a bunch of spells
|
||||
for (int i = starting_slot; i < EQEmu::spells::SPELLBOOK_SIZE; i++) { //using starting_slot should help speed this up when we're iterating through a bunch of spells
|
||||
if (!IsValidSpell(GetSpellByBookSlot(i)))
|
||||
return i;
|
||||
}
|
||||
@ -5111,7 +5109,7 @@ int Client::GetNextAvailableSpellBookSlot(int starting_slot) {
|
||||
}
|
||||
|
||||
int Client::FindSpellBookSlotBySpellID(uint16 spellid) {
|
||||
for(int i = 0; i < MAX_PP_SPELLBOOK; i++) {
|
||||
for(int i = 0; i < EQEmu::spells::SPELLBOOK_SIZE; i++) {
|
||||
if(m_pp.spell_book[i] == spellid)
|
||||
return i;
|
||||
}
|
||||
@ -5410,7 +5408,7 @@ bool Mob::UseBardSpellLogic(uint16 spell_id, int slot)
|
||||
spell_id != SPELL_UNKNOWN &&
|
||||
slot != -1 &&
|
||||
GetClass() == BARD &&
|
||||
slot <= MAX_PP_MEMSPELL &&
|
||||
slot <= EQEmu::spells::SPELL_GEM_COUNT &&
|
||||
IsBardSong(spell_id)
|
||||
);
|
||||
}
|
||||
@ -5619,12 +5617,12 @@ int Client::GetCurrentBuffSlots() const
|
||||
numbuffs++;
|
||||
if (GetLevel() > 74)
|
||||
numbuffs++;
|
||||
return EQEmu::ClampUpper(numbuffs, EQEmu::constants::Lookup(m_ClientVersion)->LongBuffs);
|
||||
return EQEmu::ClampUpper(numbuffs, EQEmu::spells::StaticLookup(m_ClientVersion)->LongBuffs);
|
||||
}
|
||||
|
||||
int Client::GetCurrentSongSlots() const
|
||||
{
|
||||
return EQEmu::constants::Lookup(m_ClientVersion)->ShortBuffs; // AAs dont affect this
|
||||
return EQEmu::spells::StaticLookup(m_ClientVersion)->ShortBuffs; // AAs dont affect this
|
||||
}
|
||||
|
||||
void Client::InitializeBuffSlots()
|
||||
|
||||
@ -135,7 +135,7 @@ void Trap::Trigger(Mob* trigger)
|
||||
entity_list.MessageClose(trigger,false,100,13,"%s",message.c_str());
|
||||
}
|
||||
if(hiddenTrigger){
|
||||
hiddenTrigger->SpellFinished(effectvalue, trigger, EQEmu::CastingSlot::Item, 0, -1, spells[effectvalue].ResistDiff);
|
||||
hiddenTrigger->SpellFinished(effectvalue, trigger, EQEmu::spells::CastingSlot::Item, 0, -1, spells[effectvalue].ResistDiff);
|
||||
}
|
||||
break;
|
||||
case trapTypeAlarm:
|
||||
|
||||
@ -537,9 +537,6 @@ void NPC::AssignWaypoints(int32 grid)
|
||||
|
||||
if (wandertype == 1 || wandertype == 2 || wandertype == 5)
|
||||
CalculateNewWaypoint();
|
||||
|
||||
if (wandertype == 1 || wandertype == 2 || wandertype == 5)
|
||||
CalculateNewWaypoint();
|
||||
}
|
||||
|
||||
void Mob::SendTo(float new_x, float new_y, float new_z) {
|
||||
@ -1066,3 +1063,32 @@ void NPC::RestoreGuardSpotCharm()
|
||||
{
|
||||
m_GuardPoint = m_GuardPointSaved;
|
||||
}
|
||||
|
||||
/******************
|
||||
* Bot-specific overloads to make them play nice with the new movement system
|
||||
*/
|
||||
#ifdef BOTS
|
||||
#include "bot.h"
|
||||
|
||||
void Bot::WalkTo(float x, float y, float z)
|
||||
{
|
||||
if (IsSitting())
|
||||
Stand();
|
||||
|
||||
if (ping_timer.Enabled())
|
||||
ping_timer.Disable();
|
||||
|
||||
Mob::WalkTo(x, y, z);
|
||||
}
|
||||
|
||||
void Bot::RunTo(float x, float y, float z)
|
||||
{
|
||||
if (IsSitting())
|
||||
Stand();
|
||||
|
||||
if (ping_timer.Enabled())
|
||||
ping_timer.Disable();
|
||||
|
||||
Mob::RunTo(x, y, z);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1772,7 +1772,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
zone->GetLongName(),
|
||||
zone->GetInstanceID()
|
||||
);
|
||||
RuleManager::Instance()->LoadRules(&database, RuleManager::Instance()->GetActiveRuleset());
|
||||
RuleManager::Instance()->LoadRules(&database, RuleManager::Instance()->GetActiveRuleset(), true);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ReloadLogs: {
|
||||
|
||||
@ -904,7 +904,7 @@ bool Zone::Init(bool iStaticZone) {
|
||||
std::string r_name = RuleManager::Instance()->GetRulesetName(&database, default_ruleset);
|
||||
if(r_name.size() > 0)
|
||||
{
|
||||
RuleManager::Instance()->LoadRules(&database, r_name.c_str());
|
||||
RuleManager::Instance()->LoadRules(&database, r_name.c_str(), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1204,12 +1204,12 @@ bool ZoneDatabase::LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_
|
||||
auto results = database.QueryDatabase(query);
|
||||
int i = 0;
|
||||
/* Initialize Spells */
|
||||
for (i = 0; i < MAX_PP_MEMSPELL; i++){
|
||||
for (i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; i++){
|
||||
pp->mem_spells[i] = 0xFFFFFFFF;
|
||||
}
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
i = atoi(row[0]);
|
||||
if (i < MAX_PP_MEMSPELL && atoi(row[1]) <= SPDAT_RECORDS){
|
||||
if (i < EQEmu::spells::SPELL_GEM_COUNT && atoi(row[1]) <= SPDAT_RECORDS){
|
||||
pp->mem_spells[i] = atoi(row[1]);
|
||||
}
|
||||
}
|
||||
@ -1225,17 +1225,28 @@ bool ZoneDatabase::LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Str
|
||||
"`character_spells` "
|
||||
"WHERE `id` = %u ORDER BY `slot_id`", character_id);
|
||||
auto results = database.QueryDatabase(query);
|
||||
int i = 0;
|
||||
|
||||
/* Initialize Spells */
|
||||
for (i = 0; i < MAX_PP_SPELLBOOK; i++){
|
||||
pp->spell_book[i] = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
memset(pp->spell_book, 0xFF, (sizeof(uint32) * EQEmu::spells::SPELLBOOK_SIZE));
|
||||
|
||||
// We have the ability to block loaded spells by max id on a per-client basis..
|
||||
// but, we do not have to ability to keep players from using older clients after
|
||||
// they have scribed spells on a newer one that exceeds the older one's limit.
|
||||
// Load them all so that server actions are valid..but, nix them in translators.
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
i = atoi(row[0]);
|
||||
if (i < MAX_PP_SPELLBOOK && atoi(row[1]) <= SPDAT_RECORDS){
|
||||
pp->spell_book[i] = atoi(row[1]);
|
||||
}
|
||||
int idx = atoi(row[0]);
|
||||
int id = atoi(row[1]);
|
||||
|
||||
if (idx < 0 || idx >= EQEmu::spells::SPELLBOOK_SIZE)
|
||||
continue;
|
||||
if (id < 3 || id > SPDAT_RECORDS) // 3 ("Summon Corpse") is the first scribable spell in spells_us.txt
|
||||
continue;
|
||||
|
||||
pp->spell_book[idx] = id;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3646,7 +3657,7 @@ void ZoneDatabase::LoadBuffs(Client *client)
|
||||
}
|
||||
|
||||
// We load up to the most our client supports
|
||||
max_slots = EQEmu::constants::Lookup(client->ClientVersion())->LongBuffs;
|
||||
max_slots = EQEmu::spells::StaticLookup(client->ClientVersion())->LongBuffs;
|
||||
for (int index = 0; index < max_slots; ++index) {
|
||||
if (!IsValidSpell(buffs[index].spellid))
|
||||
continue;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user