Skip to content

Commit 9af5be0

Browse files
Merge AzerothCore 3.3.5 to ElunaAzerothcore [skip ci]
2 parents 6a0e389 + 06e3ef3 commit 9af5be0

15 files changed

Lines changed: 1678 additions & 2138 deletions

File tree

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-- DB update 2026_04_10_02 -> 2026_04_11_00
2+
--
3+
UPDATE `waypoint_data` SET `delay` = 32000 WHERE `id` = 1281350 AND `point` = 1;
4+
UPDATE `waypoint_data` SET `delay` = 38000 WHERE `id` = 1281350 AND `point` = 8;

src/server/game/Entities/Unit/Unit.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14878,6 +14878,9 @@ void Unit::RemoveCharmedBy(Unit* charmer)
1487814878

1487914879
StopAttackingInvalidTarget();
1488014880

14881+
// End stale combat refs between now-friendly units after faction restore
14882+
GetCombatManager().RevalidateCombat();
14883+
1488114884
Player* playerCharmer = charmer->ToPlayer();
1488214885
if (playerCharmer)
1488314886
{

src/server/game/Maps/Map.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1837,12 +1837,13 @@ void Map::RemoveAllObjectsInRemoveList()
18371837
}
18381838
}
18391839

1840-
uint32 Map::GetPlayersCountExceptGMs() const
1840+
uint32 Map::GetPlayersCountExceptGMs(bool aliveOnly /*= false*/) const
18411841
{
18421842
uint32 count = 0;
1843-
for (MapRefMgr::const_iterator itr = m_mapRefMgr.begin(); itr != m_mapRefMgr.end(); ++itr)
1844-
if (!itr->GetSource()->IsGameMaster())
1845-
++count;
1843+
for (auto const& ref : m_mapRefMgr)
1844+
if (Player* player = ref.GetSource())
1845+
if (!player->IsGameMaster() && (!aliveOnly || (player->IsAlive() && !player->HasSpiritOfRedemptionAura())))
1846+
++count;
18461847
return count;
18471848
}
18481849

src/server/game/Maps/Map.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,8 @@ class Map : public GridRefMgr<MapGridType>
325325
void markCell(uint32 pCellId) { marked_cells.set(pCellId); }
326326

327327
[[nodiscard]] bool HavePlayers() const { return !m_mapRefMgr.IsEmpty(); }
328-
[[nodiscard]] uint32 GetPlayersCountExceptGMs() const;
328+
// When aliveOnly is true, counts only players that are alive and not in Spirit of Redemption form.
329+
[[nodiscard]] uint32 GetPlayersCountExceptGMs(bool aliveOnly = false) const;
329330

330331
void SendToPlayers(WorldPacket const* data) const;
331332

src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,16 @@ class npc_belnistrasz : public CreatureScript
100100
}
101101
}
102102

103+
void JustExitedCombat() override
104+
{
105+
if (channeling)
106+
{
107+
EngagementOver();
108+
return;
109+
}
110+
CreatureAI::JustExitedCombat();
111+
}
112+
103113
void JustEngagedWith(Unit* who) override
104114
{
105115
if (channeling)

src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp

Lines changed: 72 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -50,141 +50,95 @@ enum eEvents
5050
EVENT_UNROOT,
5151
};
5252

