mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-02-28 22:45:55 +00:00
fix(Core/Hunter): Stable Master, exotics pets management, tame validations. (#2100)
This commit is contained in:
@@ -149,6 +149,11 @@ struct CreatureTemplate
|
||||
return SKILL_SKINNING; // normal case
|
||||
}
|
||||
|
||||
bool IsExotic() const
|
||||
{
|
||||
return (type_flags & CREATURE_TYPE_FLAG_EXOTIC_PET) != 0;
|
||||
}
|
||||
|
||||
bool IsTameable(bool exotic) const
|
||||
{
|
||||
if (type != CREATURE_TYPE_BEAST || family == 0 || (type_flags & CREATURE_TYPE_FLAG_TAMEABLE_PET) == 0)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-GPL2
|
||||
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
@@ -97,6 +97,55 @@ void Pet::RemoveFromWorld()
|
||||
}
|
||||
}
|
||||
|
||||
SpellCastResult Pet::TryLoadFromDB(Player* owner, bool current /*= false*/, PetType mandatoryPetType /*= MAX_PET_TYPE*/)
|
||||
{
|
||||
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_PET_BY_ENTRY_AND_SLOT);
|
||||
stmt->setUInt32(0, owner->GetGUIDLow());
|
||||
stmt->setUInt8(1, uint8(current ? PET_SAVE_AS_CURRENT : PET_SAVE_NOT_IN_SLOT));
|
||||
|
||||
PreparedQueryResult result = CharacterDatabase.AsyncQuery(stmt);
|
||||
|
||||
if (!result)
|
||||
return SPELL_FAILED_NO_PET;
|
||||
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
uint32 petentry = fields[1].GetUInt32();
|
||||
uint32 savedHealth = fields[10].GetUInt32();
|
||||
uint32 summon_spell_id = fields[15].GetUInt32();
|
||||
auto petType = PetType(fields[16].GetUInt8());
|
||||
|
||||
// update for case of current pet "slot = 0"
|
||||
if (!petentry)
|
||||
return SPELL_FAILED_NO_PET;
|
||||
|
||||
CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(petentry);
|
||||
if (!creatureInfo)
|
||||
{
|
||||
sLog->outError("Pet entry %u does not exist but used at pet load (owner: %s).", petentry, owner->GetName().c_str());
|
||||
return SPELL_FAILED_NO_PET;
|
||||
}
|
||||
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(summon_spell_id);
|
||||
|
||||
bool isTemporarySummoned = spellInfo && spellInfo->GetDuration() > 0;
|
||||
|
||||
// check temporary summoned pets like mage water elemental
|
||||
if (current && isTemporarySummoned)
|
||||
return SPELL_FAILED_NO_PET;
|
||||
|
||||
if (!savedHealth)
|
||||
{
|
||||
owner->ToPlayer()->SendTameFailure(PET_TAME_DEAD);
|
||||
return SPELL_FAILED_TARGETS_DEAD;
|
||||
}
|
||||
|
||||
if (mandatoryPetType != MAX_PET_TYPE && petType != mandatoryPetType)
|
||||
return SPELL_FAILED_BAD_TARGETS;
|
||||
|
||||
return SPELL_CAST_OK;
|
||||
}
|
||||
|
||||
bool Pet::LoadPetFromDB(Player* owner, uint8 asynchLoadType, uint32 petentry, uint32 petnumber, bool current, AsynchPetSummon* info)
|
||||
{
|
||||
// we are loading pet at that moment
|
||||
|
||||
@@ -63,6 +63,7 @@ class Pet : public Guardian
|
||||
bool CreateBaseAtCreature(Creature* creature);
|
||||
bool CreateBaseAtCreatureInfo(CreatureTemplate const* cinfo, Unit* owner);
|
||||
bool CreateBaseAtTamed(CreatureTemplate const* cinfo, Map* map, uint32 phaseMask);
|
||||
static SpellCastResult TryLoadFromDB(Player* owner, bool current = false, PetType mandatoryPetType = MAX_PET_TYPE);
|
||||
static bool LoadPetFromDB(Player* owner, uint8 asynchLoadType, uint32 petentry = 0, uint32 petnumber = 0, bool current = false, AsynchPetSummon* info = NULL);
|
||||
bool isBeingLoaded() const { return m_loading;}
|
||||
void SavePetToDB(PetSaveMode mode, bool logout);
|
||||
|
||||
@@ -20815,7 +20815,10 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent)
|
||||
{
|
||||
// xinef: dont save dead pet as current, save him not in slot
|
||||
if (!pet->IsAlive() && mode == PET_SAVE_AS_CURRENT && pet->getPetType() == HUNTER_PET)
|
||||
{
|
||||
mode = PET_SAVE_NOT_IN_SLOT;
|
||||
m_temporaryUnsummonedPetNumber = 0;
|
||||
}
|
||||
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||
sLog->outDebug(LOG_FILTER_PETS, "RemovePet %u, %u, %u", pet->GetEntry(), mode, returnreagent);
|
||||
@@ -27579,3 +27582,19 @@ void Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy
|
||||
AsynchPetSummon* asynchPetInfo = new AsynchPetSummon(entry, pos, petType, duration, createdBySpell, casterGUID);
|
||||
Pet::LoadPetFromDB(this, asynchLoadType, entry, 0, false, asynchPetInfo);
|
||||
}
|
||||
|
||||
bool Player::IsPetDismissed()
|
||||
{
|
||||
/*
|
||||
* Check PET_SAVE_NOT_IN_SLOT means the pet is dismissed. If someone ever
|
||||
* Changes the slot flag, they will break this validation.
|
||||
*/
|
||||
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_PET_BY_ENTRY_AND_SLOT);
|
||||
stmt->setUInt32(0, GetGUIDLow());
|
||||
stmt->setUInt8(1, uint8(PET_SAVE_NOT_IN_SLOT));
|
||||
|
||||
if (PreparedQueryResult result = CharacterDatabase.AsyncQuery(stmt))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1214,6 +1214,7 @@ class Player : public Unit, public GridObject<Player>
|
||||
uint32 GetInnTriggerId() const { return _innTriggerId; }
|
||||
|
||||
Pet* GetPet() const;
|
||||
bool IsPetDismissed();
|
||||
void SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, uint32 despwtime, uint32 createdBySpell, uint64 casterGUID, uint8 asynchLoadType);
|
||||
void RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent = false);
|
||||
uint32 GetPhaseMaskForSpawn() const; // used for proper set phase for DB at GM-mode creature/GO spawn
|
||||
|
||||
@@ -18484,6 +18484,13 @@ void Unit::NearTeleportTo(float x, float y, float z, float orientation, bool cas
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::SendTameFailure(uint8 result)
|
||||
{
|
||||
WorldPacket data(SMSG_PET_TAME_FAILURE, 1);
|
||||
data << uint8(result);
|
||||
ToPlayer()->SendDirectMessage(&data);
|
||||
}
|
||||
|
||||
void Unit::SendTeleportPacket(Position& pos)
|
||||
{
|
||||
Position oldPos = { GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation() };
|
||||
|
||||
@@ -1761,6 +1761,7 @@ class Unit : public WorldObject
|
||||
void SendSpellDamageImmune(Unit* target, uint32 spellId);
|
||||
|
||||
void NearTeleportTo(float x, float y, float z, float orientation, bool casting = false, bool vehicleTeleport = false, bool withPet = false, bool removeTransport = false);
|
||||
void SendTameFailure(uint8 result);
|
||||
void SendTeleportPacket(Position& pos);
|
||||
virtual bool UpdatePosition(float x, float y, float z, float ang, bool teleport = false);
|
||||
// returns true if unit's position really changed
|
||||
|
||||
Reference in New Issue
Block a user