[9077] Fixes for pet work in case mounted owner.

* No unsummon temporary pet at non-fly mounting.
* Implement client side disable pet's action bar for mountted owner time

Signed-off-by: VladimirMangos <vladimir@getmangos.com>

* implement server side action disabled case (action bar modify, aggro reaction and autocast)

Signed-off-by: VladimirMangos <vladimir@getmangos.com>
This commit is contained in:
Lightguard 2009-12-28 15:44:02 +03:00 committed by VladimirMangos
parent 7d0a830bd4
commit 9c98bd92e2
10 changed files with 112 additions and 19 deletions

View file

@ -40,7 +40,7 @@ char const* petTypeSuffix[MAX_PET_TYPE] =
Pet::Pet(PetType type) :
Creature(), m_removed(false), m_petType(type), m_happinessTimer(7500), m_duration(0), m_resetTalentsCost(0),
m_bonusdamage(0), m_resetTalentsTime(0), m_usedTalentCount(0), m_auraUpdateMask(0), m_loading(false),
m_declinedname(NULL)
m_declinedname(NULL), m_petModeFlags(PET_MODE_DEFAULT)
{
m_isPet = true;
m_name = "Pet";
@ -1948,3 +1948,20 @@ void Pet::SynchronizeLevelWithOwner()
break;
}
}
void Pet::ApplyModeFlags(PetModeFlags mode, bool apply)
{
if (apply)
m_petModeFlags = PetModeFlags(m_petModeFlags | mode);
else
m_petModeFlags = PetModeFlags(m_petModeFlags & ~mode);
Unit* owner = GetOwner();
if(!owner || owner->GetTypeId()!=TYPEID_PLAYER)
return;
WorldPacket data(SMSG_PET_MODE, 12);
data << uint64(GetGUID());
data << uint32(m_petModeFlags);
((Player*)owner)->GetSession()->SendPacket(&data);
}

View file

