mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 13:37:05 +00:00
[7971] Implement support exotic pets limtations related to hunter telent 53270.
Note: before this commit hunters can tame exotic pets like any other.
After patch like not propertly contriolled pets will auto-dismiss at loading
if talent not learned.
This commit is contained in:
parent
01d93fa10d
commit
5ac6b2f34b
10 changed files with 106 additions and 39 deletions
|
|
@ -159,7 +159,7 @@ void WorldSession::HandleCharEnumOpcode( WorldPacket & /*recv_data*/ )
|
||||||
// ------- Query Without Declined Names --------
|
// ------- Query Without Declined Names --------
|
||||||
// 0 1 2 3 4 5 6 7 8
|
// 0 1 2 3 4 5 6 7 8
|
||||||
"SELECT characters.guid, characters.data, characters.name, characters.position_x, characters.position_y, characters.position_z, characters.map, characters.totaltime, characters.leveltime, "
|
"SELECT characters.guid, characters.data, characters.name, characters.position_x, characters.position_y, characters.position_z, characters.map, characters.totaltime, characters.leveltime, "
|
||||||
// 9 10 11 12 13 14
|
// 9 10 11 12 13 14
|
||||||
"characters.at_login, characters.zone, character_pet.entry, character_pet.modelid, character_pet.level, guild_member.guildid "
|
"characters.at_login, characters.zone, character_pet.entry, character_pet.modelid, character_pet.level, guild_member.guildid "
|
||||||
"FROM characters LEFT JOIN character_pet ON characters.guid=character_pet.owner AND character_pet.slot='%u' "
|
"FROM characters LEFT JOIN character_pet ON characters.guid=character_pet.owner AND character_pet.slot='%u' "
|
||||||
"LEFT JOIN guild_member ON characters.guid = guild_member.guid "
|
"LEFT JOIN guild_member ON characters.guid = guild_member.guid "
|
||||||
|
|
@ -168,7 +168,7 @@ void WorldSession::HandleCharEnumOpcode( WorldPacket & /*recv_data*/ )
|
||||||
// --------- Query With Declined Names ---------
|
// --------- Query With Declined Names ---------
|
||||||
// 0 1 2 3 4 5 6 7 8
|
// 0 1 2 3 4 5 6 7 8
|
||||||
"SELECT characters.guid, characters.data, characters.name, characters.position_x, characters.position_y, characters.position_z, characters.map, characters.totaltime, characters.leveltime, "
|
"SELECT characters.guid, characters.data, characters.name, characters.position_x, characters.position_y, characters.position_z, characters.map, characters.totaltime, characters.leveltime, "
|
||||||
// 9 10 11 12 13 14 15
|
// 9 10 11 12 13 14 15
|
||||||
"characters.at_login, characters.zone, character_pet.entry, character_pet.modelid, character_pet.level, guild_member.guildid, character_declinedname.genitive "
|
"characters.at_login, characters.zone, character_pet.entry, character_pet.modelid, character_pet.level, guild_member.guildid, character_declinedname.genitive "
|
||||||
"FROM characters LEFT JOIN character_pet ON characters.guid = character_pet.owner AND character_pet.slot='%u' "
|
"FROM characters LEFT JOIN character_pet ON characters.guid = character_pet.owner AND character_pet.slot='%u' "
|
||||||
"LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid "
|
"LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid "
|
||||||
|
|
|
||||||
|
|
@ -235,9 +235,13 @@ struct CreatureInfo
|
||||||
return SKILL_SKINNING; // normal case
|
return SKILL_SKINNING; // normal case
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isTameable() const
|
bool isTameable(bool exotic) const
|
||||||
{
|
{
|
||||||
return type == CREATURE_TYPE_BEAST && family != 0 && (type_flags & CREATURE_TYPEFLAGS_TAMEABLE);
|
if(type != CREATURE_TYPE_BEAST || family == 0 || (type_flags & CREATURE_TYPEFLAGS_TAMEABLE)==0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// if can tame exotic then can tame any temable
|
||||||
|
return exotic || (type_flags & CREATURE_TYPEFLAGS_EXOTIC)==0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1786,7 +1786,7 @@ bool ChatHandler::HandleNpcTameCommand(const char* /*args*/)
|
||||||
|
|
||||||
CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo();
|
CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo();
|
||||||
|
|
||||||
if (!cInfo->isTameable ())
|
if (!cInfo->isTameable (player->CanTameExoticPets()))
|
||||||
{
|
{
|
||||||
PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
|
PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
|
||||||
SetSentErrorMessage (true);
|
SetSentErrorMessage (true);
|
||||||
|
|
|
||||||
|
|
@ -582,11 +582,10 @@ void WorldSession::HandleStablePet( WorldPacket & recv_data )
|
||||||
|
|
||||||
Pet *pet = _player->GetPet();
|
Pet *pet = _player->GetPet();
|
||||||
|
|
||||||
WorldPacket data(SMSG_STABLE_RESULT, 200); // guess size
|
|
||||||
|
|
||||||
// can't place in stable dead pet
|
// can't place in stable dead pet
|
||||||
if(!pet||!pet->isAlive()||pet->getPetType()!=HUNTER_PET)
|
if(!pet||!pet->isAlive()||pet->getPetType()!=HUNTER_PET)
|
||||||
{
|
{
|
||||||
|
WorldPacket data(SMSG_STABLE_RESULT, 1);
|
||||||
data << uint8(0x06);
|
data << uint8(0x06);
|
||||||
SendPacket(&data);
|
SendPacket(&data);
|
||||||
return;
|
return;
|
||||||
|
|
@ -615,6 +614,7 @@ void WorldSession::HandleStablePet( WorldPacket & recv_data )
|
||||||
delete result;
|
delete result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WorldPacket data(SMSG_STABLE_RESULT, 1);
|
||||||
if( free_slot > 0 && free_slot <= GetPlayer()->m_stableSlots)
|
if( free_slot > 0 && free_slot <= GetPlayer()->m_stableSlots)
|
||||||
{
|
{
|
||||||
_player->RemovePet(pet,PetSaveMode(free_slot));
|
_player->RemovePet(pet,PetSaveMode(free_slot));
|
||||||
|
|
@ -647,11 +647,40 @@ void WorldSession::HandleUnstablePet( WorldPacket & recv_data )
|
||||||
if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
|
if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
|
||||||
GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
|
GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
|
||||||
|
|
||||||
WorldPacket data(SMSG_STABLE_RESULT, 200); // guess size
|
uint32 creature_id = 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot >='%u' AND slot <= '%u'",
|
||||||
|
_player->GetGUIDLow(),petnumber,PET_SAVE_FIRST_STABLE_SLOT,PET_SAVE_LAST_STABLE_SLOT);
|
||||||
|
if(result)
|
||||||
|
{
|
||||||
|
Field *fields = result->Fetch();
|
||||||
|
creature_id = fields[0].GetUInt32();
|
||||||
|
delete result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!creature_id)
|
||||||
|
{
|
||||||
|
WorldPacket data(SMSG_STABLE_RESULT, 1);
|
||||||
|
data << uint8(0x06);
|
||||||
|
SendPacket(&data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CreatureInfo const* creatureInfo = objmgr.GetCreatureTemplate(creature_id);
|
||||||
|
if(!creatureInfo || !creatureInfo->isTameable(_player->CanTameExoticPets()))
|
||||||
|
{
|
||||||
|
WorldPacket data(SMSG_STABLE_RESULT, 1);
|
||||||
|
data << uint8(0x06);
|
||||||
|
SendPacket(&data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Pet* pet = _player->GetPet();
|
Pet* pet = _player->GetPet();
|
||||||
if(pet && pet->isAlive())
|
if(pet && pet->isAlive())
|
||||||
{
|
{
|
||||||
|
WorldPacket data(SMSG_STABLE_RESULT, 1);
|
||||||
data << uint8(0x06);
|
data << uint8(0x06);
|
||||||
SendPacket(&data);
|
SendPacket(&data);
|
||||||
return;
|
return;
|
||||||
|
|
@ -661,28 +690,19 @@ void WorldSession::HandleUnstablePet( WorldPacket & recv_data )
|
||||||
if(pet)
|
if(pet)
|
||||||
_player->RemovePet(pet,PET_SAVE_AS_DELETED);
|
_player->RemovePet(pet,PET_SAVE_AS_DELETED);
|
||||||
|
|
||||||
Pet *newpet = NULL;
|
Pet *newpet = new Pet(HUNTER_PET);
|
||||||
|
if(!newpet->LoadPetFromDB(_player,creature_id,petnumber))
|
||||||
QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot >='%u' AND slot <= '%u'",
|
|
||||||
_player->GetGUIDLow(),petnumber,PET_SAVE_FIRST_STABLE_SLOT,PET_SAVE_LAST_STABLE_SLOT);
|
|
||||||
if(result)
|
|
||||||
{
|
{
|
||||||
Field *fields = result->Fetch();
|
delete newpet;
|
||||||
uint32 petentry = fields[0].GetUInt32();
|
newpet = NULL;
|
||||||
|
WorldPacket data(SMSG_STABLE_RESULT, 1);
|
||||||
newpet = new Pet(HUNTER_PET);
|
data << uint8(0x06);
|
||||||
if(!newpet->LoadPetFromDB(_player,petentry,petnumber))
|
SendPacket(&data);
|
||||||
{
|
return;
|
||||||
delete newpet;
|
|
||||||
newpet = NULL;
|
|
||||||
}
|
|
||||||
delete result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(newpet)
|
WorldPacket data(SMSG_STABLE_RESULT, 1);
|
||||||
data << uint8(0x09);
|
data << uint8(0x09);
|
||||||
else
|
|
||||||
data << uint8(0x06);
|
|
||||||
SendPacket(&data);
|
SendPacket(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -767,16 +787,33 @@ void WorldSession::HandleStableSwapPet( WorldPacket & recv_data )
|
||||||
|
|
||||||
Field *fields = result->Fetch();
|
Field *fields = result->Fetch();
|
||||||
|
|
||||||
uint32 slot = fields[0].GetUInt32();
|
uint32 slot = fields[0].GetUInt32();
|
||||||
uint32 petentry = fields[1].GetUInt32();
|
uint32 creature_id = fields[1].GetUInt32();
|
||||||
delete result;
|
delete result;
|
||||||
|
|
||||||
|
if(!creature_id)
|
||||||
|
{
|
||||||
|
WorldPacket data(SMSG_STABLE_RESULT, 1);
|
||||||
|
data << uint8(0x06);
|
||||||
|
SendPacket(&data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CreatureInfo const* creatureInfo = objmgr.GetCreatureTemplate(creature_id);
|
||||||
|
if(!creatureInfo || !creatureInfo->isTameable(_player->CanTameExoticPets()))
|
||||||
|
{
|
||||||
|
WorldPacket data(SMSG_STABLE_RESULT, 1);
|
||||||
|
data << uint8(0x06);
|
||||||
|
SendPacket(&data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// move alive pet to slot or delete dead pet
|
// move alive pet to slot or delete dead pet
|
||||||
_player->RemovePet(pet,pet->isAlive() ? PetSaveMode(slot) : PET_SAVE_AS_DELETED);
|
_player->RemovePet(pet,pet->isAlive() ? PetSaveMode(slot) : PET_SAVE_AS_DELETED);
|
||||||
|
|
||||||
// summon unstabled pet
|
// summon unstabled pet
|
||||||
Pet *newpet = new Pet;
|
Pet *newpet = new Pet;
|
||||||
if(!newpet->LoadPetFromDB(_player,petentry,pet_number))
|
if(!newpet->LoadPetFromDB(_player,creature_id,pet_number))
|
||||||
{
|
{
|
||||||
delete newpet;
|
delete newpet;
|
||||||
data << uint8(0x06);
|
data << uint8(0x06);
|
||||||
|
|
|
||||||
|
|
@ -134,8 +134,19 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 pet_number = fields[0].GetUInt32();
|
PetType pet_type = PetType(fields[18].GetUInt8());
|
||||||
|
if(pet_type==HUNTER_PET)
|
||||||
|
{
|
||||||
|
CreatureInfo const* creatureInfo = objmgr.GetCreatureTemplate(petentry);
|
||||||
|
if(!creatureInfo || !creatureInfo->isTameable(owner->CanTameExoticPets()))
|
||||||
|
{
|
||||||
|
delete result;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 pet_number = fields[0].GetUInt32();
|
||||||
|
|
||||||
if (current && owner->IsPetNeedBeTemporaryUnsummoned())
|
if (current && owner->IsPetNeedBeTemporaryUnsummoned())
|
||||||
{
|
{
|
||||||
owner->SetTemporaryUnsummonedPetNumber(pet_number);
|
owner->SetTemporaryUnsummonedPetNumber(pet_number);
|
||||||
|
|
@ -164,7 +175,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
setPetType(PetType(fields[18].GetUInt8()));
|
setPetType(pet_type);
|
||||||
setFaction(owner->getFaction());
|
setFaction(owner->getFaction());
|
||||||
SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id);
|
SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3480,6 +3480,14 @@ bool Player::resetTalents(bool no_cost)
|
||||||
|
|
||||||
//FIXME: remove pet before or after unlearn spells? for now after unlearn to allow removing of talent related, pet affecting auras
|
//FIXME: remove pet before or after unlearn spells? for now after unlearn to allow removing of talent related, pet affecting auras
|
||||||
RemovePet(NULL,PET_SAVE_NOT_IN_SLOT, true);
|
RemovePet(NULL,PET_SAVE_NOT_IN_SLOT, true);
|
||||||
|
/* when prev line will dropped use next line
|
||||||
|
if(Pet* pet = GetPet())
|
||||||
|
{
|
||||||
|
if(pet->getPetType()==HUNTER_PET && !pet->GetCreatureInfo()->isTameable(CanTameExoticPets()))
|
||||||
|
RemovePet(NULL,PET_SAVE_NOT_IN_SLOT, true);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
if(m_canTitanGrip)
|
if(m_canTitanGrip)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1729,6 +1729,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||||
void SetCanDualWield(bool value) { m_canDualWield = value; }
|
void SetCanDualWield(bool value) { m_canDualWield = value; }
|
||||||
bool CanTitanGrip() const { return m_canTitanGrip ; }
|
bool CanTitanGrip() const { return m_canTitanGrip ; }
|
||||||
void SetCanTitanGrip(bool value) { m_canTitanGrip = value; }
|
void SetCanTitanGrip(bool value) { m_canTitanGrip = value; }
|
||||||
|
bool CanTameExoticPets() const { return isGameMaster() || HasAuraType(SPELL_AURA_ALLOW_TAME_PET_TYPE); }
|
||||||
|
|
||||||
void SetRegularAttackTime();
|
void SetRegularAttackTime();
|
||||||
void SetBaseModValue(BaseModGroup modGroup, BaseModType modType, float value) { m_auraBaseMod[modGroup][modType] = value; }
|
void SetBaseModValue(BaseModGroup modGroup, BaseModType modType, float value) { m_auraBaseMod[modGroup][modType] = value; }
|
||||||
|
|
|
||||||
|
|
@ -1818,10 +1818,11 @@ enum CreatureFamily
|
||||||
|
|
||||||
enum CreatureTypeFlags
|
enum CreatureTypeFlags
|
||||||
{
|
{
|
||||||
CREATURE_TYPEFLAGS_TAMEABLE = 0x0001,
|
CREATURE_TYPEFLAGS_TAMEABLE = 0x00001,
|
||||||
CREATURE_TYPEFLAGS_HERBLOOT = 0x0100,
|
CREATURE_TYPEFLAGS_HERBLOOT = 0x00100,
|
||||||
CREATURE_TYPEFLAGS_MININGLOOT = 0x0200,
|
CREATURE_TYPEFLAGS_MININGLOOT = 0x00200,
|
||||||
CREATURE_TYPEFLAGS_ENGINEERLOOT = 0x8000
|
CREATURE_TYPEFLAGS_ENGINEERLOOT = 0x08000,
|
||||||
|
CREATURE_TYPEFLAGS_EXOTIC = 0x10000
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CreatureEliteType
|
enum CreatureEliteType
|
||||||
|
|
|
||||||
|
|
@ -4111,14 +4111,19 @@ SpellCastResult Spell::CheckCast(bool strict)
|
||||||
}
|
}
|
||||||
case SPELL_EFFECT_TAMECREATURE:
|
case SPELL_EFFECT_TAMECREATURE:
|
||||||
{
|
{
|
||||||
|
if (m_caster->GetTypeId() != TYPEID_PLAYER)
|
||||||
|
return SPELL_FAILED_BAD_TARGETS;
|
||||||
|
|
||||||
if (!m_targets.getUnitTarget() || m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER)
|
if (!m_targets.getUnitTarget() || m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER)
|
||||||
return SPELL_FAILED_BAD_IMPLICIT_TARGETS;
|
return SPELL_FAILED_BAD_IMPLICIT_TARGETS;
|
||||||
|
|
||||||
if (m_targets.getUnitTarget()->getLevel() > m_caster->getLevel())
|
Creature* target = (Creature*)m_targets.getUnitTarget();
|
||||||
|
|
||||||
|
if (target->getLevel() > m_caster->getLevel())
|
||||||
return SPELL_FAILED_HIGHLEVEL;
|
return SPELL_FAILED_HIGHLEVEL;
|
||||||
|
|
||||||
// use SMSG_PET_TAME_FAILURE?
|
// use SMSG_PET_TAME_FAILURE?
|
||||||
if (!((Creature*)m_targets.getUnitTarget())->GetCreatureInfo()->isTameable ())
|
if (!target->GetCreatureInfo()->isTameable (((Player*)m_caster)->CanTameExoticPets()))
|
||||||
return SPELL_FAILED_BAD_TARGETS;
|
return SPELL_FAILED_BAD_TARGETS;
|
||||||
|
|
||||||
if(m_caster->GetPetGUID())
|
if(m_caster->GetPetGUID())
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "7970"
|
#define REVISION_NR "7971"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue