Core/Creatures: Various fixes for creatures, regarding combat conditions, despawning, and few others
Port From (https://github.com/TrinityCore/TrinityCore/commit/fe63cd3dbb66f4fda743858db4284a24bc2bd400)
This commit is contained in:
@@ -175,8 +175,8 @@ namespace Framework.Constants
|
|||||||
public const int MaxCreatureModelIds = 4;
|
public const int MaxCreatureModelIds = 4;
|
||||||
public const int MaxTrainerspellAbilityReqs = 3;
|
public const int MaxTrainerspellAbilityReqs = 3;
|
||||||
public const int CreatureRegenInterval = 2 * Time.InMilliseconds;
|
public const int CreatureRegenInterval = 2 * Time.InMilliseconds;
|
||||||
public const int CreatureNoPathEvadeTime = 5 * Time.InMilliseconds;
|
|
||||||
public const int PetFocusRegenInterval = 4 * Time.InMilliseconds;
|
public const int PetFocusRegenInterval = 4 * Time.InMilliseconds;
|
||||||
|
public const int CreatureNoPathEvadeTime = 5 * Time.InMilliseconds;
|
||||||
public const int BoundaryVisualizeCreature = 15425;
|
public const int BoundaryVisualizeCreature = 15425;
|
||||||
public const float BoundaryVisualizeCreatureScale = 0.25f;
|
public const float BoundaryVisualizeCreatureScale = 0.25f;
|
||||||
public const int BoundaryVisualizeStepSize = 1;
|
public const int BoundaryVisualizeStepSize = 1;
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ namespace Game.Entities
|
|||||||
ObjectGuid m_suppressedTarget; // Stores the creature's "real" target while casting
|
ObjectGuid m_suppressedTarget; // Stores the creature's "real" target while casting
|
||||||
float m_suppressedOrientation; // Stores the creature's "real" orientation while casting
|
float m_suppressedOrientation; // Stores the creature's "real" orientation while casting
|
||||||
|
|
||||||
|
long _lastDamagedTime; // Part of Evade mechanics
|
||||||
MultiMap<byte, byte> m_textRepeat = new MultiMap<byte, byte>();
|
MultiMap<byte, byte> m_textRepeat = new MultiMap<byte, byte>();
|
||||||
|
|
||||||
public ulong m_PlayerDamageReq;
|
public ulong m_PlayerDamageReq;
|
||||||
|
|||||||
@@ -101,10 +101,7 @@ namespace Game.Entities
|
|||||||
|
|
||||||
public void DisappearAndDie()
|
public void DisappearAndDie()
|
||||||
{
|
{
|
||||||
DestroyForNearbyPlayers();
|
ForcedDespawn(0);
|
||||||
if (IsAlive())
|
|
||||||
setDeathState(DeathState.JustDied);
|
|
||||||
RemoveCorpse(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SearchFormation()
|
public void SearchFormation()
|
||||||
@@ -121,7 +118,7 @@ namespace Game.Entities
|
|||||||
FormationMgr.AddCreatureToGroup(frmdata.leaderGUID, this);
|
FormationMgr.AddCreatureToGroup(frmdata.leaderGUID, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveCorpse(bool setSpawnTime = true)
|
public void RemoveCorpse(bool setSpawnTime = true, bool destroyForNearbyPlayers = true)
|
||||||
{
|
{
|
||||||
if (getDeathState() != DeathState.Corpse)
|
if (getDeathState() != DeathState.Corpse)
|
||||||
return;
|
return;
|
||||||
@@ -135,6 +132,9 @@ namespace Game.Entities
|
|||||||
if (IsAIEnabled)
|
if (IsAIEnabled)
|
||||||
GetAI().CorpseRemoved(respawnDelay);
|
GetAI().CorpseRemoved(respawnDelay);
|
||||||
|
|
||||||
|
if (destroyForNearbyPlayers)
|
||||||
|
DestroyForNearbyPlayers();
|
||||||
|
|
||||||
// Should get removed later, just keep "compatibility" with scripts
|
// Should get removed later, just keep "compatibility" with scripts
|
||||||
if (setSpawnTime)
|
if (setSpawnTime)
|
||||||
m_respawnTime = Math.Max(Time.UnixTime + respawnDelay, m_respawnTime);
|
m_respawnTime = Math.Max(Time.UnixTime + respawnDelay, m_respawnTime);
|
||||||
@@ -145,6 +145,21 @@ namespace Game.Entities
|
|||||||
|
|
||||||
float x, y, z, o;
|
float x, y, z, o;
|
||||||
GetRespawnPosition(out x, out y, out z, out o);
|
GetRespawnPosition(out x, out y, out z, out o);
|
||||||
|
|
||||||
|
// We were spawned on transport, calculate real position
|
||||||
|
if (IsSpawnedOnTransport())
|
||||||
|
{
|
||||||
|
Position pos = m_movementInfo.transport.pos;
|
||||||
|
pos.posX = x;
|
||||||
|
pos.posY = y;
|
||||||
|
pos.posZ = z;
|
||||||
|
pos.SetOrientation(o);
|
||||||
|
|
||||||
|
ITransport transport = GetDirectTransport();
|
||||||
|
if (transport != null)
|
||||||
|
transport.CalculatePassengerPosition(ref x, ref y, ref z, ref o);
|
||||||
|
}
|
||||||
|
|
||||||
SetHomePosition(x, y, z, o);
|
SetHomePosition(x, y, z, o);
|
||||||
GetMap().CreatureRelocation(this, x, y, z, o);
|
GetMap().CreatureRelocation(this, x, y, z, o);
|
||||||
}
|
}
|
||||||
@@ -275,6 +290,11 @@ namespace Game.Entities
|
|||||||
SetNpcFlags((NPCFlags)(npcFlags & 0xFFFFFFFF));
|
SetNpcFlags((NPCFlags)(npcFlags & 0xFFFFFFFF));
|
||||||
SetNpcFlags2((NPCFlags2)(npcFlags >> 32));
|
SetNpcFlags2((NPCFlags2)(npcFlags >> 32));
|
||||||
|
|
||||||
|
// if unit is in combat, keep this flag
|
||||||
|
unitFlags &= ~(uint)UnitFlags.InCombat;
|
||||||
|
if (IsInCombat())
|
||||||
|
unitFlags |= (uint)UnitFlags.InCombat;
|
||||||
|
|
||||||
SetUnitFlags((UnitFlags)unitFlags);
|
SetUnitFlags((UnitFlags)unitFlags);
|
||||||
SetUnitFlags2((UnitFlags2)unitFlags2);
|
SetUnitFlags2((UnitFlags2)unitFlags2);
|
||||||
SetUnitFlags3((UnitFlags3)unitFlags3);
|
SetUnitFlags3((UnitFlags3)unitFlags3);
|
||||||
@@ -283,8 +303,6 @@ namespace Game.Entities
|
|||||||
|
|
||||||
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.StateAnimID), (uint)CliDB.AnimationDataStorage.Count);
|
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.StateAnimID), (uint)CliDB.AnimationDataStorage.Count);
|
||||||
|
|
||||||
RemoveUnitFlag(UnitFlags.InCombat);
|
|
||||||
|
|
||||||
SetBaseAttackTime(WeaponAttackType.BaseAttack, cInfo.BaseAttackTime);
|
SetBaseAttackTime(WeaponAttackType.BaseAttack, cInfo.BaseAttackTime);
|
||||||
SetBaseAttackTime(WeaponAttackType.OffAttack, cInfo.BaseAttackTime);
|
SetBaseAttackTime(WeaponAttackType.OffAttack, cInfo.BaseAttackTime);
|
||||||
SetBaseAttackTime(WeaponAttackType.RangedAttack, cInfo.RangeAttackTime);
|
SetBaseAttackTime(WeaponAttackType.RangedAttack, cInfo.RangeAttackTime);
|
||||||
@@ -518,13 +536,11 @@ namespace Game.Entities
|
|||||||
if (!IsInEvadeMode() && (!bInCombat || IsPolymorphed() || CanNotReachTarget())) // regenerate health if not in combat or if polymorphed
|
if (!IsInEvadeMode() && (!bInCombat || IsPolymorphed() || CanNotReachTarget())) // regenerate health if not in combat or if polymorphed
|
||||||
RegenerateHealth();
|
RegenerateHealth();
|
||||||
|
|
||||||
if (HasUnitFlag2(UnitFlags2.RegeneratePower))
|
if (GetPowerType() == PowerType.Energy)
|
||||||
{
|
Regenerate(PowerType.Energy);
|
||||||
if (GetPowerType() == PowerType.Energy)
|
else
|
||||||
Regenerate(PowerType.Energy);
|
Regenerate(PowerType.Mana);
|
||||||
else
|
|
||||||
RegenerateMana();
|
|
||||||
}
|
|
||||||
m_regenTimer = SharedConst.CreatureRegenInterval;
|
m_regenTimer = SharedConst.CreatureRegenInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,66 +557,14 @@ namespace Game.Entities
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegenerateMana()
|
|
||||||
{
|
|
||||||
int curValue = GetPower(PowerType.Mana);
|
|
||||||
int maxValue = GetMaxPower(PowerType.Mana);
|
|
||||||
|
|
||||||
if (curValue >= maxValue)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int addvalue = 0;
|
|
||||||
|
|
||||||
// Combat and any controlled creature
|
|
||||||
if (IsInCombat() || !GetCharmerOrOwnerGUID().IsEmpty())
|
|
||||||
{
|
|
||||||
float ManaIncreaseRate = WorldConfig.GetFloatValue(WorldCfg.RatePowerMana);
|
|
||||||
addvalue = (int)((27.0f / 5.0f + 17.0f) * ManaIncreaseRate);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
addvalue = maxValue / 3;
|
|
||||||
|
|
||||||
// Apply modifiers (if any).
|
|
||||||
addvalue *= (int)GetTotalAuraMultiplierByMiscValue(AuraType.ModPowerRegenPercent, (int)PowerType.Mana);
|
|
||||||
addvalue += GetTotalAuraModifierByMiscValue(AuraType.ModPowerRegen, (int)PowerType.Mana) * SharedConst.CreatureRegenInterval / (5 * Time.InMilliseconds);
|
|
||||||
|
|
||||||
ModifyPower(PowerType.Mana, addvalue);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegenerateHealth()
|
|
||||||
{
|
|
||||||
if (!isRegeneratingHealth())
|
|
||||||
return;
|
|
||||||
|
|
||||||
ulong curValue = GetHealth();
|
|
||||||
ulong maxValue = GetMaxHealth();
|
|
||||||
|
|
||||||
if (curValue >= maxValue)
|
|
||||||
return;
|
|
||||||
|
|
||||||
long addvalue = 0;
|
|
||||||
|
|
||||||
// Not only pet, but any controlled creature
|
|
||||||
if (!GetCharmerOrOwnerGUID().IsEmpty())
|
|
||||||
{
|
|
||||||
float HealthIncreaseRate = WorldConfig.GetFloatValue(WorldCfg.RateHealth);
|
|
||||||
addvalue = (uint)(0.015f * GetMaxHealth() * HealthIncreaseRate);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
addvalue = (long)maxValue / 3;
|
|
||||||
|
|
||||||
// Apply modifiers (if any).
|
|
||||||
addvalue *= (int)GetTotalAuraMultiplier(AuraType.ModHealthRegenPercent);
|
|
||||||
addvalue += GetTotalAuraModifier(AuraType.ModRegen) * SharedConst.CreatureRegenInterval / (5 * Time.InMilliseconds);
|
|
||||||
|
|
||||||
ModifyHealth(addvalue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Regenerate(PowerType power)
|
public void Regenerate(PowerType power)
|
||||||
{
|
{
|
||||||
int curValue = GetPower(power);
|
int curValue = GetPower(power);
|
||||||
int maxValue = GetMaxPower(power);
|
int maxValue = GetMaxPower(power);
|
||||||
|
|
||||||
|
if (!HasUnitFlag2(UnitFlags2.RegeneratePower))
|
||||||
|
return;
|
||||||
|
|
||||||
if (curValue >= maxValue)
|
if (curValue >= maxValue)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -620,6 +584,19 @@ namespace Game.Entities
|
|||||||
addvalue = 20;
|
addvalue = 20;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PowerType.Mana:
|
||||||
|
{
|
||||||
|
// Combat and any controlled creature
|
||||||
|
if (IsInCombat() || GetCharmerOrOwnerGUID().IsEmpty())
|
||||||
|
{
|
||||||
|
float ManaIncreaseRate = WorldConfig.GetFloatValue(WorldCfg.RatePowerMana);
|
||||||
|
addvalue = (27.0f / 5.0f + 17.0f) * ManaIncreaseRate;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
addvalue = maxValue / 3;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -631,6 +608,35 @@ namespace Game.Entities
|
|||||||
ModifyPower(power, (int)addvalue);
|
ModifyPower(power, (int)addvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegenerateHealth()
|
||||||
|
{
|
||||||
|
if (!isRegeneratingHealth())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ulong curValue = GetHealth();
|
||||||
|
ulong maxValue = GetMaxHealth();
|
||||||
|
|
||||||
|
if (curValue >= maxValue)
|
||||||
|
return;
|
||||||
|
|
||||||
|
long addvalue = 0;
|
||||||
|
|
||||||
|
// Not only pet, but any controlled creature (and not polymorphed)
|
||||||
|
if (!GetCharmerOrOwnerGUID().IsEmpty() && !IsPolymorphed())
|
||||||
|
{
|
||||||
|
float HealthIncreaseRate = WorldConfig.GetFloatValue(WorldCfg.RateHealth);
|
||||||
|
addvalue = (uint)(0.015f * GetMaxHealth() * HealthIncreaseRate);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
addvalue = (long)maxValue / 3;
|
||||||
|
|
||||||
|
// Apply modifiers (if any).
|
||||||
|
addvalue *= (int)GetTotalAuraMultiplier(AuraType.ModHealthRegenPercent);
|
||||||
|
addvalue += GetTotalAuraModifier(AuraType.ModRegen) * SharedConst.CreatureRegenInterval / (5 * Time.InMilliseconds);
|
||||||
|
|
||||||
|
ModifyHealth(addvalue);
|
||||||
|
}
|
||||||
|
|
||||||
public void DoFleeToGetAssistance()
|
public void DoFleeToGetAssistance()
|
||||||
{
|
{
|
||||||
if (!GetVictim())
|
if (!GetVictim())
|
||||||
@@ -770,6 +776,10 @@ namespace Game.Entities
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allow players to see those units while dead, do it here (mayby altered by addon auras)
|
||||||
|
if (cinfo.TypeFlags.HasAnyFlag(CreatureTypeFlags.GhostVisible))
|
||||||
|
m_serverSideVisibility.SetValue(ServerSideVisibilityType.Ghost, GhostVisibilityType.Alive | GhostVisibilityType.Ghost);
|
||||||
|
|
||||||
if (!CreateFromProto(guidlow, entry, data, vehId))
|
if (!CreateFromProto(guidlow, entry, data, vehId))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -1615,7 +1625,7 @@ namespace Game.Entities
|
|||||||
setDeathState(DeathState.Corpse);
|
setDeathState(DeathState.Corpse);
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoveCorpse(false);
|
RemoveCorpse(false, false);
|
||||||
|
|
||||||
if (getDeathState() == DeathState.Dead)
|
if (getDeathState() == DeathState.Dead)
|
||||||
{
|
{
|
||||||
@@ -1672,33 +1682,21 @@ namespace Game.Entities
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// do it before killing creature
|
||||||
|
DestroyForNearbyPlayers();
|
||||||
|
|
||||||
|
if (IsAlive())
|
||||||
|
setDeathState(DeathState.JustDied);
|
||||||
|
|
||||||
|
bool overrideRespawnTime = true;
|
||||||
if (forceRespawnTimer > TimeSpan.Zero)
|
if (forceRespawnTimer > TimeSpan.Zero)
|
||||||
{
|
{
|
||||||
if (IsAlive())
|
SetRespawnTime((uint)forceRespawnTimer.TotalSeconds);
|
||||||
{
|
overrideRespawnTime = false;
|
||||||
uint respawnDelay = m_respawnDelay;
|
|
||||||
uint corpseDelay = m_corpseDelay;
|
|
||||||
m_respawnDelay = (uint)forceRespawnTimer.TotalSeconds;
|
|
||||||
m_corpseDelay = 0;
|
|
||||||
setDeathState(DeathState.JustDied);
|
|
||||||
|
|
||||||
m_respawnDelay = respawnDelay;
|
|
||||||
m_corpseDelay = corpseDelay;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_corpseRemoveTime = Time.UnixTime;
|
|
||||||
m_respawnTime = Time.UnixTime + (long)forceRespawnTimer.TotalMilliseconds;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (IsAlive())
|
|
||||||
setDeathState(DeathState.JustDied);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoveCorpse(false);
|
// Skip corpse decay time
|
||||||
|
RemoveCorpse(overrideRespawnTime, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DespawnOrUnsummon(TimeSpan time, TimeSpan forceRespawnTimer = default(TimeSpan)) { DespawnOrUnsummon((uint)time.TotalMilliseconds, forceRespawnTimer); }
|
public void DespawnOrUnsummon(TimeSpan time, TimeSpan forceRespawnTimer = default(TimeSpan)) { DespawnOrUnsummon((uint)time.TotalMilliseconds, forceRespawnTimer); }
|
||||||
@@ -1979,6 +1977,14 @@ namespace Game.Entities
|
|||||||
if (!IsAlive())
|
if (!IsAlive())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// we cannot assist in evade mode
|
||||||
|
if (IsInEvadeMode())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// or if enemy is in evade mode
|
||||||
|
if (enemy.GetTypeId() == TypeId.Unit && enemy.ToCreature().IsInEvadeMode())
|
||||||
|
return false;
|
||||||
|
|
||||||
// we don't need help from non-combatant ;)
|
// we don't need help from non-combatant ;)
|
||||||
if (IsCivilian())
|
if (IsCivilian())
|
||||||
return false;
|
return false;
|
||||||
@@ -2066,22 +2072,41 @@ namespace Game.Entities
|
|||||||
if (IsAIEnabled && !GetAI().CanAIAttack(victim))
|
if (IsAIEnabled && !GetAI().CanAIAttack(victim))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (GetMap().IsDungeon())
|
// we cannot attack in evade mode
|
||||||
return true;
|
if (IsInEvadeMode())
|
||||||
|
return false;
|
||||||
|
|
||||||
// if the mob is actively being damaged, do not reset due to distance unless it's a world boss
|
// or if enemy is in evade mode
|
||||||
if (!isWorldBoss())
|
if (victim.GetTypeId() == TypeId.Unit && victim.ToCreature().IsInEvadeMode())
|
||||||
if (Time.UnixTime - GetLastDamagedTime() <= SharedConst.MaxAggroResetTime)
|
return false;
|
||||||
|
|
||||||
|
if (!GetCharmerOrOwnerGUID().IsPlayer())
|
||||||
|
{
|
||||||
|
if (GetMap().IsDungeon())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
//Use AttackDistance in distance check if threat radius is lower. This prevents creature bounce in and out of combat every update tick.
|
// don't check distance to home position if recently damaged, this should include taunt auras
|
||||||
float dist = Math.Max(GetAttackDistance(victim), (WorldConfig.GetFloatValue(WorldCfg.ThreatRadius) + m_CombatDistance));
|
if (!isWorldBoss() && (GetLastDamagedTime() > Global.WorldMgr.GetGameTime() || HasAuraType(AuraType.ModTaunt)))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map visibility range, but no more than 2*cell size
|
||||||
|
float dist = Math.Min(GetMap().GetVisibilityRange(), MapConst.SizeofCells * 2);
|
||||||
|
|
||||||
Unit unit = GetCharmerOrOwner();
|
Unit unit = GetCharmerOrOwner();
|
||||||
if (unit != null)
|
if (unit != null)
|
||||||
return victim.IsWithinDist(unit, dist);
|
return victim.IsWithinDist(unit, dist);
|
||||||
else
|
else
|
||||||
return victim.IsInDist(m_homePosition, dist);
|
{
|
||||||
|
// include sizes for huge npcs
|
||||||
|
dist += GetObjectSize() + victim.GetObjectSize();
|
||||||
|
|
||||||
|
// to prevent creatures in air ignore attacks because distance is already too high...
|
||||||
|
if (GetCreatureTemplate().InhabitType.HasAnyFlag(InhabitType.Air))
|
||||||
|
return victim.IsInDist2d(m_homePosition, dist);
|
||||||
|
else
|
||||||
|
return victim.IsInDist(m_homePosition, dist);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CreatureAddon GetCreatureAddon()
|
CreatureAddon GetCreatureAddon()
|
||||||
@@ -2242,40 +2267,17 @@ namespace Game.Entities
|
|||||||
|
|
||||||
public void GetRespawnPosition(out float x, out float y, out float z)
|
public void GetRespawnPosition(out float x, out float y, out float z)
|
||||||
{
|
{
|
||||||
if (m_spawnId != 0)
|
float notUsed;
|
||||||
{
|
GetRespawnPosition(out x, out y, out z, out notUsed, out notUsed);
|
||||||
CreatureData data = Global.ObjectMgr.GetCreatureData(GetSpawnId());
|
|
||||||
if (data != null)
|
|
||||||
{
|
|
||||||
x = data.posX;
|
|
||||||
y = data.posY;
|
|
||||||
z = data.posZ;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GetPosition(out x, out y, out z);
|
|
||||||
}
|
}
|
||||||
public void GetRespawnPosition(out float x, out float y, out float z, out float ori)
|
public void GetRespawnPosition(out float x, out float y, out float z, out float ori)
|
||||||
{
|
{
|
||||||
if (m_spawnId != 0)
|
float notUsed;
|
||||||
{
|
GetRespawnPosition(out x, out y, out z, out ori, out notUsed);
|
||||||
CreatureData data = Global.ObjectMgr.GetCreatureData(GetSpawnId());
|
|
||||||
if (data != null)
|
|
||||||
{
|
|
||||||
x = data.posX;
|
|
||||||
y = data.posY;
|
|
||||||
z = data.posZ;
|
|
||||||
ori = data.orientation;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GetPosition(out x, out y, out z, out ori);
|
|
||||||
}
|
}
|
||||||
public void GetRespawnPosition(out float x, out float y, out float z, out float ori, out float dist)
|
public void GetRespawnPosition(out float x, out float y, out float z, out float ori, out float dist)
|
||||||
{
|
{
|
||||||
|
// for npcs on transport, this will return transport offset
|
||||||
if (m_spawnId != 0)
|
if (m_spawnId != 0)
|
||||||
{
|
{
|
||||||
CreatureData data = Global.ObjectMgr.GetCreatureData(GetSpawnId());
|
CreatureData data = Global.ObjectMgr.GetCreatureData(GetSpawnId());
|
||||||
@@ -2291,10 +2293,17 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GetPosition(out x, out y, out z, out ori);
|
// changed this from current position to home position, fixes world summons with infinite duration (wg npcs for example)
|
||||||
|
Position homePos = GetHomePosition();
|
||||||
|
x = homePos.GetPositionX();
|
||||||
|
y = homePos.GetPositionY();
|
||||||
|
z = homePos.GetPositionZ();
|
||||||
|
ori = homePos.GetOrientation();
|
||||||
dist = 0;
|
dist = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsSpawnedOnTransport() { return m_creatureData != null && m_creatureData.mapid != GetMapId(); }
|
||||||
|
|
||||||
public void AllLootRemovedFromCorpse()
|
public void AllLootRemovedFromCorpse()
|
||||||
{
|
{
|
||||||
if (loot.loot_type != LootType.Skinning && !IsPet() && GetCreatureTemplate().SkinLootId != 0 && hasLootRecipient())
|
if (loot.loot_type != LootType.Skinning && !IsPet() && GetCreatureTemplate().SkinLootId != 0 && hasLootRecipient())
|
||||||
@@ -3056,6 +3065,10 @@ namespace Game.Entities
|
|||||||
public bool IsReputationGainDisabled() { return DisableReputationGain; }
|
public bool IsReputationGainDisabled() { return DisableReputationGain; }
|
||||||
public bool IsDamageEnoughForLootingAndReward() { return m_creatureInfo.FlagsExtra.HasAnyFlag(CreatureFlagsExtra.NoPlayerDamageReq) || m_PlayerDamageReq == 0; }
|
public bool IsDamageEnoughForLootingAndReward() { return m_creatureInfo.FlagsExtra.HasAnyFlag(CreatureFlagsExtra.NoPlayerDamageReq) || m_PlayerDamageReq == 0; }
|
||||||
|
|
||||||
|
// Part of Evade mechanics
|
||||||
|
long GetLastDamagedTime() { return _lastDamagedTime; }
|
||||||
|
public void SetLastDamagedTime(long val) { _lastDamagedTime = val; }
|
||||||
|
|
||||||
public void ResetPlayerDamageReq() { m_PlayerDamageReq = (uint)(GetHealth() / 2); }
|
public void ResetPlayerDamageReq() { m_PlayerDamageReq = (uint)(GetHealth() / 2); }
|
||||||
|
|
||||||
public uint GetOriginalEntry()
|
public uint GetOriginalEntry()
|
||||||
|
|||||||
@@ -1047,13 +1047,14 @@ namespace Game.Entities
|
|||||||
victim.ModifyHealth(-(int)damage);
|
victim.ModifyHealth(-(int)damage);
|
||||||
|
|
||||||
if (damagetype == DamageEffectType.Direct || damagetype == DamageEffectType.SpellDirect)
|
if (damagetype == DamageEffectType.Direct || damagetype == DamageEffectType.SpellDirect)
|
||||||
{
|
|
||||||
victim.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.DirectDamage, spellProto != null ? spellProto.Id : 0);
|
victim.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.DirectDamage, spellProto != null ? spellProto.Id : 0);
|
||||||
victim.UpdateLastDamagedTime(spellProto);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!victim.IsTypeId(TypeId.Player))
|
if (!victim.IsTypeId(TypeId.Player))
|
||||||
{
|
{
|
||||||
|
// Part of Evade mechanics. DoT's and Thorns / Retribution Aura do not contribute to this
|
||||||
|
if (damagetype != DamageEffectType.DOT && damage > 0 && !victim.GetOwnerGUID().IsPlayer() && (spellProto == null || !spellProto.HasAura(GetMap().GetDifficultyID(), AuraType.DamageShield)))
|
||||||
|
victim.ToCreature().SetLastDamagedTime(Global.WorldMgr.GetGameTime() + SharedConst.MaxAggroResetTime);
|
||||||
|
|
||||||
victim.AddThreat(this, damage, damageSchoolMask, spellProto);
|
victim.AddThreat(this, damage, damageSchoolMask, spellProto);
|
||||||
}
|
}
|
||||||
else // victim is a player
|
else // victim is a player
|
||||||
@@ -3206,9 +3207,5 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Part of Evade mechanics
|
|
||||||
public long GetLastDamagedTime() { return _lastDamagedTime; }
|
|
||||||
public void SetLastDamagedTime(long val) { _lastDamagedTime = val; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ namespace Game.Entities
|
|||||||
public float m_modMeleeHitChance { get; set; }
|
public float m_modMeleeHitChance { get; set; }
|
||||||
public float m_modRangedHitChance { get; set; }
|
public float m_modRangedHitChance { get; set; }
|
||||||
public float m_modSpellHitChance { get; set; }
|
public float m_modSpellHitChance { get; set; }
|
||||||
long _lastDamagedTime;
|
|
||||||
bool m_canDualWield;
|
bool m_canDualWield;
|
||||||
public int m_baseSpellCritChance { get; set; }
|
public int m_baseSpellCritChance { get; set; }
|
||||||
public uint m_regenTimer { get; set; }
|
public uint m_regenTimer { get; set; }
|
||||||
|
|||||||
@@ -4262,17 +4262,6 @@ namespace Game.Entities
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateLastDamagedTime(SpellInfo spellProto)
|
|
||||||
{
|
|
||||||
if (!IsTypeId(TypeId.Unit) || IsPet())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (spellProto != null && spellProto.HasAura(Difficulty.None, AuraType.DamageShield))
|
|
||||||
return;
|
|
||||||
|
|
||||||
SetLastDamagedTime(Time.UnixTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsHighestExclusiveAura(Aura aura, bool removeOtherAuraApplications = false)
|
public bool IsHighestExclusiveAura(Aura aura, bool removeOtherAuraApplications = false)
|
||||||
{
|
{
|
||||||
foreach (AuraEffect aurEff in aura.GetAuraEffects())
|
foreach (AuraEffect aurEff in aura.GetAuraEffects())
|
||||||
|
|||||||
@@ -143,8 +143,9 @@ namespace Game
|
|||||||
|
|
||||||
GetPlayer().RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Talk);
|
GetPlayer().RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Talk);
|
||||||
|
|
||||||
if (unit.IsArmorer() || unit.IsCivilian() || unit.IsQuestGiver() || unit.IsServiceProvider() || unit.IsGuard())
|
// and if he has pure gossip or is banker and moves or is tabard designer?
|
||||||
unit.StopMoving();
|
//if (unit->IsArmorer() || unit->IsCivilian() || unit->IsQuestGiver() || unit->IsServiceProvider() || unit->IsGuard())
|
||||||
|
unit.StopMoving();
|
||||||
|
|
||||||
// If spiritguide, no need for gossip menu, just put player into resurrect queue
|
// If spiritguide, no need for gossip menu, just put player into resurrect queue
|
||||||
if (unit.IsSpiritGuide())
|
if (unit.IsSpiritGuide())
|
||||||
|
|||||||
@@ -438,7 +438,7 @@ namespace Game.PvP
|
|||||||
{
|
{
|
||||||
// Don't save respawn time
|
// Don't save respawn time
|
||||||
creature.SetRespawnTime(0);
|
creature.SetRespawnTime(0);
|
||||||
creature.RemoveCorpse();
|
creature.DespawnOrUnsummon();
|
||||||
creature.AddObjectToRemoveList();
|
creature.AddObjectToRemoveList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2587,7 +2587,7 @@ namespace Game.Spells
|
|||||||
{
|
{
|
||||||
target.Kill(caster);
|
target.Kill(caster);
|
||||||
if (caster.IsTypeId(TypeId.Unit))
|
if (caster.IsTypeId(TypeId.Unit))
|
||||||
caster.ToCreature().RemoveCorpse();
|
caster.ToCreature().DespawnOrUnsummon();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mode.HasAnyFlag(AuraEffectHandleModes.ChangeAmount))
|
if (!mode.HasAnyFlag(AuraEffectHandleModes.ChangeAmount))
|
||||||
|
|||||||
@@ -2956,10 +2956,7 @@ namespace Game.Spells
|
|||||||
caster.RewardPlayerAndGroupAtEvent(18388, unitTarget);
|
caster.RewardPlayerAndGroupAtEvent(18388, unitTarget);
|
||||||
Creature target = unitTarget.ToCreature();
|
Creature target = unitTarget.ToCreature();
|
||||||
if (target != null)
|
if (target != null)
|
||||||
{
|
target.DespawnOrUnsummon();
|
||||||
target.setDeathState(DeathState.Corpse);
|
|
||||||
target.RemoveCorpse();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// Mug Transformation
|
// Mug Transformation
|
||||||
|
|||||||
Reference in New Issue
Block a user