aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/scripts/World/npcs_special.cpp68
1 files changed, 44 insertions, 24 deletions
diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp
index b3dc57cf028..e67823a2939 100644
--- a/src/server/scripts/World/npcs_special.cpp
+++ b/src/server/scripts/World/npcs_special.cpp
@@ -1519,7 +1519,10 @@ class npc_brewfest_reveler : public CreatureScript
enum TrainingDummy
{
NPC_ADVANCED_TARGET_DUMMY = 2674,
- NPC_TARGET_DUMMY = 2673
+ NPC_TARGET_DUMMY = 2673,
+
+ EVENT_TD_CHECK_COMBAT = 1,
+ EVENT_TD_DESPAWN = 2
};
class npc_training_dummy : public CreatureScript
@@ -1532,20 +1535,22 @@ public:
npc_training_dummyAI(Creature* creature) : ScriptedAI(creature)
{
SetCombatMovement(false);
- entry = creature->GetEntry();
}
- uint32 entry;
- uint32 resetTimer;
- uint32 despawnTimer;
+ EventMap _events;
+ std::unordered_map<uint64, time_t> _damageTimes;
void Reset() override
{
me->SetControlled(true, UNIT_STATE_STUNNED);//disable rotate
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true);//imune to knock aways like blast wave
- resetTimer = 5000;
- despawnTimer = 15000;
+ _events.Reset();
+ _damageTimes.clear();
+ if (me->GetEntry() != NPC_ADVANCED_TARGET_DUMMY && me->GetEntry() != NPC_TARGET_DUMMY)
+ _events.ScheduleEvent(EVENT_TD_CHECK_COMBAT, 1000);
+ else
+ _events.ScheduleEvent(EVENT_TD_DESPAWN, 15000);
}
void EnterEvadeMode() override
@@ -1556,37 +1561,52 @@ public:
Reset();
}
- void DamageTaken(Unit* /*doneBy*/, uint32& damage) override
+ void DamageTaken(Unit* doneBy, uint32& damage) override
{
- resetTimer = 5000;
+ me->AddThreat(doneBy, float(damage)); // just to create threat reference
+ _damageTimes[doneBy->GetGUID()] = time(NULL);
damage = 0;
}
void UpdateAI(uint32 diff) override
{
- if (!UpdateVictim())
+ if (!me->IsInCombat())
return;
if (!me->HasUnitState(UNIT_STATE_STUNNED))
me->SetControlled(true, UNIT_STATE_STUNNED);//disable rotate
- if (entry != NPC_ADVANCED_TARGET_DUMMY && entry != NPC_TARGET_DUMMY)
+ _events.Update(diff);
+
+ if (uint32 eventId = _events.ExecuteEvent())
{
- if (resetTimer <= diff)
+ switch (eventId)
{
- EnterEvadeMode();
- resetTimer = 5000;
+ case EVENT_TD_CHECK_COMBAT:
+ {
+ time_t now = time(NULL);
+ for (std::unordered_map<uint64, time_t>::iterator itr = _damageTimes.begin(); itr != _damageTimes.end();)
+ {
+ // If unit has not dealt damage to training dummy for 5 seconds, remove him from combat
+ if (itr->second < now - 5)
+ {
+ if (Unit* unit = ObjectAccessor::GetUnit(*me, itr->first))
+ unit->getHostileRefManager().deleteReference(me);
+
+ itr = _damageTimes.erase(itr);
+ }
+ else
+ ++itr;
+ }
+ _events.ScheduleEvent(EVENT_TD_CHECK_COMBAT, 1000);
+ break;
+ }
+ case EVENT_TD_DESPAWN:
+ me->DespawnOrUnsummon(1);
+ break;
+ default:
+ break;
}
- else
- resetTimer -= diff;
- return;
- }
- else
- {
- if (despawnTimer <= diff)
- me->DespawnOrUnsummon();
- else
- despawnTimer -= diff;
}
}