53-
class boss_cyanigosa : public CreatureScript
53+
struct boss_cyanigosa : public BossAI
5454
{
55-
public:
56-
boss_cyanigosa() : CreatureScript("boss_cyanigosa") { }
55+
boss_cyanigosa(Creature* c) : BossAI(c, DATA_CYANIGOSA) { }
5756

58-
CreatureAI* GetAI(Creature* pCreature) const override
57+
void JustEngagedWith(Unit* who) override
5958
{
60-
return GetVioletHoldAI<boss_cyanigosaAI>(pCreature);
59+
BossAI::JustEngagedWith(who);
60+
Talk(SAY_AGGRO);
61+
events.RescheduleEvent(EVENT_SPELL_ARCANE_VACUUM, 30s);
62+
events.RescheduleEvent(EVENT_SPELL_BLIZZARD, 5s, 10s);
63+
events.RescheduleEvent(EVENT_SPELL_TAIL_SWEEP, 15s, 20s);
64+
events.RescheduleEvent(EVENT_SPELL_UNCONTROLLABLE_ENERGY, 5s, 8s);
65+
if (IsHeroic())
66+
events.RescheduleEvent(EVENT_SPELL_MANA_DESTRUCTION, 20s);
6167
}
6268

63-
struct boss_cyanigosaAI : public ScriptedAI
69+
void SpellHitTarget(Unit* target, SpellInfo const* spell) override
6470
{
65-
boss_cyanigosaAI(Creature* c) : ScriptedAI(c)
66-
{
67-
pInstance = c->GetInstanceScript();
68-
}
69-
70-
InstanceScript* pInstance;
71-
EventMap events;
72-
73-
void Reset() override
74-
{
75-
events.Reset();
76-
}
77-
78-
void JustEngagedWith(Unit* /*who*/) override
79-
{
80-
DoZoneInCombat();
81-
Talk(SAY_AGGRO);
82-
events.Reset();
83-
events.RescheduleEvent(EVENT_SPELL_ARCANE_VACUUM, 30s);
84-
events.RescheduleEvent(EVENT_SPELL_BLIZZARD, 5s, 10s);
85-
events.RescheduleEvent(EVENT_SPELL_TAIL_SWEEP, 15s, 20s);
86-
events.RescheduleEvent(EVENT_SPELL_UNCONTROLLABLE_ENERGY, 5s, 8s);
87-
if (IsHeroic())
88-
events.RescheduleEvent(EVENT_SPELL_MANA_DESTRUCTION, 20s);
89-
}
90-
91-
void SpellHitTarget(Unit* target, SpellInfo const* spell) override
92-
{
93-
if (!target || !spell)
94-
return;
95-
switch (spell->Id)
96-
{
97-
case SPELL_ARCANE_VACUUM:
98-
target->NearTeleportTo(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 10.0f, target->GetOrientation());
99-
break;
100-
}
101-
}
71+
if (!target || !spell)
72+
return;
73+
if (spell->Id == SPELL_ARCANE_VACUUM)
74+
target->NearTeleportTo(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 10.0f, target->GetOrientation());
75+
}
10276

103-
void UpdateAI(uint32 diff) override
77+
void ExecuteEvent(uint32 eventId) override
78+
{
79+
switch (eventId)
10480
{
105-
if (!UpdateVictim())
106-
return;
107-
108-
events.Update(diff);
109-
110-
if (me->HasUnitState(UNIT_STATE_CASTING))
111-
return;
112-
113-
switch (events.ExecuteEvent())
114-
{
115-
case 0:
116-
break;
117-
case EVENT_SPELL_ARCANE_VACUUM:
118-
me->CastSpell((Unit*)nullptr, SPELL_ARCANE_VACUUM, false);
119-
DoResetThreatList();
120-
me->SetControlled(true, UNIT_STATE_ROOT);
121-
me->setAttackTimer(BASE_ATTACK, 3000);
122-
events.Repeat(30s);
123-
events.ScheduleEvent(EVENT_UNROOT, 3s);
124-
break;
125-
case EVENT_UNROOT:
126-
me->SetControlled(false, UNIT_STATE_ROOT);
127-
128-
break;
129-
case EVENT_SPELL_BLIZZARD:
130-
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 45.0f, true))
131-
me->CastSpell(target, SPELL_BLIZZARD, false);
132-
events.Repeat(15s);
133-
break;
134-
case EVENT_SPELL_MANA_DESTRUCTION:
135-
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true))
136-
me->CastSpell(target, SPELL_MANA_DESTRUCTION, false);
137-
events.Repeat(20s);
138-
break;
139-
case EVENT_SPELL_TAIL_SWEEP:
140-
me->CastSpell(me->GetVictim(), SPELL_TAIL_SWEEP, false);
141-
events.Repeat(15s, 20s);
142-
break;
143-
case EVENT_SPELL_UNCONTROLLABLE_ENERGY:
144-
me->CastSpell(me->GetVictim(), SPELL_UNCONTROLLABLE_ENERGY, false);
145-
events.Repeat(20s, 25s);
146-
break;
147-
}
148-
149-
DoMeleeAttackIfReady();
81+
case EVENT_SPELL_ARCANE_VACUUM:
82+
DoCastAOE(SPELL_ARCANE_VACUUM);
83+
DoResetThreatList();
84+
me->SetControlled(true, UNIT_STATE_ROOT);
85+
me->setAttackTimer(BASE_ATTACK, 3000);
86+
events.Repeat(30s);
87+
events.ScheduleEvent(EVENT_UNROOT, 3s);
88+
break;
89+
case EVENT_UNROOT:
90+
me->SetControlled(false, UNIT_STATE_ROOT);
91+
break;
92+
case EVENT_SPELL_BLIZZARD:
93+
DoCastRandomTarget(SPELL_BLIZZARD, 0, 45.0f);
94+
events.Repeat(15s);
95+
break;
96+
case EVENT_SPELL_MANA_DESTRUCTION:
97+
DoCastRandomTarget(SPELL_MANA_DESTRUCTION, 0, 50.0f);
98+
events.Repeat(20s);
99+
break;
100+
case EVENT_SPELL_TAIL_SWEEP:
101+
DoCastVictim(SPELL_TAIL_SWEEP);
102+
events.Repeat(15s, 20s);
103+
break;
104+
case EVENT_SPELL_UNCONTROLLABLE_ENERGY:
105+
DoCastVictim(SPELL_UNCONTROLLABLE_ENERGY);
106+
events.Repeat(20s, 25s);
107+
break;
150108
}
109+
}
151110

