mirror of
https://github.com/mangosfour/server.git
synced 2025-12-14 16:37:01 +00:00
[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:
parent
7d0a830bd4
commit
9c98bd92e2
10 changed files with 112 additions and 19 deletions
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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; }
|
||||||
|
|
|
||||||
|
|
@ -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__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue