Merge git://github.com/EQEmu/Server into Development

This commit is contained in:
KayenEQ 2014-10-05 07:49:20 -04:00
commit ad116af59d
23 changed files with 249 additions and 223 deletions

View File

@ -259,7 +259,10 @@ OPTION(EQEMU_BUILD_CLIENT_FILES "Build Client Import/Export Data Programs." ON)
#C++11 stuff
IF(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-reserved-user-defined-literal")
ENDIF()
ENDIF(NOT MSVC)
#Various definitions

View File

@ -1,5 +1,9 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50)
-------------------------------------------------------
== 10/03/2014 ==
Uleat: Fixed Ti(6.2) OP_AugmentInfo translation that I broke (does not currently need and I mis-read a process)
Uleat: Moved client patch OP_LootItem slot translation to external handlers
== 10/02/2014 ==
Kayen: Exported to PERL $client->SendSpellAnim(targetid, spellid)
This function sends the spell graphic of a spell without actually having to cast the spell.

View File

@ -534,7 +534,7 @@ struct SpellBuffFade_Struct {
/*007*/ uint8 unknown7;
/*008*/ uint32 spellid;
/*012*/ uint32 duration;
/*016*/ uint32 unknown016;
/*016*/ uint32 num_hits;
/*020*/ uint32 unknown020; //prolly global player ID
/*024*/ uint32 slotid;
/*028*/ uint32 bufffade;
@ -4312,9 +4312,9 @@ struct ControlBoat_Struct {
struct AugmentInfo_Struct
{
/*000*/ uint32 itemid; // id of the solvent needed
/*004*/ uint8 window; // window to display the information in
/*005*/ uint8 unknown005[67]; // total packet length 72, all the rest were always 00
/*000*/ uint32 itemid; // id of the solvent needed
/*004*/ uint8 window; // window to display the information in
/*005*/ uint8 unknown005[67]; // total packet length 72, all the rest were always 00
/*072*/
};
@ -4602,11 +4602,13 @@ struct BuffIconEntry_Struct
uint32 buff_slot;
uint32 spell_id;
uint32 tics_remaining;
uint32 num_hits;
};
struct BuffIcon_Struct
{
uint32 entity_id;
uint8 all_buffs;
uint16 count;
BuffIconEntry_Struct entries[0];
};

View File

@ -446,7 +446,7 @@ namespace Client62
OUT(lootee);
OUT(looter);
eq->slot_id = emu->slot_id;
eq->slot_id = ServerToClient62CorpseSlot(emu->slot_id);
OUT(auto_loot);
FINISH_ENCODE();
@ -990,11 +990,6 @@ namespace Client62
FINISH_DIRECT_DECODE();
}
#if 0
// needs to be tested (and OpCode found)
DECODE(OP_AugmentInfo) { DECODE_FORWARD(OP_ReadBook); }
#endif
DECODE(OP_AugmentItem)
{
DECODE_LENGTH_EXACT(structs::AugmentItem_Struct);
@ -1110,7 +1105,7 @@ namespace Client62
IN(lootee);
IN(looter);
emu->slot_id = eq->slot_id;
emu->slot_id = Client62ToServerCorpseSlot(eq->slot_id);
IN(auto_loot);
FINISH_DIRECT_DECODE();
@ -1239,6 +1234,7 @@ namespace Client62
int i;
uint32 sub_length;
// not sure if 6.2 has a recast timer timestamp field..but, something seems amiss between this and Ti's ordering
MakeAnyLenString(&instance,
"%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|",
stackable ? charges : 1,
@ -1322,6 +1318,7 @@ namespace Client62
static inline int16 ServerToClient62CorpseSlot(uint32 ServerCorpse)
{
//int16 Client62Corpse;
return ServerCorpse;
}
static inline uint32 Client62ToServerSlot(int16 Client62Slot)
@ -1336,6 +1333,7 @@ namespace Client62
static inline uint32 Client62ToServerCorpseSlot(int16 Client62Corpse)
{
//uint32 ServerCorpse;
return Client62Corpse;
}
}
// end namespace Client62

View File

@ -34,7 +34,6 @@ E(OP_ZoneSpawns)
// incoming packets that require a DECODE translation:
D(OP_AdventureMerchantSell)
D(OP_ApplyPoison)
//D(OP_AugmentInfo) - needs opcode for conf file update
D(OP_AugmentItem)
D(OP_CastSpell)
D(OP_CharacterCreate)

View File

@ -3099,11 +3099,6 @@ struct GuildMemberUpdate_Struct {
/*72*/ uint32 unknown072;
};
}; //end namespace structs
}; //end namespace Client62

View File

