[Patch] The ability to swap pet spells

Update 2014-03-13: Posted the patch even though it’s on an old revision, it should work on HEAD for people to play around with.

[SIZE=12px]Previous Updates:[/SIZE]

[ul][li]None yet /emoticons/default_smile.png[/li]
[/ul]

[SIZE=12px]Known Issues:[/SIZE]

[ul]
[li]Existing pets may retain an old spell or two while still learning the replacement spell. This may correct itself when the pet levels.[/li][/ul]

Details:

This patch allows for swapping pet spells (such as claw, bite, rake, etc.) with other spells. The replacement spells are applied at levelup / creature load and can easily be reverted simply by removing the entries from the pet_spell_override table.

Note: I have not tested this using a replacement spell that costs mana instead of focus. It has only been tested by swapping spells from another pet.

[SIZE=12px]Patch (in the spoiler):[/SIZE]

[SIZE=12px]NOTE: Don’t forget to apply the SQL file that is created in “srcsqlupdatescharacters”[/SIZE]

From 42e3d09f2ef651a6b7fdb1a17b95ded44a868a45 Mon Sep 17 00:00:00 2001
From: MrSmite [email protected]
Date: Wed, 12 Mar 2014 18:18:01 -0400
Subject: [PATCH] Allow swapping pet ability spells with another spell


…/characters/characters_pet_spell_override.sql | 12 ++++++++++++
src/server/game/Entities/Pet/Pet.cpp | 19 +++++++++++++±----
src/server/game/Spells/SpellMgr.cpp | 19 +++++++++++++++++±
…/Database/Implementation/CharacterDatabase.cpp | 1 +
…/Database/Implementation/CharacterDatabase.h | 1 +
5 files changed, 46 insertions(+), 6 deletions(-)
create mode 100644 sql/updates/characters/characters_pet_spell_override.sql

diff --git a/sql/updates/characters/characters_pet_spell_override.sql b/sql/updates/characters/characters_pet_spell_override.sql
new file mode 100644
index 0000000…1e3461d
— /dev/null
+++ b/sql/updates/characters/characters_pet_spell_override.sql
@@ -0,0 +1,12 @@
±- Apply this to your CHARACTER database
±-
±- Creates a table that allows for replacing spells from one pet family with those
±- of another at pet levelup.
±- Must also apply “petAbilityOverride.patch”
±-
+drop table if exists pet_spell_override;
+CREATE TABLE pet_spell_override (

  • spellId_old mediumint(8) unsigned NOT NULL DEFAULT ‘0’ COMMENT ‘The existing spell (SkillLineAbility.dbc - assuming first dbc column is 0, this value is from column 2, use column 1 for family lookup)’,
  • spellId_new mediumint(8) unsigned NOT NULL DEFAULT ‘0’ COMMENT ‘The new spell (SkillLineAbility.dbc - assuming first dbc column is 0, this value is from column 2, use column 1 for family lookup)’,
  • comment text
    +) ENGINE=InnoDB DEFAULT CHARSET=latin1
    No newline at end of file
    diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
    index b019cd7…bd4f833 100644
    — a/src/server/game/Entities/Pet/Pet.cpp
    +++ b/src/server/game/Entities/Pet/Pet.cpp
    @@ -1563,12 +1563,21 @@ void Pet::InitLevelupSpellsForLevel()
    if (!spellInfo)
    continue;
  •        // will called first if level down
    
  •        if (spellInfo->SpellLevel > level)
    
  •            unlearnSpell(spellInfo->Id, true);
    
  •        // will called if level up
    
  •        // Check if this spell has been replaced by a different one
    
  •        PreparedStatement* spellCheck = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_SPELL_OVERRIDE);
    
  •        spellCheck->setUInt32(0, spellInfo->Id);
    
  •        PreparedQueryResult result = CharacterDatabase.Query(spellCheck);
    
  •        if (!result)
    
  •        {
    
  •            // Spell not being replaced, handle as normal
    
  •            if (spellInfo->SpellLevel > level)
    
  •                unlearnSpell(spellInfo->Id, true); // level down
    
  •            else
    
  •                learnSpell(spellInfo->Id); // level up
    
  •        }
           else
    
  •            learnSpell(spellInfo->Id);
    
  •            unlearnSpell(spellInfo->Id, false); // pet shouldn't have this spell, it has been replaced
       }
    

    }
    }
    diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
    index 994050b…3827645 100644
    — a/src/server/game/Spells/SpellMgr.cpp
    +++ b/src/server/game/Spells/SpellMgr.cpp
    @@ -2353,11 +2353,28 @@ void SpellMgr::LoadPetLevelupSpellMap()
    if (!spell->SpellLevel)
    continue;

  •            // Check if this spell should be replaced
    
  •            SpellInfo const* spellNew = NULL;
    
  •            PreparedStatement* spellOverride = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_SPELL_OVERRIDE);
    
  •            spellOverride->setUInt32(0, skillLine->spellId);
    
  •            PreparedQueryResult result = CharacterDatabase.Query(spellOverride);
    
  •            if (result)
    
  •            {
    
  •                Field* fields = result->Fetch();
    
  •                spellNew = GetSpellInfo(fields[0].GetUInt32());
    
  •            }
    
  •            PetLevelupSpellSet& spellSet = mPetLevelupSpellMap[creatureFamily->ID];
               if (spellSet.empty())
                   ++family_count;
    
  •            spellSet.insert(PetLevelupSpellSet::value_type(spell->SpellLevel, spell->Id));
    
  •            // Replace the spell if necessary
    
  •            if (spellNew)
    
  •                spellSet.insert(PetLevelupSpellSet::value_type(spellNew->SpellLevel, spellNew->Id));
    
  •            else
    
  •                spellSet.insert(PetLevelupSpellSet::value_type(spell->SpellLevel, spell->Id));
    
  •            ++count;
           }
       }
    

diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index da99d6c…796ee98 100644
— a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -572,6 +572,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_PET_ENTRY, “SELECT entry FROM character_pet WHERE owner = ? AND id = ? AND slot >= ? AND slot <= ?”, CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_PET_SLOT_BY_ID, “SELECT slot, entry FROM character_pet WHERE owner = ? AND id = ?”, CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_PET_SPELL_LIST, “SELECT DISTINCT pet_spell.spell FROM pet_spell, character_pet WHERE character_pet.owner = ? AND character_pet.id = pet_spell.guid AND character_pet.id <> ?”, CONNECTION_SYNCH);

  • PrepareStatement(CHAR_SEL_PET_SPELL_OVERRIDE, “SELECT DISTINCT spellId_new FROM pet_spell_override WHERE spellId_old = ?”, CONNECTION_SYNCH);
    PrepareStatement(CHAR_SEL_CHAR_PET, “SELECT id FROM character_pet WHERE owner = ? AND id <> ?”, CONNECTION_SYNCH);
    PrepareStatement(CHAR_SEL_CHAR_PETS, “SELECT id FROM character_pet WHERE owner = ?”, CONNECTION_SYNCH);
    PrepareStatement(CHAR_DEL_CHAR_PET_DECLINEDNAME_BY_OWNER, “DELETE FROM character_pet_declinedname WHERE owner = ?”, CONNECTION_ASYNC);
    diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h
    index aa47fb5…34f829f 100644
    — a/src/server/shared/Database/Implementation/CharacterDatabase.h
    +++ b/src/server/shared/Database/Implementation/CharacterDatabase.h
    @@ -510,6 +510,7 @@ enum CharacterDatabaseStatements
    CHAR_SEL_PET_ENTRY,
    CHAR_SEL_PET_SLOT_BY_ID,
    CHAR_SEL_PET_SPELL_LIST,
  • CHAR_SEL_PET_SPELL_OVERRIDE,
    CHAR_SEL_CHAR_PET,
    CHAR_SEL_CHAR_PETS,
    CHAR_SEL_CHAR_PET_BY_ENTRY,

    1.7.11.msysgit.1

Usage example: Let’s say you want your cat to learn Furious Howl instead of Rake

[ul]
[li]You would look in SkillLineAbility.dbc and write down the IDs for all the ranks of both spells[/li]note: you could also use http://wotlk.openwow.com (wowhead is missing old spells)

You would then enter the data in the new table pet_spell_override as spellId_old and spellId_new
For example, Rake (Rank 1) is 59881 and Furious Howl (Rank 1)

> spellId_old spellId_new comment
59881 24604 Swap Rake (Rank 1) with Furious Howl (Rank 1)

[/ul]