Scripts/World: drop unnecessary GameTime shenanigans from training dummy's script and correct scripting model for current combat / threading model. The dummy will no longer get stuck in a 'engaged' state.

* additionally the combat times will now be updated in realtime instead of a 500ms interval which will lead to pin-point accurate results.
This commit is contained in:
Ovahlord
2020-07-23 14:36:07 +02:00
parent b60da9ba4c
commit bf35a3e2e7

View File

@@ -1724,104 +1724,65 @@ enum TrainingDummy
SPELL_ARCANE_MISSILES = 5143,
};
class npc_training_dummy : public CreatureScript
struct npc_training_dummy : NullCreatureAI
{
public:
npc_training_dummy() : CreatureScript("npc_training_dummy") { }
struct npc_training_dummyAI : PassiveAI
npc_training_dummy(Creature* creature) : NullCreatureAI(creature)
{
npc_training_dummyAI(Creature* creature) : PassiveAI(creature), _combatCheckTimer(500)
{
uint32 const entry = me->GetEntry();
if (entry == NPC_TARGET_DUMMY || entry == NPC_ADVANCED_TARGET_DUMMY)
{
_combatCheckTimer = 0;
me->DespawnOrUnsummon(16s);
}
}
uint32 const entry = me->GetEntry();
if (entry == NPC_TARGET_DUMMY || entry == NPC_ADVANCED_TARGET_DUMMY)
me->DespawnOrUnsummon(16s);
}
void Reset() override
{
_damageTimes.clear();
}
void DamageTaken(Unit* attacker, uint32& damage) override
{
damage = 0;
void EnterEvadeMode(EvadeReason why) override
{
if (!_EnterEvadeMode(why))
return;
if (!attacker)
return;
Reset();
}
_combatTimer[attacker->GetGUID()] = int32(5 * IN_MILLISECONDS);
}
void DamageTaken(Unit* doneBy, uint32& damage) override
// Todo: the involved training dummys have a proc aura for that. Drop this part here, once converted.
void SpellHit(Unit* caster, SpellInfo const* spell) override
{
switch (spell->Id)
{
_damageTimes[doneBy->GetGUID()] = GameTime::GetGameTime();
damage = 0;
}
void SpellHit(Unit* caster, SpellInfo const* spell) override
{
switch (spell->Id)
{
case SPELL_CHARGE: // Charge - Warrior
case SPELL_JUDGEMENT: // Judgement - Paladin
case SPELL_STEADY_SHOT: // Steady Shot - Hunter
case SPELL_EVISCERATE: // Eviscerate - Rouge
case SPELL_PRIMAL_STRIKE: // Primal Strike - Shaman
case SPELL_IMMOLATE: // Immolate - Warlock
case SPELL_ARCANE_MISSILES: // Arcane Missiles - Mage
case SPELL_CHARGE: // Charge - Warrior
case SPELL_JUDGEMENT: // Judgement - Paladin
case SPELL_STEADY_SHOT: // Steady Shot - Hunter
case SPELL_EVISCERATE: // Eviscerate - Rouge
case SPELL_PRIMAL_STRIKE: // Primal Strike - Shaman
case SPELL_IMMOLATE: // Immolate - Warlock
case SPELL_ARCANE_MISSILES: // Arcane Missiles - Mage
if (caster->GetTypeId() == TYPEID_PLAYER)
caster->ToPlayer()->KilledMonsterCredit(NPC_SPELL_PRACTICE_CREDIT);
break;
default:
break;
}
}
void UpdateAI(uint32 diff) override
{
if (!_combatCheckTimer || !me->IsInCombat())
return;
if (diff < _combatCheckTimer)
{
_combatCheckTimer -= diff;
return;
}
_combatCheckTimer = 500;
time_t const now = GameTime::GetGameTime();
auto const& pveRefs = me->GetCombatManager().GetPvECombatRefs();
for (auto 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)
{
auto it = pveRefs.find(itr->first);
if (it != pveRefs.end())
it->second->EndCombat();
itr = _damageTimes.erase(itr);
}
else
++itr;
}
for (auto const& pair : pveRefs)
if (_damageTimes.find(pair.first) == _damageTimes.end())
_damageTimes[pair.first] = now;
}
std::unordered_map<ObjectGuid, time_t> _damageTimes;
uint32 _combatCheckTimer;
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_training_dummyAI(creature);
}
void UpdateAI(uint32 diff) override
{
for (auto itr = _combatTimer.begin(); itr != _combatTimer.end();)
{
itr->second -= diff;
if (itr->second <= 0)
{
auto const& pveRefs = me->GetCombatManager().GetPvECombatRefs();
auto it = pveRefs.find(itr->first);
if (it != pveRefs.end())
it->second->EndCombat();
itr = _combatTimer.erase(itr);
}
else
++itr;
}
}
private:
std::unordered_map<ObjectGuid /*attackerGUID*/, int32 /*combatTime*/> _combatTimer;
};
/*######
@@ -3210,7 +3171,7 @@ void AddSC_npcs_special()
new npc_tonk_mine();
new npc_tournament_mount();
new npc_brewfest_reveler();
new npc_training_dummy();
RegisterCreatureAI(npc_training_dummy);
new npc_wormhole();
new npc_pet_trainer();
new npc_experience();