@ -376,6 +376,7 @@ namespace RoF
OUT(duration);
eq->playerId = 0x7cde;
OUT(slotid);
OUT(num_hits);
if (emu->bufffade == 1)
eq->bufffade = 1;
else
@ -414,7 +415,7 @@ namespace RoF
__packet->WriteUInt32(emu->entity_id);
__packet->WriteUInt32(0); // PlayerID ?
__packet->WriteUInt8(1); // 1 indicates all buffs on the player (0 to add or remove a single buff)
__packet->WriteUInt8(emu->all_buffs); // 1 indicates all buffs on the player (0 to add or remove a single buff)
__packet->WriteUInt16(emu->count);
for (uint16 i = 0; i < emu->count; ++i)
@ -429,10 +430,10 @@ namespace RoF
__packet->WriteUInt32(buffslot);
__packet->WriteUInt32(emu->entries[i].spell_id);
__packet->WriteUInt32(emu->entries[i].tics_remaining);
__packet->WriteUInt32(0); // Unknown
__packet->WriteUInt32(emu->entries[i].num_hits); // Unknown
__packet->WriteString("");
}
__packet->WriteUInt8(0); // Unknown
__packet->WriteUInt8(!emu->all_buffs); // Unknown
FINISH_ENCODE();
}
@ -1423,7 +1424,7 @@ namespace RoF
OUT(lootee);
OUT(looter);
eq->slot_id = emu->slot_id + 1;
eq->slot_id = ServerToRoFCorpseSlot(emu->slot_id);
OUT(auto_loot);
FINISH_ENCODE();
@ -4405,7 +4406,7 @@ namespace RoF
IN(lootee);
IN(looter);
emu->slot_id = eq->slot_id - 1;
emu->slot_id = RoFToServerCorpseSlot(eq->slot_id);
IN(auto_loot);
FINISH_DIRECT_DECODE();
@ -5406,6 +5407,7 @@ namespace RoF
static inline uint32 ServerToRoFCorpseSlot(uint32 ServerCorpse)
{
//uint32 RoFCorpse;
return (ServerCorpse + 1);
}
static inline uint32 RoFToServerSlot(structs::ItemSlotStruct RoFSlot)
@ -5546,6 +5548,7 @@ namespace RoF
static inline uint32 RoFToServerCorpseSlot(uint32 RoFCorpse)
{
//uint32 ServerCorpse;
return (RoFCorpse - 1);
}
}
// end namespace RoF

View File

@ -712,7 +712,8 @@ struct SpellBuffFade_Struct_Live {
/*012*/ uint32 spellid;
/*016*/ uint32 duration;
/*020*/ uint32 playerId; // Global player ID?
/*024*/ uint8 unknown0028[68];
/*024*/ uint32 num_hits;
/*028*/ uint8 unknown0028[64];
/*092*/ uint32 slotid;
/*096*/ uint32 bufffade;
/*100*/
@ -726,7 +727,7 @@ struct SpellBuffFade_Struct {
/*007*/ uint8 unknown7;
/*008*/ uint32 spellid;
/*012*/ uint32 duration;
/*016*/ uint32 unknown016;
/*016*/ uint32 num_hits;
/*020*/ uint32 unknown020; // Global player ID?
/*024*/ uint32 playerId; // Player id who cast the buff
/*028*/ uint32 slotid;
@ -741,6 +742,27 @@ struct BuffRemoveRequest_Struct
/*08*/
};
#if 0
// not in use
struct BuffIconEntry_Struct {
/*000*/ uint32 buff_slot;
/*004*/ uint32 spell_id;
/*008*/ uint32 tics_remaining;
/*012*/ uint32 num_hits;
// char name[0]; caster name is also here sometimes
// uint8 unknownend; 1 when single, 0 when all opposite of all_buffs?
};
// not in use
struct BuffIcon_Struct {
/*000*/ uint32 entity_id;
/*004*/ uint32 unknown004;
/*008*/ uint8 all_buffs; // 1 when updating all buffs, 0 when doing one
/*009*/ uint16 count;
/*011*/ BuffIconEntry_Struct entires[0];
};
#endif
struct GMTrainee_Struct
{
/*000*/ uint32 npcid;
@ -4585,9 +4607,9 @@ struct ItemQuaternaryBodyStruct
struct AugmentInfo_Struct
{
/*000*/ uint32 itemid; // id of the solvent needed
/*004*/ uint8 window; // window to display the information in
/*005*/ uint8 unknown005[71]; // total packet length 76, all the rest were always 00
/*000*/ uint32 itemid; // id of the solvent needed
/*004*/ uint8 window; // window to display the information in
/*005*/ uint8 unknown005[71]; // total packet length 76, all the rest were always 00
/*076*/
};

View File

@ -984,7 +984,7 @@ namespace SoD
OUT(lootee);
OUT(looter);
eq->slot_id = emu->slot_id + 1;
eq->slot_id = ServerToSoDCorpseSlot(emu->slot_id);
OUT(auto_loot);
FINISH_ENCODE();
@ -2956,7 +2956,7 @@ namespace SoD
IN(lootee);
IN(looter);
emu->slot_id = eq->slot_id - 1;
emu->slot_id = SoDToServerCorpseSlot(eq->slot_id);
IN(auto_loot);
FINISH_DIRECT_DECODE();
@ -3599,6 +3599,7 @@ namespace SoD
static inline uint32 ServerToSoDCorpseSlot(uint32 ServerCorpse)
{
//uint32 SoDCorpse;
return (ServerCorpse + 1);
}
static inline uint32 SoDToServerSlot(uint32 SoDSlot)
@ -3623,6 +3624,7 @@ namespace SoD
static inline uint32 SoDToServerCorpseSlot(uint32 SoDCorpse)
{
//uint32 ServerCorpse;
return (SoDCorpse - 1);
}
}
// end namespace SoD

View File

@ -4109,9 +4109,9 @@ struct ItemQuaternaryBodyStruct
struct AugmentInfo_Struct
{
/*000*/ uint32 itemid; // id of the solvent needed
/*004*/ uint8 window; // window to display the information in
/*005*/ uint8 unknown005[71]; // total packet length 76, all the rest were always 00
/*000*/ uint32 itemid; // id of the solvent needed
/*004*/ uint8 window; // window to display the information in
/*005*/ uint8 unknown005[71]; // total packet length 76, all the rest were always 00
/*076*/
};

View File

@ -783,7 +783,7 @@ namespace SoF
OUT(lootee);
OUT(looter);
eq->slot_id = emu->slot_id + 1;
eq->slot_id = ServerToSoFCorpseSlot(emu->slot_id);
OUT(auto_loot);
FINISH_ENCODE();
@ -2294,7 +2294,7 @@ namespace SoF
IN(lootee);
IN(looter);
emu->slot_id = eq->slot_id - 1;
emu->slot_id = SoFToServerCorpseSlot(eq->slot_id);
IN(auto_loot);
FINISH_DIRECT_DECODE();
@ -2920,6 +2920,7 @@ namespace SoF
static inline uint32 ServerToSoFCorpseSlot(uint32 ServerCorpse)
{
//uint32 SoFCorpse;
return (ServerCorpse + 1);
}
static inline uint32 SoFToServerSlot(uint32 SoFSlot)
@ -2945,6 +2946,7 @@ namespace SoF
static inline uint32 SoFToServerCorpseSlot(uint32 SoFCorpse)
{
//uint32 ServerCorpse;
return (SoFCorpse - 1);
}
}
// end namespace SoF

