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:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user