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