mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-27 07:36:23 +00:00
fix(Scripts/Midsummer): Implement Ribbon Pole dance effects (#17417)
* fix(Scripts/Midsummer): Implement Ribbon Pole dance effects * midsummer.cpp: remove whitespaces at end of lines * midsummer.cpp: fix unused parameter error * add spacing after 0.0f * replace Milliseconds(...) by ...ms and Seconds(...) by ...s * cleanup comments * remove manual cleanups / despawns from DoCleanupChecks() - rely on NPC despawn timers - manual cleanup / removal actually is a bit excessive * set INTERVAL_DANCING_FLAMES to 15s * set despawn time to 1min for big dancing flames according to spell 46827 * set spawnDist to 12 for big dancing flames according so spell 46827 * use library function Acore::Containers::RandomShuffle() to shuffle _danclerList * sql: do not set SmartAI for NPC 17066 already using ScriptName and can't have both * combine 3 sql files into 1 * remove INTERVAL_... enum values * remove unnecessary checks of if(_bunny) * sql: fix smartscript comment * rename spell define to correct spell name
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
-- midsummer creatureAI npc_midsummer_ribbon_pole_target
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_midsummer_ribbon_pole_target' WHERE `entry` = 17066;
|
||||
|
||||
-- midsummer NPC Big Dancing Flame - SmartAI - fire dance spell
|
||||
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 26267;
|
||||
|
||||
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 26267);
|
||||
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
|
||||
(26267, 0, 0, 0, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 45418, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Big Dancing Flames - On Just Summoned - Cast Spell \'Fire Dancing\'');
|
||||
|
||||
-- midsummer add spell script spell_midsummer_ribbon_pole_firework
|
||||
DELETE FROM `spell_script_names` WHERE `spell_id` = 46847;
|
||||
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
|
||||
(46847, 'spell_midsummer_ribbon_pole_firework');
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "Spell.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "SpellScript.h"
|
||||
#include <random>
|
||||
|
||||
enum eBonfire
|
||||
{
|
||||
@@ -210,15 +211,276 @@ class spell_gen_crab_disguise : public AuraScript
|
||||
|
||||
enum RibbonPole
|
||||
{
|
||||
GO_RIBBON_POLE = 181605,
|
||||
|
||||
SPELL_RIBBON_POLE_CHANNEL_VISUAL = 29172,
|
||||
SPELL_RIBBON_POLE_CHANNEL_VISUAL_2 = 29531,
|
||||
SPELL_TEST_RIBBON_POLE_CHANNEL_BLUE = 29705,
|
||||
SPELL_TEST_RIBBON_POLE_CHANNEL_RED = 29726,
|
||||
SPELL_TEST_RIBBON_POLE_CHANNEL_PINK = 29727,
|
||||
// player spinning/rorating around himself
|
||||
SPELL_RIBBON_POLE_PERIODIC_VISUAL = 45406,
|
||||
// spew lava trails
|
||||
SPELL_RIBBON_POLE_FIRE_SPIRAL_VISUAL= 45421,
|
||||
// blue fire ring, duration 5s
|
||||
SPELL_FLAME_RING = 46842,
|
||||
// red fire ring, duration 5s
|
||||
SPELL_FLAME_PATCH = 46836,
|
||||
// single firework explosion
|
||||
SPELL_RIBBON_POLE_FIREWORK = 46847,
|
||||
SPELL_RIBBON_POLE_GROUND_FLOWER = 46969,
|
||||
SPELL_RIBBON_POLE_XP = 29175,
|
||||
SPELL_RIBBON_POLE_FIREWORKS = 46971,
|
||||
|
||||
NPC_RIBBON_POLE_DEBUG_TARGET = 17066,
|
||||
NPC_GROUND_FLOWER = 25518,
|
||||
NPC_BIG_DANCING_FLAMES = 26267,
|
||||
NPC_RIBBON_POLE_FIRE_SPIRAL_BUNNY = 25303,
|
||||
|
||||
// dancing players count
|
||||
THRESHOLD_FLAME_CIRCLE = 1,
|
||||
THRESHOLD_FIREWORK = 2,
|
||||
THRESHOLD_FIREWORK_3 = 3,
|
||||
THRESHOLD_FIREWORK_5 = 5,
|
||||
THRESHOLD_GROUND_FLOWERS = 3,
|
||||
THRESHOLD_SPEW_LAVA = 6,
|
||||
THRESHOLD_DANCING_FLAMES = 7,
|
||||
|
||||
MAX_COUNT_GROUND_FLOWERS = 3,
|
||||
MAX_COUNT_SPEW_LAVA_TARGETS = 2,
|
||||
MAX_COUNT_DANCING_FLAMES = 4,
|
||||
};
|
||||
|
||||
struct npc_midsummer_ribbon_pole_target : public ScriptedAI
|
||||
{
|
||||
npc_midsummer_ribbon_pole_target(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
// ribbonPole trap also spawns this NPC (currently unwanted)
|
||||
if (me->ToTempSummon())
|
||||
me->DespawnOrUnsummon();
|
||||
|
||||
_ribbonPole = nullptr;
|
||||
_bunny = nullptr;
|
||||
_dancerList.clear();
|
||||
|
||||
LocateRibbonPole();
|
||||
SpawnFireSpiralBunny();
|
||||
|
||||
_scheduler.Schedule(1s, [this](TaskContext context)
|
||||
{
|
||||
DoCleanupChecks();
|
||||
context.Repeat();
|
||||
})
|
||||
.Schedule(5s, [this](TaskContext context)
|
||||
{
|
||||
DoFlameCircleChecks();
|
||||
context.Repeat();
|
||||
})
|
||||
.Schedule(15s, [this](TaskContext context)
|
||||
{
|
||||
DoFireworkChecks();
|
||||
context.Repeat();
|
||||
})
|
||||
.Schedule(10s, [this](TaskContext context)
|
||||
{
|
||||
DoGroundFlowerChecks();
|
||||
context.Repeat();
|
||||
})
|
||||
.Schedule(10s, [this](TaskContext context)
|
||||
{
|
||||
DoSpewLavaChecks();
|
||||
context.Repeat();
|
||||
})
|
||||
.Schedule(15s, [this](TaskContext context)
|
||||
{
|
||||
DoDancingFLameChecks();
|
||||
context.Repeat();
|
||||
});
|
||||
}
|
||||
|
||||
void SpellHit(Unit* caster, SpellInfo const* spell) override
|
||||
{
|
||||
Player* dancer = caster->ToPlayer();
|
||||
if (!dancer)
|
||||
return;
|
||||
|
||||
switch (spell->Id)
|
||||
{
|
||||
case SPELL_TEST_RIBBON_POLE_CHANNEL_BLUE:
|
||||
case SPELL_TEST_RIBBON_POLE_CHANNEL_RED:
|
||||
case SPELL_TEST_RIBBON_POLE_CHANNEL_PINK:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// prevent duplicates
|
||||
if (std::find(_dancerList.begin(), _dancerList.end(), dancer) != _dancerList.end())
|
||||
return;
|
||||
|
||||
_dancerList.push_back(dancer);
|
||||
}
|
||||
|
||||
void LocateRibbonPole()
|
||||
{
|
||||
_scheduler.Schedule(420ms, [this](TaskContext context)
|
||||
{
|
||||
_ribbonPole = me->FindNearestGameObject(GO_RIBBON_POLE, 10.0f);
|
||||
|
||||
if (!_ribbonPole)
|
||||
context.Repeat(420ms);
|
||||
});
|
||||
}
|
||||
|
||||
void SpawnFireSpiralBunny()
|
||||
{
|
||||
_bunny = me->FindNearestCreature(NPC_RIBBON_POLE_FIRE_SPIRAL_BUNNY, 10.0f);
|
||||
|
||||
if (!_bunny)
|
||||
_bunny = DoSpawnCreature(NPC_RIBBON_POLE_FIRE_SPIRAL_BUNNY, 0, 0, 0, 0, TEMPSUMMON_MANUAL_DESPAWN, 0);
|
||||
}
|
||||
|
||||
void DoCleanupChecks()
|
||||
{
|
||||
if (_dancerList.empty())
|
||||
return;
|
||||
|
||||
// remove non-dancing players from list
|
||||
std::erase_if(_dancerList, [](Player* dancer)
|
||||
{
|
||||
return !dancer->HasAura(SPELL_RIBBON_POLE_PERIODIC_VISUAL);
|
||||
});
|
||||
}
|
||||
|
||||
void DoFlameCircleChecks()
|
||||
{
|
||||
if (!_ribbonPole)
|
||||
return;
|
||||
if (_dancerList.size() >= THRESHOLD_FLAME_CIRCLE)
|
||||
{
|
||||
// random blue / red circle
|
||||
if (urand(0, 1))
|
||||
_ribbonPole->CastSpell(me, SPELL_FLAME_RING);
|
||||
else
|
||||
_ribbonPole->CastSpell(me, SPELL_FLAME_PATCH);
|
||||
}
|
||||
}
|
||||
|
||||
void DoFireworkChecks()
|
||||
{
|
||||
if (!_bunny)
|
||||
return;
|
||||
|
||||
if (_dancerList.size() >= THRESHOLD_FIREWORK)
|
||||
{
|
||||
_bunny->CastSpell(nullptr, SPELL_RIBBON_POLE_FIREWORK);
|
||||
}
|
||||
if (_dancerList.size() >= THRESHOLD_FIREWORK_3)
|
||||
{
|
||||
_scheduler.Schedule(500ms, [this](TaskContext /*context*/)
|
||||
{
|
||||
_bunny->CastSpell(nullptr, SPELL_RIBBON_POLE_FIREWORK);
|
||||
})
|
||||
.Schedule(1s, [this](TaskContext /*context*/)
|
||||
{
|
||||
_bunny->CastSpell(nullptr, SPELL_RIBBON_POLE_FIREWORK);
|
||||
});
|
||||
}
|
||||
if (_dancerList.size() >= THRESHOLD_FIREWORK_5)
|
||||
{
|
||||
_scheduler.Schedule(1500ms, [this](TaskContext /*context*/)
|
||||
{
|
||||
_bunny->CastSpell(nullptr, SPELL_RIBBON_POLE_FIREWORK);
|
||||
})
|
||||
.Schedule(2s, [this](TaskContext /*context*/)
|
||||
{
|
||||
_bunny->CastSpell(nullptr, SPELL_RIBBON_POLE_FIREWORK);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void DoGroundFlowerChecks()
|
||||
{
|
||||
if (!_bunny)
|
||||
return;
|
||||
|
||||
if (_dancerList.size() >= THRESHOLD_GROUND_FLOWERS)
|
||||
{
|
||||
std::list<Creature*> crList;
|
||||
me->GetCreaturesWithEntryInRange(crList, 20.0f, NPC_GROUND_FLOWER);
|
||||
|
||||
if (crList.size() < MAX_COUNT_GROUND_FLOWERS)
|
||||
_bunny->CastSpell(nullptr, SPELL_RIBBON_POLE_GROUND_FLOWER);
|
||||
}
|
||||
}
|
||||
|
||||
void DoSpewLavaChecks()
|
||||
{
|
||||
if (!_bunny)
|
||||
return;
|
||||
|
||||
if (_dancerList.size() >= THRESHOLD_SPEW_LAVA)
|
||||
{
|
||||
if (!_dancerList.empty())
|
||||
{
|
||||
Acore::Containers::RandomShuffle(_dancerList);
|
||||
|
||||
for (uint8 i = 0; (i < MAX_COUNT_SPEW_LAVA_TARGETS) && (i < _dancerList.size()); i++)
|
||||
{
|
||||
Player* dancerTarget = _dancerList[i];
|
||||
|
||||
if (dancerTarget)
|
||||
{
|
||||
Creature* fireSpiralBunny = dancerTarget->SummonCreature(NPC_RIBBON_POLE_FIRE_SPIRAL_BUNNY, dancerTarget->GetPositionX(), dancerTarget->GetPositionY(), dancerTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000);
|
||||
if (fireSpiralBunny)
|
||||
fireSpiralBunny->CastSpell(_bunny, SPELL_RIBBON_POLE_FIRE_SPIRAL_VISUAL, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoDancingFLameChecks()
|
||||
{
|
||||
if (_dancerList.size() >= THRESHOLD_DANCING_FLAMES)
|
||||
{
|
||||
std::list<Creature*> crList;
|
||||
me->GetCreaturesWithEntryInRange(crList, 20.0f, NPC_BIG_DANCING_FLAMES);
|
||||
|
||||
if (crList.size() < MAX_COUNT_DANCING_FLAMES)
|
||||
{
|
||||
float spawnDist = 12.0f;
|
||||
float angle = rand_norm() * 2 * M_PI;
|
||||
DoSpawnCreature(NPC_BIG_DANCING_FLAMES, spawnDist * cos(angle), spawnDist * std::sin(angle), 0, angle + M_PI, TEMPSUMMON_TIMED_DESPAWN, 60000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
_scheduler.Update(diff);
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
std::vector<Player*> _dancerList;
|
||||
GameObject* _ribbonPole;
|
||||
Creature* _bunny;
|
||||
};
|
||||
|
||||
class spell_midsummer_ribbon_pole_firework : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_midsummer_ribbon_pole_firework)
|
||||
|
||||
void ModDestHeight(SpellDestination& dest)
|
||||
{
|
||||
Position const offset = { 0.0f, 0.0f, 20.0f , 0.0f };
|
||||
dest.RelocateOffset(offset);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_midsummer_ribbon_pole_firework::ModDestHeight, EFFECT_0, TARGET_DEST_CASTER_RANDOM);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_midsummer_ribbon_pole : public AuraScript
|
||||
@@ -617,9 +879,11 @@ void AddSC_event_midsummer_scripts()
|
||||
// NPCs
|
||||
new go_midsummer_bonfire();
|
||||
RegisterCreatureAI(npc_midsummer_torch_target);
|
||||
RegisterCreatureAI(npc_midsummer_ribbon_pole_target);
|
||||
|
||||
// Spells
|
||||
RegisterSpellScript(spell_gen_crab_disguise);
|
||||
RegisterSpellScript(spell_midsummer_ribbon_pole_firework);
|
||||
RegisterSpellScript(spell_midsummer_ribbon_pole);
|
||||
RegisterSpellScript(spell_midsummer_ribbon_pole_visual);
|
||||
RegisterSpellScript(spell_midsummer_torch_quest);
|
||||
|
||||
Reference in New Issue
Block a user