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:
Jman
2026-09-17 08:06:54 +10:00
parent a17899e921
commit a63829a130
2 changed files with 91 additions and 50 deletions
@@ -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;
+85 -50
View File
@@ -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