From b4c7a2514d9844fccc46fc78aee0b34d1b26161e Mon Sep 17 00:00:00 2001 From: maximius Date: Fri, 9 Oct 2009 20:48:55 -0700 Subject: *Blackfathom Deeps - Event: Aku'mai, by Tartalo *Split Personality Achivement, by Destalker *Halls of Lightning Fixes, by Destalker Volkhan fixes + Achievement Ionar Fix - without this he resets each time he is invisible, spamming sparks Arcing Burn - should be a debuff (and stackable, stackable part NYI :/) *Naxxramas - Thaddius - the aura shall affect only the character without the proper aura, by Trazom *Naxxramas - Kelthuzad - some timer adjustments (may need verification or tweaking) by Cass *Merges by Stryker, thanks to all authors and testers. [8458] Re-implement SPELL_AURA_MOD_TARGET_ARMOR_PCT in more porper way for weapon dependent cases. Author: VladimirMangos [8459] Avoid mutiply apply weapon dependent armor penetration bonus for each weapon. Author: VladimirMangos [8529] check rune cost only if spell has PowerType == POWER_RUNE. Patch provided by yavi. Author: Ambal [8532] Fixed situation where some items like 42947 were not giving spell power bonus. By: Ambal [8533] Not remove timed quest and correctly fail when time runs out. Add function to remove timed quest instead of direct access to set. Author: NoFantasy [8536] Fixed spell 62776. By: Ambal [8539] Check pet aura range at area aura update. By: Ambal [8546] Implement battleground bonusweekends call to arms. Also fix typo in auctionmgr. Author: balrok [8547] Implemented scriptcall: CorpseRemoved(uint32 & /*respawnDelay*/) it will be called when the corpse of the scripted creature get's removed, it's possible to adjust the next respawn inside the script. Author: balrok [8561] Replace another auras code call by explicit code [8566] avoid singleton-lock when accessing BattleGroundMGR::isBGWeekend() Proposed by vladimir. Comitter: balrok --HG-- branch : trunk --- .../instance_blackfathom_deeps.cpp | 30 +++++++++++ .../northrend/nexus/nexus/boss_magus_telestra.cpp | 49 +++++++++++++++++- .../ulduar/halls_of_lightning/boss_ionar.cpp | 11 ++-- .../ulduar/halls_of_lightning/boss_volkhan.cpp | 58 ++++++++++++---------- src/game/AuctionHouseMgr.cpp | 4 +- src/game/BattleGroundAB.cpp | 6 +-- src/game/BattleGroundEY.cpp | 4 +- src/game/BattleGroundMgr.cpp | 17 +++++++ src/game/BattleGroundMgr.h | 2 + src/game/BattleGroundWS.cpp | 3 +- src/game/Creature.cpp | 4 ++ src/game/CreatureAI.h | 3 ++ src/game/Player.cpp | 48 +++++++++++------- src/game/Player.h | 8 ++- src/game/QuestHandler.cpp | 6 +++ src/game/SharedDefines.h | 4 +- src/game/Spell.cpp | 12 +++-- src/game/SpellAuraDefines.h | 2 +- src/game/SpellAuras.cpp | 27 +++++++++- src/game/SpellAuras.h | 1 + src/game/SpellEffects.cpp | 11 +++- src/game/SpellMgr.cpp | 2 + src/game/StatSystem.cpp | 32 +++++++++++- src/game/Unit.cpp | 4 +- 24 files changed, 272 insertions(+), 76 deletions(-) (limited to 'src') diff --git a/src/bindings/scripts/scripts/kalimdor/blackfathom_depths/instance_blackfathom_deeps.cpp b/src/bindings/scripts/scripts/kalimdor/blackfathom_depths/instance_blackfathom_deeps.cpp index b2664932461..cab14e26de8 100644 --- a/src/bindings/scripts/scripts/kalimdor/blackfathom_depths/instance_blackfathom_deeps.cpp +++ b/src/bindings/scripts/scripts/kalimdor/blackfathom_depths/instance_blackfathom_deeps.cpp @@ -128,6 +128,19 @@ struct TRINITY_DLL_DECL instance_blackfathom_deeps : public ScriptedInstance return 0; } + + void CheckFires() + { + GameObject *pShrine1 = instance->GetGameObject(m_uiShrine1GUID); + GameObject *pShrine2 = instance->GetGameObject(m_uiShrine2GUID); + GameObject *pShrine3 = instance->GetGameObject(m_uiShrine3GUID); + GameObject *pShrine4 = instance->GetGameObject(m_uiShrine4GUID); + if (pShrine1 && pShrine1->GetGoState() == GO_STATE_ACTIVE && + pShrine2 && pShrine2->GetGoState() == GO_STATE_ACTIVE && + pShrine3 && pShrine3->GetGoState() == GO_STATE_ACTIVE && + pShrine4 && pShrine4->GetGoState() == GO_STATE_ACTIVE) + HandleGameObject(m_uiMainDoorGUID,true); + } }; InstanceData* GetInstanceData_instance_blackfathom_deeps(Map* pMap) @@ -135,6 +148,18 @@ InstanceData* GetInstanceData_instance_blackfathom_deeps(Map* pMap) return new instance_blackfathom_deeps(pMap); } +bool GoHello_fire(Player *pPlayer, GameObject* pGo) +{ + ScriptedInstance *pInstance = pGo->GetInstanceData(); + + if (pInstance) + { + pGo->SetGoState(GO_STATE_ACTIVE); + ((instance_blackfathom_deeps*)pInstance)->CheckFires(); + } + return false; +} + void AddSC_instance_blackfathom_deeps() { Script *newscript; @@ -142,4 +167,9 @@ void AddSC_instance_blackfathom_deeps() newscript->Name = "instance_blackfathom_deeps"; newscript->GetInstanceData = &GetInstanceData_instance_blackfathom_deeps; newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_blackfathom_fire"; + newscript->pGOHello = &GoHello_fire; + newscript->RegisterSelf(); } diff --git a/src/bindings/scripts/scripts/northrend/nexus/nexus/boss_magus_telestra.cpp b/src/bindings/scripts/scripts/northrend/nexus/nexus/boss_magus_telestra.cpp index 3c0bc5150ae..946750a42a0 100644 --- a/src/bindings/scripts/scripts/northrend/nexus/nexus/boss_magus_telestra.cpp +++ b/src/bindings/scripts/scripts/northrend/nexus/nexus/boss_magus_telestra.cpp @@ -49,7 +49,11 @@ enum SAY_DEATH = -1576002, SAY_MERGE = -1576003, SAY_SPLIT_1 = -1576004, - SAY_SPLIT_2 = -1576005 + SAY_SPLIT_2 = -1576005, + +//Achievement + ACHIEV_SPLIT_PERSONALITY = 2150, + ACHIEV_TIMER = 5 * 1000 }; float CenterOfRoom[1][4] = @@ -85,6 +89,10 @@ struct TRINITY_DLL_DECL boss_magus_telestraAI : public ScriptedAI uint32 SPELL_GRAVITY_WELL_Timer; uint32 Cooldown; + bool AchievementTimerRunning; + uint8 AchievementProgress; + uint32 AchievementTimer; + void Reset() { Phase = 0; @@ -98,6 +106,10 @@ struct TRINITY_DLL_DECL boss_magus_telestraAI : public ScriptedAI FrostMagusGUID = 0; ArcaneMagusGUID = 0; + AchievementProgress = 0; + AchievementTimer = 0; + AchievementTimerRunning = false; + AppearDelay = false; m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); @@ -119,6 +131,21 @@ struct TRINITY_DLL_DECL boss_magus_telestraAI : public ScriptedAI { DoScriptText(SAY_DEATH, m_creature); + if (HeroicMode && AchievementProgress == 2) + { + AchievementEntry const *AchievSplitPersonality = GetAchievementStore()->LookupEntry(ACHIEV_SPLIT_PERSONALITY); + if (AchievSplitPersonality) + { + Map* pMap = m_creature->GetMap(); + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &players = pMap->GetPlayers(); + for(Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + itr->getSource()->CompletedAchievement(AchievSplitPersonality); + } + } + } + if (pInstance) pInstance->SetData(DATA_MAGUS_TELESTRA_EVENT, DONE); } @@ -191,13 +218,29 @@ struct TRINITY_DLL_DECL boss_magus_telestraAI : public ScriptedAI if (ArcaneMagusGUID) ArcaneMagus = Unit::GetUnit((*m_creature), ArcaneMagusGUID); if (FireMagus && FireMagus->isDead()) + { FireMagusDead = true; + if (!AchievementTimerRunning) + AchievementTimerRunning = true; + } if (FrostMagus && FrostMagus->isDead()) + { FrostMagusDead = true; + if (!AchievementTimerRunning) + AchievementTimerRunning = true; + } if (ArcaneMagus && ArcaneMagus->isDead()) + { ArcaneMagusDead = true; + if (!AchievementTimerRunning) + AchievementTimerRunning = true; + } + if (AchievementTimerRunning) + AchievementTimer += diff; if (FireMagusDead && FrostMagusDead && ArcaneMagusDead) { + if (AchievementTimer <= ACHIEV_TIMER) + AchievementProgress +=1; m_creature->GetMotionMaster()->Clear(); m_creature->GetMap()->CreatureRelocation(m_creature, CenterOfRoom[0][0], CenterOfRoom[0][1], CenterOfRoom[0][2], CenterOfRoom[0][3]); DoCast(m_creature, SPELL_TELESTRA_BACK); @@ -212,6 +255,8 @@ struct TRINITY_DLL_DECL boss_magus_telestraAI : public ScriptedAI AppearDelay = true; AppearDelay_Timer = 4000; DoScriptText(SAY_MERGE, m_creature); + AchievementTimerRunning = false; + AchievementTimer = 0; }else return; } @@ -220,6 +265,7 @@ struct TRINITY_DLL_DECL boss_magus_telestraAI : public ScriptedAI { Phase = 1; m_creature->CastStop(); + m_creature->RemoveAllAuras(); m_creature->SetVisibility(VISIBILITY_OFF); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); FireMagusGUID = SplitPersonality(MOB_FIRE_MAGUS); @@ -240,6 +286,7 @@ struct TRINITY_DLL_DECL boss_magus_telestraAI : public ScriptedAI { Phase = 3; m_creature->CastStop(); + m_creature->RemoveAllAuras(); m_creature->SetVisibility(VISIBILITY_OFF); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); FireMagusGUID = SplitPersonality(MOB_FIRE_MAGUS); diff --git a/src/bindings/scripts/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp b/src/bindings/scripts/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp index 2f81e6975b8..4d1c810f618 100644 --- a/src/bindings/scripts/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp +++ b/src/bindings/scripts/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp @@ -219,11 +219,11 @@ struct TRINITY_DLL_DECL boss_ionarAI : public ScriptedAI // Splitted if (m_creature->GetVisibility() == VISIBILITY_OFF) { - if (!m_creature->getVictim()) + /*if (!m_creature->getVictim()) { Reset(); return; - } + }*/ if (m_uiSplit_Timer < uiDiff) { @@ -316,14 +316,9 @@ bool EffectDummyCreature_boss_ionar(Unit* pCaster, uint32 uiSpellId, uint32 uiEf if (pCreatureTarget->GetEntry() != NPC_IONAR) return true; - for(uint8 i = 0; i < MAX_SPARKS; ++i) - { + for (uint8 i = 0; i < MAX_SPARKS; ++i) pCreatureTarget->CastSpell(pCreatureTarget, SPELL_SUMMON_SPARK, true); - //TODO: remove this line of hack when summon implemented - pCreatureTarget->SummonCreature(NPC_SPARK_OF_IONAR, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - } - pCreatureTarget->AttackStop(); pCreatureTarget->SetVisibility(VISIBILITY_OFF); diff --git a/src/bindings/scripts/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp b/src/bindings/scripts/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp index 368b6370a0f..79e6e6881ac 100644 --- a/src/bindings/scripts/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp +++ b/src/bindings/scripts/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp @@ -63,7 +63,9 @@ enum NPC_BRITTLE_GOLEM = 28681, POINT_ID_ANVIL = 0, - MAX_GOLEM = 2 + MAX_GOLEM = 2, + + ACHIEVEMENT_SHATTER_RESISTANT = 2042 }; /*###### @@ -87,6 +89,7 @@ struct TRINITY_DLL_DECL boss_volkhanAI : public ScriptedAI bool m_bIsStriking; bool m_bCanShatterGolem; + uint8 GolemsShattered; uint32 m_uiPause_Timer; uint32 m_uiShatteringStomp_Timer; uint32 m_uiShatter_Timer; @@ -102,6 +105,7 @@ struct TRINITY_DLL_DECL boss_volkhanAI : public ScriptedAI m_uiPause_Timer = 3500; m_uiShatteringStomp_Timer = 0; m_uiShatter_Timer = 5000; + GolemsShattered = 0; m_uiHealthAmountModifier = 1; @@ -112,7 +116,7 @@ struct TRINITY_DLL_DECL boss_volkhanAI : public ScriptedAI m_pInstance->SetData(TYPE_VOLKHAN, NOT_STARTED); } - void Aggro(Unit* pWho) + void EnterCombat(Unit* pWho) { DoScriptText(SAY_AGGRO, m_creature); @@ -140,6 +144,21 @@ struct TRINITY_DLL_DECL boss_volkhanAI : public ScriptedAI if (m_pInstance) m_pInstance->SetData(TYPE_VOLKHAN, DONE); + + if (HeroicMode && GolemsShattered < 5) + { + AchievementEntry const *AchievShatterResistant = GetAchievementStore()->LookupEntry(ACHIEVEMENT_SHATTER_RESISTANT); + if (AchievShatterResistant) + { + Map* pMap = m_creature->GetMap(); + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &players = pMap->GetPlayers(); + for(Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + itr->getSource()->CompletedAchievement(AchievShatterResistant); + } + } + } } void KilledUnit(Unit* pVictim) @@ -178,9 +197,12 @@ struct TRINITY_DLL_DECL boss_volkhanAI : public ScriptedAI { if (Creature* pTemp = Unit::GetCreature(*m_creature, *itr)) { - // only shatter brittle golems + // only shatter brittle golems if (pTemp->isAlive() && pTemp->GetEntry() == NPC_BRITTLE_GOLEM) + { pTemp->CastSpell(pTemp, m_bIsHeroic ? SPELL_SHATTER_H : SPELL_SHATTER_N, false); + GolemsShattered += 1; + } } } } @@ -307,11 +329,6 @@ bool EffectDummyCreature_boss_volkhan(Unit* pCaster, uint32 uiSpellId, uint32 ui for(uint8 i = 0; i < MAX_GOLEM; ++i) { pCreatureTarget->CastSpell(pCaster, SPELL_SUMMON_MOLTEN_GOLEM, true); - - //TODO: remove this line of hack when summon effect implemented - pCreatureTarget->SummonCreature(NPC_MOLTEN_GOLEM, - pCaster->GetPositionX(), pCaster->GetPositionY(), pCaster->GetPositionZ(), 0.0f, - TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000); } //always return true when we are handling this spell and effect @@ -399,30 +416,19 @@ struct TRINITY_DLL_DECL mob_molten_golemAI : public ScriptedAI void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) { - if (m_bIsFrozen) - { - //workaround for now, brittled should be immune to any kind of attacks - uiDamage = 0; - return; - } - if (uiDamage > m_creature->GetHealth()) { - m_bIsFrozen = true; - - if (m_creature->IsNonMeleeSpellCasted(false)) - m_creature->InterruptNonMeleeSpells(false); - + m_creature->UpdateEntry(NPC_BRITTLE_GOLEM); + m_creature->SetHealth(1); + uiDamage = 0; m_creature->RemoveAllAuras(); m_creature->AttackStop(); - + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); + if (m_creature->IsNonMeleeSpellCasted(false)) + m_creature->InterruptNonMeleeSpells(false); if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) m_creature->GetMotionMaster()->MovementExpired(); - - uiDamage = m_creature->GetHealth()-1; - - m_creature->UpdateEntry(NPC_BRITTLE_GOLEM); - m_creature->SetHealth(1); + m_bIsFrozen = true; } } diff --git a/src/game/AuctionHouseMgr.cpp b/src/game/AuctionHouseMgr.cpp index 294beed2fb7..4fb8398e694 100644 --- a/src/game/AuctionHouseMgr.cpp +++ b/src/game/AuctionHouseMgr.cpp @@ -295,7 +295,7 @@ void AuctionHouseMgr::LoadAuctionItems() if (!proto) { - sLog.outError("ObjectMgr::LoadAuctionItems: Unknown item (GUID: %u id: #%u) in auction, skipped.", item_guid,item_template); + sLog.outError("AuctionHouseMgr::LoadAuctionItems: Unknown item (GUID: %u id: #%u) in auction, skipped.", item_guid,item_template); continue; } @@ -404,7 +404,7 @@ void AuctionHouseMgr::LoadAuctions() } // check if sold item exists for guid - // and item_template in fact (GetAItem will fail if problematic in result check in ObjectMgr::LoadAuctionItems) + // and item_template in fact (GetAItem will fail if problematic in result check in AuctionHouseMgr::LoadAuctionItems) if (!GetAItem(aItem->item_guidlow)) { aItem->DeleteFromDB(); diff --git a/src/game/BattleGroundAB.cpp b/src/game/BattleGroundAB.cpp index adf480d6f97..39b7d06e0ce 100644 --- a/src/game/BattleGroundAB.cpp +++ b/src/game/BattleGroundAB.cpp @@ -18,10 +18,10 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "ObjectMgr.h" #include "World.h" #include "WorldPacket.h" - +#include "GameObject.h" +#include "BattleGroundMgr.h" #include "BattleGround.h" #include "BattleGroundAB.h" #include "Creature.h" @@ -593,7 +593,7 @@ void BattleGroundAB::Reset() m_ReputationScoreTics[BG_TEAM_ALLIANCE] = 0; m_ReputationScoreTics[BG_TEAM_HORDE] = 0; m_IsInformedNearVictory = false; - bool isBGWeekend = false; //TODO FIXME - call sBattleGroundMgr.IsBGWeekend(m_TypeID); - you must also implement that call! + bool isBGWeekend = sBattleGroundMgr.IsBGWeekend(GetTypeID()); m_HonorTics = (isBGWeekend) ? BG_AB_ABBGWeekendHonorTicks : BG_AB_NotABBGWeekendHonorTicks; m_ReputationTics = (isBGWeekend) ? BG_AB_ABBGWeekendReputationTicks : BG_AB_NotABBGWeekendReputationTicks; m_TeamScores500Disadvantage[BG_TEAM_ALLIANCE] = false; diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp index 78654677230..0c7ea66388b 100644 --- a/src/game/BattleGroundEY.cpp +++ b/src/game/BattleGroundEY.cpp @@ -21,7 +21,7 @@ #include "ObjectMgr.h" #include "World.h" #include "WorldPacket.h" - +#include "BattleGroundMgr.h" #include "BattleGround.h" #include "BattleGroundEY.h" #include "Creature.h" @@ -529,7 +529,7 @@ void BattleGroundEY::Reset() m_DroppedFlagGUID = 0; m_PointAddingTimer = 0; m_TowerCapCheckTimer = 0; - bool isBGWeekend = false; //TODO FIXME - call sBattleGroundMgr.IsBGWeekend(m_TypeID); - you must also implement that call! + bool isBGWeekend = sBattleGroundMgr.IsBGWeekend(GetTypeID()); m_HonorTics = (isBGWeekend) ? BG_EY_EYWeekendHonorTicks : BG_EY_NotEYWeekendHonorTicks; for(uint8 i = 0; i < EY_POINTS_MAX; ++i) diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index 64972c0c97f..d1f5d71942f 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -42,6 +42,7 @@ #include "MapInstanced.h" #include "MapManager.h" #include "Player.h" +#include "GameEventMgr.h" #include "ProgressBar.h" #include "SharedDefines.h" @@ -2113,3 +2114,19 @@ void BattleGroundMgr::LoadBattleMastersEntry() sLog.outString(); sLog.outString( ">> Loaded %u battlemaster entries", count ); } +bool BattleGroundMgr::IsBGWeekend(BattleGroundTypeId bgTypeId) +{ + switch (bgTypeId) + { + case BATTLEGROUND_AV: + return IsHolidayActive(HOLIDAY_CALL_TO_ARMS_AV); + case BATTLEGROUND_EY: + return IsHolidayActive(HOLIDAY_CALL_TO_ARMS_EY); + case BATTLEGROUND_WS: + return IsHolidayActive(HOLIDAY_CALL_TO_ARMS_WS); + case BATTLEGROUND_SA: + return IsHolidayActive(HOLIDAY_CALL_TO_ARMS_SA); + default: + return false; + } +} diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index c16de449f54..9100142ebd0 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -248,6 +248,8 @@ class BattleGroundMgr static BattleGroundQueueTypeId BGQueueTypeId(BattleGroundTypeId bgTypeId, uint8 arenaType); static BattleGroundTypeId BGTemplateId(BattleGroundQueueTypeId bgQueueTypeId); static uint8 BGArenaType(BattleGroundQueueTypeId bgQueueTypeId); + + static bool IsBGWeekend(BattleGroundTypeId bgTypeId); private: BattleMastersMap mBattleMastersMap; diff --git a/src/game/BattleGroundWS.cpp b/src/game/BattleGroundWS.cpp index 81080284b9d..ec19308e71f 100644 --- a/src/game/BattleGroundWS.cpp +++ b/src/game/BattleGroundWS.cpp @@ -25,6 +25,7 @@ #include "Language.h" #include "Object.h" #include "ObjectMgr.h" +#include "BattleGroundMgr.h" #include "Player.h" #include "World.h" #include "WorldPacket.h" @@ -679,7 +680,7 @@ void BattleGroundWS::Reset() m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE; m_TeamScores[BG_TEAM_ALLIANCE] = 0; m_TeamScores[BG_TEAM_HORDE] = 0; - bool isBGWeekend = false; //TODO FIXME - call sBattleGroundMgr.IsBGWeekend(m_TypeID); - you must also implement that call! + bool isBGWeekend = sBattleGroundMgr.IsBGWeekend(GetTypeID()); m_ReputationCapture = (isBGWeekend) ? 45 : 35; m_HonorWinKills = (isBGWeekend) ? 3 : 1; m_HonorEndKills = (isBGWeekend) ? 4 : 2; diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 5c3bf884e21..cc2bc64ae39 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -235,6 +235,10 @@ void Creature::RemoveCorpse() setDeathState(DEAD); ObjectAccessor::UpdateObjectVisibility(this); loot.clear(); + uint32 respawnDelay = m_respawnDelay; + if (AI()) + AI()->CorpseRemoved(respawnDelay); + m_respawnTime = time(NULL) + m_respawnDelay; float x,y,z,o; diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h index 791c4a96ca8..556e9be14e0 100644 --- a/src/game/CreatureAI.h +++ b/src/game/CreatureAI.h @@ -157,6 +157,9 @@ class TRINITY_DLL_SPEC CreatureAI : public UnitAI // Is unit visible for MoveInLineOfSight //virtual bool IsVisible(Unit *) const { return false; } + // called when the corpse of this creature gets removed + virtual void CorpseRemoved(uint32 & /*respawnDelay*/) {} + // Called when victim entered water and creature can not enter water //virtual bool canReachByRangeAttack(Unit*) { return false; } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index e2c9b875c7c..de731b5c5b5 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -449,6 +449,7 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa m_baseSpellPower = 0; m_baseFeralAP = 0; m_baseManaRegen = 0; + m_armorPenetrationPct = 0.0f; // Honor System m_lastHonorUpdateTime = time(NULL); @@ -5287,7 +5288,7 @@ void Player::ApplyRatingMod(CombatRating cr, int32 value, bool apply) break; case CR_ARMOR_PENETRATION: if(affectStats) - UpdateArmorPenetration(amount); + UpdateArmorPenetration(); break; } } @@ -7083,6 +7084,13 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl } } + // Apply Spell Power from ScalingStatValue if set + if(ssv) + { + if (int32 spellbonus = ssv->getSpellBonus(proto->ScalingStatValue)) + ApplySpellPowerBonus(spellbonus, apply); + } + // If set ScalingStatValue armor get it or use item armor uint32 armor = proto->Armor; if (ssv) @@ -11043,9 +11051,15 @@ Item* Player::EquipItem( uint16 pos, Item *pItem, bool update ) // update expertise and armor penetration - passive auras may need it if( slot == EQUIPMENT_SLOT_MAINHAND ) + { UpdateExpertise(BASE_ATTACK); + UpdateArmorPenetration(); + } else if( slot == EQUIPMENT_SLOT_OFFHAND ) + { UpdateExpertise(OFF_ATTACK); + UpdateArmorPenetration(); + } switch(slot) { @@ -11195,6 +11209,7 @@ void Player::RemoveItem( uint8 bag, uint8 slot, bool update ) } UpdateExpertise(BASE_ATTACK); + UpdateArmorPenetration(); } else if( slot == EQUIPMENT_SLOT_OFFHAND ) UpdateExpertise(OFF_ATTACK); @@ -11204,7 +11219,7 @@ void Player::RemoveItem( uint8 bag, uint8 slot, bool update ) case EQUIPMENT_SLOT_MAINHAND: case EQUIPMENT_SLOT_OFFHAND: case EQUIPMENT_SLOT_RANGED: - RecalculateRating(CR_ARMOR_PENETRATION); + UpdateArmorPenetration(); default: break; } @@ -11321,15 +11336,21 @@ void Player::DestroyItem( uint8 bag, uint8 slot, bool update ) case EQUIPMENT_SLOT_MAINHAND: case EQUIPMENT_SLOT_OFFHAND: case EQUIPMENT_SLOT_RANGED: - RecalculateRating(CR_ARMOR_PENETRATION); + UpdateArmorPenetration(); default: break; } - if ( slot == EQUIPMENT_SLOT_MAINHAND ) + if( slot == EQUIPMENT_SLOT_MAINHAND ) + { UpdateExpertise(BASE_ATTACK); + UpdateArmorPenetration(); + } else if( slot == EQUIPMENT_SLOT_OFFHAND ) + { UpdateExpertise(OFF_ATTACK); + UpdateArmorPenetration(); + } // equipment visual show SetVisibleItemSlot(slot, NULL); @@ -13216,9 +13237,7 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver } } - //if( qInfo->HasSpecialFlag( QUEST_FLAGS_TIMED ) ) - // SetTimedQuest( 0 ); - m_timedquests.erase(pQuest->GetQuestId()); + RemoveTimedQuest(quest_id); if (pQuest->GetRewChoiceItemsCount() > 0) { @@ -13430,6 +13449,7 @@ void Player::FailQuest(uint32 questId) { QuestStatusData& q_status = mQuestStatus[questId]; + RemoveTimedQuest(questId); q_status.m_timer = 0; SendQuestTimerFailed(questId); @@ -13655,12 +13675,12 @@ bool Player::SatisfyQuestStatus( Quest const* qInfo, bool msg ) return true; } -bool Player::SatisfyQuestTimed( Quest const* qInfo, bool msg ) +bool Player::SatisfyQuestTimed(Quest const* qInfo, bool msg) { - if ( (find(m_timedquests.begin(), m_timedquests.end(), qInfo->GetQuestId()) != m_timedquests.end()) && qInfo->HasFlag(QUEST_TRINITY_FLAGS_TIMED) ) + if (m_timedquests.empty() && qInfo->HasFlag(QUEST_TRINITY_FLAGS_TIMED)) { - if( msg ) - SendCanTakeQuestResponse( INVALIDREASON_QUEST_ONLY_ONE_TIMED ); + if (msg) + SendCanTakeQuestResponse(INVALIDREASON_QUEST_ONLY_ONE_TIMED); return false; } return true; @@ -13888,12 +13908,6 @@ void Player::SetQuestStatus(uint32 quest_id, QuestStatus status) { if (Quest const* qInfo = objmgr.GetQuestTemplate(quest_id)) { - if (status == QUEST_STATUS_NONE || status == QUEST_STATUS_INCOMPLETE || status == QUEST_STATUS_COMPLETE || status == QUEST_STATUS_FAILED) - { - if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_TIMED)) - m_timedquests.erase(qInfo->GetQuestId()); - } - QuestStatusData& q_status = mQuestStatus[quest_id]; q_status.m_status = status; diff --git a/src/game/Player.h b/src/game/Player.h index 44db36d30c4..66c92074509 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1315,6 +1315,7 @@ class MANGOS_DLL_SPEC Player : public Unit void SetInGameTime( uint32 time ) { m_ingametime = time; }; void AddTimedQuest( uint32 quest_id ) { m_timedquests.insert(quest_id); } + void RemoveTimedQuest( uint32 quest_id ) { m_timedquests.erase(quest_id); } /*********************************************************/ /*** LOAD SYSTEM ***/ @@ -1700,7 +1701,7 @@ class MANGOS_DLL_SPEC Player : public Unit void UpdateAllSpellCritChances(); void UpdateSpellCritChance(uint32 school); - void UpdateArmorPenetration(int32 amount); + void UpdateArmorPenetration(); void UpdateExpertise(WeaponAttackType attType); void ApplyManaRegenBonus(int32 amount, bool apply); void UpdateManaRegen(); @@ -1869,6 +1870,7 @@ class MANGOS_DLL_SPEC Player : public Unit float GetTotalPercentageModValue(BaseModGroup modGroup) const { return m_auraBaseMod[modGroup][FLAT_MOD] + m_auraBaseMod[modGroup][PCT_MOD]; } void _ApplyAllStatBonuses(); void _RemoveAllStatBonuses(); + float GetArmorPenetrationPct() const { return m_armorPenetrationPct; } void _ApplyWeaponDependentAuraMods(Item *item, WeaponAttackType attackType, bool apply); void _ApplyWeaponDependentAuraCritMod(Item *item, WeaponAttackType attackType, AuraEffect* aura, bool apply); @@ -2252,7 +2254,8 @@ Spell * m_spellModTakingSpell; /*********************************************************/ /*** QUEST SYSTEM ***/ /*********************************************************/ - + + //We allow only one timed quest active at the same time. Below can then be simple value instead of set. std::set m_timedquests; uint64 m_divider; @@ -2362,6 +2365,7 @@ Spell * m_spellModTakingSpell; uint16 m_baseSpellPower; uint16 m_baseFeralAP; uint16 m_baseManaRegen; + float m_armorPenetrationPct; SpellModList m_spellMods[MAX_SPELLMOD]; uint32 m_pad; diff --git a/src/game/QuestHandler.cpp b/src/game/QuestHandler.cpp index 3e9cca09ddb..a803c49d6fd 100644 --- a/src/game/QuestHandler.cpp +++ b/src/game/QuestHandler.cpp @@ -354,6 +354,12 @@ void WorldSession::HandleQuestLogRemoveQuest(WorldPacket& recv_data) if(!_player->TakeQuestSourceItem( quest, true )) return; // can't un-equip some items, reject quest cancel + if (const Quest *pQuest = objmgr.GetQuestTemplate(quest)) + { + if (pQuest->HasFlag(QUEST_TRINITY_FLAGS_TIMED)) + _player->RemoveTimedQuest(quest); + } + _player->TakeQuestSourceItem(quest, true); // remove quest src item from player _player->SetQuestStatus( quest, QUEST_STATUS_NONE); } diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 139de37bf84..0ccab173166 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -1969,7 +1969,7 @@ enum HolidayIds HOLIDAY_NOBLEGARDEN = 181, HOLIDAY_CHILDRENS_WEEK = 201, HOLIDAY_CALL_TO_ARMS_AV = 283, - HOLIDAY_CALL_TO_ARMS_WG = 284, + HOLIDAY_CALL_TO_ARMS_WS = 284, HOLIDAY_CALL_TO_ARMS_AB = 285, HOLIDAY_FISHING_EXTRAVAGANZA = 301, HOLIDAY_HARVEST_FESTIVAL = 321, @@ -1977,7 +1977,7 @@ enum HolidayIds HOLIDAY_LUNAR_FESTIVAL = 327, HOLIDAY_LOVE_IS_IN_THE_AIR = 335, HOLIDAY_FIRE_FESTIVAL = 341, - HOLIDAY_CALL_TO_ARMS_ES = 353, + HOLIDAY_CALL_TO_ARMS_EY = 353, HOLIDAY_BREWFEST = 372, HOLIDAY_DARKMOON_FAIRE_ELWYNN = 374, HOLIDAY_DARKMOON_FAIRE_THUNDER = 375, diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 31348dedda9..5301eb4069b 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -5493,10 +5493,14 @@ SpellCastResult Spell::CheckPower() sLog.outError("Spell::CheckPower: Unknown power type '%d'", m_spellInfo->powerType); return SPELL_FAILED_UNKNOWN; } - - SpellCastResult failReason = CheckRuneCost(m_spellInfo->runeCostID); - if(failReason != SPELL_CAST_OK) - return failReason; + + //check rune cost only if a spell has PowerType == POWER_RUNE + if(m_spellInfo->powerType == POWER_RUNE) + { + SpellCastResult failReason = CheckRuneCost(m_spellInfo->runeCostID); + if(failReason != SPELL_CAST_OK) + return failReason; + } // Check power amount Powers powerType = Powers(m_spellInfo->powerType); diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index ffcbdacda34..866182f9733 100644 --- a/src/game/SpellAuraDefines.h +++ b/src/game/SpellAuraDefines.h @@ -325,7 +325,7 @@ enum AuraType SPELL_AURA_MOD_MAX_AFFECTED_TARGETS = 277, SPELL_AURA_MOD_DISARM_RANGED = 278, SPELL_AURA_INITIALIZE_IMAGES = 279, - SPELL_AURA_MOD_ARMOR_PENETRATION_PCT = 280, + SPELL_AURA_MOD_TARGET_ARMOR_PCT = 280, SPELL_AURA_MOD_HONOR_GAIN_PCT = 281, SPELL_AURA_MOD_BASE_HEALTH_PCT = 282, SPELL_AURA_MOD_HEALING_RECEIVED = 283, // Possibly only for some spell family class spells diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index c1723bf9936..6454a1c2655 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -333,7 +333,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNoImmediateEffect, //277 SPELL_AURA_MOD_ABILITY_AFFECTED_TARGETS implemented in spell::settargetmap &Aura::HandleAuraModDisarm, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon &Aura::HandleAuraInitializeImages, //279 SPELL_AURA_INITIALIZE_IMAGES - &Aura::HandleNoImmediateEffect, //280 SPELL_AURA_MOD_TARGET_ARMOR_PCT implemented in Unit::CalcArmorReducedDamage + &Aura::HandleModTargetArmorPct, //280 SPELL_AURA_MOD_TARGET_ARMOR_PCT &Aura::HandleNoImmediateEffect, //281 SPELL_AURA_MOD_HONOR_GAIN_PCT implemented in Player::RewardHonor &Aura::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT &Aura::HandleNoImmediateEffect, //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus @@ -747,7 +747,7 @@ void AreaAuraEffect::Update(uint32 diff) case AREA_AURA_PET: { if(Unit *owner = caster->GetCharmerOrOwner()) - if (owner->IsWithinDistInMap(source, m_radius)) + if (caster->IsWithinDistInMap(owner, m_radius)) targets.push_back(owner); break; } @@ -6919,6 +6919,7 @@ void AuraEffect::HandleAuraCloneCaster( bool Apply, bool Real , bool /*changeAmo void AuraEffect::HandleAuraModCritPct(bool apply, bool Real, bool changeAmount) { + /* if(m_target->GetTypeId() != TYPEID_PLAYER) { m_target->m_baseSpellCritChance += apply ? m_amount:-m_amount; @@ -6931,6 +6932,20 @@ void AuraEffect::HandleAuraModCritPct(bool apply, bool Real, bool changeAmount) ((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (m_amount), apply); ((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (m_amount), apply); ((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (m_amount), apply); + */ + // spells required only Real aura add/remove + if(!Real) + return; + + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + ((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (m_amount), apply); + ((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (m_amount), apply); + ((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (m_amount), apply); + + // included in Player::UpdateSpellCritChance calculation + ((Player*)m_target)->UpdateAllSpellCritChances(); } void AuraEffect::HandleAuraLinked(bool apply, bool Real, bool /*changeAmount*/) @@ -6999,3 +7014,11 @@ bool AuraEffect::IsPeriodicTickCrit(Unit const * pCaster) const return false; } +void AuraEffect::HandleModTargetArmorPct(bool apply, bool Real, bool changeAmount) +{ + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + ((Player*)m_target)->UpdateArmorPenetration(); +} + diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index 821e208d6b7..fe82a319f20 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -333,6 +333,7 @@ class TRINITY_DLL_SPEC AuraEffect void HandleAuraCloneCaster(bool Apply, bool Real, bool changeAmount); void HandleAuraModCritPct(bool Apply, bool Real, bool changeAmount); void HandleAuraLinked(bool Apply, bool Real, bool changeAmount); + void HandleModTargetArmorPct(bool Apply, bool Real, bool changeAmount); void HandleAuraEffectSpecificMods(bool apply, bool Real, bool changeAmount); int32 CalculateCrowdControlAuraAmount(Unit * caster); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 5665121dbff..56679b1abe4 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -371,7 +371,8 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) aur->SetStackAmount(count); } } - else if(unitTarget->HasAura(m_triggeredByAuraSpell->Id)) + + if(unitTarget->HasAura(m_triggeredByAuraSpell->Id)) damage = 0; break; // Consumption @@ -409,8 +410,16 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) } // Cataclysmic Bolt case 38441: + { damage = unitTarget->GetMaxHealth() / 2; break; + } + // Tympanic Tantrum + case 62775: + { + damage = unitTarget->GetMaxHealth() / 10; + break; + } } break; } diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index ff8a1d02f29..c1b78ebc7ab 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -761,6 +761,8 @@ bool SpellMgr::_isPositiveEffect(uint32 spellId, uint32 effIndex, bool deep) con case 31719: // Suspension case 61987: // Avenging Wrath Marker case 50524: // Runic Power Feed + case 52671: // Arcing Burn + case 59834: // Arcing Burn return false; case 12042: // Arcane Power return true; diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp index 56bde0e5442..b662769b77f 100644 --- a/src/game/StatSystem.cpp +++ b/src/game/StatSystem.cpp @@ -151,6 +151,7 @@ bool Player::UpdateAllStats() UpdateAllSpellCritChances(); UpdateDefenseBonusesMod(); UpdateShieldBlockValue(); + UpdateArmorPenetration(); UpdateSpellDamageAndHealingBonus(); UpdateManaRegen(); UpdateExpertise(BASE_ATTACK); @@ -625,13 +626,13 @@ void Player::UpdateSpellCritChance(uint32 school) // Store crit value SetFloatValue(PLAYER_SPELL_CRIT_PERCENTAGE1 + school, crit); } - +/* void Player::UpdateArmorPenetration(int32 amount) { // Store Rating Value SetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + CR_ARMOR_PENETRATION, amount); } - +*/ void Player::UpdateMeleeHitChances() { m_modMeleeHitChance = GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE); @@ -687,6 +688,33 @@ void Player::UpdateExpertise(WeaponAttackType attack) } } +void Player::UpdateArmorPenetration() +{ + m_armorPenetrationPct = GetRatingBonusValue(CR_ARMOR_PENETRATION); + + AuraEffectList const& armorAuras = GetAurasByType(SPELL_AURA_MOD_TARGET_ARMOR_PCT); + for(AuraEffectList::const_iterator itr = armorAuras.begin(); itr != armorAuras.end(); ++itr) + { + // affects all weapons + if((*itr)->GetSpellProto()->EquippedItemClass == -1) + { + m_armorPenetrationPct += (*itr)->GetAmount(); + continue; + } + + // dependent on weapon class + for(uint8 i = 0; i < MAX_ATTACK; ++i) + { + Item *weapon = GetWeaponForAttack(WeaponAttackType(i)); + if(weapon && weapon->IsFitToSpellRequirements((*itr)->GetSpellProto())) + { + m_armorPenetrationPct += (*itr)->GetAmount(); + break; + } + } + } +} + void Player::ApplyManaRegenBonus(int32 amount, bool apply) { m_baseManaRegen+= apply ? amount : -amount; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 02ad5bb69cb..0364ead6776 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -1653,7 +1653,7 @@ uint32 Unit::CalcArmorReducedDamage(Unit* pVictim, const uint32 damage, SpellEnt if ( GetTypeId() == TYPEID_PLAYER ) { - AuraEffectList const& ResIgnoreAuras = GetAurasByType(SPELL_AURA_MOD_ARMOR_PENETRATION_PCT); + AuraEffectList const& ResIgnoreAuras = GetAurasByType(SPELL_AURA_MOD_TARGET_ARMOR_PCT); for(AuraEffectList::const_iterator itr = ResIgnoreAuras.begin();itr != ResIgnoreAuras.end(); ++itr) { // item neutral spell @@ -1694,7 +1694,7 @@ uint32 Unit::CalcArmorReducedDamage(Unit* pVictim, const uint32 damage, SpellEnt } // Ignore enemy armor by SPELL_AURA_MOD_TARGET_ARMOR_PCT - //armor *= 1.0f - GetTotalAuraModifier(SPELL_AURA_MOD_ARMOR_PENETRATION_PCT) / 100.0f; + armor *= 1.0f - ((Player*)this)->GetArmorPenetrationPct() / 100.0f; if (armor < 0.0f) armor = 0.0f; -- cgit v1.2.3