Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2024-03-03 11:58:01 +08:00
59 changed files with 3523 additions and 450 deletions

View File

@@ -282,7 +282,13 @@ public:
handler->PSendSysMessage("Connection peak: %u.", connPeak);
handler->PSendSysMessage(LANG_UPTIME, secsToTimeString(GameTime::GetUptime().count()).c_str());
handler->PSendSysMessage("Update time diff: %ums, average: %ums.", sWorldUpdateTime.GetLastUpdateTime(), sWorldUpdateTime.GetAverageUpdateTime());
handler->PSendSysMessage("Update time diff: %ums. Last %d diffs summary:", sWorldUpdateTime.GetLastUpdateTime(), sWorldUpdateTime.GetDatasetSize());
handler->PSendSysMessage("- Mean: %ums", sWorldUpdateTime.GetAverageUpdateTime());
handler->PSendSysMessage("- Median: %ums", sWorldUpdateTime.GetPercentile(50));
handler->PSendSysMessage("- Percentiles (95, 99, max): %ums, %ums, %ums",
sWorldUpdateTime.GetPercentile(95),
sWorldUpdateTime.GetPercentile(99),
sWorldUpdateTime.GetPercentile(100));
//! Can't use sWorld->ShutdownMsg here in case of console command
if (sWorld->IsShuttingDown())

View File

@@ -45,7 +45,7 @@ struct boss_quartermaster_zigris : public BossAI
void Reset() override
{
_Reset();
SetCombatMovement(false);
me->SetCombatMovement(false);
_hasDrunkPotion = false;
}
@@ -120,11 +120,11 @@ struct boss_quartermaster_zigris : public BossAI
{
DoCastVictim(SPELL_SHOOT);
me->GetMotionMaster()->Clear();
SetCombatMovement(false);
me->SetCombatMovement(false);
}
else if (!me->IsWithinLOSInMap(me->GetVictim()))
{
SetCombatMovement(true);
me->SetCombatMovement(true);
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveChase(me->GetVictim());
}

View File

@@ -359,7 +359,7 @@ public:
Talk(SAY_GAMESBEGIN_2);
DoCast(me, SPELL_NEFARIANS_BARRIER);
SetCombatMovement(false);
me->SetCombatMovement(false);
me->SetImmuneToPC(false);
AttackStart(SelectTarget(SelectTargetMethod::Random, 0, 200.f, true));
events.ScheduleEvent(EVENT_SHADOWBLINK, 500ms);

View File

