Updated to 8.2.0.31429 (scripts disabled atm, they still need updated)

Code Port from TrinityCore https://github.com/TrinityCore/TrinityCore
Casc from WoW-Tools https://github.com/WoW-Tools/CASCExplorer
This commit is contained in:
hondacrx
2019-08-14 11:20:42 -04:00
parent e4d500f4b5
commit 125e3b3ac7
232 changed files with 12268 additions and 14670 deletions
+2 -2
View File
@@ -236,9 +236,9 @@ namespace Game.Entities
{
_petnumber = petnumber;
if (statwindow)
_unit.SetUInt32Value(UnitFields.PetNumber, _petnumber);
_unit.SetPetNumberForClient(_petnumber);
else
_unit.SetUInt32Value(UnitFields.PetNumber, 0);
_unit.SetPetNumberForClient(0);
}
public void LoadPetActionBar(string data)
+98 -67
View File
@@ -246,15 +246,15 @@ namespace Game.Entities
public void ClearInCombat()
{
m_CombatTimer = 0;
RemoveFlag(UnitFields.Flags, UnitFlags.InCombat);
RemoveUnitFlag(UnitFlags.InCombat);
// Player's state will be cleared in Player.UpdateContestedPvP
Creature creature = ToCreature();
if (creature != null)
{
ClearUnitState(UnitState.AttackPlayer);
if (HasFlag(ObjectFields.DynamicFlags, UnitDynFlags.Tapped))
SetUInt32Value(ObjectFields.DynamicFlags, creature.GetCreatureTemplate().DynamicFlags);
if (HasDynamicFlag(UnitDynFlags.Tapped))
SetDynamicFlags((UnitDynFlags)creature.GetCreatureTemplate().DynamicFlags);
if (creature.IsPet() || creature.IsGuardian())
{
@@ -270,7 +270,7 @@ namespace Game.Entities
else
ToPlayer().OnCombatExit();
RemoveFlag(UnitFields.Flags, UnitFlags.PetInCombat);
RemoveUnitFlag(UnitFlags.PetInCombat);
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.LeaveCombat);
}
@@ -314,7 +314,7 @@ namespace Game.Entities
if (!IsAlive())
return false;
if (HasFlag(UnitFields.Flags, (UnitFlags.NonAttackable | UnitFlags.NotSelectable)))
if (HasUnitFlag(UnitFlags.NonAttackable | UnitFlags.NotSelectable))
return false;
if (IsTypeId(TypeId.Player) && ToPlayer().IsGameMaster())
@@ -329,7 +329,7 @@ namespace Game.Entities
}
public bool IsInCombat()
{
return HasFlag(UnitFields.Flags, UnitFlags.InCombat);
return HasUnitFlag(UnitFlags.InCombat);
}
public bool Attack(Unit victim, bool meleeAttack)
{
@@ -344,7 +344,7 @@ namespace Game.Entities
if (IsTypeId(TypeId.Player) && IsMounted())
return false;
if (HasFlag(UnitFields.Flags, UnitFlags.Pacified))
if (HasUnitFlag(UnitFlags.Pacified))
return false;
// nobody can attack GM in GM-mode
@@ -417,7 +417,7 @@ namespace Game.Entities
ToCreature().CallAssistance();
// Remove emote state - will be restored on creature reset
SetUInt32Value(UnitFields.NpcEmotestate, (uint)Emote.OneshotNone);
SetEmoteState(Emote.OneshotNone);
}
// delay offhand weapon attack to next attack time
@@ -455,7 +455,7 @@ namespace Game.Entities
else
Log.outInfo(LogFilter.Unit, "{0} {1} stopped attacking", (IsTypeId(TypeId.Player) ? "Player" : "Creature"), GetGUID().ToString());
}
public ObjectGuid GetTarget() { return GetGuidValue(UnitFields.Target); }
public ObjectGuid GetTarget() { return m_unitData.Target; }
public virtual void SetTarget(ObjectGuid guid) { }
public bool AttackStop()
{
@@ -517,8 +517,10 @@ namespace Game.Entities
return attackerList;
}
public float GetCombatReach() { return GetFloatValue(UnitFields.CombatReach); }
float GetBoundaryRadius() { return GetFloatValue(UnitFields.BoundingRadius); }
public float GetCombatReach() { return m_unitData.CombatReach; }
public void SetCombatReach(float combatReach) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.CombatReach), combatReach); }
public float GetBoundingRadius() { return m_unitData.BoundingRadius; }
public void SetBoundingRadius(float boundingRadius) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.BoundingRadius), boundingRadius); }
public bool haveOffhandWeapon()
{
@@ -549,7 +551,7 @@ namespace Game.Entities
}
public void AttackerStateUpdate(Unit victim, WeaponAttackType attType = WeaponAttackType.BaseAttack, bool extra = false)
{
if (HasUnitState(UnitState.CannotAutoattack) || HasFlag(UnitFields.Flags, UnitFlags.Pacified))
if (HasUnitState(UnitState.CannotAutoattack) || HasUnitFlag(UnitFlags.Pacified))
return;
if (!victim.IsAlive())
@@ -565,7 +567,7 @@ namespace Game.Entities
if (attType != WeaponAttackType.BaseAttack && attType != WeaponAttackType.OffAttack)
return;
if (IsTypeId(TypeId.Unit) && !HasFlag(UnitFields.Flags, UnitFlags.PlayerControlled))
if (IsTypeId(TypeId.Unit) && !HasUnitFlag(UnitFlags.PlayerControlled))
SetFacingToObject(victim); // update client side facing to face the target (prevents visual glitches when casting untargeted spells)
// melee attack spell casted at main hand attack only - no normal melee dmg dealt
@@ -598,7 +600,7 @@ namespace Game.Entities
public void FakeAttackerStateUpdate(Unit victim, WeaponAttackType attType = WeaponAttackType.BaseAttack)
{
if (HasUnitState(UnitState.CannotAutoattack) || HasFlag(UnitFields.Flags, UnitFlags.Pacified))
if (HasUnitState(UnitState.CannotAutoattack) || HasUnitFlag(UnitFlags.Pacified))
return;
if (!victim.IsAlive())
@@ -613,7 +615,7 @@ namespace Game.Entities
if (attType != WeaponAttackType.BaseAttack && attType != WeaponAttackType.OffAttack)
return; // ignore ranged case
if (IsTypeId(TypeId.Unit) && !HasFlag(UnitFields.Flags, UnitFlags.PlayerControlled))
if (IsTypeId(TypeId.Unit) && !HasUnitFlag(UnitFlags.PlayerControlled))
SetFacingToObject(victim); // update client side facing to face the target (prevents visual glitches when casting untargeted spells)
CalcDamageInfo damageInfo = new CalcDamageInfo();
@@ -1290,7 +1292,7 @@ namespace Game.Entities
if (IsInCombat() || HasUnitState(UnitState.Evade))
return;
SetFlag(UnitFields.Flags, UnitFlags.InCombat);
AddUnitFlag(UnitFlags.InCombat);
Creature creature = ToCreature();
if (creature != null)
@@ -1323,7 +1325,7 @@ namespace Game.Entities
foreach (var unit in m_Controlled)
{
unit.SetInCombatState(PvP, enemy);
unit.SetFlag(UnitFields.Flags, UnitFlags.PetInCombat);
unit.AddUnitFlag(UnitFlags.PetInCombat);
}
ProcSkillsAndAuras(enemy, ProcFlags.EnterCombat, ProcFlags.None, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null);
@@ -1504,7 +1506,7 @@ namespace Game.Entities
// must be after setDeathState which resets dynamic flags
if (!creature.loot.isLooted())
creature.SetFlag(ObjectFields.DynamicFlags, UnitDynFlags.Lootable);
creature.AddDynamicFlag(UnitDynFlags.Lootable);
else
creature.AllLootRemovedFromCorpse();
}
@@ -1625,7 +1627,7 @@ namespace Game.Entities
if (!player.HasUnitState(UnitState.AttackPlayer))
{
player.AddUnitState(UnitState.AttackPlayer);
player.SetFlag(PlayerFields.Flags, PlayerFlags.ContestedPVP);
player.AddPlayerFlag(PlayerFlags.ContestedPVP);
// call MoveInLineOfSight for nearby contested guards
UpdateObjectVisibility();
}
@@ -1766,6 +1768,21 @@ namespace Game.Entities
ToPlayer().ClearComboPoints();
}
public virtual bool CanUseAttackType(WeaponAttackType attacktype)
{
switch (attacktype)
{
case WeaponAttackType.BaseAttack:
return !HasUnitFlag(UnitFlags.Disarmed);
case WeaponAttackType.OffAttack:
return !HasUnitFlag2(UnitFlags2.DisarmOffhand);
case WeaponAttackType.RangedAttack:
return !HasUnitFlag2(UnitFlags2.DisarmRanged);
default:
return true;
}
}
// TODO for melee need create structure as in
void CalculateMeleeDamage(Unit victim, uint damage, out CalcDamageInfo damageInfo, WeaponAttackType attackType)
{
@@ -2082,21 +2099,21 @@ namespace Game.Entities
switch (attType)
{
case WeaponAttackType.RangedAttack:
minDamage = GetFloatValue(UnitFields.MinRangedDamage);
maxDamage = GetFloatValue(UnitFields.MaxRangedDamage);
minDamage = m_unitData.MinRangedDamage;
maxDamage = m_unitData.MaxRangedDamage;
break;
case WeaponAttackType.BaseAttack:
minDamage = GetFloatValue(UnitFields.MinDamage);
maxDamage = GetFloatValue(UnitFields.MaxDamage);
minDamage = m_unitData.MinDamage;
maxDamage = m_unitData.MaxDamage;
if (IsInFeralForm())
{
minDamage += GetFloatValue(UnitFields.MinOffHandDamage);
maxDamage += GetFloatValue(UnitFields.MaxOffHandDamage);
minDamage += m_unitData.MinOffHandDamage;
maxDamage += m_unitData.MaxOffHandDamage;
}
break;
case WeaponAttackType.OffAttack:
minDamage = GetFloatValue(UnitFields.MinOffHandDamage);
maxDamage = GetFloatValue(UnitFields.MaxOffHandDamage);
minDamage = m_unitData.MinOffHandDamage;
maxDamage = m_unitData.MaxOffHandDamage;
break;
// Just for good manner
default:
@@ -2169,17 +2186,17 @@ namespace Game.Entities
{
if (attType == WeaponAttackType.RangedAttack)
{
int ap = GetInt32Value(UnitFields.RangedAttackPower);
int ap = m_unitData.RangedAttackPower;
if (ap < 0)
return 0.0f;
return ap * (1.0f + GetFloatValue(UnitFields.RangedAttackPowerMultiplier));
return ap * (1.0f + m_unitData.RangedAttackPowerMultiplier);
}
else
{
int ap = GetInt32Value(UnitFields.AttackPower);
int ap = m_unitData.AttackPower;
if (ap < 0)
return 0.0f;
return ap * (1.0f + GetFloatValue(UnitFields.AttackPowerMultiplier));
return ap * (1.0f + m_unitData.AttackPowerMultiplier);
}
}
public float GetModifierValue(UnitMods unitMod, UnitModifierType modifierType)
@@ -2223,14 +2240,25 @@ namespace Game.Entities
}
void UpdateAttackTimeField(WeaponAttackType att)
{
SetUInt32Value(UnitFields.BaseAttackTime + (int)att, (uint)(m_baseAttackSpeed[(int)att] * m_modAttackSpeedPct[(int)att]));
switch (att)
{
case WeaponAttackType.BaseAttack:
case WeaponAttackType.OffAttack:
SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.AttackRoundBaseTime, (int)att), (uint)(m_baseAttackSpeed[(int)att] * m_modAttackSpeedPct[(int)att]));
break;
case WeaponAttackType.RangedAttack:
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.RangedAttackRoundBaseTime), (uint)(m_baseAttackSpeed[(int)att] * m_modAttackSpeedPct[(int)att]));
break;
default:
break; ;
}
}
public virtual void SetPvP(bool state)
{
if (state)
SetByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, UnitBytes2Flags.PvP);
AddPvpFlag(UnitPVPStateFlags.PvP);
else
RemoveByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, UnitBytes2Flags.PvP);
RemovePvpFlag(UnitPVPStateFlags.PvP);
}
public bool CanHaveThreatList(bool skipAliveCheck = false)
@@ -2697,11 +2725,17 @@ namespace Game.Entities
if (!spellProto.GetSchoolMask().HasAnyFlag(SpellSchoolMask.Normal))
{
float maxModDamagePercentSchool = 0.0f;
for (var i = SpellSchools.Holy; i < SpellSchools.Max; ++i)
Player thisPlayer = ToPlayer();
if (thisPlayer != null)
{
if (Convert.ToBoolean((int)spellProto.GetSchoolMask() & (1 << (int)i)))
maxModDamagePercentSchool = Math.Max(maxModDamagePercentSchool, GetFloatValue(ActivePlayerFields.ModDamageDonePct + (int)i));
for (var i = SpellSchools.Holy; i < SpellSchools.Max; ++i)
{
if (Convert.ToBoolean((int)spellProto.GetSchoolMask() & (1 << (int)i)))
maxModDamagePercentSchool = Math.Max(maxModDamagePercentSchool, thisPlayer.m_activePlayerData.ModDamageDonePercent[(int)i]);
}
}
else
maxModDamagePercentSchool = GetTotalAuraMultiplierByMiscMask(AuraType.ModDamagePercentDone, (uint)spellProto.GetSchoolMask());
DoneTotalMod *= maxModDamagePercentSchool;
}
@@ -2878,18 +2912,18 @@ namespace Game.Entities
MathFunctions.ApplyPercentModFloatVar(ref m_modAttackSpeedPct[(int)att], val, !apply);
if (att == WeaponAttackType.BaseAttack)
ApplyPercentModFloatValue(UnitFields.ModHaste, val, !apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModHaste), val, !apply);
else if (att == WeaponAttackType.RangedAttack)
ApplyPercentModFloatValue(UnitFields.ModRangedHaste, val, !apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModRangedHaste), val, !apply);
}
else
{
MathFunctions.ApplyPercentModFloatVar(ref m_modAttackSpeedPct[(int)att], -val, apply);
if (att == WeaponAttackType.BaseAttack)
ApplyPercentModFloatValue(UnitFields.ModHaste, -val, apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModHaste), -val, apply);
else if (att == WeaponAttackType.RangedAttack)
ApplyPercentModFloatValue(UnitFields.ModRangedHaste, -val, apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModRangedHaste), -val, apply);
}
UpdateAttackTimeField(att);
@@ -2937,30 +2971,30 @@ namespace Game.Entities
// can't attack untargetable
if ((bySpell == null || !bySpell.HasAttribute(SpellAttr6.CanTargetUntargetable))
&& target.HasFlag(UnitFields.Flags, UnitFlags.NotSelectable))
&& target.HasUnitFlag(UnitFlags.NotSelectable))
return false;
Player playerAttacker = ToPlayer();
if (playerAttacker != null)
{
if (playerAttacker.HasFlag(PlayerFields.Flags, PlayerFlags.Commentator2))
if (playerAttacker.HasPlayerFlag(PlayerFlags.Commentator2))
return false;
}
// check flags
if (target.HasFlag(UnitFields.Flags, (UnitFlags.NonAttackable | UnitFlags.TaxiFlight | UnitFlags.NotAttackable1 | UnitFlags.Unk16))
|| (!HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable) && target.HasFlag(UnitFields.Flags, UnitFlags.ImmuneToNpc))
|| (!target.HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable) && HasFlag(UnitFields.Flags, UnitFlags.ImmuneToNpc)))
if (target.HasUnitFlag(UnitFlags.NonAttackable | UnitFlags.TaxiFlight | UnitFlags.NotAttackable1 | UnitFlags.Unk16)
|| (!HasUnitFlag(UnitFlags.PvpAttackable) && target.HasUnitFlag(UnitFlags.ImmuneToNpc))
|| (!target.HasUnitFlag(UnitFlags.PvpAttackable) && HasUnitFlag(UnitFlags.ImmuneToNpc)))
return false;
if ((bySpell == null || !bySpell.HasAttribute(SpellAttr8.AttackIgnoreImmuneToPCFlag))
&& (HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable) && target.HasFlag(UnitFields.Flags, UnitFlags.ImmuneToPc))
&& (HasUnitFlag(UnitFlags.PvpAttackable) && target.HasUnitFlag(UnitFlags.ImmuneToPc))
// check if this is a world trigger cast - GOs are using world triggers to cast their spells, so we need to ignore their immunity flag here, this is a temp workaround, needs removal when go cast is implemented properly
&& GetEntry() != SharedConst.WorldTrigger)
return false;
// CvC case - can attack each other only when one of them is hostile
if (!HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable) && !target.HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable))
if (!HasUnitFlag(UnitFlags.PvpAttackable) && !target.HasUnitFlag(UnitFlags.PvpAttackable))
return GetReactionTo(target) <= ReputationRank.Hostile || target.GetReactionTo(this) <= ReputationRank.Hostile;
// PvP, PvC, CvP case
@@ -2968,8 +3002,8 @@ namespace Game.Entities
if (GetReactionTo(target) > ReputationRank.Neutral || target.GetReactionTo(this) > ReputationRank.Neutral)
return false;
Player playerAffectingAttacker = HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable) ? GetAffectingPlayer() : null;
Player playerAffectingTarget = target.HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable) ? target.GetAffectingPlayer() : null;
Player playerAffectingAttacker = HasUnitFlag(UnitFlags.PvpAttackable) ? GetAffectingPlayer() : null;
Player playerAffectingTarget = target.HasUnitFlag(UnitFlags.PvpAttackable) ? target.GetAffectingPlayer() : null;
// Not all neutral creatures can be attacked (even some unfriendly faction does not react aggresive to you, like Sporaggar)
if ((playerAffectingAttacker && !playerAffectingTarget) || (!playerAffectingAttacker && playerAffectingTarget))
@@ -3010,9 +3044,8 @@ namespace Game.Entities
// PvP case - can't attack when attacker or target are in sanctuary
// however, 13850 client doesn't allow to attack when one of the unit's has sanctuary flag and is pvp
if (target.HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable) && HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable)
&& (Convert.ToBoolean(target.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.Sanctuary)
|| Convert.ToBoolean(GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.Sanctuary)))
if (target.HasUnitFlag(UnitFlags.PvpAttackable) && HasUnitFlag(UnitFlags.PvpAttackable)
&& (target.HasPvpFlag(UnitPVPStateFlags.Sanctuary) || HasPvpFlag(UnitPVPStateFlags.Sanctuary)))
return false;
// additional checks - only PvP case
@@ -3024,7 +3057,7 @@ namespace Game.Entities
if (IsFFAPvP() && target.IsFFAPvP())
return true;
return HasByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, UnitBytes2Flags.Unk1) || target.HasByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, UnitBytes2Flags.Unk1);
return HasPvpFlag(UnitPVPStateFlags.Unk1) || target.HasPvpFlag(UnitPVPStateFlags.Unk1);
}
return true;
}
@@ -3062,19 +3095,19 @@ namespace Game.Entities
// can't assist untargetable
if ((bySpell == null || !bySpell.HasAttribute(SpellAttr6.CanTargetUntargetable))
&& target.HasFlag(UnitFields.Flags, UnitFlags.NotSelectable))
&& target.HasUnitFlag(UnitFlags.NotSelectable))
return false;
if (bySpell == null || !bySpell.HasAttribute(SpellAttr6.AssistIgnoreImmuneFlag))
{
if (HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable))
if (HasUnitFlag(UnitFlags.PvpAttackable))
{
if (target.HasFlag(UnitFields.Flags, UnitFlags.ImmuneToPc))
if (target.HasUnitFlag(UnitFlags.ImmuneToPc))
return false;
}
else
{
if (target.HasFlag(UnitFields.Flags, UnitFlags.ImmuneToNpc))
if (target.HasUnitFlag(UnitFlags.ImmuneToNpc))
return false;
}
}
@@ -3090,10 +3123,10 @@ namespace Game.Entities
return true;
// PvP case
else if (target.HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable))
else if (target.HasUnitFlag(UnitFlags.PvpAttackable))
{
Player targetPlayerOwner = target.GetAffectingPlayer();
if (HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable))
if (HasUnitFlag(UnitFlags.PvpAttackable))
{
Player selfPlayerOwner = GetAffectingPlayer();
if (selfPlayerOwner != null && targetPlayerOwner != null)
@@ -3103,20 +3136,18 @@ namespace Game.Entities
return false;
}
// can't assist player in ffa_pvp zone from outside
if (Convert.ToBoolean(target.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.FFAPvp)
&& !Convert.ToBoolean(GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.FFAPvp))
if (target.HasPvpFlag(UnitPVPStateFlags.FFAPvp) && !HasPvpFlag(UnitPVPStateFlags.FFAPvp))
return false;
// can't assist player out of sanctuary from sanctuary if has pvp enabled
if (Convert.ToBoolean(target.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.PvP))
if (Convert.ToBoolean(GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.Sanctuary)
&& !Convert.ToBoolean(target.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.Sanctuary))
if (target.HasPvpFlag(UnitPVPStateFlags.PvP))
if (HasPvpFlag(UnitPVPStateFlags.Sanctuary) && !target.HasPvpFlag(UnitPVPStateFlags.Sanctuary))
return false;
}
}
// PvC case - player can assist creature only if has specific type flags
else if (HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable)
else if (HasUnitFlag(UnitFlags.PvpAttackable)
&& (bySpell == null || !bySpell.HasAttribute(SpellAttr6.AssistIgnoreImmuneFlag))
&& !Convert.ToBoolean(target.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.PvP))
&& !target.HasPvpFlag(UnitPVPStateFlags.PvP))
{
Creature creatureTarget = target.ToCreature();
if (creatureTarget != null)
+4
View File
@@ -107,11 +107,15 @@ namespace Game.Entities
uint m_removedAurasCount;
//General
public UnitData m_unitData;
DiminishingReturn[] m_Diminishing = new DiminishingReturn[(int)DiminishingGroup.Max];
protected List<GameObject> m_gameObj = new List<GameObject>();
List<AreaTrigger> m_areaTrigger = new List<AreaTrigger>();
protected List<DynamicObject> m_dynObj = new List<DynamicObject>();
protected float[] CreateStats = new float[(int)Stats.Max];
float[] m_floatStatPosBuff = new float[(int)Stats.Max];
float[] m_floatStatNegBuff = new float[(int)Stats.Max];
public ObjectGuid[] m_SummonSlot = new ObjectGuid[7];
public ObjectGuid[] m_ObjectSlot = new ObjectGuid[4];
public EventSystem m_Events = new EventSystem();
+29 -20
View File
@@ -54,13 +54,13 @@ namespace Game.Entities
public virtual bool CanSwim()
{
// Mirror client behavior, if this method returns false then client will not use swimming animation and for players will apply gravity as if there was no water
if (HasFlag(UnitFields.Flags, UnitFlags.CannotSwim))
if (HasUnitFlag(UnitFlags.CannotSwim))
return false;
if (HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable)) // is player
if (HasUnitFlag(UnitFlags.PvpAttackable)) // is player
return true;
if (HasFlag(UnitFields.Flags2, 0x1000000))
if (HasUnitFlag2((UnitFlags2)0x1000000))
return false;
return HasFlag(UnitFields.Flags, UnitFlags.PetInCombat | UnitFlags.Rename | UnitFlags.Unk15);
return HasUnitFlag(UnitFlags.PetInCombat | UnitFlags.Rename | UnitFlags.Unk15);
}
public virtual bool IsInWater()
{
@@ -593,7 +593,7 @@ namespace Game.Entities
if (!obj || !IsInMap(obj) || !IsInPhase(obj))
return false;
float objBoundaryRadius = Math.Max(obj.GetBoundaryRadius(), SharedConst.MinMeleeReach);
float objBoundaryRadius = Math.Max(obj.GetBoundingRadius(), SharedConst.MinMeleeReach);
return IsInDist(obj, objBoundaryRadius);
}
@@ -737,6 +737,15 @@ namespace Game.Entities
if (mountCapability.ReqSpellKnownID != 0 && !HasSpell(mountCapability.ReqSpellKnownID))
continue;
Player thisPlayer = ToPlayer();
if (thisPlayer != null)
{
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(mountCapability.PlayerConditionID);
if (playerCondition != null)
if (!ConditionManager.IsPlayerMeetingCondition(thisPlayer, playerCondition))
continue;
}
return mountCapability;
}
@@ -944,7 +953,7 @@ namespace Game.Entities
if (enable == HasUnitMovementFlag(MovementFlag.Hover))
return false;
float hoverHeight = GetFloatValue(UnitFields.HoverHeight);
float hoverHeight = m_unitData.HoverHeight;
if (enable)
{
@@ -1133,7 +1142,7 @@ namespace Game.Entities
if (apply)
{
SetTarget(ObjectGuid.Empty);
SetFlag(UnitFields.Flags, UnitFlags.Stunned);
AddUnitFlag(UnitFlags.Stunned);
StopMoving();
@@ -1152,7 +1161,7 @@ namespace Game.Entities
// don't remove UNIT_FLAG_STUNNED for pet when owner is mounted (disabled pet's interface)
Unit owner = GetCharmerOrOwner();
if (owner == null || !owner.IsTypeId(TypeId.Player) || !owner.ToPlayer().IsMounted())
RemoveFlag(UnitFields.Flags, UnitFlags.Stunned);
RemoveUnitFlag(UnitFlags.Stunned);
if (!HasUnitState(UnitState.Root)) // prevent moving if it also has root effect
SetRooted(false);
@@ -1260,9 +1269,9 @@ namespace Game.Entities
public void Mount(uint mount, uint VehicleId = 0, uint creatureEntry = 0)
{
if (mount != 0)
SetUInt32Value(UnitFields.MountDisplayId, mount);
SetMountDisplayId(mount);
SetFlag(UnitFields.Flags, UnitFlags.Mount);
AddUnitFlag(UnitFlags.Mount);
Player player = ToPlayer();
if (player != null)
@@ -1286,7 +1295,7 @@ namespace Game.Entities
Battleground bg = ToPlayer().GetBattleground();
// don't unsummon pet in arena but SetFlag UNIT_FLAG_STUNNED to disable pet's interface
if (bg && bg.isArena())
pet.SetFlag(UnitFields.Flags, UnitFlags.Stunned);
pet.AddUnitFlag(UnitFlags.Stunned);
else
player.UnsummonPetTemporaryIfAny();
}
@@ -1295,7 +1304,7 @@ namespace Game.Entities
Unit charm = player.GetCharm();
if (charm)
if (charm.GetTypeId() == TypeId.Unit)
charm.SetFlag(UnitFields.Flags, UnitFlags.Stunned);
charm.AddUnitFlag(UnitFlags.Stunned);
player.SendMovementSetCollisionHeight(player.GetCollisionHeight(true));
}
@@ -1308,8 +1317,8 @@ namespace Game.Entities
if (!IsMounted())
return;
SetUInt32Value(UnitFields.MountDisplayId, 0);
RemoveFlag(UnitFields.Flags, UnitFlags.Mount);
SetMountDisplayId(0);
RemoveUnitFlag(UnitFlags.Mount);
Player thisPlayer = ToPlayer();
if (thisPlayer != null)
@@ -1337,8 +1346,8 @@ namespace Game.Entities
Pet pPet = player.GetPet();
if (pPet != null)
{
if (pPet.HasFlag(UnitFields.Flags, UnitFlags.Stunned) && !pPet.HasUnitState(UnitState.Stunned))
pPet.RemoveFlag(UnitFields.Flags, UnitFlags.Stunned);
if (pPet.HasUnitFlag(UnitFlags.Stunned) && !pPet.HasUnitState(UnitState.Stunned))
pPet.RemoveUnitFlag(UnitFlags.Stunned);
}
else
player.ResummonPetTemporaryUnSummonedIfAny();
@@ -1346,8 +1355,8 @@ namespace Game.Entities
// if we have charmed npc, remove stun also
Unit charm = player.GetCharm();
if (charm)
if (charm.GetTypeId() == TypeId.Unit && charm.HasFlag(UnitFields.Flags, UnitFlags.Stunned) && !charm.HasUnitState(UnitState.Stunned))
charm.RemoveFlag(UnitFields.Flags, UnitFlags.Stunned);
if (charm.GetTypeId() == TypeId.Unit && charm.HasUnitFlag(UnitFlags.Stunned) && !charm.HasUnitState(UnitState.Stunned))
charm.RemoveUnitFlag(UnitFlags.Stunned);
}
}
@@ -1381,7 +1390,7 @@ namespace Game.Entities
m_updateFlag.Vehicle = false;
m_unitTypeMask &= ~UnitTypeMask.Vehicle;
RemoveFlag64(UnitFields.NpcFlags, NPCFlags.SpellClick | NPCFlags.PlayerVehicle);
RemoveNpcFlag(NPCFlags.SpellClick | NPCFlags.PlayerVehicle);
}
void SendSetVehicleRecId(uint vehicleId)
@@ -1415,7 +1424,7 @@ namespace Game.Entities
{
float offset = 0.0f;
if (HasUnitMovementFlag(MovementFlag.Hover))
offset = GetFloatValue(UnitFields.HoverHeight);
offset = m_unitData.HoverHeight;
return GetPositionZ() - offset;
}
+52 -42
View File
@@ -168,7 +168,7 @@ namespace Game.Entities
if (IsTypeId(TypeId.Player))
{
minion.m_ControlledByPlayer = true;
minion.SetFlag(UnitFields.Flags, UnitFlags.PvpAttackable);
minion.AddUnitFlag(UnitFlags.PvpAttackable);
}
// Can only have one pet. If a new one is summoned, dismiss the old one.
@@ -196,17 +196,19 @@ namespace Game.Entities
}
if (minion.HasUnitTypeMask(UnitTypeMask.Guardian))
AddGuidValue(UnitFields.Summon, minion.GetGUID());
if (GetMinionGUID().IsEmpty())
SetMinionGUID(minion.GetGUID());
if (minion.m_Properties != null && minion.m_Properties.Title == SummonType.Minipet)
{
SetCritterGUID(minion.GetGUID());
if (GetTypeId() == TypeId.Player)
minion.SetGuidValue(UnitFields.BattlePetCompanionGuid, GetGuidValue(ActivePlayerFields.SummonedBattlePetId));
Player thisPlayer = ToPlayer();
if (thisPlayer != null)
minion.SetBattlePetCompanionGUID(thisPlayer.m_activePlayerData.SummonedBattlePetGUID);
}
// PvP, FFAPvP
minion.SetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag));
minion.SetPvpFlags(GetPvpFlags());
// FIXME: hack, speed must be set only at follow
if (IsTypeId(TypeId.Player) && minion.IsPet())
@@ -214,7 +216,7 @@ namespace Game.Entities
minion.SetSpeedRate(i, m_speed_rate[(int)i]);
// Send infinity cooldown - client does that automatically but after relog cooldown needs to be set again
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(minion.GetUInt32Value(UnitFields.CreatedBySpell));
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(minion.m_unitData.CreatedBySpell);
if (spellInfo != null && spellInfo.IsCooldownStartedOnEvent())
GetSpellHistory().StartCooldown(spellInfo, 0, null, true);
}
@@ -255,13 +257,14 @@ namespace Game.Entities
}
}
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(minion.GetUInt32Value(UnitFields.CreatedBySpell));
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(minion.m_unitData.CreatedBySpell);
// Remove infinity cooldown
if (spellInfo != null && spellInfo.IsCooldownStartedOnEvent())
GetSpellHistory().SendCooldownEvent(spellInfo);
if (RemoveGuidValue(UnitFields.Summon, minion.GetGUID()))
if (GetMinionGUID() == minion.GetGUID())
{
SetMinionGUID(ObjectGuid.Empty);
// Check if there is another minion
foreach (var unit in m_Controlled)
{
@@ -279,16 +282,14 @@ namespace Game.Entities
if (!unit.HasUnitTypeMask(UnitTypeMask.Guardian))
continue;
if (AddGuidValue(UnitFields.Summon, unit.GetGUID()))
SetMinionGUID(unit.GetGUID());
// show another pet bar if there is no charm bar
if (GetTypeId() == TypeId.Player && GetCharmGUID().IsEmpty())
{
// show another pet bar if there is no charm bar
if (IsTypeId(TypeId.Player) && GetCharmGUID().IsEmpty())
{
if (unit.IsPet())
ToPlayer().PetSpellInitialize();
else
ToPlayer().CharmSpellInitialize();
}
if (unit.IsPet())
ToPlayer().PetSpellInitialize();
else
ToPlayer().CharmSpellInitialize();
}
break;
}
@@ -364,8 +365,8 @@ namespace Game.Entities
if (aurApp != null && aurApp.GetRemoveMode() != 0)
return false;
_oldFactionId = getFaction();
SetFaction(charmer.getFaction());
_oldFactionId = GetFaction();
SetFaction(charmer.GetFaction());
// Set charmed
charmer.SetCharm(this, true);
@@ -418,14 +419,14 @@ namespace Game.Entities
switch (type)
{
case CharmType.Vehicle:
SetFlag(UnitFields.Flags, UnitFlags.PlayerControlled);
AddUnitFlag(UnitFlags.PlayerControlled);
playerCharmer.SetClientControl(this, true);
playerCharmer.VehicleSpellInitialize();
break;
case CharmType.Possess:
AddUnitState(UnitState.Possessed);
SetFlag(UnitFields.Flags, UnitFlags.PlayerControlled);
charmer.SetFlag(UnitFields.Flags, UnitFlags.RemoveClientControl);
AddUnitFlag(UnitFlags.PlayerControlled);
charmer.AddUnitFlag(UnitFlags.RemoveClientControl);
playerCharmer.SetClientControl(this, true);
playerCharmer.PossessSpellInitialize();
break;
@@ -436,14 +437,14 @@ namespace Game.Entities
if (cinfo != null && cinfo.CreatureType == CreatureType.Demon)
{
// to prevent client crash
SetByteValue(UnitFields.Bytes0, 1, (byte)Class.Mage);
SetClass(Class.Mage);
// just to enable stat window
if (GetCharmInfo() != null)
GetCharmInfo().SetPetNumber(Global.ObjectMgr.GeneratePetNumber(), true);
// if charmed two demons the same session, the 2nd gets the 1st one's name
SetUInt32Value(UnitFields.PetNameTimestamp, (uint)Time.UnixTime); // cast can't be helped
SetPetNameTimestamp((uint)Time.UnixTime); // cast can't be helped
}
}
playerCharmer.CharmSpellInitialize();
@@ -518,13 +519,13 @@ namespace Game.Entities
case CharmType.Vehicle:
playerCharmer.SetClientControl(this, false);
playerCharmer.SetClientControl(charmer, true);
RemoveFlag(UnitFields.Flags, UnitFlags.PlayerControlled);
RemoveUnitFlag(UnitFlags.PlayerControlled);
break;
case CharmType.Possess:
playerCharmer.SetClientControl(this, false);
playerCharmer.SetClientControl(charmer, true);
charmer.RemoveFlag(UnitFields.Flags, UnitFlags.RemoveClientControl);
RemoveFlag(UnitFields.Flags, UnitFlags.PlayerControlled);
charmer.RemoveUnitFlag(UnitFlags.RemoveClientControl);
RemoveUnitFlag(UnitFlags.PlayerControlled);
ClearUnitState(UnitState.Possessed);
break;
case CharmType.Charm:
@@ -533,7 +534,7 @@ namespace Game.Entities
CreatureTemplate cinfo = ToCreature().GetCreatureTemplate();
if (cinfo != null && cinfo.CreatureType == CreatureType.Demon)
{
SetByteValue(UnitFields.Bytes0, 1, (byte)cinfo.UnitClass);
SetClass((Class)cinfo.UnitClass);
if (GetCharmInfo() != null)
GetCharmInfo().SetPetNumber(0, true);
else
@@ -592,20 +593,24 @@ namespace Game.Entities
{
if (IsTypeId(TypeId.Player))
{
if (!AddGuidValue(UnitFields.Charm, charm.GetGUID()))
if (GetCharmGUID().IsEmpty())
SetCharmGUID(charm.GetGUID());
else
Log.outFatal(LogFilter.Unit, "Player {0} is trying to charm unit {1}, but it already has a charmed unit {2}", GetName(), charm.GetEntry(), GetCharmGUID());
charm.m_ControlledByPlayer = true;
// @todo maybe we can use this flag to check if controlled by player
charm.SetFlag(UnitFields.Flags, UnitFlags.PvpAttackable);
charm.AddUnitFlag(UnitFlags.PvpAttackable);
}
else
charm.m_ControlledByPlayer = false;
// PvP, FFAPvP
charm.SetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag));
charm.SetPvpFlags(GetPvpFlags());
if (!charm.AddGuidValue(UnitFields.CharmedBy, GetGUID()))
if (charm.GetCharmGUID().IsEmpty())
charm.SetCharmerGUID(GetGUID());
else
Log.outFatal(LogFilter.Unit, "Unit {0} is being charmed, but it already has a charmer {1}", charm.GetEntry(), charm.GetCharmerGUID());
_isWalkingBeforeCharm = charm.IsWalking();
@@ -619,30 +624,35 @@ namespace Game.Entities
{
if (IsTypeId(TypeId.Player))
{
if (!RemoveGuidValue(UnitFields.Charm, charm.GetGUID()))
if (GetCharmGUID() == charm.GetGUID())
SetCharmGUID(ObjectGuid.Empty);
else
Log.outFatal(LogFilter.Unit, "Player {0} is trying to uncharm unit {1}, but it has another charmed unit {2}", GetName(), charm.GetEntry(), GetCharmGUID());
}
if (!charm.RemoveGuidValue(UnitFields.CharmedBy, GetGUID()))
if (charm.GetCharmerGUID() == GetGUID())
charm.SetCharmerGUID(ObjectGuid.Empty);
else
Log.outFatal(LogFilter.Unit, "Unit {0} is being uncharmed, but it has another charmer {1}", charm.GetEntry(), charm.GetCharmerGUID());
Player player = charm.GetCharmerOrOwnerPlayerOrPlayerItself();
if (charm.IsTypeId(TypeId.Player))
{
charm.m_ControlledByPlayer = true;
charm.SetFlag(UnitFields.Flags, UnitFlags.PvpAttackable);
charm.AddUnitFlag(UnitFlags.PvpAttackable);
charm.ToPlayer().UpdatePvPState();
}
else if (player)
{
charm.m_ControlledByPlayer = true;
charm.SetFlag(UnitFields.Flags, UnitFlags.PvpAttackable);
charm.SetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, player.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag));
charm.AddUnitFlag(UnitFlags.PvpAttackable);
charm.SetPvpFlags(player.GetPvpFlags());
}
else
{
charm.m_ControlledByPlayer = false;
charm.RemoveFlag(UnitFields.Flags, UnitFlags.PvpAttackable);
charm.SetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, 0);
charm.RemoveUnitFlag(UnitFlags.PvpAttackable);
charm.SetPvpFlags(UnitPVPStateFlags.None);
}
if (charm.IsWalking() != _isWalkingBeforeCharm)
@@ -777,11 +787,11 @@ namespace Game.Entities
bool InitTamedPet(Pet pet, uint level, uint spell_id)
{
pet.SetCreatorGUID(GetGUID());
pet.SetFaction(getFaction());
pet.SetUInt32Value(UnitFields.CreatedBySpell, spell_id);
pet.SetFaction(GetFaction());
pet.SetCreatedBySpell(spell_id);
if (IsTypeId(TypeId.Player))
pet.SetUInt32Value(UnitFields.Flags, (uint)UnitFlags.PvpAttackable);
pet.AddUnitFlag(UnitFlags.PvpAttackable);
if (!pet.InitStatsForLevel(level))
{
+33 -27
View File
@@ -30,6 +30,8 @@ namespace Game.Entities
{
public virtual bool HasSpell(uint spellId) { return false; }
// function uses real base points (typically value - 1)
public int CalculateSpellDamage(Unit target, SpellInfo spellProto, uint effect_index, int? basePoints = null, int itemLevel = -1)
{
@@ -45,9 +47,10 @@ namespace Game.Entities
public int SpellBaseDamageBonusDone(SpellSchoolMask schoolMask)
{
if (IsTypeId(TypeId.Player))
Player thisPlayer = ToPlayer();
if (thisPlayer)
{
float overrideSP = GetFloatValue(ActivePlayerFields.OverrideSpellPowerByApPct);
float overrideSP = thisPlayer.m_activePlayerData.OverrideSpellPowerByAPPercent;
if (overrideSP > 0.0f)
return (int)(MathFunctions.CalculatePct(GetTotalAttackPowerValue(WeaponAttackType.BaseAttack), overrideSP) + 0.5f);
}
@@ -185,12 +188,13 @@ namespace Game.Entities
MathFunctions.AddPct(ref DoneTotalMod, modOwner.GetRatingBonusValue(CombatRating.VersatilityDamageDone) + modOwner.GetTotalAuraModifier(AuraType.ModVersatility));
float maxModDamagePercentSchool = 0.0f;
if (IsTypeId(TypeId.Player))
Player thisPlayer = ToPlayer();
if (thisPlayer)
{
for (int i = 0; i < (int)SpellSchools.Max; ++i)
{
if (Convert.ToBoolean((int)spellProto.GetSchoolMask() & (1 << i)))
maxModDamagePercentSchool = Math.Max(maxModDamagePercentSchool, GetFloatValue(ActivePlayerFields.ModDamageDonePct + i));
maxModDamagePercentSchool = Math.Max(maxModDamagePercentSchool, thisPlayer.m_activePlayerData.ModDamageDonePercent[i]);
}
}
else
@@ -336,9 +340,10 @@ namespace Game.Entities
public uint SpellBaseHealingBonusDone(SpellSchoolMask schoolMask)
{
if (IsTypeId(TypeId.Player))
Player thisPlayer = ToPlayer();
if (thisPlayer != null)
{
float overrideSP = GetFloatValue(ActivePlayerFields.OverrideSpellPowerByApPct);
float overrideSP = thisPlayer.m_activePlayerData.OverrideSpellPowerByAPPercent;
if (overrideSP > 0.0f)
return (uint)(MathFunctions.CalculatePct(GetTotalAttackPowerValue(WeaponAttackType.BaseAttack), overrideSP) + 0.5f);
}
@@ -502,8 +507,9 @@ namespace Game.Entities
if (spellProto.SpellFamilyName == SpellFamilyNames.Potion)
return 1.0f;
if (IsPlayer())
return GetFloatValue(ActivePlayerFields.ModHealingDonePct);
Player thisPlayer = ToPlayer();
if (thisPlayer != null)
return thisPlayer.m_activePlayerData.ModHealingDonePercent;
float DoneTotalMod = 1.0f;
@@ -640,7 +646,7 @@ namespace Game.Entities
crit_chance = 0.0f;
// For other schools
else if (IsTypeId(TypeId.Player))
crit_chance = GetFloatValue(ActivePlayerFields.CritPercentage);
crit_chance = ToPlayer().m_activePlayerData.SpellCritPercentage;
else
crit_chance = m_baseSpellCritChance;
@@ -1914,7 +1920,7 @@ namespace Game.Entities
if (!(spellInfo.HasAttribute(SpellAttr0.Ability | SpellAttr0.Tradespell) || spellInfo.HasAttribute(SpellAttr3.NoDoneBonus))
&& (IsTypeId(TypeId.Player) && spellInfo.SpellFamilyName != 0) || IsTypeId(TypeId.Unit))
castTime = (int)(castTime * GetFloatValue(UnitFields.ModCastSpeed));
castTime = (int)(castTime * m_unitData.ModCastingSpeed);
else if (spellInfo.HasAttribute(SpellAttr0.ReqAmmo) && !spellInfo.HasAttribute(SpellAttr2.AutorepeatFlag))
castTime = (int)(castTime * m_modAttackSpeedPct[(int)WeaponAttackType.RangedAttack]);
else if (Global.SpellMgr.IsPartOfSkillLine(SkillType.Cooking, spellInfo.Id) && HasAura(67556)) // cooking with Chef Hat.
@@ -1935,7 +1941,7 @@ namespace Game.Entities
if (!(spellInfo.HasAttribute(SpellAttr0.Ability) || spellInfo.HasAttribute(SpellAttr0.Tradespell) || spellInfo.HasAttribute(SpellAttr3.NoDoneBonus)) &&
(IsTypeId(TypeId.Player) && spellInfo.SpellFamilyName != 0) || IsTypeId(TypeId.Unit))
duration = (int)(duration * GetFloatValue(UnitFields.ModCastSpeed));
duration = (int)(duration * m_unitData.ModCastingSpeed);
else if (spellInfo.HasAttribute(SpellAttr0.ReqAmmo) && !spellInfo.HasAttribute(SpellAttr2.AutorepeatFlag))
duration = (int)(duration * m_modAttackSpeedPct[(int)WeaponAttackType.RangedAttack]);
}
@@ -2261,15 +2267,15 @@ namespace Game.Entities
{
if (val > 0)
{
ApplyPercentModFloatValue(UnitFields.ModCastSpeed, val, !apply);
ApplyPercentModFloatValue(UnitFields.ModCastHaste, val, !apply);
ApplyPercentModFloatValue(UnitFields.ModHasteRegen, val, !apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModCastingSpeed), val, !apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModSpellHaste), val, !apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModHasteRegen), val, !apply);
}
else
{
ApplyPercentModFloatValue(UnitFields.ModCastSpeed, -val, apply);
ApplyPercentModFloatValue(UnitFields.ModCastHaste, -val, apply);
ApplyPercentModFloatValue(UnitFields.ModHasteRegen, -val, apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModCastingSpeed), -val, apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModSpellHaste), -val, apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModHasteRegen), -val, apply);
}
}
@@ -3145,8 +3151,8 @@ namespace Game.Entities
continue;
// The charges / stack amounts don't count towards the total number of auras that can be dispelled.
// Ie: A dispel on a target with 5 stacks of Winters Chill and a Polymorph has 1 / (1 + 1) -> 50% chance to dispell
// Polymorph instead of 1 / (5 + 1) -> 16%.
// Ie: A dispel on a target with 5 stacks of Winters Chill and a Polymorph has 1 / (1 + 1) . 50% chance to dispell
// Polymorph instead of 1 / (5 + 1) . 16%.
bool dispelCharges = aura.GetSpellInfo().HasAttribute(SpellAttr7.DispelCharges);
byte charges = dispelCharges ? aura.GetCharges() : aura.GetStackAmount();
if (charges > 0)
@@ -3696,11 +3702,12 @@ namespace Game.Entities
public void ModifyAuraState(AuraStateType flag, bool apply)
{
uint mask = 1u << ((int)flag - 1);
if (apply)
{
if (!HasFlag(UnitFields.AuraState, (1u << ((int)flag - 1))))
if ((m_unitData.AuraState & mask) == 0)
{
SetFlag(UnitFields.AuraState, (1u << (int)flag - 1));
SetUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.AuraState), mask);
if (IsTypeId(TypeId.Player))
{
var sp_list = ToPlayer().GetSpellMap();
@@ -3735,9 +3742,9 @@ namespace Game.Entities
}
else
{
if (HasFlag(UnitFields.AuraState, (1u << (int)flag - 1)))
if ((m_unitData.AuraState & mask) != 0)
{
RemoveFlag(UnitFields.AuraState, (1u << (int)flag - 1));
RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.AuraState), mask);
foreach (var app in GetAppliedAuras())
{
@@ -3773,7 +3780,7 @@ namespace Game.Entities
}
}
return HasFlag(UnitFields.AuraState, (uint)(1 << (int)flag - 1));
return (m_unitData.AuraState & (1 << ((int)flag - 1))) != 0;
}
SpellSchools GetSpellSchoolByAuraGroup(UnitMods unitMod)
@@ -3981,9 +3988,9 @@ namespace Game.Entities
return aurApp?.GetBase();
}
uint BuildAuraStateUpdateForTarget(Unit target)
public uint BuildAuraStateUpdateForTarget(Unit target)
{
uint auraStates = GetUInt32Value(UnitFields.AuraState) & ~(uint)AuraStateType.PerCasterAuraStateMask;
uint auraStates = m_unitData.AuraState & ~(uint)AuraStateType.PerCasterAuraStateMask;
foreach (var state in m_auraStateAuras)
if (Convert.ToBoolean((1 << (int)state.Key - 1) & (uint)AuraStateType.PerCasterAuraStateMask))
if (state.Value.GetBase().GetCasterGUID() == target.GetGUID())
@@ -4465,7 +4472,6 @@ namespace Game.Entities
});
}
public void _RegisterAuraEffect(AuraEffect aurEff, bool apply)
{
if (apply)
+294 -360
View File
@@ -31,6 +31,7 @@ using Game.Spells;
using System;
using System.Collections.Generic;
using System.Linq;
using Game.Network;
namespace Game.Entities
{
@@ -85,6 +86,8 @@ namespace Game.Entities
m_serverSideVisibility.SetValue(ServerSideVisibilityType.Ghost, GhostVisibilityType.Alive);
movesplineTimer = new TimeTrackerSmall();
m_unitData = new UnitData();
}
public override void Dispose()
@@ -734,32 +737,42 @@ namespace Game.Entities
m_areaTrigger[0].Remove();
}
public bool IsVendor() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.Vendor); }
public bool IsTrainer() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.Trainer); }
public bool IsQuestGiver() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.QuestGiver); }
public bool IsGossip() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.Gossip); }
public bool IsTaxi() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.FlightMaster); }
public bool IsGuildMaster() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.Petitioner); }
public bool IsBattleMaster() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.BattleMaster); }
public bool IsBanker() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.Banker); }
public bool IsInnkeeper() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.Innkeeper); }
public bool IsSpiritHealer() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.SpiritHealer); }
public bool IsSpiritGuide() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.SpiritGuide); }
public bool IsTabardDesigner() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.TabardDesigner); }
public bool IsAuctioner() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.Auctioneer); }
public bool IsArmorer() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.Repair); }
public bool HasNpcFlag(NPCFlags flags) { return (m_unitData.NpcFlags[0] & (uint)flags) != 0; }
public void AddNpcFlag(NPCFlags flags) { SetUpdateFieldFlagValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.NpcFlags, 0), (uint)flags); }
public void RemoveNpcFlag(NPCFlags flags) { RemoveUpdateFieldFlagValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.NpcFlags, 0), (uint)flags); }
public void SetNpcFlags(NPCFlags flags) { SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.NpcFlags, 0), (uint)flags); }
public bool HasNpcFlag2(NPCFlags2 flags) { return (m_unitData.NpcFlags[1] & (uint)flags) != 0; }
public void AddNpcFlag2(NPCFlags2 flags) { SetUpdateFieldFlagValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.NpcFlags, 1), (uint)flags); }
public void RemoveNpcFlag2(NPCFlags2 flags) { RemoveUpdateFieldFlagValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.NpcFlags, 1), (uint)flags); }
public void SetNpcFlags2(NPCFlags2 flags) { SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.NpcFlags, 1), (uint)flags); }
public bool IsVendor() { return HasNpcFlag(NPCFlags.Vendor); }
public bool IsTrainer() { return HasNpcFlag(NPCFlags.Trainer); }
public bool IsQuestGiver() { return HasNpcFlag(NPCFlags.QuestGiver); }
public bool IsGossip() { return HasNpcFlag(NPCFlags.Gossip); }
public bool IsTaxi() { return HasNpcFlag(NPCFlags.FlightMaster); }
public bool IsGuildMaster() { return HasNpcFlag(NPCFlags.Petitioner); }
public bool IsBattleMaster() { return HasNpcFlag(NPCFlags.BattleMaster); }
public bool IsBanker() { return HasNpcFlag(NPCFlags.Banker); }
public bool IsInnkeeper() { return HasNpcFlag(NPCFlags.Innkeeper); }
public bool IsSpiritHealer() { return HasNpcFlag(NPCFlags.SpiritHealer); }
public bool IsSpiritGuide() { return HasNpcFlag(NPCFlags.SpiritGuide); }
public bool IsTabardDesigner() { return HasNpcFlag(NPCFlags.TabardDesigner); }
public bool IsAuctioner() { return HasNpcFlag(NPCFlags.Auctioneer); }
public bool IsArmorer() { return HasNpcFlag(NPCFlags.Repair); }
public bool IsServiceProvider()
{
return HasFlag64(UnitFields.NpcFlags,
NPCFlags.Vendor | NPCFlags.Trainer | NPCFlags.FlightMaster |
return HasNpcFlag(NPCFlags.Vendor | NPCFlags.Trainer | NPCFlags.FlightMaster |
NPCFlags.Petitioner | NPCFlags.BattleMaster | NPCFlags.Banker |
NPCFlags.Innkeeper | NPCFlags.SpiritHealer |
NPCFlags.SpiritGuide | NPCFlags.TabardDesigner | NPCFlags.Auctioneer);
}
public bool IsSpiritService() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.SpiritHealer | NPCFlags.SpiritGuide); }
public bool IsSpiritService() { return HasNpcFlag(NPCFlags.SpiritHealer | NPCFlags.SpiritGuide); }
public bool IsCritter() { return GetCreatureType() == CreatureType.Critter; }
public bool IsInFlight() { return HasUnitState(UnitState.InFlight); }
public void SetHoverHeight(float hoverHeight) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.HoverHeight), hoverHeight); }
public Guardian GetGuardianPet()
{
ObjectGuid pet_guid = GetPetGUID();
@@ -1088,7 +1101,7 @@ namespace Game.Entities
return pet;
Log.outError(LogFilter.Unit, "Unit.GetCharm: Charmed creature {0} not exist.", charm_guid);
SetGuidValue(UnitFields.Charm, ObjectGuid.Empty);
SetCharmGUID(ObjectGuid.Empty);
}
return null;
@@ -1144,7 +1157,8 @@ namespace Game.Entities
public uint GetModelForForm(ShapeShiftForm form)
{
if (IsTypeId(TypeId.Player))
Player thisPlayer = ToPlayer();
if (thisPlayer != null)
{
Aura artifactAura = GetAura(PlayerConst.ArtifactsAllWeaponsGeneralWeaponEquippedPassive);
if (artifactAura != null)
@@ -1159,8 +1173,8 @@ namespace Game.Entities
}
}
byte hairColor = GetByteValue(PlayerFields.Bytes, PlayerFieldOffsets.BytesOffsetHairColorId);
byte skinColor = GetByteValue(PlayerFields.Bytes, PlayerFieldOffsets.BytesOffsetSkinId);
byte hairColor = thisPlayer.m_playerData.HairColorID;
byte skinColor = thisPlayer.m_playerData.SkinID;
switch (form)
{
@@ -1568,21 +1582,6 @@ namespace Game.Entities
return modelid;
}
public virtual bool CanUseAttackType(WeaponAttackType attacktype)
{
switch (attacktype)
{
case WeaponAttackType.BaseAttack:
return !HasFlag(UnitFields.Flags, UnitFlags.Disarmed);
case WeaponAttackType.OffAttack:
return !HasFlag(UnitFields.Flags2, UnitFlags2.DisarmOffhand);
case WeaponAttackType.RangedAttack:
return !HasFlag(UnitFields.Flags2, UnitFlags2.DisarmRanged);
default:
return true;
}
}
public Totem ToTotem() { return IsTotem() ? (this as Totem) : null; }
public TempSummon ToTempSummon() { return IsSummon() ? (this as TempSummon) : null; }
public virtual void setDeathState(DeathState s)
@@ -1630,7 +1629,7 @@ namespace Game.Entities
// do not why since in IncreaseMaxHealth currenthealth is checked
SetHealth(0);
SetPower(GetPowerType(), 0);
SetUInt32Value(UnitFields.NpcEmotestate, 0);
SetEmoteState(Emote.OneshotNone);
// players in instance don't have ZoneScript, but they have InstanceScript
ZoneScript zoneScript = GetZoneScript() != null ? GetZoneScript() : GetInstanceScript();
@@ -1638,7 +1637,7 @@ namespace Game.Entities
zoneScript.OnUnitDeath(this);
}
else if (s == DeathState.JustRespawned)
RemoveFlag(UnitFields.Flags, UnitFlags.Skinnable); // clear skinnable for creature and player (at Battleground)
RemoveUnitFlag(UnitFlags.Skinnable); // clear skinnable for creature and player (at Battleground)
}
public bool IsVisible()
@@ -1655,12 +1654,19 @@ namespace Game.Entities
UpdateObjectVisibility();
}
public bool IsMounted() { return HasFlag(UnitFields.Flags, UnitFlags.Mount); }
public uint GetMountID() { return GetUInt32Value(UnitFields.MountDisplayId); }
public bool IsMagnet()
{
// Grounding Totem
if (m_unitData.CreatedBySpell == 8177) /// @todo: find a more generic solution
return true;
return false;
}
public void SetShapeshiftForm(ShapeShiftForm form)
{
SetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.ShapeshiftForm, (byte)form);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ShapeshiftForm), (byte)form);
}
public void SetModifierValue(UnitMods unitMod, UnitModifierType modifierType, float value)
@@ -1906,7 +1912,7 @@ namespace Game.Entities
public FactionTemplateRecord GetFactionTemplateEntry()
{
FactionTemplateRecord entry = CliDB.FactionTemplateStorage.LookupByKey(getFaction());
FactionTemplateRecord entry = CliDB.FactionTemplateStorage.LookupByKey(GetFaction());
if (entry == null)
{
ObjectGuid guid = ObjectGuid.Empty; // prevent repeating spam same faction problem
@@ -1916,11 +1922,11 @@ namespace Game.Entities
Player player = ToPlayer();
Creature creature = ToCreature();
if (player != null)
Log.outError(LogFilter.Unit, "Player {0} has invalid faction (faction template id) #{1}", player.GetName(), getFaction());
Log.outError(LogFilter.Unit, "Player {0} has invalid faction (faction template id) #{1}", player.GetName(), GetFaction());
else if (creature != null)
Log.outError(LogFilter.Unit, "Creature (template id: {0}) has invalid faction (faction template id) #{1}", creature.GetCreatureTemplate().Entry, getFaction());
Log.outError(LogFilter.Unit, "Creature (template id: {0}) has invalid faction (faction template id) #{1}", creature.GetCreatureTemplate().Entry, GetFaction());
else
Log.outError(LogFilter.Unit, "Unit (name={0}, type={1}) has invalid faction (faction template id) #{2}", GetName(), GetTypeId(), getFaction());
Log.outError(LogFilter.Unit, "Unit (name={0}, type={1}) has invalid faction (faction template id) #{2}", GetName(), GetTypeId(), GetFaction());
guid = GetGUID();
}
@@ -2028,7 +2034,7 @@ namespace Game.Entities
if (slot >= SharedConst.MaxEquipmentItems)
return 0;
return GetUInt32Value(UnitFields.VirtualItemSlotId + slot * 2);
return m_unitData.VirtualItems[slot].ItemID;
}
public ushort GetVirtualItemAppearanceMod(uint slot)
@@ -2036,85 +2042,121 @@ namespace Game.Entities
if (slot >= SharedConst.MaxEquipmentItems)
return 0;
return GetUInt16Value(UnitFields.VirtualItemSlotId + (int)slot * 2 + 1, 0);
return m_unitData.VirtualItems[(int)slot].ItemAppearanceModID;
}
public void SetVirtualItem(int slot, uint itemId, ushort appearanceModId = 0, ushort itemVisual = 0)
public void SetVirtualItem(uint slot, uint itemId, ushort appearanceModId = 0, ushort itemVisual = 0)
{
if (slot >= SharedConst.MaxEquipmentItems)
return;
SetUInt32Value(UnitFields.VirtualItemSlotId + slot * 2, itemId);
SetUInt16Value(UnitFields.VirtualItemSlotId + slot * 2 + 1, 0, appearanceModId);
SetUInt16Value(UnitFields.VirtualItemSlotId + slot * 2 + 1, 1, itemVisual);
var virtualItemField = m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.VirtualItems, (int)slot);
SetUpdateFieldValue(virtualItemField.ModifyValue((VisibleItem visibleItem) => visibleItem.ItemID), itemId);
SetUpdateFieldValue(virtualItemField.ModifyValue((VisibleItem visibleItem) => visibleItem.ItemAppearanceModID), appearanceModId);
SetUpdateFieldValue(virtualItemField.ModifyValue((VisibleItem visibleItem) => visibleItem.ItemVisual), itemVisual);
}
//Unit
public void SetLevel(uint lvl)
{
SetUInt32Value(UnitFields.Level, lvl);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Level), lvl);
if (IsTypeId(TypeId.Player))
Player player = ToPlayer();
if (player != null)
{
Player player = ToPlayer();
if (player.GetGroup())
player.SetGroupUpdateFlag(GroupUpdateFlags.Level);
Global.WorldMgr.UpdateCharacterInfoLevel(ToPlayer().GetGUID(), (byte)lvl);
}
}
public uint getLevel()
{
return GetUInt32Value(UnitFields.Level);
}
public uint getLevel() { return m_unitData.Level; }
public override uint GetLevelForTarget(WorldObject target) { return getLevel(); }
public override uint GetLevelForTarget(WorldObject target)
{
return getLevel();
}
public Race GetRace() { return (Race)(byte)m_unitData.Race; }
public void SetRace(Race race) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Race), (byte)race); }
public ulong getRaceMask() { return 1ul << ((int)GetRace() - 1); }
public Class GetClass() { return (Class)(byte)m_unitData.ClassId; }
public void SetClass(Class classId) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ClassId), (byte)classId); }
public uint getClassMask() { return (uint)(1 << ((int)GetClass() - 1)); }
public Gender GetGender() { return (Gender)(byte)m_unitData.Sex; }
public void SetGender(Gender sex) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Sex), (byte)sex); }
public Race GetRace()
{
return (Race)GetByteValue(UnitFields.Bytes0, 0);
}
public ulong getRaceMask()
{
return (1ul << ((int)GetRace() - 1));
}
public Class GetClass()
{
return (Class)GetByteValue(UnitFields.Bytes0, 1);
}
public uint getClassMask()
{
return (uint)(1 << ((int)GetClass() - 1));
}
public Gender GetGender()
{
return (Gender)GetByteValue(UnitFields.Bytes0, 3);
}
public void SetNativeDisplayId(uint displayId, float displayScale = 1f)
{
SetUInt32Value(UnitFields.NativeDisplayId, displayId);
SetFloatValue(UnitFields.NativeXDisplayScale, displayScale);
}
public uint GetDisplayId() { return m_unitData.DisplayID; }
public virtual void SetDisplayId(uint modelId, float displayScale = 1f)
{
SetUInt32Value(UnitFields.DisplayId, modelId);
SetFloatValue(UnitFields.DisplayScale, displayScale);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.DisplayID), modelId);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.DisplayScale), displayScale);
// Set Gender by modelId
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelInfo(modelId);
if (minfo != null)
SetByteValue(UnitFields.Bytes0, 3, (byte)minfo.gender);
SetGender((Gender)minfo.gender);
}
public uint GetNativeDisplayId()
public void RestoreDisplayId(bool ignorePositiveAurasPreventingMounting = false)
{
return GetUInt32Value(UnitFields.NativeDisplayId);
AuraEffect handledAura = null;
// try to receive model from transform auras
var transforms = GetAuraEffectsByType(AuraType.Transform);
if (!transforms.Empty())
{
// iterate over already applied transform auras - from newest to oldest
foreach (var eff in transforms)
{
AuraApplication aurApp = eff.GetBase().GetApplicationOfTarget(GetGUID());
if (aurApp != null)
{
if (handledAura == null)
{
if (!ignorePositiveAurasPreventingMounting)
handledAura = eff;
else
{
CreatureTemplate ci = Global.ObjectMgr.GetCreatureTemplate((uint)eff.GetMiscValue());
if (ci != null)
if (!IsDisallowedMountForm(eff.GetId(), ShapeShiftForm.None, ObjectManager.ChooseDisplayId(ci).CreatureDisplayID))
handledAura = eff;
}
}
// prefer negative auras
if (!aurApp.IsPositive())
{
handledAura = eff;
break;
}
}
}
}
uint modelId;
// transform aura was found
if (handledAura != null)
handledAura.HandleEffect(this, AuraEffectHandleModes.SendForClient, true);
// we've found shapeshift
else if ((modelId = GetModelForForm(GetShapeshiftForm())) != 0)
{
if (!ignorePositiveAurasPreventingMounting || !IsDisallowedMountForm(0, GetShapeshiftForm(), modelId))
SetDisplayId(modelId);
else
SetDisplayId(GetNativeDisplayId());
}
// no auras found - set modelid to default
else
SetDisplayId(GetNativeDisplayId());
}
public float GetNativeDisplayScale()
public uint GetNativeDisplayId() { return m_unitData.NativeDisplayID; }
public void SetNativeDisplayId(uint displayId, float displayScale = 1f)
{
return GetFloatValue(UnitFields.NativeXDisplayScale);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.NativeDisplayID), displayId);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.NativeXDisplayScale), displayScale);
}
public float GetNativeDisplayScale() { return m_unitData.NativeXDisplayScale; }
public bool IsMounted()
{
return HasUnitFlag(UnitFlags.Mount);
}
public uint GetMountDisplayId() { return m_unitData.MountDisplayID; }
public void SetMountDisplayId(uint mountDisplayId) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.MountDisplayID), mountDisplayId); }
public virtual Unit GetOwner()
{
ObjectGuid ownerid = GetOwnerGUID();
@@ -2125,18 +2167,46 @@ namespace Game.Entities
}
public virtual float GetFollowAngle() { return MathFunctions.PiOver2; }
public ObjectGuid GetOwnerGUID() { return GetGuidValue(UnitFields.SummonedBy); }
public ObjectGuid GetCreatorGUID() { return GetGuidValue(UnitFields.CreatedBy); }
public ObjectGuid GetMinionGUID() { return GetGuidValue(UnitFields.Summon); }
public ObjectGuid GetCharmerGUID() { return GetGuidValue(UnitFields.CharmedBy); }
public ObjectGuid GetCharmGUID() { return GetGuidValue(UnitFields.Charm); }
public ObjectGuid GetOwnerGUID() { return m_unitData.SummonedBy; }
public void SetOwnerGUID(ObjectGuid owner)
{
if (GetOwnerGUID() == owner)
return;
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.SummonedBy), owner);
if (owner.IsEmpty())
return;
// Update owner dependent fields
Player player = Global.ObjAccessor.GetPlayer(this, owner);
if (player == null || !player.HaveAtClient(this)) // if player cannot see this unit yet, he will receive needed data with create object
return;
UpdateData udata = new UpdateData(GetMapId());
UpdateObject packet;
BuildValuesUpdateBlockForPlayerWithFlag(udata, UpdateFieldFlag.Owner, player);
udata.BuildPacket(out packet);
player.SendPacket(packet);
}
public ObjectGuid GetCreatorGUID() { return m_unitData.CreatedBy; }
public void SetCreatorGUID(ObjectGuid creator) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.CreatedBy), creator); }
public ObjectGuid GetMinionGUID() { return m_unitData.Summon; }
public void SetMinionGUID(ObjectGuid guid) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Summon), guid); }
public ObjectGuid GetCharmerGUID() { return m_unitData.CharmedBy; }
public void SetCharmerGUID(ObjectGuid owner) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.CharmedBy), owner); }
public ObjectGuid GetCharmGUID() { return m_unitData.Charm; }
public void SetCharmGUID(ObjectGuid charm) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Charm), charm); }
public ObjectGuid GetPetGUID() { return m_SummonSlot[0]; }
public ObjectGuid GetCritterGUID() { return GetGuidValue(UnitFields.Critter); }
public void SetPetGUID(ObjectGuid guid) { m_SummonSlot[0] = guid; }
public ObjectGuid GetCritterGUID() { return m_unitData.Critter; }
public void SetCritterGUID(ObjectGuid guid) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Critter), guid); }
public ObjectGuid GetBattlePetCompanionGUID() { return m_unitData.BattlePetCompanionGUID; }
public void SetBattlePetCompanionGUID(ObjectGuid guid) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.BattlePetCompanionGUID), guid); }
public ObjectGuid GetCharmerOrOwnerGUID()
{
return !GetCharmerGUID().IsEmpty() ? GetCharmerGUID() : GetOwnerGUID();
}
ObjectGuid GetCharmerOrOwnerOrOwnGUID()
public ObjectGuid GetCharmerOrOwnerOrOwnGUID()
{
ObjectGuid guid = GetCharmerOrOwnerGUID();
if (!guid.IsEmpty())
@@ -2172,52 +2242,49 @@ namespace Game.Entities
return !GetCharmerGUID().IsEmpty() ? GetCharmer() : GetOwner();
}
public uint GetChannelSpellId() { return GetUInt32Value(UnitFields.ChannelData); }
public void SetChannelSpellId(uint channelSpellId) { SetUInt32Value(UnitFields.ChannelData, channelSpellId); }
public uint GetChannelSpellXSpellVisualId() { return GetUInt32Value(UnitFields.ChannelData + 1);}
public void SetChannelSpellXSpellVisualId(uint channelSpellXSpellVisualId) { SetUInt32Value(UnitFields.ChannelData + 1, channelSpellXSpellVisualId); }
public bool HasUnitFlag(UnitFlags flags) { return (m_unitData.Flags & (uint)flags) != 0; }
public void AddUnitFlag(UnitFlags flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Flags), (uint)flags); }
public void RemoveUnitFlag(UnitFlags flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Flags), (uint)flags); }
public void SetUnitFlags(UnitFlags flags) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Flags), (uint)flags); }
public bool HasUnitFlag2(UnitFlags2 flags) { return (m_unitData.Flags2 & (uint)flags) != 0; }
public void AddUnitFlag2(UnitFlags2 flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Flags2), (uint)flags); }
public void RemoveUnitFlag2(UnitFlags2 flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Flags2), (uint)flags); }
public void SetUnitFlags2(UnitFlags2 flags) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Flags2), (uint)flags); }
public bool HasUnitFlag3(UnitFlags3 flags) { return (m_unitData.Flags3 & (uint)flags) != 0; }
public void AddUnitFlag3(UnitFlags3 flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Flags3), (uint)flags); }
public void RemoveUnitFlag3(UnitFlags3 flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Flags3), (uint)flags); }
public void SetUnitFlags3(UnitFlags3 flags) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Flags3), (uint)flags); }
public List<ObjectGuid> GetChannelObjects() { return GetDynamicStructuredValues<ObjectGuid>(UnitDynamicFields.ChannelObjects); }
public void AddChannelObject(ObjectGuid guid) { AddDynamicStructuredValue(UnitDynamicFields.ChannelObjects, guid); }
public void SetCreatedBySpell(uint spellId) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.CreatedBySpell), spellId); }
public void SetOwnerGUID(ObjectGuid owner)
{
if (GetOwnerGUID() == owner)
return;
public Emote GetEmoteState() { return (Emote)(int)m_unitData.EmoteState; }
public void SetEmoteState(Emote emote) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.EmoteState), (int)emote); }
SetGuidValue(UnitFields.SummonedBy, owner);
if (owner.IsEmpty())
return;
// Update owner dependent fields
Player player = Global.ObjAccessor.GetPlayer(this, owner);
if (player == null || !player.HaveAtClient(this)) // if player cannot see this unit yet, he will receive needed data with create object
return;
SetFieldNotifyFlag(UpdateFieldFlags.Owner);
UpdateData udata = new UpdateData(GetMapId());
UpdateObject packet;
BuildValuesUpdateBlockForPlayer(udata, player);
udata.BuildPacket(out packet);
player.SendPacket(packet);
RemoveFieldNotifyFlag(UpdateFieldFlags.Owner);
}
public void SetCreatorGUID(ObjectGuid creator) { SetGuidValue(UnitFields.CreatedBy, creator); }
void SetMinionGUID(ObjectGuid guid) { SetGuidValue(UnitFields.Summon, guid); }
void SetCharmerGUID(ObjectGuid owner) { SetGuidValue(UnitFields.CharmedBy, owner); }
public void SetPetGUID(ObjectGuid guid) { m_SummonSlot[0] = guid; }
void SetCritterGUID(ObjectGuid guid) { SetGuidValue(UnitFields.Critter, guid); }
public SheathState GetSheath() { return (SheathState)(byte)m_unitData.SheatheState; }
public void SetSheath(SheathState sheathed) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.SheatheState), (byte)sheathed); }
public uint GetCombatTimer() { return m_CombatTimer; }
public bool IsPvP() { return HasByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, UnitBytes2Flags.PvP); }
public bool IsFFAPvP() { return HasByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, UnitBytes2Flags.FFAPvp); }
public UnitPVPStateFlags GetPvpFlags() { return (UnitPVPStateFlags)(byte)m_unitData.PvpFlags; }
public bool HasPvpFlag(UnitPVPStateFlags flags) { return (m_unitData.PvpFlags & (uint)flags) != 0; }
public void AddPvpFlag(UnitPVPStateFlags flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PvpFlags), (byte)flags); }
public void RemovePvpFlag(UnitPVPStateFlags flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PvpFlags), (byte)flags); }
public void SetPvpFlags(UnitPVPStateFlags flags) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PvpFlags), (byte)flags); }
public bool IsPvP() { return HasPvpFlag(UnitPVPStateFlags.PvP); }
public bool IsFFAPvP() { return HasPvpFlag(UnitPVPStateFlags.FFAPvp); }
public ShapeShiftForm GetShapeshiftForm()
public UnitPetFlags GetPetFlags()
{
return (ShapeShiftForm)GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.ShapeshiftForm);
return (UnitPetFlags)(byte)m_unitData.PetFlags;
}
public bool HasPetFlag(UnitPetFlags flags) { return (m_unitData.PetFlags & (byte)flags) != 0; }
public void AddPetFlag(UnitPetFlags flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PetFlags), (byte)flags); }
public void RemovePetFlag(UnitPetFlags flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PetFlags), (byte)flags); }
public void SetPetFlags(UnitPetFlags flags) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PetFlags), (byte)flags); }
public void SetPetNumberForClient(uint petNumber) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PetNumber), petNumber); }
public void SetPetNameTimestamp(uint timestamp) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PetNameTimestamp), timestamp); }
public ShapeShiftForm GetShapeshiftForm() { return (ShapeShiftForm)(byte)m_unitData.ShapeshiftForm; }
public CreatureType GetCreatureType()
{
if (IsTypeId(TypeId.Player))
@@ -2275,14 +2342,6 @@ namespace Game.Entities
{
m_state &= ~f;
}
public void SetStandFlags(object flags)
{
SetByteFlag(UnitFields.Bytes1, UnitBytes1Offsets.VisFlag, flags);
}
public void RemoveStandFlags(object flags)
{
RemoveByteFlag(UnitFields.Bytes1, UnitBytes1Offsets.VisFlag, flags);
}
public override bool IsAlwaysVisibleFor(WorldObject seer)
{
@@ -2342,9 +2401,9 @@ namespace Game.Entities
if (GetCharmerOrOwnerOrSelf() == target.GetCharmerOrOwnerOrSelf())
return ReputationRank.Friendly;
if (HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable))
if (HasUnitFlag(UnitFlags.PvpAttackable))
{
if (target.HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable))
if (target.HasUnitFlag(UnitFlags.PvpAttackable))
{
Player selfPlayerOwner = GetAffectingPlayer();
Player targetPlayerOwner = target.GetAffectingPlayer();
@@ -2373,7 +2432,7 @@ namespace Game.Entities
var targetFactionTemplateEntry = target.GetFactionTemplateEntry();
if (targetFactionTemplateEntry != null)
{
if (!selfPlayerOwner.HasFlag(UnitFields.Flags2, UnitFlags2.IgnoreReputation))
if (!selfPlayerOwner.HasUnitFlag2(UnitFlags2.IgnoreReputation))
{
var targetFactionEntry = CliDB.FactionStorage.LookupByKey(targetFactionTemplateEntry.Faction);
if (targetFactionEntry != null)
@@ -2382,7 +2441,7 @@ namespace Game.Entities
{
// check contested flags
if (Convert.ToBoolean(targetFactionTemplateEntry.Flags & (uint)FactionTemplateFlags.ContestedGuard)
&& selfPlayerOwner.HasFlag(PlayerFields.Flags, PlayerFlags.ContestedPVP))
&& selfPlayerOwner.HasPlayerFlag(PlayerFlags.ContestedPVP))
return ReputationRank.Hostile;
// if faction has reputation, hostile state depends only from AtWar state
@@ -2414,12 +2473,12 @@ namespace Game.Entities
{
// check contested flags
if (Convert.ToBoolean(factionTemplateEntry.Flags & (uint)FactionTemplateFlags.ContestedGuard)
&& targetPlayerOwner.HasFlag(PlayerFields.Flags, PlayerFlags.ContestedPVP))
&& targetPlayerOwner.HasPlayerFlag(PlayerFlags.ContestedPVP))
return ReputationRank.Hostile;
ReputationRank repRank = targetPlayerOwner.GetReputationMgr().GetForcedRankIfAny(factionTemplateEntry);
if (repRank != ReputationRank.None)
return repRank;
if (!target.HasFlag(UnitFields.Flags2, UnitFlags2.IgnoreReputation))
if (!target.HasUnitFlag2(UnitFlags2.IgnoreReputation))
{
var factionEntry = CliDB.FactionStorage.LookupByKey(factionTemplateEntry.Faction);
if (factionEntry != null)
@@ -2449,14 +2508,9 @@ namespace Game.Entities
return ReputationRank.Neutral;
}
public uint getFaction()
{
return GetUInt32Value(UnitFields.FactionTemplate);
}
public void SetFaction(uint faction)
{
SetUInt32Value(UnitFields.FactionTemplate, faction);
}
public uint GetFaction() { return m_unitData.FactionTemplate; }
public void SetFaction(uint faction) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.FactionTemplate), faction); }
public void RestoreFaction()
{
if (IsTypeId(TypeId.Player))
@@ -2468,7 +2522,7 @@ namespace Game.Entities
Unit owner = GetOwner();
if (owner)
{
SetFaction(owner.getFaction());
SetFaction(owner.GetFaction());
return;
}
}
@@ -2494,8 +2548,8 @@ namespace Game.Entities
(u1.IsTypeId(TypeId.Player) && u2.IsTypeId(TypeId.Unit) && u2.ToCreature().GetCreatureTemplate().TypeFlags.HasAnyFlag(CreatureTypeFlags.TreatAsRaidUnit)))
return true;
// else u1->GetTypeId() == u2->GetTypeId() == TYPEID_UNIT
return u1.getFaction() == u2.getFaction();
// else u1.GetTypeId() == u2.GetTypeId() == TYPEID_UNIT
return u1.GetFaction() == u2.GetFaction();
}
public bool IsInRaidWith(Unit unit)
@@ -2514,14 +2568,14 @@ namespace Game.Entities
(u1.IsTypeId(TypeId.Player) && u2.IsTypeId(TypeId.Unit) && u2.ToCreature().GetCreatureTemplate().TypeFlags.HasAnyFlag(CreatureTypeFlags.TreatAsRaidUnit)))
return true;
// else u1->GetTypeId() == u2->GetTypeId() == TYPEID_UNIT
return u1.getFaction() == u2.getFaction();
// else u1.GetTypeId() == u2.GetTypeId() == TYPEID_UNIT
return u1.GetFaction() == u2.GetFaction();
}
public SheathState GetSheath() { return (SheathState)GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.SheathState); }
public void SetSheath(SheathState sheathed) { SetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.SheathState, (byte)sheathed); }
public UnitStandStateType GetStandState() { return (UnitStandStateType)GetByteValue(UnitFields.Bytes1, UnitBytes1Offsets.StandState); }
public UnitStandStateType GetStandState() { return (UnitStandStateType)(byte)m_unitData.StandState; }
public void AddVisFlags(UnitVisFlags flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.VisFlags), (byte)flags); }
public void RemoveVisFlags(UnitVisFlags flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.VisFlags), (byte)flags); }
public void SetVisFlags(UnitVisFlags flags) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.VisFlags), (byte)flags); }
public bool IsSitState()
{
@@ -2540,7 +2594,7 @@ namespace Game.Entities
public void SetStandState(UnitStandStateType state, uint animKitId = 0)
{
SetByteValue(UnitFields.Bytes1, UnitBytes1Offsets.StandState, (byte)state);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.StandState), (byte)state);
if (IsStandState())
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.NotSeated);
@@ -2552,60 +2606,34 @@ namespace Game.Entities
}
}
public uint GetDisplayId() { return GetUInt32Value(UnitFields.DisplayId); }
public void RestoreDisplayId(bool ignorePositiveAurasPreventingMounting = false)
public void SetAnimTier(UnitBytes1Flags animTier, bool notifyClient)
{
AuraEffect handledAura = null;
// try to receive model from transform auras
var transforms = GetAuraEffectsByType(AuraType.Transform);
if (!transforms.Empty())
{
// iterate over already applied transform auras - from newest to oldest
foreach (var eff in transforms)
{
AuraApplication aurApp = eff.GetBase().GetApplicationOfTarget(GetGUID());
if (aurApp != null)
{
if (handledAura == null)
{
if (!ignorePositiveAurasPreventingMounting)
handledAura = eff;
else
{
CreatureTemplate ci = Global.ObjectMgr.GetCreatureTemplate((uint)eff.GetMiscValue());
if (ci != null)
if (!IsDisallowedMountForm(eff.GetId(), ShapeShiftForm.None, ObjectManager.ChooseDisplayId(ci).CreatureDisplayID))
handledAura = eff;
}
}
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.AnimTier), (byte)animTier);
// prefer negative auras
if (!aurApp.IsPositive())
{
handledAura = eff;
break;
}
}
}
}
uint modelId;
// transform aura was found
if (handledAura != null)
handledAura.HandleEffect(this, AuraEffectHandleModes.SendForClient, true);
// we've found shapeshift
else if ((modelId = GetModelForForm(GetShapeshiftForm())) != 0)
if (notifyClient)
{
if (!ignorePositiveAurasPreventingMounting || !IsDisallowedMountForm(0, GetShapeshiftForm(), modelId))
SetDisplayId(modelId);
else
SetDisplayId(GetNativeDisplayId());
SetAnimTier setAnimTier = new SetAnimTier();
setAnimTier.Unit = GetGUID();
setAnimTier.Tier = (int)animTier;
SendMessageToSet(setAnimTier, true);
}
// no auras found - set modelid to default
else
SetDisplayId(GetNativeDisplayId());
}
public uint GetChannelSpellId() { return ((UnitChannel)m_unitData.ChannelData).SpellID; }
public void SetChannelSpellId(uint channelSpellId)
{
SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ChannelData)._value.SpellID, channelSpellId);
}
public uint GetChannelSpellXSpellVisualId() { return ((UnitChannel)m_unitData.ChannelData).SpellXSpellVisualID; }
public void SetChannelSpellXSpellVisualId(uint channelSpellXSpellVisualId)
{
UnitChannel unitChannel = m_unitData.ModifyValue(m_unitData.ChannelData);
SetUpdateFieldValue(ref unitChannel.SpellXSpellVisualID, channelSpellXSpellVisualId);
}
public void AddChannelObject(ObjectGuid guid) { AddDynamicUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ChannelObjects), guid); }
public void SetChannelObject(int slot, ObjectGuid guid) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ChannelObjects, slot), guid); }
public void ClearChannelObjects() { ClearDynamicUpdateFieldValues(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ChannelObjects)); }
public bool IsDamageReducedByArmor(SpellSchoolMask schoolMask, SpellInfo spellInfo = null, sbyte effIndex = -1)
{
// only physical spells damage gets reduced by armor
@@ -2632,162 +2660,68 @@ namespace Game.Entities
return true;
}
public override void BuildValuesUpdate(UpdateType updatetype, ByteBuffer data, Player target)
public override UpdateFieldFlag GetUpdateFieldFlagsFor(Player target)
{
if (target == null)
return;
UpdateFieldFlag flags = UpdateFieldFlag.None;
if (target == this || GetOwnerGUID() == target.GetGUID())
flags |= UpdateFieldFlag.Owner;
ByteBuffer fieldBuffer = new ByteBuffer();
uint valCount = valuesCount;
uint[] flags = UpdateFieldFlags.UnitUpdateFieldFlags;
uint visibleFlag = UpdateFieldFlags.Public;
if (target == this)
visibleFlag |= UpdateFieldFlags.Private;
else if (IsTypeId(TypeId.Player))
valCount = (int)PlayerFields.End;
UpdateMask updateMask = new UpdateMask(valCount);
Player plr = GetCharmerOrOwnerPlayerOrPlayerItself();
if (GetOwnerGUID() == target.GetGUID())
visibleFlag |= UpdateFieldFlags.Owner;
if (HasFlag(ObjectFields.DynamicFlags, UnitDynFlags.SpecialInfo))
if (HasDynamicFlag(UnitDynFlags.SpecialInfo))
if (HasAuraTypeWithCaster(AuraType.Empathy, target.GetGUID()))
visibleFlag |= UpdateFieldFlags.SpecialInfo;
flags |= UpdateFieldFlag.Empath;
if (plr != null && plr.IsInSameRaidWith(target))
visibleFlag |= UpdateFieldFlags.PartyMember;
return flags;
}
Creature creature = ToCreature();
for (var index = 0; index < valCount; ++index)
{
if (Convert.ToBoolean(_fieldNotifyFlags & flags[index]) ||
Convert.ToBoolean((flags[index] & visibleFlag) & UpdateFieldFlags.SpecialInfo) ||
((updatetype == UpdateType.Values ? _changesMask.Get(index) : updateValues[index].UnsignedValue != 0) && flags[index].HasAnyFlag(visibleFlag)) ||
(index == (int)UnitFields.AuraState && HasFlag(UnitFields.AuraState, AuraStateType.PerCasterAuraStateMask)))
{
updateMask.SetBit(index);
public override void BuildValuesCreate(WorldPacket data, Player target)
{
UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
WorldPacket buffer = new WorldPacket();
if (index == (int)UnitFields.NpcFlags)
{
uint appendValue = GetUInt32Value(UnitFields.NpcFlags);
buffer.WriteUInt8((byte)flags);
m_objectData.WriteCreate(buffer, flags, this, target);
m_unitData.WriteCreate(buffer, flags, this, target);
if (creature != null)
if (!target.CanSeeSpellClickOn(creature))
appendValue &= ~(uint)NPCFlags.SpellClick;
data.WriteUInt32(buffer.GetSize());
data.WriteBytes(buffer);
}
fieldBuffer.WriteUInt32(appendValue);
}
else if (index == (int)UnitFields.AuraState)
{
// Check per caster aura states to not enable using a spell in client if specified aura is not by target
fieldBuffer.WriteUInt32(BuildAuraStateUpdateForTarget(target));
}
// FIXME: Some values at server stored in float format but must be sent to client in public uint format
else if ((index >= (int)UnitFields.NegStat && index < (int)UnitFields.NegStat + (int)Stats.Max) ||
(index >= (int)UnitFields.PosStat && index < (int)UnitFields.PosStat + (int)Stats.Max))
{
fieldBuffer.WriteUInt32((uint)GetFloatValue(index));
}
// Gamemasters should be always able to select units - remove not selectable flag
else if (index == (int)UnitFields.Flags)
{
UnitFlags appendValue = (UnitFlags)updateValues[index].UnsignedValue;
if (target.IsGameMaster())
appendValue &= ~UnitFlags.NotSelectable;
public override void BuildValuesUpdate(WorldPacket data, Player target)
{
UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
WorldPacket buffer = new WorldPacket();
fieldBuffer.WriteUInt32((uint)appendValue);
}
// use modelid_a if not gm, _h if gm for CREATURE_FLAG_EXTRA_TRIGGER creatures
else if (index == (int)UnitFields.DisplayId)
{
uint displayId = updateValues[index].UnsignedValue;
if (creature != null)
{
CreatureTemplate cinfo = creature.GetCreatureTemplate();
buffer.WriteUInt32(m_values.GetChangedObjectTypeMask());
if (m_values.HasChanged(TypeId.Object))
m_objectData.WriteUpdate(buffer, flags, this, target);
// this also applies for transform auras
SpellInfo transform = Global.SpellMgr.GetSpellInfo(getTransForm());
if (transform != null)
{
foreach (SpellEffectInfo effect in transform.GetEffectsForDifficulty(GetMap().GetDifficultyID()))
{
if (effect != null && effect.IsAura(AuraType.Transform))
{
CreatureTemplate transformInfo = Global.ObjectMgr.GetCreatureTemplate((uint)effect.MiscValue);
if (transformInfo != null)
{
cinfo = transformInfo;
break;
}
}
}
}
if (m_values.HasChanged(TypeId.Unit))
m_unitData.WriteUpdate(buffer, flags, this, target);
if (cinfo.FlagsExtra.HasAnyFlag(CreatureFlagsExtra.Trigger))
if (target.IsGameMaster())
displayId = cinfo.GetFirstVisibleModel().CreatureDisplayID;
}
data.WriteUInt32(buffer.GetSize());
data.WriteBytes(buffer);
}
fieldBuffer.WriteUInt32(displayId);
}
// hide lootable animation for unallowed players
else if (index == (int)ObjectFields.DynamicFlags)
{
UnitDynFlags dynamicFlags = (UnitDynFlags)updateValues[index].UnsignedValue & ~UnitDynFlags.Tapped;
void BuildValuesUpdateWithFlag(WorldPacket data, UpdateFieldFlag flags, Player target)
{
UpdateMask valuesMask = new UpdateMask(14);
valuesMask.Set((int)TypeId.Unit);
if (creature != null)
{
if (creature.hasLootRecipient() && !creature.isTappedBy(target))
dynamicFlags |= UnitDynFlags.Tapped;
WorldPacket buffer = new WorldPacket();
if (!target.isAllowedToLoot(creature))
dynamicFlags &= ~UnitDynFlags.Lootable;
}
UpdateMask mask = new UpdateMask(191);
m_unitData.AppendAllowedFieldsMaskForFlag(mask, flags);
m_unitData.WriteUpdate(buffer, mask, flags, this, target);
// unit UNIT_DYNFLAG_TRACK_UNIT should only be sent to caster of SPELL_AURA_MOD_STALKED auras
if (dynamicFlags.HasAnyFlag(UnitDynFlags.TrackUnit))
if (!HasAuraTypeWithCaster(AuraType.ModStalked, target.GetGUID()))
dynamicFlags &= ~UnitDynFlags.TrackUnit;
data.WriteUInt32(buffer.GetSize());
data.WriteUInt32(valuesMask.GetBlock(0));
data.WriteBytes(buffer);
}
fieldBuffer.WriteUInt32((uint)dynamicFlags);
}
// FG: pretend that OTHER players in own group are friendly ("blue")
else if (index == (int)UnitFields.Bytes2 || index == (int)UnitFields.FactionTemplate)
{
if (IsControlledByPlayer() && target != this && WorldConfig.GetBoolValue(WorldCfg.AllowTwoSideInteractionGroup) && IsInRaidWith(target))
{
FactionTemplateRecord ft1 = GetFactionTemplateEntry();
FactionTemplateRecord ft2 = target.GetFactionTemplateEntry();
if (ft1 != null && ft2 != null && !ft1.IsFriendlyTo(ft2))
{
if (index == (int)UnitFields.Bytes2)
// Allow targetting opposite faction in party when enabled in config
fieldBuffer.WriteUInt32(updateValues[index].UnsignedValue & ((int)UnitBytes2Flags.Sanctuary << 8)); // this flag is at public byte offset 1 !!
else
// pretend that all other HOSTILE players have own faction, to allow follow, heal, rezz (trade wont work)
fieldBuffer.WriteUInt32(target.getFaction());
}
else
fieldBuffer.WriteUInt32(updateValues[index].UnsignedValue);
}
else
fieldBuffer.WriteUInt32(updateValues[index].UnsignedValue);
}
else
{
// send in current format (float as float, public uint as uint32)
fieldBuffer.WriteUInt32(updateValues[index].UnsignedValue);
}
}
}
updateMask.AppendToPacket(data);
data.WriteBytes(fieldBuffer);
public override void ClearUpdateMask(bool remove)
{
m_values.ClearChangesMask(m_unitData);
base.ClearUpdateMask(remove);
}
public override void DestroyForPlayer(Player target)