@@ -1519,7 +1519,10 @@ class npc_brewfest_reveler : public CreatureScript
15191519enum TrainingDummy
15201520{
15211521 NPC_ADVANCED_TARGET_DUMMY = 2674 ,
1522- NPC_TARGET_DUMMY = 2673
1522+ NPC_TARGET_DUMMY = 2673 ,
1523+
1524+ EVENT_TD_CHECK_COMBAT = 1 ,
1525+ EVENT_TD_DESPAWN = 2
15231526};
15241527
15251528class npc_training_dummy : public CreatureScript
@@ -1532,20 +1535,22 @@ class npc_training_dummy : public CreatureScript
15321535 npc_training_dummyAI (Creature* creature) : ScriptedAI(creature)
15331536 {
15341537 SetCombatMovement (false );
1535- entry = creature->GetEntry ();
15361538 }
15371539
1538- uint32 entry;
1539- uint32 resetTimer;
1540- uint32 despawnTimer;
1540+ EventMap _events;
1541+ std::unordered_map<uint64, time_t > _damageTimes;
15411542
15421543 void Reset () override
15431544 {
15441545 me->SetControlled (true , UNIT_STATE_STUNNED );// disable rotate
15451546 me->ApplySpellImmune (0 , IMMUNITY_EFFECT , SPELL_EFFECT_KNOCK_BACK , true );// imune to knock aways like blast wave
15461547
1547- resetTimer = 5000 ;
1548- despawnTimer = 15000 ;
1548+ _events.Reset ();
1549+ _damageTimes.clear ();
1550+ if (me->GetEntry () != NPC_ADVANCED_TARGET_DUMMY && me->GetEntry () != NPC_TARGET_DUMMY )
1551+ _events.ScheduleEvent (EVENT_TD_CHECK_COMBAT , 1000 );
1552+ else
1553+ _events.ScheduleEvent (EVENT_TD_DESPAWN , 15000 );
15491554 }
15501555
15511556 void EnterEvadeMode () override
@@ -1556,37 +1561,52 @@ class npc_training_dummy : public CreatureScript
15561561 Reset ();
15571562 }
15581563
1559- void DamageTaken (Unit* /* doneBy*/ , uint32& damage) override
1564+ void DamageTaken (Unit* doneBy, uint32& damage) override
15601565 {
1561- resetTimer = 5000 ;
1566+ me->AddThreat (doneBy, float (damage)); // just to create threat reference
1567+ _damageTimes[doneBy->GetGUID ()] = time (NULL );
15621568 damage = 0 ;
15631569 }
15641570
15651571 void UpdateAI (uint32 diff) override
15661572 {
1567- if (!UpdateVictim ())
1573+ if (!me-> IsInCombat ())
15681574 return ;
15691575
15701576 if (!me->HasUnitState (UNIT_STATE_STUNNED ))
15711577 me->SetControlled (true , UNIT_STATE_STUNNED );// disable rotate
15721578
1573- if (entry != NPC_ADVANCED_TARGET_DUMMY && entry != NPC_TARGET_DUMMY )
1579+ _events.Update (diff);
1580+
1581+ if (uint32 eventId = _events.ExecuteEvent ())
15741582 {
1575- if (resetTimer <= diff )
1583+ switch (eventId )
15761584 {
1577- EnterEvadeMode ();
1578- resetTimer = 5000 ;
1585+ case EVENT_TD_CHECK_COMBAT :
1586+ {
1587+ time_t now = time (NULL );
1588+ for (std::unordered_map<uint64, time_t >::iterator itr = _damageTimes.begin (); itr != _damageTimes.end ();)
1589+ {
1590+ // If unit has not dealt damage to training dummy for 5 seconds, remove him from combat
1591+ if (itr->second < now - 5 )
1592+ {
1593+ if (Unit* unit = ObjectAccessor::GetUnit (*me, itr->first ))
1594+ unit->getHostileRefManager ().deleteReference (me);
1595+
1596+ itr = _damageTimes.erase (itr);
1597+ }
1598+ else
1599+ ++itr;
1600+ }
1601+ _events.ScheduleEvent (EVENT_TD_CHECK_COMBAT , 1000 );
1602+ break ;
1603+ }
1604+ case EVENT_TD_DESPAWN :
1605+ me->DespawnOrUnsummon (1 );
1606+ break ;
1607+ default :
1608+ break ;
15791609 }
1580- else
1581- resetTimer -= diff;
1582- return ;
1583- }
1584- else
1585- {
1586- if (despawnTimer <= diff)
1587- me->DespawnOrUnsummon ();
1588- else
1589- despawnTimer -= diff;
15901610 }
15911611 }
15921612
0 commit comments