diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp index cd0e1db02..9c4223e34 100644 --- a/src/game/PetAI.cpp +++ b/src/game/PetAI.cpp @@ -335,4 +335,4 @@ void PetAI::AttackedBy(Unit *attacker) if(!m_creature->getVictim() && m_creature->GetCharmInfo() && !m_creature->GetCharmInfo()->HasReactState(REACT_PASSIVE) && (!m_creature->GetCharmInfo()->HasCommandState(COMMAND_STAY) || m_creature->canReachWithAttack(attacker))) AttackStart(attacker); -} +} \ No newline at end of file diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 77bf6c22f..f81ef2e17 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -16359,9 +16359,7 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent) if(pet->isControlled()) { - WorldPacket data(SMSG_PET_SPELLS, 8); - data << uint64(0); - GetSession()->SendPacket(&data); + RemovePetActionBar(); if(GetGroup()) SetGroupUpdateFlag(GROUP_UPDATE_PET); @@ -16623,6 +16621,13 @@ void Player::CharmSpellInitialize() GetSession()->SendPacket(&data); } +void Player::RemovePetActionBar() +{ + WorldPacket data(SMSG_PET_SPELLS, 8); + data << uint64(0); + SendDirectMessage(&data); +} + bool Player::IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell) { if (!mod || !spellInfo) @@ -19380,7 +19385,7 @@ void Player::EnterVehicle(Vehicle *vehicle) vehicle->SetCharmerGUID(GetGUID()); vehicle->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - vehicle->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); + vehicle->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); vehicle->setFaction(getFaction()); SetCharm(vehicle); // charm @@ -19432,7 +19437,7 @@ void Player::ExitVehicle(Vehicle *vehicle) { vehicle->SetCharmerGUID(0); vehicle->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - vehicle->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); + vehicle->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); vehicle->setFaction((GetTeam() == ALLIANCE) ? vehicle->GetCreatureInfo()->faction_A : vehicle->GetCreatureInfo()->faction_H); SetCharm(NULL); @@ -19454,9 +19459,7 @@ void Player::ExitVehicle(Vehicle *vehicle) data << uint32(0); // fall time GetSession()->SendPacket(&data); - data.Initialize(SMSG_PET_SPELLS, 8); - data << uint64(0); - GetSession()->SendPacket(&data); + RemovePetActionBar(); // maybe called at dummy aura remove? // CastSpell(this, 45472, true); // Parachute diff --git a/src/game/Player.h b/src/game/Player.h index f7a656f81..efe279b1c 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1442,6 +1442,8 @@ class MANGOS_DLL_SPEC Player : public Unit void PetSpellInitialize(); void CharmSpellInitialize(); void PossessSpellInitialize(); + void RemovePetActionBar(); + bool HasSpell(uint32 spell) const; bool HasActiveSpell(uint32 spell) const; // show in spellbook TrainerSpellState GetTrainerSpellState(TrainerSpell const* trainer_spell) const; diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index c6e7e6372..4cd2aaf68 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -4383,8 +4383,38 @@ SpellCastResult Spell::CheckCast(bool strict) break; } case SPELL_AURA_MOD_POSSESS: + { + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return SPELL_FAILED_UNKNOWN; + + if(m_targets.getUnitTarget() == m_caster) + return SPELL_FAILED_BAD_TARGETS; + + if(m_caster->GetPetGUID()) + return SPELL_FAILED_ALREADY_HAVE_SUMMON; + + if(m_caster->GetCharmGUID()) + return SPELL_FAILED_ALREADY_HAVE_CHARM; + + if(m_caster->GetCharmerGUID()) + return SPELL_FAILED_CHARMED; + + if(!m_targets.getUnitTarget()) + return SPELL_FAILED_BAD_IMPLICIT_TARGETS; + + if(m_targets.getUnitTarget()->GetCharmerGUID()) + return SPELL_FAILED_CHARMED; + + if(int32(m_targets.getUnitTarget()->getLevel()) > CalculateDamage(i,m_targets.getUnitTarget())) + return SPELL_FAILED_HIGHLEVEL; + + break; + } case SPELL_AURA_MOD_CHARM: { + if(m_targets.getUnitTarget() == m_caster) + return SPELL_FAILED_BAD_TARGETS; + if(m_caster->GetPetGUID()) return SPELL_FAILED_ALREADY_HAVE_SUMMON; @@ -4407,6 +4437,9 @@ SpellCastResult Spell::CheckCast(bool strict) } case SPELL_AURA_MOD_POSSESS_PET: { + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return SPELL_FAILED_UNKNOWN; + if(m_caster->GetCharmGUID()) return SPELL_FAILED_ALREADY_HAVE_CHARM; diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 45b98cda2..df1cd5497 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -3074,33 +3074,33 @@ void Aura::HandleModPossess(bool apply, bool Real) if(!Real) return; - if(m_target->getLevel() > m_modifier.m_amount) - return; - // not possess yourself if(GetCasterGUID() == m_target->GetGUID()) return; Unit* caster = GetCaster(); - if(!caster) + if(!caster || caster->GetTypeId() != TYPEID_PLAYER) return; + Player* p_caster = (Player*)caster; + + if( apply ) { - m_target->SetCharmerGUID(GetCasterGUID()); - m_target->setFaction(caster->getFaction()); + m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); - caster->SetCharm(m_target); + m_target->SetCharmerGUID(p_caster->GetGUID()); + m_target->setFaction(p_caster->getFaction()); - if(caster->GetTypeId() == TYPEID_PLAYER) - { - ((Player*)caster)->SetFarSightGUID(m_target->GetGUID()); - ((Player*)caster)->SetClientControl(m_target, 1); - ((Player*)caster)->SetMover(m_target); - } + p_caster->SetCharm(m_target); + + p_caster->SetFarSightGUID(m_target->GetGUID()); + p_caster->SetClientControl(m_target, 1); + p_caster->SetMover(m_target); m_target->CombatStop(); m_target->DeleteThreatList(); + if(m_target->GetTypeId() == TYPEID_UNIT) { m_target->StopMoving(); @@ -3115,13 +3115,14 @@ void Aura::HandleModPossess(bool apply, bool Real) if(CharmInfo *charmInfo = m_target->InitCharmInfo(m_target)) charmInfo->InitPossessCreateSpells(); - if(caster->GetTypeId() == TYPEID_PLAYER) - ((Player*)caster)->PossessSpellInitialize(); + p_caster->PossessSpellInitialize(); } else { + m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); + m_target->SetCharmerGUID(0); - caster->InterruptSpell(CURRENT_CHANNELED_SPELL); // the spell is not automatically canceled when interrupted, do it now + p_caster->InterruptSpell(CURRENT_CHANNELED_SPELL); // the spell is not automatically canceled when interrupted, do it now if(m_target->GetTypeId() == TYPEID_PLAYER) { @@ -3134,18 +3135,13 @@ void Aura::HandleModPossess(bool apply, bool Real) m_target->setFaction(cinfo->faction_A); } - caster->SetCharm(NULL); + p_caster->SetCharm(NULL); - if(caster->GetTypeId() == TYPEID_PLAYER) - { - ((Player*)caster)->SetFarSightGUID(0); - ((Player*)caster)->SetClientControl(m_target, 0); - ((Player*)caster)->SetMover(NULL); + p_caster->SetFarSightGUID(0); + p_caster->SetClientControl(m_target, 0); + p_caster->SetMover(NULL); - WorldPacket data(SMSG_PET_SPELLS, 8); - data << uint64(0); - ((Player*)caster)->GetSession()->SendPacket(&data); - } + p_caster->RemovePetActionBar(); if(m_target->GetTypeId() == TYPEID_UNIT) { @@ -3170,14 +3166,16 @@ void Aura::HandleModPossessPet(bool apply, bool Real) if(!pet || pet != m_target) return; - if(apply) - pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); - else - pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); + Player* p_caster = (Player*)caster; - ((Player*)caster)->SetFarSightGUID(apply ? pet->GetGUID() : 0); - ((Player*)caster)->SetCharm(apply ? pet : NULL); - ((Player*)caster)->SetClientControl(pet, apply ? 1 : 0); + if(apply) + pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); + else + pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); + + p_caster->SetFarSightGUID(apply ? pet->GetGUID() : 0); + p_caster->SetCharm(apply ? pet : NULL); + p_caster->SetClientControl(pet, apply ? 1 : 0); ((Player*)caster)->SetMover(apply ? pet : NULL); if(apply) @@ -3217,100 +3215,92 @@ void Aura::HandleModCharm(bool apply, bool Real) if(!caster) return; - if(int32(m_target->getLevel()) <= m_modifier.m_amount) + if( apply ) { - if( apply ) + m_target->SetCharmerGUID(GetCasterGUID()); + m_target->setFaction(caster->getFaction()); + m_target->CastStop(m_target == caster ? GetId() : 0); + caster->SetCharm(m_target); + + m_target->CombatStop(); + m_target->DeleteThreatList(); + + if(m_target->GetTypeId() == TYPEID_UNIT) { - m_target->SetCharmerGUID(GetCasterGUID()); - m_target->setFaction(caster->getFaction()); - m_target->CastStop(m_target == caster ? GetId() : 0); - caster->SetCharm(m_target); + ((Creature*)m_target)->AIM_Initialize(); + CharmInfo *charmInfo = m_target->InitCharmInfo(m_target); + charmInfo->InitCharmCreateSpells(); + charmInfo->SetReactState( REACT_DEFENSIVE ); - m_target->CombatStop(); - m_target->DeleteThreatList(); - - if(m_target->GetTypeId() == TYPEID_UNIT) - { - ((Creature*)m_target)->AIM_Initialize(); - CharmInfo *charmInfo = m_target->InitCharmInfo(m_target); - charmInfo->InitCharmCreateSpells(); - charmInfo->SetReactState( REACT_DEFENSIVE ); - - if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK) - { - CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo(); - if(cinfo && cinfo->type == CREATURE_TYPE_DEMON) - { - //does not appear to have relevance. Why code added initially? See note below at !apply - //to prevent client crash - //m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048); - //just to enable stat window - charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true); - //if charmed two demons the same session, the 2nd gets the 1st one's name - m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); - } - } - } - - if(caster->GetTypeId() == TYPEID_PLAYER) - { - ((Player*)caster)->CharmSpellInitialize(); - } - } - else - { - m_target->SetCharmerGUID(0); - - if(m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->setFactionForRace(m_target->getRace()); - else + if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK) { CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo(); - - // restore faction - if(((Creature*)m_target)->isPet()) + if(cinfo && cinfo->type == CREATURE_TYPE_DEMON) { - if(Unit* owner = m_target->GetOwner()) - m_target->setFaction(owner->getFaction()); - else if(cinfo) - m_target->setFaction(cinfo->faction_A); + //does not appear to have relevance. Why code added initially? See note below at !apply + //to prevent client crash + //m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048); + //just to enable stat window + charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true); + //if charmed two demons the same session, the 2nd gets the 1st one's name + m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); } - else if(cinfo) // normal creature + } + } + + if(caster->GetTypeId() == TYPEID_PLAYER) + ((Player*)caster)->CharmSpellInitialize(); + } + else + { + m_target->SetCharmerGUID(0); + + if(m_target->GetTypeId() == TYPEID_PLAYER) + ((Player*)m_target)->setFactionForRace(m_target->getRace()); + else + { + CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo(); + + // restore faction + if(((Creature*)m_target)->isPet()) + { + if(Unit* owner = m_target->GetOwner()) + m_target->setFaction(owner->getFaction()); + else if(cinfo) m_target->setFaction(cinfo->faction_A); - - // restore UNIT_FIELD_BYTES_0 - if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON) - { - //does not appear to have relevance. Why code added initially? Class, gender, powertype should be same. - //db field removed and replaced with better way to set class, restore using this if problems - /*CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon(); - if(cainfo && cainfo->bytes0 != 0) - m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0); - else - m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);*/ - - if(m_target->GetCharmInfo()) - m_target->GetCharmInfo()->SetPetNumber(0, true); - else - sLog.outError("Aura::HandleModCharm: target (GUID: %u TypeId: %u) has a charm aura but no charm info!", m_target->GetGUIDLow(), m_target->GetTypeId()); - } } + else if(cinfo) // normal creature + m_target->setFaction(cinfo->faction_A); - caster->SetCharm(NULL); - - if(caster->GetTypeId() == TYPEID_PLAYER) + // restore UNIT_FIELD_BYTES_0 + if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON) { - WorldPacket data(SMSG_PET_SPELLS, 8); - data << uint64(0); - ((Player*)caster)->GetSession()->SendPacket(&data); - } - if(m_target->GetTypeId() == TYPEID_UNIT) - { - ((Creature*)m_target)->AIM_Initialize(); - if (((Creature*)m_target)->AI()) - ((Creature*)m_target)->AI()->AttackedBy(caster); + //does not appear to have relevance. Why code added initially? Class, gender, powertype should be same. + //db field removed and replaced with better way to set class, restore using this if problems + /*CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon(); + if(cainfo && cainfo->bytes0 != 0) + m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0); + else + m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);*/ + + if(m_target->GetCharmInfo()) + m_target->GetCharmInfo()->SetPetNumber(0, true); + else + sLog.outError("Aura::HandleModCharm: target (GUID: %u TypeId: %u) has a charm aura but no charm info!", m_target->GetGUIDLow(), m_target->GetTypeId()); } } + + caster->SetCharm(NULL); + + if(caster->GetTypeId() == TYPEID_PLAYER) + ((Player*)caster)->RemovePetActionBar(); + + if(m_target->GetTypeId() == TYPEID_UNIT) + { + ((Creature*)m_target)->AIM_Initialize(); + if (((Creature*)m_target)->AI()) + ((Creature*)m_target)->AI()->AttackedBy(caster); + } } } diff --git a/src/game/Unit.h b/src/game/Unit.h index ace8b0293..8762723a7 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -514,7 +514,7 @@ enum UnitFlags UNIT_FLAG_DISARMED = 0x00200000, // 3.0.3, disable melee spells casting..., "Required melee weapon" added to melee spells tooltip. UNIT_FLAG_CONFUSED = 0x00400000, UNIT_FLAG_FLEEING = 0x00800000, - UNIT_FLAG_UNK_24 = 0x01000000, // used in spell Eyes of the Beast for pet... + UNIT_FLAG_PLAYER_CONTROLLED= 0x01000000, // used in spell Eyes of the Beast for pet... let attack by controlled creature UNIT_FLAG_NOT_SELECTABLE = 0x02000000, UNIT_FLAG_SKINNABLE = 0x04000000, UNIT_FLAG_MOUNT = 0x08000000, diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 1faff6528..ff2b133ff 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8146" + #define REVISION_NR "8147" #endif // __REVISION_NR_H__