Exiles Reach: bind boar ride scene 2338 to its SceneScript (works without core change)
Move the Giant Boar ride scene triggers ('Trampling Time', 'Big Kill Credit', 'Knockback') from exiles_reach_general_playerscript::OnSceneTriggerEvent into a new scene_exiles_reach_boar_ride SceneScript, bound via scene_template.ScriptName (SQL included). Core dispatches these events to the bound SceneScript on every branch, so the boar trample spell works without the ScriptMgr.cpp PlayerScript fan-out change. 'Teleport' triggers stay in the PlayerScript hook.
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
-- Exiles Reach: bind the Giant Boar ride scene (SceneId 2338, package 2712) to its SceneScript.
|
||||
-- During the boar ride ("Ride of the Scientifically Enhanced Boar" / "The Redeather") the client
|
||||
-- fires "Trampling Time", "Big Kill Credit" and "Knockback" trigger events; core only dispatches
|
||||
-- those to a bound SceneScript via scene_template.ScriptName. The script itself lives in
|
||||
-- src/server/scripts/ExilesReach/exiles_reach.cpp (scene_exiles_reach_boar_ride).
|
||||
UPDATE `scene_template` SET `ScriptName` = 'scene_exiles_reach_boar_ride' WHERE `SceneId` = 2338;
|
||||
@@ -95,41 +95,11 @@ public:
|
||||
if (player->GetMapId() != MAP_EXILES_REACH)
|
||||
return;
|
||||
|
||||
if (sceneEvent == "Big Kill Credit")
|
||||
{
|
||||
player->CastSpell(player, SPELL_CADAVER_KILL_CREDIT);
|
||||
|
||||
if (player->GetQuestObjectiveProgress(QUEST_H_THE_REDEATHER, 2) == 8)
|
||||
{
|
||||
player->CastSpell(player, SPELL_CADAVER_CREDIT_CHECK_CHOPPY_MALFUNCTION, true);
|
||||
}
|
||||
|
||||
if (player->GetQuestObjectiveProgress(QUEST_RIDE_OF_THE_SCIENTIFICALLY_ENHANCED_BOAR, 2) == 8)
|
||||
{
|
||||
player->CastSpell(player, SPELL_GIANT_BOAR_PING_VEHICLE, true);
|
||||
}
|
||||
|
||||
// The boar mowed the undead down: despawn the hostile mobs around
|
||||
// the rider so the trampled army actually vanishes (and stops
|
||||
// attacking). Tied to the reliable scene credit rather than the
|
||||
// trample's own grid search.
|
||||
std::list<Creature*> mobs;
|
||||
Trinity::AnyUnitInObjectRangeCheck u_check(player, 50.0f);
|
||||
Trinity::CreatureListSearcher<Trinity::AnyUnitInObjectRangeCheck> searcher(player, mobs, u_check);
|
||||
Cell::VisitGridObjects(player, searcher, 50.0f);
|
||||
for (Creature* mob : mobs)
|
||||
{
|
||||
if (!player->IsHostileTo(mob))
|
||||
continue;
|
||||
if (mob->GetEntry() == NPC_OGRE_RUINS_TORGOK)
|
||||
continue; // leave the boss for the fight
|
||||
// Track so the undead can be respawned if the quest is abandoned.
|
||||
s_mowedDownUndead.insert(mob->GetSpawnId());
|
||||
// Long respawn delay so the mowed-down undead stay dead
|
||||
// through the rest of the ride instead of popping back.
|
||||
mob->DespawnOrUnsummon(0s, 1h);
|
||||
}
|
||||
}
|
||||
// NOTE: The Giant Boar ride triggers ("Big Kill Credit", "Knockback",
|
||||
// "Trampling Time") are handled in scene_exiles_reach_boar_ride below,
|
||||
// bound to scene_template.SceneId = 2338 via SQL. SceneScripts are
|
||||
// dispatched by core on every branch, so the ride works without any
|
||||
// core changes and fires exactly once per event.
|
||||
|
||||
if (sceneEvent == "Teleport")
|
||||
{
|
||||
@@ -164,21 +134,6 @@ public:
|
||||
player->CastSpell(player, SPELL_ORGRIMMAR_TELEPORT, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (sceneEvent == "Knockback")
|
||||
{
|
||||
player->CastSpell(player, SPELL_GIANT_BOAR_RIDING_KNOCKBACK, true);
|
||||
}
|
||||
|
||||
if (sceneEvent == "Trampling Time")
|
||||
{
|
||||
if (Creature* giantBoarVehicle = player->GetVehicleCreatureBase())
|
||||
{
|
||||
Position targetLoc = giantBoarVehicle->GetFirstCollisionPosition(20.f, 0.f);
|
||||
giantBoarVehicle->GetMotionMaster()->MoveCharge(targetLoc.GetPositionX(), targetLoc.GetPositionY(), targetLoc.GetPositionZ());
|
||||
player->CastSpell(player, SPELL_GIANT_BOAR_TRAMPLE, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnUpdateArea(Player* player, uint32 newArea, uint32 /*oldArea*/) override
|
||||
@@ -255,6 +210,84 @@ public:
|
||||
std::unordered_set<ObjectGuid::LowType> exiles_reach_general_playerscript::s_mowedDownUndead;
|
||||
std::unordered_set<ObjectGuid> exiles_reach_general_playerscript::s_rideActivePlayers;
|
||||
|
||||
/* ## SCENE SCRIPTS > ## */
|
||||
|
||||
// Giant Boar ride (scene_template.SceneId = 2338, package 2712) -
|
||||
// "Ride of the Scientifically Enhanced Boar" / "The Redeather".
|
||||
//
|
||||
// The client fires these trigger events from scene package 2712 during the boar
|
||||
// ride (verified against a retail 12.1 packet capture):
|
||||
// Conversation, then repeating pairs of "Trampling Time" + "Big Kill Credit",
|
||||
// plus "Knockback" and "Hint", until SMSG_CANCEL_SCENE.
|
||||
//
|
||||
// The logic is bound to the scene via scene_template.ScriptName (see SQL
|
||||
// update) instead of living in the PlayerScript hook above: core dispatches
|
||||
// scene trigger events to a bound SceneScript on every branch, while
|
||||
// OnSceneTriggerEvent only reaches PlayerScripts when an extra core change is
|
||||
// present. Keeping it here means each event fires exactly once on both.
|
||||
class scene_exiles_reach_boar_ride : public SceneScript
|
||||
{
|
||||
public:
|
||||
scene_exiles_reach_boar_ride() : SceneScript("scene_exiles_reach_boar_ride") {}
|
||||
|
||||
void OnSceneTriggerEvent(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/, std::string const& triggerName) override
|
||||
{
|
||||
if (player->GetMapId() != MAP_EXILES_REACH)
|
||||
return;
|
||||
|
||||
if (triggerName == "Big Kill Credit")
|
||||
{
|
||||
player->CastSpell(player, SPELL_CADAVER_KILL_CREDIT);
|
||||
|
||||
if (player->GetQuestObjectiveProgress(QUEST_H_THE_REDEATHER, 2) == 8)
|
||||
{
|
||||
player->CastSpell(player, SPELL_CADAVER_CREDIT_CHECK_CHOPPY_MALFUNCTION, true);
|
||||
}
|
||||
|
||||
if (player->GetQuestObjectiveProgress(QUEST_RIDE_OF_THE_SCIENTIFICALLY_ENHANCED_BOAR, 2) == 8)
|
||||
{
|
||||
player->CastSpell(player, SPELL_GIANT_BOAR_PING_VEHICLE, true);
|
||||
}
|
||||
|
||||
// The boar mowed the undead down: despawn the hostile mobs around
|
||||
// the rider so the trampled army actually vanishes (and stops
|
||||
// attacking). Tied to the reliable scene credit rather than the
|
||||
// trample's own grid search.
|
||||
std::list<Creature*> mobs;
|
||||
Trinity::AnyUnitInObjectRangeCheck u_check(player, 50.0f);
|
||||
Trinity::CreatureListSearcher<Trinity::AnyUnitInObjectRangeCheck> searcher(player, mobs, u_check);
|
||||
Cell::VisitGridObjects(player, searcher, 50.0f);
|
||||
for (Creature* mob : mobs)
|
||||
{
|
||||
if (!player->IsHostileTo(mob))
|
||||
continue;
|
||||
if (mob->GetEntry() == NPC_OGRE_RUINS_TORGOK)
|
||||
continue; // leave the boss for the fight
|
||||
// Track so the undead can be respawned if the quest is abandoned.
|
||||
exiles_reach_general_playerscript::s_mowedDownUndead.insert(mob->GetSpawnId());
|
||||
// Long respawn delay so the mowed-down undead stay dead
|
||||
// through the rest of the ride instead of popping back.
|
||||
mob->DespawnOrUnsummon(0s, 1h);
|
||||
}
|
||||
}
|
||||
|
||||
if (triggerName == "Knockback")
|
||||
{
|
||||
player->CastSpell(player, SPELL_GIANT_BOAR_RIDING_KNOCKBACK, true);
|
||||
}
|
||||
|
||||
if (triggerName == "Trampling Time")
|
||||
{
|
||||
if (Creature* giantBoarVehicle = player->GetVehicleCreatureBase())
|
||||
{
|
||||
Position targetLoc = giantBoarVehicle->GetFirstCollisionPosition(20.f, 0.f);
|
||||
giantBoarVehicle->GetMotionMaster()->MoveCharge(targetLoc.GetPositionX(), targetLoc.GetPositionY(), targetLoc.GetPositionZ());
|
||||
player->CastSpell(player, SPELL_GIANT_BOAR_TRAMPLE, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class map_exiles_reach : public WorldMapScript
|
||||
{
|
||||
public:
|
||||
@@ -464,6 +497,8 @@ void AddSC_exiles_reach_general()
|
||||
{
|
||||
// Player Scripts
|
||||
new exiles_reach_general_playerscript();
|
||||
// Scene Scripts
|
||||
new scene_exiles_reach_boar_ride();
|
||||
// WorldMap Scripts
|
||||
new map_exiles_reach();
|
||||
// Spell Scripts
|
||||
|
||||
Reference in New Issue
Block a user