diff --git a/sql/characters.sql b/sql/characters.sql index c6f18a193..c20530a05 100644 --- a/sql/characters.sql +++ b/sql/characters.sql @@ -21,7 +21,7 @@ DROP TABLE IF EXISTS `character_db_version`; CREATE TABLE `character_db_version` ( - `required_7802_02_characters_character_achievement_progress` bit(1) default NULL + `required_7887_01_characters_character_pet` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB'; -- @@ -483,7 +483,6 @@ CREATE TABLE `character_pet` ( `resettalents_cost` int(11) unsigned NOT NULL default '0', `resettalents_time` bigint(20) unsigned NOT NULL default '0', `abdata` longtext, - `teachspelldata` longtext, PRIMARY KEY (`id`), KEY `owner` (`owner`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Pet System'; diff --git a/sql/mangos.sql b/sql/mangos.sql index e9874df24..80135d16d 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -23,7 +23,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL, - `required_7855_01_mangos_pools` bit(1) default NULL + `required_7886_01_mangos_petcreateinfo_spell` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -3660,29 +3660,6 @@ INSERT INTO `pet_name_generation` (`word`,`entry`,`half`) VALUES /*!40000 ALTER TABLE `pet_name_generation` ENABLE KEYS */; UNLOCK TABLES; --- --- Table structure for table `petcreateinfo_spell` --- - -DROP TABLE IF EXISTS `petcreateinfo_spell`; -CREATE TABLE `petcreateinfo_spell` ( - `entry` mediumint(8) unsigned NOT NULL default '0', - `Spell1` mediumint(8) unsigned NOT NULL default '0', - `Spell2` mediumint(8) unsigned NOT NULL default '0', - `Spell3` mediumint(8) unsigned NOT NULL default '0', - `Spell4` mediumint(8) unsigned NOT NULL default '0', - PRIMARY KEY (`entry`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Pet Create Spells'; - --- --- Dumping data for table `petcreateinfo_spell` --- - -LOCK TABLES `petcreateinfo_spell` WRITE; -/*!40000 ALTER TABLE `petcreateinfo_spell` DISABLE KEYS */; -/*!40000 ALTER TABLE `petcreateinfo_spell` ENABLE KEYS */; -UNLOCK TABLES; - -- -- Table structure for table `pickpocketing_loot_template` -- diff --git a/sql/updates/7879_01_mangos_spell_proc_event.sql b/sql/updates/7879_01_mangos_spell_proc_event.sql new file mode 100644 index 000000000..0675b1904 --- /dev/null +++ b/sql/updates/7879_01_mangos_spell_proc_event.sql @@ -0,0 +1,7 @@ +ALTER TABLE db_version CHANGE COLUMN required_7855_01_mangos_pools required_7879_01_mangos_spell_proc_event bit; + + +DELETE FROM spell_proc_event WHERE entry IN (31571, 31572); +INSERT INTO spell_proc_event VALUES +(31571, 0x00, 3, 0x00000000, 0x00000022, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0), +(31572, 0x00, 3, 0x00000000, 0x00000022, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0); \ No newline at end of file diff --git a/sql/updates/7884_01_mangos_playercreateinfo_spell.sql b/sql/updates/7884_01_mangos_playercreateinfo_spell.sql new file mode 100644 index 000000000..f16e7e40e --- /dev/null +++ b/sql/updates/7884_01_mangos_playercreateinfo_spell.sql @@ -0,0 +1,3 @@ +ALTER TABLE db_version CHANGE COLUMN required_7879_01_mangos_spell_proc_event required_7884_01_mangos_playercreateinfo_spell bit; + +DELETE FROM playercreateinfo_spell WHERE Spell = '28734'; \ No newline at end of file diff --git a/sql/updates/7884_02_mangos_playercreateinfo_action.sql b/sql/updates/7884_02_mangos_playercreateinfo_action.sql new file mode 100644 index 000000000..c95375213 --- /dev/null +++ b/sql/updates/7884_02_mangos_playercreateinfo_action.sql @@ -0,0 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_7884_01_mangos_playercreateinfo_spell required_7884_02_mangos_playercreateinfo_action bit; + +DELETE FROM playercreateinfo_action WHERE action = '28734'; +UPDATE playercreateinfo_action SET button = '3' WHERE race = '10' AND class IN ('8', '9', '5', '2', '3') AND button = '4'; +UPDATE playercreateinfo_action SET button = '4' WHERE race = '10' AND class = '4' AND button = '5'; diff --git a/sql/updates/7884_03_characters_character_spell.sql b/sql/updates/7884_03_characters_character_spell.sql new file mode 100644 index 000000000..f428689f0 --- /dev/null +++ b/sql/updates/7884_03_characters_character_spell.sql @@ -0,0 +1,3 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_7802_02_characters_character_achievement_progress required_7884_03_characters_character_spell bit; + +DELETE FROM character_spell WHERE spell = '28734'; diff --git a/sql/updates/7884_04_characters_character_aura.sql b/sql/updates/7884_04_characters_character_aura.sql new file mode 100644 index 000000000..cfe19211d --- /dev/null +++ b/sql/updates/7884_04_characters_character_aura.sql @@ -0,0 +1,3 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_7884_03_characters_character_spell required_7884_04_characters_character_aura bit; + +DELETE FROM character_aura WHERE spell = '28734'; diff --git a/sql/updates/7884_05_characters_character_action.sql b/sql/updates/7884_05_characters_character_action.sql new file mode 100644 index 000000000..8aa77cc6f --- /dev/null +++ b/sql/updates/7884_05_characters_character_action.sql @@ -0,0 +1,3 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_7884_04_characters_character_aura required_7884_05_characters_character_action bit; + +DELETE FROM character_action WHERE action = '28734' AND type = '0'; \ No newline at end of file diff --git a/sql/updates/7886_01_mangos_petcreateinfo_spell.sql b/sql/updates/7886_01_mangos_petcreateinfo_spell.sql new file mode 100644 index 000000000..673d1b317 --- /dev/null +++ b/sql/updates/7886_01_mangos_petcreateinfo_spell.sql @@ -0,0 +1,4 @@ +ALTER TABLE db_version CHANGE COLUMN required_7884_02_mangos_playercreateinfo_action required_7886_01_mangos_petcreateinfo_spell bit; + +DROP TABLE IF EXISTS `petcreateinfo_spell`; + diff --git a/sql/updates/7887_01_characters_character_pet.sql b/sql/updates/7887_01_characters_character_pet.sql new file mode 100644 index 000000000..2d61410ec --- /dev/null +++ b/sql/updates/7887_01_characters_character_pet.sql @@ -0,0 +1,4 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_7884_05_characters_character_action required_7887_01_characters_character_pet bit; + +ALTER TABLE `character_pet` + DROP TeachSpelldata; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index d3aab66e3..81cb82750 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -191,6 +191,14 @@ pkgdata_DATA = \ 7850_01_mangos_command.sql \ 7855_01_mangos_pools.sql \ 7867_01_realmd_account.sql \ + 7879_01_mangos_spell_proc_event.sql \ + 7884_01_mangos_playercreateinfo_spell.sql \ + 7884_02_mangos_playercreateinfo_action.sql \ + 7884_03_characters_character_spell.sql \ + 7884_04_characters_character_aura.sql \ + 7884_05_characters_character_action.sql \ + 7886_01_mangos_petcreateinfo_spell.sql \ + 7887_01_characters_character_pet.sql \ README ## Additional files to include when running 'make dist' @@ -362,4 +370,12 @@ EXTRA_DIST = \ 7850_01_mangos_command.sql \ 7855_01_mangos_pools.sql \ 7867_01_realmd_account.sql \ + 7879_01_mangos_spell_proc_event.sql \ + 7884_01_mangos_playercreateinfo_spell.sql \ + 7884_02_mangos_playercreateinfo_action.sql \ + 7884_03_characters_character_spell.sql \ + 7884_04_characters_character_aura.sql \ + 7884_05_characters_character_action.sql \ + 7886_01_mangos_petcreateinfo_spell.sql \ + 7887_01_characters_character_pet.sql \ README diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 8d18a53dc..f01f0b835 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -128,6 +128,12 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) } return true; case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD: + if(player_dead.own_team_flag > 1) + { + sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) have wrong boolean value1 (%u).", + criteria->ID, criteria->requiredType,dataType,player_dead.own_team_flag); + return false; + } return true; case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA: case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA: @@ -193,7 +199,10 @@ bool AchievementCriteriaData::Meets(Player const* source, Unit const* target) co return false; return target->GetHealth()*100 <= health.percent*target->GetMaxHealth(); case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD: - return target && target->GetTypeId() == TYPEID_PLAYER && !target->isAlive() && ((Player*)target)->GetDeathTimer() != 0; + if (!target || target->GetTypeId() != TYPEID_PLAYER || target->isAlive() || ((Player*)target)->GetDeathTimer() == 0) + return false; + // flag set == must be same team, not set == different team + return (((Player*)target)->GetTeam() == source->GetTeam()) == (player_dead.own_team_flag != 0); case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA: return source->HasAura(aura.spell_id,aura.effect_idx); case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA: @@ -961,7 +970,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui break; } case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT: - SetCriteriaProgress(achievementCriteria, GetPlayer()->GetByteValue(PLAYER_BYTES_2, 2)+1); + SetCriteriaProgress(achievementCriteria, GetPlayer()->GetBankBagSlotCount()); break; case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION: { diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h index e4e32e20a..0749beb16 100644 --- a/src/game/AchievementMgr.h +++ b/src/game/AchievementMgr.h @@ -46,7 +46,7 @@ enum AchievementCriteriaDataType ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE = 1, // creature_id 0 ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE = 2, // class_id race_id ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH= 3, // health_percent 0 - ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD = 4, // 0 0 not corpse (not released body) + ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD = 4, // own_team 0 not corpse (not released body), own_team==false if enemy team expected ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA = 5, // spell_id effect_idx ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA = 6, // area id 0 ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA = 7, // spell_id effect_idx @@ -78,6 +78,11 @@ struct AchievementCriteriaData { uint32 percent; } health; + // ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD + struct + { + uint32 own_team_flag; + } player_dead; // ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA // ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA struct diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 83f89826c..819c16104 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -1577,6 +1577,20 @@ bool Creature::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) if (GetCreatureInfo()->MechanicImmuneMask & (1 << (spellInfo->EffectMechanic[index] - 1))) return true; + // Taunt immunity special flag check + if (GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NOT_TAUNTABLE) + { + // Taunt aura apply check + if (spellInfo->Effect[index] == SPELL_EFFECT_APPLY_AURA) + { + if (spellInfo->EffectApplyAuraName[index] == SPELL_AURA_MOD_TAUNT) + return true; + } + // Spell effect taunt check + else if (spellInfo->Effect[index] == SPELL_EFFECT_ATTACK_ME) + return true; + } + return Unit::IsImmunedToSpellEffect(spellInfo, index); } diff --git a/src/game/Creature.h b/src/game/Creature.h index 64fe08399..5f0c54a95 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -142,6 +142,7 @@ enum CreatureFlagsExtra CREATURE_FLAG_EXTRA_NO_CRUSH = 0x00000020, // creature can't do crush attacks CREATURE_FLAG_EXTRA_NO_XP_AT_KILL = 0x00000040, // creature kill not provide XP CREATURE_FLAG_EXTRA_INVISIBLE = 0x00000080, // creature is always invisible for player (mostly trigger creatures) + CREATURE_FLAG_EXTRA_NOT_TAUNTABLE = 0x00000100, // creature is immune to taunt auras and effect attack me }; // GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index edbaf674f..b171f7324 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -705,11 +705,13 @@ struct CreatureFamilyEntry // 27 m_iconFile }; +#define MAX_CREATURE_SPELL_DATA_SLOT 4 + struct CreatureSpellDataEntry { uint32 ID; // 0 m_ID - //uint32 spellId[4]; // 1-4 m_spells[4] - //uint32 availability[4]; // 4-7 m_availability[4] + uint32 spellId[MAX_CREATURE_SPELL_DATA_SLOT]; // 1-4 m_spells[4] + //uint32 availability[MAX_CREATURE_SPELL_DATA_SLOT]; // 4-7 m_availability[4] }; struct CreatureTypeEntry diff --git a/src/game/DBCfmt.h b/src/game/DBCfmt.h index 85c57592c..85fbd4525 100644 --- a/src/game/DBCfmt.h +++ b/src/game/DBCfmt.h @@ -37,7 +37,7 @@ const char ChrRacesEntryfmt[]="nxixiixxixxxxissssssssssssssssxxxxxxxxxxxxxxxxxxx const char CinematicSequencesEntryfmt[]="nxxxxxxxxx"; const char CreatureDisplayInfofmt[]="nxxxfxxxxxxxxxxx"; const char CreatureFamilyfmt[]="nfifiiiiixssssssssssssssssxx"; -const char CreatureSpellDatafmt[]="nxxxxxxxx"; +const char CreatureSpellDatafmt[]="niiiixxxx"; const char CreatureTypefmt[]="nxxxxxxxxxxxxxxxxxx"; const char CurrencyTypesfmt[]="xnxi"; const char DurabilityCostsfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiii"; diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index 435f8f9ee..bbcec610a 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -843,7 +843,7 @@ void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& recvPacket) return; } - uint32 slot = _player->GetByteValue(PLAYER_BYTES_2, 2); + uint32 slot = _player->GetBankBagSlotCount(); // next slot ++slot; @@ -861,7 +861,7 @@ void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& recvPacket) return; _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT, slot); - _player->SetByteValue(PLAYER_BYTES_2, 2, slot); + _player->SetBankBagSlotCount(slot); _player->ModifyMoney(-int32(price)); } diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index e8a669618..371659b0c 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -3563,90 +3563,6 @@ void ObjectMgr::LoadQuestLocales() sLog.outString( ">> Loaded %lu Quest locale strings", (unsigned long)mQuestLocaleMap.size() ); } -void ObjectMgr::LoadPetCreateSpells() -{ - QueryResult *result = WorldDatabase.Query("SELECT entry, Spell1, Spell2, Spell3, Spell4 FROM petcreateinfo_spell"); - if(!result) - { - barGoLink bar( 1 ); - bar.step(); - - sLog.outString(); - sLog.outString( ">> Loaded 0 pet create spells" ); - sLog.outErrorDb("`petcreateinfo_spell` table is empty!"); - return; - } - - uint32 count = 0; - - barGoLink bar( result->GetRowCount() ); - - mPetCreateSpell.clear(); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint32 creature_id = fields[0].GetUInt32(); - - if(!creature_id) - { - sLog.outErrorDb("Creature id %u listed in `petcreateinfo_spell` not exist.",creature_id); - continue; - } - - CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(creature_id); - if(!cInfo) - { - sLog.outErrorDb("Creature id %u listed in `petcreateinfo_spell` not exist.",creature_id); - continue; - } - - PetCreateSpellEntry PetCreateSpell; - - bool have_spell = false; - bool have_spell_db = false; - for(int i = 0; i < 4; i++) - { - PetCreateSpell.spellid[i] = fields[i + 1].GetUInt32(); - - if(!PetCreateSpell.spellid[i]) - continue; - - have_spell_db = true; - - SpellEntry const* i_spell = sSpellStore.LookupEntry(PetCreateSpell.spellid[i]); - if(!i_spell) - { - sLog.outErrorDb("Spell %u listed in `petcreateinfo_spell` does not exist",PetCreateSpell.spellid[i]); - PetCreateSpell.spellid[i] = 0; - continue; - } - - have_spell = true; - } - - if(!have_spell_db) - { - sLog.outErrorDb("Creature %u listed in `petcreateinfo_spell` have only 0 spell data, why it listed?",creature_id); - continue; - } - - if(!have_spell) - continue; - - mPetCreateSpell[creature_id] = PetCreateSpell; - ++count; - } - while (result->NextRow()); - - delete result; - - sLog.outString(); - sLog.outString( ">> Loaded %u pet create spells", count ); -} - void ObjectMgr::LoadScripts(ScriptMapMap& scripts, char const* tablename) { if(sWorld.IsScriptScheduled()) // function don't must be called in time scripts use. diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index c50d1198f..ad767a128 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -196,11 +196,6 @@ struct PointOfInterest std::string icon_name; }; -struct PetCreateSpellEntry -{ - uint32 spellid[4]; -}; - #define WEATHER_SEASONS 4 struct WeatherSeasonChances { @@ -320,8 +315,6 @@ class ObjectMgr typedef UNORDERED_MAP WeatherZoneMap; - typedef UNORDERED_MAP PetCreateSpellMap; - typedef std::vector ScriptNameMap; Player* GetPlayer(const char* name) const { return ObjectAccessor::Instance().FindPlayerByName(name);} @@ -464,14 +457,6 @@ class ObjectMgr return NULL; } - PetCreateSpellEntry const* GetPetCreateSpellEntry(uint32 id) const - { - PetCreateSpellMap::const_iterator itr = mPetCreateSpell.find(id); - if(itr != mPetCreateSpell.end()) - return &itr->second; - return NULL; - } - void LoadGuilds(); void LoadArenaTeams(); void LoadGroups(); @@ -502,7 +487,6 @@ class ObjectMgr bool LoadMangosStrings(DatabaseType& db, char const* table, int32 min_value, int32 max_value); bool LoadMangosStrings() { return LoadMangosStrings(WorldDatabase,"mangos_string",MIN_MANGOS_STRING_ID,MAX_MANGOS_STRING_ID); } void LoadDbScriptStrings(); - void LoadPetCreateSpells(); void LoadCreatureLocales(); void LoadCreatureTemplates(); void LoadCreatures(); @@ -816,8 +800,6 @@ class ObjectMgr WeatherZoneMap mWeatherZoneMap; - PetCreateSpellMap mPetCreateSpell; - //character reserved names typedef std::set ReservedNamesMap; ReservedNamesMap m_ReservedNames; diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index b8c8adf23..b28853183 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -87,25 +87,25 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool 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 19 20 - result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, 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 17 18 19 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, resettalents_cost, resettalents_time, 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 19 20 - result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, 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 17 18 19 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, resettalents_cost, resettalents_time, 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 19 20 - result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType " + // 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, resettalents_cost, resettalents_time, 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 19 20 - result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType " + // 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType " "FROM character_pet WHERE owner = '%u' AND (slot = '%u' OR slot > '%u') ", ownerid,PET_SAVE_AS_CURRENT,PET_SAVE_LAST_STABLE_SLOT); @@ -122,7 +122,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool return false; } - uint32 summon_spell_id = fields[19].GetUInt32(); + uint32 summon_spell_id = fields[18].GetUInt32(); SpellEntry const* spellInfo = sSpellStore.LookupEntry(summon_spell_id); bool is_temporary_summoned = spellInfo && GetSpellDuration(spellInfo) > 0; @@ -164,7 +164,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool return false; } - setPetType(PetType(fields[20].GetUInt8())); + setPetType(PetType(fields[19].GetUInt8())); SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, owner->getFaction()); SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id); @@ -257,27 +257,13 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool ++iter; m_charmInfo->GetActionBarEntry(index)->SpellOrAction = atol((*iter).c_str()); } - - //init teach spells - tokens = StrSplit(fields[15].GetString(), " "); - for (iter = tokens.begin(), index = 0; index < 4; ++iter, ++index) - { - uint32 tmp = atol((*iter).c_str()); - - ++iter; - - if(tmp) - AddTeachSpell(tmp, atol((*iter).c_str())); - else - break; - } } // since last save (in seconds) - uint32 timediff = (time(NULL) - fields[16].GetUInt32()); + uint32 timediff = (time(NULL) - fields[15].GetUInt32()); - m_resetTalentsCost = fields[17].GetUInt32(); - m_resetTalentsTime = fields[18].GetUInt64(); + m_resetTalentsCost = fields[16].GetUInt32(); + m_resetTalentsTime = fields[17].GetUInt64(); delete result; @@ -418,7 +404,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, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType) " + ss << "INSERT INTO character_pet ( id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType) " << "VALUES (" << m_charmInfo->GetPetNumber() << ", " << GetEntry() << ", " @@ -437,17 +423,6 @@ void Pet::SavePetToDB(PetSaveMode mode) for(uint32 i = 0; i < 10; ++i) ss << uint32(m_charmInfo->GetActionBarEntry(i)->Type) << " " << uint32(m_charmInfo->GetActionBarEntry(i)->SpellOrAction) << " "; - ss << "', '"; - - //save spells the pet can teach to it's Master - { - int i = 0; - for(TeachSpellMap::const_iterator itr = m_teachspells.begin(); i < 4 && itr != m_teachspells.end(); ++i, ++itr) - ss << itr->first << " " << itr->second << " "; - for(; i < 4; ++i) - ss << uint32(0) << " " << uint32(0) << " "; - } - ss << "', " << time(NULL) << ", " << uint32(m_resetTalentsCost) << ", " @@ -1437,25 +1412,40 @@ bool Pet::learnSpell(uint32 spell_id) void Pet::InitLevelupSpellsForLevel() { - uint32 family = GetCreatureInfo()->family; - if(!family) - return; - - PetLevelupSpellSet const *levelupSpells = spellmgr.GetPetLevelupSpellList(family); - if(!levelupSpells) - return; - uint32 level = getLevel(); - // PetLevelupSpellSet ordered by levels, process in reversed order - for(PetLevelupSpellSet::const_reverse_iterator itr = levelupSpells->rbegin(); itr != levelupSpells->rend(); ++itr) + if(PetLevelupSpellSet const *levelupSpells = GetCreatureInfo()->family ? spellmgr.GetPetLevelupSpellList(GetCreatureInfo()->family) : NULL) { - // will called first if level down - if(itr->first > level) - unlearnSpell(itr->second,true); // will learn prev rank if any - // will called if level up - else - learnSpell(itr->second); // will unlearn prev rank if any + // PetLevelupSpellSet ordered by levels, process in reversed order + for(PetLevelupSpellSet::const_reverse_iterator itr = levelupSpells->rbegin(); itr != levelupSpells->rend(); ++itr) + { + // will called first if level down + if(itr->first > level) + unlearnSpell(itr->second,true); // will learn prev rank if any + // will called if level up + else + learnSpell(itr->second); // will unlearn prev rank if any + } + } + + int32 petSpellsId = GetCreatureInfo()->PetSpellDataId ? -(int32)GetCreatureInfo()->PetSpellDataId : GetEntry(); + + // default spells (can be not learned if pet level (as owner level decrease result for example) less first possible in normal game) + if(PetDefaultSpellsEntry const *defSpells = spellmgr.GetPetDefaultSpellsEntry(petSpellsId)) + { + for(int i = 0; i < MAX_CREATURE_SPELL_DATA_SLOT; ++i) + { + SpellEntry const* spellEntry = sSpellStore.LookupEntry(defSpells->spellid[i]); + if(!spellEntry) + continue; + + // will called first if level down + if(spellEntry->spellLevel > level) + unlearnSpell(spellEntry->Id,false); + // will called if level up + else + learnSpell(spellEntry->Id); + } } } @@ -1516,14 +1506,16 @@ bool Pet::removeSpell(uint32 spell_id, bool learn_prev) learnSpell(prev_id); } else - { - m_charmInfo->AddSpellToAB(spell_id, 0); + learn_prev = false; + } - // need update action bar for last removed rank - if (Unit* owner = GetOwner()) - if (owner->GetTypeId() == TYPEID_PLAYER) - ((Player*)owner)->PetSpellInitialize(); - } + // if remove last rank or non-ranked then update action bar at server and client if need + if(!learn_prev && m_charmInfo->AddSpellToAB(spell_id, 0)) + { + // need update action bar for last removed rank + if (Unit* owner = GetOwner()) + if (owner->GetTypeId() == TYPEID_PLAYER) + ((Player*)owner)->PetSpellInitialize(); } return true; @@ -1534,65 +1526,11 @@ void Pet::InitPetCreateSpells() m_charmInfo->InitPetActionBar(); m_spells.clear(); - uint32 petspellid; - PetCreateSpellEntry const* CreateSpells = objmgr.GetPetCreateSpellEntry(GetEntry()); - if(CreateSpells) - { - for(uint8 i = 0; i < 4; ++i) - { - if(!CreateSpells->spellid[i]) - break; - - SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(CreateSpells->spellid[i]); - if(!learn_spellproto) - continue; - - if(learn_spellproto->Effect[0] == SPELL_EFFECT_LEARN_SPELL || learn_spellproto->Effect[0] == SPELL_EFFECT_LEARN_PET_SPELL) - { - petspellid = learn_spellproto->EffectTriggerSpell[0]; - Unit* owner = GetOwner(); - if(owner->GetTypeId() == TYPEID_PLAYER && !((Player*)owner)->HasSpell(learn_spellproto->Id)) - { - if(IsPassiveSpell(petspellid)) //learn passive skills when tamed, not sure if thats right - ((Player*)owner)->learnSpell(learn_spellproto->Id,false); - else - AddTeachSpell(learn_spellproto->EffectTriggerSpell[0], learn_spellproto->Id); - } - } - else - petspellid = learn_spellproto->Id; - - addSpell(petspellid); - } - } - LearnPetPassives(); CastPetAuras(false); } -void Pet::CheckLearning(uint32 spellid) -{ - //charmed case -> prevent crash - if(GetTypeId() == TYPEID_PLAYER || getPetType() != HUNTER_PET) - return; - - Unit* owner = GetOwner(); - - if(m_teachspells.empty() || !owner || owner->GetTypeId() != TYPEID_PLAYER) - return; - - TeachSpellMap::iterator itr = m_teachspells.find(spellid); - if(itr == m_teachspells.end()) - return; - - if(urand(0, 100) < 10) - { - ((Player*)owner)->learnSpell(itr->second,false); - m_teachspells.erase(itr); - } -} - bool Pet::resetTalents(bool no_cost) { Unit *owner = GetOwner(); diff --git a/src/game/Pet.h b/src/game/Pet.h index c16a4a550..f8de3ed5e 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -107,7 +107,6 @@ enum PetNameInvalidReason }; typedef UNORDERED_MAP PetSpellMap; -typedef std::map TeachSpellMap; typedef std::vector AutoSpellList; #define HAPPINESS_LEVEL_SIZE 333000 @@ -183,7 +182,6 @@ class Pet : public Creature void ToggleAutocast(uint32 spellid, bool apply); bool HasSpell(uint32 spell) const; - void AddTeachSpell(uint32 learned_id, uint32 source_id) { m_teachspells[learned_id] = source_id; } void LearnPetPassives(); void CastPetAuras(bool current); @@ -204,11 +202,9 @@ class Pet : public Creature bool removeSpell(uint32 spell_id, bool learn_prev); PetSpellMap m_spells; - TeachSpellMap m_teachspells; AutoSpellList m_autospells; void InitPetCreateSpells(); - void CheckLearning(uint32 spellid); bool resetTalents(bool no_cost = false); uint32 resetTalentsCost() const; diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp index 8de2644f3..7db5abfaa 100644 --- a/src/game/PetAI.cpp +++ b/src/game/PetAI.cpp @@ -273,8 +273,6 @@ void PetAI::UpdateAI(const uint32 diff) } m_creature->AddCreatureSpellCooldown(spell->m_spellInfo->Id); - if (m_creature->isPet()) - ((Pet*)m_creature)->CheckLearning(spell->m_spellInfo->Id); spell->prepare(&targets); } diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index 2cf880535..3c641cbf6 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -215,8 +215,6 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) if(result == SPELL_CAST_OK) { ((Creature*)pet)->AddCreatureSpellCooldown(spellid); - if (((Creature*)pet)->isPet()) - ((Pet*)pet)->CheckLearning(spellid); unit_target = spell->m_targets.getUnitTarget(); @@ -628,11 +626,9 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) pet->AddCreatureSpellCooldown(spellid); if(pet->isPet()) { - Pet* p = (Pet*)pet; - p->CheckLearning(spellid); //10% chance to play special pet attack talk, else growl //actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell - if(p->getPetType() == SUMMON_PET && (urand(0, 100) < 10)) + if(((Pet*)pet)->getPetType() == SUMMON_PET && (urand(0, 100) < 10)) pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); else pet->SendPetAIReaction(guid); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 912249023..657f2102d 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -8345,14 +8345,6 @@ uint32 Player::GetAttackBySlot( uint8 slot ) } } -bool Player::HasBankBagSlot( uint8 slot ) const -{ - uint32 maxslot = GetByteValue(PLAYER_BYTES_2, 2) + BANK_SLOT_BAG_START; - if( slot < maxslot ) - return true; - return false; -} - bool Player::IsInventoryPos( uint8 bag, uint8 slot ) { if( bag == INVENTORY_SLOT_BAG_0 && slot == NULL_SLOT ) @@ -9733,44 +9725,44 @@ uint8 Player::CanUnequipItem( uint16 pos, bool swap ) const uint8 Player::CanBankItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *pItem, bool swap, bool not_loading ) const { - if( !pItem ) + if (!pItem) return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_ITEM_NOT_FOUND; uint32 count = pItem->GetCount(); sLog.outDebug( "STORAGE: CanBankItem bag = %u, slot = %u, item = %u, count = %u", bag, slot, pItem->GetEntry(), pItem->GetCount()); ItemPrototype const *pProto = pItem->GetProto(); - if( !pProto ) + if (!pProto) return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_ITEM_NOT_FOUND; - if( pItem->IsBindedNotWith(GetGUID()) ) + if (pItem->IsBindedNotWith(GetGUID())) return EQUIP_ERR_DONT_OWN_THAT_ITEM; // check count of items (skip for auto move for same player from bank) uint8 res = CanTakeMoreSimilarItems(pItem); - if(res != EQUIP_ERR_OK) + if (res != EQUIP_ERR_OK) return res; // in specific slot - if( bag != NULL_BAG && slot != NULL_SLOT ) + if (bag != NULL_BAG && slot != NULL_SLOT) { - if( slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END ) + if (slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END) { if (!pItem->IsBag()) return EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT; - if( !HasBankBagSlot( slot ) ) + if (slot - BANK_SLOT_BAG_START >= GetBankBagSlotCount()) return EQUIP_ERR_MUST_PURCHASE_THAT_BAG_SLOT; - if( uint8 cantuse = CanUseItem( pItem, not_loading ) != EQUIP_ERR_OK ) + if (uint8 cantuse = CanUseItem( pItem, not_loading ) != EQUIP_ERR_OK) return cantuse; } res = _CanStoreItem_InSpecificSlot(bag,slot,dest,pProto,count,swap,pItem); - if(res!=EQUIP_ERR_OK) + if (res!=EQUIP_ERR_OK) return res; - if(count==0) + if (count==0) return EQUIP_ERR_OK; } diff --git a/src/game/Player.h b/src/game/Player.h index e22ee70a6..eb5536831 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1025,7 +1025,8 @@ class MANGOS_DLL_SPEC Player : public Unit static bool IsBankPos( uint8 bag, uint8 slot ); bool IsValidPos( uint16 pos ) { return IsBankPos(pos >> 8,pos & 255); } bool IsValidPos( uint8 bag, uint8 slot ); - bool HasBankBagSlot( uint8 slot ) const; + uint8 GetBankBagSlotCount() const { return GetByteValue(PLAYER_BYTES_2, 2); } + void SetBankBagSlotCount(uint8 count) { SetByteValue(PLAYER_BYTES_2, 2, count); } bool HasItemCount( uint32 item, uint32 count, bool inBankAlso = false ) const; bool HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item const* ignoreItem = NULL); bool CanNoReagentCast(SpellEntry const* spellInfo) const; diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index ffdb85328..4844d74d8 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -3761,26 +3761,6 @@ void Aura::HandleAuraModSilence(bool apply, bool Real) for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL;i++) if (m_target->m_currentSpells[i] && m_target->m_currentSpells[i]->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) m_target->InterruptSpell(i, false); // Stop spells on prepare or casting state - - switch (GetId()) - { - // Arcane Torrent (Energy) - case 25046: - { - Unit * caster = GetCaster(); - if (!caster) - return; - - // Search Mana Tap auras on caster - Aura * dummy = caster->GetDummyAura(28734); - if (dummy) - { - int32 bp = dummy->GetStackAmount() * 10; - caster->CastCustomSpell(caster, 25048, &bp, NULL, NULL, true); - caster->RemoveAurasDueToSpell(28734); - } - } - } } else { diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 4d83b483e..0a80ee481 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -2700,17 +2700,30 @@ void Spell::EffectCreateItem(uint32 i) void Spell::EffectCreateItem2(uint32 i) { - // special case: generate using spell_loot_template - if(!m_spellInfo->EffectItemType[i]) + if(m_caster->GetTypeId()!=TYPEID_PLAYER) + return; + Player* player = (Player*)m_caster; + + uint32 item_id = m_spellInfo->EffectItemType[i]; + if(item_id) + DoCreateItem(i, item_id); + + // special case: fake item replaced by generate using spell_loot_template + if(IsLootCraftingSpell(m_spellInfo)) { - if(m_caster->GetTypeId()!=TYPEID_PLAYER) - return; + if(item_id) + { + if(!player->HasItemCount(item_id, 1)) + return; + + // remove reagent + uint32 count = 1; + player->DestroyItemCount (item_id, count, true); + } // create some random items - ((Player*)m_caster)->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell); - return; + player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell); } - DoCreateItem(i,m_spellInfo->EffectItemType[i]); } void Spell::EffectPersistentAA(uint32 i) @@ -4933,32 +4946,12 @@ void Spell::EffectScriptEffect(uint32 effIndex) case 61288: // Minor Inscription Research case 61756: // Northrend Inscription Research (FAST QA VERSION) { - if(!IsExplicitDiscoverySpell(m_spellInfo)) - { - sLog.outError("Wrong explicit discovery spell %u structure, or outdated...",m_spellInfo->Id); - return; - } - if(m_caster->GetTypeId() != TYPEID_PLAYER) return; - Player* player = (Player*)m_caster; - - // need replace effect 0 item by loot - uint32 reagent_id = m_spellInfo->EffectItemType[0]; - - if(!player->HasItemCount(reagent_id, 1)) - return; - - // remove reagent - uint32 count = 1; - player->DestroyItemCount(reagent_id, count, true); - - // create some random items - player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell); // learn random explicit discovery recipe (if any) - if(uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, player)) - player->learnSpell(discoveredSpell, false); + if(uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, (Player*)m_caster)) + ((Player*)m_caster)->learnSpell(discoveredSpell, false); return; } } diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 5b7ba0848..9fa8cf51b 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -2223,6 +2223,131 @@ void SpellMgr::LoadPetLevelupSpellMap() sLog.outString( ">> Loaded %u pet levelup and default spells for %u families", count, family_count ); } +bool LoadPetDefaultSpells_helper(CreatureInfo const* cInfo, PetDefaultSpellsEntry& petDefSpells) +{ + // skip empty list; + bool have_spell = false; + for(int j = 0; j < MAX_CREATURE_SPELL_DATA_SLOT; ++j) + { + if(petDefSpells.spellid[j]) + { + have_spell = true; + break; + } + } + if(!have_spell) + return false; + + // remove duplicates with levelupSpells if any + if(PetLevelupSpellSet const *levelupSpells = cInfo->family ? spellmgr.GetPetLevelupSpellList(cInfo->family) : NULL) + { + for(int j = 0; j < MAX_CREATURE_SPELL_DATA_SLOT; ++j) + { + if(!petDefSpells.spellid[j]) + continue; + + for(PetLevelupSpellSet::const_iterator itr = levelupSpells->begin(); itr != levelupSpells->end(); ++itr) + { + if (itr->second == petDefSpells.spellid[j]) + { + petDefSpells.spellid[j] = 0; + break; + } + } + } + } + + // skip empty list; + have_spell = false; + for(int j = 0; j < MAX_CREATURE_SPELL_DATA_SLOT; ++j) + { + if(petDefSpells.spellid[j]) + { + have_spell = true; + break; + } + } + + return have_spell; +} + +void SpellMgr::LoadPetDefaultSpells() +{ + assert(MAX_CREATURE_SPELL_DATA_SLOT==CREATURE_MAX_SPELLS); + + mPetDefaultSpellsMap.clear(); + + uint32 countCreature = 0; + uint32 countData = 0; + + for(uint32 i = 0; i < sCreatureStorage.MaxEntry; ++i ) + { + CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(i); + if(!cInfo) + continue; + + if(!cInfo->PetSpellDataId) + continue; + + // for creature with PetSpellDataId get default pet spells from dbc + CreatureSpellDataEntry const* spellDataEntry = sCreatureSpellDataStore.LookupEntry(cInfo->PetSpellDataId); + if(!spellDataEntry) + continue; + + int32 petSpellsId = -(int32)cInfo->PetSpellDataId; + PetDefaultSpellsEntry petDefSpells; + for(int j = 0; j < MAX_CREATURE_SPELL_DATA_SLOT; ++j) + petDefSpells.spellid[j] = spellDataEntry->spellId[j]; + + if(LoadPetDefaultSpells_helper(cInfo, petDefSpells)) + { + mPetDefaultSpellsMap[petSpellsId] = petDefSpells; + ++countData; + } + } + + // different summon spells + for(uint32 i = 0; i < sSpellStore.GetNumRows(); ++i ) + { + SpellEntry const* spellEntry = sSpellStore.LookupEntry(i); + if(!spellEntry) + continue; + + for(int k = 0; k < 3; ++k) + { + if(spellEntry->Effect[k]==SPELL_EFFECT_SUMMON || spellEntry->Effect[k]==SPELL_EFFECT_SUMMON_PET) + { + uint32 creature_id = spellEntry->EffectMiscValue[k]; + CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(creature_id); + if(!cInfo) + continue; + + // already loaded + if(cInfo->PetSpellDataId) + continue; + + // for creature without PetSpellDataId get default pet spells from creature_template + int32 petSpellsId = cInfo->Entry; + if(mPetDefaultSpellsMap.find(cInfo->Entry) != mPetDefaultSpellsMap.end()) + continue; + + PetDefaultSpellsEntry petDefSpells; + for(int j = 0; j < MAX_CREATURE_SPELL_DATA_SLOT; ++j) + petDefSpells.spellid[j] = cInfo->spells[j]; + + if(LoadPetDefaultSpells_helper(cInfo, petDefSpells)) + { + mPetDefaultSpellsMap[petSpellsId] = petDefSpells; + ++countCreature; + } + } + } + } + + sLog.outString(); + sLog.outString( ">> Loaded addition spells for %u pet spell data entries and %u summonable creature templates", countData, countCreature ); +} + /// Some checks for spells, to prevent adding deprecated/broken spells for trainers, spell book, etc bool SpellMgr::IsSpellValid(SpellEntry const* spellInfo, Player* pl, bool msg) { diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 48ef3f744..59915e800 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -140,8 +140,10 @@ inline bool IsExplicitDiscoverySpell(SpellEntry const *spellInfo) inline bool IsLootCraftingSpell(SpellEntry const *spellInfo) { - return spellInfo->Effect[0]==SPELL_EFFECT_CREATE_ITEM_2 && - (spellInfo->Effect[1]==SPELL_EFFECT_SCRIPT_EFFECT || !spellInfo->EffectItemType[0]); + return spellInfo->Effect[0]==SPELL_EFFECT_CREATE_ITEM_2 && ( + spellInfo->Effect[1]==SPELL_EFFECT_SCRIPT_EFFECT || // see IsExplicitDiscoverySpell + !spellInfo->EffectItemType[0] || // result item not provided + spellInfo->TotemCategory[0] == 121); // different random cards from Inscription (121==Virtuoso Inking Set category) } int32 CompareAuraRanks(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2); @@ -562,6 +564,15 @@ typedef std::multimap SkillLineAbilityMap; typedef std::multimap PetLevelupSpellSet; typedef std::map PetLevelupSpellMap; +struct PetDefaultSpellsEntry +{ + uint32 spellid[MAX_CREATURE_SPELL_DATA_SLOT]; +}; + +// < 0 for petspelldata id, > 0 for creature_id +typedef std::map PetDefaultSpellsMap; + + inline bool IsPrimaryProfessionSkill(uint32 skill) { SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(skill); @@ -812,6 +823,15 @@ class SpellMgr return NULL; } + // < 0 for petspelldata id, > 0 for creature_id + PetDefaultSpellsEntry const* GetPetDefaultSpellsEntry(int32 id) const + { + PetDefaultSpellsMap::const_iterator itr = mPetDefaultSpellsMap.find(id); + if(itr != mPetDefaultSpellsMap.end()) + return &itr->second; + return NULL; + } + SpellCastResult GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = NULL); SpellAreaMapBounds GetSpellAreaMapBounds(uint32 spell_id) const @@ -860,6 +880,7 @@ class SpellMgr void LoadSkillLineAbilityMap(); void LoadSpellPetAuras(); void LoadPetLevelupSpellMap(); + void LoadPetDefaultSpells(); void LoadSpellAreas(); private: @@ -876,6 +897,7 @@ class SpellMgr SkillLineAbilityMap mSkillLineAbilityMap; SpellPetAuraMap mSpellPetAuraMap; PetLevelupSpellMap mPetLevelupSpellMap; + PetDefaultSpellsMap mPetDefaultSpellsMap; // only spells not listed in related mPetLevelupSpellMap entry SpellAreaMap mSpellAreaMap; SpellAreaForQuestMap mSpellAreaForQuestMap; SpellAreaForQuestMap mSpellAreaForActiveQuestMap; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 573092a4e..9111222f8 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -4846,6 +4846,25 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu triggered_spell_id = 29077; break; } + + //Arcane Potency + if (dummySpell->SpellIconID == 2120) + { + if(!procSpell) + return false; + + target = this; + switch (dummySpell->Id) + { + case 31571: triggered_spell_id = 57529; break; + case 31572: triggered_spell_id = 57531; break; + default: + sLog.outError("Unit::HandleDummyAuraProc: non handled spell id: %u",dummySpell->Id); + return false; + } + break; + } + // Hot Streak if (dummySpell->SpellIconID == 2999) { @@ -5092,9 +5111,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu if(triggeredByAura->GetCasterGUID() != pVictim->GetGUID()) return false; - // energize amount - basepoints0 = triggerAmount*damage/100; - pVictim->CastCustomSpell(pVictim,34919,&basepoints0,NULL,NULL,true,castItem,triggeredByAura); + // Energize 0.25% of max. mana + pVictim->CastSpell(pVictim,57669,true,castItem,triggeredByAura); return true; // no hidden cooldown } // Divine Aegis @@ -10462,6 +10480,7 @@ bool InitTriggerAuraData() isTriggerAura[SPELL_AURA_PRAYER_OF_MENDING] = true; isTriggerAura[SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE] = true; isTriggerAura[SPELL_AURA_MOD_DAMAGE_FROM_CASTER] = true; + isTriggerAura[SPELL_AURA_MOD_SPELL_CRIT_CHANCE] = true; isNonTriggerAura[SPELL_AURA_MOD_POWER_REGEN]=true; isNonTriggerAura[SPELL_AURA_REDUCE_PUSHBACK]=true; diff --git a/src/game/World.cpp b/src/game/World.cpp index f4ded72b6..b9062760e 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1160,12 +1160,15 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading Points Of Interest Data..." ); objmgr.LoadPointsOfInterest(); - sLog.outString( "Loading Pet Create Spells..." ); - objmgr.LoadPetCreateSpells(); - sLog.outString( "Loading Creature Data..." ); objmgr.LoadCreatures(); + sLog.outString( "Loading pet levelup spells..." ); + spellmgr.LoadPetLevelupSpellMap(); + + sLog.outString( "Loading pet default spell additional to levelup spells..." ); + spellmgr.LoadPetDefaultSpells(); + sLog.outString( "Loading Creature Addon Data..." ); sLog.outString(); objmgr.LoadCreatureAddons(); // must be after LoadCreatureTemplates() and LoadCreatures() @@ -1232,9 +1235,6 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading spell pet auras..." ); spellmgr.LoadSpellPetAuras(); - sLog.outString( "Loading pet levelup spells..." ); - spellmgr.LoadPetLevelupSpellMap(); - sLog.outString( "Loading Player Create Info & Level Stats..." ); sLog.outString(); objmgr.LoadPlayerInfo(); diff --git a/src/game/WorldSocket.cpp b/src/game/WorldSocket.cpp index 7ac685148..2281761e0 100644 --- a/src/game/WorldSocket.cpp +++ b/src/game/WorldSocket.cpp @@ -537,7 +537,7 @@ int WorldSocket::handle_input_payload (void) int WorldSocket::handle_input_missing_data (void) { - char buf [1024]; + char buf [4096]; ACE_Data_Block db ( sizeof (buf), ACE_Message_Block::MB_DATA, diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 9b676ab15..5653b1fe1 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7877" + #define REVISION_NR "7887" #endif // __REVISION_NR_H__