diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 80bf07564..c0cb648f4 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -892,6 +892,8 @@ void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) uint32 type, timestamp, decompressedSize; recv_data >> type >> timestamp >> decompressedSize; + sLog.outDebug("UAD: type %u, time %u, decompressedSize %u", type, timestamp, decompressedSize); + if(type > NUM_ACCOUNT_DATA_TYPES) return; @@ -943,6 +945,8 @@ void WorldSession::HandleRequestAccountData(WorldPacket& recv_data) uint32 type; recv_data >> type; + sLog.outDebug("RAD: type %u", type); + if(type > NUM_ACCOUNT_DATA_TYPES) return; diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 56ab76c30..ca6696832 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -56,6 +56,8 @@ Pet::Pet(PetType type) : Creature() m_auraUpdateMask = 0; + m_loading = false; + // pets always have a charminfo, even if they are not actually charmed CharmInfo* charmInfo = InitCharmInfo(this); @@ -101,6 +103,8 @@ void Pet::RemoveFromWorld() bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool current ) { + m_loading = true; + uint32 ownerid = owner->GetGUIDLow(); QueryResult *result; @@ -341,6 +345,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu } } + m_loading = false; return true; } @@ -1277,7 +1282,8 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s ToggleAutocast(itr->first, false); oldspell_id = itr->first; - removeSpell(itr->first); + //removeSpell(itr->first); + unlearnSpell(itr->first); break; } } @@ -1299,16 +1305,6 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s newspell->slotId = tmpslot; m_spells[spell_id] = newspell; - if(GetOwner()->GetTypeId() == TYPEID_PLAYER) - { - if(!IsPassiveSpell(spell_id)) - { - WorldPacket data(SMSG_PET_LEARNED_SPELL, 2); - data << uint16(spell_id); - ((Player*)GetOwner())->GetSession()->SendPacket(&data); - } - } - if (IsPassiveSpell(spell_id)) CastSpell(this, spell_id, true); else if(state == PETSPELL_NEW) @@ -1326,6 +1322,16 @@ bool Pet::learnSpell(uint16 spell_id) if (!addSpell(spell_id)) return false; + if(GetOwner()->GetTypeId() == TYPEID_PLAYER) + { + if(!m_loading) + { + WorldPacket data(SMSG_PET_LEARNED_SPELL, 2); + data << uint16(spell_id); + ((Player*)GetOwner())->GetSession()->SendPacket(&data); + } + } + Unit* owner = GetOwner(); if(owner->GetTypeId() == TYPEID_PLAYER) ((Player*)owner)->PetSpellInitialize(); @@ -1343,18 +1349,36 @@ void Pet::learnLevelupSpells() if(itr->ReqLevel <= getLevel()) learnSpell(itr->SpellId); else - removeSpell(itr->SpellId); + unlearnSpell(itr->SpellId); } } -void Pet::removeSpell(uint16 spell_id) +bool Pet::unlearnSpell(uint16 spell_id) +{ + if(removeSpell(spell_id)) + { + if(GetOwner()->GetTypeId() == TYPEID_PLAYER) + { + if(!m_loading) + { + WorldPacket data(SMSG_PET_UNLEARNED_SPELL, 2); + data << uint16(spell_id); + ((Player*)GetOwner())->GetSession()->SendPacket(&data); + } + } + return true; + } + return false; +} + +bool Pet::removeSpell(uint16 spell_id) { PetSpellMap::iterator itr = m_spells.find(spell_id); if (itr == m_spells.end()) - return; + return false; if(itr->second->state == PETSPELL_REMOVED) - return; + return false; if(itr->second->state == PETSPELL_NEW) { @@ -1366,15 +1390,7 @@ void Pet::removeSpell(uint16 spell_id) RemoveAurasDueToSpell(spell_id); - if(GetOwner()->GetTypeId() == TYPEID_PLAYER) - { - if(!IsPassiveSpell(spell_id)) - { - WorldPacket data(SMSG_PET_UNLEARNED_SPELL, 2); - data << uint16(spell_id); - ((Player*)GetOwner())->GetSession()->SendPacket(&data); - } - } + return true; } bool Pet::_removeSpell(uint16 spell_id) diff --git a/src/game/Pet.h b/src/game/Pet.h index cbabb3985..992396e7b 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -68,6 +68,7 @@ struct PetSpell { uint16 slotId; uint16 active; + PetSpellState state : 16; PetSpellType type : 16; }; @@ -191,7 +192,8 @@ class Pet : public Creature bool addSpell(uint16 spell_id,uint16 active = ACT_DECIDE, PetSpellState state = PETSPELL_NEW, uint16 slot_id=0xffff, PetSpellType type = PETSPELL_NORMAL); bool learnSpell(uint16 spell_id); void learnLevelupSpells(); - void removeSpell(uint16 spell_id); + bool unlearnSpell(uint16 spell_id); + bool removeSpell(uint16 spell_id); bool _removeSpell(uint16 spell_id); PetSpellMap m_spells; @@ -222,6 +224,7 @@ class Pet : public Creature int32 m_duration; // time until unsummon (used mostly for summoned guardians and not used for controlled pets) int32 m_bonusdamage; uint64 m_auraUpdateMask; + bool m_loading; DeclinedName *m_declinedname; diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index 511544afe..d02080ccb 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -155,7 +155,6 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) } break; case ACT_DISABLED: //0x8100 spell (disabled), ignore - case ACT_CAST: //0x0100 case ACT_ENABLED: //0xc100 spell { Unit* unit_target; @@ -349,7 +348,7 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data ) sLog.outDetail( "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X\n", _player->GetName(), position, spell_id, act_state); //if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add - if(!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_CAST) && spell_id && !pet->HasSpell(spell_id))) + if(!((act_state == ACT_ENABLED || act_state == ACT_DISABLED) && spell_id && !pet->HasSpell(spell_id))) { //sign for autocast if(act_state == ACT_ENABLED && spell_id) @@ -519,7 +518,8 @@ void WorldSession::HandlePetUnlearnOpcode(WorldPacket& recvPacket) { uint32 spell_id = itr->first; // Pet::removeSpell can invalidate iterator at erase NEW spell ++itr; - pet->removeSpell(spell_id); + //pet->removeSpell(spell_id); + pet->unlearnSpell(spell_id); } for(uint8 i = 0; i < 10; i++) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 4ee84ebc9..374138b42 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -2341,7 +2341,6 @@ void Player::SendInitialSpells() continue; data << uint16(itr->first); - //data << uint16(itr->second->slotId); data << uint16(0); // it's not slot id spellCount +=1; @@ -2368,13 +2367,13 @@ void Player::SendInitialSpells() data << uint16(sEntry->Category); // spell category if(sEntry->Category) // may be wrong, but anyway better than nothing... { - data << uint32(0); - data << uint32(cooldown); + data << uint32(0); // cooldown + data << uint32(cooldown); // category cooldown } else { - data << uint32(cooldown); - data << uint32(0); + data << uint32(cooldown); // cooldown + data << uint32(0); // category cooldown } } @@ -16002,68 +16001,67 @@ void Player::PetSpellInitialize() { Pet* pet = GetPet(); - if(pet) + if(!pet) + return; + + sLog.outDebug("Pet Spells Groups"); + + CharmInfo *charmInfo = pet->GetCharmInfo(); + + WorldPacket data(SMSG_PET_SPELLS, 8+4+4+4+10*4); + data << uint64(pet->GetGUID()); + data << uint32(pet->GetCreatureInfo()->family); // creature family (required for pet talents) + data << uint32(0); + data << uint8(charmInfo->GetReactState()) << uint8(charmInfo->GetCommandState()) << uint16(0); + + // action bar loop + for(uint32 i = 0; i < 10; i++) { - uint8 addlist = 0; - - sLog.outDebug("Pet Spells Groups"); - - CreatureInfo const *cinfo = pet->GetCreatureInfo(); - - if(pet->isControlled() && (pet->getPetType() == HUNTER_PET || cinfo && cinfo->type == CREATURE_TYPE_DEMON && getClass() == CLASS_WARLOCK)) - { - for(PetSpellMap::iterator itr = pet->m_spells.begin();itr != pet->m_spells.end();itr++) - { - if(itr->second->state == PETSPELL_REMOVED) - continue; - ++addlist; - } - } - - // first line + actionbar + spellcount + spells + last adds - WorldPacket data(SMSG_PET_SPELLS, 16+40+1+4*addlist+25); - - CharmInfo *charmInfo = pet->GetCharmInfo(); - - //16 - data << uint64(pet->GetGUID()); - data << uint32(pet->GetCreatureInfo()->family); // creature family (required for pet talents) - data << uint8(charmInfo->GetReactState()) << uint8(charmInfo->GetCommandState()) << uint16(0); - data << uint32(0); - - for(uint32 i = 0; i < 10; i++) //40 - { - data << uint16(charmInfo->GetActionBarEntry(i)->SpellOrAction) << uint16(charmInfo->GetActionBarEntry(i)->Type); - } - - data << uint8(addlist); //1 - - if(addlist && pet->isControlled()) - { - for (PetSpellMap::iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end(); ++itr) - { - if(itr->second->state == PETSPELL_REMOVED) - continue; - - data << uint16(itr->first); - data << uint16(itr->second->active); // pet spell active state isn't boolean - } - } - - //data << uint8(0x01) << uint32(0x6010) << uint32(0x01) << uint32(0x05) << uint16(0x00); //15 - uint8 count = 3; //1+8+8+8=25 - - // if count = 0, then end of packet... - data << count; - // uint32 value is spell id... - // uint64 value is constant 0, unknown... - data << uint32(0x6010) << uint64(0); // if count = 1, 2 or 3 - //data << uint32(0x5fd1) << uint64(0); // if count = 2 - data << uint32(0x8e8c) << uint64(0); // if count = 3 - data << uint32(0x8e8b) << uint64(0); // if count = 3 - - GetSession()->SendPacket(&data); + data << uint32(charmInfo->GetActionBarEntry(i)->Raw); } + + size_t spellsCountPos = data.wpos(); + + // spells count + uint8 addlist = 0; + data << uint8(addlist); // placeholder + + if(pet->isControlled() && ((pet->getPetType() == HUNTER_PET) || ((pet->GetCreatureInfo()->type == CREATURE_TYPE_DEMON) && (getClass() == CLASS_WARLOCK)))) + { + // spells loop + for (PetSpellMap::iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end(); ++itr) + { + if(itr->second->state == PETSPELL_REMOVED) + continue; + + data << uint16(itr->first); + data << uint16(itr->second->active); // pet spell active state isn't boolean + ++addlist; + } + } + + data.put(spellsCountPos, addlist); + + uint8 cooldownsCount = pet->m_CreatureSpellCooldowns.size() + pet->m_CreatureCategoryCooldowns.size(); + data << uint8(cooldownsCount); + + for(CreatureSpellCooldowns::const_iterator itr = pet->m_CreatureSpellCooldowns.begin(); itr != pet->m_CreatureSpellCooldowns.end(); ++itr) + { + data << uint16(itr->first); // spellid + data << uint16(0); // unk + data << uint32(itr->second); // cooldown + data << uint32(0); // category cooldown + } + + for(CreatureSpellCooldowns::const_iterator itr = pet->m_CreatureCategoryCooldowns.begin(); itr != pet->m_CreatureCategoryCooldowns.end(); ++itr) + { + data << uint16(itr->first); // spellid + data << uint16(0); // unk + data << uint32(0); // cooldown + data << uint32(itr->second); // category cooldown + } + + GetSession()->SendPacket(&data); } void Player::PossessSpellInitialize() @@ -16087,8 +16085,8 @@ void Player::PossessSpellInitialize() //16 data << uint64(charm->GetGUID()); data << uint32(0x00000000); - data << uint8(0) << uint8(0) << uint16(0); data << uint32(0); + data << uint8(0) << uint8(0) << uint16(0); for(uint32 i = 0; i < 10; i++) //40 { @@ -16097,11 +16095,8 @@ void Player::PossessSpellInitialize() data << uint8(addlist); //1 - uint8 count = 3; - data << count; - data << uint32(0x6010) << uint64(0); // if count = 1, 2 or 3 - data << uint32(0x8e8c) << uint64(0); // if count = 3 - data << uint32(0x8e8b) << uint64(0); // if count = 3 + uint8 count = 0; + data << uint8(count); // cooldowns count GetSession()->SendPacket(&data); } @@ -16138,15 +16133,14 @@ void Player::CharmSpellInitialize() WorldPacket data(SMSG_PET_SPELLS, 16+40+1+4*addlist+25);// first line + actionbar + spellcount + spells + last adds - data << (uint64)charm->GetGUID() << uint32(0x00000000); - + data << uint64(charm->GetGUID()); + data << uint32(0x00000000); + data << uint32(0); if(charm->GetTypeId() != TYPEID_PLAYER) data << uint8(charmInfo->GetReactState()) << uint8(charmInfo->GetCommandState()); else data << uint8(0) << uint8(0); - data << uint16(0); - data << uint32(0); for(uint32 i = 0; i < 10; i++) //40 { @@ -16168,11 +16162,8 @@ void Player::CharmSpellInitialize() } } - uint8 count = 3; - data << count; - data << uint32(0x6010) << uint64(0); // if count = 1, 2 or 3 - data << uint32(0x8e8c) << uint64(0); // if count = 3 - data << uint32(0x8e8b) << uint64(0); // if count = 3 + uint8 count = 0; + data << uint8(count); // cooldowns count GetSession()->SendPacket(&data); } diff --git a/src/game/QuestDef.cpp b/src/game/QuestDef.cpp index a8f903bf7..1e2cd6021 100644 --- a/src/game/QuestDef.cpp +++ b/src/game/QuestDef.cpp @@ -65,7 +65,7 @@ Quest::Quest(Field * questRecord) ReqItemId[i] = questRecord[39+i].GetUInt32(); for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - ReqItemCount[i] = questRecord[42+i].GetUInt32(); + ReqItemCount[i] = questRecord[43+i].GetUInt32(); for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i) ReqSourceId[i] = questRecord[47+i].GetUInt32(); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 8b894bb87..415f6a7a3 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -9897,7 +9897,7 @@ void CharmInfo::InitEmptyActionBar() { for(uint32 x = 1; x < 10; ++x) { - PetActionBar[x].Type = ACT_CAST; + PetActionBar[x].Type = ACT_ENABLED; PetActionBar[x].SpellOrAction = 0; } PetActionBar[0].Type = ACT_COMMAND; @@ -9916,7 +9916,7 @@ void CharmInfo::InitPossessCreateSpells() if (IsPassiveSpell(((Creature*)m_unit)->m_spells[x])) m_unit->CastSpell(m_unit, ((Creature*)m_unit)->m_spells[x], true); else - AddSpellToAB(0, ((Creature*)m_unit)->m_spells[x], ACT_CAST); + AddSpellToAB(0, ((Creature*)m_unit)->m_spells[x], ACT_ENABLED); } } @@ -9959,7 +9959,7 @@ void CharmInfo::InitCharmCreateSpells() if(onlyselfcast || !IsPositiveSpell(spellId)) //only self cast and spells versus enemies are autocastable newstate = ACT_DISABLED; else - newstate = ACT_CAST; + newstate = ACT_ENABLED; AddSpellToAB(0, spellId, newstate); } @@ -9970,7 +9970,7 @@ bool CharmInfo::AddSpellToAB(uint32 oldid, uint32 newid, ActiveStates newstate) { for(uint8 i = 0; i < 10; i++) { - if((PetActionBar[i].Type == ACT_DISABLED || PetActionBar[i].Type == ACT_ENABLED || PetActionBar[i].Type == ACT_CAST) && PetActionBar[i].SpellOrAction == oldid) + if((PetActionBar[i].Type == ACT_DISABLED || PetActionBar[i].Type == ACT_ENABLED) && PetActionBar[i].SpellOrAction == oldid) { PetActionBar[i].SpellOrAction = newid; if(!oldid) diff --git a/src/game/Unit.h b/src/game/Unit.h index e3ef72b73..824e530b3 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -593,8 +593,18 @@ struct CleanDamage struct UnitActionBarEntry { - uint32 Type; - uint32 SpellOrAction; + union + { + struct + { + uint16 Type; + uint16 SpellOrAction; + }; + struct + { + uint32 Raw; + }; + }; }; #define MAX_DECLINED_NAME_CASES 5 @@ -616,13 +626,12 @@ enum CurrentSpellTypes enum ActiveStates { - ACT_ENABLED = 0xC100, - ACT_DISABLED = 0x8100, - ACT_COMMAND = 0x0700, - ACT_REACTION = 0x0600, - ACT_CAST = 0x0100, - ACT_PASSIVE = 0x0000, - ACT_DECIDE = 0x0001 + ACT_PASSIVE = 0x0100, // 0x0100 - passive + ACT_DISABLED = 0x8100, // 0x8000 - castable + ACT_ENABLED = 0xC100, // 0x4000 | 0x8000 - auto cast + castable + ACT_COMMAND = 0x0700, // 0x0100 | 0x0200 | 0x0400 + ACT_REACTION = 0x0600, // 0x0200 | 0x0400 + ACT_DECIDE = 0x0001 // what is it? }; enum ReactStates diff --git a/src/game/UpdateFields.h b/src/game/UpdateFields.h index c5a8af86d..09953bea5 100644 --- a/src/game/UpdateFields.h +++ b/src/game/UpdateFields.h @@ -19,7 +19,7 @@ #ifndef _UPDATEFIELDS_AUTO_H #define _UPDATEFIELDS_AUTO_H -// Auto generated for version 3, 0, 3, 9155 +// Auto generated for version 3, 0, 3, 9183 enum EObjectFields {