Merge branch 'master' into questXPHook

This commit is contained in:
郑佩茹
2022-03-10 12:08:00 -07:00
31 changed files with 2548 additions and 351 deletions
@@ -37,9 +37,9 @@ void AddGossipItemFor(Player* player, uint32 icon, std::string const& text, uint
}
// Uses gossip item info from DB
void AddGossipItemFor(Player* player, uint32 gossipMenuID, uint32 gossipMenuItemID, uint32 sender, uint32 action)
void AddGossipItemFor(Player* player, uint32 gossipMenuID, uint32 gossipMenuItemID, uint32 sender, uint32 action, uint32 boxMoney /*= 0*/)
{
player->PlayerTalkClass->GetGossipMenu().AddMenuItem(gossipMenuID, gossipMenuItemID, sender, action);
player->PlayerTalkClass->GetGossipMenu().AddMenuItem(gossipMenuID, gossipMenuItemID, sender, action, boxMoney);
}
void SendGossipMenuFor(Player* player, uint32 npcTextID, ObjectGuid const guid)
@@ -91,7 +91,7 @@ void AddGossipItemFor(Player* player, uint32 icon, std::string const& text, uint
void AddGossipItemFor(Player* player, uint32 icon, std::string const& text, uint32 sender, uint32 action, std::string const& popupText, uint32 popupMoney, bool coded);
// Uses gossip item info from DB
void AddGossipItemFor(Player* player, uint32 gossipMenuID, uint32 gossipMenuItemID, uint32 sender, uint32 action);
void AddGossipItemFor(Player* player, uint32 gossipMenuID, uint32 gossipMenuItemID, uint32 sender, uint32 action, uint32 boxMoney = 0);
// Send menu text
void SendGossipMenuFor(Player* player, uint32 npcTextID, ObjectGuid const guid);
@@ -662,7 +662,10 @@ enum BG_AV_CreaturePlace
AV_CPLACE_TRIGGER18 = 319,
AV_CPLACE_TRIGGER19 = 320,
AV_CPLACE_MAX = 321
AV_CPLACE_MAX = 321,
AV_CPLACE_A_BOSS = 381,
AV_CPLACE_H_BOSS = 445
};
//x, y, z, o
@@ -425,8 +425,14 @@ bool Creature::InitEntry(uint32 Entry, const CreatureData* data)
SetNativeDisplayId(displayID);
// Load creature equipment
if (!data || data->equipmentId == 0) // use default from the template
LoadEquipment(0); // 0 means no equipment for creature table
if (!data)
{
LoadEquipment(); // use default from the template
}
else if (data->equipmentId == 0)
{
LoadEquipment(0); // 0 means no equipment for creature table
}
else
{
m_originalEquipmentId = data->equipmentId;
@@ -74,8 +74,9 @@ void GossipMenu::AddMenuItem(int32 menuItemId, uint8 icon, std::string const& me
* @param menuItemId Gossip menu item id.
* @param sender Identifier of the current menu.
* @param action Custom action given to OnGossipHello.
* @param boxMoney Custom price for pop-up box. If > 0, it will replace DB value.
*/
void GossipMenu::AddMenuItem(uint32 menuId, uint32 menuItemId, uint32 sender, uint32 action)
void GossipMenu::AddMenuItem(uint32 menuId, uint32 menuItemId, uint32 sender, uint32 action, uint32 boxMoney)
{
/// Find items for given menu id.
GossipMenuItemsMapBounds bounds = sObjectMgr->GetGossipMenuItemsMapBounds(menuId);
@@ -126,7 +127,7 @@ void GossipMenu::AddMenuItem(uint32 menuId, uint32 menuItemId, uint32 sender, ui
}
/// Add menu item with existing method. Menu item id -1 is also used in ADD_GOSSIP_ITEM macro.
AddMenuItem(-1, itr->second.OptionIcon, strOptionText, sender, action, strBoxText, itr->second.BoxMoney, itr->second.BoxCoded);
AddMenuItem(-1, itr->second.OptionIcon, strOptionText, sender, action, strBoxText, boxMoney ? boxMoney : itr->second.BoxMoney, itr->second.BoxCoded);
}
}
@@ -165,7 +165,7 @@ public:
~GossipMenu();
void AddMenuItem(int32 menuItemId, uint8 icon, std::string const& message, uint32 sender, uint32 action, std::string const& boxMessage, uint32 boxMoney, bool coded = false);
void AddMenuItem(uint32 menuId, uint32 menuItemId, uint32 sender, uint32 action);
void AddMenuItem(uint32 menuId, uint32 menuItemId, uint32 sender, uint32 action, uint32 boxMoney);
void SetMenuId(uint32 menu_id) { _menuId = menu_id; }
[[nodiscard]] uint32 GetMenuId() const { return _menuId; }
+10 -3
View File
@@ -3009,11 +3009,18 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spellInfo
thisLevel = std::max<int32>(thisLevel, spellInfo->SpellLevel);
int32 levelDiff = int32(victim->getLevelForTarget(this)) - thisLevel;
int32 MISS_CHANCE_MULTIPLIER = sWorld->getRate(
int32 MISS_CHANCE_MULTIPLIER;
if (sWorld->getBoolConfig(CONFIG_MISS_CHANCE_MULTIPLIER_ONLY_FOR_PLAYERS) && GetTypeId() != TYPEID_PLAYER) // keep it as it was originally (7 and 11)
{
MISS_CHANCE_MULTIPLIER = victim->GetTypeId() == TYPEID_PLAYER ? 7 : 11;
}
else
{
MISS_CHANCE_MULTIPLIER = sWorld->getRate(
victim->GetTypeId() == TYPEID_PLAYER
? RATE_MISS_CHANCE_MULTIPLIER_TARGET_PLAYER
: RATE_MISS_CHANCE_MULTIPLIER_TARGET_CREATURE
);
: RATE_MISS_CHANCE_MULTIPLIER_TARGET_CREATURE);
}
// Base hit chance from attacker and victim levels
int32 modHitChance = levelDiff < 3
+3 -3
View File
@@ -1235,9 +1235,6 @@ void GameEventMgr::ApplyNewEvent(uint16 event_id)
LOG_DEBUG("gameevent", "GameEvent {} \"{}\" started.", event_id, mGameEvent[event_id].description);
//! Run SAI scripts with SMART_EVENT_GAME_EVENT_END
RunSmartAIScripts(event_id, true);
// spawn positive event tagget objects
GameEventSpawn(event_id);
// un-spawn negative event tagged objects
@@ -1255,6 +1252,9 @@ void GameEventMgr::ApplyNewEvent(uint16 event_id)
// update bg holiday
UpdateBattlegroundSettings();
//! Run SAI scripts with SMART_EVENT_GAME_EVENT_START
RunSmartAIScripts(event_id, true);
// If event's worldstate is 0, it means the event hasn't been started yet. In that case, reset seasonal quests.
// When event ends (if it expires or if it's stopped via commands) worldstate will be set to 0 again, ready for another seasonal quest reset.
if (sWorld->getWorldState(event_id) == 0)
+3 -1
View File
@@ -9246,6 +9246,7 @@ void ObjectMgr::LoadBroadcastTextLocales()
return;
}
uint32 locales_count = 0;
do
{
Field* fields = result->Fetch();
@@ -9265,9 +9266,10 @@ void ObjectMgr::LoadBroadcastTextLocales()
AddLocaleString(fields[2].Get<std::string>(), locale, bct->second.MaleText);
AddLocaleString(fields[3].Get<std::string>(), locale, bct->second.FemaleText);
locales_count++;
} while (result->NextRow());
LOG_INFO("server.loading", ">> Loaded {} Broadcast Text Locales in {} ms", uint32(_broadcastTextStore.size()), GetMSTimeDiffToNow(oldMSTime));
LOG_INFO("server.loading", ">> Loaded {} Broadcast Text Locales in {} ms", locales_count, GetMSTimeDiffToNow(oldMSTime));
LOG_INFO("server.loading", " ");
}
+8
View File
@@ -6377,6 +6377,14 @@ SpellCastResult Spell::CheckCast(bool strict)
}
break;
}
case SPELL_AURA_MOD_SHAPESHIFT:
{
if (m_caster && m_caster->HasAura(23397)) // Nefarian Class Call (Warrior): Berserk -- Nefertum: I don't really like this but I didn't find another way.
{
return SPELL_FAILED_NOT_SHAPESHIFT;
}
break;
}
default:
break;
}
+13
View File
@@ -1590,6 +1590,19 @@ void Spell::EffectHeal(SpellEffIndex /*effIndex*/)
addhealth = unitTarget->SpellHealingBonusTaken(caster, m_spellInfo, addhealth, HEAL);
}
// Implemented this way as there is no other way to do it currently (that I know :P)...
if (caster->ToPlayer() && caster->ToPlayer()->HasAura(23401)) // Nefarian Corrupted Healing (priest)
{
if (m_spellInfo->Effects[EFFECT_0].ApplyAuraName != SPELL_AURA_PERIODIC_HEAL ||
m_spellInfo->Effects[EFFECT_1].ApplyAuraName != SPELL_AURA_PERIODIC_HEAL ||
m_spellInfo->Effects[EFFECT_2].ApplyAuraName != SPELL_AURA_PERIODIC_HEAL)
{
m_damage = 0;
caster->CastSpell(unitTarget, 23402, false); // Nefarian Corrupted Healing Periodic Damage effect.
return;
}
}
m_damage -= addhealth;
}
}
@@ -4154,6 +4154,20 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->Effects[EFFECT_1].SpellClassMask[1] = 0x00020000;
});
// Nefarian: Shadowbolt, Shadow Command
ApplySpellFix({ 22667, 22677 }, [](SpellInfo* spellInfo)
{
spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(152); // 150 yards
});
// Shadowbolt Volley
ApplySpellFix({ 22665 }, [](SpellInfo* spellInfo)
{
spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(152); // 150 yards
spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(41); // 150 yards
spellInfo->AttributesEx2 |= SPELL_ATTR2_IGNORE_LINE_OF_SIGHT;
});
// Manastorm
ApplySpellFix({ 21097 }, [](SpellInfo* spellInfo)
{
@@ -4180,6 +4194,12 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->AuraInterruptFlags |= AURA_INTERRUPT_FLAG_CHANGE_MAP;
});
// Improved Blessing Protection (Nefarian Class Call)
ApplySpellFix({ 23415 }, [](SpellInfo* spellInfo)
{
spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_DEST_TARGET_ENEMY);
});
// Bestial Wrath
ApplySpellFix({ 19574 }, [](SpellInfo* spellInfo)
{
+1
View File
@@ -173,6 +173,7 @@ enum WorldBoolConfigs
CONFIG_REALM_LOGIN_ENABLED,
CONFIG_PLAYER_SETTINGS_ENABLED,
CONFIG_ALLOW_JOIN_BG_AND_LFG,
CONFIG_MISS_CHANCE_MULTIPLIER_ONLY_FOR_PLAYERS,
BOOL_CONFIG_VALUE_COUNT
};
+3 -2
View File
@@ -572,8 +572,9 @@ void World::LoadConfigSettings(bool reload)
rate_values[RATE_ARENA_POINTS] = sConfigMgr->GetOption<float>("Rate.ArenaPoints", 1.0f);
rate_values[RATE_INSTANCE_RESET_TIME] = sConfigMgr->GetOption<float>("Rate.InstanceResetTime", 1.0f);
rate_values[RATE_MISS_CHANCE_MULTIPLIER_TARGET_CREATURE] = sConfigMgr->GetOption<float>("Rate.MissChanceMultiplier.TargetCreature", 11.0f);
rate_values[RATE_MISS_CHANCE_MULTIPLIER_TARGET_PLAYER] = sConfigMgr->GetOption<float>("Rate.MissChanceMultiplier.TargetPlayer", 7.0f);
rate_values[RATE_MISS_CHANCE_MULTIPLIER_TARGET_CREATURE] = sConfigMgr->GetOption<float>("Rate.MissChanceMultiplier.TargetCreature", 11.0f);
rate_values[RATE_MISS_CHANCE_MULTIPLIER_TARGET_PLAYER] = sConfigMgr->GetOption<float>("Rate.MissChanceMultiplier.TargetPlayer", 7.0f);
m_bool_configs[CONFIG_MISS_CHANCE_MULTIPLIER_ONLY_FOR_PLAYERS] = sConfigMgr->GetOption<bool>("Rate.MissChanceMultiplier.OnlyAffectsPlayer", false);
rate_values[RATE_TALENT] = sConfigMgr->GetOption<float>("Rate.Talent", 1.0f);
if (rate_values[RATE_TALENT] < 0.0f)
@@ -15,6 +15,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "BattlegroundAV.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
@@ -58,6 +59,11 @@ enum Events
EVENT_CHECK_RESET = 6
};
enum Factions
{
FACTION_AV_ALLIANCE = 1534
};
struct SpellPair
{
uint32 npcEntry;
@@ -104,6 +110,46 @@ public:
Reset();
}
void AttackStart(Unit* victim) override
{
ScriptedAI::AttackStart(victim);
// Boss should attack as well
if (BattlegroundMap* bgMap = me->GetMap()->ToBattlegroundMap())
{
if (Battleground* bg = bgMap->GetBG())
{
if (Creature* mainBoss = bg->GetBGCreature((me->GetFaction() == FACTION_AV_ALLIANCE ? AV_CPLACE_A_BOSS : AV_CPLACE_H_BOSS)))
{
if (mainBoss->IsAIEnabled && !mainBoss->IsInCombat())
{
mainBoss->AI()->AttackStart(victim);
}
}
}
}
}
void EnterEvadeMode() override
{
ScriptedAI::EnterEvadeMode();
// Evade boss
if (BattlegroundMap* bgMap = me->GetMap()->ToBattlegroundMap())
{
if (Battleground* bg = bgMap->GetBG())
{
if (Creature* mainBoss = bg->GetBGCreature((me->GetFaction() == FACTION_AV_ALLIANCE ? AV_CPLACE_A_BOSS : AV_CPLACE_H_BOSS)))
{
if (mainBoss->IsAIEnabled && !mainBoss->IsInEvadeMode())
{
mainBoss->AI()->EnterEvadeMode();
}
}
}
}
}
void UpdateAI(uint32 diff) override
{
// I have a feeling this isn't blizzlike, but owell, I'm only passing by and cleaning up.
@@ -15,6 +15,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "BattlegroundAV.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
@@ -64,7 +65,7 @@ public:
YellTimer = urand(20 * IN_MILLISECONDS, 30 * IN_MILLISECONDS); //20 to 30 seconds
}
void EnterCombat(Unit* /*who*/) override
void EnterCombat(Unit* /*victim*/) override
{
Talk(YELL_AGGRO);
}
@@ -75,6 +76,52 @@ public:
Talk(YELL_RESPAWN);
}
void AttackStart(Unit* victim) override
{
ScriptedAI::AttackStart(victim);
// Mini bosses should attack as well
if (BattlegroundMap* bgMap = me->GetMap()->ToBattlegroundMap())
{
if (Battleground* bg = bgMap->GetBG())
{
for (uint8 i = AV_CPLACE_H_MARSHAL_ICE; i <= AV_CPLACE_H_MARSHAL_WTOWER; ++i)
{
if (Creature* marshall = bg->GetBGCreature(i))
{
if (marshall->IsAIEnabled && !marshall->IsInCombat())
{
marshall->AI()->AttackStart(victim);
}
}
}
}
}
}
void EnterEvadeMode() override
{
ScriptedAI::EnterEvadeMode();
// Evade mini bosses
if (BattlegroundMap* bgMap = me->GetMap()->ToBattlegroundMap())
{
if (Battleground* bg = bgMap->GetBG())
{
for (uint8 i = AV_CPLACE_H_MARSHAL_ICE; i <= AV_CPLACE_H_MARSHAL_WTOWER; ++i)
{
if (Creature* marshall = bg->GetBGCreature(i))
{
if (marshall->IsAIEnabled && !marshall->IsInEvadeMode())
{
marshall->AI()->EnterEvadeMode();
}
}
}
}
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
@@ -15,6 +15,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "BattlegroundAV.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
@@ -59,11 +60,57 @@ public:
YellTimer = urand(20 * IN_MILLISECONDS, 30 * IN_MILLISECONDS);
}
void EnterCombat(Unit* /*who*/) override
void EnterCombat(Unit* /*victim*/) override
{
Talk(YELL_AGGRO);
}
void AttackStart(Unit* victim) override
{
ScriptedAI::AttackStart(victim);
// Mini bosses should attack as well
if (BattlegroundMap* bgMap = me->GetMap()->ToBattlegroundMap())
{
if (Battleground* bg = bgMap->GetBG())
{
for (uint8 i = AV_CPLACE_A_MARSHAL_SOUTH; i <= AV_CPLACE_A_MARSHAL_STONE; ++i)
{
if (Creature* marshall = bg->GetBGCreature(i))
{
if (marshall->IsAIEnabled && !marshall->IsInCombat())
{
marshall->AI()->AttackStart(victim);
}
}
}
}
}
}
void EnterEvadeMode() override
{
ScriptedAI::EnterEvadeMode();
// Evade mini bosses
if (BattlegroundMap* bgMap = me->GetMap()->ToBattlegroundMap())
{
if (Battleground* bg = bgMap->GetBG())
{
for (uint8 i = AV_CPLACE_A_MARSHAL_SOUTH; i <= AV_CPLACE_A_MARSHAL_STONE; ++i)
{
if (Creature* marshall = bg->GetBGCreature(i))
{
if (marshall->IsAIEnabled && !marshall->IsInEvadeMode())
{
marshall->AI()->EnterEvadeMode();
}
}
}
}
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
@@ -99,4 +99,6 @@ inline AI* GetBlackwingLairAI(T* obj)
return GetInstanceAI<AI>(obj, BWLScriptName);
}
#define RegisterBlackwingLairCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetBlackwingLairAI)
#endif
@@ -42,6 +42,21 @@ public:
{
boss_ebonrocAI(Creature* creature) : BossAI(creature, DATA_EBONROC) { }
void MovementInform(uint32 type, uint32 id) override
{
if (type != WAYPOINT_MOTION_TYPE || id != 12)
{
return;
}
me->GetMotionMaster()->MoveRandom(10.f);
me->m_Events.AddEventAtOffset([this]()
{
me->GetMotionMaster()->Initialize();
}, 15s);
}
void EnterCombat(Unit* who) override
{
BossAI::EnterCombat(who);
File diff suppressed because it is too large Load Diff
@@ -42,10 +42,10 @@ enum Gossip
enum Spells
{
SPELL_ESSENCEOFTHERED = 23513,
SPELL_FLAMEBREATH = 23461,
SPELL_FIRENOVA = 23462,
SPELL_TAILSWIPE = 15847,
SPELL_ESSENCE_OF_THE_RED = 23513,
SPELL_FLAME_BREATH = 23461,
SPELL_FIRE_NOVA = 23462,
SPELL_TAIL_SWEEP = 15847,
SPELL_CLEAVE = 19983, //Chain cleave is most likely named something different and contains a dummy effect
SPELL_NEFARIUS_CORRUPTION = 23642,
SPELL_RED_LIGHTNING = 19484,
@@ -64,12 +64,11 @@ enum Events
EVENT_SPEECH_5 = 5,
EVENT_SPEECH_6 = 6,
EVENT_SPEECH_7 = 7,
EVENT_ESSENCEOFTHERED = 8,
EVENT_FLAMEBREATH = 9,
EVENT_FIRENOVA = 10,
EVENT_TAILSWIPE = 11,
EVENT_CLEAVE = 12,
EVENT_BURNINGADRENALINE = 13,
EVENT_FLAME_BREATH = 8,
EVENT_FIRE_NOVA = 9,
EVENT_TAIL_SWEEP = 10,
EVENT_CLEAVE = 11,
EVENT_BURNING_ADRENALINE = 12,
};
class boss_vaelastrasz : public CreatureScript
@@ -119,15 +118,15 @@ public:
{
BossAI::EnterCombat(victim);
DoCast(me, SPELL_ESSENCEOFTHERED);
DoCastAOE(SPELL_ESSENCE_OF_THE_RED);
// now drop damage requirement to be able to take loot
me->ResetPlayerDamageReq();
events.ScheduleEvent(EVENT_CLEAVE, 10000);
events.ScheduleEvent(EVENT_FLAMEBREATH, 15000);
events.ScheduleEvent(EVENT_FIRENOVA, 20000);
events.ScheduleEvent(EVENT_TAILSWIPE, 11000);
events.ScheduleEvent(EVENT_BURNINGADRENALINE, 15000);
events.ScheduleEvent(EVENT_FLAME_BREATH, 15000);
events.ScheduleEvent(EVENT_FIRE_NOVA, 20000);
events.ScheduleEvent(EVENT_TAIL_SWEEP, 11000);
events.ScheduleEvent(EVENT_BURNING_ADRENALINE, 15000);
}
void BeginSpeech(Unit* target)
@@ -215,23 +214,19 @@ public:
events.ScheduleEvent(EVENT_CLEAVE, 15000);
DoCastVictim(SPELL_CLEAVE);
break;
case EVENT_FLAMEBREATH:
DoCastVictim(SPELL_FLAMEBREATH);
events.ScheduleEvent(EVENT_FLAMEBREATH, 8000, 14000);
case EVENT_FLAME_BREATH:
DoCastVictim(SPELL_FLAME_BREATH);
events.ScheduleEvent(EVENT_FLAME_BREATH, 8000, 14000);
break;
case EVENT_FIRENOVA:
DoCastVictim(SPELL_FIRENOVA);
events.ScheduleEvent(EVENT_FIRENOVA, 15000);
case EVENT_FIRE_NOVA:
DoCastVictim(SPELL_FIRE_NOVA);
events.ScheduleEvent(EVENT_FIRE_NOVA, 15000);
break;
case EVENT_TAILSWIPE:
//Only cast if we are behind
/*if (!me->HasInArc(M_PI, me->GetVictim()))
{
DoCast(me->GetVictim(), SPELL_TAILSWIPE);
}*/
events.ScheduleEvent(EVENT_TAILSWIPE, 15000);
case EVENT_TAIL_SWEEP:
DoCastAOE(SPELL_TAIL_SWEEP);
events.ScheduleEvent(EVENT_TAIL_SWEEP, 15000);
break;
case EVENT_BURNINGADRENALINE:
case EVENT_BURNING_ADRENALINE:
{
if (_burningAdrenalineCast < 2) // It's better to use TaskScheduler for this, but zzz
{
@@ -249,7 +244,7 @@ public:
me->CastSpell(me->GetVictim(), SPELL_BURNING_ADRENALINE, true);
_burningAdrenalineCast = 0;
}
events.ScheduleEvent(EVENT_BURNINGADRENALINE, 15000);
events.ScheduleEvent(EVENT_BURNING_ADRENALINE, 15000);
break;
}
}
@@ -257,11 +257,6 @@ public:
go->SetGoState(GO_STATE_ACTIVE);
}
if (pInstance && pInstance->GetData(TYPE_HODIR) != DONE)
{
pInstance->SetData(TYPE_SPAWN_HODIR_CACHE, 0);
}
// Reset helpers
if (!summons.size())
SpawnHelpers();
@@ -296,10 +291,13 @@ public:
switch (action)
{
case EVENT_FAIL_HM:
if (GameObject* go = me->FindNearestGameObject(GO_HODIR_CHEST_HARD, 500.0f))
if (pInstance)
{
go->SetGoState(GO_STATE_ACTIVE);
events.ScheduleEvent(EVENT_DESPAWN_CHEST, 3000);
if (GameObject* go = pInstance->instance->GetGameObject(pInstance->GetGuidData(GO_HODIR_CHEST_HARD)))
{
go->SetGoState(GO_STATE_ACTIVE);
events.ScheduleEvent(EVENT_DESPAWN_CHEST, 3000);
}
}
break;
}
@@ -425,7 +423,13 @@ public:
case EVENT_HARD_MODE_MISSED:
{
Talk(TEXT_HM_MISS);
me->CastSpell(me->FindNearestGameObject(GO_HODIR_CHEST_HARD, 400.0f), SPELL_SHATTER_CHEST, false);
if (pInstance)
{
if (GameObject* go = pInstance->instance->GetGameObject(pInstance->GetGuidData(GO_HODIR_CHEST_HARD)))
{
me->CastSpell(go, SPELL_SHATTER_CHEST, false);
}
}
}
break;
case EVENT_DESPAWN_CHEST:
@@ -1161,15 +1165,17 @@ public:
{
PrepareSpellScript(spell_hodir_shatter_chestSpellScript)
void destroyWinterCache()
void destroyWinterCache(SpellEffIndex effIndex)
{
PreventHitDefaultEffect(effIndex);
if (Unit* hodir = GetCaster())
hodir->GetAI()->DoAction(EVENT_FAIL_HM);
}
void Register() override
{
AfterHit += SpellHitFn(spell_hodir_shatter_chestSpellScript::destroyWinterCache);
OnEffectHit += SpellEffectFn(spell_hodir_shatter_chestSpellScript::destroyWinterCache, EFFECT_0, SPELL_EFFECT_TRIGGER_MISSILE);
};
};
@@ -138,7 +138,7 @@ public:
// Flame Leviathan
for (uint8 i = 0; i < 4; ++i)
m_leviathanTowers[i] = false;
m_leviathanTowers[i] = true;
_leviathanVehicles.clear();
m_unbrokenAchievement = 1;
@@ -214,75 +214,74 @@ public:
SetData(eventId, 0);
}
void SpawnHodirChests(int rd)
void SpawnHodirChests(Difficulty diff, Creature* hodir)
{
if (Creature* cr = instance->GetCreature(m_uiHodirGUID))
switch (diff)
{
switch (rd)
case RAID_DIFFICULTY_10MAN_NORMAL: // 10 man chest
{
case 0: // 10 man chest
if (!m_hodirNormalChest)
{
if (!m_hodirNormalChest)
if (GameObject* go = hodir->SummonGameObject(
GO_HODIR_CHEST_NORMAL,
normalChestPosition.GetPositionX(),
normalChestPosition.GetPositionY(),
normalChestPosition.GetPositionZ(),
normalChestPosition.GetOrientation(), 0, 0, 0, 0, 0))
{
if (GameObject* go = cr->SummonGameObject(
GO_HODIR_CHEST_NORMAL,
normalChestPosition.GetPositionX(),
normalChestPosition.GetPositionY(),
normalChestPosition.GetPositionZ(),
normalChestPosition.GetOrientation(), 0, 0, 0, 0, 0))
{
m_hodirNormalChest = go->GetGUID();
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
m_hodirNormalChest = go->GetGUID();
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
if (!m_hodirHardmodeChest)
{
if (GameObject* go = cr->SummonGameObject(
GO_HODIR_CHEST_HARD,
hardChestPosition.GetPositionX(),
hardChestPosition.GetPositionY(),
hardChestPosition.GetPositionZ(),
hardChestPosition.GetOrientation(), 0, 0, 0, 0, 0))
{
m_hodirHardmodeChest = go->GetGUID();
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
hmHodir = true;
}
}
break;
}
case 1: // 25 man chest
if (!m_hodirHardmodeChest)
{
if (!m_hodirNormalChest)
if (GameObject* go = hodir->SummonGameObject(
GO_HODIR_CHEST_HARD,
hardChestPosition.GetPositionX(),
hardChestPosition.GetPositionY(),
hardChestPosition.GetPositionZ(),
hardChestPosition.GetOrientation(), 0, 0, 0, 0, 0))
{
if (GameObject* go = cr->SummonGameObject(
GO_HODIR_CHEST_NORMAL_HERO,
normalChestPosition.GetPositionX(),
normalChestPosition.GetPositionY(),
normalChestPosition.GetPositionZ(),
normalChestPosition.GetOrientation(), 0, 0, 0, 0, 0))
{
m_hodirNormalChest = go->GetGUID();
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
m_hodirHardmodeChest = go->GetGUID();
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
hmHodir = true;
}
if (!m_hodirHardmodeChest)
{
if (GameObject* go = cr->SummonGameObject(
GO_HODIR_CHEST_HARD_HERO,
hardChestPosition.GetPositionX(),
hardChestPosition.GetPositionY(),
hardChestPosition.GetPositionZ(),
hardChestPosition.GetOrientation(), 0, 0, 0, 0, 0))
{
m_hodirHardmodeChest = go->GetGUID();
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
hmHodir = true;
}
}
break;
}
break;
}
case RAID_DIFFICULTY_25MAN_NORMAL: // 25 man chest
{
if (!m_hodirNormalChest)
{
if (GameObject* go = hodir->SummonGameObject(
GO_HODIR_CHEST_NORMAL_HERO,
normalChestPosition.GetPositionX(),
normalChestPosition.GetPositionY(),
normalChestPosition.GetPositionZ(),
normalChestPosition.GetOrientation(), 0, 0, 0, 0, 0))
{
m_hodirNormalChest = go->GetGUID();
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
}
if (!m_hodirHardmodeChest)
{
if (GameObject* go = hodir->SummonGameObject(
GO_HODIR_CHEST_HARD_HERO,
hardChestPosition.GetPositionX(),
hardChestPosition.GetPositionY(),
hardChestPosition.GetPositionZ(),
hardChestPosition.GetOrientation(), 0, 0, 0, 0, 0))
{
m_hodirHardmodeChest = go->GetGUID();
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
hmHodir = true;
}
}
break;
}
default:
break;
}
}
@@ -329,6 +328,7 @@ public:
break;
case NPC_HODIR:
m_uiHodirGUID = creature->GetGUID();
SpawnHodirChests(instance->GetDifficulty(), creature);
break;
case NPC_THORIM:
m_uiThorimGUID = creature->GetGUID();
@@ -690,11 +690,6 @@ public:
if (GetData(TYPE_HODIR) == DONE)
setChestsLootable(TYPE_HODIR);
break;
case TYPE_SPAWN_HODIR_CACHE:
// Is the difficulty 10 man(0) ? return 10 man : return 25 man;
SpawnHodirChests(m_difficulty == 0 ? 0 : 1);
break;
case TYPE_HODIR_HM_FAIL:
if (GameObject* go = instance->GetGameObject(m_hodirHardmodeChest))
{
@@ -909,10 +904,8 @@ public:
// Hodir chests
case GO_HODIR_CHEST_HARD:
case GO_HODIR_CHEST_HARD_HERO:
return m_hodirHardmodeChest;
case GO_HODIR_CHEST_NORMAL:
case GO_HODIR_CHEST_NORMAL_HERO:
return m_hodirNormalChest;
// Freya Elders
@@ -45,9 +45,8 @@ enum UlduarEncounters
TYPE_YOGGSARON = 12,
TYPE_ALGALON = 13,
TYPE_WATCHERS = 14,
TYPE_SPAWN_HODIR_CACHE = 15,
TYPE_HODIR_HM_FAIL = 16,
TYPE_WINTER_CACHE = 17,
TYPE_HODIR_HM_FAIL = 15,
TYPE_WINTER_CACHE = 16
};
enum UlduarData
@@ -2550,6 +2550,7 @@ Die.Command.Mode = 1
# Rate.MissChanceMultiplier.Creature
# Rate.MissChanceMultiplier.Player
# Rate.MissChanceMultiplier.OnlyAffectsPlayer
#
# Description: When the target is 3 or more level higher than the player,
# the chance to hit is determined by the formula: 94 - (levelDiff - 2) * Rate.MissChanceMultiplier
@@ -2557,15 +2558,19 @@ Die.Command.Mode = 1
#
# Note: this does not affect when the player is less than 3 levels different than the target,
# where this (linear) formula is used instead to calculate the hit chance: 96 - levelDiff.
# You can set Rate.MissChanceMultiplier.OnlyAffectsPlayer to 1 if you only want to affect the MissChance
# for player casters only. This way you won't be affecting creature missing chance.
#
# Example: if you want the chance to keep growing linearly, use 1.
#
# Default: Rate.MissChanceMultiplier.TargetCreature = 11
# Rate.MissChanceMultiplier.TargetPlayer = 7
# Rate.MissChanceMultiplier.OnlyAffectsPlayer = 0
#
Rate.MissChanceMultiplier.TargetCreature = 11
Rate.MissChanceMultiplier.TargetPlayer = 7
Rate.MissChanceMultiplier.OnlyAffectsPlayer = 0
#
###################################################################################################