mirror of
https://github.com/ornfelt/azerothcore_lua_scripts
synced 2026-08-22 06:26:03 -04:00
881 lines
No EOL
26 KiB
C++
881 lines
No EOL
26 KiB
C++
#include "OutdoorPvP.h"
|
|
#include "OutdoorPvPMgr.h"
|
|
#include "ScenarioMgr.h"
|
|
#include "PetBattle.h"
|
|
#include "ScriptedCreature.h"
|
|
#include "Creature.h"
|
|
#include "GameEventMgr.h"
|
|
#include "ScriptMgr.h"
|
|
|
|
// 107249 small vignette
|
|
|
|
// Vignettes
|
|
//1272
|
|
//1273
|
|
//1274
|
|
// 1287 ??
|
|
std::vector<uint32> lowNps
|
|
{
|
|
104476,
|
|
104465,
|
|
104281,
|
|
104286,
|
|
92113, // fly
|
|
104426,
|
|
104474,
|
|
104282,
|
|
104467,
|
|
104489,
|
|
104450,
|
|
104423,
|
|
104421,
|
|
104418,
|
|
105569, // + crystal 96985
|
|
104425,
|
|
104285,
|
|
};
|
|
|
|
std::vector<uint32> middleNps
|
|
{
|
|
104432,
|
|
104875,
|
|
104283,
|
|
|
|
105900,
|
|
105901,
|
|
105999,
|
|
108126,
|
|
};
|
|
|
|
std::vector<uint32> highNps
|
|
{
|
|
105954,
|
|
94357,
|
|
94226,
|
|
107198,
|
|
};
|
|
|
|
std::vector<uint32> bosses
|
|
{
|
|
107115
|
|
};
|
|
|
|
std::vector<uint32> go
|
|
{
|
|
243448, // small 114259 sum 227391 dest 227788
|
|
241610, // middle+ 109761 sum 207688 destr 218496
|
|
};
|
|
|
|
std::vector<std::pair<uint32, Position>> g_startedNPCs
|
|
{
|
|
{ 104842 , {-825.50f, 4254.05f, 857.38f, 1.50f} },
|
|
{ 104842 , {-1011.34f, 4513.21f, 857.38f, 5.09f} },
|
|
{ 104842 , {-643.05f, 4465.06f, 857.38f, 3.03f} },
|
|
{ 950116, {-857.10f, 4572.40f, 733.82f, 4.67f}},
|
|
};
|
|
|
|
std::vector<Position> g_firstStepSummonsPosition
|
|
{
|
|
{ -849.74f, 4272.29f, 745.133f },
|
|
//{ -846.346f, 4265.58f, 746.272f },
|
|
{ -814.334f, 4278.38f, 746.279f },
|
|
//{ -828.288f, 4289.49f, 746.27f },
|
|
{ -835.27f, 4315.17f, 744.881f },
|
|
//{ -846.723f, 4394.19f, 737.653f },
|
|
{ -873.506f, 4404.24f, 738.107f },
|
|
{ -873.081f, 4426.89f, 738.414f },
|
|
{ -894.844f, 4419.58f, 736.951f },
|
|
{ -916.328f, 4454.45f, 735.047f },
|
|
{ -940.503f, 4454.21f, 733.758f },
|
|
{ -957.607f, 4467.61f, 734.165f },
|
|
{ -949.275f, 4491.32f, 733.46f },
|
|
{ -924.102f, 4478.49f, 733.913f },
|
|
{ -907.797f, 4489.6f, 732.046f },
|
|
{ -884.778f, 4500.34f, 730.341f },
|
|
{ -877.921f, 4526.43f, 729.44f },
|
|
//{ -860.651f, 4543.89f, 728.33f },
|
|
{ -835.612f, 4553.13f, 728.555f },
|
|
{ -822.956f, 4538.94f, 728.621f },
|
|
{ -808.217f, 4527.09f, 729.395f },
|
|
{ -811.229f, 4507.81f, 730.909f },
|
|
{ -785.395f, 4510.84f, 730.759f },
|
|
{ -772.516f, 4486.8f, 732.507f },
|
|
{ -759.142f, 4487.11f, 732.429f },
|
|
{ -727.474f, 4460.4f, 732.989f },
|
|
{ -745.427f, 4464.49f, 733.374f },
|
|
{ -771.232f, 4465.53f, 734.295f },
|
|
{ -778.047f, 4446.28f, 737.233f },
|
|
{ -799.904f, 4444.21f, 737.773f },
|
|
{ -799.229f, 4426.23f, 738.401f },
|
|
{ -819.639f, 4412.17f, 737.714f },
|
|
{ -820.099f, 4394.09f, 738.758f },
|
|
};
|
|
|
|
std::vector<std::pair<uint32, Position>> g_thirdNPCs
|
|
{
|
|
{ 109761,{ -951.678f, 4489.05f, 733.683f, 2.70005f } },
|
|
{ 109761,{ -835.45f, 4277.18f, 747.933f, 4.15096f } },
|
|
{ 114259,{ -681.061f, 4491.7f, 728.876f, 0.561419f } },
|
|
{ 114259,{ -757.937f, 4511.77f, 730.109f, 0.76405f } },
|
|
{ 114259,{ -827.407f, 4569.37f, 728.67f, 1.02323f } },
|
|
{ 114259,{ -922.617f, 4371.83f, 740.297f, 4.02345f } },
|
|
|
|
{ 114259,{ -886.996f, 4540.06f, 729.29f, 2.50677f } },
|
|
{ 114259,{ -734.566f, 4455.58f, 733.476f, 5.57451f } },
|
|
{ 114259,{ -946.806f, 4441.15f, 734.163f, 4.021f } },
|
|
{ 114259,{ -795.448f, 4424.73f, 738.448f, 5.70568f } },
|
|
};
|
|
|
|
std::vector<Position> m_smallShipsPath // 737
|
|
{
|
|
{-853.55f, 4556.45f, 752.34f, 0.0f},
|
|
{-772.70f, 4491.85f, 748.83f, 0.0f},
|
|
{-839.11f, 4391.07f, 760.86f, 0.0f},
|
|
{-927.33f, 4463.47f, 758.90f, 0.0f}
|
|
};
|
|
|
|
enum Spells
|
|
{
|
|
SPELL_SUMMON_NPC = 216240,
|
|
SPELL_LEGION_SKY = 232407,
|
|
SPELL_KNOCK_BACK = 212437,
|
|
SPELL_ARRILERRY = 207541, // 252512
|
|
|
|
SPELL_GO_KNOCK_BACK = 223801,
|
|
};
|
|
|
|
class OutdoorPVPdalaran_invasion : public OutdoorPvP
|
|
{
|
|
public:
|
|
OutdoorPVPdalaran_invasion()
|
|
{
|
|
m_TypeId = OUTDOOR_PVP_DALARAN_EVENT;
|
|
}
|
|
|
|
~OutdoorPVPdalaran_invasion()
|
|
{
|
|
delete m_scenario;
|
|
}
|
|
|
|
bool SetupOutdoorPvP() override
|
|
{
|
|
RegisterZone(7502);
|
|
return true;
|
|
}
|
|
|
|
void HandlePlayerEnterZone(ObjectGuid guid, uint32 zone) override
|
|
{
|
|
OutdoorPvP::HandlePlayerEnterZone(guid, zone);
|
|
|
|
Player* player = ObjectAccessor::GetObjectInMap(guid, m_map, (Player*)nullptr);
|
|
if (!player)
|
|
return;
|
|
|
|
if (m_scenario)
|
|
{
|
|
m_scenario->SendStepUpdate(player, true);
|
|
player->AddDelayedEvent(500, [player]() -> void
|
|
{
|
|
player->GetPhaseMgr().SetCustomPhase(120);
|
|
});
|
|
|
|
player->CastSpell(player, SPELL_LEGION_SKY, true);
|
|
}
|
|
}
|
|
|
|
void HandlePlayerLeaveZone(ObjectGuid guid, uint32 zone) override
|
|
{
|
|
Player* player = ObjectAccessor::GetObjectInMap(guid, m_map, (Player*)nullptr);
|
|
|
|
if (player) // not leave really, it's only in GO
|
|
if (player->GetMapId() == 1220 && player->GetDistance2d(-846.85f, 4469.60f) <= 200.0f && player->GetPositionZ() >= 650.0f)
|
|
// if (!m_map->IsOutdoors(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()))
|
|
return;
|
|
|
|
OutdoorPvP::HandlePlayerLeaveZone(guid, zone);
|
|
|
|
if (!player)
|
|
return;
|
|
|
|
RemoveScenarioForPlayer(player);
|
|
}
|
|
|
|
void HandleKill(Unit* killer, Unit* killed) override
|
|
{
|
|
if (!killed->IsCreature() || !m_scenario)
|
|
return;
|
|
|
|
if (std::find(m_creatures.begin(), m_creatures.end(), killed->GetGUID()) == m_creatures.end())
|
|
return;
|
|
|
|
if (!killer->IsPlayer()) // Find Player
|
|
killer = GetFirstPlayer();
|
|
|
|
if (killer)
|
|
DoUpdateCriterias(killer->ToPlayer(), killed);
|
|
|
|
m_creatures.remove(killed->GetGUID());
|
|
|
|
if (killed->GetCustomData())
|
|
{
|
|
switch (m_scenario->GetCurrentStep())
|
|
{
|
|
case 0:
|
|
DieActionDefault(killed->GetCustomData() - 1);
|
|
break;
|
|
case 2:
|
|
if (killed->GetEntry() == 109761 || killed->GetEntry() == 114259)
|
|
{
|
|
DoThirdStepSummons();
|
|
m_thirdStepGOs.erase(killed->GetCustomData() - 1);
|
|
return; // don't need Despawn call
|
|
}
|
|
else
|
|
DieActionDefault(killed->GetCustomData() - 1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
killed->ToCreature()->DespawnOrUnsummon(1000);
|
|
}
|
|
|
|
void SetData(uint32 zone, uint32 step) override
|
|
{
|
|
switch (step)
|
|
{
|
|
case 0:
|
|
SummonNPCsByVector(g_startedNPCs);
|
|
|
|
m_currentVector = g_firstStepSummonsPosition;
|
|
m_processor.AddDelayedEvent(29000, [this]() -> void
|
|
{
|
|
SummonShips();
|
|
SummonNPCsByVectorWithRandom(true);
|
|
});
|
|
break;
|
|
case 1:
|
|
Trinity::Containers::RandomResizeList(m_currentVector, m_currentVector.size() / 4);
|
|
m_eventTimer = 23000;
|
|
m_needEvent = true;
|
|
if (auto creature = m_map->SummonCreature(middleNps[urand(0, middleNps.size() - 1)], m_currentVector[urand(0, m_currentVector.size())]))
|
|
JustSummonedActions(creature);
|
|
break;
|
|
case 2:
|
|
DoThirdStepSummons();
|
|
m_eventTimer = 13000;
|
|
m_needEvent = true;
|
|
break;
|
|
case 3:
|
|
m_needEvent = false;
|
|
if (auto creature = m_map->SummonCreature(bosses[urand(0, bosses.size() - 1)], m_currentVector[urand(0, m_currentVector.size())]))
|
|
JustSummonedActions(creature);
|
|
break;
|
|
case 100:
|
|
m_processor.KillAllFunctions();
|
|
m_needEvent = false;
|
|
m_endTimer = 5000;
|
|
ApplyOnEveryPlayerInZone([](Player* player) -> void
|
|
{
|
|
if (player->HasItemCount(136924))
|
|
return;
|
|
|
|
auto pet = sDB2Manager.GetSpeciesBySpell(210699);
|
|
for (const auto& pair : *player->GetBattlePets())
|
|
if (pair.second->Species == pet->ID)
|
|
return;
|
|
|
|
player->AddItem(136924, 1);
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
|
|
void HandleGameEventStart(uint32 eventId) override
|
|
{
|
|
if (eventId != 192)
|
|
return;
|
|
|
|
m_endTimer = 30 * MINUTE*IN_MILLISECONDS + 100;
|
|
m_scenario = new Scenario(m_map, 1);
|
|
m_scenario->SetOutdoorPvP(this, 7502);
|
|
|
|
ApplyOnEveryPlayerInZone([this](Player* player) -> void
|
|
{
|
|
HandlePlayerEnterZone(player->GetGUID(), 7502);
|
|
});
|
|
|
|
SetData(0, 0);
|
|
m_secondStepState = 0;
|
|
m_artilleryTimer = 40000;
|
|
}
|
|
|
|
void SetGuidData(uint32 type, ObjectGuid guid) override
|
|
{
|
|
if (type == 0)
|
|
{
|
|
if (Creature* cre = ObjectAccessor::GetObjectInMap(guid, m_map, (Creature*)nullptr))
|
|
JustSummonedActions(cre);
|
|
else
|
|
m_creatures.push_back(guid);
|
|
}
|
|
else if (type == 1)
|
|
m_objects.push_back(guid);
|
|
}
|
|
|
|
bool Update(uint32 diff) override
|
|
{
|
|
m_processor.Update(diff);
|
|
|
|
if (!m_scenario)
|
|
return true;
|
|
|
|
DoArtillery(diff);
|
|
DoEndTimer(diff);
|
|
DoEventTimer(diff);
|
|
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
void RemoveScenarioForPlayer(Player* player)
|
|
{
|
|
if (m_scenario)
|
|
m_scenario->SendFinishPacket(player);
|
|
|
|
if (player->GetPhaseMask() == 120)
|
|
player->AddDelayedEvent(500, [player]() -> void
|
|
{
|
|
player->GetPhaseMgr().SetCustomPhase(1);
|
|
});
|
|
|
|
player->RemoveAurasDueToSpell(SPELL_LEGION_SKY);
|
|
}
|
|
|
|
void SummonNPCsByVector(std::vector<std::pair<uint32, Position>>& npcs)
|
|
{
|
|
uint8 i = 0;
|
|
for (auto& pair : npcs)
|
|
if (auto creature = m_map->SummonCreature(pair.first, pair.second))
|
|
{
|
|
creature->SetPhaseMask(120, true);
|
|
m_creatures_first.push_back(creature->GetGUID());
|
|
creature->setActive(true);
|
|
creature->SetRespawnTime(1);
|
|
|
|
if (pair.first == 950116) // khadgar
|
|
DoKhadgarEvents(creature);
|
|
}
|
|
}
|
|
|
|
void SummonShips()
|
|
{
|
|
for (uint8 i = 0; i < 11; ++i)
|
|
{
|
|
uint8 j = urand(0, m_smallShipsPath.size()-1);
|
|
if (auto ship = m_map->SummonCreature(950120, m_smallShipsPath[j]))
|
|
{
|
|
ship->SetPhaseMask(120, true);
|
|
ship->setActive(true);
|
|
m_creatures_first.push_back(ship->GetGUID());
|
|
ship->AI()->DoAction(j);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SummonNPCsByVectorWithRandom(bool addData = false)
|
|
{
|
|
for (uint16 i = 0; i < m_currentVector.size(); ++i)
|
|
{
|
|
if ((!addData || m_scenario->GetCurrentStep() >= 1) && urand(0, 1) == 1)
|
|
continue;
|
|
|
|
m_map->LoadGrid(m_currentVector[i]);
|
|
for (uint16 j = ((urand(1, 100) > 70) ? 0 : 1); j < 2; ++j)
|
|
{
|
|
m_processor.AddDelayedEvent(100 + i * 400, [this, i, addData]() -> void
|
|
{
|
|
Position pos = m_currentVector[i];
|
|
pos.m_positionX += frand(-5.0f, 5.0f);
|
|
pos.m_positionY += frand(-5.0f, 5.0f);
|
|
|
|
if (auto creature = m_map->SummonCreature(GenerateEntry(), pos))
|
|
{
|
|
if (addData)
|
|
creature->SetCustomData(i + 1);
|
|
JustSummonedActions(creature);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
uint32 GenerateEntry() const
|
|
{
|
|
uint32 rand = urand(1, 100);
|
|
if (rand < 96 || m_scenario->GetCurrentStep() <= 1)
|
|
return lowNps[urand(0, lowNps.size() - 1)];
|
|
else if (rand < 99 || m_scenario->GetCurrentStep() <= 1)
|
|
return middleNps[urand(0, middleNps.size() - 1)];
|
|
else
|
|
return highNps[urand(0, highNps.size() - 1)];
|
|
}
|
|
|
|
void DieActionDefault(uint8 data)
|
|
{
|
|
for (uint8 i = ((urand(0,10) > 8) ? 0 : 1); i < 2; ++i)
|
|
{
|
|
m_processor.AddDelayedEvent(urand(5000, 10000), [data, this, i]() -> void
|
|
{
|
|
Position pos = g_firstStepSummonsPosition[data];
|
|
pos.m_positionX += frand(-3.0f, 3.0f);
|
|
pos.m_positionY += frand(-3.0f, 3.0f);
|
|
|
|
m_map->LoadGrid(pos);
|
|
|
|
if (auto creature = m_map->SummonCreature(GenerateEntry(), pos))
|
|
{
|
|
if (i == 1)
|
|
creature->SetCustomData(data + 1);
|
|
JustSummonedActions(creature);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
void JustSummonedActions(Creature* creature)
|
|
{
|
|
creature->SetPvP(false);
|
|
creature->SetPhaseMask(120, true);
|
|
m_creatures.push_back(creature->GetGUID());
|
|
|
|
if (!m_scenario)
|
|
return;
|
|
|
|
creature->setActive(true);
|
|
creature->SetReactState(REACT_AGGRESSIVE);
|
|
creature->CastSpell(creature, SPELL_SUMMON_NPC, true);
|
|
|
|
if (m_scenario->GetCurrentStep() != 0)
|
|
return;
|
|
|
|
creature->GetMotionMaster()->MoveIdle();
|
|
creature->AddDelayedEvent(2900, [creature]() -> void
|
|
{
|
|
creature->GetMotionMaster()->MovePath(145541501, false);
|
|
});
|
|
}
|
|
|
|
void DoKhadgarEvents(Creature* khadgar)
|
|
{
|
|
std::list<Creature*> tempCreatures{};
|
|
|
|
m_map->LoadGrid(-861.04f, 4546.27f);
|
|
|
|
for (uint8 i = 0; i < 23; ++i)
|
|
{
|
|
if (Creature* creature = m_map->SummonCreature(950117, { -861.04f + frand(-9.0f, 9.0f), 4546.27f + frand(-9.0f, 9.0f), 728.19f, 1.43f }))
|
|
{
|
|
creature->SetPhaseMask(120, true);
|
|
m_creatures_first.push_back(creature->GetGUID());
|
|
creature->setActive(true);
|
|
tempCreatures.push_back(creature);
|
|
}
|
|
}
|
|
std::list<Creature*> tempCreatures_1 = tempCreatures;
|
|
Trinity::Containers::RandomResizeList(tempCreatures_1, 4);
|
|
|
|
khadgar->AddDelayedEvent(2000, [khadgar]() -> void
|
|
{
|
|
khadgar->AI()->ZoneTalk(1);
|
|
});
|
|
|
|
uint8 i = 0;
|
|
for (auto creature: tempCreatures_1)
|
|
{
|
|
creature->AddDelayedEvent(12100 + 100 * i, [creature, i] () -> void
|
|
{
|
|
creature->AI()->ZoneTalk(i);
|
|
});
|
|
|
|
++i;
|
|
}
|
|
|
|
khadgar->AddDelayedEvent(16500, [khadgar]() -> void
|
|
{
|
|
khadgar->AI()->ZoneTalk(2);
|
|
});
|
|
|
|
for (auto creature : tempCreatures)
|
|
{
|
|
creature->AddDelayedEvent(19100, [creature] () -> void
|
|
{
|
|
creature->GetMotionMaster()->MovePath(145541501, false, frand(-5.0f, 5.0f), frand(-5.0f, 5.0f));
|
|
});
|
|
}
|
|
|
|
khadgar->AddDelayedEvent(27000, [khadgar, this]() -> void
|
|
{
|
|
if (auto go = m_map->SummonGameObject(276297, -848.25f, 4653.28f, 732.946f, 0.0f, 0, 0, 0, 0, RESPAWN_ONE_DAY))
|
|
{
|
|
go->SetPhaseMask(120, true);
|
|
m_objects.push_back(go->GetGUID());
|
|
}
|
|
khadgar->AI()->ZoneTalk(3);
|
|
});
|
|
|
|
khadgar->AddDelayedEvent(29000, [khadgar, this]() -> void
|
|
{
|
|
if (Creature* arhim = m_map->SummonCreature(950119, g_firstStepSummonsPosition[0]))
|
|
{
|
|
arhim->setActive(true);
|
|
arhim->AI()->ZoneTalk(0);
|
|
arhim->DespawnOrUnsummon(5000);
|
|
}
|
|
});
|
|
|
|
khadgar->AddDelayedEvent(40000, [khadgar, this]() -> void
|
|
{
|
|
khadgar->AI()->ZoneTalk(4);
|
|
});
|
|
|
|
}
|
|
|
|
void DoArtillery(uint32 diff)
|
|
{
|
|
if (m_artilleryTimer <= diff)
|
|
{
|
|
m_artilleryTimer = urand(10000, 20000);
|
|
if (Creature* artillery = m_map->GetCreature(m_creatures_first[urand(0, 2)]))
|
|
{
|
|
uint32 timer = 100;
|
|
for (uint8 team = TEAM_ALLIANCE; team < MAX_TEAMS; ++team)
|
|
for (GuidSet::const_iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr)
|
|
if (Player* player = ObjectAccessor::GetObjectInMap(*itr, m_map, (Player*)nullptr))
|
|
if (urand(1, 2) == 1)
|
|
{
|
|
artillery->CastSpellDelay(player, SPELL_ARRILERRY, false, timer);
|
|
timer += 100;
|
|
}
|
|
|
|
for (const auto& pos : g_firstStepSummonsPosition)
|
|
if (urand(1, 2) == 1)
|
|
{
|
|
artillery->CastSpellDelay(pos, SPELL_ARRILERRY, false, timer);
|
|
timer += 100;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
m_artilleryTimer -= diff;
|
|
}
|
|
|
|
void DoEndTimer(uint32 diff)
|
|
{
|
|
if (m_endTimer <= diff)
|
|
{
|
|
m_processor.KillAllFunctions();
|
|
sGameEventMgr->StopEvent(192, true); // stop, if don't stop
|
|
|
|
ApplyOnEveryPlayerInZone([this](Player* player) -> void
|
|
{
|
|
RemoveScenarioForPlayer(player);
|
|
});
|
|
|
|
for (auto& guid : m_creatures)
|
|
if (auto creature = m_map->GetCreature(guid))
|
|
creature->DespawnOrUnsummon();
|
|
|
|
for (auto& guid : m_creatures_first)
|
|
if (auto creature = m_map->GetCreature(guid))
|
|
creature->DespawnOrUnsummon();
|
|
|
|
for (auto& guid : m_objects)
|
|
if (auto go = m_map->GetGameObject(guid))
|
|
{
|
|
go->SetRespawnTime(0);
|
|
go->Delete();
|
|
}
|
|
|
|
m_creatures.clear();
|
|
m_creatures_first.clear();
|
|
m_objects.clear();
|
|
m_secondStepState = 0;
|
|
|
|
delete m_scenario;
|
|
m_scenario = nullptr;
|
|
}
|
|
else
|
|
m_endTimer -= diff;
|
|
}
|
|
|
|
void DoEventTimer(uint32 diff)
|
|
{
|
|
if (!m_needEvent)
|
|
return;
|
|
|
|
if (m_eventTimer <= diff)
|
|
{
|
|
SummonNPCsByVectorWithRandom(m_creatures.empty());
|
|
m_eventTimer = urand(120, 240) * 1000;
|
|
}
|
|
else
|
|
m_eventTimer -= diff;
|
|
}
|
|
|
|
void DoUpdateCriterias(Player* player, Unit* killed)
|
|
{
|
|
switch (m_scenario->GetCurrentStep())
|
|
{
|
|
case 0:
|
|
m_scenario->UpdateAchievementCriteria(CRITERIA_TYPE_SCRIPT_EVENT_2, 46005, 1, 0, nullptr, player);
|
|
break;
|
|
case 1:
|
|
{
|
|
bool needSummon = false;
|
|
if (std::find(middleNps.begin(), middleNps.end(), killed->GetEntry()) != middleNps.end())
|
|
{
|
|
m_scenario->UpdateAchievementCriteria(CRITERIA_TYPE_SCRIPT_EVENT_2, 51810, 1, 0, nullptr, player);
|
|
needSummon = true;
|
|
}
|
|
else if (std::find(highNps.begin(), highNps.end(), killed->GetEntry()) != highNps.end())
|
|
{
|
|
m_scenario->UpdateAchievementCriteria(CRITERIA_TYPE_SCRIPT_EVENT_2, 51823, 1, 0, nullptr, player);
|
|
needSummon = true;
|
|
}
|
|
|
|
if (needSummon)
|
|
{
|
|
uint32 entry = 0;
|
|
switch (++m_secondStepState)
|
|
{
|
|
case 1:
|
|
entry = middleNps[urand(0, middleNps.size() - 1)];
|
|
break;
|
|
case 2:
|
|
entry = highNps[urand(0, highNps.size() - 1)];
|
|
break;
|
|
}
|
|
if (entry)
|
|
if (auto creature = m_map->SummonCreature(entry, m_currentVector[urand(0, m_currentVector.size())]))
|
|
JustSummonedActions(creature);
|
|
}
|
|
break;
|
|
}
|
|
case 2:
|
|
if (killed->GetEntry() == 109761 || killed->GetEntry() == 114259)
|
|
{
|
|
for (uint8 i = urand(0, 2); i < 4; ++i)
|
|
m_scenario->UpdateAchievementCriteria(CRITERIA_TYPE_SCRIPT_EVENT_2, 50991, 1, 0, nullptr, player);
|
|
m_scenario->UpdateAchievementCriteria(CRITERIA_TYPE_SCRIPT_EVENT_2, 46005, 1, 0, nullptr, player);
|
|
}
|
|
else
|
|
m_scenario->UpdateAchievementCriteria(CRITERIA_TYPE_SCRIPT_EVENT_2, 50990, 1, 0, nullptr, player);
|
|
break;
|
|
case 3:
|
|
if (std::find(bosses.begin(), bosses.end(), killed->GetEntry()) != bosses.end())
|
|
m_scenario->UpdateAchievementCriteria(CRITERIA_TYPE_SCRIPT_EVENT_2, 52035, 1, 0, nullptr, player);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void DoThirdStepSummons()
|
|
{
|
|
if (m_thirdStepGOs.size() >= 3)
|
|
return;
|
|
|
|
std::list<uint8> canPositions{ 0, 1, 2, 3, 4, 5 };
|
|
for (auto id : m_thirdStepGOs)
|
|
canPositions.remove(id);
|
|
|
|
if (canPositions.empty())
|
|
return;
|
|
|
|
Trinity::Containers::RandomResizeList(canPositions, 3 - m_thirdStepGOs.size() + (m_thirdStepGOs.empty() ? 0 : 1));
|
|
for (auto id : canPositions)
|
|
{
|
|
if (auto trigger = m_map->SummonCreature(g_thirdNPCs[id].first, g_thirdNPCs[id].second))
|
|
{
|
|
trigger->SetCustomData(id + 1);
|
|
trigger->setActive(true);
|
|
trigger->SetPhaseMask(120, true);
|
|
m_creatures.push_back(trigger->GetGUID());
|
|
m_thirdStepGOs.insert(id);
|
|
}
|
|
}
|
|
}
|
|
|
|
Scenario* m_scenario{};
|
|
uint32 m_endTimer{};
|
|
std::vector<ObjectGuid> m_creatures_first{};
|
|
std::list<ObjectGuid> m_creatures{};
|
|
std::list<ObjectGuid> m_objects{};
|
|
std::vector<Position> m_currentVector{};
|
|
std::set<uint8> m_thirdStepGOs{};
|
|
|
|
FunctionProcessor m_processor{};
|
|
|
|
bool m_needEvent = false;
|
|
uint32 m_eventTimer{};
|
|
uint8 m_secondStepState = 0;
|
|
uint32 m_artilleryTimer = 0;
|
|
};
|
|
|
|
class OutdoorPvP_dalaran_invasion : public OutdoorPvPScript
|
|
{
|
|
public:
|
|
OutdoorPvP_dalaran_invasion() : OutdoorPvPScript("outdoorpvp_dalaran_invasion") {}
|
|
|
|
OutdoorPvP* GetOutdoorPvP() const override
|
|
{
|
|
return new OutdoorPVPdalaran_invasion();
|
|
}
|
|
};
|
|
|
|
// 109761, 114259
|
|
struct npc_invasion_event_gobs_triggers : public ScriptedAI
|
|
{
|
|
npc_invasion_event_gobs_triggers(Creature* creature) : ScriptedAI(creature) {}
|
|
|
|
uint32 spellSum{}, spellDesp{}, goEntry{};
|
|
ObjectGuid go{};
|
|
|
|
void InitializeAI() override
|
|
{
|
|
me->setActive(true);
|
|
|
|
switch (me->GetEntry())
|
|
{
|
|
case 109761:
|
|
spellSum = 207688;
|
|
spellDesp = 218496;
|
|
goEntry = 241610;
|
|
break;
|
|
case 114259: // small
|
|
spellSum = 227295;
|
|
spellDesp = 227775;
|
|
goEntry = 243448;
|
|
break;
|
|
}
|
|
|
|
me->AddDelayedEvent(1000, [this]() -> void
|
|
{
|
|
me->CastSpell(me, spellSum);
|
|
me->AddDelayedEvent(9000, [this]
|
|
{
|
|
auto outdoor = me->GetOutdoorPvP();
|
|
if (!outdoor)
|
|
return;
|
|
|
|
if (auto gob = me->SummonGameObject(goEntry, me->GetPosition(), me->GetOrientation(), 0, 0, 0, 0, 30 * 60))
|
|
{
|
|
gob->setActive(true);
|
|
gob->SetPhaseMask(120, true);
|
|
outdoor->SetGuidData(1, gob->GetGUID());
|
|
go = gob->GetGUID();
|
|
}
|
|
|
|
if (auto crystal = me->SummonCreature(98371, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 3.0f, 0, TEMPSUMMON_TIMED_DESPAWN, 30 * 60 * 1000))
|
|
{
|
|
outdoor->SetGuidData(0, crystal->GetGUID());
|
|
crystal->SetReactState(REACT_PASSIVE);
|
|
crystal->SetCustomData(me->GetCustomData());
|
|
}
|
|
|
|
float diff = isSmall() ? 0 : 4;
|
|
for (uint8 i = 0; i < (isSmall() ? 1 : 3);++i)
|
|
if (auto creature = me->SummonCreature(lowNps[urand(0, lowNps.size() - 1)], me->GetPositionX() + frand(-diff, diff), me->GetPositionY() + frand(-diff, diff), me->GetPositionZ() + 3.0f))
|
|
outdoor->SetGuidData(0, creature->GetGUID());
|
|
});
|
|
});
|
|
}
|
|
|
|
void SummonedCreatureDies(Creature* creature, Unit* killer) override
|
|
{
|
|
if (creature->GetEntry() == 98371)
|
|
{
|
|
creature->DespawnOrUnsummon(1);
|
|
if (auto gob = me->GetMap()->GetGameObject(go))
|
|
{
|
|
gob->SetRespawnTime(0);
|
|
gob->Delete();
|
|
}
|
|
|
|
if (auto outdoor = me->GetOutdoorPvP())
|
|
outdoor->HandleKill(killer, me);
|
|
|
|
me->CastSpell(me, spellDesp);
|
|
me->DespawnOrUnsummon(10000);
|
|
}
|
|
else if (auto outdoor = me->GetOutdoorPvP())
|
|
outdoor->HandleKill(killer, creature);
|
|
|
|
}
|
|
|
|
bool isSmall() const
|
|
{
|
|
return me->GetEntry() == 114259;
|
|
}
|
|
};
|
|
|
|
// 950120
|
|
struct npc_invasion_event_fly_ships : public ScriptedAI
|
|
{
|
|
npc_invasion_event_fly_ships(Creature* creature) : ScriptedAI(creature) {}
|
|
|
|
std::vector<Position> m_path{};
|
|
uint32 timer{};
|
|
|
|
void DoAction(int32 const act) override
|
|
{
|
|
me->SetReactState(REACT_PASSIVE);
|
|
auto itr = m_smallShipsPath.begin();
|
|
std::advance(itr, act);
|
|
m_path.insert(m_path.end(), itr, m_smallShipsPath.end());
|
|
m_path.insert(m_path.end(), m_smallShipsPath.begin(), itr);
|
|
|
|
if (urand(1, 2) == 1)
|
|
std::reverse(m_path.begin(), m_path.end());
|
|
|
|
for (auto& pos : m_path)
|
|
{
|
|
pos.m_positionX += frand(-5.0f, 5.0f);
|
|
pos.m_positionY += frand(-5.0f, 5.0f);
|
|
pos.m_positionZ -= frand(0.0f, 10.0f);
|
|
}
|
|
|
|
me->GetMotionMaster()->MovePoint(1, m_path[0]);
|
|
timer = 5000;
|
|
}
|
|
|
|
void MovementInform(uint32 type, uint32 point) override
|
|
{
|
|
if (type != POINT_MOTION_TYPE)
|
|
return;
|
|
|
|
me->AddDelayedEvent(500, [this, point]()
|
|
{
|
|
me->GetMotionMaster()->MovePoint((point % 4) + 1, m_path[point % 4]);
|
|
});
|
|
}
|
|
|
|
void UpdateAI(uint32 diff) override
|
|
{
|
|
if (timer <= diff)
|
|
{
|
|
me->CastSpell(me->GetPositionX() + frand(-8.0f, 8.0f), me->GetPositionY() + frand(-8.0f, 8.0f), me->GetWaterOrGroundLevel(me->GetPosition()), 249933);
|
|
timer = urand(1000, 1500);
|
|
}
|
|
else
|
|
timer -= diff;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void Addsc_dalaran_invasion()
|
|
{
|
|
new OutdoorPvP_dalaran_invasion();
|
|
RegisterCreatureAI(npc_invasion_event_gobs_triggers);
|
|
RegisterCreatureAI(npc_invasion_event_fly_ships);
|
|
} |