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

Code Port from TrinityCore https://github.com/TrinityCore/TrinityCore
Casc from WoW-Tools https://github.com/WoW-Tools/CASCExplorer
This commit is contained in:
hondacrx
2019-08-14 11:20:42 -04:00
parent e4d500f4b5
commit 125e3b3ac7
232 changed files with 12268 additions and 14670 deletions
+78 -21
View File
@@ -26,6 +26,7 @@ using System;
using System.Collections.Generic;
using Game;
using Framework.Dynamic;
using Game.Network;
namespace Game.Entities
{
@@ -42,7 +43,7 @@ namespace Game.Entities
m_updateFlag.Stationary = true;
m_updateFlag.AreaTrigger = true;
valuesCount = (int)AreaTriggerFields.End;
m_areaTriggerData = new AreaTriggerFieldData();
_spline = new Spline();
}
@@ -114,19 +115,35 @@ namespace Game.Entities
SetObjectScale(1.0f);
SetGuidValue(AreaTriggerFields.Caster, caster.GetGUID());
SetGuidValue(AreaTriggerFields.CreatingEffectGuid, castId);
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.Caster), caster.GetGUID());
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.CreatingEffectGUID), castId);
SetUInt32Value(AreaTriggerFields.SpellId, spell.Id);
SetUInt32Value(AreaTriggerFields.SpellForVisuals, spell.Id);
SetUInt32Value(AreaTriggerFields.SpellXSpellVisualId, spellXSpellVisualId);
SetUInt32Value(AreaTriggerFields.TimeToTargetScale, GetMiscTemplate().TimeToTargetScale != 0 ? GetMiscTemplate().TimeToTargetScale : GetUInt32Value(AreaTriggerFields.Duration));
SetFloatValue(AreaTriggerFields.BoundsRadius2d, GetTemplate().MaxSearchRadius);
SetUInt32Value(AreaTriggerFields.DecalPropertiesId, GetMiscTemplate().DecalPropertiesId);
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.SpellID), spell.Id);
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.SpellForVisuals), spell.Id);
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.SpellXSpellVisualID), spellXSpellVisualId);
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.TimeToTargetScale), GetMiscTemplate().TimeToTargetScale != 0 ? GetMiscTemplate().TimeToTargetScale : m_areaTriggerData.Duration);
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.BoundsRadius2D), GetTemplate().MaxSearchRadius);
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.DecalPropertiesID), GetMiscTemplate().DecalPropertiesId);
ScaleCurve extraScaleCurve = m_areaTriggerData.ModifyValue(m_areaTriggerData.ExtraScaleCurve);
if (GetMiscTemplate().ExtraScale.Structured.StartTimeOffset != 0)
SetUpdateFieldValue(ref extraScaleCurve.StartTimeOffset, GetMiscTemplate().ExtraScale.Structured.StartTimeOffset);
if (GetMiscTemplate().ExtraScale.Structured.X != 0 || GetMiscTemplate().ExtraScale.Structured.Y != 0)
{
Vector2 point = new Vector2(GetMiscTemplate().ExtraScale.Structured.X, GetMiscTemplate().ExtraScale.Structured.Y);
SetUpdateFieldValue(ref extraScaleCurve.Points[0], point);
}
if (GetMiscTemplate().ExtraScale.Structured.Z != 0 || GetMiscTemplate().ExtraScale.Structured.W != 0)
{
Vector2 point = new Vector2(GetMiscTemplate().ExtraScale.Structured.Z, GetMiscTemplate().ExtraScale.Structured.W);
SetUpdateFieldValue(ref extraScaleCurve.Points[1], point);
}
if (GetMiscTemplate().ExtraScale.Raw.Data[5] != 0)
SetUpdateFieldValue(ref extraScaleCurve.ParameterCurve, GetMiscTemplate().ExtraScale.Raw.Data[5]);
if (GetMiscTemplate().ExtraScale.Structured.OverrideActive != 0)
SetUpdateFieldValue(ref extraScaleCurve.OverrideActive, GetMiscTemplate().ExtraScale.Structured.OverrideActive != 0 ? true : false);
for (byte scaleCurveIndex = 0; scaleCurveIndex < SharedConst.MaxAreatriggerScale; ++scaleCurveIndex)
if (GetMiscTemplate().ExtraScale.Raw.Data[scaleCurveIndex] != 0)
SetUInt32Value(AreaTriggerFields.ExtraScaleCurve + scaleCurveIndex, (uint)GetMiscTemplate().ExtraScale.Raw.Data[scaleCurveIndex]);
PhasingHandler.InheritPhaseShift(this, caster);
@@ -137,7 +154,7 @@ namespace Game.Entities
UpdateShape();
uint timeToTarget = GetMiscTemplate().TimeToTarget != 0 ? GetMiscTemplate().TimeToTarget : GetUInt32Value(AreaTriggerFields.Duration);
uint timeToTarget = GetMiscTemplate().TimeToTarget != 0 ? GetMiscTemplate().TimeToTarget : m_areaTriggerData.Duration;
if (GetTemplate().HasFlag(AreaTriggerFlags.HasCircularMovement))
{
@@ -234,7 +251,7 @@ namespace Game.Entities
_totalDuration = newDuration;
// negative duration (permanent areatrigger) sent as 0
SetUInt32Value(AreaTriggerFields.Duration, (uint)Math.Max(newDuration, 0));
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.Duration), (uint)Math.Max(newDuration, 0));
}
void _UpdateDuration(int newDuration)
@@ -242,7 +259,8 @@ namespace Game.Entities
_duration = newDuration;
// should be sent in object create packets only
updateValues[(int)AreaTriggerFields.Duration].SignedValue = _duration;
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.Duration), (uint)_duration);
m_areaTriggerData.ClearChanged(m_areaTriggerData.Duration);
}
float GetProgress()
@@ -619,7 +637,8 @@ namespace Game.Entities
_spline.initLengths();
// should be sent in object create packets only
updateValues[(int)AreaTriggerFields.TimeToTarget].UnsignedValue = timeToTarget;
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.TimeToTarget), timeToTarget);
m_areaTriggerData.ClearChanged(m_areaTriggerData.TimeToTarget);
if (IsInWorld)
{
@@ -648,7 +667,8 @@ namespace Game.Entities
Cypher.Assert(cmi.Center.HasValue || cmi.PathTarget.HasValue);
// should be sent in object create packets only
updateValues[(int)AreaTriggerFields.TimeToTarget].UnsignedValue = timeToTarget;
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.TimeToTarget), timeToTarget);
m_areaTriggerData.ClearChanged(m_areaTriggerData.TimeToTarget);
_circularMovementInfo.Set(cmi);
@@ -822,6 +842,41 @@ namespace Game.Entities
_ai = null;
}
public override void BuildValuesCreate(WorldPacket data, Player target)
{
UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
WorldPacket buffer = new WorldPacket();
buffer.WriteUInt8((byte)flags);
m_objectData.WriteCreate(buffer, flags, this, target);
m_areaTriggerData.WriteCreate(buffer, flags, this, target);
data.WriteUInt32(buffer.GetSize());
data.WriteBytes(buffer);
}
public override void BuildValuesUpdate(WorldPacket data, Player target)
{
UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
WorldPacket buffer = new WorldPacket();
buffer.WriteUInt32(m_values.GetChangedObjectTypeMask());
if (m_values.HasChanged(TypeId.Object))
m_objectData.WriteUpdate(buffer, flags, this, target);
if (m_values.HasChanged(TypeId.AreaTrigger))
m_areaTriggerData.WriteUpdate(buffer, flags, this, target);
data.WriteUInt32(buffer.GetSize());
data.WriteBytes(buffer);
}
public override void ClearUpdateMask(bool remove)
{
m_values.ClearChangesMask(m_areaTriggerData);
base.ClearUpdateMask(remove);
}
AreaTriggerAI GetAI() { return _ai; }
[System.Diagnostics.Conditional("DEBUG")]
@@ -838,11 +893,11 @@ namespace Game.Entities
}
public bool IsRemoved() { return _isRemoved; }
public uint GetSpellId() { return GetUInt32Value(AreaTriggerFields.SpellId); }
public uint GetSpellId() { return m_areaTriggerData.SpellID; }
public AuraEffect GetAuraEffect() { return _aurEff; }
public uint GetTimeSinceCreated() { return _timeSinceCreated; }
public uint GetTimeToTarget() { return GetUInt32Value(AreaTriggerFields.TimeToTarget); }
public uint GetTimeToTargetScale() { return GetUInt32Value(AreaTriggerFields.TimeToTargetScale); }
public uint GetTimeToTarget() { return m_areaTriggerData.TimeToTarget; }
public uint GetTimeToTargetScale() { return m_areaTriggerData.TimeToTargetScale; }
public int GetDuration() { return _duration; }
public int GetTotalDuration() { return _totalDuration; }
@@ -852,7 +907,7 @@ namespace Game.Entities
public AreaTriggerMiscTemplate GetMiscTemplate() { return _areaTriggerMiscTemplate; }
public ObjectGuid GetCasterGuid() { return GetGuidValue(AreaTriggerFields.Caster); }
public ObjectGuid GetCasterGuid() { return m_areaTriggerData.Caster; }
public Vector3 GetRollPitchYaw() { return _rollPitchYaw; }
public Vector3 GetTargetRollPitchYaw() { return _targetRollPitchYaw; }
@@ -863,6 +918,8 @@ namespace Game.Entities
public Optional<AreaTriggerCircularMovementInfo> GetCircularMovementInfo() { return _circularMovementInfo; }
AreaTriggerFieldData m_areaTriggerData;
ObjectGuid _targetGuid;
AuraEffect _aurEff;
@@ -104,10 +104,19 @@ namespace Game.Entities
public uint StartTimeOffset;
[FieldOffset(4)]
public float[] Points;
public float X;
[FieldOffset(8)]
public float Y;
[FieldOffset(12)]
public float Z;
[FieldOffset(16)]
public float W;
[FieldOffset(20)]
public curveparameters CurveParameters;
public uint CurveParameters;
[FieldOffset(24)]
public uint OverrideActive;
+65 -40
View File
@@ -20,6 +20,7 @@ using Game.DataStorage;
using Game.Maps;
using Game.Spells;
using System.Collections.Generic;
using Game.Network;
namespace Game.Entities
{
@@ -35,8 +36,7 @@ namespace Game.Entities
m_updateFlag.Stationary = true;
m_updateFlag.Conversation = true;
valuesCount = (int)ConversationFields.End;
_dynamicValuesCount = (int)ConversationDynamicFields.End;
m_conversationData = new ConversationData();
}
public override void AddToWorld()
@@ -117,7 +117,7 @@ namespace Game.Entities
SetEntry(conversationEntry);
SetObjectScale(1.0f);
SetUInt32Value(ConversationFields.LastLineEndTime, conversationTemplate.LastLineEndTime);
SetUpdateFieldValue(m_values.ModifyValue(m_conversationData).ModifyValue(m_conversationData.LastLineEndTime), conversationTemplate.LastLineEndTime);
_duration = conversationTemplate.LastLineEndTime;
_textureKitId = conversationTemplate.TextureKitId;
@@ -126,11 +126,12 @@ namespace Game.Entities
ConversationActorTemplate actor = conversationTemplate.Actors[actorIndex];
if (actor != null)
{
ConversationDynamicFieldActor actorField = new ConversationDynamicFieldActor();
actorField.ActorTemplate.CreatureId = actor.CreatureId;
actorField.ActorTemplate.CreatureModelId = actor.CreatureModelId;
actorField.Type = ConversationDynamicFieldActor.ActorType.CreatureActor;
SetDynamicStructuredValue(ConversationDynamicFields.Actors, actorIndex, actorField);
ConversationActor actorField = new ConversationActor();
actorField.CreatureID = actor.CreatureId;
actorField.CreatureDisplayInfoID = actor.CreatureModelId;
actorField.Type = ConversationActorType.CreatureActor;
AddDynamicUpdateFieldValue(m_values.ModifyValue(m_conversationData).ModifyValue(m_conversationData.Actors), actorField);
}
}
@@ -150,17 +151,30 @@ namespace Game.Entities
Global.ScriptMgr.OnConversationCreate(this, creator);
List<ushort> actorIndices = new List<ushort>();
List<ConversationLine> lines = new List<ConversationLine>();
foreach (ConversationLineTemplate line in conversationTemplate.Lines)
{
actorIndices.Add(line.ActorIdx);
AddDynamicStructuredValue(ConversationDynamicFields.Lines, line);
ConversationLine lineField = new ConversationLine();
lineField.ConversationLineID = line.Id;
lineField.StartTime = line.StartTime;
lineField.UiCameraID = line.UiCameraID;
lineField.ActorIndex = line.ActorIdx;
lineField.Flags = line.Flags;
lines.Add(lineField);
}
SetUpdateFieldValue(m_values.ModifyValue(m_conversationData).ModifyValue(m_conversationData.Lines), lines);
Global.ScriptMgr.OnConversationCreate(this, creator);
// All actors need to be set
foreach (ushort actorIndex in actorIndices)
{
ConversationDynamicFieldActor actor = GetDynamicStructuredValue<ConversationDynamicFieldActor>(ConversationDynamicFields.Actors, actorIndex);
if (actor == null || actor.IsEmpty())
ConversationActor actor = actorIndex < m_conversationData.Actors.Size() ? m_conversationData.Actors[actorIndex] : null;
if (actor == null || (actor.CreatureID == 0 && actor.ActorGUID.IsEmpty()))
{
Log.outError(LogFilter.Conversation, $"Failed to create conversation (Id: {conversationEntry}) due to missing actor (Idx: {actorIndex}).");
return false;
@@ -175,10 +189,9 @@ namespace Game.Entities
void AddActor(ObjectGuid actorGuid, ushort actorIdx)
{
ConversationDynamicFieldActor actorField = new ConversationDynamicFieldActor();
actorField.ActorGuid = actorGuid;
actorField.Type = ConversationDynamicFieldActor.ActorType.WorldObjectActor;
SetDynamicStructuredValue(ConversationDynamicFields.Actors, actorIdx, actorField);
ConversationActor actorField = m_values.ModifyValue(m_conversationData).ModifyValue(m_conversationData.Actors, actorIdx);
SetUpdateFieldValue(ref actorField.ActorGUID, actorGuid);
SetUpdateFieldValue(ref actorField.Type, ConversationActorType.WorldObjectActor);
}
void AddParticipant(ObjectGuid participantGuid)
@@ -191,6 +204,41 @@ namespace Game.Entities
return Global.ConversationDataStorage.GetConversationTemplate(GetEntry()).ScriptId;
}
public override void BuildValuesCreate(WorldPacket data, Player target)
{
UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
WorldPacket buffer = new WorldPacket();
m_objectData.WriteCreate(buffer, flags, this, target);
m_conversationData.WriteCreate(buffer, flags, this, target);
data.WriteUInt32(buffer.GetSize());
data.WriteUInt8((byte)flags);
data.WriteBytes(buffer);
}
public override void BuildValuesUpdate(WorldPacket data, Player target)
{
UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
WorldPacket buffer = new WorldPacket();
buffer.WriteUInt32(m_values.GetChangedObjectTypeMask());
if (m_values.HasChanged(TypeId.Object))
m_objectData.WriteUpdate(buffer, flags, this, target);
if (m_values.HasChanged(TypeId.Conversation))
m_conversationData.WriteUpdate(buffer, flags, this, target);
data.WriteUInt32(buffer.GetSize());
data.WriteBytes(buffer);
}
public override void ClearUpdateMask(bool remove)
{
m_values.ClearChangesMask(m_conversationData);
base.ClearUpdateMask(remove);
}
uint GetDuration() { return _duration; }
public uint GetTextureKitId() { return _textureKitId; }
@@ -202,35 +250,12 @@ namespace Game.Entities
public override float GetStationaryO() { return _stationaryPosition.GetOrientation(); }
void RelocateStationaryPosition(Position pos) { _stationaryPosition.Relocate(pos); }
ConversationData m_conversationData;
Position _stationaryPosition = new Position();
ObjectGuid _creatorGuid;
uint _duration;
uint _textureKitId;
List<ObjectGuid> _participants = new List<ObjectGuid>();
}
class ConversationDynamicFieldActor
{
public enum ActorType
{
WorldObjectActor = 0,
CreatureActor = 1
}
public bool IsEmpty()
{
return ActorGuid.IsEmpty(); // this one is good enough
}
public ObjectGuid ActorGuid;
public ActorTemplateStruct ActorTemplate;
public struct ActorTemplateStruct
{
public uint CreatureId;
public uint CreatureModelId;
}
public ActorType Type;
}
}
+95 -21
View File
@@ -21,6 +21,9 @@ using Game.DataStorage;
using Game.Loots;
using Game.Maps;
using System.Collections.Generic;
using System.Text;
using Framework.Collections;
using Game.Network;
namespace Game.Entities
{
@@ -34,7 +37,7 @@ namespace Game.Entities
m_updateFlag.Stationary = true;
valuesCount = (int)CorpseFields.End;
m_corpseData = new CorpseData();
m_time = Time.UnixTime;
}
@@ -79,7 +82,7 @@ namespace Game.Entities
_Create(ObjectGuid.Create(HighGuid.Corpse, owner.GetMapId(), 0, guidlow));
SetObjectScale(1);
SetGuidValue(CorpseFields.Owner, owner.GetGUID());
SetOwnerGUID(owner.GetGUID());
_cellCoord = GridDefines.ComputeCellCoord(GetPositionX(), GetPositionY());
@@ -94,6 +97,14 @@ namespace Game.Entities
SQLTransaction trans = new SQLTransaction();
DeleteFromDB(trans);
StringBuilder items = new StringBuilder();
for (var i = 0; i < EquipmentSlot.End; ++i)
items.Append($"{m_corpseData.Items[i]} ");
uint bytes1 = ((uint)m_corpseData.RaceID << 8) | ((uint)m_corpseData.Sex << 16) | ((uint)m_corpseData.SkinID << 24);
uint bytes2 = ((uint)m_corpseData.FaceID) | ((uint)m_corpseData.HairStyleID << 8) | ((uint)m_corpseData.HairColorID << 16) | ((uint)m_corpseData.FacialHairStyleID << 24);
byte index = 0;
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CORPSE);
stmt.AddValue(index++, GetOwnerGUID().GetCounter()); // guid
@@ -102,14 +113,14 @@ namespace Game.Entities
stmt.AddValue(index++, GetPositionZ()); // posZ
stmt.AddValue(index++, GetOrientation()); // orientation
stmt.AddValue(index++, GetMapId()); // mapId
stmt.AddValue(index++, GetUInt32Value(CorpseFields.DisplayId)); // displayId
stmt.AddValue(index++, _ConcatFields(CorpseFields.Item, EquipmentSlot.End)); // itemCache
stmt.AddValue(index++, GetUInt32Value(CorpseFields.Bytes1)); // bytes1
stmt.AddValue(index++, GetUInt32Value(CorpseFields.Bytes2)); // bytes2
stmt.AddValue(index++, GetUInt32Value(CorpseFields.Flags)); // flags
stmt.AddValue(index++, GetUInt32Value(CorpseFields.DynamicFlags)); // dynFlags
stmt.AddValue(index++, (uint)m_time); // time
stmt.AddValue(index++, (uint)GetCorpseType()); // corpseType
stmt.AddValue(index++, (uint)m_corpseData.DisplayID); // displayId
stmt.AddValue(index++, items.ToString()); // itemCache
stmt.AddValue(index++, bytes1); // bytes1
stmt.AddValue(index++, bytes2); // bytes2
stmt.AddValue(index++, (uint)m_corpseData.Flags); // flags
stmt.AddValue(index++, (uint)m_corpseData.DynamicFlags); // dynFlags
stmt.AddValue(index++, (uint)m_time); // time
stmt.AddValue(index++, (uint)GetCorpseType()); // corpseType
stmt.AddValue(index++, GetInstanceId()); // instanceId
trans.Append(stmt);
@@ -153,16 +164,24 @@ namespace Game.Entities
_Create(ObjectGuid.Create(HighGuid.Corpse, mapId, 0, guid));
SetObjectScale(1.0f);
SetUInt32Value(CorpseFields.DisplayId, field.Read<uint>(5));
_LoadIntoDataField(field.Read<string>(6), (int)CorpseFields.Item, EquipmentSlot.End);
SetUInt32Value(CorpseFields.Bytes1, field.Read<uint>(7));
SetUInt32Value(CorpseFields.Bytes2, field.Read<uint>(8));
SetUInt32Value(CorpseFields.Flags, field.Read<byte>(9));
SetUInt32Value(CorpseFields.DynamicFlags, field.Read<byte>(10));
SetGuidValue(CorpseFields.Owner, ObjectGuid.Create(HighGuid.Player, field.Read<ulong>(14)));
CharacterInfo characterInfo = Global.WorldMgr.GetCharacterInfo(GetGuidValue(CorpseFields.Owner));
if (characterInfo != null)
SetUInt32Value(CorpseFields.FactionTemplate, CliDB.ChrRacesStorage.LookupByKey(characterInfo.RaceID).FactionID);
SetDisplayId(field.Read<uint>(5));
StringArray items = new StringArray(field.Read<string>(6), ' ');
for (uint index = 0; index < EquipmentSlot.End; ++index)
SetItem(index, uint.Parse(items[(int)index]));
uint bytes1 = field.Read<uint>(7);
uint bytes2 = field.Read<uint>(8);
SetRace((Race)((bytes1 >> 8) & 0xFF));
SetSex((Gender)((bytes1 >> 16) & 0xFF));
SetSkin((byte)((bytes1 >> 24) & 0xFF));
SetFace((byte)(bytes2 & 0xFF));
SetHairStyle((byte)((bytes2 >> 8) & 0xFF));
SetHairColor((byte)((bytes2 >> 16) & 0xFF));
SetFacialHairStyle((byte)((bytes2 >> 24) & 0xFF));
SetFlags((CorpseFlags)field.Read<byte>(9));
SetCorpseDynamicFlags((CorpseDynFlags)field.Read<byte>(10));
SetOwnerGUID(ObjectGuid.Create(HighGuid.Player, field.Read<ulong>(14)));
SetFactionTemplate(CliDB.ChrRacesStorage.LookupByKey(m_corpseData.RaceID).FactionID);
m_time = field.Read<uint>(11);
@@ -196,7 +215,60 @@ namespace Game.Entities
return m_time < t - 3 * Time.Day;
}
public ObjectGuid GetOwnerGUID() { return GetGuidValue(CorpseFields.Owner); }
public override void BuildValuesCreate(WorldPacket data, Player target)
{
UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
WorldPacket buffer = new WorldPacket();
m_objectData.WriteCreate(buffer, flags, this, target);
m_corpseData.WriteCreate(buffer, flags, this, target);
data.WriteUInt32(buffer.GetSize());
data.WriteUInt8((byte)flags);
data.WriteBytes(buffer);
}
public override void BuildValuesUpdate(WorldPacket data, Player target)
{
UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
WorldPacket buffer = new WorldPacket();
buffer.WriteUInt32(m_values.GetChangedObjectTypeMask());
if (m_values.HasChanged(TypeId.Object))
m_objectData.WriteUpdate(buffer, flags, this, target);
if (m_values.HasChanged(TypeId.Corpse))
m_corpseData.WriteUpdate(buffer, flags, this, target);
data.WriteUInt32(buffer.GetSize());
data.WriteBytes(buffer);
}
public override void ClearUpdateMask(bool remove)
{
m_values.ClearChangesMask(m_corpseData);
base.ClearUpdateMask(remove);
}
public void AddCorpseDynamicFlag(CorpseDynFlags dynamicFlags) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.DynamicFlags), (uint)dynamicFlags); }
public void RemoveCorpseDynamicFlag(CorpseDynFlags dynamicFlags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.DynamicFlags), (uint)dynamicFlags); }
public void SetCorpseDynamicFlags(CorpseDynFlags dynamicFlags) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.DynamicFlags), (uint)dynamicFlags); }
public ObjectGuid GetOwnerGUID() { return m_corpseData.Owner; }
public void SetOwnerGUID(ObjectGuid owner) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.Owner), owner); }
public void SetPartyGUID(ObjectGuid partyGuid) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.PartyGUID), partyGuid); }
public void SetGuildGUID(ObjectGuid guildGuid) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.GuildGUID), guildGuid); }
public void SetDisplayId(uint displayId) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.DisplayID), displayId); }
public void SetRace(Race race) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.RaceID), (byte)race); }
public void SetSex(Gender sex) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.Sex), (byte)sex); }
public void SetSkin(byte skin) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.SkinID), skin); }
public void SetFace(byte face) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.FaceID), face); }
public void SetHairStyle(byte hairStyle) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.HairStyleID), hairStyle); }
public void SetHairColor(byte hairColor) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.HairColorID), hairColor); }
public void SetFacialHairStyle(byte facialHairStyle) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.FacialHairStyleID), facialHairStyle); }
public void SetFlags(CorpseFlags flags) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.Flags), (uint)flags); }
public void SetFactionTemplate(int factionTemplate) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.FactionTemplate), factionTemplate); }
public void SetItem(uint slot, uint item) { SetUpdateFieldValue(ref m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.Items, (int)slot), item); }
public void SetCustomDisplayOption(uint slot, byte customDisplayOption) { SetUpdateFieldValue(ref m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.CustomDisplayOption, (int)slot), customDisplayOption); }
public long GetGhostTime() { return m_time; }
public void ResetGhostTime() { m_time = Time.UnixTime; }
@@ -205,6 +277,8 @@ namespace Game.Entities
public CellCoord GetCellCoord() { return _cellCoord; }
public void SetCellCoord(CellCoord cellCoord) { _cellCoord = cellCoord; }
public CorpseData m_corpseData;
public Loot loot = new Loot();
public Player lootRecipient;
public bool lootForBody;
+84 -88
View File
@@ -46,8 +46,6 @@ namespace Game.Entities
m_meleeDamageSchoolMask = SpellSchoolMask.Normal;
m_regenTimer = SharedConst.CreatureRegenInterval;
valuesCount = (int)UnitFields.End;
_dynamicValuesCount = (int)UnitDynamicFields.End;
m_SightDistance = SharedConst.SightRangeUnit;
@@ -192,9 +190,8 @@ namespace Game.Entities
m_creatureInfo = cinfo; // map mode related always
// equal to player Race field, but creature does not have race
SetByteValue(UnitFields.Bytes0, 0, 0);
SetByteValue(UnitFields.Bytes0, 1, (byte)cinfo.UnitClass);
SetRace(0);
SetClass((Class)cinfo.UnitClass);
// Cancel load if no model defined
if (cinfo.GetFirstValidModel() == null)
@@ -213,7 +210,7 @@ namespace Game.Entities
SetDisplayId(model.CreatureDisplayID, model.DisplayScale);
SetNativeDisplayId(model.CreatureDisplayID, model.DisplayScale);
SetByteValue(UnitFields.Bytes0, 3, (byte)minfo.gender);
SetGender((Gender)minfo.gender);
// Load creature equipment
if (data == null || data.equipmentId == 0)
@@ -226,12 +223,12 @@ namespace Game.Entities
SetName(normalInfo.Name); // at normal entry always
SetFloatValue(UnitFields.ModCastSpeed, 1.0f);
SetFloatValue(UnitFields.ModCastHaste, 1.0f);
SetFloatValue(UnitFields.ModHaste, 1.0f);
SetFloatValue(UnitFields.ModRangedHaste, 1.0f);
SetFloatValue(UnitFields.ModHasteRegen, 1.0f);
SetFloatValue(UnitFields.ModTimeRate, 1.0f);
SetModCastingSpeed(1.0f);
SetModSpellHaste(1.0f);
SetModHaste(1.0f);
SetModRangedHaste(1.0f);
SetModHasteRegen(1.0f);
SetModTimeRate(1.0f);
SetSpeedRate(UnitMoveType.Walk, cinfo.SpeedWalk);
SetSpeedRate(UnitMoveType.Run, cinfo.SpeedRun);
@@ -240,7 +237,7 @@ namespace Game.Entities
SetObjectScale(cinfo.Scale);
SetFloatValue(UnitFields.HoverHeight, cinfo.HoverHeight);
SetHoverHeight(cinfo.HoverHeight);
// checked at loading
m_defaultMovementType = (MovementGeneratorType)cinfo.MovementType;
@@ -273,19 +270,20 @@ namespace Game.Entities
ObjectManager.ChooseCreatureFlags(cInfo, out npcFlags, out unitFlags, out unitFlags2, out unitFlags3, out dynamicFlags, data);
if (cInfo.FlagsExtra.HasAnyFlag(CreatureFlagsExtra.Worldevent))
SetUInt64Value(UnitFields.NpcFlags, npcFlags | Global.GameEventMgr.GetNPCFlag(this));
else
SetUInt64Value(UnitFields.NpcFlags, npcFlags);
npcFlags |= Global.GameEventMgr.GetNPCFlag(this);
SetUInt32Value(UnitFields.Flags, unitFlags);
SetUInt32Value(UnitFields.Flags2, unitFlags2);
SetUInt32Value(UnitFields.Flags3, unitFlags3);
SetNpcFlags((NPCFlags)(npcFlags & 0xFFFFFFFF));
SetNpcFlags2((NPCFlags2)(npcFlags >> 32));
SetUInt32Value(ObjectFields.DynamicFlags, dynamicFlags);
SetUnitFlags((UnitFlags)unitFlags);
SetUnitFlags2((UnitFlags2)unitFlags2);
SetUnitFlags3((UnitFlags3)unitFlags3);
SetUInt32Value(UnitFields.StateAnimId, (uint)CliDB.AnimationDataStorage.Count);
SetDynamicFlags((UnitDynFlags)dynamicFlags);
RemoveFlag(UnitFields.Flags, UnitFlags.InCombat);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.StateAnimID), (uint)CliDB.AnimationDataStorage.Count);
RemoveUnitFlag(UnitFlags.InCombat);
SetBaseAttackTime(WeaponAttackType.BaseAttack, cInfo.BaseAttackTime);
SetBaseAttackTime(WeaponAttackType.OffAttack, cInfo.BaseAttackTime);
@@ -323,14 +321,14 @@ namespace Game.Entities
Player owner = GetCharmerOrOwnerPlayerOrPlayerItself();
if (owner != null) // this check comes in case we don't have a player
{
SetFaction(owner.getFaction()); // vehicles should have same as owner faction
SetFaction(owner.GetFaction()); // vehicles should have same as owner faction
owner.VehicleSpellInitialize();
}
}
// trigger creature is always not selectable and can not be attacked
if (IsTrigger())
SetFlag(UnitFields.Flags, UnitFlags.NotSelectable);
AddUnitFlag(UnitFlags.NotSelectable);
InitializeReactState();
@@ -411,7 +409,7 @@ namespace Game.Entities
else if (m_corpseRemoveTime <= Time.UnixTime)
{
RemoveCorpse(false);
Log.outDebug(LogFilter.Unit, "Removing corpse... {0} ", GetUInt32Value(ObjectFields.Entry));
Log.outDebug(LogFilter.Unit, "Removing corpse... {0} ", GetEntry());
}
break;
case DeathState.Alive:
@@ -519,7 +517,7 @@ namespace Game.Entities
if (!IsInEvadeMode() && (!bInCombat || IsPolymorphed() || CanNotReachTarget())) // regenerate health if not in combat or if polymorphed
RegenerateHealth();
if (HasFlag(UnitFields.Flags2, UnitFlags2.RegeneratePower))
if (HasUnitFlag2(UnitFlags2.RegeneratePower))
{
if (GetPowerType() == PowerType.Energy)
Regenerate(PowerType.Energy);
@@ -798,7 +796,7 @@ namespace Game.Entities
//! Need to be called after LoadCreaturesAddon - MOVEMENTFLAG_HOVER is set there
if (HasUnitMovementFlag(MovementFlag.Hover))
{
z += GetFloatValue(UnitFields.HoverHeight);
z += m_unitData.HoverHeight;
//! Relocate again with updated Z coord
Relocate(x, y, z, ang);
@@ -810,7 +808,7 @@ namespace Game.Entities
{
SetDisplayId(display.CreatureDisplayID, display.DisplayScale);
SetNativeDisplayId(display.CreatureDisplayID, display.DisplayScale);
SetByteValue(UnitFields.Bytes0, 3, (byte)minfo.gender);
SetGender((Gender)minfo.gender);
}
LastUsedScriptID = GetScriptId();
@@ -956,7 +954,7 @@ namespace Game.Entities
{
m_lootRecipient.Clear();
m_lootRecipientGroup.Clear();
RemoveFlag(ObjectFields.DynamicFlags, UnitDynFlags.Lootable | UnitDynFlags.Tapped);
RemoveDynamicFlag(UnitDynFlags.Lootable | UnitDynFlags.Tapped);
return;
}
@@ -972,7 +970,7 @@ namespace Game.Entities
if (group)
m_lootRecipientGroup = group.GetGUID();
SetFlag(ObjectFields.DynamicFlags, UnitDynFlags.Tapped);
AddDynamicFlag(UnitDynFlags.Tapped);
}
public bool isTappedBy(Player player)
@@ -1011,11 +1009,11 @@ namespace Game.Entities
CreatureData data = Global.ObjectMgr.NewOrExistCreatureData(m_spawnId);
uint displayId = GetNativeDisplayId();
ulong npcflag = GetUInt64Value(UnitFields.NpcFlags);
uint unitFlags = GetUInt32Value(UnitFields.Flags);
uint unitFlags2 = GetUInt32Value(UnitFields.Flags2);
uint unitFlags3 = GetUInt32Value(UnitFields.Flags3);
uint dynamicflags = GetUInt32Value(ObjectFields.DynamicFlags);
ulong npcflag = ((ulong)m_unitData.NpcFlags[1] << 32) | m_unitData.NpcFlags[0];
uint unitFlags = m_unitData.Flags;
uint unitFlags2 = m_unitData.Flags2;
uint unitFlags3 = m_unitData.Flags3;
UnitDynFlags dynamicflags = (UnitDynFlags)(uint)m_objectData.DynamicFlags;
// check if it's a custom model and if not, use 0 for displayId
CreatureTemplate cinfo = GetCreatureTemplate();
@@ -1037,7 +1035,7 @@ namespace Game.Entities
if (unitFlags3 == cinfo.UnitFlags3)
unitFlags3 = 0;
if (dynamicflags == cinfo.DynamicFlags)
if (dynamicflags == (UnitDynFlags)cinfo.DynamicFlags)
dynamicflags = 0;
}
@@ -1064,7 +1062,7 @@ namespace Game.Entities
data.unit_flags = unitFlags;
data.unit_flags2 = unitFlags2;
data.unit_flags3 = unitFlags3;
data.dynamicflags = dynamicflags;
data.dynamicflags = (uint)dynamicflags;
data.phaseId = GetDBPhase() > 0 ? (uint)GetDBPhase() : data.phaseId;
data.phaseGroup = GetDBPhase() < 0 ? (uint)-GetDBPhase() : data.phaseGroup;
@@ -1119,14 +1117,14 @@ namespace Game.Entities
if (HasScalableLevels())
{
SetUInt32Value(UnitFields.ScalingLevelMin, cInfo.levelScaling.Value.MinLevel);
SetUInt32Value(UnitFields.ScalingLevelMax, cInfo.levelScaling.Value.MaxLevel);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ScalingLevelMin), cInfo.levelScaling.Value.MinLevel);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ScalingLevelMax), cInfo.levelScaling.Value.MaxLevel);
int mindelta = Math.Min(cInfo.levelScaling.Value.DeltaLevelMax, cInfo.levelScaling.Value.DeltaLevelMin);
int maxdelta = Math.Max(cInfo.levelScaling.Value.DeltaLevelMax, cInfo.levelScaling.Value.DeltaLevelMin);
int delta = mindelta == maxdelta ? mindelta : RandomHelper.IRand(mindelta, maxdelta);
SetInt32Value(UnitFields.ScalingLevelDelta, delta);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ScalingLevelDelta), delta);
}
UpdateLevelDependantStats();
@@ -1434,9 +1432,9 @@ namespace Game.Entities
return false;
// This set of checks is should be done only for creatures
if ((HasFlag(UnitFields.Flags, UnitFlags.ImmuneToNpc) && !who.IsTypeId(TypeId.Player)) // flag is valid only for non player characters
|| (HasFlag(UnitFields.Flags, UnitFlags.ImmuneToPc) && who.IsTypeId(TypeId.Player)) // immune to PC and target is a player, return false
|| (who.GetOwner() && who.GetOwner().IsTypeId(TypeId.Player) && HasFlag(UnitFields.Flags, UnitFlags.ImmuneToPc))) // player pets are immune to pc as well
if ((HasUnitFlag(UnitFlags.ImmuneToNpc) && !who.IsTypeId(TypeId.Player)) // flag is valid only for non player characters
|| (HasUnitFlag(UnitFlags.ImmuneToPc) && who.IsTypeId(TypeId.Player)) // immune to PC and target is a player, return false
|| (who.GetOwner() && who.GetOwner().IsTypeId(TypeId.Player) && HasUnitFlag(UnitFlags.ImmuneToPc))) // player pets are immune to pc as well
return false;
// Do not attack non-combat pets
@@ -1530,9 +1528,10 @@ namespace Game.Entities
DoNotReacquireTarget(); // cancel delayed re-target
SetTarget(ObjectGuid.Empty); // drop target - dead mobs shouldn't ever target things
SetUInt64Value(UnitFields.NpcFlags, (ulong)NPCFlags.None);
SetNpcFlags(NPCFlags.None);
SetNpcFlags2(NPCFlags2.None);
SetUInt32Value(UnitFields.MountDisplayId, 0); // if creature is mounted on a virtual mount, remove it at death
SetMountDisplayId(0); // if creature is mounted on a virtual mount, remove it at death
setActive(false);
@@ -1576,16 +1575,17 @@ namespace Game.Entities
ObjectManager.ChooseCreatureFlags(cInfo, out npcFlags, out unitFlags, out unitFlags2, out unitFlags3, out dynamicFlags, creatureData);
if (cInfo.FlagsExtra.HasAnyFlag(CreatureFlagsExtra.Worldevent))
SetUInt64Value(UnitFields.NpcFlags, npcFlags | Global.GameEventMgr.GetNPCFlag(this));
else
SetUInt64Value(UnitFields.NpcFlags, npcFlags);
npcFlags |= Global.GameEventMgr.GetNPCFlag(this);
SetUInt32Value(UnitFields.Flags, unitFlags);
SetUInt32Value(UnitFields.Flags2, unitFlags2);
SetUInt32Value(UnitFields.Flags3, unitFlags3);
SetUInt32Value(ObjectFields.DynamicFlags, dynamicFlags);
SetNpcFlags((NPCFlags)(npcFlags & 0xFFFFFFFF));
SetNpcFlags2((NPCFlags2)(npcFlags >> 32));
RemoveFlag(UnitFields.Flags, UnitFlags.InCombat);
SetUnitFlags((UnitFlags)unitFlags);
SetUnitFlags2((UnitFlags2)unitFlags2);
SetUnitFlags3((UnitFlags3)unitFlags3);
SetDynamicFlags((UnitDynFlags)dynamicFlags);
RemoveUnitFlag(UnitFlags.InCombat);
SetMeleeDamageSchool((SpellSchools)cInfo.DmgSchool);
}
@@ -1633,7 +1633,7 @@ namespace Game.Entities
{
SetDisplayId(display.CreatureDisplayID, display.DisplayScale);
SetNativeDisplayId(display.CreatureDisplayID, display.DisplayScale);
SetByteValue(UnitFields.Bytes0, 3, (byte)minfo.gender);
SetGender((Gender)minfo.gender);
}
GetMotionMaster().InitDefault();
@@ -1805,9 +1805,9 @@ namespace Game.Entities
float dist = GetDistance(victim);
if (dist > range || dist < minrange)
continue;
if (spellInfo.PreventionType.HasAnyFlag(SpellPreventionType.Silence) && HasFlag(UnitFields.Flags, UnitFlags.Silenced))
if (spellInfo.PreventionType.HasAnyFlag(SpellPreventionType.Silence) && HasUnitFlag(UnitFlags.Silenced))
continue;
if (spellInfo.PreventionType.HasAnyFlag(SpellPreventionType.Pacify) && HasFlag(UnitFields.Flags, UnitFlags.Pacified))
if (spellInfo.PreventionType.HasAnyFlag(SpellPreventionType.Pacify) && HasUnitFlag(UnitFlags.Pacified))
continue;
return spellInfo;
}
@@ -1854,9 +1854,9 @@ namespace Game.Entities
if (dist > range || dist < minrange)
continue;
if (spellInfo.PreventionType.HasAnyFlag(SpellPreventionType.Silence) && HasFlag(UnitFields.Flags, UnitFlags.Silenced))
if (spellInfo.PreventionType.HasAnyFlag(SpellPreventionType.Silence) && HasUnitFlag(UnitFlags.Silenced))
continue;
if (spellInfo.PreventionType.HasAnyFlag(SpellPreventionType.Pacify) && HasFlag(UnitFields.Flags, UnitFlags.Pacified))
if (spellInfo.PreventionType.HasAnyFlag(SpellPreventionType.Pacify) && HasUnitFlag(UnitFlags.Pacified))
continue;
return spellInfo;
}
@@ -1969,7 +1969,7 @@ namespace Game.Entities
if (IsCivilian())
return false;
if (HasFlag(UnitFields.Flags, UnitFlags.NonAttackable | UnitFlags.NotSelectable | UnitFlags.ImmuneToPc))
if (HasUnitFlag(UnitFlags.NonAttackable | UnitFlags.NotSelectable | UnitFlags.ImmuneToPc))
return false;
// skip fighting creature
@@ -1983,7 +1983,7 @@ namespace Game.Entities
// only from same creature faction
if (checkfaction)
{
if (getFaction() != u.getFaction())
if (GetFaction() != u.GetFaction())
return false;
}
else
@@ -2009,7 +2009,7 @@ namespace Game.Entities
if (target.HasUnitState(UnitState.Died))
{
// guards can detect fake death
if (IsGuard() && target.HasFlag(UnitFields.Flags2, UnitFlags2.FeignDeath))
if (IsGuard() && target.HasUnitFlag2(UnitFlags2.FeignDeath))
return true;
else
return false;
@@ -2099,18 +2099,16 @@ namespace Game.Entities
// 2 StandFlags
// 3 StandMiscFlags
SetByteValue(UnitFields.Bytes1, UnitBytes1Offsets.StandState, (byte)(cainfo.bytes1 & 0xFF));
//SetByteValue(UnitFields.Bytes1, UnitBytes1Offsets.PetTalent, (byte)((cainfo.bytes1 >> 8) & 0xFF));
SetByteValue(UnitFields.Bytes1, UnitBytes1Offsets.PetTalents, 0);
SetByteValue(UnitFields.Bytes1, UnitBytes1Offsets.VisFlag, (byte)((cainfo.bytes1 >> 16) & 0xFF));
SetByteValue(UnitFields.Bytes1, UnitBytes1Offsets.AnimTier, (byte)((cainfo.bytes1 >> 24) & 0xFF));
SetStandState((UnitStandStateType)(cainfo.bytes1 & 0xFF));
SetVisFlags((UnitVisFlags)((cainfo.bytes1 >> 16) & 0xFF));
SetAnimTier((UnitBytes1Flags)((cainfo.bytes1 >> 24) & 0xFF), false);
//! Suspected correlation between UNIT_FIELD_BYTES_1, offset 3, value 0x2:
//! If no inhabittype_fly (if no MovementFlag_DisableGravity or MovementFlag_CanFly flag found in sniffs)
//! Check using InhabitType as movement flags are assigned dynamically
//! basing on whether the creature is in air or not
//! Set MovementFlag_Hover. Otherwise do nothing.
if (Convert.ToBoolean(GetByteValue(UnitFields.Bytes1, UnitBytes1Offsets.AnimTier) & (byte)UnitBytes1Flags.Hover) && !Convert.ToBoolean(GetCreatureTemplate().InhabitType & InhabitType.Air))
if (Convert.ToBoolean(m_unitData.AnimTier & (byte)UnitBytes1Flags.Hover) && !Convert.ToBoolean(GetCreatureTemplate().InhabitType & InhabitType.Air))
AddUnitMovementFlag(MovementFlag.Hover);
}
@@ -2121,16 +2119,14 @@ namespace Game.Entities
// 2 PetFlags Pet only, so always 0 for default creature
// 3 ShapeshiftForm Must be determined/set by shapeshift spell/aura
SetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.SheathState, (byte)(cainfo.bytes2 & 0xFF));
//SetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, uint8((cainfo->bytes2 >> 8) & 0xFF));
//SetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PetFlags, uint8((cainfo->bytes2 >> 16) & 0xFF));
SetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PetFlags, 0);
//SetByteValue(UnitFields.Bytes2, UNIT_BYTES_2_OFFSET_SHAPESHIFT_FORM, uint8((cainfo->bytes2 >> 24) & 0xFF));
SetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.ShapeshiftForm, 0);
SetSheath((SheathState)(cainfo.bytes2 & 0xFF));
SetPvpFlags(UnitPVPStateFlags.None);
SetPetFlags(UnitPetFlags.None);
SetShapeshiftForm(ShapeShiftForm.None);
}
if (cainfo.emote != 0)
SetUInt32Value(UnitFields.NpcEmotestate, cainfo.emote);
SetEmoteState((Emote)cainfo.emote);
SetAIAnimKitId(cainfo.aiAnimKit);
SetMovementAnimKitId(cainfo.movementAnimKit);
@@ -2289,7 +2285,7 @@ namespace Game.Entities
{
if (loot.loot_type != LootType.Skinning && !IsPet() && GetCreatureTemplate().SkinLootId != 0 && hasLootRecipient())
if (LootStorage.Skinning.HaveLootFor(GetCreatureTemplate().SkinLootId))
SetFlag(UnitFields.Flags, UnitFlags.Skinnable);
AddUnitFlag(UnitFlags.Skinnable);
long now = Time.UnixTime;
// Do not reset corpse remove time if corpse is already removed
@@ -2380,12 +2376,12 @@ namespace Game.Entities
// between UNIT_FIELD_SCALING_LEVEL_MIN and UNIT_FIELD_SCALING_LEVEL_MAX
if (HasScalableLevels())
{
int targetLevelWithDelta = ((int)unitTarget.getLevel() + GetInt32Value(UnitFields.ScalingLevelDelta));
int targetLevelWithDelta = (int)unitTarget.getLevel() + m_unitData.ScalingLevelDelta;
if (target.IsPlayer())
targetLevelWithDelta += target.GetInt32Value(ActivePlayerFields.ScalingPlayerLevelDelta);
targetLevelWithDelta += target.ToPlayer().m_activePlayerData.ScalingPlayerLevelDelta;
return (uint)MathFunctions.RoundToInterval(ref targetLevelWithDelta, GetInt32Value(UnitFields.ScalingLevelMin), GetInt32Value(UnitFields.ScalingLevelMax));
return (uint)MathFunctions.RoundToInterval(ref targetLevelWithDelta, m_unitData.ScalingLevelMin, m_unitData.ScalingLevelMax);
}
}
@@ -2409,7 +2405,7 @@ namespace Game.Entities
if (creatureData != null)
return creatureData.ScriptId;
return Global.ObjectMgr.GetCreatureTemplate(GetEntry()).ScriptID;
return Global.ObjectMgr.GetCreatureTemplate(GetEntry()) != null ? Global.ObjectMgr.GetCreatureTemplate(GetEntry()).ScriptID : 0;
}
public VendorItemData GetVendorItems()
@@ -2668,8 +2664,8 @@ namespace Game.Entities
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelInfo(GetDisplayId());
if (minfo != null)
{
SetFloatValue(UnitFields.BoundingRadius, (IsPet() ? 1.0f : minfo.BoundingRadius) * scale);
SetFloatValue(UnitFields.CombatReach, (IsPet() ? SharedConst.DefaultCombatReach : minfo.CombatReach) * scale);
SetBoundingRadius((IsPet() ? 1.0f : minfo.BoundingRadius) * scale);
SetCombatReach((IsPet() ? SharedConst.DefaultCombatReach : minfo.CombatReach) * scale);
}
}
@@ -2680,8 +2676,8 @@ namespace Game.Entities
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelInfo(modelId);
if (minfo != null)
{
SetFloatValue(UnitFields.BoundingRadius, (IsPet() ? 1.0f : minfo.BoundingRadius) * GetObjectScale());
SetFloatValue(UnitFields.CombatReach, (IsPet() ? SharedConst.DefaultCombatReach : minfo.CombatReach) * GetObjectScale());
SetBoundingRadius((IsPet() ? 1.0f : minfo.BoundingRadius) * GetObjectScale());
SetCombatReach((IsPet() ? SharedConst.DefaultCombatReach : minfo.CombatReach) * GetObjectScale());
}
}
@@ -2697,7 +2693,7 @@ namespace Game.Entities
if (IsFocusing(null, true))
m_suppressedTarget = guid;
else
SetGuidValue(UnitFields.Target, guid);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Target), guid);
}
public void FocusTarget(Spell focusSpell, WorldObject target)
@@ -2716,7 +2712,7 @@ namespace Game.Entities
// store pre-cast values for target and orientation (used to later restore)
if (!IsFocusing(null, true))
{ // only overwrite these fields if we aren't transitioning from one spell focus to another
m_suppressedTarget = GetGuidValue(UnitFields.Target);
m_suppressedTarget = GetTarget();
m_suppressedOrientation = GetOrientation();
}
@@ -2724,9 +2720,9 @@ namespace Game.Entities
// set target, then force send update packet to players if it changed to provide appropriate facing
ObjectGuid newTarget = target ? target.GetGUID() : ObjectGuid.Empty;
if (GetGuidValue(UnitFields.Target) != newTarget)
if (GetTarget() != newTarget)
{
SetGuidValue(UnitFields.Target, newTarget);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Target), newTarget);
// here we determine if the (relatively expensive) forced update is worth it, or whether we can afford to wait until the scheduled update tick
// only require instant update for spells that actually have a visual
@@ -2794,7 +2790,7 @@ namespace Game.Entities
if (IsPet())// player pets do not use delay system
{
SetGuidValue(UnitFields.Target, m_suppressedTarget);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Target), m_suppressedTarget);
if (!m_suppressedTarget.IsEmpty())
{
WorldObject objTarget = Global.ObjAccessor.GetWorldObject(this, m_suppressedTarget);
@@ -42,7 +42,7 @@ namespace Game.Entities
public uint RequiredExpansion;
public uint VignetteID; // @todo Read Vignette.db2
public uint Faction;
public NPCFlags Npcflag;
public ulong Npcflag;
public float SpeedWalk;
public float SpeedRun;
public float Scale;
+49 -14
View File
@@ -17,6 +17,7 @@
using Framework.Constants;
using Game.Spells;
using Game.Network;
namespace Game.Entities
{
@@ -29,7 +30,7 @@ namespace Game.Entities
m_updateFlag.Stationary = true;
valuesCount = (int)DynamicObjectFields.End;
m_dynamicObjectData = new DynamicObjectData();
}
public override void Dispose()
@@ -77,7 +78,6 @@ namespace Game.Entities
public bool CreateDynamicObject(ulong guidlow, Unit caster, SpellInfo spell, Position pos, float radius, DynamicObjectType type, uint spellXSpellVisualId)
{
_spellXSpellVisualId = spellXSpellVisualId;
SetMap(caster.GetMap());
Relocate(pos);
if (!IsPositionValid())
@@ -91,13 +91,13 @@ namespace Game.Entities
SetEntry(spell.Id);
SetObjectScale(1f);
SetGuidValue(DynamicObjectFields.Caster, caster.GetGUID());
SetUInt32Value(DynamicObjectFields.Type, (uint)type);
SetUInt32Value(DynamicObjectFields.SpellXSpellVisualId, spellXSpellVisualId);
SetUInt32Value(DynamicObjectFields.SpellId, spell.Id);
SetFloatValue(DynamicObjectFields.Radius, radius);
SetUInt32Value(DynamicObjectFields.CastTime, Time.GetMSTime());
SetUpdateFieldValue(m_values.ModifyValue(m_dynamicObjectData).ModifyValue(m_dynamicObjectData.Caster), caster.GetGUID());
SetUpdateFieldValue(m_values.ModifyValue(m_dynamicObjectData).ModifyValue(m_dynamicObjectData.Type), (byte)type);
SetUpdateFieldValue(m_values.ModifyValue(m_dynamicObjectData).ModifyValue(m_dynamicObjectData.SpellXSpellVisualID), spellXSpellVisualId);
SetUpdateFieldValue(m_values.ModifyValue(m_dynamicObjectData).ModifyValue(m_dynamicObjectData.SpellID), spell.Id);
SetUpdateFieldValue(m_values.ModifyValue(m_dynamicObjectData).ModifyValue(m_dynamicObjectData.Radius), radius);
SetUpdateFieldValue(m_values.ModifyValue(m_dynamicObjectData).ModifyValue(m_dynamicObjectData.CastTime), Time.GetMSTime());
if (IsWorldObject())
setActive(true); //must before add to map to be put in world container
@@ -207,7 +207,7 @@ namespace Game.Entities
if (caster != null)
{
caster.SetViewpoint(this, true);
_isViewpoint = true;
_isViewpoint = true;
}
}
@@ -242,16 +242,51 @@ namespace Game.Entities
return Global.SpellMgr.GetSpellInfo(GetSpellId());
}
public Unit GetCaster() { return _caster; }
public uint GetSpellId() { return GetUInt32Value(DynamicObjectFields.SpellId); }
public ObjectGuid GetCasterGUID() { return GetGuidValue(DynamicObjectFields.Caster); }
public float GetRadius() { return GetFloatValue(DynamicObjectFields.Radius); }
public override void BuildValuesCreate(WorldPacket data, Player target)
{
UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
WorldPacket buffer = new WorldPacket();
buffer.WriteUInt8((byte)flags);
m_objectData.WriteCreate(buffer, flags, this, target);
m_dynamicObjectData.WriteCreate(buffer, flags, this, target);
data.WriteUInt32(buffer.GetSize());
data.WriteBytes(buffer);
}
public override void BuildValuesUpdate(WorldPacket data, Player target)
{
UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
WorldPacket buffer = new WorldPacket();
buffer.WriteUInt32(m_values.GetChangedObjectTypeMask());
if (m_values.HasChanged(TypeId.Object))
m_objectData.WriteUpdate(buffer, flags, this, target);
if (m_values.HasChanged(TypeId.DynamicObject))
m_dynamicObjectData.WriteUpdate(buffer, flags, this, target);
data.WriteUInt32(buffer.GetSize());
data.WriteBytes(buffer);
}
public override void ClearUpdateMask(bool remove)
{
m_values.ClearChangesMask(m_dynamicObjectData);
base.ClearUpdateMask(remove);
}
public Unit GetCaster() { return _caster; }
public uint GetSpellId() { return m_dynamicObjectData.SpellID; }
public ObjectGuid GetCasterGUID() { return m_dynamicObjectData.Caster; }
public float GetRadius() { return m_dynamicObjectData.Radius; }
DynamicObjectData m_dynamicObjectData;
Aura _aura;
Aura _removedAura;
Unit _caster;
int _duration; // for non-aura dynobjects
uint _spellXSpellVisualId;
bool _isViewpoint;
}
+106 -156
View File
@@ -31,6 +31,7 @@ using Game.Spells;
using System;
using System.Collections.Generic;
using System.Linq;
using Game.Network;
namespace Game.Entities
{
@@ -44,13 +45,14 @@ namespace Game.Entities
m_updateFlag.Stationary = true;
m_updateFlag.Rotation = true;
valuesCount = (int)GameObjectFields.End;
m_respawnDelayTime = 300;
m_lootState = LootState.NotReady;
m_spawnedByDefault = true;
ResetLootMode(); // restore default loot mode
m_stationaryPosition = new Position();
m_gameObjectData = new GameObjectFieldData();
}
public override void Dispose()
@@ -248,8 +250,8 @@ namespace Game.Entities
if (m_goTemplateAddon != null)
{
SetUInt32Value(GameObjectFields.Faction, m_goTemplateAddon.faction);
SetUInt32Value(GameObjectFields.Flags, m_goTemplateAddon.flags);
SetFaction(m_goTemplateAddon.faction);
SetFlags((GameObjectFlags)m_goTemplateAddon.flags);
if (m_goTemplateAddon.WorldEffectID != 0)
{
@@ -267,7 +269,7 @@ namespace Game.Entities
m_model = CreateModel();
if (m_model != null && m_model.isMapObject())
SetFlag(GameObjectFields.Flags, GameObjectFlags.MapObject);
AddFlag(GameObjectFlags.MapObject);
// GAMEOBJECT_BYTES_1, index at 0, 1, 2 and 3
SetGoType(goInfo.type);
@@ -275,7 +277,7 @@ namespace Game.Entities
SetGoState(goState);
SetGoArtKit((byte)artKit);
SetUInt32Value(GameObjectFields.StateAnimId, (uint)CliDB.AnimationDataStorage.Count);
SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.SpawnTrackingStateAnimID), (uint)CliDB.AnimationDataStorage.Count);
switch (goInfo.type)
{
@@ -287,7 +289,8 @@ namespace Game.Entities
m_goValue.Building.Health = 20000;//goinfo.DestructibleBuilding.intactNumHits + goinfo.DestructibleBuilding.damagedNumHits;
m_goValue.Building.MaxHealth = m_goValue.Building.Health;
SetGoAnimProgress(255);
SetUInt32Value(GameObjectFields.ParentRotation, goInfo.DestructibleBuilding.DestructibleModelRec);
// yes, even after the updatefield rewrite this garbage hack is still in client
SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.ParentRotation), new Quaternion(goInfo.DestructibleBuilding.DestructibleModelRec, 0f, 0f, 0f));
break;
case GameObjectTypes.Transport:
m_goValue.Transport.AnimationInfo = Global.TransportMgr.GetTransportAnimInfo(goInfo.entry);
@@ -324,7 +327,7 @@ namespace Game.Entities
SetGoAnimProgress(animProgress);
break;
case GameObjectTypes.FishingNode:
SetUInt32Value(GameObjectFields.Level, 1);
SetLevel(1);
SetGoAnimProgress(255);
break;
case GameObjectTypes.Trap:
@@ -341,10 +344,11 @@ namespace Game.Entities
}
break;
case GameObjectTypes.PhaseableMo:
SetByteValue(GameObjectFields.Flags, 1, (byte)(m_goInfo.PhaseableMO.AreaNameSet & 0xF));
RemoveFlag((GameObjectFlags)0xF00);
AddFlag((GameObjectFlags)((m_goInfo.PhaseableMO.AreaNameSet & 0xF) << 8));
break;
case GameObjectTypes.CapturePoint:
SetUInt32Value(GameObjectFields.SpellVisualId, m_goInfo.CapturePoint.SpellVisual1);
SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.SpellVisualID), m_goInfo.CapturePoint.SpellVisual1);
break;
default:
SetGoAnimProgress(animProgress);
@@ -438,15 +442,15 @@ namespace Game.Entities
m_goValue.Transport.PathProgress += diff;
/* TODO: Fix movement in unloaded grid - currently GO will just disappear
public uint timer = m_goValue.Transport.PathProgress % GetTransportPeriod();
TransportAnimationEntry const* node = m_goValue.Transport.AnimationInfo->GetAnimNode(timer);
if (node && m_goValue.Transport.CurrentSeg != node->TimeSeg)
TransportAnimationEntry const* node = m_goValue.Transport.AnimationInfo.GetAnimNode(timer);
if (node && m_goValue.Transport.CurrentSeg != node.TimeSeg)
{
m_goValue.Transport.CurrentSeg = node->TimeSeg;
m_goValue.Transport.CurrentSeg = node.TimeSeg;
G3D.Quat rotation = m_goValue.Transport.AnimationInfo->GetAnimRotation(timer);
G3D.Quat rotation = m_goValue.Transport.AnimationInfo.GetAnimRotation(timer);
G3D.Vector3 pos = rotation.toRotationMatrix()
G3D.Matrix3.fromEulerAnglesZYX(GetOrientation(), 0.0f, 0.0f)
G3D.Vector3(node->X, node->Y, node->Z);
G3D.Vector3(node.X, node.Y, node.Z);
pos += G3D.Vector3(GetStationaryX(), GetStationaryY(), GetStationaryZ());
@@ -454,7 +458,7 @@ namespace Game.Entities
TC_LOG_DEBUG("misc", "Src: {0} Dest: {1}", src.toString().c_str(), pos.toString().c_str());
GetMap()->GameObjectRelocation(this, pos.x, pos.y, pos.z, GetOrientation());
GetMap().GameObjectRelocation(this, pos.x, pos.y, pos.z, GetOrientation());
}
*/
if (!m_goValue.Transport.StopFrames.Empty())
@@ -464,8 +468,9 @@ namespace Game.Entities
uint visualStateAfter = (m_goValue.Transport.StateUpdateTimer / 20000) & 1;
if (visualStateBefore != visualStateAfter)
{
ForceValuesUpdateAtIndex(GameObjectFields.Level);
ForceValuesUpdateAtIndex(GameObjectFields.Bytes1);
m_gameObjectData.ModifyValue(m_gameObjectData.Level);
m_gameObjectData.ModifyValue(m_gameObjectData.State);
ForceUpdateFieldChange();
}
}
}
@@ -480,7 +485,7 @@ namespace Game.Entities
if (caster != null && caster.IsTypeId(TypeId.Player))
{
SetGoState(GameObjectState.Active);
SetUInt32Value(GameObjectFields.Flags, (uint)GameObjectFlags.NoDespawn);
SetFlags(GameObjectFlags.NoDespawn);
UpdateData udata = new UpdateData(caster.GetMapId());
UpdateObject packet;
@@ -650,7 +655,7 @@ namespace Game.Entities
case GameObjectTypes.Goober:
if (m_cooldownTime < Time.UnixTime)
{
RemoveFlag(GameObjectFields.Flags, GameObjectFlags.InUse);
RemoveFlag(GameObjectFlags.InUse);
SetLootState(LootState.JustDeactivated);
m_cooldownTime = 0;
@@ -770,7 +775,7 @@ namespace Game.Entities
//reset flags
GameObjectTemplateAddon addon = GetTemplateAddon();
if (addon != null)
SetUInt32Value(GameObjectFields.Flags, addon.flags);
SetFlags((GameObjectFlags)addon.flags);
}
if (m_respawnDelayTime == 0)
@@ -823,7 +828,7 @@ namespace Game.Entities
SetGoState(GameObjectState.Ready);
GameObjectTemplateAddon addon = GetTemplateAddon();
if (addon != null)
SetUInt32Value(GameObjectFields.Flags, addon.flags);
SetFlags((GameObjectFlags)addon.flags);
uint poolid = GetSpawnId() != 0 ? Global.PoolMgr.IsPartOfAPool<GameObject>(GetSpawnId()) : 0;
if (poolid != 0)
@@ -918,7 +923,7 @@ namespace Game.Entities
data.animprogress = GetGoAnimProgress();
data.go_state = GetGoState();
data.spawnDifficulties = spawnDifficulties;
data.artKit = GetGoArtKit();
data.artKit = (byte)GetGoArtKit();
Global.ObjectMgr.NewGOData(m_spawnId, data);
data.phaseId = GetDBPhase() > 0 ? (uint)GetDBPhase() : data.phaseId;
@@ -980,7 +985,7 @@ namespace Game.Entities
if (!GetGoInfo().GetDespawnPossibility() && !GetGoInfo().IsDespawnAtAction())
{
SetFlag(GameObjectFields.Flags, GameObjectFlags.NoDespawn);
AddFlag(GameObjectFlags.NoDespawn);
m_respawnDelayTime = 0;
m_respawnTime = 0;
}
@@ -1104,7 +1109,7 @@ namespace Game.Entities
if (GetGoType() == GameObjectTypes.SpellFocus && GetGoInfo().SpellFocus.serverOnly == 1)
return true;
if (GetUInt32Value(GameObjectFields.DisplayId) == 0)
if (GetDisplayId() == 0)
return true;
return false;
@@ -1157,7 +1162,7 @@ namespace Game.Entities
}
}
bool ActivateToQuest(Player target)
public bool ActivateToQuest(Player target)
{
if (target.HasQuestForGO((int)GetEntry()))
return true;
@@ -1231,7 +1236,7 @@ namespace Game.Entities
if (m_lootState == LootState.Ready || m_lootState == LootState.JustDeactivated)
return;
RemoveFlag(GameObjectFields.Flags, GameObjectFlags.InUse);
RemoveFlag(GameObjectFlags.InUse);
SetGoState(m_prevGoState);
SetLootState(LootState.JustDeactivated);
@@ -1254,7 +1259,7 @@ namespace Game.Entities
public void SetGoArtKit(byte kit)
{
SetByteValue(GameObjectFields.Bytes1, 2, kit);
SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.ArtKit), kit);
GameObjectData data = Global.ObjectMgr.GetGOData(m_spawnId);
if (data != null)
data.artKit = kit;
@@ -1278,9 +1283,9 @@ namespace Game.Entities
void SwitchDoorOrButton(bool activate, bool alternative = false)
{
if (activate)
SetFlag(GameObjectFields.Flags, GameObjectFlags.InUse);
AddFlag(GameObjectFlags.InUse);
else
RemoveFlag(GameObjectFields.Flags, GameObjectFlags.InUse);
RemoveFlag(GameObjectFlags.InUse);
if (GetGoState() == GameObjectState.Ready) //if closed . open
SetGoState(alternative ? GameObjectState.ActiveAlternative : GameObjectState.Active);
@@ -1423,7 +1428,7 @@ namespace Game.Entities
{
guid = player.GetGUID(); //this slot in now used by player
player.TeleportTo(GetMapId(), x_lowest, y_lowest, GetPositionZ(), GetOrientation(), (TeleportToOptions.NotLeaveTransport | TeleportToOptions.NotLeaveCombat | TeleportToOptions.NotUnSummonPet));
player.SetStandState(UnitStandStateType.SitLowChair + (int)info.Chair.chairheight);
player.SetStandState(UnitStandStateType.SitLowChair + (byte)info.Chair.chairheight);
return;
}
}
@@ -1487,7 +1492,7 @@ namespace Game.Entities
if (trapEntry != 0)
TriggeringLinkedGameObject(trapEntry, user);
SetFlag(GameObjectFields.Flags, GameObjectFlags.InUse);
AddFlag(GameObjectFlags.InUse);
SetLootState(LootState.Activated, user);
// this appear to be ok, however others exist in addition to this that should have custom (ex: 190510, 188692, 187389)
@@ -1864,7 +1869,7 @@ namespace Game.Entities
// fallback, will always work
player.TeleportTo(GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation(), (TeleportToOptions.NotLeaveTransport | TeleportToOptions.NotLeaveCombat | TeleportToOptions.NotUnSummonPet));
player.SetStandState((UnitStandStateType)(UnitStandStateType.SitLowChair + (int)info.BarberChair.chairheight), info.BarberChair.SitAnimKit);
player.SetStandState((UnitStandStateType.SitLowChair + (byte)info.BarberChair.chairheight), info.BarberChair.SitAnimKit);
return;
}
case GameObjectTypes.ArtifactForge:
@@ -1972,16 +1977,16 @@ namespace Game.Entities
return;
// remove immunity flags, to allow spell to target anything
trigger.RemoveFlag(UnitFields.Flags, UnitFlags.ImmuneToNpc | UnitFlags.ImmuneToPc);
trigger.RemoveUnitFlag(UnitFlags.ImmuneToNpc | UnitFlags.ImmuneToPc);
Unit owner = GetOwner();
if (owner)
{
trigger.SetFaction(owner.getFaction());
if (owner.HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable))
trigger.SetFlag(UnitFields.Flags, UnitFlags.PvpAttackable);
trigger.SetFaction(owner.GetFaction());
if (owner.HasUnitFlag(UnitFlags.PvpAttackable))
trigger.AddUnitFlag(UnitFlags.PvpAttackable);
// copy pvp state flags from owner
trigger.SetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, owner.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag));
trigger.SetPvpFlags(owner.GetPvpFlags());
// needed for GO casts for proper target validation checks
trigger.SetOwnerGUID(owner.GetGUID());
trigger.CastSpell(target != null ? target : trigger, spellInfo, triggered, null, null, owner.GetGUID());
@@ -2097,10 +2102,7 @@ namespace Game.Entities
public void SetParentRotation(Quaternion rotation)
{
SetFloatValue(GameObjectFields.ParentRotation + 0, rotation.X);
SetFloatValue(GameObjectFields.ParentRotation + 1, rotation.Y);
SetFloatValue(GameObjectFields.ParentRotation + 2, rotation.Z);
SetFloatValue(GameObjectFields.ParentRotation + 3, rotation.W);
SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.ParentRotation), rotation);
}
public void SetWorldRotationAngles(float z_rot, float y_rot, float x_rot)
@@ -2165,7 +2167,7 @@ namespace Game.Entities
switch (state)
{
case GameObjectDestructibleState.Intact:
RemoveFlag(GameObjectFields.Flags, GameObjectFlags.Damaged | GameObjectFlags.Destroyed);
RemoveFlag(GameObjectFlags.Damaged | GameObjectFlags.Destroyed);
SetDisplayId(m_goInfo.displayId);
if (setHealth)
{
@@ -2179,8 +2181,8 @@ namespace Game.Entities
EventInform(m_goInfo.DestructibleBuilding.DamagedEvent, eventInvoker);
Global.ScriptMgr.OnGameObjectDamaged(this, eventInvoker);
RemoveFlag(GameObjectFields.Flags, GameObjectFlags.Destroyed);
SetFlag(GameObjectFields.Flags, GameObjectFlags.Damaged);
RemoveFlag(GameObjectFlags.Destroyed);
AddFlag(GameObjectFlags.Damaged);
uint modelId = m_goInfo.displayId;
DestructibleModelDataRecord modelData = CliDB.DestructibleModelDataStorage.LookupByKey(m_goInfo.DestructibleBuilding.DestructibleModelRec);
@@ -2211,8 +2213,8 @@ namespace Game.Entities
bg.DestroyGate(eventInvoker, this);
}
RemoveFlag(GameObjectFields.Flags, GameObjectFlags.Damaged);
SetFlag(GameObjectFields.Flags, GameObjectFlags.Destroyed);
RemoveFlag(GameObjectFlags.Damaged);
AddFlag(GameObjectFlags.Destroyed);
uint modelId = m_goInfo.displayId;
DestructibleModelDataRecord modelData = CliDB.DestructibleModelDataStorage.LookupByKey(m_goInfo.DestructibleBuilding.DestructibleModelRec);
@@ -2232,7 +2234,7 @@ namespace Game.Entities
case GameObjectDestructibleState.Rebuilding:
{
EventInform(m_goInfo.DestructibleBuilding.RebuildingEvent, eventInvoker);
RemoveFlag(GameObjectFields.Flags, GameObjectFlags.Damaged | GameObjectFlags.Destroyed);
RemoveFlag(GameObjectFlags.Damaged | GameObjectFlags.Destroyed);
uint modelId = m_goInfo.displayId;
DestructibleModelDataRecord modelData = CliDB.DestructibleModelDataStorage.LookupByKey(m_goInfo.DestructibleBuilding.DestructibleModelRec);
@@ -2277,7 +2279,7 @@ namespace Game.Entities
public void SetGoState(GameObjectState state)
{
SetByteValue(GameObjectFields.Bytes1, 0, (byte)state);
SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.State), (sbyte)state);
Global.ScriptMgr.OnGameObjectStateChanged(this, state);
if (m_model != null && !IsTransport())
{
@@ -2327,7 +2329,7 @@ namespace Game.Entities
public void SetDisplayId(uint displayid)
{
SetUInt32Value(GameObjectFields.DisplayId, displayid);
SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.DisplayID), displayid);
UpdateModel();
}
@@ -2357,7 +2359,8 @@ namespace Game.Entities
case GameObjectTypes.GarrisonBuilding:
case GameObjectTypes.GarrisonPlot:
case GameObjectTypes.PhaseableMo:
return (byte)(GetByteValue(GameObjectFields.Flags, 1) & 0xF);
var flags = (GameObjectFlags)(uint)m_gameObjectData.Flags;
return (byte)(((int)flags >> 8) & 0xF);
default:
break;
}
@@ -2386,7 +2389,10 @@ namespace Game.Entities
if (m_model != null)
GetMap().InsertGameObjectModel(m_model);
ApplyModFlag(GameObjectFields.Flags, GameObjectFlags.MapObject, m_model != null && m_model.isMapObject());
if (m_model != null && m_model.isMapObject())
AddFlag(GameObjectFlags.MapObject);
else
RemoveFlag(GameObjectFlags.MapObject);
}
Player GetLootRecipient()
@@ -2434,7 +2440,7 @@ namespace Game.Entities
m_lootRecipientGroup = unitGroup.GetGUID();
}
bool IsLootAllowedFor(Player player)
public bool IsLootAllowedFor(Player player)
{
if (m_lootRecipient.IsEmpty() && m_lootRecipientGroup.IsEmpty())
return true;
@@ -2455,103 +2461,39 @@ namespace Game.Entities
return ObjectAccessor.GetGameObject(this, m_linkedTrap);
}
public override void BuildValuesUpdate(UpdateType updateType, ByteBuffer data, Player target)
public override void BuildValuesCreate(WorldPacket data, Player target)
{
if (!target)
return;
UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
WorldPacket buffer = new WorldPacket();
bool isStoppableTransport = GetGoType() == GameObjectTypes.Transport && !m_goValue.Transport.StopFrames.Empty();
bool forcedFlags = GetGoType() == GameObjectTypes.Chest && GetGoInfo().Chest.usegrouplootrules != 0 && HasLootRecipient();
bool targetIsGM = target.IsGameMaster();
buffer.WriteUInt8((byte)flags);
m_objectData.WriteCreate(buffer, flags, this, target);
m_gameObjectData.WriteCreate(buffer, flags, this, target);
ByteBuffer fieldBuffer = new ByteBuffer();
UpdateMask updateMask = new UpdateMask(valuesCount);
data.WriteUInt32(buffer.GetSize());
data.WriteBytes(buffer);
}
uint[] flags = UpdateFieldFlags.GameObjectUpdateFieldFlags;
uint visibleFlag = UpdateFieldFlags.Public;
if (GetOwnerGUID() == target.GetGUID())
visibleFlag |= UpdateFieldFlags.Owner;
public override void BuildValuesUpdate(WorldPacket data, Player target)
{
UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
WorldPacket buffer = new WorldPacket();
for (int index = 0; index < valuesCount; ++index)
{
if (_fieldNotifyFlags.HasAnyFlag(flags[index]) ||
((updateType == UpdateType.Values ? _changesMask.Get(index) : updateValues[index].UnsignedValue != 0) && flags[index].HasAnyFlag(visibleFlag)) ||
(index == (int)GameObjectFields.Flags && forcedFlags))
{
updateMask.SetBit(index);
buffer.WriteUInt32(m_values.GetChangedObjectTypeMask());
if (m_values.HasChanged(TypeId.Object))
m_objectData.WriteUpdate(buffer, flags, this, target);
if (index == (int)ObjectFields.DynamicFlags)
{
GameObjectDynamicLowFlags dynFlags = 0;
short pathProgress = -1;
switch (GetGoType())
{
case GameObjectTypes.QuestGiver:
if (ActivateToQuest(target))
dynFlags |= GameObjectDynamicLowFlags.Activate;
break;
case GameObjectTypes.Chest:
case GameObjectTypes.Goober:
if (ActivateToQuest(target) || targetIsGM)
dynFlags |= GameObjectDynamicLowFlags.Activate | GameObjectDynamicLowFlags.Sparkle;
break;
case GameObjectTypes.Generic:
if (ActivateToQuest(target))
dynFlags |= GameObjectDynamicLowFlags.Sparkle;
break;
case GameObjectTypes.Transport:
case GameObjectTypes.MapObjTransport:
uint transportPeriod = GetTransportPeriod();
if (transportPeriod != 0)
{
float timer = (float)m_goValue.Transport.PathProgress % transportPeriod;
pathProgress = (short)(timer / transportPeriod * 65535.0f);
}
break;
default:
break;
}
if (m_values.HasChanged(TypeId.GameObject))
m_gameObjectData.WriteUpdate(buffer, flags, this, target);
fieldBuffer.WriteUInt16(dynFlags);
fieldBuffer.WriteInt16(pathProgress);
}
else if (index == (int)GameObjectFields.Flags)
{
GameObjectFlags _flags = (GameObjectFlags)GetUInt32Value(GameObjectFields.Flags);
if (GetGoType() == GameObjectTypes.Chest)
if (GetGoInfo().Chest.usegrouplootrules != 0 && !IsLootAllowedFor(target))
_flags |= GameObjectFlags.Locked | GameObjectFlags.NotSelectable;
data.WriteUInt32(buffer.GetSize());
data.WriteBytes(buffer);
}
fieldBuffer.WriteUInt32(_flags);
}
else if (index == (int)GameObjectFields.Level)
{
if (isStoppableTransport)
fieldBuffer.WriteUInt32(m_goValue.Transport.PathProgress);
else
fieldBuffer.WriteUInt32(updateValues[index].UnsignedValue);
}
else if (index == (int)GameObjectFields.Bytes1)
{
uint bytes1 = GetUInt32Value(index);
if (isStoppableTransport && GetGoState() == GameObjectState.TransportActive)
{
if (Convert.ToBoolean((m_goValue.Transport.StateUpdateTimer / 20000) & 1))
{
bytes1 &= 0xFFFFFF00;
bytes1 |= (int)GameObjectState.TransportStopped;
}
}
fieldBuffer.WriteUInt32(bytes1);
}
else
fieldBuffer.WriteUInt32(updateValues[index].UnsignedValue);
}
}
updateMask.AppendToPacket(data);
data.WriteBytes(fieldBuffer);
public override void ClearUpdateMask(bool remove)
{
m_values.ClearChangesMask(m_gameObjectData);
base.ClearUpdateMask(remove);
}
public void GetRespawnPosition(out float x, out float y, out float z, out float ori)
@@ -2632,7 +2574,8 @@ namespace Game.Entities
public GameObjectTemplate GetGoInfo() { return m_goInfo; }
public GameObjectTemplateAddon GetTemplateAddon() { return m_goTemplateAddon; }
GameObjectData GetGoData() { return m_goData; }
public GameObjectData GetGoData() { return m_goData; }
public GameObjectValue GetGoValue() { return m_goValue; }
public ulong GetSpawnId() { return m_spawnId; }
@@ -2651,9 +2594,9 @@ namespace Game.Entities
Cypher.Assert(false);
}
m_spawnedByDefault = false; // all object with owner is despawned after delay
SetGuidValue(GameObjectFields.CreatedBy, owner);
SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.CreatedBy), owner);
}
public ObjectGuid GetOwnerGUID() { return GetGuidValue(GameObjectFields.CreatedBy); }
public ObjectGuid GetOwnerGUID() { return m_gameObjectData.CreatedBy; }
public void SetSpellId(uint id)
{
@@ -2688,12 +2631,18 @@ namespace Game.Entities
public void SetSpawnedByDefault(bool b) { m_spawnedByDefault = b; }
public uint GetRespawnDelay() { return m_respawnDelayTime; }
public GameObjectTypes GetGoType() { return (GameObjectTypes)GetByteValue(GameObjectFields.Bytes1, 1); }
public void SetGoType(GameObjectTypes type) { SetByteValue(GameObjectFields.Bytes1, 1, (byte)type); }
public GameObjectState GetGoState() { return (GameObjectState)GetByteValue(GameObjectFields.Bytes1, 0); }
byte GetGoArtKit() { return GetByteValue(GameObjectFields.Bytes1, 2); }
byte GetGoAnimProgress() { return GetByteValue(GameObjectFields.Bytes1, 3); }
public void SetGoAnimProgress(uint animprogress) { SetByteValue(GameObjectFields.Bytes1, 3, (byte)animprogress); }
public bool HasFlag(GameObjectFlags flags) { return (m_gameObjectData.Flags & (uint)flags) != 0; }
public void AddFlag(GameObjectFlags flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.Flags), (uint)flags); }
public void RemoveFlag(GameObjectFlags flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.Flags), (uint)flags); }
public void SetFlags(GameObjectFlags flags) { SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.Flags), (uint)flags); }
public void SetLevel(uint level) { SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.Level), level); }
public GameObjectTypes GetGoType() { return (GameObjectTypes)(sbyte)m_gameObjectData.TypeID; }
public void SetGoType(GameObjectTypes type) { SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.TypeID), (sbyte)type); }
public GameObjectState GetGoState() { return (GameObjectState)(sbyte)m_gameObjectData.State; }
uint GetGoArtKit() { return m_gameObjectData.ArtKit; }
byte GetGoAnimProgress() { return m_gameObjectData.PercentHealth; }
public void SetGoAnimProgress(uint animprogress) { SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.PercentHealth), (byte)animprogress); }
public LootState getLootState() { return m_lootState; }
public LootModes GetLootMode() { return m_LootMode; }
@@ -2732,19 +2681,19 @@ namespace Game.Entities
GameObjectDestructibleState GetDestructibleState()
{
if (HasFlag(GameObjectFields.Flags, GameObjectFlags.Destroyed))
if ((m_gameObjectData.Flags & (uint)GameObjectFlags.Destroyed) != 0)
return GameObjectDestructibleState.Destroyed;
if (HasFlag(GameObjectFields.Flags, GameObjectFlags.Damaged))
if ((m_gameObjectData.Flags & (uint)GameObjectFlags.Damaged) != 0)
return GameObjectDestructibleState.Damaged;
return GameObjectDestructibleState.Intact;
}
public GameObjectAI GetAI() { return m_AI; }
public uint GetDisplayId() { return GetUInt32Value(GameObjectFields.DisplayId); }
public uint GetDisplayId() { return m_gameObjectData.DisplayID; }
uint GetFaction() { return GetUInt32Value(GameObjectFields.Faction); }
public void SetFaction(uint faction) { SetUInt32Value(GameObjectFields.Faction, faction); }
public uint GetFaction() { return m_gameObjectData.FactionTemplate; }
public void SetFaction(uint faction) { SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.FactionTemplate), faction); }
public override float GetStationaryX() { return m_stationaryPosition.GetPositionX(); }
public override float GetStationaryY() { return m_stationaryPosition.GetPositionY(); }
@@ -2766,7 +2715,8 @@ namespace Game.Entities
}
#region Fields
public GameObjectValue m_goValue;
protected GameObjectFieldData m_gameObjectData;
protected GameObjectValue m_goValue;
protected GameObjectTemplate m_goInfo;
protected GameObjectTemplateAddon m_goTemplateAddon;
GameObjectData m_goData;
+60 -17
View File
@@ -17,6 +17,7 @@
using Framework.Constants;
using Framework.Database;
using Game.Network;
namespace Game.Entities
{
@@ -27,8 +28,7 @@ namespace Game.Entities
objectTypeMask |= TypeMask.Container;
objectTypeId = TypeId.Container;
valuesCount = (int)ContainerFields.End;
_dynamicValuesCount = (int)ItemDynamicFields.End;
m_containerData = new ContainerData();
}
public override void Dispose()
@@ -86,20 +86,20 @@ namespace Game.Entities
if (owner)
{
SetGuidValue(ItemFields.Owner, owner.GetGUID());
SetGuidValue(ItemFields.Contained, owner.GetGUID());
SetOwnerGUID(owner.GetGUID());
SetContainedIn(owner.GetGUID());
}
SetUInt32Value(ItemFields.MaxDurability, itemProto.MaxDurability);
SetUInt32Value(ItemFields.Durability, itemProto.MaxDurability);
SetUInt32Value(ItemFields.StackCount, 1);
SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.MaxDurability), itemProto.MaxDurability);
SetDurability(itemProto.MaxDurability);
SetCount(1);
// Setting the number of Slots the Container has
SetUInt32Value(ContainerFields.NumSlots, itemProto.GetContainerSlots());
SetBagSize(itemProto.GetContainerSlots());
// Cleaning 20 slots
for (byte i = 0; i < ItemConst.MaxBagSize; ++i)
SetGuidValue(ContainerFields.Slot1 + (i * 4), ObjectGuid.Empty);
SetSlot(i, ObjectGuid.Empty);
m_bagslot = new Item[ItemConst.MaxBagSize];
return true;
@@ -111,11 +111,11 @@ namespace Game.Entities
return false;
ItemTemplate itemProto = GetTemplate(); // checked in Item.LoadFromDB
SetUInt32Value(ContainerFields.NumSlots, itemProto.GetContainerSlots());
SetBagSize(itemProto.GetContainerSlots());
// cleanup bag content related item value fields (its will be filled correctly from `character_inventory`)
for (byte i = 0; i < ItemConst.MaxBagSize; ++i)
{
SetGuidValue(ContainerFields.Slot1 + (i * 4), ObjectGuid.Empty);
SetSlot(i, ObjectGuid.Empty);
m_bagslot[i] = null;
}
return true;
@@ -144,9 +144,9 @@ namespace Game.Entities
{
if (m_bagslot[slot] != null)
m_bagslot[slot].SetContainer(null);
m_bagslot[slot] = null;
SetGuidValue(ContainerFields.Slot1 + (slot * 4), ObjectGuid.Empty);
SetSlot(slot, ObjectGuid.Empty);
}
public void StoreItem(byte slot, Item pItem, bool update)
@@ -154,9 +154,9 @@ namespace Game.Entities
if (pItem != null && pItem.GetGUID() != GetGUID())
{
m_bagslot[slot] = pItem;
SetGuidValue(ContainerFields.Slot1 + (slot * 4), pItem.GetGUID());
pItem.SetGuidValue(ItemFields.Contained, GetGUID());
pItem.SetGuidValue(ItemFields.Owner, GetOwnerGUID());
SetSlot(slot, pItem.GetGUID());
pItem.SetContainedIn(GetGUID());
pItem.SetOwnerGUID(GetOwnerGUID());
pItem.SetContainer(this);
pItem.SetSlot(slot);
}
@@ -171,6 +171,45 @@ namespace Game.Entities
m_bagslot[i].BuildCreateUpdateBlockForPlayer(data, target);
}
public override void BuildValuesCreate(WorldPacket data, Player target)
{
UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
WorldPacket buffer = new WorldPacket();
buffer.WriteUInt8((byte)flags);
m_objectData.WriteCreate(buffer, flags, this, target);
m_itemData.WriteCreate(buffer, flags, this, target);
m_containerData.WriteCreate(buffer, flags, this, target);
data.WriteUInt32(buffer.GetSize());
data.WriteBytes(buffer);
}
public override void BuildValuesUpdate(WorldPacket data, Player target)
{
UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
WorldPacket buffer = new WorldPacket();
buffer.WriteUInt32(m_values.GetChangedObjectTypeMask());
if (m_values.HasChanged(TypeId.Object))
m_objectData.WriteUpdate(buffer, flags, this, target);
if (m_values.HasChanged(TypeId.Item))
m_itemData.WriteUpdate(buffer, flags, this, target);
if (m_values.HasChanged(TypeId.Container))
m_containerData.WriteUpdate(buffer, flags, this, target);
data.WriteUInt32(buffer.GetSize());
data.WriteBytes(buffer);
}
public override void ClearUpdateMask(bool remove)
{
m_values.ClearChangesMask(m_containerData);
base.ClearUpdateMask(remove);
}
public bool IsEmpty()
{
for (var i = 0; i < GetBagSize(); ++i)
@@ -243,13 +282,17 @@ namespace Game.Entities
return null;
}
public uint GetBagSize() { return GetUInt32Value(ContainerFields.NumSlots); }
public uint GetBagSize() { return m_containerData.NumSlots; }
void SetBagSize(uint numSlots) { SetUpdateFieldValue(m_values.ModifyValue(m_containerData).ModifyValue(m_containerData.NumSlots), numSlots); }
void SetSlot(int slot, ObjectGuid guid) { SetUpdateFieldValue(ref m_values.ModifyValue(m_containerData).ModifyValue(m_containerData.Slots, slot), guid); }
public static Item NewItemOrBag(ItemTemplate proto)
{
return (proto.GetInventoryType() == InventoryType.Bag) ? new Bag() : new Item();
}
ContainerData m_containerData;
Item[] m_bagslot = new Item[36];
}
}
File diff suppressed because it is too large Load Diff
+39 -161
View File
@@ -22,148 +22,79 @@ using System.Collections.Generic;
namespace Game.Entities
{
public class ItemEnchantment
public class ItemEnchantmentManager
{
static ItemEnchantment()
public static void LoadItemRandomBonusListTemplates()
{
RandomItemEnch = new EnchantmentStore();
}
uint oldMSTime = Time.GetMSTime();
public static void LoadRandomEnchantmentsTable()
{
// for reload case
RandomItemEnch[ItemRandomEnchantmentType.Property].Clear();
RandomItemEnch[ItemRandomEnchantmentType.Suffix].Clear();
_storage.Clear();
// 0 1 2 3
SQLResult result = DB.World.Query("SELECT entry, type, ench, chance FROM item_enchantment_template");
// 0 1 2
SQLResult result = DB.World.Query("SELECT Id, BonusListID, Chance FROM item_random_bonus_list_template");
if (result.IsEmpty())
{
Log.outError(LogFilter.Player, "Loaded 0 Item Enchantment definitions. DB table `item_enchantment_template` is empty.");
return;
}
uint count = 0;
do
{
uint entry = result.Read<uint>(0);
ItemRandomEnchantmentType type = (ItemRandomEnchantmentType)result.Read<byte>(1);
uint ench = result.Read<uint>(2);
float chance = result.Read<float>(3);
uint id = result.Read<uint>(0);
uint bonusListId = result.Read<uint>(1);
float chance = result.Read<float>(2);
switch (type)
if (Global.DB2Mgr.GetItemBonusList(bonusListId) == null)
{
case ItemRandomEnchantmentType.Property:
if (!CliDB.ItemRandomPropertiesStorage.ContainsKey(ench))
{
Log.outError(LogFilter.Sql, "Property {0} used in `item_enchantment_template` by entry {1} doesn't have exist in ItemRandomProperties.db2", ench, entry);
continue;
}
break;
case ItemRandomEnchantmentType.Suffix:
if (!CliDB.ItemRandomSuffixStorage.ContainsKey(ench))
{
Log.outError(LogFilter.Sql, "Suffix {0} used in `item_enchantment_template` by entry {1} doesn't have exist in ItemRandomSuffix.db2", ench, entry);
continue;
}
break;
case ItemRandomEnchantmentType.BonusList:
if (Global.DB2Mgr.GetItemBonusList(ench) == null)
{
Log.outError(LogFilter.Sql, "Bonus list {0} used in `item_enchantment_template` by entry {1} doesn't have exist in ItemBonus.db2", ench, entry);
continue;
}
break;
default:
Log.outError(LogFilter.Sql, "Invalid random enchantment type specified in `item_enchantment_template` table for `entry` {0} `ench` {1}", entry, ench);
break;
Log.outError(LogFilter.Sql, $"Bonus list {bonusListId} used in `item_random_bonus_list_template` by id {id} doesn't have exist in ItemBonus.db2");
continue;
}
if (chance < 0.000001f || chance > 100.0f)
{
Log.outError(LogFilter.Sql, "Random item enchantment for entry {0} type {1} ench {2} has invalid chance {3}", entry, type, ench, chance);
Log.outError(LogFilter.Sql, $"Bonus list {bonusListId} used in `item_random_bonus_list_template` by id {id} has invalid chance {chance}");
continue;
}
switch (type)
{
case ItemRandomEnchantmentType.Property:
RandomItemEnch[ItemRandomEnchantmentType.Property].Add(entry, new EnchStoreItem(type, ench, chance));
break;
case ItemRandomEnchantmentType.Suffix:
case ItemRandomEnchantmentType.BonusList: // random bonus lists use RandomSuffix field in Item-sparse.db2
RandomItemEnch[ItemRandomEnchantmentType.Suffix].Add(entry, new EnchStoreItem(type, ench, chance));
break;
default:
break;
}
if (!_storage.ContainsKey(id))
_storage[id] = new RandomBonusListIds();
RandomBonusListIds ids = _storage[id];
ids.BonusListIDs.Add(bonusListId);
ids.Chances.Add(chance);
++count;
} while (result.NextRow());
Log.outInfo(LogFilter.Player, "Loaded {0} Item Enchantment definitions", count);
Log.outInfo(LogFilter.Player, $"Loaded {count} Random item bonus list definitions in {Time.GetMSTimeDiffToNow(oldMSTime)} ms");
}
public static ItemRandomEnchantmentId GetItemEnchantMod(int entry, ItemRandomEnchantmentType type)
{
if (entry == 0)
return ItemRandomEnchantmentId.Empty;
if (entry == -1)
return ItemRandomEnchantmentId.Empty;
var tab = RandomItemEnch[type].LookupByKey(entry);
if (tab == null)
{
Log.outError(LogFilter.Player, "Item RandomProperty / RandomSuffix id #{0} used in `item_template` but it does not have records in `item_enchantment_template` table.", entry);
return ItemRandomEnchantmentId.Empty;
}
var selectedItem = tab.SelectRandomElementByWeight(enchant => enchant.chance);
return new ItemRandomEnchantmentId(selectedItem.type, selectedItem.ench);
}
public static ItemRandomEnchantmentId GenerateItemRandomPropertyId(uint item_id)
public static uint GenerateItemRandomBonusListId(uint item_id)
{
ItemTemplate itemProto = Global.ObjectMgr.GetItemTemplate(item_id);
if (itemProto == null)
return ItemRandomEnchantmentId.Empty;
return 0;
// item must have one from this field values not null if it can have random enchantments
if (itemProto.GetRandomProperty() == 0 && itemProto.GetRandomSuffix() == 0)
return ItemRandomEnchantmentId.Empty;
if (itemProto.RandomBonusListTemplateId == 0)
return 0;
// item can have not null only one from field values
if (itemProto.GetRandomProperty() != 0 && itemProto.GetRandomSuffix() != 0)
var tab = _storage.LookupByKey(itemProto.RandomBonusListTemplateId);
if (tab == null)
{
Log.outError(LogFilter.Sql, "Item template {0} have RandomProperty == {1} and RandomSuffix == {2}, but must have one from field =0", itemProto.GetId(), itemProto.GetRandomProperty(), itemProto.GetRandomSuffix());
return ItemRandomEnchantmentId.Empty;
Log.outError(LogFilter.Sql, $"Item RandomBonusListTemplateId id {itemProto.RandomBonusListTemplateId} used in `item_template_addon` but it does not have records in `item_random_bonus_list_template` table.");
return 0;
}
// RandomProperty case
if (itemProto.GetRandomProperty() != 0)
return GetItemEnchantMod((int)itemProto.GetRandomProperty(), ItemRandomEnchantmentType.Property);
// RandomSuffix case
else
return GetItemEnchantMod((int)itemProto.GetRandomSuffix(), ItemRandomEnchantmentType.Suffix);
}
public static uint GenerateEnchSuffixFactor(uint item_id)
{
ItemTemplate itemProto = Global.ObjectMgr.GetItemTemplate(item_id);
if (itemProto == null)
return 0;
if (itemProto.GetRandomSuffix() == 0)
return 0;
return GetRandomPropertyPoints(itemProto.GetBaseItemLevel(), itemProto.GetQuality(), itemProto.GetInventoryType(), itemProto.GetSubClass());
//todo fix me this is ulgy
return tab.BonusListIDs.SelectRandomElementByWeight(x => (float)tab.Chances[tab.BonusListIDs.IndexOf(x)]);
}
public static uint GetRandomPropertyPoints(uint itemLevel, ItemQuality quality, InventoryType inventoryType, uint subClass)
{
{
uint propIndex;
switch (inventoryType)
{
case InventoryType.Head:
@@ -208,11 +139,11 @@ namespace Game.Entities
default:
return 0;
}
RandPropPointsRecord randPropPointsEntry = CliDB.RandPropPointsStorage.LookupByKey(itemLevel);
if (randPropPointsEntry == null)
return 0;
// Select rare/epic modifier
switch (quality)
{
case ItemQuality.Uncommon:
@@ -225,69 +156,16 @@ namespace Game.Entities
case ItemQuality.Artifact:
return randPropPointsEntry.Epic[propIndex];
}
return 0;
}
static EnchantmentStore RandomItemEnch;
public class EnchStoreItem
{
public EnchStoreItem()
{
ench = 0;
chance = 0;
}
public EnchStoreItem(ItemRandomEnchantmentType _type, uint _ench, float _chance)
{
type = _type;
ench = _ench;
chance = _chance;
}
public ItemRandomEnchantmentType type;
public uint ench;
public float chance;
}
class EnchantmentStore
{
public EnchantmentStore()
{
_data[(byte)ItemRandomEnchantmentType.Property] = new MultiMap<uint, EnchStoreItem>();
_data[(byte)ItemRandomEnchantmentType.Suffix] = new MultiMap<uint, EnchStoreItem>();
}
public MultiMap<uint, EnchStoreItem> this[ItemRandomEnchantmentType type]
{
get
{
//(type != ItemRandomEnchantmentType.BonusList, "Random bonus lists do not have their own storage, use Suffix for them");
return _data[(byte)type];
}
}
MultiMap<uint, EnchStoreItem>[] _data = new MultiMap<uint, EnchStoreItem>[2];
}
static Dictionary<uint, RandomBonusListIds> _storage = new Dictionary<uint, RandomBonusListIds>();
}
public struct ItemRandomEnchantmentId
public class RandomBonusListIds
{
public static ItemRandomEnchantmentId Empty = default(ItemRandomEnchantmentId);
public ItemRandomEnchantmentId(ItemRandomEnchantmentType type, uint id)
{
Type = type;
Id = id;
}
public ItemRandomEnchantmentType Type;
public uint Id;
}
public enum ItemRandomEnchantmentType
{
Property = 0,
Suffix = 1,
BonusList = 2
public List<uint> BonusListIDs = new List<uint>();
public List<double> Chances = new List<double>();
}
}
+3 -4
View File
@@ -223,9 +223,9 @@ namespace Game.Entities
if (GetFlags().HasAnyFlag(ItemFlags.IsBoundToAccount) && alwaysAllowBoundToAccount)
return true;
uint spec = player.GetUInt32Value(ActivePlayerFields.LootSpecId);
uint spec = player.GetLootSpecId();
if (spec == 0)
spec = player.GetUInt32Value(PlayerFields.CurrentSpecId);
spec = player.GetPrimarySpecialization();
if (spec == 0)
spec = player.GetDefaultSpecId();
@@ -295,8 +295,6 @@ namespace Game.Entities
public uint GetPageText() { return ExtendedData.PageID; }
public uint GetStartQuest() { return ExtendedData.StartQuestID; }
public uint GetLockID() { return ExtendedData.LockID; }
public uint GetRandomProperty() { return ExtendedData.RandomSelect; }
public uint GetRandomSuffix() { return ExtendedData.ItemRandomSuffixGroupID; }
public uint GetItemSet() { return ExtendedData.ItemSet; }
public uint GetArea() { return ExtendedData.ZoneBound; }
public uint GetMap() { return ExtendedData.InstanceBound; }
@@ -345,6 +343,7 @@ namespace Game.Entities
public uint MaxMoneyLoot;
public ItemFlagsCustom FlagsCu;
public float SpellPPMRate;
public uint RandomBonusListTemplateId;
public BitArray[] Specializations = new BitArray[3];
public uint ItemSpecClassMask;
@@ -56,13 +56,13 @@ namespace Game.Entities
if (buffer.WriteBit(!outOfRangeGUIDs.Empty()))
{
buffer.WriteUInt16(0); // object limit to instantly destroy - objects before this index on m_outOfRangeGUIDs list get "smoothly phased out"
buffer.WriteUInt32(outOfRangeGUIDs.Count);
buffer.WriteInt32(outOfRangeGUIDs.Count);
foreach (var guid in outOfRangeGUIDs)
buffer.WritePackedGuid(guid);
}
var bytes = data.GetData();
buffer.WriteUInt32(bytes.Length);
buffer.WriteInt32(bytes.Length);
buffer.WriteBytes(bytes);
packet.Data = buffer.GetData();
@@ -0,0 +1,453 @@
/*
* Copyright (C) 2012-2019 CypherCore <http://github.com/CypherCore>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using Framework.Constants;
using Game.Network;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace Game.Entities
{
public class UpdateFieldHolder
{
public UpdateFieldHolder(WorldObject owner) { _owner = owner; }
public BaseUpdateData<T> ModifyValue<T>(BaseUpdateData<T> updateData)
{
_changesMask.Set(updateData.Bit);
return updateData;
}
public void ClearChangesMask<T>(BaseUpdateData<T> updateData)
{
_changesMask.Reset(updateData.Bit);
}
public void ClearChangesMask<T, U>(BaseUpdateData<T> updateData, ref UpdateField<U> updateField) where T : new() where U : new()
{
_changesMask.Reset(updateData.Bit);
IHasChangesMask hasChangesMask = (IHasChangesMask)updateField._value;
if (hasChangesMask != null)
hasChangesMask.ClearChangesMask();
}
public uint GetChangedObjectTypeMask()
{
return _changesMask.GetBlock(0);
}
public bool HasChanged(TypeId index)
{
return _changesMask[(int)index];
}
UpdateMask _changesMask = new UpdateMask((int)TypeId.Max);
WorldObject _owner;
}
public interface IUpdateField<T>
{
void SetValue(T value);
T GetValue();
}
public class UpdateField<T> : IUpdateField<T> where T : new()
{
public T _value;
public int BlockBit;
public int Bit;
public UpdateField(int blockBit, int bit)
{
BlockBit = blockBit;
Bit = bit;
_value = new T();
}
public static implicit operator T(UpdateField<T> updateField)
{
return updateField._value;
}
public void SetValue(T value) { _value = value; }
public T GetValue() { return _value; }
}
public class UpdateFieldArray<T> where T : new()
{
public T[] _values;
public int FirstElementBit;
public int Bit;
public UpdateFieldArray(uint size, int bit, int firstElementBit)
{
_values = new T[size];
for (var i = 0; i < size; ++i)
_values[i] = new T();
Bit = bit;
FirstElementBit = firstElementBit;
}
public T this[int index]
{
get
{
return _values[index];
}
set
{
_values[index] = value;
}
}
public int GetSize() { return _values.Length; }
public IEnumerator<T> GetEnumerator()
{
foreach (var obj in _values)
yield return obj;
}
}
public class DynamicUpdateField<T> where T : new()
{
public List<T> _values;
public List<uint> _updateMask;
public int BlockBit;
public int Bit;
public DynamicUpdateField()
{
_values = new List<T>();
_updateMask = new List<uint>();
BlockBit = -1;
Bit = -1;
}
public DynamicUpdateField(int blockBit, int bit)
{
_values = new List<T>();
_updateMask = new List<uint>();
BlockBit = blockBit;
Bit = bit;
}
public int FindIndex(T value)
{
return _values.IndexOf(value);
}
public bool HasChanged(int index)
{
return (_updateMask[index / 32] & (1 << (index % 32))) != 0;
}
public void WriteUpdateMask(WorldPacket data)
{
data.WriteBits(_values.Count, 32);
if (_values.Count > 32)
{
if (data.HasUnfinishedBitPack())
for (int block = 0; block < _values.Count / 32; ++block)
data.WriteBits(_updateMask[block], 32);
else
for (int block = 0; block < _values.Count / 32; ++block)
data.WriteUInt32(_updateMask[block]);
}
if ((_values.Count % 32) != 0)
data.WriteBits(_updateMask.Last(), _values.Count % 32);
}
public void ClearChangesMask()
{
for (var i = 0; i < _updateMask.Count; ++i)
_updateMask[i] = 0;
}
public void AddValue(T value)
{
MarkChanged(_values.Count);
if (value is IHasChangesMask)
{
IHasChangesMask hasChanges = (IHasChangesMask)value;
if (hasChanges != null)
hasChanges.GetUpdateMask().SetAll();
}
_values.Add(value);
}
public void InsertValue(int index, T value)
{
_values.Insert(index, value);
for (int i = index; i < _values.Count; ++i)
{
MarkChanged(i);
// also mark all fields of value as changed
IHasChangesMask hasChangesMask = (IHasChangesMask)_values[i];
if (hasChangesMask != null)
hasChangesMask.GetUpdateMask().SetAll();
}
}
public void RemoveValue(int index)
{
// remove by shifting entire container - client might rely on values being sorted for certain fields
_values.RemoveAt(index);
for (int i = index; i < _values.Count; ++i)
{
MarkChanged(i);
// also mark all fields of value as changed
IHasChangesMask hasChanges = (IHasChangesMask)_values[i];
if (hasChanges != null)
hasChanges.GetUpdateMask().SetAll();
}
if ((_values.Count % 32) != 0)
_updateMask[UpdateMask.GetBlockIndex(_values.Count)] &= (uint)~UpdateMask.GetBlockFlag(_values.Count);
else
_updateMask.RemoveAt(_updateMask.Count - 1);
}
public void Clear()
{
_values.Clear();
_updateMask.Clear();
}
public void MarkChanged(int index)
{
int block = UpdateMask.GetBlockIndex(index);
if (block >= _updateMask.Count)
_updateMask.Add(0);
_updateMask[block] |= (uint)UpdateMask.GetBlockFlag(index);
}
public void ClearChanged(int index)
{
int block = UpdateMask.GetBlockIndex(index);
if (block >= _updateMask.Count)
_updateMask.Add(0);
_updateMask[block] &= ~(uint)UpdateMask.GetBlockFlag(index);
}
public int Size()
{
return _values.Count;
}
public T this[int index]
{
get
{
if (_values.Count <= index)
_values.Add(new T());
return _values[index];
}
set
{
_values[index] = value;
}
}
public static implicit operator List<T>(DynamicUpdateField<T> updateField)
{
return updateField._values;
}
public IEnumerator<T> GetEnumerator()
{
foreach (var obj in _values)
yield return obj;
}
}
public interface IHasChangesMask
{
void ClearChangesMask();
UpdateMask GetUpdateMask();
}
public abstract class BaseUpdateData<T> : IHasChangesMask
{
public UpdateMask _changesMask;
public int _blockBit;
public int Bit;
public BaseUpdateData(int blockBit, TypeId bit, int changeMask)
{
_blockBit = blockBit;
Bit = (int)bit;
_changesMask = new UpdateMask(changeMask);
}
public BaseUpdateData(int changeMask)
{
_changesMask = new UpdateMask(changeMask);
}
public abstract void WriteCreate(WorldPacket data, UpdateFieldFlag fieldVisibilityFlags, T owner, Player receiver);
public abstract void WriteUpdate(WorldPacket data, UpdateFieldFlag fieldVisibilityFlags, T owner, Player receiver);
public abstract void ClearChangesMask();
public UpdateMask GetUpdateMask()
{
return _changesMask;
}
public void ClearChanged<U>(UpdateField<U> updateField) where U : new()
{
_changesMask.Reset(updateField.Bit);
}
public void ClearChanged<U>(UpdateFieldArray<U> updateField, int index) where U : new()
{
_changesMask.Reset(updateField.Bit);
_changesMask.Reset(updateField.FirstElementBit + index);
}
public void ClearChanged<U>(DynamicUpdateField<U> updateField, int index) where U : new()
{
_changesMask.Reset(Bit);
updateField.ClearChanged(index);
}
public void ClearChangesMask<U>(UpdateField<U> updateField) where U : new()
{
if (typeof(U).BaseType == typeof(IHasChangesMask))
((IHasChangesMask)updateField._value).ClearChangesMask();
}
public void ClearChangesMask<U>(UpdateFieldArray<U> updateField) where U : new()
{
if (typeof(U).BaseType == typeof(IHasChangesMask))
{
for (int i = 0; i < updateField.GetSize(); ++i)
((IHasChangesMask)updateField[i]).ClearChangesMask();
}
}
public void ClearChangesMask<U>(DynamicUpdateField<U> updateField) where U : new()
{
if (typeof(U).BaseType == typeof(IHasChangesMask))
{
for (int i = 0; i < updateField.Size(); ++i)
((IHasChangesMask)updateField[i]).ClearChangesMask();
updateField.ClearChangesMask();
}
}
public UpdateField<UU> ModifyValue<U, UU>(Expression<Func<U, UpdateField<UU>>> expression) where UU : new()
{
var fieldInfo = ((MemberExpression)expression.Body).Member as FieldInfo;
if (fieldInfo == null)
throw new ArgumentException("The lambda expression 'property' should point to a valid Property");
var updateField = (UpdateField<UU>)fieldInfo.GetValue(this);
_changesMask.Set(updateField.BlockBit);
_changesMask.Set(updateField.Bit);
return updateField;
}
public ref UU ModifyValue<U, UU>(Expression<Func<U, UpdateFieldArray<UU>>> expression, int index) where UU : new()
{
var fieldInfo = ((MemberExpression)expression.Body).Member as FieldInfo;
if (fieldInfo == null)
throw new ArgumentException("The lambda expression 'property' should point to a valid Property");
var updateFieldArray = (UpdateFieldArray<UU>)fieldInfo.GetValue(this);
_changesMask.Set(updateFieldArray.Bit);
_changesMask.Set(updateFieldArray.FirstElementBit + index);
return ref updateFieldArray._values[index];
}
public UpdateField<U> ModifyValue<U>(UpdateField<U> updateField) where U : new()
{
_changesMask.Set(updateField.BlockBit);
_changesMask.Set(updateField.Bit);
return updateField;
}
public ref U ModifyValue<U>(UpdateFieldArray<U> updateField, int index) where U : new()
{
_changesMask.Set(updateField.Bit);
_changesMask.Set(updateField.FirstElementBit + index);
return ref updateField._values[index];
}
public DynamicUpdateField<U> ModifyValue<U>(DynamicUpdateField<U> updateField) where U : new()
{
_changesMask.Set(updateField.BlockBit);
_changesMask.Set(updateField.Bit);
return updateField;
}
public DynamicUpdateFieldSetter<U> ModifyValue<U>(DynamicUpdateField<U> updateField, int index) where U : new()
{
if (index >= updateField._values.Count)
{
// fill with zeros until reaching desired slot
updateField._values.Resize((uint)index + 1);
updateField._updateMask.Resize((uint)(updateField._values.Count + 31) / 32);
}
_changesMask.Set(updateField.BlockBit);
_changesMask.Set(updateField.Bit);
updateField.MarkChanged(index);
return new DynamicUpdateFieldSetter<U>(updateField, index);
}
}
public class DynamicUpdateFieldSetter<T> : IUpdateField<T> where T : new()
{
public DynamicUpdateFieldSetter(DynamicUpdateField<T> dynamicUpdateField, int index)
{
_dynamicUpdateField = dynamicUpdateField;
_index = index;
}
public void SetValue(T value)
{
_dynamicUpdateField[_index] = value;
}
public T GetValue() { return _dynamicUpdateField[_index]; }
public static implicit operator T(DynamicUpdateFieldSetter<T> dynamicUpdateFieldSetter)
{
return dynamicUpdateFieldSetter.GetValue();
}
DynamicUpdateField<T> _dynamicUpdateField;
int _index;
}
}
File diff suppressed because it is too large Load Diff
@@ -24,88 +24,127 @@ namespace Game.Entities
{
public class UpdateMask
{
public UpdateMask(uint valuesCount = 0)
{
_fieldCount = valuesCount;
_blockCount = (valuesCount + 32 - 1) / 32;
int _blockCount;
int _blocksMaskCount;
uint[] _blocks;
uint[] _blocksMask;
_mask = new BitArray((int)valuesCount, false);
public UpdateMask(int bits, uint[] input = null)
{
_blockCount = (bits + 31) / 32;
_blocksMaskCount = (_blockCount + 31) / 32;
_blocks = new uint[_blockCount];
_blocksMask = new uint[_blocksMaskCount];
if (input != null)
{
int block = 0;
for (; block < input.Length; ++block)
if ((_blocks[block] = input[block]) != 0)
_blocksMask[GetBlockIndex(block)] |= (uint)GetBlockFlag(block);
for (; block < _blockCount; ++block)
_blocks[block] = 0;
}
}
public void SetCount(int valuesCount)
public uint GetBlocksMask(uint index)
{
_fieldCount = (uint)valuesCount;
_blockCount = (uint)(valuesCount + 32 - 1) / 32;
_mask = new BitArray((int)valuesCount, false);
return _blocksMask[index];
}
public uint GetCount() { return _fieldCount; }
public virtual void AppendToPacket(ByteBuffer data)
public uint GetBlock(uint index)
{
data.WriteUInt8(_blockCount);
var maskArray = new byte[_blockCount << 2];
_mask.CopyTo(maskArray, 0);
data.WriteBytes(maskArray);
return _blocks[index];
}
public bool GetBit(int index)
public bool this[int index]
{
return _mask.Get(index);
get
{
return (_blocks[index / 32] & (1 << (index % 32))) != 0;
}
}
public void SetBit(int index)
public void Reset(int index)
{
_mask.Set(index, true);
int blockIndex = GetBlockIndex(index);
if ((_blocks[blockIndex] &= ~(uint)GetBlockFlag(index)) == 0)
_blocksMask[GetBlockIndex(blockIndex)] &= ~(uint)GetBlockFlag(blockIndex);
}
void UnsetBit(int index)
public void ResetAll()
{
_mask.Set(index, false);
Array.Clear(_blocks, 0, _blocks.Length);
Array.Clear(_blocksMask, 0, _blocksMask.Length);
}
public void Clear()
public void Set(int index)
{
_mask.SetAll(false);
int blockIndex = GetBlockIndex(index);
_blocks[blockIndex] |= (uint)GetBlockFlag(index);
_blocksMask[GetBlockIndex(blockIndex)] |= (uint)GetBlockFlag(blockIndex);
}
protected uint _fieldCount;
protected uint _blockCount;
protected BitArray _mask;
}
public class DynamicUpdateMask : UpdateMask
{
public DynamicUpdateMask(uint valuesCount) : base(valuesCount) { }
public void EncodeDynamicFieldChangeType(DynamicFieldChangeType changeType, UpdateType updateType)
public void SetAll()
{
_updateType = updateType;
DynamicFieldChangeType = (uint)(_blockCount | ((uint)(changeType & Entities.DynamicFieldChangeType.ValueAndSizeChanged) * ((3 - (int)updateType /*this part evaluates to 0 if update type is not VALUES*/) / 3)));
for (int i = 0; i < _blocksMaskCount; ++i)
_blocksMask[i] = 0xFFFFFFFF;
for (int i = 0; i < _blockCount; ++i)
_blocks[i] = 0xFFFFFFFF;
if ((_blocksMaskCount % 32) != 0)
{
int unused = 32 - (_blocksMaskCount % 32);
_blocksMask[_blocksMaskCount - 1] &= (0xFFFFFFFF >> unused);
}
if ((_blockCount % 32) != 0)
{
int unused = 32 - (_blockCount % 32);
_blocks[_blockCount - 1] &= (0xFFFFFFFF >> unused);
}
}
public override void AppendToPacket(ByteBuffer data)
public void AND(UpdateMask right)
{
data.WriteUInt16(DynamicFieldChangeType);
if (DynamicFieldChangeType.HasAnyFlag((uint)Entities.DynamicFieldChangeType.ValueAndSizeChanged) && _updateType == UpdateType.Values)
data.WriteUInt32(_fieldCount);
for (int i = 0; i < _blocksMaskCount; ++i)
_blocksMask[i] &= right._blocksMask[i];
var maskArray = new byte[_blockCount << 2];
_mask.CopyTo(maskArray, 0);
data.WriteBytes(maskArray);
for (int i = 0; i < _blockCount; ++i)
{
if (!Convert.ToBoolean(_blocks[i] &= right._blocks[i]))
_blocksMask[GetBlockIndex(i)] &= ~(uint)GetBlockFlag(i);
}
}
public uint DynamicFieldChangeType;
public UpdateType _updateType;
}
public void OR(UpdateMask right)
{
for (int i = 0; i < _blocksMaskCount; ++i)
_blocksMask[i] |= right._blocksMask[i];
public enum DynamicFieldChangeType
{
Unchanged = 0,
ValueChanged = 0x7FFF,
ValueAndSizeChanged = 0x8000
for (int i = 0; i < _blockCount; ++i)
_blocks[i] |= right._blocks[i];
}
public static UpdateMask operator &(UpdateMask left, UpdateMask right)
{
UpdateMask result = left;
result.AND(right);
return result;
}
public static UpdateMask operator |(UpdateMask left, UpdateMask right)
{
UpdateMask result = left;
result.OR(right);
return result;
}
//helpers
public static int GetBlockIndex(int bit) { return bit / 32; }
public static int GetBlockFlag(int bit) { return 1 << (bit % 32); }
}
}
File diff suppressed because it is too large Load Diff
+37 -33
View File
@@ -174,8 +174,8 @@ namespace Game.Entities
PhasingHandler.InheritPhaseShift(this, owner);
setPetType(petType);
SetFaction(owner.getFaction());
SetUInt32Value(UnitFields.CreatedBySpell, summonSpellId);
SetFaction(owner.GetFaction());
SetCreatedBySpell(summonSpellId);
float px, py, pz;
if (IsCritter())
@@ -199,7 +199,8 @@ namespace Game.Entities
SetDisplayId(result.Read<uint>(3));
SetNativeDisplayId(result.Read<uint>(3));
uint petlevel = result.Read<ushort>(4);
SetUInt64Value(UnitFields.NpcFlags, (ulong)NPCFlags.None);
SetNpcFlags(NPCFlags.None);
SetNpcFlags2(NPCFlags2.None);
SetName(result.Read<string>(8));
switch (getPetType())
@@ -207,16 +208,15 @@ namespace Game.Entities
case PetType.Summon:
petlevel = owner.getLevel();
SetByteValue(UnitFields.Bytes0, 1, (byte)Class.Mage);
SetUInt32Value(UnitFields.Flags, (uint)UnitFlags.PvpAttackable); // this enables popup window (pet dismiss, cancel)
SetClass(Class.Mage);
SetUnitFlags(UnitFlags.PvpAttackable); // this enables popup window (pet dismiss, cancel)
break;
case PetType.Hunter:
SetByteValue(UnitFields.Bytes0, 1, (byte)Class.Warrior);
SetByteValue(UnitFields.Bytes0, 3, (byte)Gender.None);
SetClass(Class.Warrior);
SetGender(Gender.None);
SetSheath(SheathState.Melee);
SetByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PetFlags, (result.Read<bool>(9) ? UnitPetFlags.CanBeAbandoned : UnitPetFlags.CanBeRenamed | UnitPetFlags.CanBeAbandoned));
SetUInt32Value(UnitFields.Flags, (uint)UnitFlags.PvpAttackable); // this enables popup window (pet abandon, cancel)
SetPetFlags(result.Read<bool>(9) ? UnitPetFlags.CanBeAbandoned : UnitPetFlags.CanBeRenamed | UnitPetFlags.CanBeAbandoned);
SetUnitFlags(UnitFlags.PvpAttackable); // this enables popup window (pet abandon, cancel)
break;
default:
if (!IsPetGhoul())
@@ -224,11 +224,11 @@ namespace Game.Entities
break;
}
SetUInt32Value(UnitFields.PetNameTimestamp, (uint)Time.UnixTime); // cast can't be helped here
SetPetNameTimestamp((uint)Time.UnixTime); // cast can't be helped here
SetCreatorGUID(owner.GetGUID());
InitStatsForLevel(petlevel);
SetUInt32Value(UnitFields.PetExperience, result.Read<uint>(5));
SetPetExperience(result.Read<uint>(5));
SynchronizeLevelWithOwner();
@@ -443,16 +443,16 @@ namespace Game.Entities
stmt.AddValue(2, ownerLowGUID);
stmt.AddValue(3, GetNativeDisplayId());
stmt.AddValue(4, getLevel());
stmt.AddValue(5, GetUInt32Value(UnitFields.PetExperience));
stmt.AddValue(5, (uint)m_unitData.PetExperience);
stmt.AddValue(6, GetReactState());
stmt.AddValue(7, mode);
stmt.AddValue(8, GetName());
stmt.AddValue(9, HasByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PetFlags, UnitPetFlags.CanBeRenamed) ? 0 : 1);
stmt.AddValue(9, HasPetFlag(UnitPetFlags.CanBeRenamed) ? 0 : 1);
stmt.AddValue(10, curhealth);
stmt.AddValue(11, curmana);
stmt.AddValue(12, GenerateActionBarData());
stmt.AddValue(13, Time.UnixTime);
stmt.AddValue(14, GetUInt32Value(UnitFields.CreatedBySpell));
stmt.AddValue(14, (uint)m_unitData.CreatedBySpell);
stmt.AddValue(15, getPetType());
stmt.AddValue(16, m_petSpecialization);
trans.Append(stmt);
@@ -510,8 +510,8 @@ namespace Game.Entities
if (getPetType() == PetType.Hunter)
{
// pet corpse non lootable and non skinnable
SetUInt32Value(ObjectFields.DynamicFlags, (uint)UnitDynFlags.None);
RemoveFlag(UnitFields.Flags, UnitFlags.Skinnable);
SetDynamicFlags(UnitDynFlags.None);
RemoveUnitFlag(UnitFlags.Skinnable);
}
}
else if (getDeathState() == DeathState.Alive)
@@ -626,8 +626,8 @@ namespace Game.Entities
if (petlevel >= maxlevel)
return;
uint nextLvlXP = GetUInt32Value(UnitFields.PetNextLevelExp);
uint curXP = GetUInt32Value(UnitFields.PetExperience);
uint nextLvlXP = m_unitData.PetNextLevelExperience;
uint curXP = m_unitData.PetExperience;
uint newXP = curXP + xp;
// Check how much XP the pet should receive, and hand off have any left from previous levelups
@@ -639,10 +639,10 @@ namespace Game.Entities
GivePetLevel((int)petlevel);
nextLvlXP = GetUInt32Value(UnitFields.PetNextLevelExp);
nextLvlXP = m_unitData.PetNextLevelExperience;
}
// Not affected by special conditions - give it new XP
SetUInt32Value(UnitFields.PetExperience, petlevel < maxlevel ? newXP : 0);
SetPetExperience(petlevel < maxlevel ? newXP : 0);
}
public void GivePetLevel(int level)
@@ -652,8 +652,8 @@ namespace Game.Entities
if (getPetType() == PetType.Hunter)
{
SetUInt32Value(UnitFields.PetExperience, 0);
SetUInt32Value(UnitFields.PetNextLevelExp, (uint)(Global.ObjectMgr.GetXPForLevel((uint)level) * PetXPFactor));
SetPetExperience(0);
SetPetNextLevelExperience((uint)(Global.ObjectMgr.GetXPForLevel((uint)level) * PetXPFactor));
}
InitStatsForLevel((uint)level);
@@ -712,18 +712,19 @@ namespace Game.Entities
if (!Create(map.GenerateLowGuid(HighGuid.Pet), map, cinfo.Entry))
return false;
SetUInt32Value(UnitFields.PetNameTimestamp, 0);
SetUInt32Value(UnitFields.PetExperience, 0);
SetUInt32Value(UnitFields.PetNextLevelExp, (uint)(Global.ObjectMgr.GetXPForLevel(getLevel() + 1) * PetXPFactor));
SetUInt64Value(UnitFields.NpcFlags, (ulong)NPCFlags.None);
SetPetNameTimestamp(0);
SetPetExperience(0);
SetPetNextLevelExperience((uint)(Global.ObjectMgr.GetXPForLevel(getLevel() + 1) * PetXPFactor));
SetNpcFlags(NPCFlags.None);
SetNpcFlags2(NPCFlags2.None);
if (cinfo.CreatureType == CreatureType.Beast)
{
SetByteValue(UnitFields.Bytes0, 1, (byte)Class.Warrior);
SetByteValue(UnitFields.Bytes0, 3, (byte)Gender.None);
SetUInt32Value(UnitFields.DisplayPower, (uint)PowerType.Focus);
SetClass(Class.Warrior);
SetGender(Gender.None);
SetPowerType(PowerType.Focus);
SetSheath(SheathState.Melee);
SetByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PetFlags, (UnitPetFlags.CanBeRenamed | UnitPetFlags.CanBeAbandoned));
SetPetFlags(UnitPetFlags.CanBeRenamed | UnitPetFlags.CanBeAbandoned);
}
return true;
@@ -1347,7 +1348,7 @@ namespace Game.Entities
return false;
// Force regen flag for player pets, just like we do for players themselves
SetFlag(UnitFields.Flags2, UnitFlags2.RegeneratePower);
AddUnitFlag2(UnitFlags2.RegeneratePower);
SetSheath(SheathState.Melee);
return true;
@@ -1472,7 +1473,7 @@ namespace Game.Entities
}
public PetType getPetType() { return m_petType; }
void setPetType(PetType type) { m_petType = type; }
public void setPetType(PetType type) { m_petType = type; }
public bool isControlled() { return getPetType() == PetType.Summon || getPetType() == PetType.Hunter; }
public bool isTemporarySummoned() { return m_duration > 0; }
@@ -1490,6 +1491,9 @@ namespace Game.Entities
public void SetDuration(uint dur) { m_duration = (int)dur; }
public int GetDuration() { return m_duration; }
public void SetPetExperience(uint xp) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PetExperience), xp); }
public void SetPetNextLevelExperience(uint xp) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PetNextLevelExperience), xp); }
public ushort GetSpecialization() { return m_petSpecialization; }
public GroupUpdatePetFlags GetGroupUpdateFlag() { return m_groupUpdateMask; }
@@ -69,15 +69,15 @@ namespace Game.Entities
public void LoadToys()
{
foreach (var value in _toys.Keys)
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.Toys, value);
foreach (var pair in _toys)
_owner.GetPlayer().AddToy(pair.Key, (uint)pair.Value);
}
public bool AddToy(uint itemId, bool isFavourite, bool hasFanfare)
{
if (UpdateAccountToys(itemId, isFavourite, hasFanfare))
{
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.Toys, itemId);
_owner.GetPlayer().AddToy(itemId, (uint)GetToyFlags(isFavourite, hasFanfare));
return true;
}
@@ -92,8 +92,7 @@ namespace Game.Entities
do
{
uint itemId = result.Read<uint>(0);
_toys[itemId] = GetToyFlags(result.Read<bool>(1), result.Read<bool>(2));
_toys.Add(itemId, GetToyFlags(result.Read<bool>(1), result.Read<bool>(2)));
} while (result.NextRow());
}
@@ -175,7 +174,9 @@ namespace Game.Entities
uint bonusId = 0;
if (flags.HasAnyFlag(HeirloomPlayerFlags.BonusLevel110))
if (flags.HasAnyFlag(HeirloomPlayerFlags.BonusLevel120))
bonusId = heirloom.UpgradeItemBonusListID[3];
else if (flags.HasAnyFlag(HeirloomPlayerFlags.BonusLevel110))
bonusId = heirloom.UpgradeItemBonusListID[2];
else if (flags.HasAnyFlag(HeirloomPlayerFlags.BonusLevel100))
bonusId = heirloom.UpgradeItemBonusListID[1];
@@ -220,19 +221,13 @@ namespace Game.Entities
public void LoadHeirlooms()
{
foreach (var item in _heirlooms)
{
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.Heirlooms, item.Key);
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.HeirloomFlags, (uint)item.Value.flags);
}
_owner.GetPlayer().AddHeirloom(item.Key, (uint)item.Value.flags);
}
public void AddHeirloom(uint itemId, HeirloomPlayerFlags flags)
{
if (UpdateAccountHeirlooms(itemId, flags))
{
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.Heirlooms, itemId);
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.HeirloomFlags, (uint)flags);
}
_owner.GetPlayer().AddHeirloom(itemId, (uint)flags);
}
public void UpgradeHeirloom(uint itemId, uint castItem)
@@ -267,15 +262,20 @@ namespace Game.Entities
flags |= HeirloomPlayerFlags.BonusLevel110;
bonusId = heirloom.UpgradeItemBonusListID[2];
}
if (heirloom.UpgradeItemID[3] == castItem)
{
flags |= HeirloomPlayerFlags.BonusLevel120;
bonusId = heirloom.UpgradeItemBonusListID[3];
}
foreach (Item item in player.GetItemListByEntry(itemId, true))
item.AddBonuses(bonusId);
// Get heirloom offset to update only one part of dynamic field
var fields = player.GetDynamicValues(ActivePlayerDynamicFields.Heirlooms);
ushort offset = (ushort)Array.IndexOf(fields, itemId);
List<uint> heirlooms = player.m_activePlayerData.Heirlooms;
int offset = heirlooms.IndexOf(itemId);
player.SetDynamicValue(ActivePlayerDynamicFields.HeirloomFlags, offset, (uint)flags);
player.SetHeirloomFlags(offset, (uint)flags);
data.flags = flags;
data.bonusId = bonusId;
}
@@ -315,11 +315,11 @@ namespace Game.Entities
if (newItemId != 0)
{
var heirloomFields = player.GetDynamicValues(ActivePlayerDynamicFields.Heirlooms);
ushort offset = (ushort)Array.IndexOf(heirloomFields, item.GetEntry());
List<uint> heirlooms = player.m_activePlayerData.Heirlooms;
int offset = heirlooms.IndexOf(item.GetEntry());
player.SetDynamicValue(ActivePlayerDynamicFields.Heirlooms, offset, newItemId);
player.SetDynamicValue(ActivePlayerDynamicFields.HeirloomFlags, offset, 0);
player.SetHeirloom(offset, newItemId);
player.SetHeirloomFlags(offset, 0);
_heirlooms.Remove(item.GetEntry());
_heirlooms[newItemId] = null;
@@ -327,12 +327,17 @@ namespace Game.Entities
return;
}
var fields = item.GetDynamicValues(ItemDynamicFields.BonusListIds);
foreach (uint bonusId in fields)
List<uint> bonusListIDs = item.m_itemData.BonusListIDs;
foreach (uint bonusId in bonusListIDs)
{
if (bonusId != data.bonusId)
item.ClearDynamicValue(ItemDynamicFields.BonusListIds);
{
item.ClearBonuses();
break;
}
}
if (!fields.Contains(data.bonusId))
if (!bonusListIDs.Contains(data.bonusId))
item.AddBonuses(data.bonusId);
}
}
@@ -346,6 +351,8 @@ namespace Game.Entities
if (data == null)
return false;
if (data.flags.HasAnyFlag(HeirloomPlayerFlags.BonusLevel120))
return level <= 120;
if (data.flags.HasAnyFlag(HeirloomPlayerFlags.BonusLevel110))
return level <= 110;
if (data.flags.HasAnyFlag(HeirloomPlayerFlags.BonusLevel100))
@@ -453,13 +460,12 @@ namespace Game.Entities
public void LoadItemAppearances()
{
Player owner = _owner.GetPlayer();
foreach (uint blockValue in _appearances.ToBlockRange())
{
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.Transmog, blockValue);
}
owner.AddTransmogBlock(blockValue);
foreach (var value in _temporaryAppearances.Keys)
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.ConditionalTransmog, value);
owner.AddConditionalTransmog(value);
}
public void LoadAccountItemAppearances(SQLResult knownAppearances, SQLResult favoriteAppearances)
@@ -578,7 +584,7 @@ namespace Game.Entities
if (!CanAddAppearance(itemModifiedAppearance))
return;
if (Convert.ToBoolean(item.GetUInt32Value(ItemFields.Flags) & (uint)(ItemFieldFlags.BopTradeable | ItemFieldFlags.Refundable)))
if (item.HasItemFlag(ItemFieldFlags.BopTradeable | ItemFieldFlags.Refundable))
{
AddTemporaryAppearance(item.GetGUID(), itemModifiedAppearance);
return;
@@ -678,24 +684,24 @@ namespace Game.Entities
//todo check this
void AddItemAppearance(ItemModifiedAppearanceRecord itemModifiedAppearance)
{
Player owner = _owner.GetPlayer();
if (_appearances.Count <= itemModifiedAppearance.Id)
{
uint numBlocks = (uint)(_appearances.Count << 2);
_appearances.Length = (int)itemModifiedAppearance.Id + 1;
numBlocks = (uint)(_appearances.Count << 2) - numBlocks;
while (numBlocks-- != 0)
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.Transmog, 0);
owner.AddTransmogBlock(0);
}
_appearances.Set((int)itemModifiedAppearance.Id, true);
uint blockIndex = itemModifiedAppearance.Id / 32;
uint bitIndex = itemModifiedAppearance.Id % 32;
uint currentMask = _owner.GetPlayer().GetDynamicValue(ActivePlayerDynamicFields.Transmog, (ushort)blockIndex);
_owner.GetPlayer().SetDynamicValue(ActivePlayerDynamicFields.Transmog, (ushort)blockIndex, (uint)((int)currentMask | (1 << (int)bitIndex)));
owner.AddTransmogFlag((int)blockIndex, 1u << (int)bitIndex);
var temporaryAppearance = _temporaryAppearances.LookupByKey(itemModifiedAppearance.Id);
if (!temporaryAppearance.Empty())
{
_owner.GetPlayer().RemoveDynamicValue(ActivePlayerDynamicFields.ConditionalTransmog, itemModifiedAppearance.Id);
owner.RemoveConditionalTransmog(itemModifiedAppearance.Id);
_temporaryAppearances.Remove(itemModifiedAppearance.Id);
}
@@ -717,7 +723,7 @@ namespace Game.Entities
{
var itemsWithAppearance = _temporaryAppearances[itemModifiedAppearance.Id];
if (itemsWithAppearance.Empty())
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.ConditionalTransmog, itemModifiedAppearance.Id);
_owner.GetPlayer().AddConditionalTransmog(itemModifiedAppearance.Id);
itemsWithAppearance.Add(itemGuid);
}
@@ -735,7 +741,7 @@ namespace Game.Entities
guid.Remove(item.GetGUID());
if (guid.Empty())
{
_owner.GetPlayer().RemoveDynamicValue(ActivePlayerDynamicFields.ConditionalTransmog, itemModifiedAppearance.Id);
_owner.GetPlayer().RemoveConditionalTransmog(itemModifiedAppearance.Id);
_temporaryAppearances.Remove(itemModifiedAppearance.Id);
}
}
+22 -32
View File
@@ -88,21 +88,9 @@ namespace Game.Entities
SendPacket(packet);
}
bool CanTitanGrip() { return m_canTitanGrip; }
public override uint GetBlockPercent() { return m_activePlayerData.ShieldBlock; }
public override 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);
}
return true;
}
bool CanTitanGrip() { return m_canTitanGrip; }
float GetRatingMultiplier(CombatRating cr)
{
@@ -118,7 +106,7 @@ namespace Game.Entities
}
public float GetRatingBonusValue(CombatRating cr)
{
float baseResult = GetFloatValue(ActivePlayerFields.CombatRating + (int)cr) * GetRatingMultiplier(cr);
float baseResult = m_activePlayerData.CombatRatings[(int)cr] * GetRatingMultiplier(cr);
if (cr != CombatRating.ResiliencePlayerDamage)
return baseResult;
return (float)(1.0f - Math.Pow(0.99f, baseResult)) * 100.0f;
@@ -189,9 +177,9 @@ namespace Game.Entities
switch (attType)
{
case WeaponAttackType.BaseAttack:
return baseExpertise + GetUInt32Value(ActivePlayerFields.Expertise) / 4.0f;
return baseExpertise + m_activePlayerData.MainhandExpertise / 4.0f;
case WeaponAttackType.OffAttack:
return baseExpertise + GetUInt32Value(ActivePlayerFields.OffhandExpertise) / 4.0f;
return baseExpertise + m_activePlayerData.OffhandExpertise / 4.0f;
default:
break;
}
@@ -201,7 +189,7 @@ namespace Game.Entities
public bool IsUseEquipedWeapon(bool mainhand)
{
// disarm applied only to mainhand weapon
return !IsInFeralForm() && (!mainhand || !HasFlag(UnitFields.Flags, UnitFlags.Disarmed));
return !IsInFeralForm() && (!mainhand || !HasUnitFlag(UnitFlags.Disarmed));
}
public void SetCanTitanGrip(bool value, uint penaltySpellId = 0)
@@ -321,8 +309,8 @@ namespace Game.Entities
Global.ScriptMgr.OnPlayerDuelStart(this, duel.opponent);
SetUInt32Value(PlayerFields.DuelTeam, 1);
duel.opponent.SetUInt32Value(PlayerFields.DuelTeam, 2);
SetDuelTeam(1);
duel.opponent.SetDuelTeam(2);
duel.startTimer = 0;
duel.startTime = currTime;
@@ -335,7 +323,7 @@ namespace Game.Entities
if (duel == null)
return;
ObjectGuid duelFlagGUID = GetGuidValue(PlayerFields.DuelArbiter);
ObjectGuid duelFlagGUID = m_playerData.DuelArbiter;
GameObject obj = GetMap().GetGameObject(duelFlagGUID);
if (!obj)
return;
@@ -439,7 +427,7 @@ namespace Game.Entities
duel.opponent.CastSpell(duel.opponent, 52852, true);
//Remove Duel Flag object
GameObject obj = GetMap().GetGameObject(GetGuidValue(PlayerFields.DuelArbiter));
GameObject obj = GetMap().GetGameObject(m_playerData.DuelArbiter);
if (obj)
duel.initiator.RemoveGameObject(obj, true);
@@ -465,14 +453,16 @@ namespace Game.Entities
duel.opponent.ClearComboPoints();
//cleanups
SetGuidValue(PlayerFields.DuelArbiter, ObjectGuid.Empty);
SetUInt32Value(PlayerFields.DuelTeam, 0);
duel.opponent.SetGuidValue(PlayerFields.DuelArbiter, ObjectGuid.Empty);
duel.opponent.SetUInt32Value(PlayerFields.DuelTeam, 0);
SetDuelArbiter(ObjectGuid.Empty);
SetDuelTeam(0);
duel.opponent.SetDuelArbiter(ObjectGuid.Empty);
duel.opponent.SetDuelTeam(0);
duel.opponent.duel = null;
duel = null;
}
public void SetDuelArbiter(ObjectGuid guid) { SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.DuelArbiter), guid); }
void SetDuelTeam(uint duelTeam) { SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.DuelTeam), duelTeam); }
//PVP
public void SetPvPDeath(bool on)
@@ -488,7 +478,7 @@ namespace Game.Entities
public void ResetContestedPvP()
{
ClearUnitState(UnitState.AttackPlayer);
RemoveFlag(PlayerFields.Flags, PlayerFlags.ContestedPVP);
RemovePlayerFlag(PlayerFlags.ContestedPVP);
m_contestedPvPTimer = 0;
}
void UpdateAfkReport(long currTime)
@@ -547,16 +537,16 @@ namespace Game.Entities
{
if (!IsFFAPvP())
{
SetByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, UnitBytes2Flags.FFAPvp);
AddPvpFlag(UnitPVPStateFlags.FFAPvp);
foreach (var unit in m_Controlled)
unit.SetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, (byte)UnitBytes2Flags.FFAPvp);
unit.AddPvpFlag(UnitPVPStateFlags.FFAPvp);
}
}
else if (IsFFAPvP())
{
RemoveByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, UnitBytes2Flags.FFAPvp);
RemovePvpFlag(UnitPVPStateFlags.FFAPvp);
foreach (var unit in m_Controlled)
unit.RemoveByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, UnitBytes2Flags.FFAPvp);
unit.RemovePvpFlag(UnitPVPStateFlags.FFAPvp);
}
if (onlyFFA)
@@ -569,7 +559,7 @@ namespace Game.Entities
}
else // in friendly area
{
if (IsPvP() && !HasFlag(PlayerFields.Flags, PlayerFlags.InPVP) && pvpInfo.EndTimer == 0)
if (IsPvP() && !HasPlayerFlag(PlayerFlags.InPVP) && pvpInfo.EndTimer == 0)
pvpInfo.EndTimer = Time.UnixTime; // start toggle-off
}
}
File diff suppressed because it is too large Load Diff
+7 -6
View File
@@ -184,6 +184,10 @@ namespace Game.Entities
//Core
WorldSession Session;
public PlayerData m_playerData;
public ActivePlayerData m_activePlayerData;
uint m_nextSave;
byte m_cinematic;
@@ -330,7 +334,6 @@ namespace Game.Entities
public List<uint>[] Glyphs = new List<uint>[PlayerConst.MaxSpecializations];
public uint ResetTalentsCost;
public long ResetTalentsTime;
public uint PrimarySpecialization;
public byte ActiveGroup;
}
@@ -442,13 +445,12 @@ namespace Game.Entities
public class VoidStorageItem
{
public VoidStorageItem(ulong id, uint entry, ObjectGuid creator, ItemRandomEnchantmentId randomPropertyId, uint suffixFactor, uint upgradeId, uint fixedScalingLevel, uint artifactKnowledgeLevel, byte context, ICollection<uint> bonuses)
public VoidStorageItem(ulong id, uint entry, ObjectGuid creator, uint randomBonusListId, uint upgradeId, uint fixedScalingLevel, uint artifactKnowledgeLevel, byte context, List<uint> bonuses)
{
ItemId = id;
ItemEntry = entry;
CreatorGuid = creator;
ItemRandomPropertyId = randomPropertyId;
ItemSuffixFactor = suffixFactor;
RandomBonusListId = randomBonusListId;
ItemUpgradeId = upgradeId;
FixedScalingLevel = fixedScalingLevel;
ArtifactKnowledgeLevel = artifactKnowledgeLevel;
@@ -461,8 +463,7 @@ namespace Game.Entities
public ulong ItemId;
public uint ItemEntry;
public ObjectGuid CreatorGuid;
public ItemRandomEnchantmentId ItemRandomPropertyId;
public uint ItemSuffixFactor;
public uint RandomBonusListId;
public uint ItemUpgradeId;
public uint FixedScalingLevel;
public uint ArtifactKnowledgeLevel;
+2 -2
View File
@@ -165,10 +165,10 @@ namespace Game.Entities
public void SetPartyType(GroupCategory category, GroupType type)
{
Cypher.Assert(category < GroupCategory.Max);
byte value = GetByteValue(PlayerFields.Bytes3, PlayerFieldOffsets.Bytes3OffsetPartyType);
byte value = m_playerData.PartyType;
value &= (byte)~((byte)0xFF << ((byte)category * 4));
value |= (byte)((byte)type << ((byte)category * 4));
SetByteValue(PlayerFields.Bytes3, PlayerFieldOffsets.Bytes3OffsetPartyType, value);
SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.PartyType), value);
}
public void ResetGroupUpdateSequenceIfNeeded(Group group)
+88 -100
View File
@@ -47,7 +47,7 @@ namespace Game.Entities
}
public void RefundItem(Item item)
{
if (!item.HasFlag(ItemFields.Flags, ItemFieldFlags.Refundable))
if (!item.HasItemFlag(ItemFieldFlags.Refundable))
{
Log.outDebug(LogFilter.Player, "Item refund: item not refundable!");
return;
@@ -152,7 +152,7 @@ namespace Game.Entities
// This function call unsets ITEM_FLAGS_REFUNDABLE if played time is over 2 hours.
item.UpdatePlayedTime(this);
if (!item.HasFlag(ItemFields.Flags, ItemFieldFlags.Refundable))
if (!item.HasItemFlag(ItemFieldFlags.Refundable))
{
Log.outDebug(LogFilter.Player, "Item refund: item not refundable!");
return;
@@ -301,7 +301,7 @@ namespace Game.Entities
if (item == null)
return;
uint pMaxDurability = item.GetUInt32Value(ItemFields.MaxDurability);
uint pMaxDurability = item.m_itemData.MaxDurability;
if (pMaxDurability == 0)
return;
@@ -352,14 +352,14 @@ namespace Game.Entities
if (HasAuraType(AuraType.PreventDurabilityLoss))
return;
int pMaxDurability = item.GetInt32Value(ItemFields.MaxDurability);
int pOldDurability = item.GetInt32Value(ItemFields.Durability);
int pNewDurability = pOldDurability - points;
uint pMaxDurability = item.m_itemData.MaxDurability;
uint pOldDurability = item.m_itemData.Durability;
int pNewDurability = (int)(pOldDurability - points);
if (pNewDurability < 0)
pNewDurability = 0;
else if (pNewDurability > pMaxDurability)
pNewDurability = pMaxDurability;
pNewDurability = (int)pMaxDurability;
if (pOldDurability != pNewDurability)
{
@@ -367,7 +367,7 @@ namespace Game.Entities
if (pNewDurability == 0 && pOldDurability > 0 && item.IsEquipped())
_ApplyItemMods(item, item.GetSlot(), false);
item.SetInt32Value(ItemFields.Durability, pNewDurability);
item.SetDurability((uint)pNewDurability);
// modify item stats _after_ restore durability to pass _ApplyItemMods internal check
if (pNewDurability > 0 && pOldDurability == 0 && item.IsEquipped())
@@ -407,11 +407,11 @@ namespace Game.Entities
if (item == null)
return TotalCost;
uint maxDurability = item.GetUInt32Value(ItemFields.MaxDurability);
uint maxDurability = item.m_itemData.MaxDurability;
if (maxDurability == 0)
return TotalCost;
uint curDurability = item.GetUInt32Value(ItemFields.Durability);
uint curDurability = item.m_itemData.Durability;
if (cost)
{
@@ -474,7 +474,7 @@ namespace Game.Entities
}
}
item.SetUInt32Value(ItemFields.Durability, maxDurability);
item.SetDurability(maxDurability);
item.SetState(ItemUpdateState.Changed, this);
// reapply mods for total broken and repaired item if equipped
@@ -644,7 +644,7 @@ namespace Game.Entities
// search free slot in bag for place to
if (bag == InventorySlots.Bag0) // inventory
{
if (pItem && pItem.HasFlag(ItemFields.Flags, ItemFieldFlags.Child))
if (pItem && pItem.HasItemFlag(ItemFieldFlags.Child))
{
res = CanStoreItem_InInventorySlots(InventorySlots.ChildEquipmentStart, InventorySlots.ChildEquipmentEnd, dest, pProto, ref count, false, pItem, bag, slot);
if (res != InventoryResult.Ok)
@@ -662,7 +662,7 @@ namespace Game.Entities
return InventoryResult.ItemMaxCount;
}
}
else if (pProto.IsCraftingReagent() && HasFlag(PlayerFields.FlagsEx, PlayerFlagsEx.ReagentBankUnlocked))
else if (pProto.IsCraftingReagent() && HasPlayerFlagEx(PlayerFlagsEx.ReagentBankUnlocked))
{
res = CanStoreItem_InInventorySlots(InventorySlots.ReagentStart, InventorySlots.ReagentEnd, dest, pProto, ref count, false, pItem, bag, slot);
if (res != InventoryResult.Ok)
@@ -832,7 +832,7 @@ namespace Game.Entities
if (pItem != null && pItem.IsNotEmptyBag())
return InventoryResult.BagInBag;
if (pItem && pItem.HasFlag(ItemFields.Flags, ItemFieldFlags.Child))
if (pItem && pItem.HasItemFlag(ItemFieldFlags.Child))
{
res = CanStoreItem_InInventorySlots(InventorySlots.ChildEquipmentStart, InventorySlots.ChildEquipmentEnd, dest, pProto, ref count, false, pItem, bag, slot);
if (res != InventoryResult.Ok)
@@ -850,7 +850,7 @@ namespace Game.Entities
return InventoryResult.ItemMaxCount;
}
}
else if (pProto.IsCraftingReagent() && HasFlag(PlayerFields.FlagsEx, PlayerFlagsEx.ReagentBankUnlocked))
else if (pProto.IsCraftingReagent() && HasPlayerFlagEx(PlayerFlagsEx.ReagentBankUnlocked))
{
res = CanStoreItem_InInventorySlots(InventorySlots.ReagentStart, InventorySlots.ReagentEnd, dest, pProto, ref count, false, pItem, bag, slot);
if (res != InventoryResult.Ok)
@@ -1132,9 +1132,9 @@ namespace Game.Entities
if (pBag == null)
{
m_items[slot] = pItem;
SetGuidValue(ActivePlayerFields.InvSlotHead + (slot * 4), pItem.GetGUID());
pItem.SetGuidValue(ItemFields.Contained, GetGUID());
pItem.SetGuidValue(ItemFields.Owner, GetGUID());
SetInvSlot(slot, pItem.GetGUID());
pItem.SetContainedIn(GetGUID());
pItem.SetOwnerGUID(GetGUID());
pItem.SetSlot(slot);
pItem.SetContainer(null);
@@ -1251,7 +1251,7 @@ namespace Game.Entities
msg = CanStoreNewItem(InventorySlots.Bag0, ItemConst.NullSlot, sDest, titem_id, titem_amount);
if (msg == InventoryResult.Ok)
{
StoreNewItem(sDest, titem_id, true, ItemEnchantment.GenerateItemRandomPropertyId(titem_id));
StoreNewItem(sDest, titem_id, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(titem_id));
return true; // stored
}
@@ -1259,7 +1259,7 @@ namespace Game.Entities
Log.outError(LogFilter.Player, "STORAGE: Can't equip or store initial item {0} for race {1} class {2}, error msg = {3}", titem_id, GetRace(), GetClass(), msg);
return false;
}
public Item StoreNewItem(List<ItemPosCount> pos, uint itemId, bool update, ItemRandomEnchantmentId randomPropertyId = default(ItemRandomEnchantmentId), List<ObjectGuid> allowedLooters = null, byte context = 0, List<uint> bonusListIDs = null, bool addToCollection = true)
public Item StoreNewItem(List<ItemPosCount> pos, uint itemId, bool update, uint randomPropertyId = 0, List<ObjectGuid> allowedLooters = null, byte context = 0, List<uint> bonusListIDs = null, bool addToCollection = true)
{
uint count = 0;
foreach (var itemPosCount in pos)
@@ -1272,28 +1272,24 @@ namespace Game.Entities
UpdateCriteria(CriteriaTypes.ReceiveEpicItem, itemId, count);
UpdateCriteria(CriteriaTypes.OwnItem, itemId, 1);
item.SetFlag(ItemFields.Flags, ItemFieldFlags.NewItem);
item.AddItemFlag(ItemFieldFlags.NewItem);
uint upgradeID = Global.DB2Mgr.GetRulesetItemUpgrade(itemId);
if (upgradeID != 0)
item.SetModifier(ItemModifier.UpgradeId, upgradeID);
item.SetUInt32Value(ItemFields.Context, context);
if (bonusListIDs != null)
{
foreach (uint bonusListID in bonusListIDs)
item.AddBonuses(bonusListID);
}
item.SetContext(context);
item.SetBonuses(bonusListIDs);
item = StoreItem(pos, item, update);
item.SetFixedLevel(getLevel());
item.SetItemRandomProperties(randomPropertyId);
item.SetItemRandomBonusList(randomPropertyId);
if (allowedLooters != null && allowedLooters.Count > 1 && item.GetTemplate().GetMaxStackSize() == 1 && item.IsSoulBound())
{
item.SetSoulboundTradeable(allowedLooters);
item.SetUInt32Value(ItemFields.CreatePlayedTime, GetTotalPlayedTime());
item.SetCreatePlayedTime(GetTotalPlayedTime());
AddTradeableItem(item);
// save data
@@ -1318,11 +1314,11 @@ namespace Game.Entities
{
List<ItemPosCount> childDest = new List<ItemPosCount>();
CanStoreItem_InInventorySlots(InventorySlots.ChildEquipmentStart, InventorySlots.ChildEquipmentEnd, childDest, childTemplate, ref count, false, null, ItemConst.NullBag, ItemConst.NullSlot);
Item childItem = StoreNewItem(childDest, childTemplate.GetId(), update, ItemRandomEnchantmentId.Empty, null, context, null, addToCollection);
Item childItem = StoreNewItem(childDest, childTemplate.GetId(), update, 0, null, context, null, addToCollection);
if (childItem)
{
childItem.SetGuidValue(ItemFields.Creator, item.GetGUID());
childItem.SetFlag(ItemFields.Flags, ItemFieldFlags.Child);
childItem.SetCreator(item.GetGUID());
childItem.AddItemFlag(ItemFieldFlags.Child);
item.SetChildItem(childItem.GetGUID());
}
}
@@ -1505,7 +1501,7 @@ namespace Game.Entities
ArtifactRecord artifact = CliDB.ArtifactStorage.LookupByKey(proto.GetArtifactID());
if (artifact != null)
if (artifact.ChrSpecializationID != GetUInt32Value(PlayerFields.CurrentSpecId))
if (artifact.ChrSpecializationID != GetPrimarySpecialization())
return InventoryResult.CantUseItem;
return InventoryResult.Ok;
@@ -1907,7 +1903,7 @@ namespace Game.Entities
return false;
}
Item item = StoreNewItem(dest, itemId, true, ItemEnchantment.GenerateItemRandomPropertyId(itemId));
Item item = StoreNewItem(dest, itemId, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(itemId));
if (item != null)
SendNewItem(item, count, true, false);
else
@@ -1947,20 +1943,7 @@ namespace Game.Entities
{
// remove held enchantments, update expertise
if (slot == EquipmentSlot.MainHand)
{
if (pItem.GetItemSuffixFactor() != 0)
{
pItem.ClearEnchantment(EnchantmentSlot.Prop3);
pItem.ClearEnchantment(EnchantmentSlot.Prop4);
}
else
{
pItem.ClearEnchantment(EnchantmentSlot.Prop0);
pItem.ClearEnchantment(EnchantmentSlot.Prop1);
}
UpdateExpertise(WeaponAttackType.BaseAttack);
}
else if (slot == EquipmentSlot.OffHand)
UpdateExpertise(WeaponAttackType.OffAttack);
// update armor penetration - passive auras may need it
@@ -1975,7 +1958,7 @@ namespace Game.Entities
}
m_items[slot] = null;
SetGuidValue(ActivePlayerFields.InvSlotHead + (slot * 4), ObjectGuid.Empty);
SetInvSlot(slot, ObjectGuid.Empty);
if (slot < EquipmentSlot.End)
{
@@ -1988,7 +1971,7 @@ namespace Game.Entities
if (pBag != null)
pBag.RemoveItem(slot, update);
pItem.SetGuidValue(ItemFields.Contained, ObjectGuid.Empty);
pItem.SetContainedIn(ObjectGuid.Empty);
pItem.SetSlot(ItemConst.NullSlot);
if (IsInWorld && update)
pItem.SendUpdateToPlayer(this);
@@ -2122,9 +2105,9 @@ namespace Game.Entities
if (pSrcItem == null)
return;
if (pSrcItem.HasFlag(ItemFields.Flags, ItemFieldFlags.Child))
if (pSrcItem.HasItemFlag(ItemFieldFlags.Child))
{
Item parentItem = GetItemByGuid(pSrcItem.GetGuidValue(ItemFields.Creator));
Item parentItem = GetItemByGuid(pSrcItem.m_itemData.Creator);
if (parentItem)
{
if (IsEquipmentPos(src))
@@ -2136,9 +2119,9 @@ namespace Game.Entities
}
}
}
else if (pDstItem && pDstItem.HasFlag(ItemFields.Flags, ItemFieldFlags.Child))
else if (pDstItem && pDstItem.HasItemFlag(ItemFieldFlags.Child))
{
Item parentItem = GetItemByGuid(pDstItem.GetGuidValue(ItemFields.Creator));
Item parentItem = GetItemByGuid(pDstItem.m_itemData.Creator);
if (parentItem)
{
if (IsEquipmentPos(dst))
@@ -2529,7 +2512,7 @@ namespace Game.Entities
}
}
Item it = bStore ? StoreNewItem(vDest, item, true, ItemEnchantment.GenerateItemRandomPropertyId(item), null, 0, crItem.BonusListIDs, false) : EquipNewItem(uiDest, item, true);
Item it = bStore ? StoreNewItem(vDest, item, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(item), null, 0, crItem.BonusListIDs, false) : EquipNewItem(uiDest, item, true);
if (it != null)
{
uint new_count = pVendor.UpdateVendorItemCurrentCount(crItem, count);
@@ -2548,7 +2531,7 @@ namespace Game.Entities
if (pProto.GetFlags().HasAnyFlag(ItemFlags.ItemPurchaseRecord) && crItem.ExtendedCost != 0 && pProto.GetMaxStackSize() == 1)
{
it.SetFlag(ItemFields.Flags, ItemFieldFlags.Refundable);
it.AddItemFlag(ItemFieldFlags.Refundable);
it.SetRefundRecipient(GetGUID());
it.SetPaidMoney((uint)price);
it.SetPaidExtendedCost(crItem.ExtendedCost);
@@ -2604,7 +2587,7 @@ namespace Game.Entities
}
void AddItemDurations(Item item)
{
if (item.GetUInt32Value(ItemFields.Duration) != 0)
if (item.m_itemData.Expiration != 0)
{
m_itemDuration.Add(item);
item.SendTimeUpdate(this);
@@ -3399,7 +3382,7 @@ namespace Game.Entities
// if current back slot non-empty search oldest or free
if (m_items[slot] != null)
{
uint oldest_time = GetUInt32Value(ActivePlayerFields.BuyBackTimestamp);
uint oldest_time = m_activePlayerData.BuybackTimestamp[0];
uint oldest_slot = InventorySlots.BuyBackStart;
for (byte i = InventorySlots.BuyBackStart + 1; i < InventorySlots.BuyBackEnd; ++i)
@@ -3411,7 +3394,7 @@ namespace Game.Entities
break;
}
uint i_time = GetUInt32Value(ActivePlayerFields.BuyBackTimestamp + i - InventorySlots.BuyBackStart);
uint i_time = m_activePlayerData.BuybackTimestamp[i - InventorySlots.BuyBackStart];
if (oldest_time > i_time)
{
@@ -3430,15 +3413,16 @@ namespace Game.Entities
m_items[slot] = pItem;
var time = Time.UnixTime;
uint etime = (uint)(time - m_logintime + (30 * 3600));
int eslot = (int)slot - InventorySlots.BuyBackStart;
uint eslot = slot - InventorySlots.BuyBackStart;
SetGuidValue(ActivePlayerFields.InvSlotHead + ((int)slot * 4), pItem.GetGUID());
SetInvSlot(slot, pItem.GetGUID());
ItemTemplate proto = pItem.GetTemplate();
if (proto != null)
SetUInt32Value(ActivePlayerFields.BuyBackPrice + eslot, proto.GetSellPrice() * pItem.GetCount());
SetBuybackPrice(eslot, proto.GetSellPrice() * pItem.GetCount());
else
SetUInt32Value(ActivePlayerFields.BuyBackPrice + eslot, 0);
SetUInt32Value(ActivePlayerFields.BuyBackTimestamp + eslot, etime);
SetBuybackPrice(eslot, 0);
SetBuybackTimestamp(eslot, etime);
// move to next (for non filled list is move most optimized choice)
if (m_currentBuybackSlot < InventorySlots.BuyBackEnd - 1)
@@ -3462,7 +3446,7 @@ namespace Game.Entities
return false;
}
Creature creature = GetNPCIfCanInteractWith(vendorGuid, NPCFlags.Vendor);
Creature creature = GetNPCIfCanInteractWith(vendorGuid, NPCFlags.Vendor, NPCFlags2.None);
if (!creature)
{
Log.outDebug(LogFilter.Network, "WORLD: BuyCurrencyFromVendorSlot - {0} not found or you can't interact with him.", vendorGuid.ToString());
@@ -3629,7 +3613,7 @@ namespace Game.Entities
if (!IsGameMaster() && ((pProto.GetFlags2().HasAnyFlag(ItemFlags2.FactionHorde) && GetTeam() == Team.Alliance) || (pProto.GetFlags2().HasAnyFlag(ItemFlags2.FactionAlliance) && GetTeam() == Team.Horde)))
return false;
Creature creature = GetNPCIfCanInteractWith(vendorguid, NPCFlags.Vendor);
Creature creature = GetNPCIfCanInteractWith(vendorguid, NPCFlags.Vendor, NPCFlags2.None);
if (!creature)
{
Log.outDebug(LogFilter.Network, "WORLD: BuyItemFromVendor - {0} not found or you can't interact with him.", vendorguid.ToString());
@@ -3866,6 +3850,8 @@ namespace Game.Entities
draft.SendMailTo(trans, new MailReceiver(this, GetGUID().GetCounter()), sender);
DB.Characters.CommitTransaction(trans);
}
public void SetBuybackPrice(uint slot, uint price) { SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.BuybackPrice, (int)slot), price); }
public void SetBuybackTimestamp(uint slot, uint timestamp) { SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.BuybackTimestamp, (int)slot), timestamp); }
public Item GetItemFromBuyBackSlot(uint slot)
{
@@ -3889,10 +3875,10 @@ namespace Game.Entities
m_items[slot] = null;
int eslot = (int)slot - InventorySlots.BuyBackStart;
SetGuidValue(ActivePlayerFields.InvSlotHead + (int)(slot * 4), ObjectGuid.Empty);
SetUInt32Value(ActivePlayerFields.BuyBackPrice + eslot, 0);
SetUInt32Value(ActivePlayerFields.BuyBackTimestamp + eslot, 0);
uint eslot = slot - InventorySlots.BuyBackStart;
SetInvSlot(slot, ObjectGuid.Empty);
SetBuybackPrice(eslot, 0);
SetBuybackTimestamp(eslot, 0);
// if current backslot is filled set to now free slot
if (m_items[m_currentBuybackSlot])
@@ -4268,7 +4254,7 @@ namespace Game.Entities
&& Global.DB2Mgr.GetHeirloomByItemId(item.GetEntry()) != null)
continue;
if (spellData.ChrSpecializationID != 0 && spellData.ChrSpecializationID != GetUInt32Value(PlayerFields.CurrentSpecId))
if (spellData.ChrSpecializationID != 0 && spellData.ChrSpecializationID != GetPrimarySpecialization())
continue;
ApplyEquipSpell(spellproto, item, apply, formChange);
@@ -4559,10 +4545,10 @@ namespace Game.Entities
if (pSrcItem.IsNotEmptyBag() && !IsBagPos((ushort)((ushort)bag << 8 | slot)))
return InventoryResult.DestroyNonemptyBag;
if (pSrcItem.HasFlag(ItemFields.Flags, ItemFieldFlags.Child) && !IsEquipmentPos(bag, slot) && !IsChildEquipmentPos(bag, slot))
if (pSrcItem.HasItemFlag(ItemFieldFlags.Child) && !IsEquipmentPos(bag, slot) && !IsChildEquipmentPos(bag, slot))
return InventoryResult.WrongBagType3;
if (!pSrcItem.HasFlag(ItemFields.Flags, ItemFieldFlags.Child) && IsChildEquipmentPos(bag, slot))
if (!pSrcItem.HasItemFlag(ItemFieldFlags.Child) && IsChildEquipmentPos(bag, slot))
return InventoryResult.WrongBagType3;
}
@@ -4655,7 +4641,7 @@ namespace Game.Entities
// in case trade we already have item in other player inventory
pLastItem.SetState(in_characterInventoryDB ? ItemUpdateState.Changed : ItemUpdateState.New, this);
if (pLastItem.HasFlag(ItemFields.Flags, ItemFieldFlags.BopTradeable))
if (pLastItem.HasItemFlag(ItemFieldFlags.BopTradeable))
AddTradeableItem(pLastItem);
}
}
@@ -4903,7 +4889,7 @@ namespace Game.Entities
if (pSrcItem.IsNotEmptyBag())
return InventoryResult.DestroyNonemptyBag;
if (pSrcItem.HasFlag(ItemFields.Flags, ItemFieldFlags.Child))
if (pSrcItem.HasItemFlag(ItemFieldFlags.Child))
return InventoryResult.WrongBagType3;
}
@@ -5305,7 +5291,7 @@ namespace Game.Entities
return res;
// check unique-equipped on gems
foreach (ItemDynamicFieldGems gemData in pItem.GetGems())
foreach (SocketedGem gemData in pItem.m_itemData.Gems)
{
ItemTemplate pGem = Global.ObjectMgr.GetItemTemplate(gemData.ItemId);
if (pGem == null)
@@ -5400,7 +5386,7 @@ namespace Game.Entities
//Artifact
void ApplyArtifactPowers(Item item, bool apply)
{
foreach (ItemDynamicFieldArtifactPowers artifactPower in item.GetArtifactPowers())
foreach (ArtifactPower artifactPower in item.m_itemData.ArtifactPowers)
{
byte rank = artifactPower.CurrentRankWithBonus;
if (rank == 0)
@@ -5573,16 +5559,18 @@ namespace Game.Entities
//Visual
public void SetVisibleItemSlot(uint slot, Item pItem)
{
var itemField = m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.VisibleItems, (int)slot);
if (pItem != null)
{
SetUInt32Value(PlayerFields.VisibleItem + (int)(slot * 2), pItem.GetVisibleEntry(this));
SetUInt16Value(PlayerFields.VisibleItem + 1 + (int)(slot * 2), 0, pItem.GetVisibleAppearanceModId(this));
SetUInt16Value(PlayerFields.VisibleItem + 1 + (int)(slot * 2), 1, pItem.GetVisibleItemVisual(this));
SetUpdateFieldValue(itemField.ModifyValue(itemField.ItemID), pItem.GetVisibleEntry(this));
SetUpdateFieldValue(itemField.ModifyValue(itemField.ItemAppearanceModID), pItem.GetVisibleAppearanceModId(this));
SetUpdateFieldValue(itemField.ModifyValue(itemField.ItemVisual), pItem.GetVisibleItemVisual(this));
}
else
{
SetUInt32Value(PlayerFields.VisibleItem + (int)(slot * 2), 0);
SetUInt32Value(PlayerFields.VisibleItem + 1 + (int)(slot * 2), 0);
SetUpdateFieldValue(itemField.ModifyValue(itemField.ItemID), 0u);
SetUpdateFieldValue(itemField.ModifyValue(itemField.ItemAppearanceModID), (ushort)0);
SetUpdateFieldValue(itemField.ModifyValue(itemField.ItemVisual), (ushort)0);
}
}
void VisualizeItem(uint slot, Item pItem)
@@ -5601,9 +5589,9 @@ namespace Game.Entities
Log.outDebug(LogFilter.Player, "STORAGE: EquipItem slot = {0}, item = {1}", slot, pItem.GetEntry());
m_items[slot] = pItem;
SetGuidValue(ActivePlayerFields.InvSlotHead + (int)(slot * 4), pItem.GetGUID());
pItem.SetGuidValue(ItemFields.Contained, GetGUID());
pItem.SetGuidValue(ItemFields.Owner, GetGUID());
SetInvSlot(slot, pItem.GetGUID());
pItem.SetContainedIn(GetGUID());
pItem.SetOwnerGUID(GetGUID());
pItem.SetSlot((byte)slot);
pItem.SetContainer(null);
@@ -5625,7 +5613,7 @@ namespace Game.Entities
for (byte i = 0; i < ItemConst.MaxBagSize; ++i)
DestroyItem(slot, i, update);
if (pItem.HasFlag(ItemFields.Flags, ItemFieldFlags.Wrapped))
if (pItem.HasItemFlag(ItemFieldFlags.Wrapped))
{
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_GIFT);
stmt.AddValue(0, pItem.GetGUID().GetCounter());
@@ -5645,7 +5633,7 @@ namespace Game.Entities
Bag pBag;
if (bag == InventorySlots.Bag0)
{
SetGuidValue(ActivePlayerFields.InvSlotHead + (slot * 4), ObjectGuid.Empty);
SetInvSlot(slot, ObjectGuid.Empty);
// equipment and equipped bags can have applied bonuses
if (slot < InventorySlots.BagEnd)
@@ -5699,7 +5687,7 @@ namespace Game.Entities
}
//pItem.SetOwnerGUID(ObjectGuid.Empty);
pItem.SetGuidValue(ItemFields.Contained, ObjectGuid.Empty);
pItem.SetContainedIn(ObjectGuid.Empty);
pItem.SetSlot(ItemConst.NullSlot);
pItem.SetState(ItemUpdateState.Removed, this);
}
@@ -6010,12 +5998,12 @@ namespace Game.Entities
continue;
}
Item pItem = StoreNewItem(dest, lootItem.itemid, true, lootItem.randomPropertyId, null, lootItem.context, lootItem.BonusListIDs);
Item pItem = StoreNewItem(dest, lootItem.itemid, true, lootItem.randomBonusListId, null, lootItem.context, lootItem.BonusListIDs);
SendNewItem(pItem, lootItem.count, false, false, broadcast);
}
}
public byte GetInventorySlotCount() { return GetByteValue(ActivePlayerFields.Bytes2, PlayerFieldOffsets.FieldBytes2OffsetNumBackpackSlots); }
public byte GetInventorySlotCount() { return m_activePlayerData.NumBackpackSlots; }
public void SetInventorySlotCount(byte slots)
{
//ASSERT(slots <= (INVENTORY_SLOT_ITEM_END - INVENTORY_SLOT_ITEM_START));
@@ -6058,15 +6046,15 @@ namespace Game.Entities
}
}
SetByteValue(ActivePlayerFields.Bytes2, PlayerFieldOffsets.FieldBytes2OffsetNumBackpackSlots, slots);
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.NumBackpackSlots), slots);
}
public byte GetBankBagSlotCount() { return GetByteValue(PlayerFields.Bytes3, PlayerFieldOffsets.Bytes3OffsetBankBagSlots); }
public void SetBankBagSlotCount(byte count) { SetByteValue(PlayerFields.Bytes3, PlayerFieldOffsets.Bytes3OffsetBankBagSlots, count); }
public byte GetBankBagSlotCount() { return m_activePlayerData.NumBankSlots; }
public void SetBankBagSlotCount(byte count) { SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.NumBankSlots), count); }
//Loot
public ObjectGuid GetLootGUID() { return GetGuidValue(PlayerFields.LootTargetGuid); }
public void SetLootGUID(ObjectGuid guid) { SetGuidValue(PlayerFields.LootTargetGuid, guid); }
public ObjectGuid GetLootGUID() { return m_playerData.LootTargetGUID; }
public void SetLootGUID(ObjectGuid guid) { SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.LootTargetGUID), guid); }
public void StoreLootItem(byte lootSlot, Loot loot, AELootResult aeResult = null)
{
NotNormalLootItem qitem = null;
@@ -6104,7 +6092,7 @@ namespace Game.Entities
InventoryResult msg = CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, item.itemid, item.count);
if (msg == InventoryResult.Ok)
{
Item newitem = StoreNewItem(dest, item.itemid, true, item.randomPropertyId, item.GetAllowedLooters(), item.context, item.BonusListIDs);
Item newitem = StoreNewItem(dest, item.itemid, true, item.randomBonusListId, item.GetAllowedLooters(), item.context, item.BonusListIDs);
if (qitem != null)
{
qitem.is_looted = true;
@@ -6196,7 +6184,7 @@ namespace Game.Entities
return;
// Now we must make bones lootable, and send player loot
bones.SetFlag(CorpseFields.DynamicFlags, 0x01);
bones.AddCorpseDynamicFlag(CorpseDynFlags.Lootable);
// We store the level of our player in the gold field
// We retrieve this information at Player.SendLoot()
@@ -6571,7 +6559,7 @@ namespace Game.Entities
SendLootError(loot.GetGUID(), guid, LootError.DidntKill);
if (loot_type == LootType.Corpse && !guid.IsItem())
SetFlag(UnitFields.Flags, UnitFlags.Looting);
AddUnitFlag(UnitFlags.Looting);
}
public void SendLootError(ObjectGuid lootObj, ObjectGuid owner, LootError error)
@@ -6663,9 +6651,9 @@ namespace Game.Entities
}
//Void Storage
public bool IsVoidStorageUnlocked() { return HasFlag(PlayerFields.Flags, PlayerFlags.VoidUnlocked); }
public void UnlockVoidStorage() { SetFlag(PlayerFields.Flags, PlayerFlags.VoidUnlocked); }
public void LockVoidStorage() { RemoveFlag(PlayerFields.Flags, PlayerFlags.VoidUnlocked); }
public bool IsVoidStorageUnlocked() { return HasPlayerFlag(PlayerFlags.VoidUnlocked); }
public void UnlockVoidStorage() { AddPlayerFlag(PlayerFlags.VoidUnlocked); }
public void LockVoidStorage() { RemovePlayerFlag(PlayerFlags.VoidUnlocked); }
public byte GetNextVoidStorageFreeSlot()
{
+2 -2
View File
@@ -125,13 +125,13 @@ namespace Game.Entities
pvpInfo.IsInNoPvPArea = false;
if (area != null && area.IsSanctuary()) // in sanctuary
{
SetByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, UnitBytes2Flags.Sanctuary);
AddPvpFlag(UnitPVPStateFlags.Sanctuary);
pvpInfo.IsInNoPvPArea = true;
if (duel == null)
CombatStopWithPets();
}
else
RemoveByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, UnitBytes2Flags.Sanctuary);
RemovePvpFlag(UnitPVPStateFlags.Sanctuary);
AreaFlags areaRestFlag = (GetTeam() == Team.Alliance) ? AreaFlags.RestZoneAlliance : AreaFlags.RestZoneHorde;
if (area != null && area.Flags[0].HasAnyFlag(areaRestFlag))
+31 -24
View File
@@ -46,16 +46,15 @@ namespace Game.Entities
if (m_lastHonorUpdateTime >= yesterday)
{
// this is the first update today, reset today's contribution
ushort killsToday = GetUInt16Value(ActivePlayerFields.Kills, 0);
SetUInt16Value(ActivePlayerFields.Kills, 0, 0);
SetUInt16Value(ActivePlayerFields.Kills, 1, killsToday);
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.YesterdayHonorableKills), m_activePlayerData.TodayHonorableKills);
}
else
{
// no honor/kills yesterday or today, reset
SetUInt32Value(ActivePlayerFields.Kills, 0);
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.YesterdayHonorableKills), (ushort)0);
}
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TodayHonorableKills), (ushort)0);
}
m_lastHonorUpdateTime = now;
@@ -116,7 +115,8 @@ namespace Game.Entities
// [15..28] Horde honor titles and player name
// [29..38] Other title and player name
// [39+] Nothing
uint victim_title = victim.GetUInt32Value(PlayerFields.ChosenTitle);
// this is all wrong, should be going off PvpTitle, not PlayerTitle
uint victim_title = plrVictim.m_playerData.PlayerTitle;
// Get Killer titles, CharTitlesEntry.bit_index
// Ranks:
// title[1..14] . rank[5..18]
@@ -134,9 +134,9 @@ namespace Game.Entities
honor_f = (float)Math.Ceiling(Formulas.hk_honor_at_level_f(k_level) * (v_level - k_grey) / (k_level - k_grey));
// count the number of playerkills in one day
ApplyModUInt16Value(ActivePlayerFields.Kills, 0, 1, true);
ApplyModUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TodayHonorableKills), (ushort)1, true);
// and those in a lifetime
ApplyModUInt32Value(ActivePlayerFields.LifetimeHonorableKills, 1, true);
ApplyModUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.LifetimeHonorableKills), 1u, true);
UpdateCriteria(CriteriaTypes.EarnHonorableKill);
UpdateCriteria(CriteriaTypes.HkClass, (uint)victim.GetClass());
UpdateCriteria(CriteriaTypes.HkRace, (uint)victim.GetRace());
@@ -215,9 +215,16 @@ namespace Game.Entities
return true;
}
public void ResetHonorStats()
{
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TodayHonorableKills), (ushort)0);
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.YesterdayHonorableKills), (ushort)0);
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.LifetimeHonorableKills), 0u);
}
void _InitHonorLevelOnLoadFromDB(uint honor, uint honorLevel)
{
SetUInt32Value(PlayerFields.HonorLevel, honorLevel);
SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.HonorLevel), honorLevel);
UpdateHonorNextLevel();
AddHonorXP(honor);
@@ -250,8 +257,8 @@ namespace Game.Entities
public void AddHonorXP(uint xp)
{
uint currentHonorXP = GetUInt32Value(ActivePlayerFields.Honor);
uint nextHonorLevelXP = GetUInt32Value(ActivePlayerFields.HonorNextLevel);
uint currentHonorXP = m_activePlayerData.Honor;
uint nextHonorLevelXP = m_activePlayerData.HonorNextLevel;
uint newHonorXP = currentHonorXP + xp;
uint honorLevel = GetHonorLevel();
@@ -266,10 +273,10 @@ namespace Game.Entities
SetHonorLevel((byte)(honorLevel + 1));
honorLevel = GetHonorLevel();
nextHonorLevelXP = GetUInt32Value(ActivePlayerFields.HonorNextLevel);
nextHonorLevelXP = m_activePlayerData.HonorNextLevel;
}
SetUInt32Value(ActivePlayerFields.Honor, IsMaxHonorLevel() ? 0 : newHonorXP);
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.Honor), IsMaxHonorLevel() ? 0 : newHonorXP);
}
void SetHonorLevel(byte level)
@@ -278,7 +285,7 @@ namespace Game.Entities
if (level == oldHonorLevel)
return;
SetUInt32Value(PlayerFields.HonorLevel, level);
SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.HonorLevel), level);
UpdateHonorNextLevel();
UpdateCriteria(CriteriaTypes.HonorLevelReached);
@@ -289,10 +296,10 @@ namespace Game.Entities
// 5500 at honor level 1
// no idea what between here
// 8800 at honor level ~14 (never goes above 8800)
SetUInt32Value(ActivePlayerFields.HonorNextLevel, 8800);
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.HonorNextLevel), 8800u);
}
public uint GetHonorLevel() { return GetUInt32Value(PlayerFields.HonorLevel); }
public uint GetHonorLevel() { return m_playerData.HonorLevel; }
public bool IsMaxHonorLevel() { return GetHonorLevel() == PlayerConst.MaxHonorLevel; }
public void ActivatePvpItemLevels(bool activate) { _usePvpItemLevels = activate; }
@@ -329,7 +336,7 @@ namespace Game.Entities
if (talentInfo == null)
return TalentLearnResult.FailedUnknown;
if (talentInfo.SpecID != GetInt32Value(PlayerFields.CurrentSpecId))
if (talentInfo.SpecID != GetPrimarySpecialization())
return TalentLearnResult.FailedUnknown;
if (talentInfo.LevelRequired > getLevel())
@@ -350,7 +357,7 @@ namespace Game.Entities
PvpTalentRecord talent = CliDB.PvpTalentStorage.LookupByKey(GetPvpTalentMap(GetActiveTalentGroup())[slot]);
if (talent != null)
{
if (!HasFlag(PlayerFields.Flags, PlayerFlags.Resting) && !HasFlag(UnitFields.Flags2, UnitFlags2.AllowChangingTalents))
if (!HasPlayerFlag(PlayerFlags.Resting) && !HasUnitFlag2(UnitFlags2.AllowChangingTalents))
return TalentLearnResult.FailedRestArea;
if (GetSpellHistory().HasCooldown(talent.SpellID))
@@ -638,7 +645,7 @@ namespace Game.Entities
if (gameobject)
{
FactionTemplateRecord playerFaction = GetFactionTemplateEntry();
FactionTemplateRecord faction = CliDB.FactionTemplateStorage.LookupByKey(gameobject.GetUInt32Value(GameObjectFields.Faction));
FactionTemplateRecord faction = CliDB.FactionTemplateStorage.LookupByKey(gameobject.GetFaction());
if (playerFaction != null && faction != null && !playerFaction.IsFriendlyTo(faction))
return false;
@@ -705,7 +712,7 @@ namespace Game.Entities
public void SetBGTeam(Team team)
{
m_bgData.bgTeam = (uint)team;
SetByteValue(PlayerFields.Bytes4, PlayerFieldOffsets.Bytes4OffsetArenaFaction, (byte)(team == Team.Alliance ? 1 : 0));
SetArenaFaction((byte)(team == Team.Alliance ? 1 : 0));
}
public Team GetBGTeam()
@@ -871,7 +878,7 @@ namespace Game.Entities
//Arenas
public void SetArenaTeamInfoField(byte slot, ArenaTeamInfoType type, uint value)
{
SetUInt32Value(ActivePlayerFields.ArenaTeamInfo + (slot * (int)ArenaTeamInfoType.End) + (int)type, value);
}
public void SetInArenaTeam(uint ArenaTeamId, byte slot, byte type)
@@ -914,11 +921,11 @@ namespace Game.Entities
}
while (result.NextRow());
}
public uint GetArenaTeamId(byte slot) { return GetUInt32Value(ActivePlayerFields.ArenaTeamInfo + (slot * (int)ArenaTeamInfoType.End) + (int)ArenaTeamInfoType.Id); }
public uint GetArenaPersonalRating(byte slot) { return GetUInt32Value(ActivePlayerFields.ArenaTeamInfo + (slot * (int)ArenaTeamInfoType.End) + (int)ArenaTeamInfoType.PersonalRating); }
public uint GetArenaTeamId(byte slot) { return 0; }
public uint GetArenaPersonalRating(byte slot) { return m_activePlayerData.PvpInfo[slot].Rating; }
public void SetArenaTeamIdInvited(uint ArenaTeamId) { m_ArenaTeamIdInvited = ArenaTeamId; }
public uint GetArenaTeamIdInvited() { return m_ArenaTeamIdInvited; }
public uint GetRBGPersonalRating() { return 0; }
public uint GetRBGPersonalRating() { return m_activePlayerData.PvpInfo[3].Rating; }
//OutdoorPVP
public bool IsOutdoorPvPActive()
+38 -48
View File
@@ -145,7 +145,7 @@ namespace Game.Entities
public void DailyReset()
{
foreach (uint questId in GetDynamicValues(ActivePlayerDynamicFields.DailyQuests))
foreach (uint questId in m_activePlayerData.DailyQuestsCompleted)
{
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(questId);
if (questBit != 0)
@@ -153,10 +153,10 @@ namespace Game.Entities
}
DailyQuestsReset dailyQuestsReset = new DailyQuestsReset();
dailyQuestsReset.Count = GetDynamicValues(ActivePlayerDynamicFields.DailyQuests).Length;
dailyQuestsReset.Count = m_activePlayerData.DailyQuestsCompleted.Size();
SendPacket(dailyQuestsReset);
ClearDynamicValue(ActivePlayerDynamicFields.DailyQuests);
ClearDynamicUpdateFieldValues(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.DailyQuestsCompleted));
m_DFQuests.Clear(); // Dungeon Finder Quests.
@@ -226,7 +226,7 @@ namespace Game.Entities
switch (questGiver.GetTypeId())
{
case TypeId.Unit:
return GetNPCIfCanInteractWith(questGiver.GetGUID(), NPCFlags.QuestGiver) != null;
return GetNPCIfCanInteractWith(questGiver.GetGUID(), NPCFlags.QuestGiver, NPCFlags2.None) != null;
case TypeId.GameObject:
return GetGameObjectIfCanInteractWith(questGiver.GetGUID(), GameObjectTypes.QuestGiver) != null;
case TypeId.Player:
@@ -331,7 +331,7 @@ namespace Game.Entities
return;
}
if (!source.IsTypeId(TypeId.Unit) || source.HasFlag64(UnitFields.NpcFlags, NPCFlags.Gossip))
if (!source.IsTypeId(TypeId.Unit) || source.ToUnit().HasNpcFlag(NPCFlags.Gossip))
{
if (quest.IsAutoAccept() && CanAddQuest(quest, true) && CanTakeQuest(quest, true))
AddQuestAndCheckCompletion(quest, source);
@@ -880,7 +880,7 @@ namespace Game.Entities
List<ItemPosCount> dest = new List<ItemPosCount>();
if (CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, questPackageItem.ItemID, questPackageItem.ItemQuantity) == InventoryResult.Ok)
{
Item item = StoreNewItem(dest, questPackageItem.ItemID, true, ItemEnchantment.GenerateItemRandomPropertyId(questPackageItem.ItemID));
Item item = StoreNewItem(dest, questPackageItem.ItemID, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(questPackageItem.ItemID));
SendNewItem(item, questPackageItem.ItemQuantity, true, false);
}
}
@@ -900,7 +900,7 @@ namespace Game.Entities
List<ItemPosCount> dest = new List<ItemPosCount>();
if (CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, questPackageItem.ItemID, questPackageItem.ItemQuantity) == InventoryResult.Ok)
{
Item item = StoreNewItem(dest, questPackageItem.ItemID, true, ItemEnchantment.GenerateItemRandomPropertyId(questPackageItem.ItemID));
Item item = StoreNewItem(dest, questPackageItem.ItemID, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(questPackageItem.ItemID));
SendNewItem(item, questPackageItem.ItemQuantity, true, false);
}
}
@@ -954,7 +954,7 @@ namespace Game.Entities
List<ItemPosCount> dest = new List<ItemPosCount>();
if (CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, reward, quest.RewardChoiceItemCount[i]) == InventoryResult.Ok)
{
Item item = StoreNewItem(dest, reward, true, ItemEnchantment.GenerateItemRandomPropertyId(reward));
Item item = StoreNewItem(dest, reward, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(reward));
SendNewItem(item, quest.RewardChoiceItemCount[i], true, false);
}
}
@@ -975,7 +975,7 @@ namespace Game.Entities
List<ItemPosCount> dest = new List<ItemPosCount>();
if (CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, itemId, quest.RewardItemCount[i]) == InventoryResult.Ok)
{
Item item = StoreNewItem(dest, itemId, true, ItemEnchantment.GenerateItemRandomPropertyId(itemId));
Item item = StoreNewItem(dest, itemId, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(itemId));
SendNewItem(item, quest.RewardItemCount[i], true, false);
}
else if (quest.IsDFQuest())
@@ -1609,12 +1609,7 @@ namespace Game.Entities
return true;
}
var dailies = GetDynamicValues(ActivePlayerDynamicFields.DailyQuests);
foreach (var dailyQuestId in dailies)
if (dailyQuestId == qInfo.Id)
return false;
return true;
return m_activePlayerData.DailyQuestsCompleted.FindIndex(qInfo.Id) == -1;
}
public bool SatisfyQuestWeek(Quest qInfo, bool msg)
@@ -1977,34 +1972,37 @@ namespace Game.Entities
public uint GetQuestSlotQuestId(ushort slot)
{
return GetUInt32Value(PlayerFields.QuestLog + (slot * QuestSlotOffsets.Max) + QuestSlotOffsets.Id);
return m_playerData.QuestLog[slot].QuestID;
}
public uint GetQuestSlotState(ushort slot, byte counter)
{
return GetUInt32Value(PlayerFields.QuestLog + (slot * QuestSlotOffsets.Max) + QuestSlotOffsets.State);
return m_playerData.QuestLog[slot].StateFlags;
}
public ushort GetQuestSlotCounter(ushort slot, byte counter)
{
if (counter < SharedConst.MaxQuestCounts)
return GetUInt16Value(PlayerFields.QuestLog + slot * QuestSlotOffsets.Max + QuestSlotOffsets.Counts + counter /2, (byte)(counter % 2));
return m_playerData.QuestLog[slot].ObjectiveProgress[counter];
return 0;
}
public uint GetQuestSlotTime(ushort slot)
{
return GetUInt32Value(PlayerFields.QuestLog + (slot * QuestSlotOffsets.Max) + QuestSlotOffsets.Time);
return m_playerData.QuestLog[slot].EndTime;
}
public void SetQuestSlot(ushort slot, uint quest_id, uint timer = 0)
{
SetUInt32Value(PlayerFields.QuestLog + (slot * QuestSlotOffsets.Max) + QuestSlotOffsets.Id, quest_id);
SetUInt32Value(PlayerFields.QuestLog + (slot * QuestSlotOffsets.Max) + QuestSlotOffsets.State, 0);
for (int i = 0; i < SharedConst.MaxQuestCounts / 2; ++i)
SetUInt32Value(PlayerFields.QuestLog + slot * QuestSlotOffsets.Max + QuestSlotOffsets.Counts + i, 0);
SetUInt32Value(PlayerFields.QuestLog + (slot * QuestSlotOffsets.Max) + QuestSlotOffsets.Time, timer);
var questLogField = m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.QuestLog, slot);
SetUpdateFieldValue(questLogField.ModifyValue(questLogField.QuestID), quest_id);
SetUpdateFieldValue(questLogField.ModifyValue(questLogField.StateFlags), 0u);
for (int i = 0; i < SharedConst.MaxQuestCounts; ++i)
SetUpdateFieldValue(ref questLogField.ModifyValue(questLogField.ObjectiveProgress, i), (ushort)0);
SetUpdateFieldValue(questLogField.ModifyValue(questLogField.EndTime), timer);
}
public void SetQuestSlotCounter(ushort slot, byte counter, ushort count)
@@ -2012,22 +2010,24 @@ namespace Game.Entities
if (counter >= SharedConst.MaxQuestCounts)
return;
SetUInt16Value(PlayerFields.QuestLog + slot * QuestSlotOffsets.Max + QuestSlotOffsets.Counts + counter / 2, (byte)(counter % 2), count);
SetUpdateFieldValue(ref m_playerData.ModifyValue(m_playerData.QuestLog, slot).ModifyValue((QuestLog questLogField) => questLogField.ObjectiveProgress, counter), count);
}
public void SetQuestSlotState(ushort slot, QuestSlotStateMask state)
{
SetFlag(PlayerFields.QuestLog + (slot * QuestSlotOffsets.Max) + QuestSlotOffsets.State, state);
QuestLog questLogField = m_playerData.ModifyValue(m_playerData.QuestLog, slot);
SetUpdateFieldFlagValue(questLogField.ModifyValue(questLogField.StateFlags), (uint)state);
}
public void RemoveQuestSlotState(ushort slot, QuestSlotStateMask state)
{
RemoveFlag(PlayerFields.QuestLog + (slot * QuestSlotOffsets.Max) + QuestSlotOffsets.State, state);
QuestLog questLogField = m_playerData.ModifyValue(m_playerData.QuestLog, slot);
RemoveUpdateFieldFlagValue(questLogField.ModifyValue(questLogField.StateFlags), (uint)state);
}
public void SetQuestSlotTimer(ushort slot, uint timer)
{
SetUInt32Value(PlayerFields.QuestLog + (slot * QuestSlotOffsets.Max) + QuestSlotOffsets.Time, timer);
SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.QuestLog, slot).ModifyValue((QuestLog questLog) => questLog.EndTime), timer);
}
void SetQuestCompletedBit(uint questBit, bool completed)
@@ -2035,11 +2035,15 @@ namespace Game.Entities
if (questBit == 0)
return;
int fieldOffset = ((int)questBit - 1) >> 5;
uint fieldOffset = (questBit - 1) >> 6;
if (fieldOffset >= PlayerConst.QuestsCompletedBitsSize)
return;
ApplyModFlag(ActivePlayerFields.QuestCompleted + fieldOffset, (uint)(1 << (((int)questBit - 1) & 31)), completed);
ulong flag = 1ul << (((int)questBit - 1) & 63);
if (completed)
SetUpdateFieldFlagValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.QuestCompleted, (int)fieldOffset), flag);
else
RemoveUpdateFieldFlagValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.QuestCompleted, (int)fieldOffset), flag);
}
public void AreaExploredOrEventHappens(uint questId)
@@ -2885,7 +2889,7 @@ namespace Game.Entities
if (!questgiver || questgiver.IsHostileTo(this))
continue;
if (!questgiver.HasFlag64(UnitFields.NpcFlags, NPCFlags.QuestGiver))
if (!questgiver.HasNpcFlag(NPCFlags.QuestGiver))
continue;
response.QuestGiver.Add(new QuestGiverInfo(questgiver.GetGUID(), GetQuestDialogStatus(questgiver)));
@@ -2978,7 +2982,7 @@ namespace Game.Entities
continue;
// check if this unit requires quest specific flags
if (!obj.HasFlag64(UnitFields.NpcFlags, NPCFlags.SpellClick))
if (!obj.HasNpcFlag(NPCFlags.SpellClick))
continue;
var clickPair = Global.ObjectMgr.GetSpellClickInfoMapBounds(obj.GetEntry());
@@ -3014,7 +3018,7 @@ namespace Game.Entities
{
if (!qQuest.IsDFQuest())
{
AddDynamicValue(ActivePlayerDynamicFields.DailyQuests, quest_id);
AddDynamicUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.DailyQuestsCompleted), quest_id);
m_lastDailyQuestTime = Time.UnixTime; // last daily quest time
m_DailyQuestChanged = true;
@@ -3030,21 +3034,7 @@ namespace Game.Entities
public bool IsDailyQuestDone(uint quest_id)
{
bool found = false;
if (Global.ObjectMgr.GetQuestTemplate(quest_id) != null)
{
var dailies = GetDynamicValues(ActivePlayerDynamicFields.DailyQuests);
foreach (uint dailyQuestId in dailies)
{
if (dailyQuestId == quest_id)
{
found = true;
break;
}
}
}
return found;
return m_activePlayerData.DailyQuestsCompleted.FindIndex(quest_id) >= 0;
}
void SetWeeklyQuestStatus(uint quest_id)
+209 -249
View File
@@ -32,10 +32,11 @@ namespace Game.Entities
void UpdateSkillsForLevel()
{
ushort maxSkill = GetMaxSkillValueForLevel();
SkillInfo skillInfoField = m_activePlayerData.Skill;
foreach (var pair in mSkillStatus)
{
if (pair.Value.State == SkillState.Deleted)
if (pair.Value.State == SkillState.Deleted || skillInfoField.SkillRank[pair.Value.Pos] == 0)
continue;
uint pskill = pair.Key;
@@ -43,36 +44,35 @@ namespace Game.Entities
if (rcEntry == null)
continue;
ushort field = (ushort)(pair.Value.Pos / 2);
byte offset = (byte)(pair.Value.Pos & 1);
if (Global.SpellMgr.GetSkillRangeType(rcEntry) == SkillRangeType.Level)
{
ushort max = GetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset);
ushort max = skillInfoField.SkillMaxRank[pair.Value.Pos];
// update only level dependent max skill values
if (max != 1)
{
SetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset, maxSkill);
SetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset, maxSkill);
SetSkillRank(pair.Value.Pos, maxSkill);
SetSkillMaxRank(pair.Value.Pos, maxSkill);
if (pair.Value.State != SkillState.New)
pair.Value.State = SkillState.Changed;
}
}
// Update level dependent skillline spells
LearnSkillRewardedSpells(rcEntry.SkillID, GetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset));
LearnSkillRewardedSpells(rcEntry.SkillID, skillInfoField.SkillRank[pair.Value.Pos]);
}
}
public void UpdateSkillsToMaxSkillsForLevel()
{
foreach (var skill in mSkillStatus)
SkillInfo skillInfoField = m_activePlayerData.Skill;
foreach (var pair in mSkillStatus)
{
if (skill.Value.State == SkillState.Deleted)
if (pair.Value.State == SkillState.Deleted || skillInfoField.SkillRank[pair.Value.Pos] == 0)
continue;
uint pskill = skill.Key;
uint pskill = pair.Key;
SkillRaceClassInfoRecord rcEntry = Global.DB2Mgr.GetSkillRaceClassInfo(pskill, GetRace(), GetClass());
if (rcEntry == null)
continue;
@@ -83,16 +83,13 @@ namespace Game.Entities
if (Global.SpellMgr.IsWeaponSkill(rcEntry.SkillID))
continue;
ushort field = (ushort)(skill.Value.Pos / 2);
byte offset = (byte)(skill.Value.Pos & 1);
ushort max = GetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset);
ushort max = skillInfoField.SkillMaxRank[pair.Value.Pos];
if (max > 1)
{
SetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset, max);
SetSkillRank(pair.Value.Pos, max);
if (skill.Value.State != SkillState.New)
skill.Value.State = SkillState.Changed;
if (pair.Value.State != SkillState.New)
pair.Value.State = SkillState.Changed;
}
}
}
@@ -102,16 +99,15 @@ namespace Game.Entities
if (skill == 0)
return 0;
SkillInfo skillInfo = m_activePlayerData.Skill;
var skillStatusData = mSkillStatus.LookupByKey(skill);
if (skillStatusData == null || skillStatusData.State == SkillState.Deleted)
if (skillStatusData == null || skillStatusData.State == SkillState.Deleted || skillInfo.SkillRank[skillStatusData.Pos] == 0)
return 0;
var field = (ushort)(skillStatusData.Pos / 2);
var offset = (byte)(skillStatusData.Pos & 1);
int result = GetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset);
result += GetUInt16Value(ActivePlayerFields.SkillLineTempBonus + field, offset);
result += GetUInt16Value(ActivePlayerFields.SkillLinePermBonus + field, offset);
int result = skillInfo.SkillRank[skillStatusData.Pos];
result += skillInfo.SkillTempBonus[skillStatusData.Pos];
result += skillInfo.SkillPermBonus[skillStatusData.Pos];
return (ushort)(result < 0 ? 0 : result);
}
@@ -120,16 +116,15 @@ namespace Game.Entities
if (skill == 0)
return 0;
SkillInfo skillInfo = m_activePlayerData.Skill;
var skillStatusData = mSkillStatus.LookupByKey(skill);
if (skillStatusData == null || skillStatusData.State == SkillState.Deleted)
if (skillStatusData == null || skillStatusData.State == SkillState.Deleted || skillInfo.SkillRank[skillStatusData.Pos] == 0)
return 0;
var field = (ushort)(skillStatusData.Pos / 2);
var offset = (byte)(skillStatusData.Pos & 1);
int result = GetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset);
result += GetUInt16Value(ActivePlayerFields.SkillLineTempBonus + field, offset);
result += GetUInt16Value(ActivePlayerFields.SkillLinePermBonus + field, offset);
int result = skillInfo.SkillMaxRank[skillStatusData.Pos];
result += skillInfo.SkillTempBonus[skillStatusData.Pos];
result += skillInfo.SkillPermBonus[skillStatusData.Pos];
return (ushort)(result < 0 ? 0 : result);
}
@@ -138,14 +133,13 @@ namespace Game.Entities
if (skill == 0)
return 0;
SkillInfo skillInfo = m_activePlayerData.Skill;
var skillStatusData = mSkillStatus.LookupByKey((uint)skill);
if (skillStatusData == null || skillStatusData.State == SkillState.Deleted)
if (skillStatusData == null || skillStatusData.State == SkillState.Deleted || skillInfo.SkillRank[skillStatusData.Pos] == 0)
return 0;
var field = (ushort)(skillStatusData.Pos / 2);
var offset = (byte)(skillStatusData.Pos & 1);
return GetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset);
return skillInfo.SkillRank[skillStatusData.Pos];
}
public ushort GetSkillStep(SkillType skill)
@@ -153,14 +147,16 @@ namespace Game.Entities
if (skill == 0)
return 0;
SkillInfo skillInfo = m_activePlayerData.Skill;
var skillStatusData = mSkillStatus.LookupByKey(skill);
if (skillStatusData == null || skillStatusData.State == SkillState.Deleted)
if (skillStatusData == null || skillStatusData.State == SkillState.Deleted || skillInfo.SkillRank[skillStatusData.Pos] == 0)
return 0;
var field = (ushort)(skillStatusData.Pos / 2);
var offset = (byte)(skillStatusData.Pos & 1);
return GetUInt16Value(ActivePlayerFields.SkillLineStep + field, offset);
return skillInfo.SkillStep[skillStatusData.Pos];
}
public ushort GetPureMaxSkillValue(SkillType skill)
@@ -168,14 +164,13 @@ namespace Game.Entities
if (skill == 0)
return 0;
SkillInfo skillInfo = m_activePlayerData.Skill;
var skillStatusData = mSkillStatus.LookupByKey(skill);
if (skillStatusData == null || skillStatusData.State == SkillState.Deleted)
if (skillStatusData == null || skillStatusData.State == SkillState.Deleted || skillInfo.SkillRank[skillStatusData.Pos] == 0)
return 0;
var field = (ushort)(skillStatusData.Pos / 2);
var offset = (byte)(skillStatusData.Pos & 1);
return GetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset);
return skillInfo.SkillMaxRank[skillStatusData.Pos];
}
public ushort GetBaseSkillValue(SkillType skill)
@@ -183,15 +178,14 @@ namespace Game.Entities
if (skill == 0)
return 0;
SkillInfo skillInfo = m_activePlayerData.Skill;
var skillStatusData = mSkillStatus.LookupByKey(skill);
if (skillStatusData == null || skillStatusData.State == SkillState.Deleted)
if (skillStatusData == null || skillStatusData.State == SkillState.Deleted || skillInfo.SkillRank[skillStatusData.Pos] == 0)
return 0;
var field = (ushort)(skillStatusData.Pos / 2);
var offset = (byte)(skillStatusData.Pos & 1);
var result = (int)GetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset);
result += GetUInt16Value(ActivePlayerFields.SkillLinePermBonus + field, offset);
int result = skillInfo.SkillRank[skillStatusData.Pos];
result += skillInfo.SkillPermBonus[skillStatusData.Pos];
return (ushort)(result < 0 ? 0 : result);
}
@@ -200,14 +194,13 @@ namespace Game.Entities
if (skill == 0)
return 0;
SkillInfo skillInfo = m_activePlayerData.Skill;
var skillStatusData = mSkillStatus.LookupByKey(skill);
if (skillStatusData == null || skillStatusData.State == SkillState.Deleted)
if (skillStatusData == null || skillStatusData.State == SkillState.Deleted || skillInfo.SkillRank[skillStatusData.Pos] == 0)
return 0;
var field = (ushort)(skillStatusData.Pos / 2);
var offset = (byte)(skillStatusData.Pos & 1);
return GetUInt16Value(ActivePlayerFields.SkillLinePermBonus + field, offset);
return skillInfo.SkillPermBonus[skillStatusData.Pos];
}
public ushort GetSkillTempBonusValue(uint skill)
@@ -215,19 +208,18 @@ namespace Game.Entities
if (skill == 0)
return 0;
SkillInfo skillInfo = m_activePlayerData.Skill;
var skillStatusData = mSkillStatus.LookupByKey(skill);
if (skillStatusData == null || skillStatusData.State == SkillState.Deleted)
if (skillStatusData == null || skillStatusData.State == SkillState.Deleted || skillInfo.SkillRank[skillStatusData.Pos] == 0)
return 0;
var field = (ushort)(skillStatusData.Pos / 2);
var offset = (byte)(skillStatusData.Pos & 1);
return GetUInt16Value(ActivePlayerFields.SkillLineTempBonus + field, offset);
return skillInfo.SkillTempBonus[skillStatusData.Pos];
}
void InitializeSelfResurrectionSpells()
{
ClearDynamicValue(ActivePlayerDynamicFields.SelfResSpells);
ClearSelfResSpell();
uint[] spells = new uint[3];
@@ -248,7 +240,7 @@ namespace Game.Entities
foreach (uint selfResSpell in spells)
if (selfResSpell != 0)
AddDynamicValue(ActivePlayerDynamicFields.SelfResSpells, selfResSpell);
AddSelfResSpell(selfResSpell);
}
public void PetSpellInitialize()
@@ -294,7 +286,7 @@ namespace Game.Entities
public bool CanSeeSpellClickOn(Creature creature)
{
if (!creature.HasFlag64(UnitFields.NpcFlags, NPCFlags.SpellClick))
if (!creature.HasNpcFlag(NPCFlags.SpellClick))
return false;
var clickPair = Global.ObjectMgr.GetSpellClickInfoMapBounds(creature.GetEntry());
@@ -329,19 +321,21 @@ namespace Game.Entities
return base.GetCastSpellInfo(spellInfo);
}
void AddOverrideSpell(uint overridenSpellId, uint newSpellId)
public void SetOverrideSpellsId(uint overrideSpellsId) { SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.OverrideSpellsID), overrideSpellsId); }
public void AddOverrideSpell(uint overridenSpellId, uint newSpellId)
{
m_overrideSpells.Add(overridenSpellId, newSpellId);
}
void RemoveOverrideSpell(uint overridenSpellId, uint newSpellId)
public void RemoveOverrideSpell(uint overridenSpellId, uint newSpellId)
{
m_overrideSpells.Remove(overridenSpellId, newSpellId);
}
void LearnSpecializationSpells()
{
var specSpells = Global.DB2Mgr.GetSpecializationSpells(GetUInt32Value(PlayerFields.CurrentSpecId));
var specSpells = Global.DB2Mgr.GetSpecializationSpells(GetPrimarySpecialization());
if (specSpells != null)
{
for (int j = 0; j < specSpells.Count; ++j)
@@ -406,6 +400,23 @@ namespace Game.Entities
SendPacket(cooldowns);
}
void InitializeSkillFields()
{
uint i = 0;
foreach (SkillLineRecord skillLine in CliDB.SkillLineStorage.Values)
{
SkillRaceClassInfoRecord rcEntry = Global.DB2Mgr.GetSkillRaceClassInfo(skillLine.Id, GetRace(), GetClass());
if (rcEntry != null)
{
SetSkillLineId(i, (ushort)skillLine.Id);
SetSkillStartingRank(i, 1);
mSkillStatus.Add(skillLine.Id, new SkillStatusData(i, SkillState.Unchanged));
if (++i >= SkillConst.MaxPlayerSkills)
break;
}
}
}
public bool UpdateSkillPro(SkillType skillId, int chance, uint step)
{
return UpdateSkillPro((uint)skillId, chance, step);
@@ -431,11 +442,10 @@ namespace Game.Entities
if (skillStatusData == null || skillStatusData.State == SkillState.Deleted)
return false;
ushort field = (ushort)(skillStatusData.Pos / 2);
byte offset = (byte)(skillStatusData.Pos & 1);
SkillInfo skillInfoField = m_activePlayerData.Skill;
ushort value = GetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset);
ushort max = GetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset);
ushort value = skillInfoField.SkillRank[skillStatusData.Pos];
ushort max = skillInfoField.SkillMaxRank[skillStatusData.Pos];
if (max == 0 || value == 0 || value >= max)
return false;
@@ -450,7 +460,7 @@ namespace Game.Entities
if (new_value > max)
new_value = max;
SetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset, new_value);
SetSkillRank(skillStatusData.Pos, new_value);
if (skillStatusData.State != SkillState.New)
skillStatusData.State = SkillState.Changed;
@@ -577,7 +587,7 @@ namespace Game.Entities
}
// Cogwheel gems dont have requirement data set in SpellItemEnchantment.dbc, but they do have it in Item-sparse.db2
ItemDynamicFieldGems gem = item.GetGem((ushort)(slot - EnchantmentSlot.Sock1));
SocketedGem gem = item.GetGem((ushort)(slot - EnchantmentSlot.Sock1));
if (gem != null)
{
ItemTemplate gemTemplate = Global.ObjectMgr.GetItemTemplate(gem.ItemId);
@@ -617,31 +627,7 @@ namespace Game.Entities
if (enchant_spell_id != 0)
{
if (apply)
{
int basepoints = 0;
// Random Property Exist - try found basepoints for spell (basepoints depends from item suffix factor)
if (item.GetItemRandomPropertyId() < 0)
{
ItemRandomSuffixRecord item_rand = CliDB.ItemRandomSuffixStorage.LookupByKey(Math.Abs(item.GetItemRandomPropertyId()));
if (item_rand != null)
{
// Search enchant_amount
for (int k = 0; k < ItemConst.MaxItemRandomProperties; ++k)
{
if (item_rand.Enchantment[k] == enchant_id)
{
basepoints = (int)((item_rand.AllocationPct[k] * item.GetItemSuffixFactor()) / 10000);
break;
}
}
}
}
// Cast custom spell vs all equal basepoints got from enchant_amount
if (basepoints != 0)
CastCustomSpell(this, enchant_spell_id, basepoints, basepoints, basepoints, true, item);
else
CastSpell(this, enchant_spell_id, true, item);
}
CastSpell(this, enchant_spell_id, true, item);
else
RemoveAurasDueToItemSpell(enchant_spell_id, item.GetGUID());
}
@@ -650,7 +636,7 @@ namespace Game.Entities
if (pEnchant.ScalingClass != 0)
{
int scalingClass = pEnchant.ScalingClass;
if ((GetUInt32Value(UnitFields.MinItemLevel) != 0 || GetUInt32Value(UnitFields.MaxItemlevel) != 0) && pEnchant.ScalingClassRestricted != 0)
if ((m_unitData.MinItemLevel != 0 || m_unitData.MaxItemLevel != 0) && pEnchant.ScalingClassRestricted != 0)
scalingClass = pEnchant.ScalingClassRestricted;
uint minLevel = ((uint)(pEnchant.Flags)).HasAnyFlag(0x20u) ? 1 : 60u;
@@ -667,22 +653,7 @@ namespace Game.Entities
enchant_amount = (uint)(pEnchant.EffectScalingPoints[s] * CliDB.GetSpellScalingColumnForClass(spellScaling, scalingClass));
}
if (enchant_amount == 0)
{
ItemRandomSuffixRecord item_rand = CliDB.ItemRandomSuffixStorage.LookupByKey(Math.Abs(item.GetItemRandomPropertyId()));
if (item_rand != null)
{
for (int k = 0; k < ItemConst.MaxItemRandomProperties; ++k)
{
if (item_rand.Enchantment[k] == enchant_id)
{
enchant_amount = (item_rand.AllocationPct[k] * item.GetItemSuffixFactor()) / 10000;
break;
}
}
}
}
enchant_amount = Math.Max(enchant_amount, 1u);
HandleStatModifier((UnitMods)((uint)UnitMods.ResistanceStart + enchant_spell_id), UnitModifierType.TotalValue, enchant_amount, apply);
break;
case ItemEnchantmentType.Stat:
@@ -690,7 +661,7 @@ namespace Game.Entities
if (pEnchant.ScalingClass != 0)
{
int scalingClass = pEnchant.ScalingClass;
if ((GetUInt32Value(UnitFields.MinItemLevel) != 0 || GetUInt32Value(UnitFields.MaxItemlevel) != 0) && pEnchant.ScalingClassRestricted != 0)
if ((m_unitData.MinItemLevel != 0 || m_unitData.MaxItemLevel != 0) && pEnchant.ScalingClassRestricted != 0)
scalingClass = pEnchant.ScalingClassRestricted;
uint minLevel = ((uint)(pEnchant.Flags)).HasAnyFlag(0x20u) ? 1 : 60u;
@@ -707,21 +678,7 @@ namespace Game.Entities
enchant_amount = (uint)(pEnchant.EffectScalingPoints[s] * CliDB.GetSpellScalingColumnForClass(spellScaling, scalingClass));
}
if (enchant_amount == 0)
{
ItemRandomSuffixRecord item_rand_suffix = CliDB.ItemRandomSuffixStorage.LookupByKey(Math.Abs(item.GetItemRandomPropertyId()));
if (item_rand_suffix != null)
{
for (int k = 0; k < ItemConst.MaxItemRandomProperties; ++k)
{
if (item_rand_suffix.Enchantment[k] == enchant_id)
{
enchant_amount = (item_rand_suffix.AllocationPct[k] * item.GetItemSuffixFactor()) / 10000;
break;
}
}
}
}
enchant_amount = Math.Max(enchant_amount, 1u);
Log.outDebug(LogFilter.Player, "Adding {0} to stat nb {1}", enchant_amount, enchant_spell_id);
switch ((ItemModType)enchant_spell_id)
@@ -914,7 +871,9 @@ namespace Game.Entities
// visualize enchantment at player and equipped items
if (slot == EnchantmentSlot.Perm)
SetUInt16Value(PlayerFields.VisibleItem + 1 + (item.GetSlot() * 2), 1, item.GetVisibleItemVisual(this));
{
SetUpdateFieldValue(m_playerData.ModifyValue(m_playerData.VisibleItems, item.GetSlot()).ModifyValue((VisibleItem visibleItemField) => visibleItemField.ItemVisual), item.GetVisibleItemVisual(this));
}
if (apply_dur)
{
@@ -935,16 +894,16 @@ namespace Game.Entities
public void ModifySkillBonus(SkillType skillid, int val, bool talent)
{
var skill = mSkillStatus.LookupByKey(skillid);
if (skill == null || skill.State == SkillState.Deleted)
SkillInfo skillInfoField = m_activePlayerData.Skill;
var skillStatusData = mSkillStatus.LookupByKey(skillid);
if (skillStatusData == null || skillStatusData.State == SkillState.Deleted || skillInfoField.SkillRank[skillStatusData.Pos] == 0)
return;
int field = (int)(skill.Pos / 2 + (talent ? ActivePlayerFields.SkillLinePermBonus : ActivePlayerFields.SkillLineTempBonus));
byte offset = (byte)(skill.Pos & 1);
ushort bonus = GetUInt16Value(field, offset);
SetUInt16Value(field, offset, (ushort)(bonus + val));
if (talent)
SetSkillPermBonus(skillStatusData.Pos, (ushort)(skillInfoField.SkillPermBonus[skillStatusData.Pos] + val));
else
SetSkillTempBonus(skillStatusData.Pos, (ushort)(skillInfoField.SkillTempBonus[skillStatusData.Pos] + val));
}
public void StopCastingBindSight()
@@ -1091,7 +1050,7 @@ namespace Game.Entities
public bool CanUseMastery()
{
ChrSpecializationRecord chrSpec = CliDB.ChrSpecializationStorage.LookupByKey(GetUInt32Value(PlayerFields.CurrentSpecId));
ChrSpecializationRecord chrSpec = CliDB.ChrSpecializationStorage.LookupByKey(GetPrimarySpecialization());
if (chrSpec != null)
return HasSpell(chrSpec.MasterySpellID[0]) || HasSpell(chrSpec.MasterySpellID[1]);
@@ -1103,8 +1062,10 @@ namespace Game.Entities
if (skill == 0)
return false;
var _skill = mSkillStatus.LookupByKey((uint)skill);
return _skill != null && _skill.State != SkillState.Deleted;
SkillInfo skillInfoField = m_activePlayerData.Skill;
var skillStatusData = mSkillStatus.LookupByKey((uint)skill);
return skillStatusData != null && skillStatusData.State != SkillState.Deleted && skillInfoField.SkillRank[skillStatusData.Pos] != 0;
}
public void SetSkill(SkillType skill, uint step, uint newVal, uint maxVal)
{
@@ -1117,13 +1078,12 @@ namespace Game.Entities
ushort currVal;
var skillStatusData = mSkillStatus.LookupByKey(id);
SkillInfo skillInfoField = m_activePlayerData.Skill;
//has skill
if (skillStatusData != null && skillStatusData.State != SkillState.Deleted)
{
var field = (ushort)(skillStatusData.Pos / 2);
var offset = (byte)(skillStatusData.Pos & 1);
currVal = GetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset);
currVal = skillInfoField.SkillRank[skillStatusData.Pos];
if (newVal != 0)
{
// if skill value is going down, update enchantments before setting the new value
@@ -1131,10 +1091,10 @@ namespace Game.Entities
UpdateSkillEnchantments(id, currVal, (ushort)newVal);
// update step
SetUInt16Value(ActivePlayerFields.SkillLineStep + field, offset, (ushort)step);
SetSkillStep(skillStatusData.Pos, (ushort)step);
// update value
SetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset, (ushort)newVal);
SetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset, (ushort)maxVal);
SetSkillRank(skillStatusData.Pos, (ushort)newVal);
SetSkillMaxRank(skillStatusData.Pos, (ushort)maxVal);
if (skillStatusData.State != SkillState.New)
skillStatusData.State = SkillState.Changed;
@@ -1152,45 +1112,45 @@ namespace Game.Entities
//remove enchantments needing this skill
UpdateSkillEnchantments(id, currVal, 0);
// clear skill fields
SetUInt16Value(ActivePlayerFields.SkillLineId + field, offset, 0);
SetUInt16Value(ActivePlayerFields.SkillLineStep + field, offset, 0);
SetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset, 0);
SetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset, 0);
SetUInt16Value(ActivePlayerFields.SkillLineTempBonus + field, offset, 0);
SetUInt16Value(ActivePlayerFields.SkillLinePermBonus + field, offset, 0);
SetSkillStep(skillStatusData.Pos, 0);
SetSkillRank(skillStatusData.Pos, 0);
SetSkillStartingRank(skillStatusData.Pos, 1);
SetSkillMaxRank(skillStatusData.Pos, 0);
SetSkillTempBonus(skillStatusData.Pos, 0);
SetSkillPermBonus(skillStatusData.Pos, 0);
// mark as deleted or simply remove from map if not saved yet
if (skillStatusData.State != SkillState.New)
skillStatusData.State = SkillState.Deleted;
else
mSkillStatus.Remove(id);
// remove all spells that related to this skill
List<SkillLineAbilityRecord> skillLineAbilities = Global.DB2Mgr.GetSkillLineAbilitiesBySkill(id);
foreach (SkillLineAbilityRecord skillLineAbility in skillLineAbilities)
RemoveSpell(Global.SpellMgr.GetFirstSpellInChain(skillLineAbility.Spell));
foreach (SkillLineRecord childSkillLine in CliDB.SkillLineStorage.Values)
List<SkillLineRecord> childSkillLines = Global.DB2Mgr.GetSkillLinesForParentSkill(id);
if (childSkillLines != null)
{
if (childSkillLine.ParentSkillLineID == id)
SetSkill(childSkillLine.Id, 0, 0, 0);
foreach (SkillLineRecord childSkillLine in childSkillLines)
{
if (childSkillLine.ParentSkillLineID == id)
SetSkill(childSkillLine.Id, 0, 0, 0);
}
}
// Clear profession lines
if (GetUInt32Value(ActivePlayerFields.ProfessionSkillLine) == id)
SetUInt32Value(ActivePlayerFields.ProfessionSkillLine, 0);
else if (GetUInt32Value(ActivePlayerFields.ProfessionSkillLine + 1) == id)
SetUInt32Value(ActivePlayerFields.ProfessionSkillLine + 1, 0);
if (m_activePlayerData.ProfessionSkillLine[0] == id)
SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ProfessionSkillLine, 0), 0u);
else if (m_activePlayerData.ProfessionSkillLine[1] == id)
SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ProfessionSkillLine, 1), 0u);
}
}
else if (newVal != 0) //add
else //add
{
currVal = 0;
for (int i = 0; i < SkillConst.MaxPlayerSkills; ++i)
for (uint i = 0; i < SkillConst.MaxPlayerSkills; ++i)
{
var field = (ushort)(i / 2);
var offset = (byte)(i & 1);
if (GetUInt16Value(ActivePlayerFields.SkillLineId + field, offset) == 0)
if (skillInfoField.SkillLineID[(int)i] == 0)
{
var skillEntry = CliDB.SkillLineStorage.LookupByKey(id);
if (skillEntry == null)
@@ -1200,7 +1160,7 @@ namespace Game.Entities
}
if (skillEntry.ParentSkillLineID != 0 && skillEntry.ParentTierIndex > 0)
if (skillEntry.ParentSkillLineID != 0)
{
SkillRaceClassInfoRecord rcEntry = Global.DB2Mgr.GetSkillRaceClassInfo(skillEntry.ParentSkillLineID, GetRace(), GetClass());
if (rcEntry != null)
@@ -1209,25 +1169,38 @@ namespace Game.Entities
if (tier != null)
{
ushort skillval = GetPureSkillValue((SkillType)skillEntry.ParentSkillLineID);
SetSkill((SkillType)skillEntry.ParentSkillLineID, (uint)skillEntry.ParentTierIndex, Math.Max(skillval, (ushort)1), tier.Value[skillEntry.ParentTierIndex - 1]);
SetSkill(skillEntry.ParentSkillLineID, (uint)skillEntry.ParentTierIndex, Math.Max(skillval, (ushort)1), tier.Value[skillEntry.ParentTierIndex - 1]);
}
}
}
else
{ // also learn missing child skills at 0 value
List<SkillLineRecord> childSkillLines = Global.DB2Mgr.GetSkillLinesForParentSkill(id);
if (childSkillLines != null)
foreach (SkillLineRecord childSkillLine in childSkillLines)
if (!HasSkill((SkillType)childSkillLine.Id))
SetSkill(childSkillLine.Id, 0, 0, 0);
if (skillEntry.CategoryID == SkillCategory.Profession)
{
int freeProfessionSlot = FindProfessionSlotFor(id);
if (freeProfessionSlot != -1)
SetUInt32Value(ActivePlayerFields.ProfessionSkillLine + freeProfessionSlot, id);
SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ProfessionSkillLine, freeProfessionSlot), id);
}
}
SetUInt16Value(ActivePlayerFields.SkillLineId + field, offset, (ushort)id);
SetUInt16Value(ActivePlayerFields.SkillLineStep + field, offset, (ushort)step);
SetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset, (ushort)newVal);
SetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset, (ushort)maxVal);
SetSkillLineId(i, (ushort)id);
SetSkillStep(i, (ushort)step);
SetSkillRank(i, (ushort)newVal);
SetSkillStartingRank(i, 1);
SetSkillMaxRank(i, (ushort)maxVal);
// apply skill bonuses
SetSkillTempBonus(i, 0);
SetSkillPermBonus(i, 0);
UpdateSkillEnchantments(id, currVal, (ushort)newVal);
UpdateCriteria(CriteriaTypes.ReachSkillLevel, id);
UpdateCriteria(CriteriaTypes.LearnSkillLevel, id);
// insert new entry or update if not deleted old entry yet
if (skillStatusData != null)
@@ -1238,35 +1211,31 @@ namespace Game.Entities
else
mSkillStatus.Add(id, new SkillStatusData((uint)i, SkillState.New));
// apply skill bonuses
SetUInt16Value(ActivePlayerFields.SkillLineTempBonus + field, offset, 0);
SetUInt16Value(ActivePlayerFields.SkillLinePermBonus + field, offset, 0);
// temporary bonuses
var mModSkill = GetAuraEffectsByType(AuraType.ModSkill);
foreach (var j in mModSkill)
if (newVal != 0)
{
if (j.GetMiscValue() == id)
j.HandleEffect(this, AuraEffectHandleModes.Skill, true);
}
UpdateCriteria(CriteriaTypes.ReachSkillLevel, id);
UpdateCriteria(CriteriaTypes.LearnSkillLevel, id);
var mModSkill2 = GetAuraEffectsByType(AuraType.ModSkill2);
foreach (var j in mModSkill2)
{
if (j.GetMiscValue() == id)
j.HandleEffect(this, AuraEffectHandleModes.Skill, true);
}
// temporary bonuses
var mModSkill = GetAuraEffectsByType(AuraType.ModSkill);
foreach (var auraEffect in mModSkill)
if (auraEffect.GetMiscValue() == id)
auraEffect.HandleEffect(this, AuraEffectHandleModes.Skill, true);
// permanent bonuses
var mModSkillTalent = GetAuraEffectsByType(AuraType.ModSkillTalent);
foreach (var eff in mModSkillTalent)
{
if (eff.GetMiscValue() == id)
eff.HandleEffect(this, AuraEffectHandleModes.Skill, true);
}
var mModSkill2 = GetAuraEffectsByType(AuraType.ModSkill2);
foreach (var auraEffect in mModSkill2)
if (auraEffect.GetMiscValue() == id)
auraEffect.HandleEffect(this, AuraEffectHandleModes.Skill, true);
// Learn all spells for skill
LearnSkillRewardedSpells(id, newVal);
// permanent bonuses
var mModSkillTalent = GetAuraEffectsByType(AuraType.ModSkillTalent);
foreach (var auraEffect in mModSkillTalent)
if (auraEffect.GetMiscValue() == id)
auraEffect.HandleEffect(this, AuraEffectHandleModes.Skill, true);
// Learn all spells for skill
LearnSkillRewardedSpells(id, newVal);
}
return;
}
}
@@ -1424,7 +1393,7 @@ namespace Game.Entities
Item pItem2 = GetItemByPos(InventorySlots.Bag0, i);
if (pItem2 != null && !pItem2.IsBroken())
{
foreach (ItemDynamicFieldGems gemData in pItem2.GetGems())
foreach (SocketedGem gemData in pItem2.m_itemData.Gems)
{
ItemTemplate gemProto = Global.ObjectMgr.GetItemTemplate(gemData.ItemId);
if (gemProto == null)
@@ -1642,7 +1611,7 @@ namespace Game.Entities
if (ability.AcquireMethod != AbilityLearnType.OnSkillValue && ability.AcquireMethod != AbilityLearnType.OnSkillLearn)
continue;
// AcquireMethod == 2 && NumSkillUps == 1 --> automatically learn riding skill spell, else we skip it (client shows riding in spellbook as trainable).
// AcquireMethod == 2 && NumSkillUps == 1 -. automatically learn riding skill spell, else we skip it (client shows riding in spellbook as trainable).
if (skillId == (uint)SkillType.Riding && (ability.AcquireMethod != AbilityLearnType.OnSkillLearn || ability.NumSkillUps != 1))
continue;
@@ -1676,39 +1645,15 @@ namespace Game.Entities
if (skillEntry == null)
return -1;
// both free, return first slot
if (GetUInt32Value(ActivePlayerFields.ProfessionSkillLine) == 0 && GetUInt32Value(ActivePlayerFields.ProfessionSkillLine + 1) == 0)
return 0;
ActivePlayerFields professionsBegin = ActivePlayerFields.ProfessionSkillLine;
ActivePlayerFields professionsEnd = professionsBegin + 2;
// when any slot is filled we need to check both - one of them might be earlier step of the same profession
ActivePlayerFields sameProfessionSlot = professionsEnd;
for (var slot = professionsBegin; slot < professionsEnd; ++slot)
{
SkillLineRecord slotProfession = CliDB.SkillLineStorage.LookupByKey(GetUInt32Value(slot));
if (slotProfession != null)
{
if (slotProfession.ParentSkillLineID == skillEntry.ParentSkillLineID)
{
sameProfessionSlot = slot;
break;
}
}
}
if (sameProfessionSlot != professionsEnd)
{
if (CliDB.SkillLineStorage.LookupByKey(sameProfessionSlot).ParentTierIndex < skillEntry.ParentTierIndex)
return sameProfessionSlot - professionsBegin;
return -1;
}
int index = 0;
// if there is no same profession, find any free slot
for (var slot = professionsBegin; slot < professionsEnd; ++slot)
if (GetUInt32Value(slot) == 0)
return slot - professionsBegin;
foreach (var b in m_activePlayerData.ProfessionSkillLine)
{
if (b == 0)
return index;
index++;
}
return -1;
}
@@ -2288,7 +2233,7 @@ namespace Game.Entities
public bool IsCurrentSpecMasterySpell(SpellInfo spellInfo)
{
ChrSpecializationRecord chrSpec = CliDB.ChrSpecializationStorage.LookupByKey(GetUInt32Value(PlayerFields.CurrentSpecId));
ChrSpecializationRecord chrSpec = CliDB.ChrSpecializationStorage.LookupByKey(GetPrimarySpecialization());
if (chrSpec != null)
return spellInfo.Id == chrSpec.MasterySpellID[0] || spellInfo.Id == chrSpec.MasterySpellID[1];
@@ -3107,7 +3052,7 @@ namespace Game.Entities
{
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(itemSetSpell.SpellID);
if (itemSetSpell.ChrSpecID != 0 && itemSetSpell.ChrSpecID != GetUInt32Value(PlayerFields.CurrentSpecId))
if (itemSetSpell.ChrSpecID != 0 && itemSetSpell.ChrSpecID != GetPrimarySpecialization())
ApplyEquipSpell(spellInfo, null, false, false); // item set aura is not for current spec
else
{
@@ -3197,7 +3142,7 @@ namespace Game.Entities
if (GetClass() != Class.Deathknight)
return;
int runeIndex = (int)GetPowerIndex(PowerType.Runes);
uint runeIndex = GetPowerIndex(PowerType.Runes);
if (runeIndex == (int)PowerType.Max)
return;
@@ -3208,8 +3153,8 @@ namespace Game.Entities
SetRuneCooldown(i, 0); // reset cooldowns
// set a base regen timer equal to 10 sec
SetStatFloatValue(UnitFields.PowerRegenFlatModifier + runeIndex, 0.0f);
SetStatFloatValue(UnitFields.PowerRegenInterruptedFlatModifier + runeIndex, 0.0f);
SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PowerRegenFlatModifier, (int)runeIndex), 0.0f);
SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PowerRegenInterruptedFlatModifier, (int)runeIndex), 0.0f);
}
public void UpdateAllRunesRegen()
@@ -3217,15 +3162,15 @@ namespace Game.Entities
if (GetClass() != Class.Deathknight)
return;
int runeIndex = (int)GetPowerIndex(PowerType.Runes);
uint runeIndex = GetPowerIndex(PowerType.Runes);
if (runeIndex == (int)PowerType.Max)
return;
PowerTypeRecord runeEntry = Global.DB2Mgr.GetPowerTypeEntry(PowerType.Runes);
uint cooldown = GetRuneBaseCooldown();
SetStatFloatValue(UnitFields.PowerRegenFlatModifier + runeIndex, (float)(1 * Time.InMilliseconds) / (float)cooldown - runeEntry.RegenPeace);
SetStatFloatValue(UnitFields.PowerRegenInterruptedFlatModifier + runeIndex, (float)(1 * Time.InMilliseconds) / (float)cooldown - runeEntry.RegenCombat);
SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PowerRegenFlatModifier, (int)runeIndex), (float)(1 * Time.InMilliseconds) / cooldown - runeEntry.RegenPeace);
SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PowerRegenInterruptedFlatModifier, (int)runeIndex), (float)(1 * Time.InMilliseconds) / cooldown - runeEntry.RegenCombat);
}
public uint GetRuneCooldown(byte index) { return m_runes.Cooldown[index]; }
@@ -3234,20 +3179,25 @@ namespace Game.Entities
{
// don't take reagents for spells with SPELL_ATTR5_NO_REAGENT_WHILE_PREP
if (spellInfo.HasAttribute(SpellAttr5.NoReagentWhilePrep) &&
HasFlag(UnitFields.Flags, UnitFlags.Preparation))
HasUnitFlag(UnitFlags.Preparation))
return true;
// Check no reagent use mask
FlagArray128 noReagentMask = new FlagArray128();
noReagentMask[0] = GetUInt32Value(ActivePlayerFields.NoReagentCost);
noReagentMask[1] = GetUInt32Value(ActivePlayerFields.NoReagentCost + 1);
noReagentMask[2] = GetUInt32Value(ActivePlayerFields.NoReagentCost + 2);
noReagentMask[3] = GetUInt32Value(ActivePlayerFields.NoReagentCost + 3);
noReagentMask[0] = m_activePlayerData.NoReagentCostMask[0];
noReagentMask[1] = m_activePlayerData.NoReagentCostMask[1];
noReagentMask[2] = m_activePlayerData.NoReagentCostMask[2];
noReagentMask[3] = m_activePlayerData.NoReagentCostMask[3];
if (spellInfo.SpellFamilyFlags & noReagentMask)
return true;
return false;
}
public void SetNoRegentCostMask(FlagArray128 mask)
{
for (byte i = 0; i < 4; ++i)
SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.NoReagentCostMask, i), mask[i]);
}
public void CastItemCombatSpell(DamageInfo damageInfo)
{
@@ -3469,6 +3419,16 @@ namespace Game.Entities
LearnCustomSpells();
LearnQuestRewardedSpells();
}
public void SetPetSpellPower(uint spellPower) { SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.PetSpellPower), spellPower); }
public void SetSkillLineId(uint pos, ushort skillLineId) { SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.Skill)._value.ModifyValue((SkillInfo skillInfo) => skillInfo.SkillLineID, (int)pos), skillLineId); }
public void SetSkillStep(uint pos, ushort step) { SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.Skill)._value.ModifyValue((SkillInfo skillInfo) => skillInfo.SkillStep, (int)pos), step); }
public void SetSkillRank(uint pos, ushort rank) { SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.Skill)._value.ModifyValue((SkillInfo skillInfo) => skillInfo.SkillRank, (int)pos), rank); }
public void SetSkillStartingRank(uint pos, ushort starting) { SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.Skill)._value.ModifyValue((SkillInfo skillInfo) => skillInfo.SkillStartingRank, (int)pos), starting); }
public void SetSkillMaxRank(uint pos, ushort max) { SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.Skill)._value.ModifyValue((SkillInfo skillInfo) => skillInfo.SkillMaxRank, (int)pos), max); }
public void SetSkillTempBonus(uint pos, ushort bonus) { SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.Skill)._value.ModifyValue((SkillInfo skillInfo) => skillInfo.SkillTempBonus, (int)pos), bonus); }
public void SetSkillPermBonus(uint pos, ushort bonus) { SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.Skill)._value.ModifyValue((SkillInfo skillInfo) => skillInfo.SkillPermBonus, (int)pos), bonus); }
}
public class PlayerSpell
+13 -16
View File
@@ -33,7 +33,7 @@ namespace Game.Entities
if (level < PlayerConst.MinSpecializationLevel)
ResetTalentSpecialization();
uint talentTiers = (uint)Global.DB2Mgr.GetNumTalentsAtLevel(level, GetClass());
uint talentTiers = Global.DB2Mgr.GetNumTalentsAtLevel(level, GetClass());
if (level < 15)
{
// Remove all talent points
@@ -50,7 +50,7 @@ namespace Game.Entities
}
}
SetUInt32Value(ActivePlayerFields.MaxTalentTiers, talentTiers);
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.MaxTalentTiers), talentTiers);
if (!GetSession().PlayerLoading())
SendTalentsInfoData(); // update at client
@@ -112,14 +112,14 @@ namespace Game.Entities
if (IsDead())
return TalentLearnResult.FailedCantDoThatRightNow;
if (GetUInt32Value(PlayerFields.CurrentSpecId) == 0)
if (GetPrimarySpecialization() == 0)
return TalentLearnResult.FailedNoPrimaryTreeSelected;
TalentRecord talentInfo = CliDB.TalentStorage.LookupByKey(talentId);
if (talentInfo == null)
return TalentLearnResult.FailedUnknown;
if (talentInfo.SpecID != 0 && talentInfo.SpecID != GetUInt32Value(PlayerFields.CurrentSpecId))
if (talentInfo.SpecID != 0 && talentInfo.SpecID != GetPrimarySpecialization())
return TalentLearnResult.FailedUnknown;
// prevent learn talent for different class (cheating)
@@ -127,7 +127,7 @@ namespace Game.Entities
return TalentLearnResult.FailedUnknown;
// check if we have enough talent points
if (talentInfo.TierID >= GetUInt32Value(ActivePlayerFields.MaxTalentTiers))
if (talentInfo.TierID >= m_activePlayerData.MaxTalentTiers)
return TalentLearnResult.FailedUnknown;
// TODO: prevent changing talents that are on cooldown
@@ -144,7 +144,7 @@ namespace Game.Entities
if (talent.SpecID == 0)
bestSlotMatch = talent;
else if (talent.SpecID == GetUInt32Value(PlayerFields.CurrentSpecId))
else if (talent.SpecID == GetPrimarySpecialization())
{
bestSlotMatch = talent;
break;
@@ -159,13 +159,13 @@ namespace Game.Entities
{
foreach (TalentRecord talent in Global.DB2Mgr.GetTalentsByPosition(GetClass(), talentInfo.TierID, c))
{
if (talent.SpecID != 0 && talent.SpecID != GetUInt32Value(PlayerFields.CurrentSpecId))
if (talent.SpecID != 0 && talent.SpecID != GetPrimarySpecialization())
continue;
if (!HasTalent(talent.Id, GetActiveTalentGroup()))
continue;
if (!HasFlag(PlayerFields.Flags, PlayerFlags.Resting) && HasFlag(UnitFields.Flags2, UnitFlags2.AllowChangingTalents))
if (!HasPlayerFlag(PlayerFlags.Resting) && HasUnitFlag2(UnitFlags2.AllowChangingTalents))
return TalentLearnResult.FailedRestArea;
if (GetSpellHistory().HasCooldown(talent.SpellID))
@@ -221,7 +221,6 @@ namespace Game.Entities
ChrSpecializationRecord defaultSpec = Global.DB2Mgr.GetDefaultChrSpecializationForClass(GetClass());
SetPrimarySpecialization(defaultSpec.Id);
SetActiveTalentGroup(defaultSpec.OrderIndex);
SetUInt32Value(PlayerFields.CurrentSpecId, defaultSpec.Id);
LearnSpecializationSpells();
@@ -238,14 +237,14 @@ namespace Game.Entities
void SetTalentResetCost(uint cost) { _specializationInfo.ResetTalentsCost = cost; }
long GetTalentResetTime() { return _specializationInfo.ResetTalentsTime; }
void SetTalentResetTime(long time_) { _specializationInfo.ResetTalentsTime = time_; }
uint GetPrimarySpecialization() { return _specializationInfo.PrimarySpecialization; }
void SetPrimarySpecialization(uint spec) { _specializationInfo.PrimarySpecialization = spec; }
public uint GetPrimarySpecialization() { return m_playerData.CurrentSpecID; }
void SetPrimarySpecialization(uint spec) { SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.CurrentSpecID), spec); }
public byte GetActiveTalentGroup() { return _specializationInfo.ActiveGroup; }
void SetActiveTalentGroup(byte group) { _specializationInfo.ActiveGroup = group; }
// Loot Spec
public void SetLootSpecId(uint id) { SetUInt32Value(ActivePlayerFields.LootSpecId, id); }
uint GetLootSpecId() { return GetUInt32Value(ActivePlayerFields.LootSpecId); }
public void SetLootSpecId(uint id) { SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.LootSpecID), (ushort)id); }
public uint GetLootSpecId() { return m_activePlayerData.LootSpecID; }
public uint GetDefaultSpecId()
{
@@ -334,9 +333,7 @@ namespace Game.Entities
RemoveAurasDueToSpell(CliDB.GlyphPropertiesStorage.LookupByKey(glyphId).SpellID);
SetActiveTalentGroup(spec.OrderIndex);
SetUInt32Value(PlayerFields.CurrentSpecId, spec.Id);
if (GetPrimarySpecialization() == 0)
SetPrimarySpecialization(spec.Id);
SetPrimarySpecialization(spec.Id);
foreach (var talentInfo in CliDB.TalentStorage.Values)
{
File diff suppressed because it is too large Load Diff
+22 -24
View File
@@ -11,9 +11,7 @@ namespace Game.Entities
public void SetRestBonus(RestTypes restType, float restBonus)
{
byte rest_rested_offset;
byte rest_state_offset;
ActivePlayerFields next_level_xp_field;
uint next_level_xp;
bool affectedByRaF = false;
switch (restType)
@@ -23,9 +21,7 @@ namespace Game.Entities
if (_player.getLevel() >= WorldConfig.GetIntValue(WorldCfg.MaxPlayerLevel))
restBonus = 0;
rest_rested_offset = PlayerFieldOffsets.RestRestedXp;
rest_state_offset = PlayerFieldOffsets.RestStateXp;
next_level_xp_field = ActivePlayerFields.NextLevelXp;
next_level_xp = _player.m_activePlayerData.NextLevelXP;
affectedByRaF = true;
break;
case RestTypes.Honor:
@@ -33,37 +29,39 @@ namespace Game.Entities
if (_player.IsMaxHonorLevel())
restBonus = 0;
rest_rested_offset = PlayerFieldOffsets.RestRestedHonor;
rest_state_offset = PlayerFieldOffsets.RestStateHonor;
next_level_xp_field = ActivePlayerFields.HonorNextLevel;
next_level_xp = _player.m_activePlayerData.HonorNextLevel;
break;
default:
return;
}
float rest_bonus_max = next_level_xp * 1.5f / 2;
if (restBonus < 0)
restBonus = 0;
float rest_bonus_max = (float)(_player.GetUInt32Value(next_level_xp_field)) * 1.5f / 2;
if (restBonus > rest_bonus_max)
_restBonus[(int)restType] = rest_bonus_max;
else
_restBonus[(int)restType] = restBonus;
restBonus = rest_bonus_max;
_restBonus[(int)restType] = restBonus;
uint oldBonus = (uint)_restBonus[(int)restType];
if (oldBonus == restBonus)
return;
// update data for client
if (affectedByRaF && _player.GetsRecruitAFriendBonus(true) && (_player.GetSession().IsARecruiter() || _player.GetSession().GetRecruiterId() != 0))
_player.SetUInt32Value(ActivePlayerFields.RestInfo + rest_state_offset, (uint)PlayerRestState.RAFLinked);
_player.SetRestState(restType, PlayerRestState.RAFLinked);
else
{
if (_restBonus[(int)restType] > 10)
_player.SetUInt32Value(ActivePlayerFields.RestInfo + rest_state_offset, (uint)PlayerRestState.Rested);
_player.SetRestState(restType, PlayerRestState.Rested);
else if (_restBonus[(int)restType] <= 1)
_player.SetUInt32Value(ActivePlayerFields.RestInfo + rest_state_offset, (uint)PlayerRestState.NotRAFLinked);
_player.SetRestState(restType, PlayerRestState.NotRAFLinked);
}
// RestTickUpdate
_player.SetUInt32Value(ActivePlayerFields.RestInfo + rest_rested_offset, (uint)_restBonus[(int)restType]);
_player.SetRestThreshold(restType, (uint)_restBonus[(int)restType]);
}
public void AddRestBonus(RestTypes restType, float restBonus)
@@ -84,7 +82,7 @@ namespace Game.Entities
if (oldRestMask == 0 && _restFlagMask != 0) // only set flag/time on the first rest state
{
_restTime = Time.UnixTime;
_player.SetFlag(PlayerFields.Flags, PlayerFlags.Resting);
_player.AddPlayerFlag(PlayerFlags.Resting);
}
if (triggerId != 0)
@@ -99,7 +97,7 @@ namespace Game.Entities
if (oldRestMask != 0 && _restFlagMask == 0) // only remove flag/time on the last rest state remove
{
_restTime = 0;
_player.RemoveFlag(PlayerFields.Flags, PlayerFlags.Resting);
_player.RemovePlayerFlag(PlayerFlags.Resting);
}
}
@@ -135,8 +133,8 @@ namespace Game.Entities
public void LoadRestBonus(RestTypes restType, PlayerRestState state, float restBonus)
{
_restBonus[(int)restType] = restBonus;
_player.SetUInt32Value(ActivePlayerFields.RestInfo + (int)restType * 2, (uint)state);
_player.SetUInt32Value(ActivePlayerFields.RestInfo + (int)restType * 2 + 1, (uint)restBonus);
_player.SetRestState(restType, state);
_player.SetRestThreshold(restType, (uint)restBonus);
}
public float CalcExtraPerSec(RestTypes restType, float bubble)
@@ -144,9 +142,9 @@ namespace Game.Entities
switch (restType)
{
case RestTypes.Honor:
return (_player.GetUInt32Value(ActivePlayerFields.HonorNextLevel)) / 72000.0f * bubble;
return _player.m_activePlayerData.HonorNextLevel / 72000.0f * bubble;
case RestTypes.XP:
return (_player.GetUInt32Value(ActivePlayerFields.NextLevelXp)) / 72000.0f * bubble;
return _player.m_activePlayerData.NextLevelXP / 72000.0f * bubble;
default:
return 0.0f;
}
+159 -162
View File
@@ -183,12 +183,18 @@ namespace Game.Entities
public void ApplyStatBuffMod(Stats stat, float val, bool apply)
{
ApplyModSignedFloatValue((val > 0 ? UnitFields.PosStat + (int)stat : UnitFields.NegStat + (int)stat), val, apply);
MathFunctions.ApplyPercentModFloatVar(ref (val > 0 ? ref m_floatStatPosBuff[(int)stat] : ref m_floatStatNegBuff[(int)stat]), val, apply);
UpdateStatBuffModForClient(stat);
}
public void ApplyStatPercentBuffMod(Stats stat, float val, bool apply)
{
ApplyPercentModFloatValue(UnitFields.PosStat + (int)stat, val, apply);
ApplyPercentModFloatValue(UnitFields.NegStat + (int)stat, val, apply);
MathFunctions.ApplyPercentModFloatVar(ref m_floatStatPosBuff[(int)stat], val, apply);
MathFunctions.ApplyPercentModFloatVar(ref m_floatStatNegBuff[(int)stat], val, apply);
}
void UpdateStatBuffModForClient(Stats stat)
{
SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.StatPosBuff, (int)stat), (int)m_floatStatPosBuff[(int)stat]);
SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.StatNegBuff, (int)stat), (int)m_floatStatNegBuff[(int)stat]);
}
public virtual bool UpdateStats(Stats stat) { return false; }
@@ -219,16 +225,16 @@ namespace Game.Entities
{
case WeaponAttackType.BaseAttack:
default:
SetStatFloatValue(UnitFields.MinDamage, minDamage);
SetStatFloatValue(UnitFields.MaxDamage, maxDamage);
SetUpdateFieldStatValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.MinDamage), minDamage);
SetUpdateFieldStatValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.MaxDamage), maxDamage);
break;
case WeaponAttackType.OffAttack:
SetStatFloatValue(UnitFields.MinOffHandDamage, minDamage);
SetStatFloatValue(UnitFields.MaxOffHandDamage, maxDamage);
SetUpdateFieldStatValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.MinOffHandDamage), minDamage);
SetUpdateFieldStatValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.MaxOffHandDamage), maxDamage);
break;
case WeaponAttackType.RangedAttack:
SetStatFloatValue(UnitFields.MinRangedDamage, minDamage);
SetStatFloatValue(UnitFields.MaxRangedDamage, maxDamage);
SetUpdateFieldStatValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.MinRangedDamage), minDamage);
SetUpdateFieldStatValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.MaxRangedDamage), maxDamage);
break;
}
}
@@ -245,26 +251,10 @@ namespace Game.Entities
}
//Stats
public float GetStat(Stats stat)
{
return GetUInt32Value(UnitFields.Stat + (int)stat);
}
public void SetCreateStat(Stats stat, float val)
{
CreateStats[(int)stat] = val;
}
public void SetStat(Stats stat, int val)
{
SetStatInt32Value(UnitFields.Stat + (int)stat, val);
}
public void SetCreateMana(uint val)
{
SetUInt32Value(UnitFields.BaseMana, val);
}
public uint GetCreateMana()
{
return GetUInt32Value(UnitFields.BaseMana);
}
public float GetStat(Stats stat) { return m_unitData.Stats[(int)stat]; }
public void SetStat(Stats stat, int val) { SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Stats, (int)stat), val); }
public uint GetCreateMana() { return m_unitData.BaseMana; }
public void SetCreateMana(uint val) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.BaseMana), val); }
public uint GetArmor()
{
return (uint)(GetResistance(SpellSchools.Normal) + GetBonusResistanceMod(SpellSchools.Normal));
@@ -274,13 +264,23 @@ namespace Game.Entities
SetResistance(SpellSchools.Normal, val);
SetBonusResistanceMod(SpellSchools.Normal, bonusVal);
}
public float GetCreateStat(Stats stat)
{
return CreateStats[(int)stat];
}
public void SetCreateStat(Stats stat, float val)
{
CreateStats[(int)stat] = val;
}
public float GetPosStat(Stats stat) { return m_unitData.StatPosBuff[(int)stat]; }
public float GetNegStat(Stats stat) { return m_unitData.StatNegBuff[(int)stat]; }
public int GetResistance(SpellSchools school)
{
return GetInt32Value(UnitFields.Resistances + (int)school);
return m_unitData.Resistances[(int)school];
}
public int GetBonusResistanceMod(SpellSchools school)
{
return GetInt32Value(UnitFields.BonusResistanceMods + (int)school);
return m_unitData.BonusResistanceMods[(int)school];
}
public int GetResistance(SpellSchoolMask mask)
{
@@ -295,25 +295,22 @@ namespace Game.Entities
// resist value will never be negative here
return resist.HasValue ? resist.Value : 0;
}
public void SetResistance(SpellSchools school, int val)
{
SetStatInt32Value(UnitFields.Resistances + (int)school, val);
}
public void SetBonusResistanceMod(SpellSchools school, int val)
{
SetStatInt32Value(UnitFields.BonusResistanceMods + (int)school, val);
}
public void SetResistance(SpellSchools school, int val) { SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Resistances, (int)school), val); }
public void SetBonusResistanceMod(SpellSchools school, int val) { SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.BonusResistanceMods, (int)school), val); }
public void SetModCastingSpeed(float castingSpeed) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModCastingSpeed), castingSpeed); }
public void SetModSpellHaste(float spellHaste) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModSpellHaste), spellHaste); }
public void SetModHaste(float haste) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModHaste), haste); }
public void SetModRangedHaste(float rangedHaste) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModRangedHaste), rangedHaste); }
public void SetModHasteRegen(float hasteRegen) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModHasteRegen), hasteRegen); }
public void SetModTimeRate(float timeRate) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModTimeRate), timeRate); }
public float GetCreateStat(Stats stat)
{
return CreateStats[(int)stat];
}
public void InitStatBuffMods()
{
for (var i = Stats.Strength; i < Stats.Max; ++i)
for (var stat = Stats.Strength; stat < Stats.Max; ++stat)
{
SetFloatValue(UnitFields.PosStat + (int)i, 0);
SetFloatValue(UnitFields.NegStat + (int)i, 0);
m_floatStatPosBuff[(int)stat] = 0.0f;
m_floatStatNegBuff[(int)stat] = 0.0f;
UpdateStatBuffModForClient(stat);
}
}
@@ -341,16 +338,10 @@ namespace Game.Entities
return value;
}
//Health
public uint GetCreateHealth() { return GetUInt32Value(UnitFields.BaseHealth); }
public ulong GetHealth() { return GetUInt64Value(UnitFields.Health); }
public ulong GetMaxHealth() { return GetUInt64Value(UnitFields.MaxHealth); }
public float GetHealthPct() { return GetMaxHealth() != 0 ? 100.0f * GetHealth() / GetMaxHealth() : 0.0f; }
public void SetCreateHealth(uint val)
{
SetUInt32Value(UnitFields.BaseHealth, val);
}
//Health
public uint GetCreateHealth() { return m_unitData.BaseHealth; }
public void SetCreateHealth(uint val) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.BaseHealth), val); }
public ulong GetHealth() { return m_unitData.Health; }
public void SetHealth(ulong val)
{
if (getDeathState() == DeathState.JustDied)
@@ -364,7 +355,7 @@ namespace Game.Entities
val = maxHealth;
}
SetUInt64Value(UnitFields.Health, val);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Health), val);
// group update
Player player = ToPlayer();
@@ -380,13 +371,14 @@ namespace Game.Entities
pet.SetGroupUpdateFlag(GroupUpdatePetFlags.CurHp);
}
}
public ulong GetMaxHealth() { return m_unitData.MaxHealth; }
public void SetMaxHealth(ulong val)
{
if (val == 0)
val = 1;
ulong health = GetHealth();
SetUInt64Value(UnitFields.MaxHealth, val);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.MaxHealth), val);
// group update
if (IsTypeId(TypeId.Player))
@@ -404,6 +396,7 @@ namespace Game.Entities
if (val < health)
SetHealth(val);
}
public float GetHealthPct() { return GetMaxHealth() != 0 ? 100.0f * GetHealth() / GetMaxHealth() : 0.0f; }
public void SetFullHealth() { SetHealth(GetMaxHealth()); }
public bool IsFullHealth() { return GetHealth() == GetMaxHealth(); }
@@ -419,21 +412,19 @@ namespace Game.Entities
public virtual float GetArmorMultiplierForTarget(WorldObject target) { return 1.0f; }
//Powers
public PowerType GetPowerType()
{
return (PowerType)GetUInt32Value(UnitFields.DisplayPower);
}
public PowerType GetPowerType() { return (PowerType)(byte)m_unitData.DisplayPower; }
public void SetPowerType(PowerType powerType)
{
if (GetPowerType() == powerType)
return;
SetUInt32Value(UnitFields.DisplayPower, (uint)powerType);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.DisplayPower), (byte)powerType);
if (IsTypeId(TypeId.Player))
Player thisPlayer = ToPlayer();
if (thisPlayer != null)
{
if (ToPlayer().GetGroup())
ToPlayer().SetGroupUpdateFlag(GroupUpdateFlags.PowerType);
if (thisPlayer.GetGroup())
thisPlayer.SetGroupUpdateFlag(GroupUpdateFlags.PowerType);
}
/*else if (IsPet()) TODO 6.x
{
@@ -461,6 +452,8 @@ namespace Game.Entities
break;
}
}
public void SetOverrideDisplayPowerId(uint powerDisplayId) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.OverrideDisplayPowerID), powerDisplayId); }
public void SetMaxPower(PowerType powerType, int val)
{
uint powerIndex = GetPowerIndex(powerType);
@@ -468,7 +461,7 @@ namespace Game.Entities
return;
int cur_power = GetPower(powerType);
SetInt32Value(UnitFields.MaxPower + (int)powerIndex, val);
SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.MaxPower, (int)powerIndex), (uint)val);
// group update
if (IsTypeId(TypeId.Player))
@@ -496,7 +489,7 @@ namespace Game.Entities
if (maxPower < val)
val = maxPower;
SetInt32Value(UnitFields.Power + (int)powerIndex, val);
SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Power, (int)powerIndex), val);
if (IsInWorld)
{
@@ -527,7 +520,7 @@ namespace Game.Entities
if (powerIndex == (int)PowerType.Max || powerIndex >= (int)PowerType.MaxPerClass)
return 0;
return GetInt32Value(UnitFields.Power + (int)powerIndex);
return m_unitData.Power[(int)powerIndex];
}
public int GetMaxPower(PowerType powerType)
{
@@ -535,7 +528,7 @@ namespace Game.Entities
if (powerIndex == (int)PowerType.Max || powerIndex >= (int)PowerType.MaxPerClass)
return 0;
return GetInt32Value(UnitFields.MaxPower + (int)powerIndex);
return (int)(uint)m_unitData.MaxPower[(int)powerIndex];
}
public int GetCreatePowers(PowerType powerType)
{
@@ -597,6 +590,15 @@ namespace Game.Entities
return MathFunctions.CalculatePct(damage, percent);
}
public void SetAttackPower(int attackPower) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.AttackPower), attackPower); }
public void SetAttackPowerModPos(int attackPowerMod) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.AttackPowerModPos), attackPowerMod); }
public void SetAttackPowerModNeg(int attackPowerMod) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.AttackPowerModNeg), attackPowerMod); }
public void SetAttackPowerMultiplier(float attackPowerMult) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.AttackPowerMultiplier), attackPowerMult); }
public void SetRangedAttackPower(int attackPower) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.RangedAttackPower), attackPower); }
public void SetRangedAttackPowerModPos(int attackPowerMod) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.RangedAttackPowerModPos), attackPowerMod); }
public void SetRangedAttackPowerModNeg(int attackPowerMod) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.RangedAttackPowerModNeg), attackPowerMod); }
public void SetRangedAttackPowerMultiplier(float attackPowerMult) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.RangedAttackPowerMultiplier), attackPowerMult); }
//Chances
float MeleeSpellMissChance(Unit victim, WeaponAttackType attType, uint spellId)
{
@@ -635,18 +637,19 @@ namespace Game.Entities
float GetUnitCriticalChance(WeaponAttackType attackType, Unit victim)
{
float chance = 0.0f;
if (IsTypeId(TypeId.Player))
Player thisPlayer = ToPlayer();
if (thisPlayer != null)
{
switch (attackType)
{
case WeaponAttackType.BaseAttack:
chance = GetFloatValue(ActivePlayerFields.CritPercentage);
chance = thisPlayer.m_activePlayerData.CritPercentage;
break;
case WeaponAttackType.OffAttack:
chance = GetFloatValue(ActivePlayerFields.OffhandCritPercentage);
chance = thisPlayer.m_activePlayerData.OffhandCritPercentage;
break;
case WeaponAttackType.RangedAttack:
chance = GetFloatValue(ActivePlayerFields.RangedCritPercentage);
chance = thisPlayer.m_activePlayerData.RangedCritPercentage;
break;
}
}
@@ -684,8 +687,9 @@ namespace Game.Entities
float chance = 0.0f;
float levelBonus = 0.0f;
if (victim.IsTypeId(TypeId.Player))
chance = victim.GetFloatValue(ActivePlayerFields.DodgePercentage);
Player playerVictim = victim.ToPlayer();
if (playerVictim)
chance = playerVictim.m_activePlayerData.DodgePercentage;
else
{
if (!victim.IsTotem())
@@ -729,7 +733,7 @@ namespace Game.Entities
tmpitem = playerVictim.GetWeaponForAttack(WeaponAttackType.OffAttack, true);
if (tmpitem)
chance = playerVictim.GetFloatValue(ActivePlayerFields.ParryPercentage);
chance = playerVictim.m_activePlayerData.ParryPercentage;
}
}
else
@@ -777,7 +781,7 @@ namespace Game.Entities
{
Item tmpitem = playerVictim.GetUseableItemByPos(InventorySlots.Bag0, EquipmentSlot.OffHand);
if (tmpitem && !tmpitem.IsBroken() && tmpitem.GetTemplate().GetInventoryType() == InventoryType.Shield)
chance = playerVictim.GetFloatValue(ActivePlayerFields.BlockPercentage);
chance = playerVictim.m_activePlayerData.BlockPercentage;
}
}
else
@@ -796,7 +800,7 @@ namespace Game.Entities
return Math.Max(chance, 0.0f);
}
int GetMechanicResistChance(SpellInfo spellInfo)
public int GetMechanicResistChance(SpellInfo spellInfo)
{
if (spellInfo == null)
return 0;
@@ -817,6 +821,9 @@ namespace Game.Entities
}
return Math.Max(resistMech, 0);
}
public void ApplyModPowerCostModifier(SpellSchools school, int mod, bool apply) { ApplyModUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PowerCostModifier, (int)school), mod, apply); }
public void ApplyModPowerCostMultiplier(SpellSchools school, float pct, bool apply) { ApplyModUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PowerCostMultiplier, (int)school), pct, apply); }
}
public partial class Player
@@ -925,7 +932,14 @@ namespace Game.Entities
UpdateArmor();
}
void RecalculateRating(CombatRating cr) { ApplyRatingMod(cr, 0, true); }
public void ApplyModTargetResistance(int mod, bool apply) { ApplyModUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModTargetResistance), mod, apply); }
public void ApplyModTargetPhysicalResistance(int mod, bool apply) { ApplyModUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModTargetPhysicalResistance), mod, apply); }
public void RecalculateRating(CombatRating cr) { ApplyRatingMod(cr, 0, true); }
public void ApplyModDamageDonePos(SpellSchools school, int mod, bool apply) { ApplyModUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModDamageDonePos, (int)school), mod, apply); }
public void ApplyModDamageDoneNeg(SpellSchools school, int mod, bool apply) { ApplyModUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModDamageDoneNeg, (int)school), mod, apply); }
public void ApplyModDamageDonePercent(SpellSchools school, float pct, bool apply) { ApplyPercentModUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModDamageDonePercent, (int)school), pct, apply); }
public void ApplyRatingMod(CombatRating combatRating, int value, bool apply)
{
@@ -989,7 +1003,7 @@ namespace Game.Entities
max_damage = ((baseValue + weaponMaxDamage) * basePct + totalValue) * totalPct * versaDmgMod;
}
void UpdateAllCritPercentages()
public void UpdateAllCritPercentages()
{
float value = 5.0f;
@@ -1004,7 +1018,7 @@ namespace Game.Entities
public void UpdateManaRegen()
{
int manaIndex = (int)GetPowerIndex(PowerType.Mana);
uint manaIndex = GetPowerIndex(PowerType.Mana);
if (manaIndex == (int)PowerType.Max)
return;
@@ -1021,8 +1035,8 @@ namespace Game.Entities
// Apply PCT bonus from SPELL_AURA_MOD_MANA_REGEN_PCT
base_regen *= GetTotalAuraMultiplierByMiscValue(AuraType.ModManaRegenPct, (int)PowerType.Mana);
SetFloatValue(UnitFields.PowerRegenInterruptedFlatModifier + manaIndex, base_regen);
SetFloatValue(UnitFields.PowerRegenFlatModifier + manaIndex, base_regen);
SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PowerRegenFlatModifier, (int)manaIndex), base_regen);
SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PowerRegenInterruptedFlatModifier, (int)manaIndex), base_regen);
}
public void UpdateSpellDamageAndHealingBonus()
@@ -1030,18 +1044,19 @@ namespace Game.Entities
// Magic damage modifiers implemented in Unit.SpellDamageBonusDone
// This information for client side use only
// Get healing bonus for all schools
SetStatInt32Value(ActivePlayerFields.ModHealingDonePos, (int)SpellBaseHealingBonusDone(SpellSchoolMask.All));
SetUpdateFieldStatValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModHealingDonePos), (int)SpellBaseHealingBonusDone(SpellSchoolMask.All));
// Get damage bonus for all schools
var modDamageAuras = GetAuraEffectsByType(AuraType.ModDamageDone);
for (var i = SpellSchools.Holy; i < SpellSchools.Max; ++i)
for (int i = (int)SpellSchools.Holy; i < (int)SpellSchools.Max; ++i)
{
SetInt32Value(ActivePlayerFields.ModDamageDoneNeg + (int)i, modDamageAuras.Aggregate(0, (negativeMod, aurEff) =>
SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModDamageDoneNeg, i), modDamageAuras.Aggregate(0, (negativeMod, aurEff) =>
{
if (aurEff.GetAmount() < 0 && Convert.ToBoolean(aurEff.GetMiscValue() & (1 << (int)i)))
if (aurEff.GetAmount() < 0 && Convert.ToBoolean(aurEff.GetMiscValue() & (1 << i)))
negativeMod += aurEff.GetAmount();
return negativeMod;
}));
SetStatInt32Value(ActivePlayerFields.ModDamageDonePos + (int)i, SpellBaseDamageBonusDone((SpellSchoolMask)(1 << (int)i)) - GetInt32Value(ActivePlayerFields.ModDamageDoneNeg + (int)i));
SetUpdateFieldStatValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModDamageDonePos, i),
(SpellBaseDamageBonusDone((SpellSchoolMask)(1 << i)) - m_activePlayerData.ModDamageDoneNeg[i]));
}
if (HasAuraType(AuraType.OverrideAttackPowerBySpPct))
@@ -1060,17 +1075,6 @@ namespace Game.Entities
var entry = CliDB.ChrClassesStorage.LookupByKey(GetClass());
UnitMods unitMod = ranged ? UnitMods.AttackPowerRanged : UnitMods.AttackPower;
UnitFields index = UnitFields.AttackPower;
UnitFields index_mod = UnitFields.AttackPowerModPos;
UnitFields index_mult = UnitFields.AttackPowerMultiplier;
if (ranged)
{
index = UnitFields.RangedAttackPower;
index_mod = UnitFields.RangedAttackPowerModPos;
index_mult = UnitFields.RangedAttackPowerMultiplier;
}
if (!HasAuraType(AuraType.OverrideAttackPowerBySpPct))
{
if (!ranged)
@@ -1090,11 +1094,11 @@ namespace Game.Entities
}
else
{
int minSpellPower = GetInt32Value(ActivePlayerFields.ModHealingDonePos);
int minSpellPower = m_activePlayerData.ModHealingDonePos;
for (var i = SpellSchools.Holy; i < SpellSchools.Max; ++i)
minSpellPower = Math.Min(minSpellPower, GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)i));
minSpellPower = Math.Min(minSpellPower, m_activePlayerData.ModDamageDonePos[(int)i]);
val2 = MathFunctions.CalculatePct(minSpellPower, GetFloatValue(ActivePlayerFields.OverrideApBySpellPowerPercent));
val2 = MathFunctions.CalculatePct(minSpellPower, m_activePlayerData.OverrideAPBySpellPowerPercent);
}
SetModifierValue(unitMod, UnitModifierType.BaseValue, val2);
@@ -1112,9 +1116,18 @@ namespace Game.Entities
attPowerMod += (int)(GetArmor() / iter.GetAmount());
}
SetUInt32Value(index, (uint)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field
SetUInt32Value(index_mod, (uint)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MOD_POS field
SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field
if (ranged)
{
SetRangedAttackPower((int)base_attPower);
SetRangedAttackPowerModPos((int)attPowerMod);
SetRangedAttackPowerMultiplier(attPowerMultiplier);
}
else
{
SetAttackPower((int)base_attPower);
SetAttackPowerModPos((int)attPowerMod);
SetAttackPowerMultiplier(attPowerMultiplier);
}
Pet pet = GetPet(); //update pet's AP
Guardian guardian = GetGuardianPet();
@@ -1220,8 +1233,8 @@ namespace Game.Entities
if (amount < 0)
amount = 0;
uint oldRating = GetUInt32Value(ActivePlayerFields.CombatRating + (int)cr);
SetUInt32Value(ActivePlayerFields.CombatRating + (int)cr, (uint)amount);
uint oldRating = m_activePlayerData.CombatRatings[(int)cr];
SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.CombatRatings, (int)cr), (uint)amount);
bool affectStats = CanModifyStats();
@@ -1320,15 +1333,15 @@ namespace Game.Entities
{
if (!CanUseMastery())
{
SetFloatValue(ActivePlayerFields.Mastery, 0.0f);
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.Mastery), 0.0f);
return;
}
float value = GetTotalAuraModifier(AuraType.Mastery);
value += GetRatingBonusValue(CombatRating.Mastery);
SetFloatValue(ActivePlayerFields.Mastery, value);
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.Mastery), value);
ChrSpecializationRecord chrSpec = CliDB.ChrSpecializationStorage.LookupByKey(GetUInt32Value(PlayerFields.CurrentSpecId));
ChrSpecializationRecord chrSpec = CliDB.ChrSpecializationStorage.LookupByKey(GetPrimarySpecialization());
if (chrSpec == null)
return;
@@ -1354,8 +1367,8 @@ namespace Game.Entities
public void UpdateVersatilityDamageDone()
{
// No proof that CR_VERSATILITY_DAMAGE_DONE is allways = PLAYER_VERSATILITY
SetUInt32Value(ActivePlayerFields.Versatility, GetUInt32Value(ActivePlayerFields.CombatRating + (int)CombatRating.VersatilityDamageDone));
// No proof that CR_VERSATILITY_DAMAGE_DONE is allways = ActivePlayerData::Versatility
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.Versatility), (int)m_activePlayerData.CombatRatings[(int)CombatRating.VersatilityDamageDone]);
if (GetClass() == Class.Hunter)
UpdateDamagePhysical(WeaponAttackType.RangedAttack);
@@ -1372,13 +1385,13 @@ namespace Game.Entities
foreach (AuraEffect auraEffect in GetAuraEffectsByType(AuraType.ModHealingDonePercent))
MathFunctions.AddPct(ref value, auraEffect.GetAmount());
SetStatFloatValue(ActivePlayerFields.ModHealingDonePct, value);
SetUpdateFieldStatValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModHealingDonePercent), value);
}
void UpdateArmorPenetration(int amount)
{
// Store Rating Value
SetInt32Value(ActivePlayerFields.CombatRating + (int)CombatRating.ArmorPenetration, amount);
SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.CombatRatings, (int)CombatRating.ArmorPenetration), (uint)amount);
}
public void UpdateParryPercentage()
{
@@ -1413,10 +1426,8 @@ namespace Game.Entities
if (WorldConfig.GetBoolValue(WorldCfg.StatsLimitsEnable))
value = value > WorldConfig.GetFloatValue(WorldCfg.StatsLimitsParry) ? WorldConfig.GetFloatValue(WorldCfg.StatsLimitsParry) : value;
value = value < 0.0f ? 0.0f : value;
}
SetFloatValue(ActivePlayerFields.ParryPercentage, value);
SetUpdateFieldStatValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ParryPercentage), value);
}
public void UpdateDodgePercentage()
@@ -1450,8 +1461,7 @@ namespace Game.Entities
if (WorldConfig.GetBoolValue(WorldCfg.StatsLimitsEnable))
value = value > WorldConfig.GetFloatValue(WorldCfg.StatsLimitsDodge) ? WorldConfig.GetFloatValue(WorldCfg.StatsLimitsDodge) : value;
value = value < 0.0f ? 0.0f : value;
SetStatFloatValue(ActivePlayerFields.DodgePercentage, value);
SetUpdateFieldStatValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.DodgePercentage), value);
}
public void UpdateBlockPercentage()
{
@@ -1468,47 +1478,35 @@ namespace Game.Entities
if (WorldConfig.GetBoolValue(WorldCfg.StatsLimitsEnable))
value = value > WorldConfig.GetFloatValue(WorldCfg.StatsLimitsBlock) ? WorldConfig.GetFloatValue(WorldCfg.StatsLimitsBlock) : value;
value = value < 0.0f ? 0.0f : value;
}
SetFloatValue(ActivePlayerFields.BlockPercentage, value);
SetUpdateFieldStatValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.BlockPercentage), value);
}
public void UpdateCritPercentage(WeaponAttackType attType)
{
BaseModGroup modGroup;
ActivePlayerFields index;
CombatRating cr;
float applyCritLimit(float value)
{
if (WorldConfig.GetBoolValue(WorldCfg.StatsLimitsEnable))
value = value > WorldConfig.GetFloatValue(WorldCfg.StatsLimitsCrit) ? WorldConfig.GetFloatValue(WorldCfg.StatsLimitsCrit) : value;
return value;
}
switch (attType)
{
case WeaponAttackType.OffAttack:
modGroup = BaseModGroup.OffhandCritPercentage;
index = ActivePlayerFields.OffhandCritPercentage;
cr = CombatRating.CritMelee;
SetUpdateFieldStatValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.OffhandCritPercentage),
applyCritLimit(GetTotalPercentageModValue(BaseModGroup.OffhandCritPercentage) + GetRatingBonusValue(CombatRating.CritMelee)));
break;
case WeaponAttackType.RangedAttack:
modGroup = BaseModGroup.RangedCritPercentage;
index = ActivePlayerFields.RangedCritPercentage;
cr = CombatRating.CritRanged;
SetUpdateFieldStatValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.RangedCritPercentage),
applyCritLimit(GetTotalPercentageModValue(BaseModGroup.RangedCritPercentage) + GetRatingBonusValue(CombatRating.CritRanged)));
break;
case WeaponAttackType.BaseAttack:
default:
modGroup = BaseModGroup.CritPercentage;
index = ActivePlayerFields.CritPercentage;
cr = CombatRating.CritMelee;
SetUpdateFieldStatValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.CritPercentage),
applyCritLimit(GetTotalPercentageModValue(BaseModGroup.CritPercentage) + GetRatingBonusValue(CombatRating.CritMelee)));
break;
}
float value = GetTotalPercentageModValue(modGroup) + GetRatingBonusValue(cr);
// Modify crit from weapon skill and maximized defense skill of same level victim difference
value += (GetMaxSkillValueForLevel() - GetMaxSkillValueForLevel()) * 0.04f;
if (WorldConfig.GetBoolValue(WorldCfg.StatsLimitsEnable))
value = value > WorldConfig.GetFloatValue(WorldCfg.StatsLimitsCrit) ? WorldConfig.GetFloatValue(WorldCfg.StatsLimitsCrit) : value;
value = value < 0.0f ? 0.0f : value;
SetFloatValue(index, value);
}
public void UpdateExpertise(WeaponAttackType attack)
@@ -1528,10 +1526,10 @@ namespace Game.Entities
switch (attack)
{
case WeaponAttackType.BaseAttack:
SetInt32Value(ActivePlayerFields.Expertise, expertise);
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.MainhandExpertise), expertise);
break;
case WeaponAttackType.OffAttack:
SetInt32Value(ActivePlayerFields.OffhandExpertise, expertise);
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.OffhandExpertise), expertise);
break;
default: break;
}
@@ -1623,7 +1621,7 @@ namespace Game.Entities
crit += GetRatingBonusValue(CombatRating.CritSpell);
// Store crit value
SetFloatValue(ActivePlayerFields.SpellCritPercentage1, crit);
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.SpellCritPercentage), crit);
}
public void UpdateMeleeHitChances()
@@ -1688,7 +1686,7 @@ namespace Game.Entities
public void ApplySpellPenetrationBonus(int amount, bool apply)
{
ApplyModInt32Value(ActivePlayerFields.ModTargetResistance, -amount, apply);
ApplyModTargetResistance(-amount, apply);
m_spellPenetrationItemMod += apply ? amount : -amount;
}
@@ -1711,9 +1709,9 @@ namespace Game.Entities
apply = _ModifyUInt32(apply, ref m_baseSpellPower, ref amount);
// For speed just update for client
ApplyModUInt32Value(ActivePlayerFields.ModHealingDonePos, amount, apply);
for (int i = (int)SpellSchools.Holy; i < (int)SpellSchools.Max; ++i)
ApplyModUInt32Value(ActivePlayerFields.ModDamageDonePos + i, amount, apply);
ApplyModUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModHealingDonePos), amount, apply);
for (SpellSchools spellSchool = SpellSchools.Holy; spellSchool < SpellSchools.Max; ++spellSchool)
ApplyModDamageDonePos(spellSchool, amount, apply);
if (HasAuraType(AuraType.OverrideAttackPowerBySpPct))
{
@@ -1826,20 +1824,19 @@ namespace Game.Entities
{
UnitMods unitMod = ranged ? UnitMods.AttackPowerRanged : UnitMods.AttackPower;
UnitFields index = UnitFields.AttackPower;
UnitFields index_mult = UnitFields.AttackPowerMultiplier;
float baseAttackPower = GetModifierValue(unitMod, UnitModifierType.BaseValue) * GetModifierValue(unitMod, UnitModifierType.BasePCT);
float attackPowerMultiplier = GetModifierValue(unitMod, UnitModifierType.TotalPCT) - 1.0f;
if (ranged)
{
index = UnitFields.RangedAttackPower;
index_mult = UnitFields.RangedAttackPowerMultiplier;
SetRangedAttackPower((int)baseAttackPower);
SetRangedAttackPowerMultiplier(attackPowerMultiplier);
}
else
{
SetAttackPower((int)baseAttackPower);
SetAttackPowerMultiplier(attackPowerMultiplier);
}
float base_attPower = GetModifierValue(unitMod, UnitModifierType.BaseValue) * GetModifierValue(unitMod, UnitModifierType.BasePCT);
float attPowerMultiplier = GetModifierValue(unitMod, UnitModifierType.TotalPCT) - 1.0f;
SetInt32Value(index, (int)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field
SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field
//automatically update weapon damage after attack power modification
if (ranged)
+22 -25
View File
@@ -187,7 +187,7 @@ namespace Game.Entities
if (owner != null && IsTrigger() && m_spells[0] != 0)
{
SetFaction(owner.getFaction());
SetFaction(owner.GetFaction());
SetLevel(owner.getLevel());
if (owner.IsTypeId(TypeId.Player))
m_ControlledByPlayer = true;
@@ -215,7 +215,7 @@ namespace Game.Entities
if (m_Properties.Faction != 0)
SetFaction(m_Properties.Faction);
else if (IsVehicle() && owner != null) // properties should be vehicle
SetFaction(owner.getFaction());
SetFaction(owner.GetFaction());
}
public virtual void InitSummon()
@@ -327,7 +327,7 @@ namespace Game.Entities
SetReactState(ReactStates.Passive);
SetCreatorGUID(GetOwner().GetGUID());
SetFaction(GetOwner().getFaction());
SetFaction(GetOwner().GetFaction());
GetOwner().SetMinion(this, true);
}
@@ -448,9 +448,6 @@ namespace Game.Entities
SetBaseAttackTime(WeaponAttackType.OffAttack, SharedConst.BaseAttackTime);
SetBaseAttackTime(WeaponAttackType.RangedAttack, SharedConst.BaseAttackTime);
SetFloatValue(UnitFields.ModCastSpeed, 1.0f);
SetFloatValue(UnitFields.ModCastHaste, 1.0f);
//scale
var cFamily = CliDB.CreatureFamilyStorage.LookupByKey(cinfo.Family);
if (cFamily != null && cFamily.MinScale > 0.0f && petType == PetType.Hunter)
@@ -517,8 +514,8 @@ namespace Game.Entities
case PetType.Summon:
{
// the damage bonus used for pets is either fire or shadow damage, whatever is higher
int fire = GetOwner().GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)SpellSchools.Fire);
int shadow = GetOwner().GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)SpellSchools.Shadow);
int fire = GetOwner().ToPlayer().m_activePlayerData.ModDamageDonePos[(int)SpellSchools.Fire];
int shadow = GetOwner().ToPlayer().m_activePlayerData.ModDamageDonePos[(int)SpellSchools.Shadow];
int val = (fire > shadow) ? fire : shadow;
if (val < 0)
val = 0;
@@ -531,7 +528,7 @@ namespace Game.Entities
}
case PetType.Hunter:
{
SetUInt32Value(UnitFields.PetNextLevelExp, (uint)(Global.ObjectMgr.GetXPForLevel(petlevel) * 0.05f));
ToPet().SetPetNextLevelExperience((uint)(Global.ObjectMgr.GetXPForLevel(petlevel) * 0.05f));
//these formula may not be correct; however, it is designed to be close to what it should be
//this makes dps 0.5 of pets level
SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, petlevel - (petlevel / 4));
@@ -865,8 +862,8 @@ namespace Game.Entities
else
val = 2 * GetStat(Stats.Strength) - 20.0f;
Unit owner = GetOwner();
if (owner != null && owner.IsTypeId(TypeId.Player))
Player owner = GetOwner() ? GetOwner().ToPlayer() : null;
if (owner != null)
{
if (IsHunterPet()) //hunter pets benefit from owner's attack power
{
@@ -888,8 +885,8 @@ namespace Game.Entities
//demons benefit from warlocks shadow or fire damage
else if (IsPet())
{
int fire = owner.GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)SpellSchools.Fire) - owner.GetInt32Value(ActivePlayerFields.ModDamageDoneNeg + (int)SpellSchools.Fire);
int shadow = owner.GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)SpellSchools.Shadow) - owner.GetInt32Value(ActivePlayerFields.ModDamageDoneNeg + (int)SpellSchools.Shadow);
int fire = owner.m_activePlayerData.ModDamageDonePos[(int)SpellSchools.Fire] - owner.m_activePlayerData.ModDamageDoneNeg[(int)SpellSchools.Fire];
int shadow = owner.m_activePlayerData.ModDamageDonePos[(int)SpellSchools.Shadow] - owner.m_activePlayerData.ModDamageDoneNeg[(int)SpellSchools.Shadow];
int maximum = (fire > shadow) ? fire : shadow;
if (maximum < 0)
maximum = 0;
@@ -899,7 +896,7 @@ namespace Game.Entities
//water elementals benefit from mage's frost damage
else if (GetEntry() == ENTRY_WATER_ELEMENTAL)
{
int frost = owner.GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)SpellSchools.Frost) - owner.GetInt32Value(ActivePlayerFields.ModDamageDoneNeg + (int)SpellSchools.Frost);
int frost = owner.m_activePlayerData.ModDamageDonePos[(int)SpellSchools.Frost] - owner.m_activePlayerData.ModDamageDoneNeg[(int)SpellSchools.Frost];
if (frost < 0)
frost = 0;
SetBonusDamage((int)(frost * 0.4f));
@@ -912,10 +909,8 @@ namespace Game.Entities
float base_attPower = GetModifierValue(unitMod, UnitModifierType.BaseValue) * GetModifierValue(unitMod, UnitModifierType.BasePCT);
float attPowerMultiplier = GetModifierValue(unitMod, UnitModifierType.TotalPCT) - 1.0f;
//UNIT_FIELD_(RANGED)_ATTACK_POWER field
SetInt32Value(UnitFields.AttackPower, (int)base_attPower);
//UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field
SetFloatValue(UnitFields.AttackPowerMultiplier, attPowerMultiplier);
SetAttackPower((int)base_attPower);
SetAttackPowerMultiplier(attPowerMultiplier);
//automatically update weapon damage after attack power modification
UpdateDamagePhysical(WeaponAttackType.BaseAttack);
@@ -927,19 +922,20 @@ namespace Game.Entities
return;
float bonusDamage = 0.0f;
if (GetOwner().IsTypeId(TypeId.Player))
Player playerOwner = m_owner.ToPlayer();
if (playerOwner != null)
{
//force of nature
if (GetEntry() == ENTRY_TREANT)
{
int spellDmg = GetOwner().GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)SpellSchools.Nature) - GetOwner().GetInt32Value(ActivePlayerFields.ModDamageDoneNeg + (int)SpellSchools.Nature);
int spellDmg = playerOwner.m_activePlayerData.ModDamageDonePos[(int)SpellSchools.Nature] - playerOwner.m_activePlayerData.ModDamageDoneNeg[(int)SpellSchools.Nature];
if (spellDmg > 0)
bonusDamage = spellDmg * 0.09f;
}
//greater fire elemental
else if (GetEntry() == ENTRY_FIRE_ELEMENTAL)
{
int spellDmg = GetOwner().GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)SpellSchools.Fire) - GetOwner().GetInt32Value(ActivePlayerFields.ModDamageDoneNeg + (int)SpellSchools.Fire);
int spellDmg = playerOwner.m_activePlayerData.ModDamageDonePos[(int)SpellSchools.Fire] - playerOwner.m_activePlayerData.ModDamageDoneNeg[(int)SpellSchools.Fire];
if (spellDmg > 0)
bonusDamage = spellDmg * 0.4f;
}
@@ -960,15 +956,16 @@ namespace Game.Entities
float mindamage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct;
float maxdamage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct;
SetStatFloatValue(UnitFields.MinDamage, mindamage);
SetStatFloatValue(UnitFields.MaxDamage, maxdamage);
SetUpdateFieldStatValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.MinDamage), mindamage);
SetUpdateFieldStatValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.MaxDamage), maxdamage);
}
void SetBonusDamage(int damage)
{
m_bonusSpellDamage = damage;
if (GetOwner().IsTypeId(TypeId.Player))
GetOwner().SetUInt32Value(ActivePlayerFields.PetSpellPower, (uint)damage);
Player playerOwner = GetOwner().ToPlayer();
if (playerOwner != null)
playerOwner.SetPetSpellPower((uint)damage);
}
public int GetBonusDamage() { return m_bonusSpellDamage; }
+4 -6
View File
@@ -63,15 +63,13 @@ namespace Game.Entities
packet.Totem = GetGUID();
packet.Slot = (byte)(m_Properties.Slot - (int)SummonSlot.Totem);
packet.Duration = duration;
packet.SpellID = GetUInt32Value(UnitFields.CreatedBySpell);
packet.SpellID = m_unitData.CreatedBySpell;
owner.ToPlayer().SendPacket(packet);
}
// set display id depending on caster's race
uint totemDisplayId = Global.SpellMgr.GetModelForTotem(GetUInt32Value(UnitFields.CreatedBySpell), owner.GetRace());
if (totemDisplayId == 0)
Log.outError(LogFilter.Spells, $"Spell {GetUInt32Value(UnitFields.CreatedBySpell)} with RaceID ({owner.GetRace()}) have no totem model data defined, set to default model.");
else
uint totemDisplayId = Global.SpellMgr.GetModelForTotem(m_unitData.CreatedBySpell, owner.GetRace());
if (totemDisplayId != 0)
SetDisplayId(totemDisplayId);
}
@@ -127,7 +125,7 @@ namespace Game.Entities
{
owner.SendAutoRepeatCancel(this);
SpellInfo spell = Global.SpellMgr.GetSpellInfo(GetUInt32Value(UnitFields.CreatedBySpell));
SpellInfo spell = Global.SpellMgr.GetSpellInfo(m_unitData.CreatedBySpell);
if (spell != null)
GetSpellHistory().SendCooldownEvent(spell, 0, null, false);
+5 -5
View File
@@ -118,11 +118,11 @@ namespace Game.Entities
if (m_goTemplateAddon != null)
{
SetFaction(m_goTemplateAddon.faction);
SetUInt32Value(GameObjectFields.Flags, m_goTemplateAddon.flags);
SetFlags((GameObjectFlags)m_goTemplateAddon.flags);
}
m_goValue.Transport.PathProgress = 0;
SetFloatValue(ObjectFields.ScaleX, goinfo.size);
SetObjectScale(goinfo.size);
SetPeriod(tInfo.pathTime);
SetEntry(goinfo.entry);
SetDisplayId(goinfo.displayId);
@@ -473,7 +473,7 @@ namespace Game.Entities
PhasingHandler.InheritPhaseShift(summon, summoner ? (WorldObject)summoner : this);
summon.SetUInt32Value(UnitFields.CreatedBySpell, spellId);
summon.SetCreatedBySpell(spellId);
summon.SetTransport(this);
summon.m_movementInfo.transport.guid = GetGUID();
@@ -778,8 +778,8 @@ namespace Game.Entities
public HashSet<WorldObject> GetPassengers() { return _passengers; }
public override uint GetTransportPeriod() { return GetUInt32Value(GameObjectFields.Level); }
public void SetPeriod(uint period) { SetUInt32Value(GameObjectFields.Level, period); }
public override uint GetTransportPeriod() { return m_gameObjectData.Level; }
public void SetPeriod(uint period) { SetLevel(period); }
uint GetTimer() { return m_goValue.Transport.PathProgress; }
public List<KeyFrame> GetKeyFrames() { return _transportInfo.keyFrames; }
+2 -2
View File
@@ -236,9 +236,9 @@ namespace Game.Entities
{
_petnumber = petnumber;
if (statwindow)
_unit.SetUInt32Value(UnitFields.PetNumber, _petnumber);
_unit.SetPetNumberForClient(_petnumber);
else
_unit.SetUInt32Value(UnitFields.PetNumber, 0);
_unit.SetPetNumberForClient(0);
}
public void LoadPetActionBar(string data)
+98 -67
View File
@@ -246,15 +246,15 @@ namespace Game.Entities
public void ClearInCombat()
{
m_CombatTimer = 0;
RemoveFlag(UnitFields.Flags, UnitFlags.InCombat);
RemoveUnitFlag(UnitFlags.InCombat);
// Player's state will be cleared in Player.UpdateContestedPvP
Creature creature = ToCreature();
if (creature != null)
{
ClearUnitState(UnitState.AttackPlayer);
if (HasFlag(ObjectFields.DynamicFlags, UnitDynFlags.Tapped))
SetUInt32Value(ObjectFields.DynamicFlags, creature.GetCreatureTemplate().DynamicFlags);
if (HasDynamicFlag(UnitDynFlags.Tapped))
SetDynamicFlags((UnitDynFlags)creature.GetCreatureTemplate().DynamicFlags);
if (creature.IsPet() || creature.IsGuardian())
{
@@ -270,7 +270,7 @@ namespace Game.Entities
else
ToPlayer().OnCombatExit();
RemoveFlag(UnitFields.Flags, UnitFlags.PetInCombat);
RemoveUnitFlag(UnitFlags.PetInCombat);
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.LeaveCombat);
}
@@ -314,7 +314,7 @@ namespace Game.Entities
if (!IsAlive())
return false;
if (HasFlag(UnitFields.Flags, (UnitFlags.NonAttackable | UnitFlags.NotSelectable)))
if (HasUnitFlag(UnitFlags.NonAttackable | UnitFlags.NotSelectable))
return false;
if (IsTypeId(TypeId.Player) && ToPlayer().IsGameMaster())
@@ -329,7 +329,7 @@ namespace Game.Entities
}
public bool IsInCombat()
{
return HasFlag(UnitFields.Flags, UnitFlags.InCombat);
return HasUnitFlag(UnitFlags.InCombat);
}
public bool Attack(Unit victim, bool meleeAttack)
{
@@ -344,7 +344,7 @@ namespace Game.Entities
if (IsTypeId(TypeId.Player) && IsMounted())
return false;
if (HasFlag(UnitFields.Flags, UnitFlags.Pacified))
if (HasUnitFlag(UnitFlags.Pacified))
return false;
// nobody can attack GM in GM-mode
@@ -417,7 +417,7 @@ namespace Game.Entities
ToCreature().CallAssistance();
// Remove emote state - will be restored on creature reset
SetUInt32Value(UnitFields.NpcEmotestate, (uint)Emote.OneshotNone);
SetEmoteState(Emote.OneshotNone);
}
// delay offhand weapon attack to next attack time
@@ -455,7 +455,7 @@ namespace Game.Entities
else
Log.outInfo(LogFilter.Unit, "{0} {1} stopped attacking", (IsTypeId(TypeId.Player) ? "Player" : "Creature"), GetGUID().ToString());
}
public ObjectGuid GetTarget() { return GetGuidValue(UnitFields.Target); }
public ObjectGuid GetTarget() { return m_unitData.Target; }
public virtual void SetTarget(ObjectGuid guid) { }
public bool AttackStop()
{
@@ -517,8 +517,10 @@ namespace Game.Entities
return attackerList;
}
public float GetCombatReach() { return GetFloatValue(UnitFields.CombatReach); }
float GetBoundaryRadius() { return GetFloatValue(UnitFields.BoundingRadius); }
public float GetCombatReach() { return m_unitData.CombatReach; }
public void SetCombatReach(float combatReach) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.CombatReach), combatReach); }
public float GetBoundingRadius() { return m_unitData.BoundingRadius; }
public void SetBoundingRadius(float boundingRadius) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.BoundingRadius), boundingRadius); }
public bool haveOffhandWeapon()
{
@@ -549,7 +551,7 @@ namespace Game.Entities
}
public void AttackerStateUpdate(Unit victim, WeaponAttackType attType = WeaponAttackType.BaseAttack, bool extra = false)
{
if (HasUnitState(UnitState.CannotAutoattack) || HasFlag(UnitFields.Flags, UnitFlags.Pacified))
if (HasUnitState(UnitState.CannotAutoattack) || HasUnitFlag(UnitFlags.Pacified))
return;
if (!victim.IsAlive())
@@ -565,7 +567,7 @@ namespace Game.Entities
if (attType != WeaponAttackType.BaseAttack && attType != WeaponAttackType.OffAttack)
return;
if (IsTypeId(TypeId.Unit) && !HasFlag(UnitFields.Flags, UnitFlags.PlayerControlled))
if (IsTypeId(TypeId.Unit) && !HasUnitFlag(UnitFlags.PlayerControlled))
SetFacingToObject(victim); // update client side facing to face the target (prevents visual glitches when casting untargeted spells)
// melee attack spell casted at main hand attack only - no normal melee dmg dealt
@@ -598,7 +600,7 @@ namespace Game.Entities
public void FakeAttackerStateUpdate(Unit victim, WeaponAttackType attType = WeaponAttackType.BaseAttack)
{
if (HasUnitState(UnitState.CannotAutoattack) || HasFlag(UnitFields.Flags, UnitFlags.Pacified))
if (HasUnitState(UnitState.CannotAutoattack) || HasUnitFlag(UnitFlags.Pacified))
return;
if (!victim.IsAlive())
@@ -613,7 +615,7 @@ namespace Game.Entities
if (attType != WeaponAttackType.BaseAttack && attType != WeaponAttackType.OffAttack)
return; // ignore ranged case
if (IsTypeId(TypeId.Unit) && !HasFlag(UnitFields.Flags, UnitFlags.PlayerControlled))
if (IsTypeId(TypeId.Unit) && !HasUnitFlag(UnitFlags.PlayerControlled))
SetFacingToObject(victim); // update client side facing to face the target (prevents visual glitches when casting untargeted spells)
CalcDamageInfo damageInfo = new CalcDamageInfo();
@@ -1290,7 +1292,7 @@ namespace Game.Entities
if (IsInCombat() || HasUnitState(UnitState.Evade))
return;
SetFlag(UnitFields.Flags, UnitFlags.InCombat);
AddUnitFlag(UnitFlags.InCombat);
Creature creature = ToCreature();
if (creature != null)
@@ -1323,7 +1325,7 @@ namespace Game.Entities
foreach (var unit in m_Controlled)
{
unit.SetInCombatState(PvP, enemy);
unit.SetFlag(UnitFields.Flags, UnitFlags.PetInCombat);
unit.AddUnitFlag(UnitFlags.PetInCombat);
}
ProcSkillsAndAuras(enemy, ProcFlags.EnterCombat, ProcFlags.None, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null);
@@ -1504,7 +1506,7 @@ namespace Game.Entities
// must be after setDeathState which resets dynamic flags
if (!creature.loot.isLooted())
creature.SetFlag(ObjectFields.DynamicFlags, UnitDynFlags.Lootable);
creature.AddDynamicFlag(UnitDynFlags.Lootable);
else
creature.AllLootRemovedFromCorpse();
}
@@ -1625,7 +1627,7 @@ namespace Game.Entities
if (!player.HasUnitState(UnitState.AttackPlayer))
{
player.AddUnitState(UnitState.AttackPlayer);
player.SetFlag(PlayerFields.Flags, PlayerFlags.ContestedPVP);
player.AddPlayerFlag(PlayerFlags.ContestedPVP);
// call MoveInLineOfSight for nearby contested guards
UpdateObjectVisibility();
}
@@ -1766,6 +1768,21 @@ namespace Game.Entities
ToPlayer().ClearComboPoints();
}
public virtual bool CanUseAttackType(WeaponAttackType attacktype)
{
switch (attacktype)
{
case WeaponAttackType.BaseAttack:
return !HasUnitFlag(UnitFlags.Disarmed);
case WeaponAttackType.OffAttack:
return !HasUnitFlag2(UnitFlags2.DisarmOffhand);
case WeaponAttackType.RangedAttack:
return !HasUnitFlag2(UnitFlags2.DisarmRanged);
default:
return true;
}
}
// TODO for melee need create structure as in
void CalculateMeleeDamage(Unit victim, uint damage, out CalcDamageInfo damageInfo, WeaponAttackType attackType)
{
@@ -2082,21 +2099,21 @@ namespace Game.Entities
switch (attType)
{
case WeaponAttackType.RangedAttack:
minDamage = GetFloatValue(UnitFields.MinRangedDamage);
maxDamage = GetFloatValue(UnitFields.MaxRangedDamage);
minDamage = m_unitData.MinRangedDamage;
maxDamage = m_unitData.MaxRangedDamage;
break;
case WeaponAttackType.BaseAttack:
minDamage = GetFloatValue(UnitFields.MinDamage);
maxDamage = GetFloatValue(UnitFields.MaxDamage);
minDamage = m_unitData.MinDamage;
maxDamage = m_unitData.MaxDamage;
if (IsInFeralForm())
{
minDamage += GetFloatValue(UnitFields.MinOffHandDamage);
maxDamage += GetFloatValue(UnitFields.MaxOffHandDamage);
minDamage += m_unitData.MinOffHandDamage;
maxDamage += m_unitData.MaxOffHandDamage;
}
break;
case WeaponAttackType.OffAttack:
minDamage = GetFloatValue(UnitFields.MinOffHandDamage);
maxDamage = GetFloatValue(UnitFields.MaxOffHandDamage);
minDamage = m_unitData.MinOffHandDamage;
maxDamage = m_unitData.MaxOffHandDamage;
break;
// Just for good manner
default:
@@ -2169,17 +2186,17 @@ namespace Game.Entities
{
if (attType == WeaponAttackType.RangedAttack)
{
int ap = GetInt32Value(UnitFields.RangedAttackPower);
int ap = m_unitData.RangedAttackPower;
if (ap < 0)
return 0.0f;
return ap * (1.0f + GetFloatValue(UnitFields.RangedAttackPowerMultiplier));
return ap * (1.0f + m_unitData.RangedAttackPowerMultiplier);
}
else
{
int ap = GetInt32Value(UnitFields.AttackPower);
int ap = m_unitData.AttackPower;
if (ap < 0)
return 0.0f;
return ap * (1.0f + GetFloatValue(UnitFields.AttackPowerMultiplier));
return ap * (1.0f + m_unitData.AttackPowerMultiplier);
}
}
public float GetModifierValue(UnitMods unitMod, UnitModifierType modifierType)
@@ -2223,14 +2240,25 @@ namespace Game.Entities
}
void UpdateAttackTimeField(WeaponAttackType att)
{
SetUInt32Value(UnitFields.BaseAttackTime + (int)att, (uint)(m_baseAttackSpeed[(int)att] * m_modAttackSpeedPct[(int)att]));
switch (att)
{
case WeaponAttackType.BaseAttack:
case WeaponAttackType.OffAttack:
SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.AttackRoundBaseTime, (int)att), (uint)(m_baseAttackSpeed[(int)att] * m_modAttackSpeedPct[(int)att]));
break;
case WeaponAttackType.RangedAttack:
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.RangedAttackRoundBaseTime), (uint)(m_baseAttackSpeed[(int)att] * m_modAttackSpeedPct[(int)att]));
break;
default:
break; ;
}
}
public virtual void SetPvP(bool state)
{
if (state)
SetByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, UnitBytes2Flags.PvP);
AddPvpFlag(UnitPVPStateFlags.PvP);
else
RemoveByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, UnitBytes2Flags.PvP);
RemovePvpFlag(UnitPVPStateFlags.PvP);
}
public bool CanHaveThreatList(bool skipAliveCheck = false)
@@ -2697,11 +2725,17 @@ namespace Game.Entities
if (!spellProto.GetSchoolMask().HasAnyFlag(SpellSchoolMask.Normal))
{
float maxModDamagePercentSchool = 0.0f;
for (var i = SpellSchools.Holy; i < SpellSchools.Max; ++i)
Player thisPlayer = ToPlayer();
if (thisPlayer != null)
{
if (Convert.ToBoolean((int)spellProto.GetSchoolMask() & (1 << (int)i)))
maxModDamagePercentSchool = Math.Max(maxModDamagePercentSchool, GetFloatValue(ActivePlayerFields.ModDamageDonePct + (int)i));
for (var i = SpellSchools.Holy; i < SpellSchools.Max; ++i)
{
if (Convert.ToBoolean((int)spellProto.GetSchoolMask() & (1 << (int)i)))
maxModDamagePercentSchool = Math.Max(maxModDamagePercentSchool, thisPlayer.m_activePlayerData.ModDamageDonePercent[(int)i]);
}
}
else
maxModDamagePercentSchool = GetTotalAuraMultiplierByMiscMask(AuraType.ModDamagePercentDone, (uint)spellProto.GetSchoolMask());
DoneTotalMod *= maxModDamagePercentSchool;
}
@@ -2878,18 +2912,18 @@ namespace Game.Entities
MathFunctions.ApplyPercentModFloatVar(ref m_modAttackSpeedPct[(int)att], val, !apply);
if (att == WeaponAttackType.BaseAttack)
ApplyPercentModFloatValue(UnitFields.ModHaste, val, !apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModHaste), val, !apply);
else if (att == WeaponAttackType.RangedAttack)
ApplyPercentModFloatValue(UnitFields.ModRangedHaste, val, !apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModRangedHaste), val, !apply);
}
else
{
MathFunctions.ApplyPercentModFloatVar(ref m_modAttackSpeedPct[(int)att], -val, apply);
if (att == WeaponAttackType.BaseAttack)
ApplyPercentModFloatValue(UnitFields.ModHaste, -val, apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModHaste), -val, apply);
else if (att == WeaponAttackType.RangedAttack)
ApplyPercentModFloatValue(UnitFields.ModRangedHaste, -val, apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModRangedHaste), -val, apply);
}
UpdateAttackTimeField(att);
@@ -2937,30 +2971,30 @@ namespace Game.Entities
// can't attack untargetable
if ((bySpell == null || !bySpell.HasAttribute(SpellAttr6.CanTargetUntargetable))
&& target.HasFlag(UnitFields.Flags, UnitFlags.NotSelectable))
&& target.HasUnitFlag(UnitFlags.NotSelectable))
return false;
Player playerAttacker = ToPlayer();
if (playerAttacker != null)
{
if (playerAttacker.HasFlag(PlayerFields.Flags, PlayerFlags.Commentator2))
if (playerAttacker.HasPlayerFlag(PlayerFlags.Commentator2))
return false;
}
// check flags
if (target.HasFlag(UnitFields.Flags, (UnitFlags.NonAttackable | UnitFlags.TaxiFlight | UnitFlags.NotAttackable1 | UnitFlags.Unk16))
|| (!HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable) && target.HasFlag(UnitFields.Flags, UnitFlags.ImmuneToNpc))
|| (!target.HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable) && HasFlag(UnitFields.Flags, UnitFlags.ImmuneToNpc)))
if (target.HasUnitFlag(UnitFlags.NonAttackable | UnitFlags.TaxiFlight | UnitFlags.NotAttackable1 | UnitFlags.Unk16)
|| (!HasUnitFlag(UnitFlags.PvpAttackable) && target.HasUnitFlag(UnitFlags.ImmuneToNpc))
|| (!target.HasUnitFlag(UnitFlags.PvpAttackable) && HasUnitFlag(UnitFlags.ImmuneToNpc)))
return false;
if ((bySpell == null || !bySpell.HasAttribute(SpellAttr8.AttackIgnoreImmuneToPCFlag))
&& (HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable) && target.HasFlag(UnitFields.Flags, UnitFlags.ImmuneToPc))
&& (HasUnitFlag(UnitFlags.PvpAttackable) && target.HasUnitFlag(UnitFlags.ImmuneToPc))
// check if this is a world trigger cast - GOs are using world triggers to cast their spells, so we need to ignore their immunity flag here, this is a temp workaround, needs removal when go cast is implemented properly
&& GetEntry() != SharedConst.WorldTrigger)
return false;
// CvC case - can attack each other only when one of them is hostile
if (!HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable) && !target.HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable))
if (!HasUnitFlag(UnitFlags.PvpAttackable) && !target.HasUnitFlag(UnitFlags.PvpAttackable))
return GetReactionTo(target) <= ReputationRank.Hostile || target.GetReactionTo(this) <= ReputationRank.Hostile;
// PvP, PvC, CvP case
@@ -2968,8 +3002,8 @@ namespace Game.Entities
if (GetReactionTo(target) > ReputationRank.Neutral || target.GetReactionTo(this) > ReputationRank.Neutral)
return false;
Player playerAffectingAttacker = HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable) ? GetAffectingPlayer() : null;
Player playerAffectingTarget = target.HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable) ? target.GetAffectingPlayer() : null;
Player playerAffectingAttacker = HasUnitFlag(UnitFlags.PvpAttackable) ? GetAffectingPlayer() : null;
Player playerAffectingTarget = target.HasUnitFlag(UnitFlags.PvpAttackable) ? target.GetAffectingPlayer() : null;
// Not all neutral creatures can be attacked (even some unfriendly faction does not react aggresive to you, like Sporaggar)
if ((playerAffectingAttacker && !playerAffectingTarget) || (!playerAffectingAttacker && playerAffectingTarget))
@@ -3010,9 +3044,8 @@ namespace Game.Entities
// PvP case - can't attack when attacker or target are in sanctuary
// however, 13850 client doesn't allow to attack when one of the unit's has sanctuary flag and is pvp
if (target.HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable) && HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable)
&& (Convert.ToBoolean(target.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.Sanctuary)
|| Convert.ToBoolean(GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.Sanctuary)))
if (target.HasUnitFlag(UnitFlags.PvpAttackable) && HasUnitFlag(UnitFlags.PvpAttackable)
&& (target.HasPvpFlag(UnitPVPStateFlags.Sanctuary) || HasPvpFlag(UnitPVPStateFlags.Sanctuary)))
return false;
// additional checks - only PvP case
@@ -3024,7 +3057,7 @@ namespace Game.Entities
if (IsFFAPvP() && target.IsFFAPvP())
return true;
return HasByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, UnitBytes2Flags.Unk1) || target.HasByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, UnitBytes2Flags.Unk1);
return HasPvpFlag(UnitPVPStateFlags.Unk1) || target.HasPvpFlag(UnitPVPStateFlags.Unk1);
}
return true;
}
@@ -3062,19 +3095,19 @@ namespace Game.Entities
// can't assist untargetable
if ((bySpell == null || !bySpell.HasAttribute(SpellAttr6.CanTargetUntargetable))
&& target.HasFlag(UnitFields.Flags, UnitFlags.NotSelectable))
&& target.HasUnitFlag(UnitFlags.NotSelectable))
return false;
if (bySpell == null || !bySpell.HasAttribute(SpellAttr6.AssistIgnoreImmuneFlag))
{
if (HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable))
if (HasUnitFlag(UnitFlags.PvpAttackable))
{
if (target.HasFlag(UnitFields.Flags, UnitFlags.ImmuneToPc))
if (target.HasUnitFlag(UnitFlags.ImmuneToPc))
return false;
}
else
{
if (target.HasFlag(UnitFields.Flags, UnitFlags.ImmuneToNpc))
if (target.HasUnitFlag(UnitFlags.ImmuneToNpc))
return false;
}
}
@@ -3090,10 +3123,10 @@ namespace Game.Entities
return true;
// PvP case
else if (target.HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable))
else if (target.HasUnitFlag(UnitFlags.PvpAttackable))
{
Player targetPlayerOwner = target.GetAffectingPlayer();
if (HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable))
if (HasUnitFlag(UnitFlags.PvpAttackable))
{
Player selfPlayerOwner = GetAffectingPlayer();
if (selfPlayerOwner != null && targetPlayerOwner != null)
@@ -3103,20 +3136,18 @@ namespace Game.Entities
return false;
}
// can't assist player in ffa_pvp zone from outside
if (Convert.ToBoolean(target.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.FFAPvp)
&& !Convert.ToBoolean(GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.FFAPvp))
if (target.HasPvpFlag(UnitPVPStateFlags.FFAPvp) && !HasPvpFlag(UnitPVPStateFlags.FFAPvp))
return false;
// can't assist player out of sanctuary from sanctuary if has pvp enabled
if (Convert.ToBoolean(target.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.PvP))
if (Convert.ToBoolean(GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.Sanctuary)
&& !Convert.ToBoolean(target.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.Sanctuary))
if (target.HasPvpFlag(UnitPVPStateFlags.PvP))
if (HasPvpFlag(UnitPVPStateFlags.Sanctuary) && !target.HasPvpFlag(UnitPVPStateFlags.Sanctuary))
return false;
}
}
// PvC case - player can assist creature only if has specific type flags
else if (HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable)
else if (HasUnitFlag(UnitFlags.PvpAttackable)
&& (bySpell == null || !bySpell.HasAttribute(SpellAttr6.AssistIgnoreImmuneFlag))
&& !Convert.ToBoolean(target.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.PvP))
&& !target.HasPvpFlag(UnitPVPStateFlags.PvP))
{
Creature creatureTarget = target.ToCreature();
if (creatureTarget != null)
+4
View File
@@ -107,11 +107,15 @@ namespace Game.Entities
uint m_removedAurasCount;
//General
public UnitData m_unitData;
DiminishingReturn[] m_Diminishing = new DiminishingReturn[(int)DiminishingGroup.Max];
protected List<GameObject> m_gameObj = new List<GameObject>();
List<AreaTrigger> m_areaTrigger = new List<AreaTrigger>();
protected List<DynamicObject> m_dynObj = new List<DynamicObject>();
protected float[] CreateStats = new float[(int)Stats.Max];
float[] m_floatStatPosBuff = new float[(int)Stats.Max];
float[] m_floatStatNegBuff = new float[(int)Stats.Max];
public ObjectGuid[] m_SummonSlot = new ObjectGuid[7];
public ObjectGuid[] m_ObjectSlot = new ObjectGuid[4];
public EventSystem m_Events = new EventSystem();
+29 -20
View File
@@ -54,13 +54,13 @@ namespace Game.Entities
public virtual bool CanSwim()
{
// Mirror client behavior, if this method returns false then client will not use swimming animation and for players will apply gravity as if there was no water
if (HasFlag(UnitFields.Flags, UnitFlags.CannotSwim))
if (HasUnitFlag(UnitFlags.CannotSwim))
return false;
if (HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable)) // is player
if (HasUnitFlag(UnitFlags.PvpAttackable)) // is player
return true;
if (HasFlag(UnitFields.Flags2, 0x1000000))
if (HasUnitFlag2((UnitFlags2)0x1000000))
return false;
return HasFlag(UnitFields.Flags, UnitFlags.PetInCombat | UnitFlags.Rename | UnitFlags.Unk15);
return HasUnitFlag(UnitFlags.PetInCombat | UnitFlags.Rename | UnitFlags.Unk15);
}
public virtual bool IsInWater()
{
@@ -593,7 +593,7 @@ namespace Game.Entities
if (!obj || !IsInMap(obj) || !IsInPhase(obj))
return false;
float objBoundaryRadius = Math.Max(obj.GetBoundaryRadius(), SharedConst.MinMeleeReach);
float objBoundaryRadius = Math.Max(obj.GetBoundingRadius(), SharedConst.MinMeleeReach);
return IsInDist(obj, objBoundaryRadius);
}
@@ -737,6 +737,15 @@ namespace Game.Entities
if (mountCapability.ReqSpellKnownID != 0 && !HasSpell(mountCapability.ReqSpellKnownID))
continue;
Player thisPlayer = ToPlayer();
if (thisPlayer != null)
{
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(mountCapability.PlayerConditionID);
if (playerCondition != null)
if (!ConditionManager.IsPlayerMeetingCondition(thisPlayer, playerCondition))
continue;
}
return mountCapability;
}
@@ -944,7 +953,7 @@ namespace Game.Entities
if (enable == HasUnitMovementFlag(MovementFlag.Hover))
return false;
float hoverHeight = GetFloatValue(UnitFields.HoverHeight);
float hoverHeight = m_unitData.HoverHeight;
if (enable)
{
@@ -1133,7 +1142,7 @@ namespace Game.Entities
if (apply)
{
SetTarget(ObjectGuid.Empty);
SetFlag(UnitFields.Flags, UnitFlags.Stunned);
AddUnitFlag(UnitFlags.Stunned);
StopMoving();
@@ -1152,7 +1161,7 @@ namespace Game.Entities
// don't remove UNIT_FLAG_STUNNED for pet when owner is mounted (disabled pet's interface)
Unit owner = GetCharmerOrOwner();
if (owner == null || !owner.IsTypeId(TypeId.Player) || !owner.ToPlayer().IsMounted())
RemoveFlag(UnitFields.Flags, UnitFlags.Stunned);
RemoveUnitFlag(UnitFlags.Stunned);
if (!HasUnitState(UnitState.Root)) // prevent moving if it also has root effect
SetRooted(false);
@@ -1260,9 +1269,9 @@ namespace Game.Entities
public void Mount(uint mount, uint VehicleId = 0, uint creatureEntry = 0)
{
if (mount != 0)
SetUInt32Value(UnitFields.MountDisplayId, mount);
SetMountDisplayId(mount);
SetFlag(UnitFields.Flags, UnitFlags.Mount);
AddUnitFlag(UnitFlags.Mount);
Player player = ToPlayer();
if (player != null)
@@ -1286,7 +1295,7 @@ namespace Game.Entities
Battleground bg = ToPlayer().GetBattleground();
// don't unsummon pet in arena but SetFlag UNIT_FLAG_STUNNED to disable pet's interface
if (bg && bg.isArena())
pet.SetFlag(UnitFields.Flags, UnitFlags.Stunned);
pet.AddUnitFlag(UnitFlags.Stunned);
else
player.UnsummonPetTemporaryIfAny();
}
@@ -1295,7 +1304,7 @@ namespace Game.Entities
Unit charm = player.GetCharm();
if (charm)
if (charm.GetTypeId() == TypeId.Unit)
charm.SetFlag(UnitFields.Flags, UnitFlags.Stunned);
charm.AddUnitFlag(UnitFlags.Stunned);
player.SendMovementSetCollisionHeight(player.GetCollisionHeight(true));
}
@@ -1308,8 +1317,8 @@ namespace Game.Entities
if (!IsMounted())
return;
SetUInt32Value(UnitFields.MountDisplayId, 0);
RemoveFlag(UnitFields.Flags, UnitFlags.Mount);
SetMountDisplayId(0);
RemoveUnitFlag(UnitFlags.Mount);
Player thisPlayer = ToPlayer();
if (thisPlayer != null)
@@ -1337,8 +1346,8 @@ namespace Game.Entities
Pet pPet = player.GetPet();
if (pPet != null)
{
if (pPet.HasFlag(UnitFields.Flags, UnitFlags.Stunned) && !pPet.HasUnitState(UnitState.Stunned))
pPet.RemoveFlag(UnitFields.Flags, UnitFlags.Stunned);
if (pPet.HasUnitFlag(UnitFlags.Stunned) && !pPet.HasUnitState(UnitState.Stunned))
pPet.RemoveUnitFlag(UnitFlags.Stunned);
}
else
player.ResummonPetTemporaryUnSummonedIfAny();
@@ -1346,8 +1355,8 @@ namespace Game.Entities
// if we have charmed npc, remove stun also
Unit charm = player.GetCharm();
if (charm)
if (charm.GetTypeId() == TypeId.Unit && charm.HasFlag(UnitFields.Flags, UnitFlags.Stunned) && !charm.HasUnitState(UnitState.Stunned))
charm.RemoveFlag(UnitFields.Flags, UnitFlags.Stunned);
if (charm.GetTypeId() == TypeId.Unit && charm.HasUnitFlag(UnitFlags.Stunned) && !charm.HasUnitState(UnitState.Stunned))
charm.RemoveUnitFlag(UnitFlags.Stunned);
}
}
@@ -1381,7 +1390,7 @@ namespace Game.Entities
m_updateFlag.Vehicle = false;
m_unitTypeMask &= ~UnitTypeMask.Vehicle;
RemoveFlag64(UnitFields.NpcFlags, NPCFlags.SpellClick | NPCFlags.PlayerVehicle);
RemoveNpcFlag(NPCFlags.SpellClick | NPCFlags.PlayerVehicle);
}
void SendSetVehicleRecId(uint vehicleId)
@@ -1415,7 +1424,7 @@ namespace Game.Entities
{
float offset = 0.0f;
if (HasUnitMovementFlag(MovementFlag.Hover))
offset = GetFloatValue(UnitFields.HoverHeight);
offset = m_unitData.HoverHeight;
return GetPositionZ() - offset;
}
+52 -42
View File
@@ -168,7 +168,7 @@ namespace Game.Entities
if (IsTypeId(TypeId.Player))
{
minion.m_ControlledByPlayer = true;
minion.SetFlag(UnitFields.Flags, UnitFlags.PvpAttackable);
minion.AddUnitFlag(UnitFlags.PvpAttackable);
}
// Can only have one pet. If a new one is summoned, dismiss the old one.
@@ -196,17 +196,19 @@ namespace Game.Entities
}
if (minion.HasUnitTypeMask(UnitTypeMask.Guardian))
AddGuidValue(UnitFields.Summon, minion.GetGUID());
if (GetMinionGUID().IsEmpty())
SetMinionGUID(minion.GetGUID());
if (minion.m_Properties != null && minion.m_Properties.Title == SummonType.Minipet)
{
SetCritterGUID(minion.GetGUID());
if (GetTypeId() == TypeId.Player)
minion.SetGuidValue(UnitFields.BattlePetCompanionGuid, GetGuidValue(ActivePlayerFields.SummonedBattlePetId));
Player thisPlayer = ToPlayer();
if (thisPlayer != null)
minion.SetBattlePetCompanionGUID(thisPlayer.m_activePlayerData.SummonedBattlePetGUID);
}
// PvP, FFAPvP
minion.SetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag));
minion.SetPvpFlags(GetPvpFlags());
// FIXME: hack, speed must be set only at follow
if (IsTypeId(TypeId.Player) && minion.IsPet())
@@ -214,7 +216,7 @@ namespace Game.Entities
minion.SetSpeedRate(i, m_speed_rate[(int)i]);
// Send infinity cooldown - client does that automatically but after relog cooldown needs to be set again
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(minion.GetUInt32Value(UnitFields.CreatedBySpell));
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(minion.m_unitData.CreatedBySpell);
if (spellInfo != null && spellInfo.IsCooldownStartedOnEvent())
GetSpellHistory().StartCooldown(spellInfo, 0, null, true);
}
@@ -255,13 +257,14 @@ namespace Game.Entities
}
}
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(minion.GetUInt32Value(UnitFields.CreatedBySpell));
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(minion.m_unitData.CreatedBySpell);
// Remove infinity cooldown
if (spellInfo != null && spellInfo.IsCooldownStartedOnEvent())
GetSpellHistory().SendCooldownEvent(spellInfo);
if (RemoveGuidValue(UnitFields.Summon, minion.GetGUID()))
if (GetMinionGUID() == minion.GetGUID())
{
SetMinionGUID(ObjectGuid.Empty);
// Check if there is another minion
foreach (var unit in m_Controlled)
{
@@ -279,16 +282,14 @@ namespace Game.Entities
if (!unit.HasUnitTypeMask(UnitTypeMask.Guardian))
continue;
if (AddGuidValue(UnitFields.Summon, unit.GetGUID()))
SetMinionGUID(unit.GetGUID());
// show another pet bar if there is no charm bar
if (GetTypeId() == TypeId.Player && GetCharmGUID().IsEmpty())
{
// show another pet bar if there is no charm bar
if (IsTypeId(TypeId.Player) && GetCharmGUID().IsEmpty())
{
if (unit.IsPet())
ToPlayer().PetSpellInitialize();
else
ToPlayer().CharmSpellInitialize();
}
if (unit.IsPet())
ToPlayer().PetSpellInitialize();
else
ToPlayer().CharmSpellInitialize();
}
break;
}
@@ -364,8 +365,8 @@ namespace Game.Entities
if (aurApp != null && aurApp.GetRemoveMode() != 0)
return false;
_oldFactionId = getFaction();
SetFaction(charmer.getFaction());
_oldFactionId = GetFaction();
SetFaction(charmer.GetFaction());
// Set charmed
charmer.SetCharm(this, true);
@@ -418,14 +419,14 @@ namespace Game.Entities
switch (type)
{
case CharmType.Vehicle:
SetFlag(UnitFields.Flags, UnitFlags.PlayerControlled);
AddUnitFlag(UnitFlags.PlayerControlled);
playerCharmer.SetClientControl(this, true);
playerCharmer.VehicleSpellInitialize();
break;
case CharmType.Possess:
AddUnitState(UnitState.Possessed);
SetFlag(UnitFields.Flags, UnitFlags.PlayerControlled);
charmer.SetFlag(UnitFields.Flags, UnitFlags.RemoveClientControl);
AddUnitFlag(UnitFlags.PlayerControlled);
charmer.AddUnitFlag(UnitFlags.RemoveClientControl);
playerCharmer.SetClientControl(this, true);
playerCharmer.PossessSpellInitialize();
break;
@@ -436,14 +437,14 @@ namespace Game.Entities
if (cinfo != null && cinfo.CreatureType == CreatureType.Demon)
{
// to prevent client crash
SetByteValue(UnitFields.Bytes0, 1, (byte)Class.Mage);
SetClass(Class.Mage);
// just to enable stat window
if (GetCharmInfo() != null)
GetCharmInfo().SetPetNumber(Global.ObjectMgr.GeneratePetNumber(), true);
// if charmed two demons the same session, the 2nd gets the 1st one's name
SetUInt32Value(UnitFields.PetNameTimestamp, (uint)Time.UnixTime); // cast can't be helped
SetPetNameTimestamp((uint)Time.UnixTime); // cast can't be helped
}
}
playerCharmer.CharmSpellInitialize();
@@ -518,13 +519,13 @@ namespace Game.Entities
case CharmType.Vehicle:
playerCharmer.SetClientControl(this, false);
playerCharmer.SetClientControl(charmer, true);
RemoveFlag(UnitFields.Flags, UnitFlags.PlayerControlled);
RemoveUnitFlag(UnitFlags.PlayerControlled);
break;
case CharmType.Possess:
playerCharmer.SetClientControl(this, false);
playerCharmer.SetClientControl(charmer, true);
charmer.RemoveFlag(UnitFields.Flags, UnitFlags.RemoveClientControl);
RemoveFlag(UnitFields.Flags, UnitFlags.PlayerControlled);
charmer.RemoveUnitFlag(UnitFlags.RemoveClientControl);
RemoveUnitFlag(UnitFlags.PlayerControlled);
ClearUnitState(UnitState.Possessed);
break;
case CharmType.Charm:
@@ -533,7 +534,7 @@ namespace Game.Entities
CreatureTemplate cinfo = ToCreature().GetCreatureTemplate();
if (cinfo != null && cinfo.CreatureType == CreatureType.Demon)
{
SetByteValue(UnitFields.Bytes0, 1, (byte)cinfo.UnitClass);
SetClass((Class)cinfo.UnitClass);
if (GetCharmInfo() != null)
GetCharmInfo().SetPetNumber(0, true);
else
@@ -592,20 +593,24 @@ namespace Game.Entities
{
if (IsTypeId(TypeId.Player))
{
if (!AddGuidValue(UnitFields.Charm, charm.GetGUID()))
if (GetCharmGUID().IsEmpty())
SetCharmGUID(charm.GetGUID());
else
Log.outFatal(LogFilter.Unit, "Player {0} is trying to charm unit {1}, but it already has a charmed unit {2}", GetName(), charm.GetEntry(), GetCharmGUID());
charm.m_ControlledByPlayer = true;
// @todo maybe we can use this flag to check if controlled by player
charm.SetFlag(UnitFields.Flags, UnitFlags.PvpAttackable);
charm.AddUnitFlag(UnitFlags.PvpAttackable);
}
else
charm.m_ControlledByPlayer = false;
// PvP, FFAPvP
charm.SetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag));
charm.SetPvpFlags(GetPvpFlags());
if (!charm.AddGuidValue(UnitFields.CharmedBy, GetGUID()))
if (charm.GetCharmGUID().IsEmpty())
charm.SetCharmerGUID(GetGUID());
else
Log.outFatal(LogFilter.Unit, "Unit {0} is being charmed, but it already has a charmer {1}", charm.GetEntry(), charm.GetCharmerGUID());
_isWalkingBeforeCharm = charm.IsWalking();
@@ -619,30 +624,35 @@ namespace Game.Entities
{
if (IsTypeId(TypeId.Player))
{
if (!RemoveGuidValue(UnitFields.Charm, charm.GetGUID()))
if (GetCharmGUID() == charm.GetGUID())
SetCharmGUID(ObjectGuid.Empty);
else
Log.outFatal(LogFilter.Unit, "Player {0} is trying to uncharm unit {1}, but it has another charmed unit {2}", GetName(), charm.GetEntry(), GetCharmGUID());
}
if (!charm.RemoveGuidValue(UnitFields.CharmedBy, GetGUID()))
if (charm.GetCharmerGUID() == GetGUID())
charm.SetCharmerGUID(ObjectGuid.Empty);
else
Log.outFatal(LogFilter.Unit, "Unit {0} is being uncharmed, but it has another charmer {1}", charm.GetEntry(), charm.GetCharmerGUID());
Player player = charm.GetCharmerOrOwnerPlayerOrPlayerItself();
if (charm.IsTypeId(TypeId.Player))
{
charm.m_ControlledByPlayer = true;
charm.SetFlag(UnitFields.Flags, UnitFlags.PvpAttackable);
charm.AddUnitFlag(UnitFlags.PvpAttackable);
charm.ToPlayer().UpdatePvPState();
}
else if (player)
{
charm.m_ControlledByPlayer = true;
charm.SetFlag(UnitFields.Flags, UnitFlags.PvpAttackable);
charm.SetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, player.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag));
charm.AddUnitFlag(UnitFlags.PvpAttackable);
charm.SetPvpFlags(player.GetPvpFlags());
}
else
{
charm.m_ControlledByPlayer = false;
charm.RemoveFlag(UnitFields.Flags, UnitFlags.PvpAttackable);
charm.SetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, 0);
charm.RemoveUnitFlag(UnitFlags.PvpAttackable);
charm.SetPvpFlags(UnitPVPStateFlags.None);
}
if (charm.IsWalking() != _isWalkingBeforeCharm)
@@ -777,11 +787,11 @@ namespace Game.Entities
bool InitTamedPet(Pet pet, uint level, uint spell_id)
{
pet.SetCreatorGUID(GetGUID());
pet.SetFaction(getFaction());
pet.SetUInt32Value(UnitFields.CreatedBySpell, spell_id);
pet.SetFaction(GetFaction());
pet.SetCreatedBySpell(spell_id);
if (IsTypeId(TypeId.Player))
pet.SetUInt32Value(UnitFields.Flags, (uint)UnitFlags.PvpAttackable);
pet.AddUnitFlag(UnitFlags.PvpAttackable);
if (!pet.InitStatsForLevel(level))
{
+33 -27
View File
@@ -30,6 +30,8 @@ namespace Game.Entities
{
public virtual bool HasSpell(uint spellId) { return false; }
// function uses real base points (typically value - 1)
public int CalculateSpellDamage(Unit target, SpellInfo spellProto, uint effect_index, int? basePoints = null, int itemLevel = -1)
{
@@ -45,9 +47,10 @@ namespace Game.Entities
public int SpellBaseDamageBonusDone(SpellSchoolMask schoolMask)
{
if (IsTypeId(TypeId.Player))
Player thisPlayer = ToPlayer();
if (thisPlayer)
{
float overrideSP = GetFloatValue(ActivePlayerFields.OverrideSpellPowerByApPct);
float overrideSP = thisPlayer.m_activePlayerData.OverrideSpellPowerByAPPercent;
if (overrideSP > 0.0f)
return (int)(MathFunctions.CalculatePct(GetTotalAttackPowerValue(WeaponAttackType.BaseAttack), overrideSP) + 0.5f);
}
@@ -185,12 +188,13 @@ namespace Game.Entities
MathFunctions.AddPct(ref DoneTotalMod, modOwner.GetRatingBonusValue(CombatRating.VersatilityDamageDone) + modOwner.GetTotalAuraModifier(AuraType.ModVersatility));
float maxModDamagePercentSchool = 0.0f;
if (IsTypeId(TypeId.Player))
Player thisPlayer = ToPlayer();
if (thisPlayer)
{
for (int i = 0; i < (int)SpellSchools.Max; ++i)
{
if (Convert.ToBoolean((int)spellProto.GetSchoolMask() & (1 << i)))
maxModDamagePercentSchool = Math.Max(maxModDamagePercentSchool, GetFloatValue(ActivePlayerFields.ModDamageDonePct + i));
maxModDamagePercentSchool = Math.Max(maxModDamagePercentSchool, thisPlayer.m_activePlayerData.ModDamageDonePercent[i]);
}
}
else
@@ -336,9 +340,10 @@ namespace Game.Entities
public uint SpellBaseHealingBonusDone(SpellSchoolMask schoolMask)
{
if (IsTypeId(TypeId.Player))
Player thisPlayer = ToPlayer();
if (thisPlayer != null)
{
float overrideSP = GetFloatValue(ActivePlayerFields.OverrideSpellPowerByApPct);
float overrideSP = thisPlayer.m_activePlayerData.OverrideSpellPowerByAPPercent;
if (overrideSP > 0.0f)
return (uint)(MathFunctions.CalculatePct(GetTotalAttackPowerValue(WeaponAttackType.BaseAttack), overrideSP) + 0.5f);
}
@@ -502,8 +507,9 @@ namespace Game.Entities
if (spellProto.SpellFamilyName == SpellFamilyNames.Potion)
return 1.0f;
if (IsPlayer())
return GetFloatValue(ActivePlayerFields.ModHealingDonePct);
Player thisPlayer = ToPlayer();
if (thisPlayer != null)
return thisPlayer.m_activePlayerData.ModHealingDonePercent;
float DoneTotalMod = 1.0f;
@@ -640,7 +646,7 @@ namespace Game.Entities
crit_chance = 0.0f;
// For other schools
else if (IsTypeId(TypeId.Player))
crit_chance = GetFloatValue(ActivePlayerFields.CritPercentage);
crit_chance = ToPlayer().m_activePlayerData.SpellCritPercentage;
else
crit_chance = m_baseSpellCritChance;
@@ -1914,7 +1920,7 @@ namespace Game.Entities
if (!(spellInfo.HasAttribute(SpellAttr0.Ability | SpellAttr0.Tradespell) || spellInfo.HasAttribute(SpellAttr3.NoDoneBonus))
&& (IsTypeId(TypeId.Player) && spellInfo.SpellFamilyName != 0) || IsTypeId(TypeId.Unit))
castTime = (int)(castTime * GetFloatValue(UnitFields.ModCastSpeed));
castTime = (int)(castTime * m_unitData.ModCastingSpeed);
else if (spellInfo.HasAttribute(SpellAttr0.ReqAmmo) && !spellInfo.HasAttribute(SpellAttr2.AutorepeatFlag))
castTime = (int)(castTime * m_modAttackSpeedPct[(int)WeaponAttackType.RangedAttack]);
else if (Global.SpellMgr.IsPartOfSkillLine(SkillType.Cooking, spellInfo.Id) && HasAura(67556)) // cooking with Chef Hat.
@@ -1935,7 +1941,7 @@ namespace Game.Entities
if (!(spellInfo.HasAttribute(SpellAttr0.Ability) || spellInfo.HasAttribute(SpellAttr0.Tradespell) || spellInfo.HasAttribute(SpellAttr3.NoDoneBonus)) &&
(IsTypeId(TypeId.Player) && spellInfo.SpellFamilyName != 0) || IsTypeId(TypeId.Unit))
duration = (int)(duration * GetFloatValue(UnitFields.ModCastSpeed));
duration = (int)(duration * m_unitData.ModCastingSpeed);
else if (spellInfo.HasAttribute(SpellAttr0.ReqAmmo) && !spellInfo.HasAttribute(SpellAttr2.AutorepeatFlag))
duration = (int)(duration * m_modAttackSpeedPct[(int)WeaponAttackType.RangedAttack]);
}
@@ -2261,15 +2267,15 @@ namespace Game.Entities
{
if (val > 0)
{
ApplyPercentModFloatValue(UnitFields.ModCastSpeed, val, !apply);
ApplyPercentModFloatValue(UnitFields.ModCastHaste, val, !apply);
ApplyPercentModFloatValue(UnitFields.ModHasteRegen, val, !apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModCastingSpeed), val, !apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModSpellHaste), val, !apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModHasteRegen), val, !apply);
}
else
{
ApplyPercentModFloatValue(UnitFields.ModCastSpeed, -val, apply);
ApplyPercentModFloatValue(UnitFields.ModCastHaste, -val, apply);
ApplyPercentModFloatValue(UnitFields.ModHasteRegen, -val, apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModCastingSpeed), -val, apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModSpellHaste), -val, apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModHasteRegen), -val, apply);
}
}
@@ -3145,8 +3151,8 @@ namespace Game.Entities
continue;
// The charges / stack amounts don't count towards the total number of auras that can be dispelled.
// Ie: A dispel on a target with 5 stacks of Winters Chill and a Polymorph has 1 / (1 + 1) -> 50% chance to dispell
// Polymorph instead of 1 / (5 + 1) -> 16%.
// Ie: A dispel on a target with 5 stacks of Winters Chill and a Polymorph has 1 / (1 + 1) . 50% chance to dispell
// Polymorph instead of 1 / (5 + 1) . 16%.
bool dispelCharges = aura.GetSpellInfo().HasAttribute(SpellAttr7.DispelCharges);
byte charges = dispelCharges ? aura.GetCharges() : aura.GetStackAmount();
if (charges > 0)
@@ -3696,11 +3702,12 @@ namespace Game.Entities
public void ModifyAuraState(AuraStateType flag, bool apply)
{
uint mask = 1u << ((int)flag - 1);
if (apply)
{
if (!HasFlag(UnitFields.AuraState, (1u << ((int)flag - 1))))
if ((m_unitData.AuraState & mask) == 0)
{
SetFlag(UnitFields.AuraState, (1u << (int)flag - 1));
SetUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.AuraState), mask);
if (IsTypeId(TypeId.Player))
{
var sp_list = ToPlayer().GetSpellMap();
@@ -3735,9 +3742,9 @@ namespace Game.Entities
}
else
{
if (HasFlag(UnitFields.AuraState, (1u << (int)flag - 1)))
if ((m_unitData.AuraState & mask) != 0)
{
RemoveFlag(UnitFields.AuraState, (1u << (int)flag - 1));
RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.AuraState), mask);
foreach (var app in GetAppliedAuras())
{
@@ -3773,7 +3780,7 @@ namespace Game.Entities
}
}
return HasFlag(UnitFields.AuraState, (uint)(1 << (int)flag - 1));
return (m_unitData.AuraState & (1 << ((int)flag - 1))) != 0;
}
SpellSchools GetSpellSchoolByAuraGroup(UnitMods unitMod)
@@ -3981,9 +3988,9 @@ namespace Game.Entities
return aurApp?.GetBase();
}
uint BuildAuraStateUpdateForTarget(Unit target)
public uint BuildAuraStateUpdateForTarget(Unit target)
{
uint auraStates = GetUInt32Value(UnitFields.AuraState) & ~(uint)AuraStateType.PerCasterAuraStateMask;
uint auraStates = m_unitData.AuraState & ~(uint)AuraStateType.PerCasterAuraStateMask;
foreach (var state in m_auraStateAuras)
if (Convert.ToBoolean((1 << (int)state.Key - 1) & (uint)AuraStateType.PerCasterAuraStateMask))
if (state.Value.GetBase().GetCasterGUID() == target.GetGUID())
@@ -4465,7 +4472,6 @@ namespace Game.Entities
});
}
public void _RegisterAuraEffect(AuraEffect aurEff, bool apply)
{
if (apply)
+294 -360
View File
@@ -31,6 +31,7 @@ using Game.Spells;
using System;
using System.Collections.Generic;
using System.Linq;
using Game.Network;
namespace Game.Entities
{
@@ -85,6 +86,8 @@ namespace Game.Entities
m_serverSideVisibility.SetValue(ServerSideVisibilityType.Ghost, GhostVisibilityType.Alive);
movesplineTimer = new TimeTrackerSmall();
m_unitData = new UnitData();
}
public override void Dispose()
@@ -734,32 +737,42 @@ namespace Game.Entities
m_areaTrigger[0].Remove();
}
public bool IsVendor() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.Vendor); }
public bool IsTrainer() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.Trainer); }
public bool IsQuestGiver() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.QuestGiver); }
public bool IsGossip() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.Gossip); }
public bool IsTaxi() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.FlightMaster); }
public bool IsGuildMaster() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.Petitioner); }
public bool IsBattleMaster() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.BattleMaster); }
public bool IsBanker() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.Banker); }
public bool IsInnkeeper() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.Innkeeper); }
public bool IsSpiritHealer() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.SpiritHealer); }
public bool IsSpiritGuide() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.SpiritGuide); }
public bool IsTabardDesigner() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.TabardDesigner); }
public bool IsAuctioner() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.Auctioneer); }
public bool IsArmorer() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.Repair); }
public bool HasNpcFlag(NPCFlags flags) { return (m_unitData.NpcFlags[0] & (uint)flags) != 0; }
public void AddNpcFlag(NPCFlags flags) { SetUpdateFieldFlagValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.NpcFlags, 0), (uint)flags); }
public void RemoveNpcFlag(NPCFlags flags) { RemoveUpdateFieldFlagValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.NpcFlags, 0), (uint)flags); }
public void SetNpcFlags(NPCFlags flags) { SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.NpcFlags, 0), (uint)flags); }
public bool HasNpcFlag2(NPCFlags2 flags) { return (m_unitData.NpcFlags[1] & (uint)flags) != 0; }
public void AddNpcFlag2(NPCFlags2 flags) { SetUpdateFieldFlagValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.NpcFlags, 1), (uint)flags); }
public void RemoveNpcFlag2(NPCFlags2 flags) { RemoveUpdateFieldFlagValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.NpcFlags, 1), (uint)flags); }
public void SetNpcFlags2(NPCFlags2 flags) { SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.NpcFlags, 1), (uint)flags); }
public bool IsVendor() { return HasNpcFlag(NPCFlags.Vendor); }
public bool IsTrainer() { return HasNpcFlag(NPCFlags.Trainer); }
public bool IsQuestGiver() { return HasNpcFlag(NPCFlags.QuestGiver); }
public bool IsGossip() { return HasNpcFlag(NPCFlags.Gossip); }
public bool IsTaxi() { return HasNpcFlag(NPCFlags.FlightMaster); }
public bool IsGuildMaster() { return HasNpcFlag(NPCFlags.Petitioner); }
public bool IsBattleMaster() { return HasNpcFlag(NPCFlags.BattleMaster); }
public bool IsBanker() { return HasNpcFlag(NPCFlags.Banker); }
public bool IsInnkeeper() { return HasNpcFlag(NPCFlags.Innkeeper); }
public bool IsSpiritHealer() { return HasNpcFlag(NPCFlags.SpiritHealer); }
public bool IsSpiritGuide() { return HasNpcFlag(NPCFlags.SpiritGuide); }
public bool IsTabardDesigner() { return HasNpcFlag(NPCFlags.TabardDesigner); }
public bool IsAuctioner() { return HasNpcFlag(NPCFlags.Auctioneer); }
public bool IsArmorer() { return HasNpcFlag(NPCFlags.Repair); }
public bool IsServiceProvider()
{
return HasFlag64(UnitFields.NpcFlags,
NPCFlags.Vendor | NPCFlags.Trainer | NPCFlags.FlightMaster |
return HasNpcFlag(NPCFlags.Vendor | NPCFlags.Trainer | NPCFlags.FlightMaster |
NPCFlags.Petitioner | NPCFlags.BattleMaster | NPCFlags.Banker |
NPCFlags.Innkeeper | NPCFlags.SpiritHealer |
NPCFlags.SpiritGuide | NPCFlags.TabardDesigner | NPCFlags.Auctioneer);
}
public bool IsSpiritService() { return HasFlag64(UnitFields.NpcFlags, NPCFlags.SpiritHealer | NPCFlags.SpiritGuide); }
public bool IsSpiritService() { return HasNpcFlag(NPCFlags.SpiritHealer | NPCFlags.SpiritGuide); }
public bool IsCritter() { return GetCreatureType() == CreatureType.Critter; }
public bool IsInFlight() { return HasUnitState(UnitState.InFlight); }
public void SetHoverHeight(float hoverHeight) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.HoverHeight), hoverHeight); }
public Guardian GetGuardianPet()
{
ObjectGuid pet_guid = GetPetGUID();
@@ -1088,7 +1101,7 @@ namespace Game.Entities
return pet;
Log.outError(LogFilter.Unit, "Unit.GetCharm: Charmed creature {0} not exist.", charm_guid);
SetGuidValue(UnitFields.Charm, ObjectGuid.Empty);
SetCharmGUID(ObjectGuid.Empty);
}
return null;
@@ -1144,7 +1157,8 @@ namespace Game.Entities
public uint GetModelForForm(ShapeShiftForm form)
{
if (IsTypeId(TypeId.Player))
Player thisPlayer = ToPlayer();
if (thisPlayer != null)
{
Aura artifactAura = GetAura(PlayerConst.ArtifactsAllWeaponsGeneralWeaponEquippedPassive);
if (artifactAura != null)
@@ -1159,8 +1173,8 @@ namespace Game.Entities
}
}
byte hairColor = GetByteValue(PlayerFields.Bytes, PlayerFieldOffsets.BytesOffsetHairColorId);
byte skinColor = GetByteValue(PlayerFields.Bytes, PlayerFieldOffsets.BytesOffsetSkinId);
byte hairColor = thisPlayer.m_playerData.HairColorID;
byte skinColor = thisPlayer.m_playerData.SkinID;
switch (form)
{
@@ -1568,21 +1582,6 @@ namespace Game.Entities
return modelid;
}
public virtual bool CanUseAttackType(WeaponAttackType attacktype)
{
switch (attacktype)
{
case WeaponAttackType.BaseAttack:
return !HasFlag(UnitFields.Flags, UnitFlags.Disarmed);
case WeaponAttackType.OffAttack:
return !HasFlag(UnitFields.Flags2, UnitFlags2.DisarmOffhand);
case WeaponAttackType.RangedAttack:
return !HasFlag(UnitFields.Flags2, UnitFlags2.DisarmRanged);
default:
return true;
}
}
public Totem ToTotem() { return IsTotem() ? (this as Totem) : null; }
public TempSummon ToTempSummon() { return IsSummon() ? (this as TempSummon) : null; }
public virtual void setDeathState(DeathState s)
@@ -1630,7 +1629,7 @@ namespace Game.Entities
// do not why since in IncreaseMaxHealth currenthealth is checked
SetHealth(0);
SetPower(GetPowerType(), 0);
SetUInt32Value(UnitFields.NpcEmotestate, 0);
SetEmoteState(Emote.OneshotNone);
// players in instance don't have ZoneScript, but they have InstanceScript
ZoneScript zoneScript = GetZoneScript() != null ? GetZoneScript() : GetInstanceScript();
@@ -1638,7 +1637,7 @@ namespace Game.Entities
zoneScript.OnUnitDeath(this);
}
else if (s == DeathState.JustRespawned)
RemoveFlag(UnitFields.Flags, UnitFlags.Skinnable); // clear skinnable for creature and player (at Battleground)
RemoveUnitFlag(UnitFlags.Skinnable); // clear skinnable for creature and player (at Battleground)
}
public bool IsVisible()
@@ -1655,12 +1654,19 @@ namespace Game.Entities
UpdateObjectVisibility();
}
public bool IsMounted() { return HasFlag(UnitFields.Flags, UnitFlags.Mount); }
public uint GetMountID() { return GetUInt32Value(UnitFields.MountDisplayId); }
public bool IsMagnet()
{
// Grounding Totem
if (m_unitData.CreatedBySpell == 8177) /// @todo: find a more generic solution
return true;
return false;
}
public void SetShapeshiftForm(ShapeShiftForm form)
{
SetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.ShapeshiftForm, (byte)form);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ShapeshiftForm), (byte)form);
}
public void SetModifierValue(UnitMods unitMod, UnitModifierType modifierType, float value)
@@ -1906,7 +1912,7 @@ namespace Game.Entities
public FactionTemplateRecord GetFactionTemplateEntry()
{
FactionTemplateRecord entry = CliDB.FactionTemplateStorage.LookupByKey(getFaction());
FactionTemplateRecord entry = CliDB.FactionTemplateStorage.LookupByKey(GetFaction());
if (entry == null)
{
ObjectGuid guid = ObjectGuid.Empty; // prevent repeating spam same faction problem
@@ -1916,11 +1922,11 @@ namespace Game.Entities
Player player = ToPlayer();
Creature creature = ToCreature();
if (player != null)
Log.outError(LogFilter.Unit, "Player {0} has invalid faction (faction template id) #{1}", player.GetName(), getFaction());
Log.outError(LogFilter.Unit, "Player {0} has invalid faction (faction template id) #{1}", player.GetName(), GetFaction());
else if (creature != null)
Log.outError(LogFilter.Unit, "Creature (template id: {0}) has invalid faction (faction template id) #{1}", creature.GetCreatureTemplate().Entry, getFaction());
Log.outError(LogFilter.Unit, "Creature (template id: {0}) has invalid faction (faction template id) #{1}", creature.GetCreatureTemplate().Entry, GetFaction());
else
Log.outError(LogFilter.Unit, "Unit (name={0}, type={1}) has invalid faction (faction template id) #{2}", GetName(), GetTypeId(), getFaction());
Log.outError(LogFilter.Unit, "Unit (name={0}, type={1}) has invalid faction (faction template id) #{2}", GetName(), GetTypeId(), GetFaction());
guid = GetGUID();
}
@@ -2028,7 +2034,7 @@ namespace Game.Entities
if (slot >= SharedConst.MaxEquipmentItems)
return 0;
return GetUInt32Value(UnitFields.VirtualItemSlotId + slot * 2);
return m_unitData.VirtualItems[slot].ItemID;
}
public ushort GetVirtualItemAppearanceMod(uint slot)
@@ -2036,85 +2042,121 @@ namespace Game.Entities
if (slot >= SharedConst.MaxEquipmentItems)
return 0;
return GetUInt16Value(UnitFields.VirtualItemSlotId + (int)slot * 2 + 1, 0);
return m_unitData.VirtualItems[(int)slot].ItemAppearanceModID;
}
public void SetVirtualItem(int slot, uint itemId, ushort appearanceModId = 0, ushort itemVisual = 0)
public void SetVirtualItem(uint slot, uint itemId, ushort appearanceModId = 0, ushort itemVisual = 0)
{
if (slot >= SharedConst.MaxEquipmentItems)
return;
SetUInt32Value(UnitFields.VirtualItemSlotId + slot * 2, itemId);
SetUInt16Value(UnitFields.VirtualItemSlotId + slot * 2 + 1, 0, appearanceModId);
SetUInt16Value(UnitFields.VirtualItemSlotId + slot * 2 + 1, 1, itemVisual);
var virtualItemField = m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.VirtualItems, (int)slot);
SetUpdateFieldValue(virtualItemField.ModifyValue((VisibleItem visibleItem) => visibleItem.ItemID), itemId);
SetUpdateFieldValue(virtualItemField.ModifyValue((VisibleItem visibleItem) => visibleItem.ItemAppearanceModID), appearanceModId);
SetUpdateFieldValue(virtualItemField.ModifyValue((VisibleItem visibleItem) => visibleItem.ItemVisual), itemVisual);
}
//Unit
public void SetLevel(uint lvl)
{
SetUInt32Value(UnitFields.Level, lvl);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Level), lvl);
if (IsTypeId(TypeId.Player))
Player player = ToPlayer();
if (player != null)
{
Player player = ToPlayer();
if (player.GetGroup())
player.SetGroupUpdateFlag(GroupUpdateFlags.Level);
Global.WorldMgr.UpdateCharacterInfoLevel(ToPlayer().GetGUID(), (byte)lvl);
}
}
public uint getLevel()
{
return GetUInt32Value(UnitFields.Level);
}
public uint getLevel() { return m_unitData.Level; }
public override uint GetLevelForTarget(WorldObject target) { return getLevel(); }
public override uint GetLevelForTarget(WorldObject target)
{
return getLevel();
}
public Race GetRace() { return (Race)(byte)m_unitData.Race; }
public void SetRace(Race race) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Race), (byte)race); }
public ulong getRaceMask() { return 1ul << ((int)GetRace() - 1); }
public Class GetClass() { return (Class)(byte)m_unitData.ClassId; }
public void SetClass(Class classId) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ClassId), (byte)classId); }
public uint getClassMask() { return (uint)(1 << ((int)GetClass() - 1)); }
public Gender GetGender() { return (Gender)(byte)m_unitData.Sex; }
public void SetGender(Gender sex) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Sex), (byte)sex); }
public Race GetRace()
{
return (Race)GetByteValue(UnitFields.Bytes0, 0);
}
public ulong getRaceMask()
{
return (1ul << ((int)GetRace() - 1));
}
public Class GetClass()
{
return (Class)GetByteValue(UnitFields.Bytes0, 1);
}
public uint getClassMask()
{
return (uint)(1 << ((int)GetClass() - 1));
}
public Gender GetGender()
{
return (Gender)GetByteValue(UnitFields.Bytes0, 3);
}
public void SetNativeDisplayId(uint displayId, float displayScale = 1f)
{
SetUInt32Value(UnitFields.NativeDisplayId, displayId);
SetFloatValue(UnitFields.NativeXDisplayScale, displayScale);
}
public uint GetDisplayId() { return m_unitData.DisplayID; }
public virtual void SetDisplayId(uint modelId, float displayScale = 1f)
{
SetUInt32Value(UnitFields.DisplayId, modelId);
SetFloatValue(UnitFields.DisplayScale, displayScale);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.DisplayID), modelId);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.DisplayScale), displayScale);
// Set Gender by modelId
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelInfo(modelId);
if (minfo != null)
SetByteValue(UnitFields.Bytes0, 3, (byte)minfo.gender);
SetGender((Gender)minfo.gender);
}
public uint GetNativeDisplayId()
public void RestoreDisplayId(bool ignorePositiveAurasPreventingMounting = false)
{
return GetUInt32Value(UnitFields.NativeDisplayId);
AuraEffect handledAura = null;
// try to receive model from transform auras
var transforms = GetAuraEffectsByType(AuraType.Transform);
if (!transforms.Empty())
{
// iterate over already applied transform auras - from newest to oldest
foreach (var eff in transforms)
{
AuraApplication aurApp = eff.GetBase().GetApplicationOfTarget(GetGUID());
if (aurApp != null)
{
if (handledAura == null)
{
if (!ignorePositiveAurasPreventingMounting)
handledAura = eff;
else
{
CreatureTemplate ci = Global.ObjectMgr.GetCreatureTemplate((uint)eff.GetMiscValue());
if (ci != null)
if (!IsDisallowedMountForm(eff.GetId(), ShapeShiftForm.None, ObjectManager.ChooseDisplayId(ci).CreatureDisplayID))
handledAura = eff;
}
}
// prefer negative auras
if (!aurApp.IsPositive())
{
handledAura = eff;
break;
}
}
}
}
uint modelId;
// transform aura was found
if (handledAura != null)
handledAura.HandleEffect(this, AuraEffectHandleModes.SendForClient, true);
// we've found shapeshift
else if ((modelId = GetModelForForm(GetShapeshiftForm())) != 0)
{
if (!ignorePositiveAurasPreventingMounting || !IsDisallowedMountForm(0, GetShapeshiftForm(), modelId))
SetDisplayId(modelId);
else
SetDisplayId(GetNativeDisplayId());
}
// no auras found - set modelid to default
else
SetDisplayId(GetNativeDisplayId());
}
public float GetNativeDisplayScale()
public uint GetNativeDisplayId() { return m_unitData.NativeDisplayID; }
public void SetNativeDisplayId(uint displayId, float displayScale = 1f)
{
return GetFloatValue(UnitFields.NativeXDisplayScale);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.NativeDisplayID), displayId);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.NativeXDisplayScale), displayScale);
}
public float GetNativeDisplayScale() { return m_unitData.NativeXDisplayScale; }
public bool IsMounted()
{
return HasUnitFlag(UnitFlags.Mount);
}
public uint GetMountDisplayId() { return m_unitData.MountDisplayID; }
public void SetMountDisplayId(uint mountDisplayId) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.MountDisplayID), mountDisplayId); }
public virtual Unit GetOwner()
{
ObjectGuid ownerid = GetOwnerGUID();
@@ -2125,18 +2167,46 @@ namespace Game.Entities
}
public virtual float GetFollowAngle() { return MathFunctions.PiOver2; }
public ObjectGuid GetOwnerGUID() { return GetGuidValue(UnitFields.SummonedBy); }
public ObjectGuid GetCreatorGUID() { return GetGuidValue(UnitFields.CreatedBy); }
public ObjectGuid GetMinionGUID() { return GetGuidValue(UnitFields.Summon); }
public ObjectGuid GetCharmerGUID() { return GetGuidValue(UnitFields.CharmedBy); }
public ObjectGuid GetCharmGUID() { return GetGuidValue(UnitFields.Charm); }
public ObjectGuid GetOwnerGUID() { return m_unitData.SummonedBy; }
public void SetOwnerGUID(ObjectGuid owner)
{
if (GetOwnerGUID() == owner)
return;
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.SummonedBy), owner);
if (owner.IsEmpty())
return;
// Update owner dependent fields
Player player = Global.ObjAccessor.GetPlayer(this, owner);
if (player == null || !player.HaveAtClient(this)) // if player cannot see this unit yet, he will receive needed data with create object
return;
UpdateData udata = new UpdateData(GetMapId());
UpdateObject packet;
BuildValuesUpdateBlockForPlayerWithFlag(udata, UpdateFieldFlag.Owner, player);
udata.BuildPacket(out packet);
player.SendPacket(packet);
}
public ObjectGuid GetCreatorGUID() { return m_unitData.CreatedBy; }
public void SetCreatorGUID(ObjectGuid creator) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.CreatedBy), creator); }
public ObjectGuid GetMinionGUID() { return m_unitData.Summon; }
public void SetMinionGUID(ObjectGuid guid) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Summon), guid); }
public ObjectGuid GetCharmerGUID() { return m_unitData.CharmedBy; }
public void SetCharmerGUID(ObjectGuid owner) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.CharmedBy), owner); }
public ObjectGuid GetCharmGUID() { return m_unitData.Charm; }
public void SetCharmGUID(ObjectGuid charm) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Charm), charm); }
public ObjectGuid GetPetGUID() { return m_SummonSlot[0]; }
public ObjectGuid GetCritterGUID() { return GetGuidValue(UnitFields.Critter); }
public void SetPetGUID(ObjectGuid guid) { m_SummonSlot[0] = guid; }
public ObjectGuid GetCritterGUID() { return m_unitData.Critter; }
public void SetCritterGUID(ObjectGuid guid) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Critter), guid); }
public ObjectGuid GetBattlePetCompanionGUID() { return m_unitData.BattlePetCompanionGUID; }
public void SetBattlePetCompanionGUID(ObjectGuid guid) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.BattlePetCompanionGUID), guid); }
public ObjectGuid GetCharmerOrOwnerGUID()
{
return !GetCharmerGUID().IsEmpty() ? GetCharmerGUID() : GetOwnerGUID();
}
ObjectGuid GetCharmerOrOwnerOrOwnGUID()
public ObjectGuid GetCharmerOrOwnerOrOwnGUID()
{
ObjectGuid guid = GetCharmerOrOwnerGUID();
if (!guid.IsEmpty())
@@ -2172,52 +2242,49 @@ namespace Game.Entities
return !GetCharmerGUID().IsEmpty() ? GetCharmer() : GetOwner();
}
public uint GetChannelSpellId() { return GetUInt32Value(UnitFields.ChannelData); }
public void SetChannelSpellId(uint channelSpellId) { SetUInt32Value(UnitFields.ChannelData, channelSpellId); }
public uint GetChannelSpellXSpellVisualId() { return GetUInt32Value(UnitFields.ChannelData + 1);}
public void SetChannelSpellXSpellVisualId(uint channelSpellXSpellVisualId) { SetUInt32Value(UnitFields.ChannelData + 1, channelSpellXSpellVisualId); }
public bool HasUnitFlag(UnitFlags flags) { return (m_unitData.Flags & (uint)flags) != 0; }
public void AddUnitFlag(UnitFlags flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Flags), (uint)flags); }
public void RemoveUnitFlag(UnitFlags flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Flags), (uint)flags); }
public void SetUnitFlags(UnitFlags flags) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Flags), (uint)flags); }
public bool HasUnitFlag2(UnitFlags2 flags) { return (m_unitData.Flags2 & (uint)flags) != 0; }
public void AddUnitFlag2(UnitFlags2 flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Flags2), (uint)flags); }
public void RemoveUnitFlag2(UnitFlags2 flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Flags2), (uint)flags); }
public void SetUnitFlags2(UnitFlags2 flags) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Flags2), (uint)flags); }
public bool HasUnitFlag3(UnitFlags3 flags) { return (m_unitData.Flags3 & (uint)flags) != 0; }
public void AddUnitFlag3(UnitFlags3 flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Flags3), (uint)flags); }
public void RemoveUnitFlag3(UnitFlags3 flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Flags3), (uint)flags); }
public void SetUnitFlags3(UnitFlags3 flags) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Flags3), (uint)flags); }
public List<ObjectGuid> GetChannelObjects() { return GetDynamicStructuredValues<ObjectGuid>(UnitDynamicFields.ChannelObjects); }
public void AddChannelObject(ObjectGuid guid) { AddDynamicStructuredValue(UnitDynamicFields.ChannelObjects, guid); }
public void SetCreatedBySpell(uint spellId) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.CreatedBySpell), spellId); }
public void SetOwnerGUID(ObjectGuid owner)
{
if (GetOwnerGUID() == owner)
return;
public Emote GetEmoteState() { return (Emote)(int)m_unitData.EmoteState; }
public void SetEmoteState(Emote emote) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.EmoteState), (int)emote); }
SetGuidValue(UnitFields.SummonedBy, owner);
if (owner.IsEmpty())
return;
// Update owner dependent fields
Player player = Global.ObjAccessor.GetPlayer(this, owner);
if (player == null || !player.HaveAtClient(this)) // if player cannot see this unit yet, he will receive needed data with create object
return;
SetFieldNotifyFlag(UpdateFieldFlags.Owner);
UpdateData udata = new UpdateData(GetMapId());
UpdateObject packet;
BuildValuesUpdateBlockForPlayer(udata, player);
udata.BuildPacket(out packet);
player.SendPacket(packet);
RemoveFieldNotifyFlag(UpdateFieldFlags.Owner);
}
public void SetCreatorGUID(ObjectGuid creator) { SetGuidValue(UnitFields.CreatedBy, creator); }
void SetMinionGUID(ObjectGuid guid) { SetGuidValue(UnitFields.Summon, guid); }
void SetCharmerGUID(ObjectGuid owner) { SetGuidValue(UnitFields.CharmedBy, owner); }
public void SetPetGUID(ObjectGuid guid) { m_SummonSlot[0] = guid; }
void SetCritterGUID(ObjectGuid guid) { SetGuidValue(UnitFields.Critter, guid); }
public SheathState GetSheath() { return (SheathState)(byte)m_unitData.SheatheState; }
public void SetSheath(SheathState sheathed) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.SheatheState), (byte)sheathed); }
public uint GetCombatTimer() { return m_CombatTimer; }
public bool IsPvP() { return HasByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, UnitBytes2Flags.PvP); }
public bool IsFFAPvP() { return HasByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, UnitBytes2Flags.FFAPvp); }
public UnitPVPStateFlags GetPvpFlags() { return (UnitPVPStateFlags)(byte)m_unitData.PvpFlags; }
public bool HasPvpFlag(UnitPVPStateFlags flags) { return (m_unitData.PvpFlags & (uint)flags) != 0; }
public void AddPvpFlag(UnitPVPStateFlags flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PvpFlags), (byte)flags); }
public void RemovePvpFlag(UnitPVPStateFlags flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PvpFlags), (byte)flags); }
public void SetPvpFlags(UnitPVPStateFlags flags) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PvpFlags), (byte)flags); }
public bool IsPvP() { return HasPvpFlag(UnitPVPStateFlags.PvP); }
public bool IsFFAPvP() { return HasPvpFlag(UnitPVPStateFlags.FFAPvp); }
public ShapeShiftForm GetShapeshiftForm()
public UnitPetFlags GetPetFlags()
{
return (ShapeShiftForm)GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.ShapeshiftForm);
return (UnitPetFlags)(byte)m_unitData.PetFlags;
}
public bool HasPetFlag(UnitPetFlags flags) { return (m_unitData.PetFlags & (byte)flags) != 0; }
public void AddPetFlag(UnitPetFlags flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PetFlags), (byte)flags); }
public void RemovePetFlag(UnitPetFlags flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PetFlags), (byte)flags); }
public void SetPetFlags(UnitPetFlags flags) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PetFlags), (byte)flags); }
public void SetPetNumberForClient(uint petNumber) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PetNumber), petNumber); }
public void SetPetNameTimestamp(uint timestamp) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PetNameTimestamp), timestamp); }
public ShapeShiftForm GetShapeshiftForm() { return (ShapeShiftForm)(byte)m_unitData.ShapeshiftForm; }
public CreatureType GetCreatureType()
{
if (IsTypeId(TypeId.Player))
@@ -2275,14 +2342,6 @@ namespace Game.Entities
{
m_state &= ~f;
}
public void SetStandFlags(object flags)
{
SetByteFlag(UnitFields.Bytes1, UnitBytes1Offsets.VisFlag, flags);
}
public void RemoveStandFlags(object flags)
{
RemoveByteFlag(UnitFields.Bytes1, UnitBytes1Offsets.VisFlag, flags);
}
public override bool IsAlwaysVisibleFor(WorldObject seer)
{
@@ -2342,9 +2401,9 @@ namespace Game.Entities
if (GetCharmerOrOwnerOrSelf() == target.GetCharmerOrOwnerOrSelf())
return ReputationRank.Friendly;
if (HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable))
if (HasUnitFlag(UnitFlags.PvpAttackable))
{
if (target.HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable))
if (target.HasUnitFlag(UnitFlags.PvpAttackable))
{
Player selfPlayerOwner = GetAffectingPlayer();
Player targetPlayerOwner = target.GetAffectingPlayer();
@@ -2373,7 +2432,7 @@ namespace Game.Entities
var targetFactionTemplateEntry = target.GetFactionTemplateEntry();
if (targetFactionTemplateEntry != null)
{
if (!selfPlayerOwner.HasFlag(UnitFields.Flags2, UnitFlags2.IgnoreReputation))
if (!selfPlayerOwner.HasUnitFlag2(UnitFlags2.IgnoreReputation))
{
var targetFactionEntry = CliDB.FactionStorage.LookupByKey(targetFactionTemplateEntry.Faction);
if (targetFactionEntry != null)
@@ -2382,7 +2441,7 @@ namespace Game.Entities
{
// check contested flags
if (Convert.ToBoolean(targetFactionTemplateEntry.Flags & (uint)FactionTemplateFlags.ContestedGuard)
&& selfPlayerOwner.HasFlag(PlayerFields.Flags, PlayerFlags.ContestedPVP))
&& selfPlayerOwner.HasPlayerFlag(PlayerFlags.ContestedPVP))
return ReputationRank.Hostile;
// if faction has reputation, hostile state depends only from AtWar state
@@ -2414,12 +2473,12 @@ namespace Game.Entities
{
// check contested flags
if (Convert.ToBoolean(factionTemplateEntry.Flags & (uint)FactionTemplateFlags.ContestedGuard)
&& targetPlayerOwner.HasFlag(PlayerFields.Flags, PlayerFlags.ContestedPVP))
&& targetPlayerOwner.HasPlayerFlag(PlayerFlags.ContestedPVP))
return ReputationRank.Hostile;
ReputationRank repRank = targetPlayerOwner.GetReputationMgr().GetForcedRankIfAny(factionTemplateEntry);
if (repRank != ReputationRank.None)
return repRank;
if (!target.HasFlag(UnitFields.Flags2, UnitFlags2.IgnoreReputation))
if (!target.HasUnitFlag2(UnitFlags2.IgnoreReputation))
{
var factionEntry = CliDB.FactionStorage.LookupByKey(factionTemplateEntry.Faction);
if (factionEntry != null)
@@ -2449,14 +2508,9 @@ namespace Game.Entities
return ReputationRank.Neutral;
}
public uint getFaction()
{
return GetUInt32Value(UnitFields.FactionTemplate);
}
public void SetFaction(uint faction)
{
SetUInt32Value(UnitFields.FactionTemplate, faction);
}
public uint GetFaction() { return m_unitData.FactionTemplate; }
public void SetFaction(uint faction) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.FactionTemplate), faction); }
public void RestoreFaction()
{
if (IsTypeId(TypeId.Player))
@@ -2468,7 +2522,7 @@ namespace Game.Entities
Unit owner = GetOwner();
if (owner)
{
SetFaction(owner.getFaction());
SetFaction(owner.GetFaction());
return;
}
}
@@ -2494,8 +2548,8 @@ namespace Game.Entities
(u1.IsTypeId(TypeId.Player) && u2.IsTypeId(TypeId.Unit) && u2.ToCreature().GetCreatureTemplate().TypeFlags.HasAnyFlag(CreatureTypeFlags.TreatAsRaidUnit)))
return true;
// else u1->GetTypeId() == u2->GetTypeId() == TYPEID_UNIT
return u1.getFaction() == u2.getFaction();
// else u1.GetTypeId() == u2.GetTypeId() == TYPEID_UNIT
return u1.GetFaction() == u2.GetFaction();
}
public bool IsInRaidWith(Unit unit)
@@ -2514,14 +2568,14 @@ namespace Game.Entities
(u1.IsTypeId(TypeId.Player) && u2.IsTypeId(TypeId.Unit) && u2.ToCreature().GetCreatureTemplate().TypeFlags.HasAnyFlag(CreatureTypeFlags.TreatAsRaidUnit)))
return true;
// else u1->GetTypeId() == u2->GetTypeId() == TYPEID_UNIT
return u1.getFaction() == u2.getFaction();
// else u1.GetTypeId() == u2.GetTypeId() == TYPEID_UNIT
return u1.GetFaction() == u2.GetFaction();
}
public SheathState GetSheath() { return (SheathState)GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.SheathState); }
public void SetSheath(SheathState sheathed) { SetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.SheathState, (byte)sheathed); }
public UnitStandStateType GetStandState() { return (UnitStandStateType)GetByteValue(UnitFields.Bytes1, UnitBytes1Offsets.StandState); }
public UnitStandStateType GetStandState() { return (UnitStandStateType)(byte)m_unitData.StandState; }
public void AddVisFlags(UnitVisFlags flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.VisFlags), (byte)flags); }
public void RemoveVisFlags(UnitVisFlags flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.VisFlags), (byte)flags); }
public void SetVisFlags(UnitVisFlags flags) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.VisFlags), (byte)flags); }
public bool IsSitState()
{
@@ -2540,7 +2594,7 @@ namespace Game.Entities
public void SetStandState(UnitStandStateType state, uint animKitId = 0)
{
SetByteValue(UnitFields.Bytes1, UnitBytes1Offsets.StandState, (byte)state);
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.StandState), (byte)state);
if (IsStandState())
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.NotSeated);
@@ -2552,60 +2606,34 @@ namespace Game.Entities
}
}
public uint GetDisplayId() { return GetUInt32Value(UnitFields.DisplayId); }
public void RestoreDisplayId(bool ignorePositiveAurasPreventingMounting = false)
public void SetAnimTier(UnitBytes1Flags animTier, bool notifyClient)
{
AuraEffect handledAura = null;
// try to receive model from transform auras
var transforms = GetAuraEffectsByType(AuraType.Transform);
if (!transforms.Empty())
{
// iterate over already applied transform auras - from newest to oldest
foreach (var eff in transforms)
{
AuraApplication aurApp = eff.GetBase().GetApplicationOfTarget(GetGUID());
if (aurApp != null)
{
if (handledAura == null)
{
if (!ignorePositiveAurasPreventingMounting)
handledAura = eff;
else
{
CreatureTemplate ci = Global.ObjectMgr.GetCreatureTemplate((uint)eff.GetMiscValue());
if (ci != null)
if (!IsDisallowedMountForm(eff.GetId(), ShapeShiftForm.None, ObjectManager.ChooseDisplayId(ci).CreatureDisplayID))
handledAura = eff;
}
}
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.AnimTier), (byte)animTier);
// prefer negative auras
if (!aurApp.IsPositive())
{
handledAura = eff;
break;
}
}
}
}
uint modelId;
// transform aura was found
if (handledAura != null)
handledAura.HandleEffect(this, AuraEffectHandleModes.SendForClient, true);
// we've found shapeshift
else if ((modelId = GetModelForForm(GetShapeshiftForm())) != 0)
if (notifyClient)
{
if (!ignorePositiveAurasPreventingMounting || !IsDisallowedMountForm(0, GetShapeshiftForm(), modelId))
SetDisplayId(modelId);
else
SetDisplayId(GetNativeDisplayId());
SetAnimTier setAnimTier = new SetAnimTier();
setAnimTier.Unit = GetGUID();
setAnimTier.Tier = (int)animTier;
SendMessageToSet(setAnimTier, true);
}
// no auras found - set modelid to default
else
SetDisplayId(GetNativeDisplayId());
}
public uint GetChannelSpellId() { return ((UnitChannel)m_unitData.ChannelData).SpellID; }
public void SetChannelSpellId(uint channelSpellId)
{
SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ChannelData)._value.SpellID, channelSpellId);
}
public uint GetChannelSpellXSpellVisualId() { return ((UnitChannel)m_unitData.ChannelData).SpellXSpellVisualID; }
public void SetChannelSpellXSpellVisualId(uint channelSpellXSpellVisualId)
{
UnitChannel unitChannel = m_unitData.ModifyValue(m_unitData.ChannelData);
SetUpdateFieldValue(ref unitChannel.SpellXSpellVisualID, channelSpellXSpellVisualId);
}
public void AddChannelObject(ObjectGuid guid) { AddDynamicUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ChannelObjects), guid); }
public void SetChannelObject(int slot, ObjectGuid guid) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ChannelObjects, slot), guid); }
public void ClearChannelObjects() { ClearDynamicUpdateFieldValues(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ChannelObjects)); }
public bool IsDamageReducedByArmor(SpellSchoolMask schoolMask, SpellInfo spellInfo = null, sbyte effIndex = -1)
{
// only physical spells damage gets reduced by armor
@@ -2632,162 +2660,68 @@ namespace Game.Entities
return true;
}
public override void BuildValuesUpdate(UpdateType updatetype, ByteBuffer data, Player target)
public override UpdateFieldFlag GetUpdateFieldFlagsFor(Player target)
{
if (target == null)
return;
UpdateFieldFlag flags = UpdateFieldFlag.None;
if (target == this || GetOwnerGUID() == target.GetGUID())
flags |= UpdateFieldFlag.Owner;
ByteBuffer fieldBuffer = new ByteBuffer();
uint valCount = valuesCount;
uint[] flags = UpdateFieldFlags.UnitUpdateFieldFlags;
uint visibleFlag = UpdateFieldFlags.Public;
if (target == this)
visibleFlag |= UpdateFieldFlags.Private;
else if (IsTypeId(TypeId.Player))
valCount = (int)PlayerFields.End;
UpdateMask updateMask = new UpdateMask(valCount);
Player plr = GetCharmerOrOwnerPlayerOrPlayerItself();
if (GetOwnerGUID() == target.GetGUID())
visibleFlag |= UpdateFieldFlags.Owner;
if (HasFlag(ObjectFields.DynamicFlags, UnitDynFlags.SpecialInfo))
if (HasDynamicFlag(UnitDynFlags.SpecialInfo))
if (HasAuraTypeWithCaster(AuraType.Empathy, target.GetGUID()))
visibleFlag |= UpdateFieldFlags.SpecialInfo;
flags |= UpdateFieldFlag.Empath;
if (plr != null && plr.IsInSameRaidWith(target))
visibleFlag |= UpdateFieldFlags.PartyMember;
return flags;
}
Creature creature = ToCreature();
for (var index = 0; index < valCount; ++index)
{
if (Convert.ToBoolean(_fieldNotifyFlags & flags[index]) ||
Convert.ToBoolean((flags[index] & visibleFlag) & UpdateFieldFlags.SpecialInfo) ||
((updatetype == UpdateType.Values ? _changesMask.Get(index) : updateValues[index].UnsignedValue != 0) && flags[index].HasAnyFlag(visibleFlag)) ||
(index == (int)UnitFields.AuraState && HasFlag(UnitFields.AuraState, AuraStateType.PerCasterAuraStateMask)))
{
updateMask.SetBit(index);
public override void BuildValuesCreate(WorldPacket data, Player target)
{
UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
WorldPacket buffer = new WorldPacket();
if (index == (int)UnitFields.NpcFlags)
{
uint appendValue = GetUInt32Value(UnitFields.NpcFlags);
buffer.WriteUInt8((byte)flags);
m_objectData.WriteCreate(buffer, flags, this, target);
m_unitData.WriteCreate(buffer, flags, this, target);
if (creature != null)
if (!target.CanSeeSpellClickOn(creature))
appendValue &= ~(uint)NPCFlags.SpellClick;
data.WriteUInt32(buffer.GetSize());
data.WriteBytes(buffer);
}
fieldBuffer.WriteUInt32(appendValue);
}
else if (index == (int)UnitFields.AuraState)
{
// Check per caster aura states to not enable using a spell in client if specified aura is not by target
fieldBuffer.WriteUInt32(BuildAuraStateUpdateForTarget(target));
}
// FIXME: Some values at server stored in float format but must be sent to client in public uint format
else if ((index >= (int)UnitFields.NegStat && index < (int)UnitFields.NegStat + (int)Stats.Max) ||
(index >= (int)UnitFields.PosStat && index < (int)UnitFields.PosStat + (int)Stats.Max))
{
fieldBuffer.WriteUInt32((uint)GetFloatValue(index));
}
// Gamemasters should be always able to select units - remove not selectable flag
else if (index == (int)UnitFields.Flags)
{
UnitFlags appendValue = (UnitFlags)updateValues[index].UnsignedValue;
if (target.IsGameMaster())
appendValue &= ~UnitFlags.NotSelectable;
public override void BuildValuesUpdate(WorldPacket data, Player target)
{
UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
WorldPacket buffer = new WorldPacket();
fieldBuffer.WriteUInt32((uint)appendValue);
}
// use modelid_a if not gm, _h if gm for CREATURE_FLAG_EXTRA_TRIGGER creatures
else if (index == (int)UnitFields.DisplayId)
{
uint displayId = updateValues[index].UnsignedValue;
if (creature != null)
{
CreatureTemplate cinfo = creature.GetCreatureTemplate();
buffer.WriteUInt32(m_values.GetChangedObjectTypeMask());
if (m_values.HasChanged(TypeId.Object))
m_objectData.WriteUpdate(buffer, flags, this, target);
// this also applies for transform auras
SpellInfo transform = Global.SpellMgr.GetSpellInfo(getTransForm());
if (transform != null)
{
foreach (SpellEffectInfo effect in transform.GetEffectsForDifficulty(GetMap().GetDifficultyID()))
{
if (effect != null && effect.IsAura(AuraType.Transform))
{
CreatureTemplate transformInfo = Global.ObjectMgr.GetCreatureTemplate((uint)effect.MiscValue);
if (transformInfo != null)
{
cinfo = transformInfo;
break;
}
}
}
}
if (m_values.HasChanged(TypeId.Unit))
m_unitData.WriteUpdate(buffer, flags, this, target);
if (cinfo.FlagsExtra.HasAnyFlag(CreatureFlagsExtra.Trigger))
if (target.IsGameMaster())
displayId = cinfo.GetFirstVisibleModel().CreatureDisplayID;
}
data.WriteUInt32(buffer.GetSize());
data.WriteBytes(buffer);
}
fieldBuffer.WriteUInt32(displayId);
}
// hide lootable animation for unallowed players
else if (index == (int)ObjectFields.DynamicFlags)
{
UnitDynFlags dynamicFlags = (UnitDynFlags)updateValues[index].UnsignedValue & ~UnitDynFlags.Tapped;
void BuildValuesUpdateWithFlag(WorldPacket data, UpdateFieldFlag flags, Player target)
{
UpdateMask valuesMask = new UpdateMask(14);
valuesMask.Set((int)TypeId.Unit);
if (creature != null)
{
if (creature.hasLootRecipient() && !creature.isTappedBy(target))
dynamicFlags |= UnitDynFlags.Tapped;
WorldPacket buffer = new WorldPacket();
if (!target.isAllowedToLoot(creature))
dynamicFlags &= ~UnitDynFlags.Lootable;
}
UpdateMask mask = new UpdateMask(191);
m_unitData.AppendAllowedFieldsMaskForFlag(mask, flags);
m_unitData.WriteUpdate(buffer, mask, flags, this, target);
// unit UNIT_DYNFLAG_TRACK_UNIT should only be sent to caster of SPELL_AURA_MOD_STALKED auras
if (dynamicFlags.HasAnyFlag(UnitDynFlags.TrackUnit))
if (!HasAuraTypeWithCaster(AuraType.ModStalked, target.GetGUID()))
dynamicFlags &= ~UnitDynFlags.TrackUnit;
data.WriteUInt32(buffer.GetSize());
data.WriteUInt32(valuesMask.GetBlock(0));
data.WriteBytes(buffer);
}
fieldBuffer.WriteUInt32((uint)dynamicFlags);
}
// FG: pretend that OTHER players in own group are friendly ("blue")
else if (index == (int)UnitFields.Bytes2 || index == (int)UnitFields.FactionTemplate)
{
if (IsControlledByPlayer() && target != this && WorldConfig.GetBoolValue(WorldCfg.AllowTwoSideInteractionGroup) && IsInRaidWith(target))
{
FactionTemplateRecord ft1 = GetFactionTemplateEntry();
FactionTemplateRecord ft2 = target.GetFactionTemplateEntry();
if (ft1 != null && ft2 != null && !ft1.IsFriendlyTo(ft2))
{
if (index == (int)UnitFields.Bytes2)
// Allow targetting opposite faction in party when enabled in config
fieldBuffer.WriteUInt32(updateValues[index].UnsignedValue & ((int)UnitBytes2Flags.Sanctuary << 8)); // this flag is at public byte offset 1 !!
else
// pretend that all other HOSTILE players have own faction, to allow follow, heal, rezz (trade wont work)
fieldBuffer.WriteUInt32(target.getFaction());
}
else
fieldBuffer.WriteUInt32(updateValues[index].UnsignedValue);
}
else
fieldBuffer.WriteUInt32(updateValues[index].UnsignedValue);
}
else
{
// send in current format (float as float, public uint as uint32)
fieldBuffer.WriteUInt32(updateValues[index].UnsignedValue);
}
}
}
updateMask.AppendToPacket(data);
data.WriteBytes(fieldBuffer);
public override void ClearUpdateMask(bool remove)
{
m_values.ClearChangesMask(m_unitData);
base.ClearUpdateMask(remove);
}
public override void DestroyForPlayer(Player target)
+8 -8
View File
@@ -53,9 +53,9 @@ namespace Game.Entities
// Set or remove correct flags based on available seats. Will overwrite db data (if wrong).
if (UsableSeatNum != 0)
_me.SetFlag64(UnitFields.NpcFlags, (_me.IsTypeId(TypeId.Player) ? NPCFlags.PlayerVehicle : NPCFlags.SpellClick));
_me.AddNpcFlag(_me.IsTypeId(TypeId.Player) ? NPCFlags.PlayerVehicle : NPCFlags.SpellClick);
else
_me.RemoveFlag64(UnitFields.NpcFlags, (_me.IsTypeId(TypeId.Player) ? NPCFlags.PlayerVehicle : NPCFlags.SpellClick));
_me.RemoveNpcFlag(_me.IsTypeId(TypeId.Player) ? NPCFlags.PlayerVehicle : NPCFlags.SpellClick);
InitMovementInfoForBase();
}
@@ -345,7 +345,7 @@ namespace Game.Entities
unit.GetName(), _me.GetEntry(), _vehicleInfo.Id, _me.GetGUID().ToString(), seat.Key);
if (seat.Value.SeatInfo.CanEnterOrExit() && ++UsableSeatNum != 0)
_me.SetFlag64(UnitFields.NpcFlags, (_me.IsTypeId(TypeId.Player) ? NPCFlags.PlayerVehicle : NPCFlags.SpellClick));
_me.AddNpcFlag(_me.IsTypeId(TypeId.Player) ? NPCFlags.PlayerVehicle : NPCFlags.SpellClick);
// Enable gravity for passenger when he did not have it active before entering the vehicle
if (seat.Value.SeatInfo.Flags.HasAnyFlag(VehicleSeatFlags.DisableGravity) && !seat.Value.Passenger.IsGravityDisabled)
@@ -353,7 +353,7 @@ namespace Game.Entities
// Remove UNIT_FLAG_NOT_SELECTABLE if passenger did not have it before entering vehicle
if (seat.Value.SeatInfo.Flags.HasAnyFlag(VehicleSeatFlags.PassengerNotSelectable) && !seat.Value.Passenger.IsUnselectable)
unit.RemoveFlag(UnitFields.Flags, UnitFlags.NotSelectable);
unit.RemoveUnitFlag(UnitFlags.NotSelectable);
seat.Value.Passenger.Reset();
@@ -560,7 +560,7 @@ namespace Game.Entities
Passenger.SetVehicle(Target);
Seat.Value.Passenger.Guid = Passenger.GetGUID();
Seat.Value.Passenger.IsUnselectable = Passenger.HasFlag(UnitFields.Flags, UnitFlags.NotSelectable);
Seat.Value.Passenger.IsUnselectable = Passenger.HasUnitFlag(UnitFlags.NotSelectable);
Seat.Value.Passenger.IsGravityDisabled = Passenger.HasUnitMovementFlag(MovementFlag.DisableGravity);
if (Seat.Value.SeatInfo.CanEnterOrExit())
{
@@ -569,9 +569,9 @@ namespace Game.Entities
if (Target.UsableSeatNum == 0)
{
if (Target.GetBase().IsTypeId(TypeId.Player))
Target.GetBase().RemoveFlag64(UnitFields.NpcFlags, NPCFlags.PlayerVehicle);
Target.GetBase().RemoveNpcFlag(NPCFlags.PlayerVehicle);
else
Target.GetBase().RemoveFlag64(UnitFields.NpcFlags, NPCFlags.SpellClick);
Target.GetBase().RemoveNpcFlag(NPCFlags.SpellClick);
}
}
@@ -599,7 +599,7 @@ namespace Game.Entities
Passenger.SetDisableGravity(true);
if (Seat.Value.SeatInfo.Flags.HasAnyFlag(VehicleSeatFlags.PassengerNotSelectable))
Passenger.SetFlag(UnitFields.Flags, UnitFlags.NotSelectable);
Passenger.AddUnitFlag(UnitFlags.NotSelectable);
Passenger.m_movementInfo.transport.pos.Relocate(veSeat.AttachmentOffset.X, veSeat.AttachmentOffset.Y, veSeat.AttachmentOffset.Z);
Passenger.m_movementInfo.transport.time = 0;