Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2024-03-09 10:30:25 +08:00
15 changed files with 257 additions and 18 deletions

View File

@@ -15,6 +15,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cmath>
#include "CreatureScript.h"
#include "MoveSplineInit.h"
#include "ScriptedCreature.h"
@@ -85,6 +86,8 @@ enum qruseoftheAshtongue
QUEST_RUSE_OF_THE_ASHTONGUE = 10946,
};
const float INNER_CIRCLE_RADIUS = 60.0f;
struct boss_alar : public BossAI
{
@@ -109,6 +112,7 @@ struct boss_alar : public BossAI
_baseAttackOverride = false;
_spawnPhoenixes = false;
_platform = 0;
_noMelee = false;
_platformRoll = 0;
_noQuillTimes = 0;
_platformMoveRepeatTimer = 16s;
@@ -135,7 +139,7 @@ struct boss_alar : public BossAI
if (_noQuillTimes++ > 0)
{
me->SetOrientation(alarPoints[_platform].GetOrientation());
SpawnPhoenixes(1, me);
SpawnPhoenixes(1, me, false);
}
me->GetMotionMaster()->MovePoint(POINT_PLATFORM, alarPoints[_platform], false, true);
_platform = (_platform+1)%4;
@@ -191,6 +195,7 @@ struct boss_alar : public BossAI
ScheduleUniqueTimedEvent(16001ms, [&]{
me->SetHealth(me->GetMaxHealth());
me->SetReactState(REACT_AGGRESSIVE);
_noMelee = false;
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
_platform = POINT_MIDDLE;
me->GetMotionMaster()->MoveChase(me->GetVictim());
@@ -201,6 +206,7 @@ struct boss_alar : public BossAI
void PretendToDie(Creature* creature)
{
_noMelee = true;
scheduler.CancelAll();
creature->InterruptNonMeleeSpells(true);
creature->RemoveAllAuras();
@@ -229,11 +235,11 @@ struct boss_alar : public BossAI
me->SummonCreature(NPC_FLAME_PATCH, *target, TEMPSUMMON_TIMED_DESPAWN, 2 * MINUTE * IN_MILLISECONDS);
}
}, 30s);
ScheduleTimedEvent(30s, [&]
ScheduleTimedEvent(50s, [&]
{
me->GetMotionMaster()->MovePoint(POINT_DIVE, alarPoints[POINT_DIVE], false, true);
scheduler.DelayAll(15s);
}, 30s);
}, 50s);
ScheduleUniqueTimedEvent(10min, [&]
{
DoCastSelf(SPELL_BERSERK);
@@ -241,24 +247,33 @@ struct boss_alar : public BossAI
ScheduleMainSpellAttack(0s);
}
void SpawnPhoenixes(uint8 count, Unit* targetToSpawnAt)
void SpawnPhoenixes(uint8 count, Unit* targetToSpawnAt, bool onPosition)
{
if (targetToSpawnAt)
{
for (uint8 i = 0; i < count; ++i)
{
me->SummonCreature(NPC_EMBER_OF_ALAR, *targetToSpawnAt, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 6000);
if (onPosition)
{
Position spawnPosition = DeterminePhoenixPosition(targetToSpawnAt->GetPosition());
me->SummonCreature(NPC_EMBER_OF_ALAR, spawnPosition, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 6000);
}
else
{
me->SummonCreature(NPC_EMBER_OF_ALAR, *targetToSpawnAt, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 6000);
}
}
}
}
void DoDiveBomb()
{
_noMelee = true;
scheduler.Schedule(2s, [this](TaskContext)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 10.0f, true))
{
SpawnPhoenixes(2, target);
SpawnPhoenixes(2, target, true);
}
}).Schedule(6s, [this](TaskContext)
{
@@ -267,6 +282,7 @@ struct boss_alar : public BossAI
}).Schedule(10s, [this](TaskContext)
{
me->GetMotionMaster()->MoveChase(me->GetVictim());
_noMelee = false;
});
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 90.0f, true))
{
@@ -341,10 +357,61 @@ struct boss_alar : public BossAI
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
{
return;
}
scheduler.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
{
return;
}
if (!_noMelee)
{
DoMeleeAttackIfReady();
}
}
Position DeterminePhoenixPosition(Position playerPosition)
{
// set finalPosition to playerPosition in case the fraction fails
Position finalPosition = playerPosition;
float playerXPosition = playerPosition.GetPositionX();
float playerYPosition = playerPosition.GetPositionY();
float centreXPosition = alarPoints[POINT_MIDDLE].GetPositionX();
float centreYPosition = alarPoints[POINT_MIDDLE].GetPositionY();
float deltaX = std::abs(playerXPosition-centreXPosition);
float deltaY = std::abs(playerYPosition-centreYPosition);
int8 signMultiplier[2] = {1, 1};
// if fraction has x position 0.0f we get nan as a result
if (float playerFraction = deltaX/deltaY)
{
// player angle based on delta X and delta Y
float playerAngle = std::atan(playerFraction);
float phoenixDeltaYPosition = std::cos(playerAngle)*INNER_CIRCLE_RADIUS;
float phoenixDeltaXPosition = std::sin(playerAngle)*INNER_CIRCLE_RADIUS;
// as calculations are absolute values we have to multiply in the end
// should be negative if player position was further down than centre
if (playerXPosition < centreXPosition)
signMultiplier[0] = -1;
if (playerYPosition < centreYPosition)
signMultiplier[1] = -1;
// phoenix position based on set distance
finalPosition = {centreXPosition+signMultiplier[0]*phoenixDeltaXPosition, centreYPosition+signMultiplier[1]*phoenixDeltaYPosition, 0.0f, 0.0f};
}
return finalPosition;
}
private:
bool _canAttackCooldown;
bool _baseAttackOverride;
bool _spawnPhoenixes;
bool _noMelee;
uint8 _platform;
uint8 _platformRoll;
uint8 _noQuillTimes;