View File

@ -3963,9 +3963,9 @@ struct ItemQuaternaryBodyStruct
struct AugmentInfo_Struct
{
/*000*/ uint32 itemid; // id of the solvent needed
/*004*/ uint8 window; // window to display the information in
/*005*/ uint8 unknown005[71]; // total packet length 76, all the rest were always 00
/*000*/ uint32 itemid; // id of the solvent needed
/*004*/ uint8 window; // window to display the information in
/*005*/ uint8 unknown005[71]; // total packet length 76, all the rest were always 00
/*076*/
};

View File

@ -654,7 +654,7 @@ namespace Titanium
OUT(lootee);
OUT(looter);
eq->slot_id = emu->slot_id;
eq->slot_id = ServerToTitaniumCorpseSlot(emu->slot_id);
OUT(auto_loot);
FINISH_ENCODE();
@ -1347,9 +1347,6 @@ namespace Titanium
FINISH_DIRECT_DECODE();
}
// needs to be tested
DECODE(OP_AugmentInfo) { DECODE_FORWARD(OP_ReadBook); }
DECODE(OP_AugmentItem)
{
DECODE_LENGTH_EXACT(structs::AugmentItem_Struct);
@ -1520,7 +1517,7 @@ namespace Titanium
IN(lootee);
IN(looter);
emu->slot_id = eq->slot_id;
emu->slot_id = TitaniumToServerCorpseSlot(eq->slot_id);
IN(auto_loot);
FINISH_DIRECT_DECODE();
@ -1678,7 +1675,7 @@ namespace Titanium
0,
//merchant_slot, //instance ID, bullshit for now
(merchant_slot == 0) ? inst->GetSerialNumber() : merchant_slot,
0,
0, // item recast timer timestamp field (aka..last_cast_time field in SoF+ clients)
(stackable ? ((inst->GetItem()->ItemType == ItemTypePotion) ? 1 : 0) : charges),
inst->IsInstNoDrop() ? 1 : 0,
0
@ -1748,6 +1745,7 @@ namespace Titanium
static inline int16 ServerToTitaniumCorpseSlot(uint32 ServerCorpse)
{
//int16 TitaniumCorpse;
return ServerCorpse;
}
static inline uint32 TitaniumToServerSlot(int16 TitaniumSlot)
@ -1762,6 +1760,7 @@ namespace Titanium
static inline uint32 TitaniumToServerCorpseSlot(int16 TitaniumCorpse)
{
//uint32 ServerCorpse;
return TitaniumCorpse;
}
}
// end namespace Titanium

View File

@ -47,7 +47,6 @@ E(OP_ZoneSpawns)
// incoming packets that require a DECODE translation:
D(OP_AdventureMerchantSell)
D(OP_ApplyPoison)
D(OP_AugmentInfo)
D(OP_AugmentItem)
D(OP_CastSpell)
D(OP_CharacterCreate)