@@ -159,7 +159,7 @@ struct boss_dorothee : public ScriptedAI
{
boss_dorothee(Creature* creature) : ScriptedAI(creature)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
//this is kinda a big no-no. but it will prevent her from moving to chase targets. she should just cast her spells. in this case, since there is not really something to LOS her with or get out of range this would work. but a more elegant solution would be better
instance = creature->GetInstanceScript();

View File

@@ -123,7 +123,7 @@ struct boss_jeklik : public BossAI
me->SetDisableGravity(false);
me->SetReactState(REACT_PASSIVE);
BossAI::SetCombatMovement(false);
BossAI::me->SetCombatMovement(false);
batRidersCount = 0;
DoCastSelf(SPELL_GREEN_CHANNELING, true);
@@ -148,7 +148,7 @@ struct boss_jeklik : public BossAI
BossAI::PathEndReached(pathId);
me->SetDisableGravity(false);
SetCombatMovement(true);
me->SetCombatMovement(true);
me->SetReactState(REACT_AGGRESSIVE);
//

View File

@@ -2168,7 +2168,7 @@ public:
{
boss_blight_wormAI(Creature* creature) : ScriptedAI(creature)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
}
void Reset() override

View File

@@ -134,7 +134,7 @@ public:
{
npc_andorhal_towerAI(Creature* creature) : ScriptedAI(creature)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
}
void MoveInLineOfSight(Unit* who) override

View File

@@ -1411,7 +1411,7 @@ public:
{
alliance_riflemanAI(Creature* creature) : ScriptedAI(creature)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
}
uint32 ExplodeTimer;

View File

@@ -84,7 +84,7 @@ struct boss_ayamiss : public BossAI
void Reset() override
{
BossAI::Reset();
SetCombatMovement(false);
me->SetCombatMovement(false);
me->SetReactState(REACT_AGGRESSIVE);
ScheduleHealthCheckEvent(70, [&] {
@@ -127,7 +127,7 @@ struct boss_ayamiss : public BossAI
}
else if (type == WAYPOINT_MOTION_TYPE && id == POINT_GROUND)
{
SetCombatMovement(true);
me->SetCombatMovement(true);
me->SetDisableGravity(false);
me->m_Events.AddEventAtOffset([this]()

View File

@@ -188,7 +188,7 @@ struct npc_buru_egg : public ScriptedAI
npc_buru_egg(Creature* creature) : ScriptedAI(creature)
{
_instance = me->GetInstanceScript();
SetCombatMovement(false);
me->SetCombatMovement(false);
me->SetReactState(REACT_PASSIVE);
me->SetControlled(true, UNIT_STATE_STUNNED);
}

View File

@@ -147,7 +147,7 @@ struct boss_eye_of_cthun : public BossAI
{
boss_eye_of_cthun(Creature* creature) : BossAI(creature, DATA_CTHUN)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
me->m_SightDistance = 90.f;
}
@@ -377,7 +377,7 @@ struct boss_cthun : public BossAI
{
boss_cthun(Creature* creature) : BossAI(creature, DATA_CTHUN)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
}
void Reset() override
@@ -597,7 +597,7 @@ struct npc_eye_tentacle : public ScriptedAI
}
}
SetCombatMovement(false);
me->SetCombatMovement(false);
}
void JustDied(Unit* /*killer*/) override
@@ -651,7 +651,7 @@ struct npc_claw_tentacle : public ScriptedAI
{
npc_claw_tentacle(Creature* creature) : ScriptedAI(creature)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
if (Creature* portal = me->SummonCreature(NPC_SMALL_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN))
{
@@ -720,7 +720,7 @@ struct npc_giant_claw_tentacle : public ScriptedAI
{
npc_giant_claw_tentacle(Creature* creature) : ScriptedAI(creature)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
if (Creature* portal = me->SummonCreature(NPC_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN))
{
@@ -870,7 +870,7 @@ struct npc_giant_eye_tentacle : public ScriptedAI
{
npc_giant_eye_tentacle(Creature* creature) : ScriptedAI(creature)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
if (Creature* portal = me->SummonCreature(NPC_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN))
{

View File

@@ -106,7 +106,7 @@ struct boss_ouro : public BossAI
{
boss_ouro(Creature* creature) : BossAI(creature, DATA_OURO)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
me->SetControlled(true, UNIT_STATE_ROOT);
}

View File

@@ -366,7 +366,7 @@ struct npc_toxic_slime : public ScriptedAI
void InitializeAI() override
{
SetCombatMovement(false);
me->SetCombatMovement(false);
DoCastSelf(SPELL_TOXIN);
InstanceScript* instance = me->GetInstanceScript();

View File

@@ -99,7 +99,7 @@ public:
{
npc_tiger_matriarch_creditAI(Creature* creature) : ScriptedAI(creature)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
events.ScheduleEvent(EVENT_CHECK_SUMMON_AURA, 2s);
}

View File

@@ -235,7 +235,7 @@ struct npc_amanitar_mushrooms : public ScriptedAI
{
npc_amanitar_mushrooms(Creature* pCreature) : ScriptedAI(pCreature)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
//TODO: this prolly needs to be done in database
pCreature->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);

View File

@@ -295,7 +295,7 @@ struct boss_jedoga_shadowseeker : public BossAI
{
if (!ritualTriggered && me->HealthBelowPctDamaged(55, damage) && events.IsInPhase(PHASE_NORMAL))
{
SetCombatMovement(false);
me->SetCombatMovement(false);
me->InterruptNonMeleeSpells(false);
me->AttackStop();
me->SetReactState(REACT_PASSIVE);
@@ -368,7 +368,7 @@ struct boss_jedoga_shadowseeker : public BossAI
me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL);
me->RemoveAurasDueToSpell(SPELL_LIGHTNING_BOLTS);
me->RemoveAurasDueToSpell(SPELL_HOVER_FALL);
SetCombatMovement(true);
me->SetCombatMovement(true);
me->SetDisableGravity(false);
me->SetHover(false);

View File

@@ -606,14 +606,14 @@ struct boss_jormungarAI : public ScriptedAI
if( bIsStationary )
{
me->SetNativeDisplayId(_MODEL_MOBILE);
SetCombatMovement(true);
me->SetCombatMovement(true);
if( Unit* victim = me->GetVictim() )
me->GetMotionMaster()->MoveChase(victim);
}
else
{
me->SetNativeDisplayId(_MODEL_STATIONARY);
SetCombatMovement(false);
me->SetCombatMovement(false);
}
me->RemoveAurasDueToSpell(SPELL_SUBMERGE_0);
me->CastSpell(me, SPELL_EMERGE_0, false);
@@ -692,7 +692,7 @@ public:
_MODEL_STATIONARY = MODEL_ACIDMAW_STATIONARY;
_MODEL_MOBILE = MODEL_ACIDMAW_MOBILE;
_TYPE_OTHER = TYPE_DREADSCALE;
SetCombatMovement(false);
me->SetCombatMovement(false);
}
};

View File

@@ -1525,7 +1525,7 @@ public:
{
boss_yoggsaron_crusher_tentacleAI(Creature* pCreature) : ScriptedAI(pCreature)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
me->CastSpell(me, SPELL_CRUSH, true);
me->CastSpell(me, SPELL_FOCUSED_ANGER, true);
me->CastSpell(me, SPELL_DIMINISH_POWER, false);
@@ -1587,7 +1587,7 @@ public:
{
boss_yoggsaron_corruptor_tentacleAI(Creature* pCreature) : ScriptedAI(pCreature)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
}
void DoAction(int32 param) override
@@ -1644,7 +1644,7 @@ public:
{
boss_yoggsaron_constrictor_tentacleAI(Creature* pCreature) : ScriptedAI(pCreature)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
_checkTimer = 1;
_playerGUID.Clear();
}

View File

@@ -1049,7 +1049,7 @@ public:
{
npc_warmage_coldarraAI(Creature* creature) : ScriptedAI(creature)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
}
uint32 m_uiTimer; //Timer until recast

View File

@@ -147,7 +147,7 @@ struct npc_warmage_violetstand : public ScriptedAI
{
npc_warmage_violetstand(Creature* creature) : ScriptedAI(creature)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
}
ObjectGuid targetGUID;

View File

@@ -1532,7 +1532,7 @@ public:
{
npc_guardian_pavilionAI(Creature* creature) : ScriptedAI(creature)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
}
void MoveInLineOfSight(Unit* who) override
@@ -1596,7 +1596,7 @@ public:
{
npc_tournament_training_dummyAI(Creature* creature) : ScriptedAI(creature)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true);
}
@@ -1816,7 +1816,7 @@ public:
PhaseCount = 0;
Summons.DespawnAll();
SetCombatMovement(false);
me->SetCombatMovement(false);
}
EventMap events;

View File

@@ -57,7 +57,7 @@ struct boss_murmur : public BossAI
{
boss_murmur(Creature* creature) : BossAI(creature, DATA_MURMUR)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);

View File

@@ -149,6 +149,23 @@ class spell_morogrim_tidewalker_watery_grave : public SpellScript
return true;
}
void FilterTargets(std::list<WorldObject*>& targets)
{
uint8 maxSize = 4;
Unit* caster = GetCaster();
targets.remove_if([caster](WorldObject const* target) -> bool
{
// Should not target current victim.
return caster->GetVictim() == target;
});
if (targets.size() > maxSize)
{
Acore::Containers::RandomResize(targets, maxSize);
}
}
void HandleDummy(SpellEffIndex effIndex)
{
PreventHitDefaultEffect(effIndex);
@@ -159,6 +176,7 @@ class spell_morogrim_tidewalker_watery_grave : public SpellScript
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_morogrim_tidewalker_watery_grave::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
OnEffectHitTarget += SpellEffectFn(spell_morogrim_tidewalker_watery_grave::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}

View File

@@ -98,7 +98,7 @@ struct boss_ahune : public ScriptedAI
{
boss_ahune(Creature* c) : ScriptedAI(c), summons(me)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
SetEquipmentSlots(false, 54806, EQUIP_UNEQUIP, EQUIP_UNEQUIP);
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
InvokerGUID.Clear();

View File

@@ -41,7 +41,7 @@ struct boss_omor_the_unscarred : public BossAI
{
boss_omor_the_unscarred(Creature* creature) : BossAI(creature, DATA_OMOR_THE_UNSCARRED)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);

View File

@@ -69,7 +69,8 @@ enum Misc
EVENT_SPELL_BERSERK = 3,
EVENT_MOVE_TO_PHASE_2 = 4,
EVENT_FINISH_DIVE = 5
EVENT_FINISH_DIVE = 5,
EVENT_INVISIBLE = 6
};
enum GroupAlar
@@ -89,7 +90,7 @@ struct boss_alar : public BossAI
boss_alar(Creature* creature) : BossAI(creature, DATA_ALAR)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
}
void JustReachedHome() override
@@ -172,22 +173,25 @@ struct boss_alar : public BossAI
if (damage >= me->GetHealth() && _platform < POINT_MIDDLE)
{
damage = 0;
me->SetReactState(REACT_PASSIVE);
scheduler.CancelAll();
me->CastStop();
me->SetHealth(me->GetMaxHealth());
DoCastSelf(SPELL_EMBER_BLAST, true); //spellscript doesn't trigger
DoCastSelf(SPELL_EMBER_BLAST, true);
PretendToDie(me);
ScheduleUniqueTimedEvent(1s, [&]{
me->SetVisible(false);
}, EVENT_INVISIBLE);
ScheduleUniqueTimedEvent(8s, [&]{
me->SetPosition(alarPoints[POINT_MIDDLE]);
}, EVENT_RELOCATE_MIDDLE);
ScheduleUniqueTimedEvent(12s, [&]
{
me->SetStandState(UNIT_STAND_STATE_STAND);
me->SetVisible(true);
DoCastSelf(SPELL_CLEAR_ALL_DEBUFFS, true);
DoCastSelf(SPELL_REBIRTH_PHASE2);
}, EVENT_MOVE_TO_PHASE_2);
ScheduleUniqueTimedEvent(16001ms, [&]{
me->SetHealth(me->GetMaxHealth());
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
_platform = POINT_MIDDLE;
me->GetMotionMaster()->MoveChase(me->GetVictim());
ScheduleAbilities();
@@ -195,6 +199,18 @@ struct boss_alar : public BossAI
}
}
void PretendToDie(Creature* creature)
{
scheduler.CancelAll();
creature->InterruptNonMeleeSpells(true);
creature->RemoveAllAuras();
creature->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
creature->SetReactState(REACT_PASSIVE);
creature->GetMotionMaster()->MovementExpired(false);
creature->GetMotionMaster()->MoveIdle();
creature->SetStandState(UNIT_STAND_STATE_DEAD);
}
void ScheduleAbilities()
{
ScheduleTimedEvent(57s, [&]
@@ -394,37 +410,6 @@ class spell_alar_ember_blast : public SpellScript
}
};
class spell_alar_ember_blast_death : public AuraScript
{
PrepareAuraScript(spell_alar_ember_blast_death);
void OnApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
PreventDefaultAction(); // xinef: prevent default action after change that invisibility in instances is executed instantly even for creatures
Unit* target = GetTarget();
InvisibilityType type = InvisibilityType(aurEff->GetMiscValue());
target->m_invisibility.AddFlag(type);
target->m_invisibility.AddValue(type, aurEff->GetAmount());
GetUnitOwner()->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
GetUnitOwner()->SetStandState(UNIT_STAND_STATE_DEAD);
GetUnitOwner()->m_last_notify_position.Relocate(0.0f, 0.0f, 0.0f);
GetUnitOwner()->m_delayed_unit_relocation_timer = 1000;
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
GetUnitOwner()->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
GetUnitOwner()->SetStandState(UNIT_STAND_STATE_STAND);
}
void Register() override
{
OnEffectApply += AuraEffectApplyFn(spell_alar_ember_blast_death::OnApply, EFFECT_2, SPELL_AURA_MOD_INVISIBILITY, AURA_EFFECT_HANDLE_REAL);
OnEffectRemove += AuraEffectRemoveFn(spell_alar_ember_blast_death::OnRemove, EFFECT_2, SPELL_AURA_MOD_INVISIBILITY, AURA_EFFECT_HANDLE_REAL);
}
};
class spell_alar_dive_bomb : public AuraScript
{
PrepareAuraScript(spell_alar_dive_bomb);
@@ -446,7 +431,6 @@ void AddSC_boss_alar()
RegisterTheEyeAI(boss_alar);
RegisterSpellScript(spell_alar_flame_quills);
RegisterSpellScript(spell_alar_ember_blast);
RegisterSpellScript(spell_alar_ember_blast_death);
RegisterSpellScript(spell_alar_dive_bomb);
}

View File

@@ -145,6 +145,8 @@ enum Misc
DATA_RESURRECT_CAST = 1,
NPC_WORLD_TRIGGER = 19871,
NPC_NETHER_VAPOR = 21002,
NPC_NETHERSTRAND_LONGBOW = 21268,
NPC_STAFF_OF_DISINTEGRATION = 21274,
PHASE_NONE = 0,
PHASE_SINGLE_ADVISOR = 1,
@@ -207,14 +209,16 @@ enum KaelActions
ACTION_START_SANGUINAR = 0,
ACTION_START_CAPERNIAN = 1,
ACTION_START_TELONICUS = 2,
ACTION_START_WEAPONS = 3
ACTION_START_WEAPONS = 3,
ACTION_PROGRESS_PHASE_CHECK = 4
};
enum SpellGroups
{
GROUP_PYROBLAST = 0,
GROUP_SHOCK_BARRIER = 1,
GROUP_NETHER_BEAM = 2
GROUP_PROGRESS_PHASE = 0,
GROUP_PYROBLAST = 1,
GROUP_SHOCK_BARRIER = 2,
GROUP_NETHER_BEAM = 3
};
const Position triggersPos[6] =
@@ -253,9 +257,12 @@ struct boss_kaelthas : public BossAI
summons.DoForAllSummons([&](WorldObject* summon){
if (Creature* summonedCreature = summon->ToCreature())
{
summonedCreature->SetReactState(REACT_PASSIVE);
summonedCreature->setDeathState(DeathState::JustRespawned);
summonedCreature->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
if (summonedCreature->GetEntry() >= NPC_LORD_SANGUINAR && summonedCreature->GetEntry() <= NPC_THALADRED)
{
summonedCreature->SetReactState(REACT_PASSIVE);
summonedCreature->setDeathState(DeathState::JustRespawned);
summonedCreature->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
}
}
});
}
@@ -382,11 +389,53 @@ struct boss_kaelthas : public BossAI
}
}
});
ScheduleUniqueTimedEvent(2min, [&]{
scheduler.Schedule(2min, GROUP_PROGRESS_PHASE, [this](TaskContext)
{
PhaseAllAdvisorsExecute();
}, EVENT_PREFIGHT_PHASE61);
});
}, EVENT_PREFIGHT_PHASE52);
break;
case ACTION_PROGRESS_PHASE_CHECK:
if (_phase == PHASE_WEAPONS)
{
bool aliveWeapon = false;
summons.DoForAllSummons([&aliveWeapon](WorldObject* summon)
{
if (Creature* summonedCreature = summon->ToCreature())
{
if (summonedCreature->IsAlive())
{
if (summonedCreature->GetEntry() >= NPC_NETHERSTRAND_LONGBOW && summonedCreature->GetEntry() <= NPC_STAFF_OF_DISINTEGRATION)
{
aliveWeapon = true;
return;
}
}
}
});
if (!aliveWeapon)
PhaseAllAdvisorsExecute();
}
else if (_phase == PHASE_ALL_ADVISORS)
{
bool advisorAlive = false;
summons.DoForAllSummons([&advisorAlive](WorldObject* summon)
{
if (Creature* summonedCreature = summon->ToCreature())
{
if (summonedCreature->IsAlive())
{
if (summonedCreature->GetEntry() >= NPC_LORD_SANGUINAR && summonedCreature->GetEntry() <= NPC_THALADRED)
{
advisorAlive = true;
return;
}
}
}
});
if (!advisorAlive)
PhaseKaelExecute();
}
default:
break;
}
@@ -629,17 +678,7 @@ struct boss_kaelthas : public BossAI
void PhaseAllAdvisorsExecute()
{
//remove all weapons so they don't get revived
summons.DoForAllSummons([&](WorldObject* summon)
{
if (Creature* summonedCreature = summon->ToCreature())
{
if (summonedCreature->GetEntry() >= 21268 && summonedCreature->GetEntry() <= 21274)
{
summonedCreature->DespawnOrUnsummon();
}
}
});
scheduler.CancelGroup(GROUP_PROGRESS_PHASE);
_phase = PHASE_ALL_ADVISORS;
Talk(SAY_PHASE3_ADVANCE);
ScheduleUniqueTimedEvent(6s, [&]{
@@ -662,9 +701,10 @@ struct boss_kaelthas : public BossAI
}
}
});
ScheduleUniqueTimedEvent(3min, [&]{
scheduler.Schedule(3min, GROUP_PROGRESS_PHASE, [this](TaskContext)
{
PhaseKaelExecute();
}, EVENT_PREFIGHT_PHASE71);
});
}, EVENT_PREFIGHT_PHASE63);
}
@@ -778,15 +818,16 @@ struct npc_lord_sanguinar : public ScriptedAI
void JustDied(Unit* /*killer*/) override
{
if (!_hasDied)
if (Creature* kael = _instance->GetCreature(DATA_KAELTHAS))
{
Talk(SAY_SANGUINAR_DEATH);
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
if (Creature* kael = _instance->GetCreature(DATA_KAELTHAS))
kael->AI()->DoAction(ACTION_PROGRESS_PHASE_CHECK);
if (!_hasDied)
{
Talk(SAY_SANGUINAR_DEATH);
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
kael->AI()->DoAction(ACTION_START_CAPERNIAN);
_hasDied = true;
}
_hasDied = true;
}
}
@@ -830,7 +871,7 @@ struct npc_capernian : public ScriptedAI
{
if (me->Attack(who, false))
{
me->GetMotionMaster()->MoveChase(who, 45.0f, 0);
me->GetMotionMaster()->MoveChase(who, 30.0f, 0);
me->AddThreat(who, 0.0f);
}
}
@@ -850,7 +891,7 @@ struct npc_capernian : public ScriptedAI
}
else
{
me->GetMotionMaster()->MoveChase(me->GetVictim(), 45.0f);
me->GetMotionMaster()->MoveChase(me->GetVictim(), 30.0f);
DoCastVictim(SPELL_CAPERNIAN_FIREBALL);
}
@@ -865,15 +906,16 @@ struct npc_capernian : public ScriptedAI
void JustDied(Unit* /*killer*/) override
{
if (!_hasDied)
if (Creature* kael = _instance->GetCreature(DATA_KAELTHAS))
{
Talk(SAY_CAPERNIAN_DEATH);
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
if (Creature* kael = _instance->GetCreature(DATA_KAELTHAS))
kael->AI()->DoAction(ACTION_PROGRESS_PHASE_CHECK);
if (!_hasDied)
{
Talk(SAY_CAPERNIAN_DEATH);
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
kael->AI()->DoAction(ACTION_START_TELONICUS);
_hasDied = true;
}
_hasDied = true;
}
}
@@ -927,15 +969,16 @@ struct npc_telonicus : public ScriptedAI
void JustDied(Unit* /*killer*/) override
{
if (!_hasDied)
if (Creature* kael = _instance->GetCreature(DATA_KAELTHAS))
{
Talk(SAY_TELONICUS_DEATH);
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
if (Creature* kael = _instance->GetCreature(DATA_KAELTHAS))
kael->AI()->DoAction(ACTION_PROGRESS_PHASE_CHECK);
if (!_hasDied)
{
Talk(SAY_TELONICUS_DEATH);
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
kael->AI()->DoAction(ACTION_START_WEAPONS);
_hasDied = true;
}
_hasDied = true;
}
}
@@ -1011,15 +1054,16 @@ struct npc_thaladred : public ScriptedAI
void JustDied(Unit* /*killer*/) override
{
if (!_hasDied)
if (Creature* kael = _instance->GetCreature(DATA_KAELTHAS))
{
Talk(SAY_THALADRED_DEATH);
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
if (Creature* kael = _instance->GetCreature(DATA_KAELTHAS))
kael->AI()->DoAction(ACTION_PROGRESS_PHASE_CHECK);
if (!_hasDied)
{
Talk(SAY_THALADRED_DEATH);
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
kael->AI()->DoAction(ACTION_START_SANGUINAR);
_hasDied = true;
}
_hasDied = true;
}
}
@@ -1040,200 +1084,123 @@ private:
bool _hasDied;
};
class spell_kaelthas_kael_phase_two : public SpellScriptLoader
class spell_kaelthas_kael_phase_two : public SpellScript
{
public:
spell_kaelthas_kael_phase_two() : SpellScriptLoader("spell_kaelthas_kael_phase_two") { }
PrepareSpellScript(spell_kaelthas_kael_phase_two);
class spell_kaelthas_kael_phase_two_SpellScript : public SpellScript
bool Load() override
{
PrepareSpellScript(spell_kaelthas_kael_phase_two_SpellScript);
if (GetCaster()->GetTypeId() == TYPEID_UNIT)
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
if (Creature* kael = instance->GetCreature(DATA_KAELTHAS))
kael->AI()->SummonedCreatureDies(GetCaster()->ToCreature(), nullptr);
return true;
}
bool Load() override
{
if (GetCaster()->GetTypeId() == TYPEID_UNIT)
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
if (Creature* kael = ObjectAccessor::GetCreature(*GetCaster(), instance->GetGuidData(NPC_KAELTHAS)))
kael->AI()->SummonedCreatureDies(GetCaster()->ToCreature(), nullptr);
return true;
}
void Register() override
{
}
};
SpellScript* GetSpellScript() const override
void Register() override
{
return new spell_kaelthas_kael_phase_two_SpellScript();
}
};
class spell_kaelthas_remote_toy : public SpellScriptLoader
class spell_kaelthas_remote_toy : public AuraScript
{
public:
spell_kaelthas_remote_toy() : SpellScriptLoader("spell_kaelthas_remote_toy") { }
PrepareAuraScript(spell_kaelthas_remote_toy);
class spell_kaelthas_remote_toy_AuraScript : public AuraScript
void HandlePeriodic(AuraEffect const* /*aurEff*/)
{
PrepareAuraScript(spell_kaelthas_remote_toy_AuraScript);
PreventDefaultAction();
if (roll_chance_i(66))
GetUnitOwner()->CastSpell(GetUnitOwner(), SPELL_REMOTE_TOY_STUN, true);
}
void HandlePeriodic(AuraEffect const* /*aurEff*/)
{
PreventDefaultAction();
if (roll_chance_i(66))
GetUnitOwner()->CastSpell(GetUnitOwner(), SPELL_REMOTE_TOY_STUN, true);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_kaelthas_remote_toy_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
AuraScript* GetAuraScript() const override
void Register() override
{
return new spell_kaelthas_remote_toy_AuraScript();
OnEffectPeriodic += AuraEffectPeriodicFn(spell_kaelthas_remote_toy::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
class spell_kaelthas_summon_weapons : public SpellScriptLoader
class spell_kaelthas_summon_weapons : public SpellScript
{
public:
spell_kaelthas_summon_weapons() : SpellScriptLoader("spell_kaelthas_summon_weapons") { }
PrepareSpellScript(spell_kaelthas_summon_weapons);
class spell_kaelthas_summon_weapons_SpellScript : public SpellScript
void HandleScriptEffect(SpellEffIndex effIndex)
{
PrepareSpellScript(spell_kaelthas_summon_weapons_SpellScript);
PreventHitEffect(effIndex);
for (uint32 i = SPELL_SUMMON_WEAPONA; i <= SPELL_SUMMON_WEAPONG; ++i)
GetCaster()->CastSpell(GetCaster(), i, true);
}
void HandleScriptEffect(SpellEffIndex effIndex)
{
PreventHitEffect(effIndex);
for (uint32 i = SPELL_SUMMON_WEAPONA; i <= SPELL_SUMMON_WEAPONG; ++i)
GetCaster()->CastSpell(GetCaster(), i, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_summon_weapons_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
SpellScript* GetSpellScript() const override
void Register() override
{
return new spell_kaelthas_summon_weapons_SpellScript();
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_summon_weapons::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
class spell_kaelthas_resurrection : public SpellScriptLoader
class spell_kaelthas_resurrection : public SpellScript
{
public:
spell_kaelthas_resurrection() : SpellScriptLoader("spell_kaelthas_resurrection") { }
PrepareSpellScript(spell_kaelthas_resurrection);
class spell_kaelthas_resurrection_SpellScript : public SpellScript
void HandleBeforeCast()
{
PrepareSpellScript(spell_kaelthas_resurrection_SpellScript);
GetCaster()->GetAI()->SetData(DATA_RESURRECT_CAST, DATA_RESURRECT_CAST);
}
void HandleBeforeCast()
{
GetCaster()->GetAI()->SetData(DATA_RESURRECT_CAST, DATA_RESURRECT_CAST);
}
void Register() override
{
BeforeCast += SpellCastFn(spell_kaelthas_resurrection_SpellScript::HandleBeforeCast);
}
};
SpellScript* GetSpellScript() const override
void Register() override
{
return new spell_kaelthas_resurrection_SpellScript();
BeforeCast += SpellCastFn(spell_kaelthas_resurrection::HandleBeforeCast);
}
};
class spell_kaelthas_mind_control : public SpellScriptLoader
class spell_kaelthas_mind_control : public SpellScript
{
public:
spell_kaelthas_mind_control() : SpellScriptLoader("spell_kaelthas_mind_control") { }
PrepareSpellScript(spell_kaelthas_mind_control);
class spell_kaelthas_mind_control_SpellScript : public SpellScript
void SelectTarget(std::list<WorldObject*>& targets)
{
PrepareSpellScript(spell_kaelthas_mind_control_SpellScript);
if (Unit* victim = GetCaster()->GetVictim())
targets.remove_if(Acore::ObjectGUIDCheck(victim->GetGUID(), true));
}
void SelectTarget(std::list<WorldObject*>& targets)
{
if (Unit* victim = GetCaster()->GetVictim())
targets.remove_if(Acore::ObjectGUIDCheck(victim->GetGUID(), true));
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_kaelthas_mind_control_SpellScript::SelectTarget, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
SpellScript* GetSpellScript() const override
void Register() override
{
return new spell_kaelthas_mind_control_SpellScript();
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_kaelthas_mind_control::SelectTarget, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
class spell_kaelthas_burn : public SpellScriptLoader
class spell_kaelthas_burn : public AuraScript
{
public:
spell_kaelthas_burn() : SpellScriptLoader("spell_kaelthas_burn") { }
PrepareAuraScript(spell_kaelthas_burn);
class spell_kaelthas_burn_AuraScript : public AuraScript
void HandlePeriodic(AuraEffect const* /*aurEff*/)
{
PrepareAuraScript(spell_kaelthas_burn_AuraScript);
Unit::DealDamage(GetUnitOwner(), GetUnitOwner(), GetUnitOwner()->CountPctFromMaxHealth(5) + 1);
}
void HandlePeriodic(AuraEffect const* /*aurEff*/)
{
Unit::DealDamage(GetUnitOwner(), GetUnitOwner(), GetUnitOwner()->CountPctFromMaxHealth(5) + 1);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_kaelthas_burn_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
AuraScript* GetAuraScript() const override
void Register() override
{
return new spell_kaelthas_burn_AuraScript();
OnEffectPeriodic += AuraEffectPeriodicFn(spell_kaelthas_burn::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
class spell_kaelthas_flame_strike : public SpellScriptLoader
class spell_kaelthas_flame_strike : public AuraScript
{
public:
spell_kaelthas_flame_strike() : SpellScriptLoader("spell_kaelthas_flame_strike") { }
PrepareAuraScript(spell_kaelthas_flame_strike);
class spell_kaelthas_flame_strike_AuraScript : public AuraScript
bool Load() override
{
PrepareAuraScript(spell_kaelthas_flame_strike_AuraScript);
return GetUnitOwner()->GetTypeId() == TYPEID_UNIT;
}
bool Load() override
{
return GetUnitOwner()->GetTypeId() == TYPEID_UNIT;
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
GetUnitOwner()->RemoveAllAuras();
GetUnitOwner()->CastSpell(GetUnitOwner(), SPELL_FLAME_STRIKE_DAMAGE, true);
GetUnitOwner()->ToCreature()->DespawnOrUnsummon(2000);
}
void Register() override
{
OnEffectRemove += AuraEffectRemoveFn(spell_kaelthas_flame_strike_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
return new spell_kaelthas_flame_strike_AuraScript();
GetUnitOwner()->RemoveAllAuras();
GetUnitOwner()->CastSpell(GetUnitOwner(), SPELL_FLAME_STRIKE_DAMAGE, true);
GetUnitOwner()->ToCreature()->DespawnOrUnsummon(2000);
}
void Register() override
{
OnEffectRemove += AuraEffectRemoveFn(spell_kaelthas_flame_strike::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
@@ -1260,111 +1227,78 @@ private:
Player* _owner;
};
class spell_kaelthas_gravity_lapse : public SpellScriptLoader
class spell_kaelthas_gravity_lapse : public SpellScript
{
public:
spell_kaelthas_gravity_lapse() : SpellScriptLoader("spell_kaelthas_gravity_lapse") { }
PrepareSpellScript(spell_kaelthas_gravity_lapse);
class spell_kaelthas_gravity_lapse_SpellScript : public SpellScript
bool Load() override
{
PrepareSpellScript(spell_kaelthas_gravity_lapse_SpellScript);
bool Load() override
{
_currentSpellId = SPELL_GRAVITY_LAPSE_TELEPORT1;
return true;
}
void HandleScriptEffect(SpellEffIndex effIndex)
{
PreventHitEffect(effIndex);
if (_currentSpellId < SPELL_GRAVITY_LAPSE_TELEPORT1 + 25)
if (Player* target = GetHitPlayer())
{
GetCaster()->CastSpell(target, _currentSpellId++, true);
target->m_Events.AddEvent(new lapseTeleport(target), target->m_Events.CalculateTime(1));
}
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_gravity_lapse_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
private:
uint32 _currentSpellId;
};
SpellScript* GetSpellScript() const override
{
return new spell_kaelthas_gravity_lapse_SpellScript();
_currentSpellId = SPELL_GRAVITY_LAPSE_TELEPORT1;
return true;
}
};
class spell_kaelthas_nether_beam : public SpellScriptLoader
{
public:
spell_kaelthas_nether_beam() : SpellScriptLoader("spell_kaelthas_nether_beam") { }
class spell_kaelthas_nether_beam_SpellScript : public SpellScript
void HandleScriptEffect(SpellEffIndex effIndex)
{
PrepareSpellScript(spell_kaelthas_nether_beam_SpellScript);
void HandleScriptEffect(SpellEffIndex effIndex)
{
PreventHitEffect(effIndex);
ThreatContainer::StorageType const& ThreatList = GetCaster()-> GetThreatMgr().GetThreatList();
std::list<Unit*> targetList;
for (ThreatContainer::StorageType::const_iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr)
PreventHitEffect(effIndex);
if (_currentSpellId < SPELL_GRAVITY_LAPSE_TELEPORT1 + 25)
if (Player* target = GetHitPlayer())
{
Unit* target = ObjectAccessor::GetUnit(*GetCaster(), (*itr)->getUnitGuid());
if (target && target->GetTypeId() == TYPEID_PLAYER)
targetList.push_back(target);
GetCaster()->CastSpell(target, _currentSpellId++, true);
target->m_Events.AddEvent(new lapseTeleport(target), target->m_Events.CalculateTime(1));
}
}
Acore::Containers::RandomResize(targetList, 5);
for (std::list<Unit*>::const_iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
GetCaster()->CastSpell(*itr, SPELL_NETHER_BEAM_DAMAGE, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_nether_beam_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
SpellScript* GetSpellScript() const override
void Register() override
{
return new spell_kaelthas_nether_beam_SpellScript();
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_gravity_lapse::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
private:
uint32 _currentSpellId;
};
class spell_kaelthas_nether_beam : public SpellScript
{
PrepareSpellScript(spell_kaelthas_nether_beam);
void HandleScriptEffect(SpellEffIndex effIndex)
{
PreventHitEffect(effIndex);
ThreatContainer::StorageType const& ThreatList = GetCaster()-> GetThreatMgr().GetThreatList();
std::list<Unit*> targetList;
for (ThreatContainer::StorageType::const_iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr)
{
Unit* target = ObjectAccessor::GetUnit(*GetCaster(), (*itr)->getUnitGuid());
if (target && target->GetTypeId() == TYPEID_PLAYER)
targetList.push_back(target);
}
Acore::Containers::RandomResize(targetList, 5);
for (std::list<Unit*>::const_iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
GetCaster()->CastSpell(*itr, SPELL_NETHER_BEAM_DAMAGE, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_nether_beam::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
class spell_kaelthas_summon_nether_vapor : public SpellScriptLoader
class spell_kaelthas_summon_nether_vapor : public SpellScript
{
public:
spell_kaelthas_summon_nether_vapor() : SpellScriptLoader("spell_kaelthas_summon_nether_vapor") { }
PrepareSpellScript(spell_kaelthas_summon_nether_vapor);
class spell_kaelthas_summon_nether_vapor_SpellScript : public SpellScript
void HandleScriptEffect(SpellEffIndex effIndex)
{
PrepareSpellScript(spell_kaelthas_summon_nether_vapor_SpellScript);
PreventHitEffect(effIndex);
for (uint32 i = 0; i < 5; ++i)
GetCaster()->SummonCreature(NPC_NETHER_VAPOR, GetCaster()->GetPositionX() + 6 * cos(i / 5.0f * 2 * M_PI), GetCaster()->GetPositionY() + 6 * std::sin(i / 5.0f * 2 * M_PI), GetCaster()->GetPositionZ() + 7.0f + i, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 30000);
}
void HandleScriptEffect(SpellEffIndex effIndex)
{
PreventHitEffect(effIndex);
for (uint32 i = 0; i < 5; ++i)
GetCaster()->SummonCreature(NPC_NETHER_VAPOR, GetCaster()->GetPositionX() + 6 * cos(i / 5.0f * 2 * M_PI), GetCaster()->GetPositionY() + 6 * std::sin(i / 5.0f * 2 * M_PI), GetCaster()->GetPositionZ() + 7.0f + i, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 30000);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_summon_nether_vapor_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
SpellScript* GetSpellScript() const override
void Register() override
{
return new spell_kaelthas_summon_nether_vapor_SpellScript();
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_summon_nether_vapor::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
@@ -1375,15 +1309,15 @@ void AddSC_boss_kaelthas()
RegisterTheEyeAI(npc_capernian);
RegisterTheEyeAI(npc_telonicus);
RegisterTheEyeAI(npc_thaladred);
new spell_kaelthas_kael_phase_two();
new spell_kaelthas_remote_toy();
new spell_kaelthas_summon_weapons();
new spell_kaelthas_resurrection();
new spell_kaelthas_mind_control();
new spell_kaelthas_burn();
new spell_kaelthas_flame_strike();
new spell_kaelthas_gravity_lapse();
new spell_kaelthas_nether_beam();
new spell_kaelthas_summon_nether_vapor();
RegisterSpellScript(spell_kaelthas_kael_phase_two);
RegisterSpellScript(spell_kaelthas_remote_toy);
RegisterSpellScript(spell_kaelthas_summon_weapons);
RegisterSpellScript(spell_kaelthas_resurrection);
RegisterSpellScript(spell_kaelthas_mind_control);
RegisterSpellScript(spell_kaelthas_burn);
RegisterSpellScript(spell_kaelthas_flame_strike);
RegisterSpellScript(spell_kaelthas_gravity_lapse);
RegisterSpellScript(spell_kaelthas_nether_beam);
RegisterSpellScript(spell_kaelthas_summon_nether_vapor);
}

View File

@@ -768,13 +768,12 @@ class spell_gen_proc_not_self : public AuraScript
if (Unit* caster = GetCaster())
if (Unit* target = eventInfo.GetActionTarget())
{
ObjectGuid targetGUID = target->GetGUID();
uint32 spellID = aurEff->GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell;
caster->m_Events.AddEventAtOffset([caster, target, spellID]()
caster->m_Events.AddEventAtOffset([caster, targetGUID, spellID]()
{
if (target)
{
if (Unit *target = ObjectAccessor::GetUnit(*caster, targetGUID))
caster->CastSpell(target, spellID, true);
}
}, 100ms);
}
}

View File

@@ -334,7 +334,7 @@ public:
{
npc_training_dummyAI(Creature* creature) : ScriptedAI(creature)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true); //imune to knock aways like blast wave
}
@@ -392,7 +392,7 @@ public:
{
npc_target_dummyAI(Creature* creature) : ScriptedAI(creature)
{
SetCombatMovement(false);
me->SetCombatMovement(false);
deathTimer = 15000;
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true); //imune to knock aways like blast wave
}