Core/Misc: A variety of clean-up changes, mostly following up on 532ab1c to fix legacy bugs exposed by it:

- Triggers can no longer have a threat list (this may expose some ugliness in old legacy scripts)
- Threat entries are forced to OFFLINE if the AI refuses to attack the target
- Clean up passive creature evade behavior to be more consistent
- Fix a months old issue in spawn group management that would cause "Inactive" to incorrectly show in .list respawns for system groups outside of map 0
- Valithria script cleanups, remove old hacks and make it work with the new system. Closes #21174.
- Some strings cleanup

(cherry picked from commit 9f9507e6a1)
This commit is contained in:
Treeston
2018-01-04 04:46:22 +01:00
committed by Shauren
parent 83159544b5
commit 5aee452943
7 changed files with 56 additions and 61 deletions

View File

@@ -0,0 +1,2 @@
-- valithria LK dummy is now a trigger
UPDATE `creature_template` SET `flags_extra`=(`flags_extra`&(~0x02) | 0x80) WHERE `entry`=16980;

View File

@@ -84,11 +84,12 @@ void CreatureAI::DoZoneInCombat(Creature* creature /*= nullptr*/, float maxRange
{
if (Unit* summoner = creature->ToTempSummon()->GetSummoner())
{
Unit* target = summoner->getAttackerForHelper();
if (!target && !summoner->GetThreatManager().IsThreatListEmpty())
target = summoner->GetThreatManager().GetAnyTarget();
if (target && (creature->IsFriendlyTo(summoner) || creature->IsHostileTo(target)))
creature->AI()->AttackStart(target);
if (creature->IsFriendlyTo(summoner))
{
Unit* target = summoner->getAttackerForHelper();
if (target && creature->IsHostileTo(target))
creature->AI()->AttackStart(target);
}
}
}
}
@@ -109,7 +110,7 @@ void CreatureAI::DoZoneInCombat(Creature* creature /*= nullptr*/, float maxRange
for (Map::PlayerList::const_iterator itr = playerList.begin(); itr != playerList.end(); ++itr)
if (Player* player = itr->GetSource())
if (player->IsAlive())
creature->SetInCombatWith(player);
creature->EngageWithTarget(player);
}
// scripts does not take care about MoveInLineOfSight loops
@@ -237,12 +238,12 @@ bool CreatureAI::UpdateVictim()
return me->GetVictim() != nullptr;
}
else if (me->GetThreatManager().IsThreatListEmpty(true))
else if (!me->IsInCombat())
{
EnterEvadeMode(EVADE_REASON_NO_HOSTILES);
return false;
}
else
else if (me->GetVictim())
me->AttackStop();
return true;

View File

@@ -94,6 +94,8 @@ ThreatReference::OnlineState ThreatReference::SelectOnlineState()
return ONLINE_STATE_OFFLINE;
if (!FlagsAllowFighting(_owner, _victim) || !FlagsAllowFighting(_victim, _owner))
return ONLINE_STATE_OFFLINE;
if (_owner->IsAIEnabled && !_owner->GetAI()->CanAIAttack(_victim))
return ONLINE_STATE_OFFLINE;
// next, check suppression (immunity to chosen melee attack school)
if (_victim->IsImmunedToDamage(_owner->GetMeleeDamageSchoolMask()))
return ONLINE_STATE_SUPPRESSED;
@@ -135,16 +137,17 @@ void ThreatReference::ClearThreat(bool sendRemove)
/*static*/ bool ThreatManager::CanHaveThreatList(Unit const* who)
{
Creature const* cWho = who->ToCreature();
// only creatures can have threat list
if (who->GetTypeId() != TYPEID_UNIT)
if (!cWho)
return false;
// pets and totems cannot have threat list
if (who->IsPet() || who->IsTotem())
// pets, totems and triggers cannot have threat list
if (cWho->IsPet() || cWho->IsTotem() || cWho->IsTrigger())
return false;
// summons cannot have a threat list, unless they are controlled by a creature
if (who->HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_GUARDIAN) && !who->GetOwnerGUID().IsCreature())
if (cWho->HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_GUARDIAN) && !cWho->GetOwnerGUID().IsCreature())
return false;
return true;

View File

