Core/Players: Pet talents can be reset at a pet trainer for free, original idea by rsa

This commit is contained in:
tobmaps
2011-05-31 05:47:17 +07:00
parent 7f573dbcb8
commit 600cc16c94
7 changed files with 30 additions and 75 deletions
+4 -4
View File
@@ -2610,15 +2610,15 @@ bool ChatHandler::HandleResetTalentsCommand(const char * args)
Creature* creature = getSelectedCreature();
if (!*args && creature && creature->isPet())
{
Unit *owner = creature->GetOwner();
if (owner && owner->GetTypeId() == TYPEID_PLAYER && ((Pet *)creature)->IsPermanentPetFor(owner->ToPlayer()))
Unit* owner = creature->GetOwner();
if (owner && owner->GetTypeId() == TYPEID_PLAYER && creature->ToPet()->IsPermanentPetFor(owner->ToPlayer()))
{
((Pet *)creature)->resetTalents(true);
creature->ToPet()->resetTalents();
owner->ToPlayer()->SendTalentsInfoData(true);
ChatHandler(owner->ToPlayer()).SendSysMessage(LANG_RESET_PET_TALENTS);
if (!m_session || m_session->GetPlayer() != owner->ToPlayer())
PSendSysMessage(LANG_RESET_PET_TALENTS_ONLINE, GetNameLink(owner->ToPlayer()).c_str());
PSendSysMessage(LANG_RESET_PET_TALENTS_ONLINE, GetNameLink(owner->ToPlayer()).c_str());
}
return true;
}
+21 -63
View File
@@ -42,9 +42,9 @@ char const* petTypeSuffix[MAX_PET_TYPE] =
#define PET_XP_FACTOR 0.05f
Pet::Pet(Player *owner, PetType type) : Guardian(NULL, owner),
m_resetTalentsCost(0), m_resetTalentsTime(0), m_usedTalentCount(0),
m_removed(false), m_owner(owner), m_happinessTimer(7500), m_petType(type),
m_duration(0), m_auraRaidUpdateMask(0), m_loading(false), m_declinedname(NULL)
m_usedTalentCount(0), m_removed(false), m_owner(owner),
m_happinessTimer(7500), m_petType(type), m_duration(0),
m_auraRaidUpdateMask(0), m_loading(false), m_declinedname(NULL)
{
m_unitTypeMask |= UNIT_MASK_PET;
if (type == HUNTER_PET)
@@ -110,25 +110,25 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petentry, uint32 petnumber, bool c
QueryResult result;
if (petnumber)
// known petnumber entry 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType "
// known petnumber entry 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType "
"FROM character_pet WHERE owner = '%u' AND id = '%u'",
ownerid, petnumber);
else if (current)
// current pet (slot 0) 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType "
// current pet (slot 0) 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType "
"FROM character_pet WHERE owner = '%u' AND slot = '%u'",
ownerid, PET_SAVE_AS_CURRENT);
else if (petentry)
// known petentry entry (unique for summoned pet, but non unique for hunter pet (only from current or not stabled pets)
// 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType "
// 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType "
"FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '%u' OR slot > '%u') ",
ownerid, petentry, PET_SAVE_AS_CURRENT, PET_SAVE_LAST_STABLE_SLOT);
else
// any current or other non-stabled pet (for hunter "call pet")
// 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType "
// 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType "
"FROM character_pet WHERE owner = '%u' AND (slot = '%u' OR slot > '%u') ",
ownerid, PET_SAVE_AS_CURRENT, PET_SAVE_LAST_STABLE_SLOT);
@@ -145,7 +145,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petentry, uint32 petnumber, bool c
if (!petentry)
return false;
uint32 summon_spell_id = fields[17].GetUInt32();
uint32 summon_spell_id = fields[15].GetUInt32();
SpellEntry const* spellInfo = sSpellStore.LookupEntry(summon_spell_id);
bool is_temporary_summoned = spellInfo && GetSpellDuration(spellInfo) > 0;
@@ -154,7 +154,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petentry, uint32 petnumber, bool c
if (current && is_temporary_summoned)
return false;
PetType pet_type = PetType(fields[18].GetUInt8());
PetType pet_type = PetType(fields[16].GetUInt8());
if (pet_type == HUNTER_PET)
{
CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(petentry);
@@ -208,14 +208,14 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petentry, uint32 petnumber, bool c
switch (getPetType())
{
case SUMMON_PET:
petlevel=owner->getLevel();
petlevel = owner->getLevel();
SetUInt32Value(UNIT_FIELD_BYTES_0, 0x800); //class=mage
SetUInt32Value(UNIT_FIELD_BYTES_0, 0x800); // class = mage
SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
// this enables popup window (pet dismiss, cancel)
break;
case HUNTER_PET:
SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); //class=warrior, gender=none, power=focus
SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); // class = warrior, gender = none, power = focus
SetSheath(SHEATH_STATE_MELEE);
SetByteFlag(UNIT_FIELD_BYTES_2, 2, fields[9].GetBool() ? UNIT_CAN_BE_ABANDONED : UNIT_CAN_BE_RENAMED | UNIT_CAN_BE_ABANDONED);
@@ -261,7 +261,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petentry, uint32 petnumber, bool c
// 0=current
// 1..MAX_PET_STABLES in stable slot
// PET_SAVE_NOT_IN_SLOT(100) = not stable slot (summoning))
if (fields[7].GetUInt8() != 0)
if (fields[7].GetUInt8())
{
SQLTransaction trans = CharacterDatabase.BeginTransaction();
trans->PAppend("UPDATE character_pet SET slot = '%u' WHERE owner = '%u' AND slot = '%u' AND id <> '%u'",
@@ -289,8 +289,6 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petentry, uint32 petnumber, bool c
owner->SetMinion(this, true);
map->Add(this->ToCreature());
m_resetTalentsCost = fields[15].GetUInt32();
m_resetTalentsTime = time_t(fields[16].GetUInt32());
InitTalentForLevel(); // set original talents points before spell loading
uint32 timediff = uint32(time(NULL) - fields[14].GetUInt32());
@@ -410,7 +408,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
owner, PET_SAVE_AS_CURRENT, PET_SAVE_LAST_STABLE_SLOT);
// save pet
std::ostringstream ss;
ss << "INSERT INTO character_pet (id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType) "
ss << "INSERT INTO character_pet (id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType) "
<< "VALUES ("
<< m_charmInfo->GetPetNumber() << ", "
<< GetEntry() << ", "
@@ -434,8 +432,6 @@ void Pet::SavePetToDB(PetSaveMode mode)
ss << "', "
<< time(NULL) << ", "
<< uint32(m_resetTalentsCost) << ", "
<< uint64(m_resetTalentsTime) << ", "
<< GetUInt32Value(UNIT_CREATED_BY_SPELL) << ", "
<< uint32(getPetType()) << ")";
@@ -1566,7 +1562,7 @@ void Pet::InitPetCreateSpells()
CastPetAuras(false);
}
bool Pet::resetTalents(bool no_cost)
bool Pet::resetTalents()
{
Unit *owner = GetOwner();
if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
@@ -1595,19 +1591,6 @@ bool Pet::resetTalents(bool no_cost)
return false;
}
uint32 cost = 0;
if (!no_cost)
{
cost = resetTalentsCost();
if (!player->HasEnoughMoney(cost))
{
player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0);
return false;
}
}
for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i)
{
TalentEntry const *talentInfo = sTalentStore.LookupEntry(i);
@@ -1651,13 +1634,6 @@ bool Pet::resetTalents(bool no_cost)
SetFreeTalentPoints(talentPointsForLevel);
if (!no_cost)
{
player->ModifyMoney(-(int32)cost);
m_resetTalentsCost = cost;
m_resetTalentsTime = time(NULL);
}
if (!m_loading)
player->PetSpellInitialize();
return true;
@@ -1671,7 +1647,7 @@ void Pet::resetTalentsForAllPetsOf(Player* owner, Pet* online_pet /*= NULL*/)
// reset for online
if (online_pet)
online_pet->resetTalents(true);
online_pet->resetTalents();
// now need only reset for offline pets (all pets except online case)
uint32 except_petnumber = online_pet ? online_pet->GetCharmInfo()->GetPetNumber() : 0;
@@ -1746,7 +1722,7 @@ void Pet::InitTalentForLevel()
uint32 talentPointsForLevel = GetMaxTalentPointsForLevel(level);
// Reset talents in case low level (on level down) or wrong points for level (hunter can unlearn TP increase talent)
if (talentPointsForLevel == 0 || m_usedTalentCount > talentPointsForLevel)
resetTalents(true); // Remove all talent points
resetTalents(); // Remove all talent points
SetFreeTalentPoints(talentPointsForLevel - m_usedTalentCount);
@@ -1758,24 +1734,6 @@ void Pet::InitTalentForLevel()
owner->ToPlayer()->SendTalentsInfoData(true);
}
uint32 Pet::resetTalentsCost() const
{
int64 days = int64(sWorld->GetGameTime() - m_resetTalentsTime)/DAY;
// The first time reset costs 10 silver; after 1 day cost is reset to 10 silver
if (m_resetTalentsCost < 10*SILVER || days > 0)
return 10*SILVER;
// then 50 silver
else if (m_resetTalentsCost < 50*SILVER)
return 50*SILVER;
// then 1 gold
else if (m_resetTalentsCost < 1*GOLD)
return 1*GOLD;
// then increasing at a rate of 1 gold; cap 10 gold
else
return (m_resetTalentsCost + 1*GOLD > 10*GOLD ? 10*GOLD : m_resetTalentsCost + 1*GOLD);
}
uint8 Pet::GetMaxTalentPointsForLevel(uint8 level)
{
uint8 points = (level >= 20) ? ((level - 16) / 4) : 0;
+1 -4
View File
@@ -208,17 +208,14 @@ class Pet : public Guardian
void InitPetCreateSpells();
bool resetTalents(bool no_cost = false);
bool resetTalents();
static void resetTalentsForAllPetsOf(Player* owner, Pet* online_pet = NULL);
uint32 resetTalentsCost() const;
void InitTalentForLevel();
uint8 GetMaxTalentPointsForLevel(uint8 level);
uint8 GetFreeTalentPoints() { return GetByteValue(UNIT_FIELD_BYTES_1, 1); }
void SetFreeTalentPoints(uint8 points) { SetByteValue(UNIT_FIELD_BYTES_1, 1, points); }
uint32 m_resetTalentsCost;
time_t m_resetTalentsTime;
uint32 m_usedTalentCount;
const uint64& GetAuraUpdateMaskForRaid() const { return m_auraRaidUpdateMask; }
+1 -1
View File
@@ -778,7 +778,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x2ED*/ { "SMSG_BATTLEGROUND_PLAYER_LEFT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x2EE*/ { "CMSG_BATTLEMASTER_JOIN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlemasterJoinOpcode },
/*0x2EF*/ { "SMSG_ADDON_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x2F0*/ { "CMSG_PET_UNLEARN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL },
/*0x2F0*/ { "CMSG_PET_UNLEARN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x2F1*/ { "SMSG_PET_UNLEARN_CONFIRM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x2F2*/ { "SMSG_PARTY_MEMBER_STATS_FULL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x2F3*/ { "CMSG_PET_SPELL_AUTOCAST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetSpellAutocastOpcode },
-1
View File
@@ -708,7 +708,6 @@ class WorldSession
void HandlePetAbandon(WorldPacket & recv_data);
void HandlePetRename(WorldPacket & recv_data);
void HandlePetCancelAuraOpcode(WorldPacket& recvPacket);
void HandlePetUnlearnOpcode(WorldPacket& recvPacket);
void HandlePetSpellAutocastOpcode(WorldPacket& recvPacket);
void HandlePetCastSpellOpcode(WorldPacket& recvPacket);
void HandlePetLearnTalent(WorldPacket& recvPacket);