diff options
Diffstat (limited to 'src/game/Pet.cpp')
| -rw-r--r-- | src/game/Pet.cpp | 191 | 
1 files changed, 173 insertions, 18 deletions
diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 6c77138c38c..e5fd0d037e4 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -55,6 +55,7 @@ Pet::Pet(PetType type) : Creature()      m_resetTalentsCost = 0;      m_resetTalentsTime = 0; +    m_usedTalentCount = 0;      m_auraUpdateMask = 0; @@ -725,6 +726,7 @@ void Pet::GivePetLevel(uint32 level)          return;      InitStatsForLevel(level); +    InitTalentForLevel();  }  bool Pet::CreateBaseAtCreature(Creature* creature) @@ -1325,22 +1327,42 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, PetSpell      else          newspell->active = active; -    uint32 chainstart = spellmgr.GetFirstSpellInChain(spell_id); - -    for (PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) +    // talent: unlearn all other talent ranks (high and low) +    if(TalentSpellPos const* talentPos = GetTalentSpellPos(spell_id))      { -        if(itr->second->state == PETSPELL_REMOVED) continue; +        if(TalentEntry const *talentInfo = sTalentStore.LookupEntry( talentPos->talent_id )) +        { +            for(int i=0; i <5; ++i) +            { +                // skip learning spell and no rank spell case +                uint32 rankSpellId = talentInfo->RankID[i]; +                if(!rankSpellId || rankSpellId==spell_id) +                    continue; -        if(spellmgr.GetFirstSpellInChain(itr->first) == chainstart) +                // skip unknown ranks +                if(!HasSpell(rankSpellId)) +                    continue; +                removeSpell(rankSpellId); +            } +        } +    } +    else if(uint32 chainstart = spellmgr.GetFirstSpellInChain(spell_id)) +    { +        for (PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)          { -            newspell->active = itr->second->active; +            if(itr->second->state == PETSPELL_REMOVED) continue; + +            if(spellmgr.GetFirstSpellInChain(itr->first) == chainstart) +            { +                newspell->active = itr->second->active; -            if(newspell->active == ACT_ENABLED) -                ToggleAutocast(itr->first, false); +                if(newspell->active == ACT_ENABLED) +                    ToggleAutocast(itr->first, false); -            oldspell_id = itr->first; -            unlearnSpell(itr->first); -            break; +                oldspell_id = itr->first; +                unlearnSpell(itr->first); +                break; +            }          }      } @@ -1354,6 +1376,15 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, PetSpell      if(newspell->active == ACT_ENABLED)          ToggleAutocast(spell_id, true); +    uint32 talentCost = GetTalentSpellCost(spell_id); +    if (talentCost) +    { +        int32 free_points = GetMaxTalentPointsForLevel(getLevel()); +        m_usedTalentCount+=talentCost; +        // update free talent points +        free_points-=m_usedTalentCount; +        SetFreeTalentPoints(free_points > 0 ? free_points : 0); +    }      return true;  } @@ -1363,19 +1394,17 @@ bool Pet::learnSpell(uint16 spell_id)      if (!addSpell(spell_id))          return false; -    if(GetOwner()->GetTypeId() == TYPEID_PLAYER) +    Unit* owner = GetOwner(); +    if(owner && owner->GetTypeId() == TYPEID_PLAYER)      {          if(!m_loading)          {              WorldPacket data(SMSG_PET_LEARNED_SPELL, 2);              data << uint16(spell_id); -            ((Player*)GetOwner())->GetSession()->SendPacket(&data); +            ((Player*)owner)->GetSession()->SendPacket(&data);          } -    } - -    Unit* owner = GetOwner(); -    if(owner->GetTypeId() == TYPEID_PLAYER)          ((Player*)owner)->PetSpellInitialize(); +    }      return true;  } @@ -1433,6 +1462,18 @@ bool Pet::removeSpell(uint16 spell_id)      RemoveAurasDueToSpell(spell_id); +    uint32 talentCost = GetTalentSpellCost(spell_id); +    if (talentCost > 0) +    { +        if (m_usedTalentCount > talentCost) +            m_usedTalentCount-=talentCost; +        else +            m_usedTalentCount = 0; +        // update free talent points +        int32 free_points = GetMaxTalentPointsForLevel(getLevel()) - m_usedTalentCount; +        SetFreeTalentPoints(free_points > 0 ? free_points : 0); +    } +      return true;  } @@ -1512,6 +1553,110 @@ void Pet::CheckLearning(uint32 spellid)      }  } +bool Pet::resetTalents(bool no_cost) +{ +    Unit *owner = GetOwner(); +    if (!owner || owner->GetTypeId()!=TYPEID_PLAYER) +        return false; + +    CreatureInfo const * ci = GetCreatureInfo(); +    if(!ci) +        return false; +    // Check pet talent type +    CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(ci->family); +    if(!pet_family || pet_family->petTalentType < 0) +        return false; + +    Player *player = (Player *)owner; + +    uint32 level = getLevel(); +    uint32 talentPointsForLevel = GetMaxTalentPointsForLevel(level); + +    if (m_usedTalentCount == 0) +    { +        SetFreeTalentPoints(talentPointsForLevel); +        return false; +    } + +    uint32 cost = 0; + +    if(!no_cost) +    { +        cost = resetTalentsCost(); + +        if (player->GetMoney() < cost) +        { +            player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0); +            return false; +        } +    } + +    for (unsigned int i = 0; i < sTalentStore.GetNumRows(); i++) +    { +        TalentEntry const *talentInfo = sTalentStore.LookupEntry(i); + +        if (!talentInfo) continue; + +        TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentInfo->TalentTab ); + +        if(!talentTabInfo) +            continue; + +        // unlearn only talents for pets family talent type +        if(!((1 << pet_family->petTalentType) & talentTabInfo->petTalentMask)) +            continue; + +        for (int j = 0; j < 5; j++) +        { +            for(PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end();) +            { +                if(itr->second->state == PETSPELL_REMOVED) +                { +                    ++itr; +                    continue; +                } +                // remove learned spells (all ranks) +                uint32 itrFirstId = spellmgr.GetFirstSpellInChain(itr->first); + +                // unlearn if first rank is talent or learned by talent +                if (itrFirstId == talentInfo->RankID[j] || spellmgr.IsSpellLearnToSpell(talentInfo->RankID[j],itrFirstId)) +                { +                    removeSpell(itr->first); +                    itr = m_spells.begin(); +                    continue; +                } +                else +                    ++itr; +            } +        } +    } + +    SetFreeTalentPoints(talentPointsForLevel); + +    if(!no_cost) +    { +        player->ModifyMoney(-(int32)cost); + +        m_resetTalentsCost = cost; +        m_resetTalentsTime = time(NULL); +    } +    player->PetSpellInitialize(); +    return true; +} + +void Pet::InitTalentForLevel() +{ +    uint32 level = getLevel(); +    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) +    { +        // Remove all talent points +        resetTalents(true); +    } +    SetFreeTalentPoints(talentPointsForLevel - m_usedTalentCount); +} +  uint32 Pet::resetTalentsCost() const  {      uint32 days = (sWorld.GetGameTime() - m_resetTalentsTime)/DAY; @@ -1530,6 +1675,15 @@ uint32 Pet::resetTalentsCost() const          return (m_resetTalentsCost + 1*GOLD > 10*GOLD ? 10*GOLD : m_resetTalentsCost + 1*GOLD);  } +uint8 Pet::GetMaxTalentPointsForLevel(uint32 level) +{ +    uint8 points = (level >= 20) ? ((level - 16) / 4) : 0; +    // Mod points from owner SPELL_AURA_MOD_PET_TALENT_POINTS +    if (Unit *owner = GetOwner()) +        points+=owner->GetTotalAuraModifier(SPELL_AURA_MOD_PET_TALENT_POINTS); +    return points; +} +  void Pet::ToggleAutocast(uint32 spellid, bool apply)  {      if(IsPassiveSpell(spellid)) @@ -1594,7 +1748,8 @@ bool Pet::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 pet_number)  bool Pet::HasSpell(uint32 spell) const  { -    return (m_spells.find(spell) != m_spells.end()); +    PetSpellMap::const_iterator itr = m_spells.find((uint16)spell); +    return (itr != m_spells.end() && itr->second->state != PETSPELL_REMOVED );  }  // Get all passive spells in our skill line  | 