@ -46,6 +46,17 @@ enum PetSaveMode
PET_SAVE_NOT_IN_SLOT = 100 // for avoid conflict with stable size grow will use 100
};
// There might be a lot more
enum PetModeFlags
{
PET_MODE_UNKNOWN_0 = 0x0000001,
PET_MODE_UNKNOWN_2 = 0x0000100,
PET_MODE_DISABLE_ACTIONS = 0x8000000,
// autoset in client at summon
PET_MODE_DEFAULT = PET_MODE_UNKNOWN_0 | PET_MODE_UNKNOWN_2,
};
enum HappinessState
{
UNHAPPY = 1,
@ -182,6 +193,9 @@ class Pet : public Creature
bool CanTakeMoreActiveSpells(uint32 SpellIconID);
void ToggleAutocast(uint32 spellid, bool apply);
void ApplyModeFlags(PetModeFlags mode, bool apply);
PetModeFlags GetModeFlags() const { return m_petModeFlags; }
bool HasSpell(uint32 spell) const;
void LearnPetPassives();
@ -242,6 +256,8 @@ class Pet : public Creature
DeclinedName *m_declinedname;
private:
PetModeFlags m_petModeFlags;
void SaveToDB(uint32, uint8) // overwrited of Creature::SaveToDB - don't must be called
{
assert(false);

View file

@ -44,9 +44,16 @@ PetAI::PetAI(Creature *c) : CreatureAI(c), i_tracker(TIME_INTERVAL_LOOK), inComb
void PetAI::MoveInLineOfSight(Unit *u)
{
if( !m_creature->getVictim() && m_creature->GetCharmInfo() &&
m_creature->GetCharmInfo()->HasReactState(REACT_AGGRESSIVE) &&
u->isTargetableForAttack() && m_creature->IsHostileTo( u ) &&
if (m_creature->getVictim())
return;
if (m_creature->isPet() && ((Pet*)m_creature)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS)
return;
if (!m_creature->GetCharmInfo() || !m_creature->GetCharmInfo()->HasReactState(REACT_AGGRESSIVE))
return;
if (u->isTargetableForAttack() && m_creature->IsHostileTo( u ) &&
u->isInAccessablePlaceFor(m_creature))
{
float attackRadius = m_creature->GetAttackDistance(u);
@ -139,7 +146,7 @@ void PetAI::UpdateAI(const uint32 diff)
else
m_updateAlliesTimer -= diff;
if (inCombat && !m_creature->getVictim())
if (inCombat && (!m_creature->getVictim() || m_creature->isPet() && ((Pet*)m_creature)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS))
_stopAttack();
// i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc.

View file

@ -44,23 +44,33 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
// used also for charmed creature
Unit* pet= ObjectAccessor::GetUnit(*_player, guid1);
sLog.outDetail("HandlePetAction.Pet %u flag is %u, spellid is %u, target %u.", uint32(GUID_LOPART(guid1)), uint32(flag), spellid, uint32(GUID_LOPART(guid2)) );
if(!pet)
if (!pet)
{
sLog.outError( "Pet %u not exist.", uint32(GUID_LOPART(guid1)) );
return;
}
if(pet != GetPlayer()->GetPet() && pet != GetPlayer()->GetCharm())
if (pet != GetPlayer()->GetPet() && pet != GetPlayer()->GetCharm())
{
sLog.outError("HandlePetAction.Pet %u isn't pet of player %s.", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName() );
return;
}
if(!pet->isAlive())
if (!pet->isAlive())
return;
if(pet->GetTypeId() == TYPEID_PLAYER && !(flag == ACT_COMMAND && spellid == COMMAND_ATTACK))
return;
if (pet->GetTypeId() == TYPEID_PLAYER)
{
// controller player can only do melee attack
if (!(flag == ACT_COMMAND && spellid == COMMAND_ATTACK))
return;
}
else if (((Creature*)pet)->isPet())
{
// pet can have action bar disabled
if(((Pet*)pet)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS)
return;
}
CharmInfo *charmInfo = pet->GetCharmInfo();
if(!charmInfo)
@ -316,6 +326,10 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data )
return;
}
// pet can have action bar disabled
if(pet->isPet() && ((Pet*)pet)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS)
return;
CharmInfo *charmInfo = pet->GetCharmInfo();
if(!charmInfo)
{

View file

@ -17095,6 +17095,18 @@ void Player::PetSpellInitialize()
GetSession()->SendPacket(&data);
}
void Player::SendPetGUIDs()
{
if(!GetPetGUID())
return;
// Later this function might get modified for multiple guids
WorldPacket data(SMSG_PET_GUIDS, 12);
data << uint32(1); // count
data << uint64(GetPetGUID());
GetSession()->SendPacket(&data);
}
void Player::PossessSpellInitialize()
{
Unit* charm = GetCharm();

View file

@ -1551,6 +1551,7 @@ class MANGOS_DLL_SPEC Player : public Unit
}
void PetSpellInitialize();
void SendPetGUIDs();
void CharmSpellInitialize();
void PossessSpellInitialize();
void RemovePetActionBar();

View file

@ -2817,7 +2817,7 @@ void Aura::HandleAuraMounted(bool apply, bool Real)
if (minfo)
display_id = minfo->modelid;
m_target->Mount(display_id);
m_target->Mount(display_id, m_spellProto->Id);
}
else
{

View file

@ -8382,6 +8382,9 @@ void Unit::SetPet(Pet* pet)
{
SetPetGUID(pet ? pet->GetGUID() : 0);
if(pet && GetTypeId() == TYPEID_PLAYER)
((Player*)this)->SendPetGUIDs();
// FIXME: hack, speed must be set only at follow
if(pet && GetTypeId()==TYPEID_PLAYER)
for(int i = 0; i < MAX_MOVE_TYPE; ++i)
@ -9866,9 +9869,9 @@ float Unit::GetPPMProcChance(uint32 WeaponSpeed, float PPM) const
return WeaponSpeed * PPM / 600.0f; // result is chance in percents (probability = Speed_in_sec * (PPM / 60))
}
void Unit::Mount(uint32 mount)
void Unit::Mount(uint32 mount, uint32 spellId)
{
if(!mount)
if (!mount)
return;
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOUNTING);
@ -9877,9 +9880,27 @@ void Unit::Mount(uint32 mount)
SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT );
// unsummon pet
if(GetTypeId() == TYPEID_PLAYER)
((Player*)this)->UnsummonPetTemporaryIfAny();
if (GetTypeId() == TYPEID_PLAYER)
{
// Called by Taxi system / GM command
if (!spellId)
((Player*)this)->UnsummonPetTemporaryIfAny();
// Called by mount aura
else if (SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId))
{
// Flying case (Unsummon any pet)
if (IsSpellHaveAura(spellInfo, SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED))
((Player*)this)->UnsummonPetTemporaryIfAny();
// Normal case (Unsummon only permanent pet)
else if (Pet* pet = GetPet())
{
if (pet->IsPermanentPetFor((Player*)this))
((Player*)this)->UnsummonPetTemporaryIfAny();
else
pet->ApplyModeFlags(PET_MODE_DISABLE_ACTIONS,true);
}
}
}
}
void Unit::Unmount()
@ -9896,7 +9917,12 @@ void Unit::Unmount()
// this prevents adding a pet to a not created map which would otherwise cause a crash
// (it could probably happen when logging in after a previous crash)
if(GetTypeId() == TYPEID_PLAYER)
((Player*)this)->ResummonPetTemporaryUnSummonedIfAny();
{
if(Pet* pet = GetPet())
pet->ApplyModeFlags(PET_MODE_DISABLE_ACTIONS,false);
else
((Player*)this)->ResummonPetTemporaryUnSummonedIfAny();
}
}
void Unit::SetInCombatWith(Unit* enemy)

View file

@ -1026,7 +1026,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
bool IsMounted() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT ); }
uint32 GetMountID() const { return GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID); }
void Mount(uint32 mount);
void Mount(uint32 mount, uint32 spellId = 0);
void Unmount();
uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; }

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "9076"
#define REVISION_NR "9077"
#endif // __REVISION_NR_H__