Ports from (https://github.com/TrinityCore/TrinityCore)
Core/Unit: don't clear low health aura states on death Core/Gossip: Fix gossip bug on modify money Core/Spells: Change the radius of PBAoEs following the feedback received on Core/Player: update interaction checks, some info taken from client Core/Spell: abort channeling if no valid targets are found after searching Core/Creature: fix _DespawnAtEvade saving wrong respawn time Core/Spell: fixed some problems with per caster aura states Quickfix a bug introduced by 2f19d97 which prevented GTAoE from being cast. Core/SmartAI: allow SMART_ACTION_SEND_GOSSIP_MENU to override default gossip Core/Spell: in case of immunity, check all effects to choose correct procFlags, as none has technically hit Fix evade issues when a spell hits the target just before evading. Scripts/Command: implement .debug play music command Partial revert, Unit::getAttackerForHelper() shouldn't return units that we aren't in combat with (victim can be such a unit for players/player pets, which can startattack from a distance without entering combat). Fix an issue where CanSpawn would never get invoked on creatures without per-guid script. Core/Players: fix null dereference crash
This commit is contained in:
@@ -1695,27 +1695,34 @@ namespace Game.Entities
|
||||
{
|
||||
if (timeMSToDespawn != 0)
|
||||
{
|
||||
ForcedDespawnDelayEvent pEvent = new ForcedDespawnDelayEvent(this, forceRespawnTimer);
|
||||
|
||||
m_Events.AddEvent(pEvent, m_Events.CalculateTime(timeMSToDespawn));
|
||||
m_Events.AddEvent(new ForcedDespawnDelayEvent(this, forceRespawnTimer), m_Events.CalculateTime(timeMSToDespawn));
|
||||
return;
|
||||
}
|
||||
|
||||
uint corpseDelay = GetCorpseDelay();
|
||||
uint respawnDelay = GetRespawnDelay();
|
||||
|
||||
// do it before killing creature
|
||||
DestroyForNearbyPlayers();
|
||||
|
||||
bool overrideRespawnTime = false;
|
||||
if (IsAlive())
|
||||
SetDeathState(DeathState.JustDied);
|
||||
|
||||
bool overrideRespawnTime = true;
|
||||
if (forceRespawnTimer > TimeSpan.Zero)
|
||||
{
|
||||
SetRespawnTime((uint)forceRespawnTimer.TotalSeconds);
|
||||
overrideRespawnTime = false;
|
||||
if (forceRespawnTimer > TimeSpan.Zero)
|
||||
{
|
||||
SetCorpseDelay(0);
|
||||
SetRespawnDelay((uint)forceRespawnTimer.TotalSeconds);
|
||||
overrideRespawnTime = false;
|
||||
}
|
||||
|
||||
SetDeathState(DeathState.JustDied);
|
||||
}
|
||||
|
||||
// Skip corpse decay time
|
||||
RemoveCorpse(overrideRespawnTime, false);
|
||||
|
||||
SetCorpseDelay(corpseDelay);
|
||||
SetRespawnDelay(respawnDelay);
|
||||
}
|
||||
|
||||
public void DespawnOrUnsummon(TimeSpan time, TimeSpan forceRespawnTimer = default) { DespawnOrUnsummon((uint)time.TotalMilliseconds, forceRespawnTimer); }
|
||||
@@ -2060,14 +2067,9 @@ namespace Game.Entities
|
||||
Unit targetVictim = target.GetAttackerForHelper();
|
||||
|
||||
// if I'm already fighting target, or I'm hostile towards the target, the target is acceptable
|
||||
if (GetVictim() == target || IsHostileTo(target))
|
||||
if (IsInCombatWith(target) || IsHostileTo(target))
|
||||
return true;
|
||||
|
||||
// a player is targeting me, but I'm not hostile towards it, and not currently attacking it, the target is not acceptable
|
||||
// (players may set their victim from a distance, and doesn't mean we should attack)
|
||||
if (target.GetTypeId() == TypeId.Player && targetVictim == this)
|
||||
return false;
|
||||
|
||||
// if the target's victim is friendly, and the target is neutral, the target is acceptable
|
||||
if (targetVictim != null && IsFriendlyTo(targetVictim))
|
||||
return true;
|
||||
|
||||
@@ -1824,7 +1824,6 @@ namespace Game.Entities
|
||||
List<uint> qr;
|
||||
List<uint> qir;
|
||||
|
||||
PlayerTalkClass.ClearMenus();
|
||||
switch (questgiver.GetTypeId())
|
||||
{
|
||||
case TypeId.GameObject:
|
||||
|
||||
@@ -3615,19 +3615,24 @@ namespace Game.Entities
|
||||
|
||||
void ResurrectUsingRequestDataImpl()
|
||||
{
|
||||
// save health and mana before resurrecting, _resurrectionData can be erased
|
||||
uint resurrectHealth = _resurrectionData.Health;
|
||||
uint resurrectMana = _resurrectionData.Mana;
|
||||
uint resurrectAura = _resurrectionData.Aura;
|
||||
ObjectGuid resurrectGUID = _resurrectionData.GUID;
|
||||
|
||||
ResurrectPlayer(0.0f, false);
|
||||
|
||||
SetHealth(_resurrectionData.Health);
|
||||
SetPower(PowerType.Mana, (int)_resurrectionData.Mana);
|
||||
SetHealth(resurrectHealth);
|
||||
SetPower(PowerType.Mana, (int)resurrectMana);
|
||||
|
||||
SetPower(PowerType.Rage, 0);
|
||||
SetFullPower(PowerType.Energy);
|
||||
SetFullPower(PowerType.Focus);
|
||||
SetPower(PowerType.LunarPower, 0);
|
||||
|
||||
uint aura = _resurrectionData.Aura;
|
||||
if (aura != 0)
|
||||
CastSpell(this, aura, true, null, null, _resurrectionData.GUID);
|
||||
if (resurrectAura != 0)
|
||||
CastSpell(this, resurrectAura, true, null, null, resurrectGUID);
|
||||
|
||||
SpawnCorpseBones();
|
||||
}
|
||||
@@ -5562,8 +5567,8 @@ namespace Game.Entities
|
||||
if (creature.GetReactionTo(this) <= ReputationRank.Unfriendly)
|
||||
return null;
|
||||
|
||||
// not too far
|
||||
if (!creature.IsWithinDistInMap(this, SharedConst.InteractionDistance))
|
||||
// not too far, taken from CGGameUI::SetInteractTarget
|
||||
if (!creature.IsWithinDistInMap(this, creature.GetCombatReach() + 4.0f))
|
||||
return null;
|
||||
|
||||
return creature;
|
||||
@@ -5571,34 +5576,36 @@ namespace Game.Entities
|
||||
|
||||
public GameObject GetGameObjectIfCanInteractWith(ObjectGuid guid)
|
||||
{
|
||||
GameObject go = GetMap().GetGameObject(guid);
|
||||
if (go)
|
||||
{
|
||||
if (go.IsWithinDistInMap(this, go.GetInteractionDistance()))
|
||||
return go;
|
||||
if (guid.IsEmpty())
|
||||
return null;
|
||||
|
||||
Log.outDebug(LogFilter.Maps, "Player.GetGameObjectIfCanInteractWith: GameObject '{0}' ({1}) is too far away from player '{2}' ({3}) to be used by him (Distance: {4}, maximal {5} is allowed)",
|
||||
go.GetName(), go.GetGUID().ToString(), GetName(), GetGUID().ToString(), go.GetDistance(this), go.GetInteractionDistance());
|
||||
}
|
||||
if (!IsInWorld)
|
||||
return null;
|
||||
|
||||
return null;
|
||||
if (IsInFlight())
|
||||
return null;
|
||||
|
||||
// exist
|
||||
GameObject go = ObjectAccessor.GetGameObject(this, guid);
|
||||
if (go == null)
|
||||
return null;
|
||||
|
||||
if (!go.IsWithinDistInMap(this, go.GetInteractionDistance()))
|
||||
return null;
|
||||
|
||||
return go;
|
||||
}
|
||||
|
||||
public GameObject GetGameObjectIfCanInteractWith(ObjectGuid guid, GameObjectTypes type)
|
||||
{
|
||||
GameObject go = GetMap().GetGameObject(guid);
|
||||
if (go != null)
|
||||
{
|
||||
if (go.GetGoType() == type)
|
||||
{
|
||||
if (go.IsWithinDistInMap(this, go.GetInteractionDistance()))
|
||||
return go;
|
||||
GameObject go = GetGameObjectIfCanInteractWith(guid);
|
||||
if (!go)
|
||||
return null;
|
||||
|
||||
Log.outDebug(LogFilter.Maps, "Player.GetGameObjectIfCanInteractWith: GameObject '{0}' ({1}) is too far away from player '{2}' ({3}) to be used by him (Distance: {4}, maximal {5} is allowed)",
|
||||
go.GetName(), go.GetGUID().ToString(), GetName(), GetGUID().ToString(), go.GetDistance(this), go.GetInteractionDistance());
|
||||
}
|
||||
}
|
||||
if (go.GetGoType() != type)
|
||||
return null;
|
||||
|
||||
return null;
|
||||
return go;
|
||||
}
|
||||
|
||||
public void SendInitialPacketsBeforeAddToMap()
|
||||
|
||||
@@ -376,6 +376,11 @@ namespace Game.Entities
|
||||
if (IsTypeId(TypeId.Player) && IsMounted())
|
||||
return false;
|
||||
|
||||
Creature creature = ToCreature();
|
||||
// creatures cannot attack while evading
|
||||
if (creature != null && creature.IsInEvadeMode())
|
||||
return false;
|
||||
|
||||
if (HasUnitFlag(UnitFlags.Pacified))
|
||||
return false;
|
||||
|
||||
@@ -436,7 +441,7 @@ namespace Game.Entities
|
||||
if (meleeAttack)
|
||||
AddUnitState(UnitState.MeleeAttacking);
|
||||
|
||||
if (IsTypeId(TypeId.Unit) && !IsPet())
|
||||
if (creature != null && !IsPet())
|
||||
{
|
||||
// should not let player enter combat by right clicking target - doesn't helps
|
||||
AddThreat(victim, 0.0f);
|
||||
@@ -445,8 +450,8 @@ namespace Game.Entities
|
||||
if (victim.IsTypeId(TypeId.Player))
|
||||
victim.SetInCombatWith(this);
|
||||
|
||||
ToCreature().SendAIReaction(AiReaction.Hostile);
|
||||
ToCreature().CallAssistance();
|
||||
creature.SendAIReaction(AiReaction.Hostile);
|
||||
creature.CallAssistance();
|
||||
|
||||
// Remove emote state - will be restored on creature reset
|
||||
SetEmoteState(Emote.OneshotNone);
|
||||
@@ -536,12 +541,28 @@ namespace Game.Entities
|
||||
}
|
||||
public Unit GetAttackerForHelper()
|
||||
{
|
||||
if (GetVictim() != null)
|
||||
return GetVictim();
|
||||
Unit victim = GetVictim();
|
||||
if (victim != null)
|
||||
if (!IsControlledByPlayer() || IsInCombatWith(victim) || victim.IsInCombatWith(this))
|
||||
return victim;
|
||||
|
||||
if (attackerList.Count != 0)
|
||||
if (!attackerList.Empty())
|
||||
return attackerList[0];
|
||||
|
||||
Player owner = GetCharmerOrOwnerPlayerOrPlayerItself();
|
||||
if (owner != null)
|
||||
{
|
||||
HostileReference refe = owner.GetHostileRefManager().GetFirst();
|
||||
while (refe != null)
|
||||
{
|
||||
Unit hostile = refe.GetSource().GetOwner();
|
||||
if (hostile != null)
|
||||
return hostile;
|
||||
|
||||
refe = refe.Next();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
public List<Unit> GetAttackers()
|
||||
|
||||
@@ -3965,9 +3965,22 @@ namespace Game.Entities
|
||||
ToTotem().SetDeathState(DeathState.JustDied);
|
||||
}
|
||||
|
||||
// Remove aurastates only if were not found
|
||||
if (!auraStateFound)
|
||||
ModifyAuraState(auraState, false);
|
||||
// Remove aurastates only if needed and were not found
|
||||
if (auraState != 0)
|
||||
{
|
||||
if (!auraStateFound)
|
||||
ModifyAuraState(auraState, false);
|
||||
else
|
||||
{
|
||||
// update for casters, some shouldn't 'see' the aura state
|
||||
uint aStateMask = (1u << ((int)auraState - 1));
|
||||
if ((aStateMask & (uint)AuraStateType.PerCasterAuraStateMask) != 0)
|
||||
{
|
||||
m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.AuraState);
|
||||
ForceUpdateFieldChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aura.HandleAuraSpecificMods(aurApp, caster, false, false);
|
||||
}
|
||||
@@ -4099,7 +4112,17 @@ namespace Game.Entities
|
||||
// Update target aura state flag
|
||||
AuraStateType aState = aura.GetSpellInfo().GetAuraState();
|
||||
if (aState != 0)
|
||||
ModifyAuraState(aState, true);
|
||||
{
|
||||
uint aStateMask = (1u << ((int)aState - 1));
|
||||
// force update so the new caster registers it
|
||||
if (aStateMask.HasAnyFlag((uint)AuraStateType.PerCasterAuraStateMask) && (m_unitData.AuraState & aStateMask) != 0)
|
||||
{
|
||||
m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.AuraState);
|
||||
ForceUpdateFieldChange();
|
||||
}
|
||||
else
|
||||
ModifyAuraState(aState, true);
|
||||
}
|
||||
|
||||
if (aurApp.HasRemoveMode())
|
||||
return;
|
||||
|
||||
@@ -1626,8 +1626,6 @@ namespace Game.Entities
|
||||
|
||||
if (s == DeathState.JustDied)
|
||||
{
|
||||
ModifyAuraState(AuraStateType.HealthLess20Percent, false);
|
||||
ModifyAuraState(AuraStateType.HealthLess35Percent, false);
|
||||
// remove aurastates allowing special moves
|
||||
ClearAllReactives();
|
||||
m_Diminishing.Clear();
|
||||
|
||||
Reference in New Issue
Block a user