View File

@ -330,6 +330,7 @@ namespace Underfoot
OUT(duration);
OUT(slotid);
OUT(bufffade); // Live (October 2011) sends a 2 rather than 0 when a buff is created, but it doesn't seem to matter.
OUT(num_hits);
eq->unknown008 = 1.0f;
FINISH_ENCODE();
@ -348,7 +349,7 @@ namespace Underfoot
*((uint32*)ptr) = emu->entity_id;
ptr += sizeof(uint32);
ptr += sizeof(uint32);
*((uint8*)ptr) = 1;
*((uint8*)ptr) = emu->all_buffs;
ptr += sizeof(uchar);
*((uint16*)ptr) = emu->count;
ptr += sizeof(uint16);
@ -371,7 +372,9 @@ namespace Underfoot
ptr += sizeof(uint32);
*((uint32*)ptr) = emu->entries[i].tics_remaining;
ptr += sizeof(uint32);
*((uint32*)ptr) = emu->entries[i].num_hits;
ptr += sizeof(uint32);
*((uint8*)ptr) = !emu->all_buffs;
ptr += 1;
}
@ -1234,7 +1237,7 @@ namespace Underfoot
OUT(lootee);
OUT(looter);
eq->slot_id = emu->slot_id + 1;
eq->slot_id = ServerToUnderFootCorpseSlot(emu->slot_id);
OUT(auto_loot);
FINISH_ENCODE();
@ -3294,7 +3297,7 @@ namespace Underfoot
IN(lootee);
IN(looter);
emu->slot_id = eq->slot_id - 1;
emu->slot_id = UnderfootToServerCorpseSlot(eq->slot_id);
IN(auto_loot);
FINISH_DIRECT_DECODE();
@ -4021,6 +4024,7 @@ namespace Underfoot
static inline uint32 ServerToUnderFootCorpseSlot(uint32 ServerCorpse)
{
//uint32 UnderfootCorpse;
return (ServerCorpse + 1);
}
static inline uint32 UnderfootToServerSlot(uint32 UnderfootSlot)
@ -4046,6 +4050,7 @@ namespace Underfoot
static inline uint32 UnderfootToServerCorpseSlot(uint32 UnderfootCorpse)
{
//uint32 ServerCorpse;
return (UnderfootCorpse - 1);
}
}
// end namespace Underfoot

View File