View File

@@ -23,12 +23,10 @@
enum Yells
{
SAY_AGGRO = 0,
SAY_SUMMON1 = 1,
SAY_SUMMON2 = 2,
SAY_KILL = 3,
SAY_DEATH = 4,
SAY_VOIDA = 5,
SAY_VOIDB = 6
SAY_SUMMON = 1,
SAY_KILL = 2,
SAY_DEATH = 3,
SAY_VOID = 4
};
enum Spells
@@ -59,7 +57,13 @@ enum Misc
struct boss_high_astromancer_solarian : public BossAI
{
boss_high_astromancer_solarian(Creature* creature) : BossAI(creature, DATA_ASTROMANCER) { }
boss_high_astromancer_solarian(Creature* creature) : BossAI(creature, DATA_ASTROMANCER)
{
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void Reset() override
{
@@ -68,6 +72,8 @@ struct boss_high_astromancer_solarian : public BossAI
me->SetReactState(REACT_AGGRESSIVE);
ScheduleHealthCheckEvent(20, [&]{
Talk(SAY_VOID);
me->InterruptNonMeleeSpells(false);
scheduler.CancelAll();
me->ResumeChasingVictim();
scheduler.Schedule(3s, [this](TaskContext context)
@@ -116,7 +122,7 @@ struct boss_high_astromancer_solarian : public BossAI
scheduler.Schedule(3650ms, [this](TaskContext context)
{
me->GetMotionMaster()->Clear();
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f, true))
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f, true, true, -SPELL_WRATH_OF_THE_ASTROMANCER))
{
DoCast(target, SPELL_ARCANE_MISSILES);
}
@@ -138,11 +144,11 @@ struct boss_high_astromancer_solarian : public BossAI
}).Schedule(52100ms, [this](TaskContext context)
{
me->SetReactState(REACT_PASSIVE);
Talk(SAY_SUMMON);
me->SetModelVisible(false);
scheduler.DelayAll(21s);
scheduler.Schedule(6s, [this](TaskContext)
{
Talk(SAY_SUMMON1);
summons.DoForAllSummons([&](WorldObject* summon)
{
if (Creature* light = summon->ToCreature())
@@ -164,7 +170,6 @@ struct boss_high_astromancer_solarian : public BossAI
}).Schedule(20s, [this](TaskContext)
{
me->SetReactState(REACT_AGGRESSIVE);
Talk(SAY_SUMMON2);
summons.DoForAllSummons([&](WorldObject* summon)
{
if (Creature* light = summon->ToCreature())

View File

@@ -963,7 +963,7 @@ struct npc_telonicus : public ScriptedAI
DoCastVictim(SPELL_BOMB);
}, 3600ms, 7100ms);
ScheduleTimedEvent(13250ms, [&]{
DoCastRandomTarget(SPELL_CONFLAGRATION, 0, 100.0f);
DoCastRandomTarget(SPELL_REMOTE_TOY, 0, 100.0f);
}, 15750ms);
}