Fix Dire Beast (120679): summoned beasts now attack the hunter target

The spell script spell_hun_dire_beast summoned the zone "Beast" guardian but
never ordered it to attack, and the ~108 summon templates had no AIName/ScriptName,
so the beasts idled next to the owner instead of engaging the target.

Add a dedicated ScriptedAI npc_pet_hun_dire_beast (mirroring npc_pet_hunter_snake_trap,
minus the snake-specific level-40 health formula and poison) that, on spawn, attacks
the summoner target (owner GetVictim / getAttackerForHelper), and bind it to the 108
inert level-1 friendly "Beast" summon templates via sql/sylvania/dire_beast_ai_20260705.sql.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
SylvaniaCore deploy
2026-07-05 21:18:48 +00:00
parent 89168bc275
commit 7b178bb198
2 changed files with 72 additions and 0 deletions
+15
View File
@@ -0,0 +1,15 @@
-- Dire Beast (spell 120679 "Bête féroce") — the summoned "Beast" guardians had no AI/ScriptName
-- and never engaged the hunter's target (they idled next to the owner).
-- Bind them to the new C++ AI npc_pet_hun_dire_beast (added to src/server/scripts/Pet/pet_hunter.cpp),
-- which orders the summon to attack the summoner's target on spawn.
-- Targets the 108 inert level-1 friendly "Beast" summon templates (one per zone/expansion).
-- 2026-07-05
UPDATE `creature_template`
SET `ScriptName` = 'npc_pet_hun_dire_beast'
WHERE `name` = 'Beast'
AND `type` = 1
AND `faction` = 35
AND `minlevel` = 1
AND `maxlevel` = 1
AND (`AIName` IS NULL OR `AIName` = '')
AND (`ScriptName` IS NULL OR `ScriptName` = '');
+57
View File
@@ -181,8 +181,65 @@ public:
}
};
// Dire Beast (120679) summoned "Beast" - order the summoned beast to attack the hunter's target.
// Same proven pattern as npc_pet_hunter_snake_trap, without the snake-specific health/poison
// (dire beasts are level 1 -> the snake health formula would underflow).
class npc_pet_hun_dire_beast : public CreatureScript
{
public:
npc_pet_hun_dire_beast() : CreatureScript("npc_pet_hun_dire_beast") { }
struct npc_pet_hun_dire_beastAI : public ScriptedAI
{
npc_pet_hun_dire_beastAI(Creature* creature) : ScriptedAI(creature) { }
void EnterCombat(Unit* /*who*/) override { }
void Reset() override
{
// On spawn, engage the summoner's current target (or its attacker).
if (!me->GetVictim() && me->IsSummon())
if (Unit* owner = me->ToTempSummon()->GetSummoner())
{
if (Unit* target = owner->GetVictim())
AttackStart(target);
else if (Unit* attacker = owner->getAttackerForHelper())
AttackStart(attacker);
}
}
// Pick up a closer target if the owner switches while the beast is out.
void MoveInLineOfSight(Unit* who) override
{
if (!me->GetVictim() && me->CanCreatureAttack(who))
{
if (me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE)
return;
float attackRadius = me->GetAttackDistance(who);
if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who))
AttackStart(who);
}
}
void UpdateAI(uint32 /*diff*/) override
{
if (!UpdateVictim() || !me->GetVictim())
return;
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_pet_hun_dire_beastAI(creature);
}
};
void AddSC_hunter_pet_scripts()
{
new npc_pet_hunter_snake_trap();
new npc_pet_hunter_hati();
new npc_pet_hun_dire_beast();
}