@ -564,7 +564,7 @@ struct SpellBuffFade_Struct_Underfoot {
/*008*/ float unknown008;
/*012*/ uint32 spellid;
/*016*/ uint32 duration;
/*020*/ uint32 unknown016;
/*020*/ uint32 num_hits;
/*024*/ uint32 playerId; // Global player ID?
/*028*/ uint32 unknown020;
/*032*/ uint8 unknown0028[48];
@ -589,6 +589,25 @@ struct SpellBuffFade_Struct {
/*036*/
};
#if 0
struct BuffIconEntry_Struct {
/*000*/ uint32 buff_slot;
/*004*/ uint32 spell_id;
/*008*/ uint32 tics_remaining;
/*012*/ uint32 num_hits;
// char name[0]; caster name is also here sometimes
// uint8 unknownend; 1 when single, 0 when all opposite of all_buffs?
};
struct BuffIcon_Struct {
/*000*/ uint32 entity_id;
/*004*/ uint32 unknown004;
/*008*/ uint8 all_buffs; // 1 when updating all buffs, 0 when doing one
/*009*/ uint16 count;
/*011*/ BuffIconEntry_Struct entires[0];
};
#endif
struct BuffRemoveRequest_Struct
{
/*00*/ uint32 SlotID;
@ -4160,9 +4179,9 @@ struct ItemQuaternaryBodyStruct
struct AugmentInfo_Struct
{
/*000*/ uint32 itemid; // id of the solvent needed
/*004*/ uint8 window; // window to display the information in
/*005*/ uint8 unknown005[71]; // total packet length 76, all the rest were always 00
/*000*/ uint32 itemid; // id of the solvent needed
/*004*/ uint8 window; // window to display the information in
/*005*/ uint8 unknown005[71]; // total packet length 76, all the rest were always 00
/*076*/
};

View File

@ -615,6 +615,8 @@ OP_RAWOutOfSession=0x0000 #
OP_Some3ByteHPUpdate=0x0000 #initial HP update for mobs
OP_InitialHPUpdate=0x0000 #
OP_ItemRecastDelay=0x0ada
# Opcodes from the client that are currently Unknowns:
# 0x3E85 - Sent when Guild Management window is opened

View File

@ -1751,19 +1751,15 @@ void ZoneDatabase::FillAAEffects(SendAA_Struct* aa_struct){
if(!aa_struct)
return;
std::string query = StringFormat("SELECT effectid, base1, base2, slot from aa_effects where aaid=%i order by slot asc", aa_struct->id);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in Client::FillAAEffects query: '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return;
}
int index = 0;
for (auto row = results.begin(); row != results.end(); ++row, ++index) {
aa_struct->abilities[index].skill_id=atoi(row[0]);
aa_struct->abilities[index].base1=atoi(row[1]);
aa_struct->abilities[index].base2=atoi(row[2]);
aa_struct->abilities[index].slot=atoi(row[3]);
auto it = aa_effects.find(aa_struct->id);
if (it != aa_effects.end()) {
for (int slot = 0; slot < aa_struct->total_abilities; slot++) {
// aa_effects is a map of a map, so the slot reference does not start at 0
aa_struct->abilities[slot].skill_id = it->second[slot + 1].skill_id;
aa_struct->abilities[slot].base1 = it->second[slot + 1].base1;
aa_struct->abilities[slot].base2 = it->second[slot + 1].base2;
aa_struct->abilities[slot].slot = it->second[slot + 1].slot;
}
}
}

View File

@ -39,15 +39,10 @@
extern volatile bool RunLoops;
#include "../common/features.h"
#include "masterentity.h"
#include "worldserver.h"
#include "../common/misc.h"
#include "zonedb.h"
#include "../common/spdat.h"
#include "net.h"
#include "../common/packet_dump.h"
#include "../common/packet_functions.h"
#include "petitions.h"
#include "../common/serverinfo.h"
#include "../common/zone_numbers.h"
#include "../common/moremath.h"
@ -55,6 +50,12 @@ extern volatile bool RunLoops;
#include "../common/breakdowns.h"
#include "../common/rulesys.h"
#include "../common/string_util.h"
#include "../common/data_verification.h"
#include "net.h"
#include "masterentity.h"
#include "worldserver.h"
#include "zonedb.h"
#include "petitions.h"
#include "forage.h"
#include "command.h"
#include "string_ids.h"
@ -594,19 +595,8 @@ bool Client::Save(uint8 iCommitNow) {
database.SaveCharacterTribute(this->CharacterID(), &m_pp);
SaveTaskState(); /* Save Character Task */
if(m_pp.hunger_level < 0) {
m_pp.hunger_level = 0;
}
else if(m_pp.hunger_level > 6000) {
m_pp.hunger_level = 6000;
}
if(m_pp.thirst_level < 0) {
m_pp.thirst_level = 0;
}
else if(m_pp.thirst_level > 6000) {
m_pp.thirst_level = 6000;
}
m_pp.hunger_level = EQEmu::Clamp(m_pp.hunger_level, 0, 50000);
m_pp.thirst_level = EQEmu::Clamp(m_pp.thirst_level, 0, 50000);
database.SaveCharacterData(this->CharacterID(), this->AccountID(), &m_pp, &m_epp); /* Save Character Data */
return true;

View File

@ -896,7 +896,8 @@ public:
//This is used to later set the buff duration of the spell, in slot to duration.
//Doesn't appear to work directly after the client recieves an action packet.
void SendBuffDurationPacket(uint16 spell_id, int duration, int inlevel);
void SendBuffDurationPacket(Buffs_Struct &buff);
void SendBuffNumHitPacket(Buffs_Struct &buff, int slot);
void ProcessInspectRequest(Client* requestee, Client* requester);
bool ClientFinishedLoading() { return (conn_state == ClientConnectFinished); }

View File

@ -3395,7 +3395,7 @@ void Mob::BuffProcess()
{
if(buffs[buffs_i].UpdateClient == true)
{
CastToClient()->SendBuffDurationPacket(buffs[buffs_i].spellid, buffs[buffs_i].ticsremaining, buffs[buffs_i].casterlevel);
CastToClient()->SendBuffDurationPacket(buffs[buffs_i]);
buffs[buffs_i].UpdateClient = false;
}
}
@ -5559,64 +5559,56 @@ void Mob::CheckNumHitsRemaining(uint8 type, uint32 buff_slot, uint16 spell_id)
uint32 buff_max = GetMaxTotalSlots();
//Spell specific procs [Type 7,10,11]
if (IsValidSpell(spell_id)){
for(uint32 d = 0; d < buff_max; d++) {
if((buffs[d].spellid == spell_id) && (buffs[d].numhits > 0) && (spells[buffs[d].spellid].numhitstype == type)){
if(--buffs[d].numhits == 0) {
if (IsValidSpell(spell_id)) {
for (uint32 d = 0; d < buff_max; d++) {
if (buffs[d].spellid == spell_id && buffs[d].numhits > 0 &&
spells[buffs[d].spellid].numhitstype == type) {
if (--buffs[d].numhits == 0) {
CastOnNumHitFade(buffs[d].spellid);
if(!TryFadeEffect(d))
if (!TryFadeEffect(d))
BuffFadeBySlot(d, true);
} else if (IsClient()) { // still have numhits and client, update
CastToClient()->SendBuffNumHitPacket(buffs[d], d);
}
}
}
}
else if (type == 7){
if (buff_slot > 0){
if(--buffs[buff_slot].numhits == 0) {
} else if (type == 7) {
if (buff_slot > 0) {
if (--buffs[buff_slot].numhits == 0) {
CastOnNumHitFade(buffs[buff_slot].spellid);
if(!TryFadeEffect(buff_slot))
if (!TryFadeEffect(buff_slot))
BuffFadeBySlot(buff_slot , true);
}
} else if (IsClient()) { // still have numhits and client, update
CastToClient()->SendBuffNumHitPacket(buffs[buff_slot], buff_slot);
}
else {
for(int d = 0; d < buff_max; d++) {
if(!m_spellHitsLeft[d])
} else {
for (int d = 0; d < buff_max; d++) {
if (!m_spellHitsLeft[d])
continue;
if ((IsValidSpell(buffs[d].spellid)) && (m_spellHitsLeft[d] == buffs[d].spellid)) {
if(--buffs[d].numhits == 0) {
if (IsValidSpell(buffs[d].spellid) && m_spellHitsLeft[d] == buffs[d].spellid) {
if (--buffs[d].numhits == 0) {
CastOnNumHitFade(buffs[d].spellid);
m_spellHitsLeft[d] = 0;
if(!TryFadeEffect(d))
if (!TryFadeEffect(d))
BuffFadeBySlot(d, true);
} else if (IsClient()) { // still have numhits and client, update
CastToClient()->SendBuffNumHitPacket(buffs[d], d);
}
}
}
}
}
else{
for(uint32 d = 0; d < buff_max; d++) {
if((IsValidSpell(buffs[d].spellid)) && (buffs[d].numhits > 0) && (spells[buffs[d].spellid].numhitstype == type)){
if(--buffs[d].numhits == 0) {
} else {
for (uint32 d = 0; d < buff_max; d++) {
if (IsValidSpell(buffs[d].spellid) && buffs[d].numhits > 0 &&
spells[buffs[d].spellid].numhitstype == type) {
if (--buffs[d].numhits == 0) {
CastOnNumHitFade(buffs[d].spellid);
if(!TryFadeEffect(d)){
if (!TryFadeEffect(d))
BuffFadeBySlot(d, true);
}
} else if (IsClient()) { // still have numhits and client, update
CastToClient()->SendBuffNumHitPacket(buffs[d], d);
}
}
}
}

View File

@ -484,19 +484,6 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot,
return false;
}
// This needs a bit more work for saving timer to PP for zoning etc
if (IsClient() && item_slot != INVALID_INDEX && ((slot == USE_ITEM_SPELL_SLOT) || (slot == POTION_BELT_SPELL_SLOT))) {
ItemInst *itm = CastToClient()->GetInv().GetItem(item_slot);
if (itm && itm->GetItem()->RecastDelay) {
outapp = new EQApplicationPacket(OP_ItemRecastDelay, sizeof(ItemRecastDelay_Struct));
ItemRecastDelay_Struct *ird = (ItemRecastDelay_Struct *)outapp->pBuffer;
ird->recast_delay = itm->GetItem()->RecastDelay;
ird->recast_type = itm->GetItem()->RecastType;
CastToClient()->QueuePacket(outapp);
safe_delete(outapp);
}
}
return(true);
}
@ -2228,6 +2215,12 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16
ItemInst *itm = CastToClient()->GetInv().GetItem(inventory_slot);
if(itm && itm->GetItem()->RecastDelay > 0){
CastToClient()->GetPTimers().Start((pTimerItemStart + itm->GetItem()->RecastType), itm->GetItem()->RecastDelay);
EQApplicationPacket *outapp = new EQApplicationPacket(OP_ItemRecastDelay, sizeof(ItemRecastDelay_Struct));
ItemRecastDelay_Struct *ird = (ItemRecastDelay_Struct *)outapp->pBuffer;
ird->recast_delay = itm->GetItem()->RecastDelay;
ird->recast_type = itm->GetItem()->RecastType;
CastToClient()->QueuePacket(outapp);
safe_delete(outapp);
}
}
@ -5164,20 +5157,40 @@ void Mob::_StopSong()
//Thus I use this in the buff process to update the correct duration once after casting
//this allows AAs and focus effects that increase buff duration to work correctly, but could probably
//be used for other things as well
void Client::SendBuffDurationPacket(uint16 spell_id, int duration, int inlevel)
void Client::SendBuffDurationPacket(Buffs_Struct &buff)
{
EQApplicationPacket* outapp;
outapp = new EQApplicationPacket(OP_Buff, sizeof(SpellBuffFade_Struct));
SpellBuffFade_Struct* sbf = (SpellBuffFade_Struct*) outapp->pBuffer;
sbf->entityid = GetID();
sbf->slot=2;
sbf->spellid=spell_id;
sbf->slotid=0;
sbf->effect = inlevel > 0 ? inlevel : GetLevel();
sbf->level = inlevel > 0 ? inlevel : GetLevel();
sbf->slot = 2;
sbf->spellid = buff.spellid;
sbf->slotid = 0;
sbf->effect = buff.casterlevel > 0 ? buff.casterlevel : GetLevel();
sbf->level = buff.casterlevel > 0 ? buff.casterlevel : GetLevel();
sbf->bufffade = 0;
sbf->duration = duration;
sbf->duration = buff.ticsremaining;
sbf->num_hits = buff.numhits;
FastQueuePacket(&outapp);
}
void Client::SendBuffNumHitPacket(Buffs_Struct &buff, int slot)
{
// UF+ use this packet
if (GetClientVersion() < EQClientUnderfoot)
return;
EQApplicationPacket *outapp;
outapp = new EQApplicationPacket(OP_BuffCreate, sizeof(BuffIcon_Struct) + sizeof(BuffIconEntry_Struct));
BuffIcon_Struct *bi = (BuffIcon_Struct *)outapp->pBuffer;
bi->entity_id = GetID();
bi->count = 1;
bi->all_buffs = 0;
bi->entries[0].buff_slot = slot;
bi->entries[0].spell_id = buff.spellid;
bi->entries[0].tics_remaining = buff.ticsremaining;
bi->entries[0].num_hits = buff.numhits;
FastQueuePacket(&outapp);
}
@ -5252,6 +5265,7 @@ EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target)
BuffIcon_Struct *buff = (BuffIcon_Struct*)outapp->pBuffer;
buff->entity_id = GetID();
buff->count = count;
buff->all_buffs = 1;
uint32 index = 0;
for(unsigned int i = 0; i < buff_count; ++i)
@ -5261,6 +5275,7 @@ EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target)
buff->entries[index].buff_slot = i;
buff->entries[index].spell_id = buffs[i].spellid;
buff->entries[index].tics_remaining = buffs[i].ticsremaining;
buff->entries[index].num_hits = buffs[i].numhits;
++index;
}
}
@ -5278,7 +5293,7 @@ void Mob::BuffModifyDurationBySpellID(uint16 spell_id, int32 newDuration)
buffs[i].ticsremaining = newDuration;
if(IsClient())
{
CastToClient()->SendBuffDurationPacket(buffs[i].spellid, buffs[i].ticsremaining, buffs[i].casterlevel);
CastToClient()->SendBuffDurationPacket(buffs[i]);
}
}
}

View File

@ -2895,96 +2895,74 @@ void ZoneDatabase::LoadBuffs(Client *client) {
}
}
void ZoneDatabase::SavePetInfo(Client *client) {
void ZoneDatabase::SavePetInfo(Client *client)
{
PetInfo *petinfo = nullptr;
PetInfo *petinfo = client->GetPetInfo(0);
PetInfo *suspended = client->GetPetInfo(1);
std::string query = StringFormat("DELETE FROM `character_pet_buffs` WHERE `char_id` = %u", client->CharacterID());
auto results = database.QueryDatabase(query);
if(!results.Success())
std::string query = StringFormat("DELETE FROM `character_pet_buffs` WHERE `char_id` = %u", client->CharacterID());
auto results = database.QueryDatabase(query);
if (!results.Success())
return;
query = StringFormat("DELETE FROM `character_pet_buffs` WHERE `char_id` = %u", client->CharacterID());
query = StringFormat("DELETE FROM `character_pet_inventory` WHERE `char_id` = %u", client->CharacterID());
results = database.QueryDatabase(query);
if(!results.Success())
if (!results.Success())
return;
query = StringFormat("INSERT INTO `character_pet_info` "
"(`char_id`, `pet`, `petname`, `petpower`, `spell_id`, `hp`, `mana`, `size`) "
"VALUES (%u, 0, '%s', %i, %u, %u, %u, %f) "
"ON DUPLICATE KEY UPDATE `petname` = '%s', `petpower` = %i, `spell_id` = %u, "
"`hp` = %u, `mana` = %u, `size` = %f",
client->CharacterID(), petinfo->Name, petinfo->petpower, petinfo->SpellID,
petinfo->HP, petinfo->Mana, petinfo->size, petinfo->Name, petinfo->petpower,
petinfo->SpellID, petinfo->HP, petinfo->Mana, petinfo->size);
results = database.QueryDatabase(query);
if(!results.Success())
return;
for (int pet = 0; pet < 2; pet++) {
petinfo = client->GetPetInfo(pet);
if (!petinfo)
continue;
for(int index = 0; index < RuleI(Spells, MaxTotalSlotsPET); index++) {
if (petinfo->Buffs[index].spellid == SPELL_UNKNOWN || petinfo->Buffs[index].spellid == 0)
continue;
query = StringFormat("INSERT INTO `character_pet_info` "
"(`char_id`, `pet`, `petname`, `petpower`, `spell_id`, `hp`, `mana`, `size`) "
"VALUES (%u, %u, '%s', %i, %u, %u, %u, %f) "
"ON DUPLICATE KEY UPDATE `petname` = '%s', `petpower` = %i, `spell_id` = %u, "
"`hp` = %u, `mana` = %u, `size` = %f",
client->CharacterID(), pet, petinfo->Name, petinfo->petpower, petinfo->SpellID,
petinfo->HP, petinfo->Mana, petinfo->size, // and now the ON DUPLICATE ENTRIES
petinfo->Name, petinfo->petpower, petinfo->SpellID, petinfo->HP, petinfo->Mana, petinfo->size);
results = database.QueryDatabase(query);
if (!results.Success())
return;
query.clear();
query = StringFormat("INSERT INTO `character_pet_buffs` "
"(`char_id`, `pet`, `slot`, `spell_id`, `caster_level`, "
"`ticsremaining`, `counters`) "
"VALUES (%u, 0, %u, %u, %u, %u, %d)",
client->CharacterID(), index, petinfo->Buffs[index].spellid,
petinfo->Buffs[index].level, petinfo->Buffs[index].duration,
petinfo->Buffs[index].counters);
database.QueryDatabase(query);
}
// pet buffs!
for (int index = 0; index < RuleI(Spells, MaxTotalSlotsPET); index++) {
if (petinfo->Buffs[index].spellid == SPELL_UNKNOWN || petinfo->Buffs[index].spellid == 0)
continue;
if (query.length() == 0)
query = StringFormat("INSERT INTO `character_pet_buffs` "
"(`char_id`, `pet`, `slot`, `spell_id`, `caster_level`, "
"`ticsremaining`, `counters`) "
"VALUES (%u, %u, %u, %u, %u, %u, %d)",
client->CharacterID(), pet, index, petinfo->Buffs[index].spellid,
petinfo->Buffs[index].level, petinfo->Buffs[index].duration,
petinfo->Buffs[index].counters);
else
query += StringFormat(", (%u, %u, %u, %u, %u, %u, %d)",
client->CharacterID(), pet, index, petinfo->Buffs[index].spellid,
petinfo->Buffs[index].level, petinfo->Buffs[index].duration,
petinfo->Buffs[index].counters);
}
database.QueryDatabase(query);
query.clear();
for(int index = 0; index < RuleI(Spells, MaxTotalSlotsPET); index++) {
if (petinfo->Buffs[index].spellid == SPELL_UNKNOWN || petinfo->Buffs[index].spellid == 0)
continue;
// pet inventory!
for (int index = EmuConstants::EQUIPMENT_BEGIN; index <= EmuConstants::EQUIPMENT_END; index++) {
if (!petinfo->Items[index])
continue;
query = StringFormat("INSERT INTO `character_pet_buffs` "
"(`char_id`, `pet`, `slot`, `spell_id`, `caster_level`, "
"`ticsremaining`, `counters`) "
"VALUES (%u, 1, %u, %u, %u, %u, %d)",
client->CharacterID(), index, suspended->Buffs[index].spellid,
suspended->Buffs[index].level, suspended->Buffs[index].duration,
suspended->Buffs[index].counters);
database.QueryDatabase(query);
if (query.length() == 0)
query = StringFormat("INSERT INTO `character_pet_inventory` "
"(`char_id`, `pet`, `slot`, `item_id`) "
"VALUES (%u, %u, %u, %u)",
client->CharacterID(), pet, index, petinfo->Items[index]);
else
query += StringFormat(", (%u, %u, %u, %u)", client->CharacterID(), pet, index, petinfo->Items[index]);
}
database.QueryDatabase(query);
}
for (int index = EmuConstants::EQUIPMENT_BEGIN; index <= EmuConstants::EQUIPMENT_END; index++) {
if(!petinfo->Items[index])
continue;
query = StringFormat("INSERT INTO `character_pet_inventory` "
"(`char_id`, `pet`, `slot`, `item_id`) "
"VALUES (%u, 0, %u, %u)",
client->CharacterID(), index, petinfo->Items[index]);
database.QueryDatabase(query);
}
query = StringFormat("INSERT INTO `character_pet_info` "
"(`char_id`, `pet`, `petname`, `petpower`, `spell_id`, `hp`, `mana`, `size`) "
"VALUES (%u, 1, '%s', %u, %u, %u, %u, %f) "
"ON DUPLICATE KEY UPDATE "
"`petname`='%s', `petpower`=%i, `spell_id`=%u, `hp`=%u, `mana`=%u, `size`=%f",
client->CharacterID(), suspended->Name, suspended->petpower, suspended->SpellID,
suspended->HP, suspended->Mana, suspended->size, suspended->Name, suspended->petpower,
suspended->SpellID, suspended->HP, suspended->Mana, suspended->size);
results = database.QueryDatabase(query);
if(!results.Success())
return;
for (int index = EmuConstants::EQUIPMENT_BEGIN; index <= EmuConstants::EQUIPMENT_END; index++) {
if(!suspended->Items[index])
continue;
query = StringFormat("INSERT INTO `character_pet_inventory` "
"(`char_id`, `pet`, `slot`, `item_id`) "
"VALUES (%u, 1, %u, %u)",
client->CharacterID(), index, suspended->Items[index]);
database.QueryDatabase(query);
}
}
void ZoneDatabase::RemoveTempFactions(Client *client) {