@@ -678,7 +678,7 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/,
void Creature::Update(uint32 diff)
{
if (IsAIEnabled && m_triggerJustAppeared && m_deathState == ALIVE)
if (IsAIEnabled && m_triggerJustAppeared && m_deathState != DEAD)
{
if (m_respawnCompatibilityMode && m_vehicleKit)
m_vehicleKit->Reset();

View File

@@ -3396,7 +3396,7 @@ void Map::ApplyDynamicModeRespawnScaling(WorldObject const* obj, ObjectGuid::Low
SpawnGroupTemplateData const* Map::GetSpawnGroupData(uint32 groupId) const
{
SpawnGroupTemplateData const* data = sObjectMgr->GetSpawnGroupData(groupId);
if (data && data->mapId == GetId())
if (data && (data->flags & SPAWNGROUP_FLAG_SYSTEM || data->mapId == GetId()))
return data;
return nullptr;
}
@@ -3527,11 +3527,12 @@ bool Map::IsSpawnGroupActive(uint32 groupId) const
SpawnGroupTemplateData const* const data = GetSpawnGroupData(groupId);
if (!data)
{
TC_LOG_WARN("maps", "Tried to query state of non-existing spawn group %u on map %u.", groupId, GetId());
TC_LOG_ERROR("maps", "Tried to query state of non-existing spawn group %u on map %u.", groupId, GetId());
return false;
}
if (data->flags & SPAWNGROUP_FLAG_SYSTEM)
return true;
// either manual spawn group and toggled, or not manual spawn group and not toggled...
return (_toggledSpawnGroupIds.find(groupId) != _toggledSpawnGroupIds.end()) != !(data->flags & SPAWNGROUP_FLAG_MANUAL_SPAWN);
}

View File

@@ -856,8 +856,6 @@ public:
handler->PSendSysMessage("%s (%s) is not alive.", target->GetName().c_str(), target->GetGUID().ToString().c_str());
return true;
}
if (!target->CanHaveThreatList())
handler->PSendSysMessage("%s (%s) cannot have a threat list.", target->GetName().c_str(), target->GetGUID().ToString().c_str());
uint32 count = 0;
auto const& threatenedByMe = target->GetThreatManager().GetThreatenedByMeList();
@@ -875,8 +873,8 @@ public:
}
if (!mgr.CanHaveThreatList())
return true;
if (mgr.IsEngaged())
handler->PSendSysMessage("%s (%s) cannot have a threat list.", target->GetName().c_str(), target->GetGUID().ToString().c_str());
else if (mgr.IsEngaged())
{
count = 0;
handler->PSendSysMessage("Threat list of %s (%s, SpawnID %u)", target->GetName().c_str(), target->GetGUID().ToString().c_str(), target->GetTypeId() == TYPEID_UNIT ? target->ToCreature()->GetSpawnId() : 0);

View File

@@ -230,44 +230,10 @@ class ValithriaDespawner : public BasicEvent
void operator()(Creature* creature) const
{
switch (creature->GetEntry())
{
case NPC_VALITHRIA_DREAMWALKER:
if (InstanceScript* instance = creature->GetInstanceScript())
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, creature);
break;
case NPC_BLAZING_SKELETON:
case NPC_SUPPRESSER:
case NPC_BLISTERING_ZOMBIE:
case NPC_GLUTTONOUS_ABOMINATION:
case NPC_MANA_VOID:
case NPC_COLUMN_OF_FROST:
case NPC_ROT_WORM:
creature->DespawnOrUnsummon();
return;
case NPC_RISEN_ARCHMAGE:
if (!creature->GetSpawnId())
{
creature->DespawnOrUnsummon();
return;
}
creature->Respawn(true);
break;
default:
return;
}
uint32 corpseDelay = creature->GetCorpseDelay();
uint32 respawnDelay = creature->GetRespawnDelay();
creature->SetCorpseDelay(1);
creature->SetRespawnDelay(10);
if (CreatureData const* data = creature->GetCreatureData())
creature->UpdatePosition(data->spawnPoint);
creature->DespawnOrUnsummon();
creature->SetCorpseDelay(corpseDelay);
creature->SetRespawnDelay(respawnDelay);
if (creature->GetEntry() == NPC_VALITHRIA_DREAMWALKER)
if (InstanceScript* instance = creature->GetInstanceScript())
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, creature);
creature->DespawnOrUnsummon(0, 10s);
}
private:
@@ -365,7 +331,7 @@ class boss_valithria_dreamwalker : public CreatureScript
}
else if (_instance->GetBossState(DATA_VALITHRIA_DREAMWALKER) == NOT_STARTED)
if (Creature* archmage = me->FindNearestCreature(NPC_RISEN_ARCHMAGE, 30.0f))
archmage->AI()->DoZoneInCombat(); // call JustEngagedWith on one of them, that will make it all start
archmage->EngageWithTarget(healer); // call JustEngagedWith on one of them, that will make it all start
}
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
@@ -628,8 +594,9 @@ class npc_the_lich_king_controller : public CreatureScript
{
// must not be in dream phase
PhasingHandler::RemovePhase(summon, 173, true);
summon->AI()->DoZoneInCombat();
if (summon->GetEntry() != NPC_SUPPRESSER)
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
if (Unit* target = me->GetCombatManager().GetAnyTarget())
summon->AI()->AttackStart(target);
}
@@ -711,7 +678,7 @@ class npc_risen_archmage : public CreatureScript
Initialize();
}
void JustEngagedWith(Unit* /*target*/) override
void JustEngagedWith(Unit* target) override
{
me->FinishSpell(CURRENT_CHANNELED_SPELL, false);
if (me->GetSpawnId() && _canCallJustEngagedWith)
@@ -724,10 +691,16 @@ class npc_risen_archmage : public CreatureScript
(*itr)->AI()->DoAction(ACTION_ENTER_COMBAT);
if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_LICH_KING)))
{
lichKing->EngageWithTarget(target);
lichKing->AI()->DoZoneInCombat();
}
if (Creature* trigger = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_TRIGGER)))
{
trigger->EngageWithTarget(target);
trigger->AI()->DoZoneInCombat();
}
}
}
@@ -883,7 +856,24 @@ class npc_suppresser : public CreatureScript
void IsSummonedBy(Unit* /*summoner*/) override
{
if (Creature* valithria = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_DREAMWALKER)))
AttackStart(valithria);
{
float x, y, z;
valithria->GetContactPoint(me, x,y,z);
me->GetMotionMaster()->MovePoint(42, x, y, z);
}
}
void MovementInform(uint32 /*type*/, uint32 id)
{
if (id == 42)
{
me->SetReactState(REACT_AGGRESSIVE);
if (Creature* valithria = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_DREAMWALKER)))
{
AttackStart(valithria);
DoCastAOE(SPELL_SUPPRESSION);
}
}
}
void UpdateAI(uint32 diff) override