152-
void JustDied(Unit* /*killer*/) override
111+
void JustDied(Unit* killer) override
112+
{
113+
Talk(SAY_DEATH);
114+
BossAI::JustDied(killer);
115+
float h = me->GetMapHeight(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ());
116+
if (h != INVALID_HEIGHT && me->GetPositionZ() - h > 3.0f)
153117
{
154-
Talk(SAY_DEATH);
155-
if (pInstance)
156-
pInstance->SetData(DATA_BOSS_DIED, 0);
157-
float h = me->GetMapHeight(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ());
158-
if (h != INVALID_HEIGHT && me->GetPositionZ() - h > 3.0f)
159-
{
160-
me->UpdatePosition(me->GetPositionX(), me->GetPositionY(), h, me->GetOrientation(), true); // move to ground
161-
me->StopMovingOnCurrentPos();
162-
me->DestroyForVisiblePlayers();
163-
}
118+
me->UpdatePosition(me->GetPositionX(), me->GetPositionY(), h, me->GetOrientation(), true);
119+
me->StopMovingOnCurrentPos();
120+
me->DestroyForVisiblePlayers();
164121
}
122+
}
165123

166-
void KilledUnit(Unit* victim) override
167-
{
168-
if (victim && victim->GetGUID() == me->GetGUID())
169-
return;
170-
Talk(SAY_SLAY);
171-
}
124+
void KilledUnit(Unit* victim) override
125+
{
126+
if (victim && victim->GetGUID() == me->GetGUID())
127+
return;
128+
Talk(SAY_SLAY);
129+
}
172130

173-
void MoveInLineOfSight(Unit* /*who*/) override {}
131+
void MoveInLineOfSight(Unit* /*who*/) override {}
174132

175-
void EnterEvadeMode(EvadeReason why) override
176-
{
177-
me->SetControlled(false, UNIT_STATE_ROOT);
178-
ScriptedAI::EnterEvadeMode(why);
179-
events.Reset();
180-
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
181-
if (pInstance)
182-
pInstance->SetData(DATA_FAILED, 1);
183-
}
184-
};
133+
void EnterEvadeMode(EvadeReason why) override
134+
{
135+
me->SetControlled(false, UNIT_STATE_ROOT);
136+
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
137+
_EnterEvadeMode(why);
138+
}
185139
};
186140

187141
void AddSC_boss_cyanigosa()
188142
{
189-
new boss_cyanigosa();
143+
RegisterVioletHoldCreatureAI(boss_cyanigosa);
190144
}

0 commit comments

Comments
 (0)