[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) : Pet::Pet(PetType type) :
Creature(), m_removed(false), m_petType(type), m_happinessTimer(7500), m_duration(0), m_resetTalentsCost(0), 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_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_isPet = true;
m_name = "Pet"; m_name = "Pet";
@ -1948,3 +1948,20 @@ void Pet::SynchronizeLevelWithOwner()
break; 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 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 enum HappinessState
{ {
UNHAPPY = 1, UNHAPPY = 1,
@ -182,6 +193,9 @@ class Pet : public Creature
bool CanTakeMoreActiveSpells(uint32 SpellIconID); bool CanTakeMoreActiveSpells(uint32 SpellIconID);
void ToggleAutocast(uint32 spellid, bool apply); void ToggleAutocast(uint32 spellid, bool apply);
void ApplyModeFlags(PetModeFlags mode, bool apply);
PetModeFlags GetModeFlags() const { return m_petModeFlags; }
bool HasSpell(uint32 spell) const; bool HasSpell(uint32 spell) const;
void LearnPetPassives(); void LearnPetPassives();
@ -242,6 +256,8 @@ class Pet : public Creature
DeclinedName *m_declinedname; DeclinedName *m_declinedname;
private: private:
PetModeFlags m_petModeFlags;
void SaveToDB(uint32, uint8) // overwrited of Creature::SaveToDB - don't must be called void SaveToDB(uint32, uint8) // overwrited of Creature::SaveToDB - don't must be called
{ {
assert(false); 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) void PetAI::MoveInLineOfSight(Unit *u)
{ {
if( !m_creature->getVictim() && m_creature->GetCharmInfo() && if (m_creature->getVictim())
m_creature->GetCharmInfo()->HasReactState(REACT_AGGRESSIVE) && return;
u->isTargetableForAttack() && m_creature->IsHostileTo( u ) &&
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)) u->isInAccessablePlaceFor(m_creature))
{ {
float attackRadius = m_creature->GetAttackDistance(u); float attackRadius = m_creature->GetAttackDistance(u);
@ -139,7 +146,7 @@ void PetAI::UpdateAI(const uint32 diff)
else else
m_updateAlliesTimer -= diff; 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(); _stopAttack();
// i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc. // 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 // used also for charmed creature
Unit* pet= ObjectAccessor::GetUnit(*_player, guid1); 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)) ); 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)) ); sLog.outError( "Pet %u not exist.", uint32(GUID_LOPART(guid1)) );
return; 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() ); sLog.outError("HandlePetAction.Pet %u isn't pet of player %s.", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName() );
return; return;
} }
if(!pet->isAlive()) if (!pet->isAlive())
return; return;
if(pet->GetTypeId() == TYPEID_PLAYER && !(flag == ACT_COMMAND && spellid == COMMAND_ATTACK)) if (pet->GetTypeId() == TYPEID_PLAYER)
return; {
// 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(); CharmInfo *charmInfo = pet->GetCharmInfo();
if(!charmInfo) if(!charmInfo)
@ -316,6 +326,10 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data )
return; return;
} }
// pet can have action bar disabled
if(pet->isPet() && ((Pet*)pet)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS)
return;
CharmInfo *charmInfo = pet->GetCharmInfo(); CharmInfo *charmInfo = pet->GetCharmInfo();
if(!charmInfo) if(!charmInfo)
{ {

View file

@ -17095,6 +17095,18 @@ void Player::PetSpellInitialize()
GetSession()->SendPacket(&data); 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() void Player::PossessSpellInitialize()
{ {
Unit* charm = GetCharm(); Unit* charm = GetCharm();

View file

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

View file

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

View file

@ -8382,6 +8382,9 @@ void Unit::SetPet(Pet* pet)
{ {
SetPetGUID(pet ? pet->GetGUID() : 0); SetPetGUID(pet ? pet->GetGUID() : 0);
if(pet && GetTypeId() == TYPEID_PLAYER)
((Player*)this)->SendPetGUIDs();
// FIXME: hack, speed must be set only at follow // FIXME: hack, speed must be set only at follow
if(pet && GetTypeId()==TYPEID_PLAYER) if(pet && GetTypeId()==TYPEID_PLAYER)
for(int i = 0; i < MAX_MOVE_TYPE; ++i) 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)) 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; return;
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOUNTING); RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOUNTING);
@ -9877,9 +9880,27 @@ void Unit::Mount(uint32 mount)
SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT ); SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT );
// unsummon pet if (GetTypeId() == TYPEID_PLAYER)
if(GetTypeId() == TYPEID_PLAYER) {
((Player*)this)->UnsummonPetTemporaryIfAny(); // 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() 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 // 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) // (it could probably happen when logging in after a previous crash)
if(GetTypeId() == TYPEID_PLAYER) 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) 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 ); } bool IsMounted() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT ); }
uint32 GetMountID() const { return GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID); } uint32 GetMountID() const { return GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID); }
void Mount(uint32 mount); void Mount(uint32 mount, uint32 spellId = 0);
void Unmount(); void Unmount();
uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; } uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; }

View file

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