BFA Update (still lots of testing to do tho)

This commit is contained in:
hondacrx
2018-12-10 12:46:25 -05:00
parent 468b053946
commit 8e20114e10
256 changed files with 35613 additions and 10459 deletions
@@ -39,7 +39,8 @@ namespace Game.Entities
objectTypeMask |= TypeMask.AreaTrigger;
objectTypeId = TypeId.AreaTrigger;
m_updateFlag = UpdateFlag.StationaryPosition | UpdateFlag.Areatrigger;
m_updateFlag.Stationary = true;
m_updateFlag.AreaTrigger = true;
valuesCount = (int)AreaTriggerFields.End;
@@ -142,7 +143,7 @@ namespace Game.Entities
{
AreaTriggerCircularMovementInfo cmi = GetMiscTemplate().CircularMovementInfo;
if (target && GetTemplate().HasFlag(AreaTriggerFlags.HasAttached))
cmi.TargetGUID.Set(target.GetGUID());
cmi.PathTarget.Set(target.GetGUID());
else
cmi.Center.Set(new Vector3(pos.posX, pos.posY, pos.posZ));
@@ -624,12 +625,12 @@ namespace Game.Entities
{
if (_reachedDestination)
{
AreaTriggerReShape reshapeDest = new AreaTriggerReShape();
AreaTriggerRePath reshapeDest = new AreaTriggerRePath();
reshapeDest.TriggerGUID = GetGUID();
SendMessageToSet(reshapeDest, true);
}
AreaTriggerReShape reshape = new AreaTriggerReShape();
AreaTriggerRePath reshape = new AreaTriggerRePath();
reshape.TriggerGUID = GetGUID();
reshape.AreaTriggerSpline.HasValue = true;
reshape.AreaTriggerSpline.Value.ElapsedTimeForMovement = GetElapsedTimeForMovement();
@@ -644,7 +645,7 @@ namespace Game.Entities
void InitCircularMovement(AreaTriggerCircularMovementInfo cmi, uint timeToTarget)
{
// Circular movement requires either a center position or an attached unit
Cypher.Assert(cmi.Center.HasValue || cmi.TargetGUID.HasValue);
Cypher.Assert(cmi.Center.HasValue || cmi.PathTarget.HasValue);
// should be sent in object create packets only
updateValues[(int)AreaTriggerFields.TimeToTarget].UnsignedValue = timeToTarget;
@@ -656,7 +657,7 @@ namespace Game.Entities
if (IsInWorld)
{
AreaTriggerReShape reshape = new AreaTriggerReShape();
AreaTriggerRePath reshape = new AreaTriggerRePath();
reshape.TriggerGUID = GetGUID();
reshape.AreaTriggerCircularMovement = _circularMovementInfo;
@@ -671,12 +672,12 @@ namespace Game.Entities
Position GetCircularMovementCenterPosition()
{
if (_circularMovementInfo.HasValue)
if (!_circularMovementInfo.HasValue)
return null;
if (_circularMovementInfo.Value.TargetGUID.HasValue)
if (_circularMovementInfo.Value.PathTarget.HasValue)
{
WorldObject center = Global.ObjAccessor.GetWorldObject(this, _circularMovementInfo.Value.TargetGUID.Value);
WorldObject center = Global.ObjAccessor.GetWorldObject(this, _circularMovementInfo.Value.PathTarget.Value);
if (center)
return center;
}
@@ -120,7 +120,7 @@ namespace Game.Entities
{
public void Write(WorldPacket data)
{
data.WriteBit(TargetGUID.HasValue);
data.WriteBit(PathTarget.HasValue);
data.WriteBit(Center.HasValue);
data.WriteBit(CounterClockwise);
data.WriteBit(CanLoop);
@@ -133,14 +133,14 @@ namespace Game.Entities
data.WriteFloat(InitialAngle);
data.WriteFloat(ZOffset);
if (TargetGUID.HasValue)
data.WritePackedGuid(TargetGUID.Value);
if (PathTarget.HasValue)
data.WritePackedGuid(PathTarget.Value);
if (Center.HasValue)
data.WriteVector3(Center.Value);
}
public Optional<ObjectGuid> TargetGUID;
public Optional<ObjectGuid> PathTarget;
public Optional<Vector3> Center;
public bool CounterClockwise;
public bool CanLoop;
@@ -228,6 +228,9 @@ namespace Game.Entities
public uint MorphCurveId;
public uint FacingCurveId;
public uint AnimId;
public uint AnimKitId;
public uint DecalPropertiesId;
public uint TimeToTarget;
+14 -3
View File
@@ -32,7 +32,8 @@ namespace Game.Entities
objectTypeMask |= TypeMask.Conversation;
objectTypeId = TypeId.Conversation;
m_updateFlag = UpdateFlag.StationaryPosition;
m_updateFlag.Stationary = true;
m_updateFlag.Conversation = true;
valuesCount = (int)ConversationFields.End;
_dynamicValuesCount = (int)ConversationDynamicFields.End;
@@ -118,6 +119,7 @@ namespace Game.Entities
SetUInt32Value(ConversationFields.LastLineEndTime, conversationTemplate.LastLineEndTime);
_duration = conversationTemplate.LastLineEndTime;
_textureKitId = conversationTemplate.TextureKitId;
for (ushort actorIndex = 0; actorIndex < conversationTemplate.Actors.Count; ++actorIndex)
{
@@ -125,7 +127,8 @@ namespace Game.Entities
if (actor != null)
{
ConversationDynamicFieldActor actorField = new ConversationDynamicFieldActor();
actorField.ActorTemplate = actor;
actorField.ActorTemplate.CreatureId = actor.CreatureId;
actorField.ActorTemplate.CreatureModelId = actor.CreatureModelId;
actorField.Type = ConversationDynamicFieldActor.ActorType.CreatureActor;
SetDynamicStructuredValue(ConversationDynamicFields.Actors, actorIndex, actorField);
}
@@ -189,6 +192,7 @@ namespace Game.Entities
}
uint GetDuration() { return _duration; }
public uint GetTextureKitId() { return _textureKitId; }
public ObjectGuid GetCreatorGuid() { return _creatorGuid; }
@@ -201,6 +205,7 @@ namespace Game.Entities
Position _stationaryPosition = new Position();
ObjectGuid _creatorGuid;
uint _duration;
uint _textureKitId;
List<ObjectGuid> _participants = new List<ObjectGuid>();
}
@@ -218,7 +223,13 @@ namespace Game.Entities
}
public ObjectGuid ActorGuid;
public ConversationActorTemplate ActorTemplate;
public ActorTemplateStruct ActorTemplate;
public struct ActorTemplateStruct
{
public uint CreatureId;
public uint CreatureModelId;
}
public ActorType Type;
}
+1 -1
View File
@@ -32,7 +32,7 @@ namespace Game.Entities
objectTypeId = TypeId.Corpse;
objectTypeMask |= TypeMask.Corpse;
m_updateFlag = UpdateFlag.StationaryPosition;
m_updateFlag.Stationary = true;
valuesCount = (int)CorpseFields.End;
+45 -27
View File
@@ -141,6 +141,10 @@ namespace Game.Entities
if (setSpawnTime)
m_respawnTime = Time.UnixTime + respawnDelay;
// if corpse was removed during falling, the falling will continue and override relocation to respawn position
if (IsFalling())
StopMoving();
float x, y, z, o;
GetRespawnPosition(out x, out y, out z, out o);
SetHomePosition(x, y, z, o);
@@ -193,22 +197,22 @@ namespace Game.Entities
SetByteValue(UnitFields.Bytes0, 1, (byte)cinfo.UnitClass);
// Cancel load if no model defined
if (cinfo.GetFirstValidModelId() == 0)
if (cinfo.GetFirstValidModel() == null)
{
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) has no model defined in table `creature_template`, can't load. ", entry);
return false;
}
uint displayID = ObjectManager.ChooseDisplayId(GetCreatureTemplate(), data);
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelRandomGender(ref displayID);
CreatureModel model = ObjectManager.ChooseDisplayId(cinfo, data);
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelRandomGender(ref model, cinfo);
if (minfo == null) // Cancel load if no model defined
{
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) has no model defined in table `creature_template`, can't load. ", entry);
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) has invalid model {1} defined in table `creature_template`, can't load.", entry, model.CreatureDisplayID);
return false;
}
SetDisplayId(displayID);
SetNativeDisplayId(displayID);
SetDisplayId(model.CreatureDisplayID, model.DisplayScale);
SetNativeDisplayId(model.CreatureDisplayID, model.DisplayScale);
SetByteValue(UnitFields.Bytes0, 3, (byte)minfo.gender);
// Load creature equipment
@@ -279,6 +283,8 @@ namespace Game.Entities
SetUInt32Value(ObjectFields.DynamicFlags, dynamicFlags);
SetUInt32Value(UnitFields.StateAnimId, (uint)CliDB.AnimationDataStorage.Count);
RemoveFlag(UnitFields.Flags, UnitFlags.InCombat);
SetBaseAttackTime(WeaponAttackType.BaseAttack, cInfo.BaseAttackTime);
@@ -768,7 +774,8 @@ namespace Game.Entities
if (!CreateFromProto(guidlow, entry, data, vehId))
return false;
switch (GetCreatureTemplate().Rank)
cinfo = GetCreatureTemplate(); // might be different than initially requested
switch (cinfo.Rank)
{
case CreatureEliteType.Rare:
m_corpseDelay = WorldConfig.GetUIntValue(WorldCfg.CorpseDecayRare);
@@ -797,12 +804,12 @@ namespace Game.Entities
Relocate(x, y, z, ang);
}
uint displayID = GetNativeDisplayId();
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelRandomGender(ref displayID);
CreatureModel display = new CreatureModel(GetNativeDisplayId(), GetNativeDisplayScale(), 1.0f);
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelRandomGender(ref display, cinfo);
if (minfo != null && !IsTotem()) // Cancel load if no model defined or if totem
{
SetDisplayId(displayID);
SetNativeDisplayId(displayID);
SetDisplayId(display.CreatureDisplayID, display.DisplayScale);
SetNativeDisplayId(display.CreatureDisplayID, display.DisplayScale);
SetByteValue(UnitFields.Bytes0, 3, (byte)minfo.gender);
}
@@ -815,10 +822,10 @@ namespace Game.Entities
m_serverSideVisibilityDetect.SetValue(ServerSideVisibilityType.Ghost, GhostVisibilityType.Ghost);
}
if (GetCreatureTemplate().FlagsExtra.HasAnyFlag(CreatureFlagsExtra.IgnorePathfinding))
if (cinfo.FlagsExtra.HasAnyFlag(CreatureFlagsExtra.IgnorePathfinding))
AddUnitState(UnitState.IgnorePathfinding);
if (GetCreatureTemplate().FlagsExtra.HasAnyFlag(CreatureFlagsExtra.ImmunityKnockback))
if (cinfo.FlagsExtra.HasAnyFlag(CreatureFlagsExtra.ImmunityKnockback))
{
ApplySpellImmune(0, SpellImmunity.Effect, SpellEffectName.KnockBack, true);
ApplySpellImmune(0, SpellImmunity.Effect, SpellEffectName.KnockBackDest, true);
@@ -1014,9 +1021,9 @@ namespace Game.Entities
CreatureTemplate cinfo = GetCreatureTemplate();
if (cinfo != null)
{
if (displayId == cinfo.ModelId1 || displayId == cinfo.ModelId2 ||
displayId == cinfo.ModelId3 || displayId == cinfo.ModelId4)
displayId = 0;
foreach (CreatureModel model in cinfo.Models)
if (displayId != 0 && displayId == model.CreatureDisplayID)
displayId = 0;
if (npcflag == (uint)cinfo.Npcflag)
npcflag = 0;
@@ -1620,12 +1627,12 @@ namespace Game.Entities
setDeathState(DeathState.JustRespawned);
uint displayID = GetNativeDisplayId();
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelRandomGender(ref displayID);
CreatureModel display = new CreatureModel(GetNativeDisplayId(), GetNativeDisplayScale(), 1.0f);
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelRandomGender(ref display, GetCreatureTemplate());
if (minfo != null) // Cancel load if no model defined
{
SetDisplayId(displayID);
SetNativeDisplayId(displayID);
SetDisplayId(display.CreatureDisplayID, display.DisplayScale);
SetNativeDisplayId(display.CreatureDisplayID, display.DisplayScale);
SetByteValue(UnitFields.Bytes0, 3, (byte)minfo.gender);
}
@@ -2372,7 +2379,7 @@ namespace Game.Entities
int targetLevelWithDelta = ((int)unitTarget.getLevel() + GetInt32Value(UnitFields.ScalingLevelDelta));
if (target.IsPlayer())
targetLevelWithDelta += target.GetInt32Value(PlayerFields.ScalingLevelDelta);
targetLevelWithDelta += target.GetInt32Value(ActivePlayerFields.ScalingPlayerLevelDelta);
return (uint)MathFunctions.RoundToInterval(ref targetLevelWithDelta, GetInt32Value(UnitFields.ScalingLevelMin), GetInt32Value(UnitFields.ScalingLevelMax));
}
@@ -2622,6 +2629,10 @@ namespace Game.Entities
if (m_playerMovingMe != null)
return;
// Creatures with CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE should control MovementFlags in your own scripts
if (GetCreatureTemplate().FlagsExtra.HasAnyFlag(CreatureFlagsExtra.NoMoveFlagsUpdate))
return;
// Set the movement flags if the creature is in that mode. (Only fly if actually in air, only swim if in water, etc)
float ground = GetMap().GetHeight(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZMinusOffset());
@@ -2653,23 +2664,30 @@ namespace Game.Entities
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelInfo(GetDisplayId());
if (minfo != null)
{
SetFloatValue(UnitFields.BoundingRadius, minfo.BoundingRadius * scale);
SetFloatValue(UnitFields.CombatReach, minfo.CombatReach * scale);
SetFloatValue(UnitFields.BoundingRadius, (IsPet() ? 1.0f : minfo.BoundingRadius) * scale);
SetFloatValue(UnitFields.CombatReach, (IsPet() ? SharedConst.DefaultCombatReach : minfo.CombatReach) * scale);
}
}
public override void SetDisplayId(uint modelId)
public override void SetDisplayId(uint modelId, float displayScale = 1f)
{
base.SetDisplayId(modelId);
base.SetDisplayId(modelId, displayScale);
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelInfo(modelId);
if (minfo != null)
{
SetFloatValue(UnitFields.BoundingRadius, minfo.BoundingRadius * GetObjectScale());
SetFloatValue(UnitFields.CombatReach, minfo.CombatReach * GetObjectScale());
SetFloatValue(UnitFields.BoundingRadius, (IsPet() ? 1.0f : minfo.BoundingRadius) * GetObjectScale());
SetFloatValue(UnitFields.CombatReach, (IsPet() ? SharedConst.DefaultCombatReach : minfo.CombatReach) * GetObjectScale());
}
}
public void SetDisplayFromModel(int modelIdx)
{
CreatureModel model = GetCreatureTemplate().GetModelByIdx(modelIdx);
if (model != null)
SetDisplayId(model.CreatureDisplayID, model.DisplayScale);
}
public override void SetTarget(ObjectGuid guid)
{
if (IsFocusing(null, true))
+65 -58
View File
@@ -28,10 +28,7 @@ namespace Game.Entities
public uint Entry;
public uint[] DifficultyEntry = new uint[SharedConst.MaxCreatureDifficulties];
public uint[] KillCredit = new uint[SharedConst.MaxCreatureKillCredit];
public uint ModelId1;
public uint ModelId2;
public uint ModelId3;
public uint ModelId4;
public List<CreatureModel> Models = new List<CreatureModel>();
public string Name;
public string FemaleName;
public string SubName;
@@ -91,75 +88,67 @@ namespace Game.Entities
public CreatureFlagsExtra FlagsExtra;
public uint ScriptID;
public uint GetRandomValidModelId()
public CreatureModel GetModelByIdx(int idx)
{
byte c = 0;
uint[] modelIDs = new uint[4];
if (ModelId1 != 0)
modelIDs[c++] = ModelId1;
if (ModelId2 != 0)
modelIDs[c++] = ModelId2;
if (ModelId3 != 0)
modelIDs[c++] = ModelId3;
if (ModelId4 != 0)
modelIDs[c++] = ModelId4;
return c > 0 ? modelIDs[RandomHelper.IRand(0, c - 1)] : 0;
}
public uint GetFirstValidModelId()
{
if (ModelId1 != 0)
return ModelId1;
if (ModelId2 != 0)
return ModelId2;
if (ModelId3 != 0)
return ModelId3;
if (ModelId4 != 0)
return ModelId4;
return 0;
return idx < Models.Count ? Models[idx] : null;
}
public uint GetFirstInvisibleModel()
public CreatureModel GetRandomValidModel()
{
CreatureModelInfo modelInfo = Global.ObjectMgr.GetCreatureModelInfo(ModelId1);
if (modelInfo != null && modelInfo.IsTrigger)
return ModelId1;
if (Models.Empty())
return null;
modelInfo = Global.ObjectMgr.GetCreatureModelInfo(ModelId2);
if (modelInfo != null && modelInfo.IsTrigger)
return ModelId2;
// If only one element, ignore the Probability (even if 0)
if (Models.Count == 1)
return Models[0];
modelInfo = Global.ObjectMgr.GetCreatureModelInfo(ModelId3);
if (modelInfo != null && modelInfo.IsTrigger)
return ModelId3;
var selectedItr = Models.SelectRandomElementByWeight(model =>
{
return model.Probability;
});
modelInfo = Global.ObjectMgr.GetCreatureModelInfo(ModelId4);
if (modelInfo != null && modelInfo.IsTrigger)
return ModelId4;
return selectedItr;
}
public CreatureModel GetFirstValidModel()
{
foreach (CreatureModel model in Models)
if (model.CreatureDisplayID != 0)
return model;
return 11686;
return null;
}
public uint GetFirstVisibleModel()
public CreatureModel GetModelWithDisplayId(uint displayId)
{
CreatureModelInfo modelInfo = Global.ObjectMgr.GetCreatureModelInfo(ModelId1);
if (modelInfo != null && !modelInfo.IsTrigger)
return ModelId1;
foreach (CreatureModel model in Models)
if (displayId == model.CreatureDisplayID)
return model;
modelInfo = Global.ObjectMgr.GetCreatureModelInfo(ModelId2);
if (modelInfo != null && !modelInfo.IsTrigger)
return ModelId2;
return null;
}
modelInfo = Global.ObjectMgr.GetCreatureModelInfo(ModelId3);
if (modelInfo != null && !modelInfo.IsTrigger)
return ModelId3;
public CreatureModel GetFirstInvisibleModel()
{
foreach (CreatureModel model in Models)
{
CreatureModelInfo modelInfo = Global.ObjectMgr.GetCreatureModelInfo(model.CreatureDisplayID);
if (modelInfo != null && modelInfo.IsTrigger)
return model;
}
modelInfo = Global.ObjectMgr.GetCreatureModelInfo(ModelId4);
if (modelInfo != null && !modelInfo.IsTrigger)
return ModelId4;
return CreatureModel.DefaultInvisibleModel;
}
return 17519;
public CreatureModel GetFirstVisibleModel()
{
foreach (CreatureModel model in Models)
{
CreatureModelInfo modelInfo = Global.ObjectMgr.GetCreatureModelInfo(model.CreatureDisplayID);
if (modelInfo != null && !modelInfo.IsTrigger)
return model;
}
return CreatureModel.DefaultVisibleModel;
}
public SkillType GetRequiredLootSkill()
@@ -314,6 +303,24 @@ namespace Game.Entities
public bool IsTrigger;
}
public class CreatureModel
{
public static CreatureModel DefaultInvisibleModel = new CreatureModel(11686, 1.0f, 1.0f);
public static CreatureModel DefaultVisibleModel = new CreatureModel(17519, 1.0f, 1.0f);
public uint CreatureDisplayID;
public float DisplayScale;
public float Probability;
public CreatureModel() { }
public CreatureModel(uint creatureDisplayID, float displayScale, float probability)
{
CreatureDisplayID = creatureDisplayID;
DisplayScale = displayScale;
Probability = probability;
}
}
public class CreatureAddon
{
public uint path_id;
+8 -2
View File
@@ -316,6 +316,7 @@ namespace Game.Misc
}
GossipPOI packet = new GossipPOI();
packet.ID = pointOfInterest.ID;
packet.Name = pointOfInterest.Name;
LocaleConstant locale = _session.GetSessionDbLocaleIndex();
@@ -431,10 +432,11 @@ namespace Game.Misc
packet.InformUnit = _session.GetPlayer().GetDivider();
packet.QuestID = quest.Id;
packet.PortraitGiver = quest.QuestGiverPortrait;
packet.PortraitGiverMount = quest.QuestGiverPortraitMount;
packet.PortraitTurnIn = quest.QuestTurnInPortrait;
packet.AutoLaunched = autoLaunched;
packet.DisplayPopup = displayPopup;
packet.QuestFlags[0] = (uint)quest.Flags;
packet.QuestFlags[0] = (uint)(quest.Flags & (WorldConfig.GetBoolValue(WorldCfg.QuestIgnoreAutoAccept) ? ~QuestFlags.AutoAccept : ~QuestFlags.None));
packet.QuestFlags[1] = (uint)quest.FlagsEx;
packet.SuggestedPartyMembers = quest.SuggestedPlayers;
@@ -501,6 +503,7 @@ namespace Game.Misc
packet.Info.QuestID = quest.Id;
packet.Info.QuestType = (int)quest.Type;
packet.Info.QuestLevel = quest.Level;
packet.Info.QuestScalingFactionGroup = quest.ScalingFactionGroup;
packet.Info.QuestMaxScalingLevel = quest.MaxScalingLevel;
packet.Info.QuestPackageID = quest.PackageID;
packet.Info.QuestMinLevel = quest.MinLevel;
@@ -532,12 +535,14 @@ namespace Game.Misc
packet.Info.StartItem = quest.SourceItemId;
packet.Info.Flags = (uint)quest.Flags;
packet.Info.FlagsEx = (uint)quest.FlagsEx;
packet.Info.FlagsEx2 = (uint)quest.FlagsEx2;
packet.Info.RewardTitle = quest.RewardTitleId;
packet.Info.RewardArenaPoints = quest.RewardArenaPoints;
packet.Info.RewardSkillLineID = quest.RewardSkillId;
packet.Info.RewardNumSkillUps = quest.RewardSkillPoints;
packet.Info.RewardFactionFlags = quest.RewardReputationMask;
packet.Info.PortraitGiver = quest.QuestGiverPortrait;
packet.Info.PortraitGiverMount = quest.QuestGiverPortraitMount;
packet.Info.PortraitTurnIn = quest.QuestTurnInPortrait;
for (byte i = 0; i < SharedConst.QuestItemDropCount; ++i)
@@ -574,7 +579,7 @@ namespace Game.Misc
packet.Info.POIPriority = quest.POIPriority;
packet.Info.AllowableRaces = quest.AllowableRaces;
packet.Info.QuestRewardID = (int)quest.QuestRewardID;
packet.Info.TreasurePickerID = (int)quest.TreasurePickerID;
packet.Info.Expansion = quest.Expansion;
foreach (QuestObjective questObjective in quest.Objectives)
@@ -654,6 +659,7 @@ namespace Game.Misc
packet.PortraitTurnIn = quest.QuestTurnInPortrait;
packet.PortraitGiver = quest.QuestGiverPortrait;
packet.PortraitGiverMount = quest.QuestGiverPortraitMount;
packet.QuestPackageID = quest.PackageID;
packet.QuestData = offer;
+28 -7
View File
@@ -15,8 +15,7 @@ namespace Game.Entities
public Array<uint> ReqAbility = new Array<uint>(3);
public byte ReqLevel;
public uint LearnedSpellId;
public bool IsCastable() { return LearnedSpellId != SpellId; }
public bool IsCastable() { return Global.SpellMgr.GetSpellInfo(SpellId).HasEffect(SpellEffectName.LearnSpell); }
}
public class Trainer
@@ -108,7 +107,7 @@ namespace Game.Entities
TrainerSpellState GetSpellState(Player player, TrainerSpell trainerSpell)
{
if (player.HasSpell(trainerSpell.IsCastable() ? trainerSpell.LearnedSpellId : trainerSpell.SpellId))
if (player.HasSpell(trainerSpell.SpellId))
return TrainerSpellState.Known;
// check race/class requirement
@@ -128,10 +127,32 @@ namespace Game.Entities
return TrainerSpellState.Unavailable;
// check ranks
uint previousRankSpellId = Global.SpellMgr.GetPrevSpellInChain(trainerSpell.LearnedSpellId);
if (previousRankSpellId != 0)
if (!player.HasSpell(previousRankSpellId))
return TrainerSpellState.Unavailable;
bool hasLearnSpellEffect = false;
bool knowsAllLearnedSpells = true;
foreach (SpellEffectInfo spellEffect in Global.SpellMgr.GetSpellInfo(trainerSpell.SpellId).GetEffectsForDifficulty(Difficulty.None))
{
if (spellEffect == null || !spellEffect.IsEffect(SpellEffectName.LearnSpell))
continue;
hasLearnSpellEffect = true;
if (!player.HasSpell(spellEffect.TriggerSpell))
knowsAllLearnedSpells = false;
uint previousRankSpellId = Global.SpellMgr.GetPrevSpellInChain(spellEffect.TriggerSpell);
if (previousRankSpellId != 0)
if (!player.HasSpell(previousRankSpellId))
return TrainerSpellState.Unavailable;
}
if (!hasLearnSpellEffect)
{
uint previousRankSpellId = Global.SpellMgr.GetPrevSpellInChain(trainerSpell.SpellId);
if (previousRankSpellId != 0)
if (!player.HasSpell(previousRankSpellId))
return TrainerSpellState.Unavailable;
}
else if (knowsAllLearnedSpells)
return TrainerSpellState.Known;
// check additional spell requirement
foreach (var spellId in Global.SpellMgr.GetSpellsRequiredForSpellBounds(trainerSpell.SpellId))
+1 -1
View File
@@ -27,7 +27,7 @@ namespace Game.Entities
objectTypeMask |= TypeMask.DynamicObject;
objectTypeId = TypeId.DynamicObject;
m_updateFlag = UpdateFlag.StationaryPosition;
m_updateFlag.Stationary = true;
valuesCount = (int)DynamicObjectFields.End;
}
@@ -41,7 +41,8 @@ namespace Game.Entities
objectTypeMask |= TypeMask.GameObject;
objectTypeId = TypeId.GameObject;
m_updateFlag = UpdateFlag.StationaryPosition | UpdateFlag.Rotation;
m_updateFlag.Stationary = true;
m_updateFlag.Rotation = true;
valuesCount = (int)GameObjectFields.End;
m_respawnDelayTime = 300;
@@ -219,7 +220,7 @@ namespace Game.Entities
else
{
guid = ObjectGuid.Create(HighGuid.Transport, map.GenerateLowGuid(HighGuid.Transport));
m_updateFlag |= UpdateFlag.Transport;
m_updateFlag.ServerTime = true;
}
_Create(guid);
@@ -252,7 +253,7 @@ namespace Game.Entities
if (m_goTemplateAddon.WorldEffectID != 0)
{
m_updateFlag |= UpdateFlag.Gameobject;
m_updateFlag.GameObject = true;
SetWorldEffectID(m_goTemplateAddon.WorldEffectID);
}
}
@@ -274,6 +275,8 @@ namespace Game.Entities
SetGoState(goState);
SetGoArtKit((byte)artKit);
SetUInt32Value(GameObjectFields.StateAnimId, (uint)CliDB.AnimationDataStorage.Count);
switch (goInfo.type)
{
case GameObjectTypes.FishingHole:
@@ -356,7 +359,7 @@ namespace Game.Entities
if (gameObjectAddon != null && gameObjectAddon.WorldEffectID != 0)
{
m_updateFlag |= UpdateFlag.Gameobject;
m_updateFlag.GameObject = true;
SetWorldEffectID(gameObjectAddon.WorldEffectID);
}
@@ -194,6 +194,18 @@ namespace Game.Entities
[FieldOffset(68)]
public challengemodereward ChallengeModeReward;
[FieldOffset(68)]
public multi Multi;
[FieldOffset(68)]
public siegeableMulti SiegeableMulti;
[FieldOffset(68)]
public siegeableMO SiegeableMO;
[FieldOffset(68)]
public pvpReward PvpReward;
[FieldOffset(68)]
public raw Raw;
@@ -264,6 +276,10 @@ namespace Game.Entities
return CapturePoint.open;
case GameObjectTypes.GatheringNode:
return GatheringNode.open;
case GameObjectTypes.ChallengeModeReward:
return ChallengeModeReward.open;
case GameObjectTypes.PvpReward:
return PvpReward.open;
default:
return 0;
}
@@ -490,7 +506,7 @@ namespace Game.Entities
public uint usegrouplootrules; // 15 use group loot rules, enum { false, true, }; Default: false
public uint floatingTooltip; // 16 floatingTooltip, enum { false, true, }; Default: false
public uint conditionID1; // 17 conditionID1, References: PlayerCondition, NoValue = 0
public int xpLevel; // 18 xpLevel, int, Min value: -1, Max value: 123, Default value: 0
public uint xpLevel; // 18 XP Level Range, References: ContentTuning, NoValue = 0
public uint xpDifficulty; // 19 xpDifficulty, enum { No Exp, Trivial, Very Small, Small, Substandard, Standard, High, Epic, Dungeon, 5, }; Default: No Exp
public uint lootLevel; // 20 lootLevel, int, Min value: 0, Max value: 123, Default value: 0
public uint GroupXP; // 21 Group XP, enum { false, true, }; Default: false
@@ -505,6 +521,7 @@ namespace Game.Entities
public uint chestPersonalLoot; // 30 chest Personal Loot, References: Treasure, NoValue = 0
public uint turnpersonallootsecurityoff; // 31 turn personal loot security off, enum { false, true, }; Default: false
public uint ChestProperties; // 32 Chest Properties, References: ChestProperties, NoValue = 0
public uint chestPushLoot; // 33 chest Push Loot, References: Treasure, NoValue = 0
}
@@ -710,6 +727,7 @@ namespace Game.Entities
{
public uint creatureID; // 0 creatureID, References: Creature, NoValue = 0
public uint charges; // 1 charges, int, Min value: 0, Max value: 65535, Default value: 1
public uint Preferonlyifinlineofsight; // 2 Prefer only if in line of sight (expensive), enum { false, true, }; Default: false
}
@@ -885,7 +903,10 @@ namespace Game.Entities
public uint startOpen; // 1 startOpen, enum { false, true, }; Default: false
public uint autoClose; // 2 autoClose (ms), int, Min value: 0, Max value: 2147483647, Default value: 0
public uint BlocksPathsDown; // 3 Blocks Paths Down, enum { false, true, }; Default: false
public uint PathBlockerBump; // 4 Path Blocker Bump (ft), int, Min value: -2147483648, Max value: 2147483647, Default value: 0
public int PathBlockerBump; // 4 Path Blocker Bump (ft), int, Min value: -2147483648, Max value: 2147483647, Default value: 0
public uint GiganticAOI; // 5 Gigantic AOI, enum { false, true, }; Default: false
public uint InfiniteAOI; // 6 Infinite AOI, enum { false, true, }; Default: false
public uint DoorisOpaque; // 7 Door is Opaque (Disable portal on close), enum { false, true, }; Default: false
}
@@ -971,7 +992,7 @@ namespace Game.Entities
public struct phaseablemo
{
public int SpawnMap; // 0 Spawn Map, References: Map, NoValue = -1
public uint AreaNameSet; // 1 Area Name Set (Index), int, Min value: -2147483648, Max value: 2147483647, Default value: 0
public int AreaNameSet; // 1 Area Name Set (Index), int, Min value: -2147483648, Max value: 2147483647, Default value: 0
public uint DoodadSetA; // 2 Doodad Set A, int, Min value: 0, Max value: 2147483647, Default value: 0
public uint DoodadSetB; // 3 Doodad Set B, int, Min value: 0, Max value: 2147483647, Default value: 0
}
@@ -1009,7 +1030,7 @@ namespace Game.Entities
public struct uilink
{
public uint UILinkType; // 0 UI Link Type, enum { Adventure Journal, Obliterum Forge, }; Default: Adventure Journal
public uint UILinkType; // 0 UI Link Type, enum { Adventure Journal, Obliterum Forge, Scrapping Machine}; Default: Adventure Journal
public uint allowMounted; // 1 allowMounted, enum { false, true, }; Default: false
public uint GiganticAOI; // 2 Gigantic AOI, enum { false, true, }; Default: false
public uint spellFocusType; // 3 spellFocusType, References: SpellFocusObject, NoValue = 0
@@ -1032,7 +1053,7 @@ namespace Game.Entities
public uint openTextID; // 9 openTextID, References: BroadcastText, NoValue = 0
public uint floatingTooltip; // 10 floatingTooltip, enum { false, true, }; Default: false
public uint conditionID1; // 11 conditionID1, References: PlayerCondition, NoValue = 0
public uint xpLevel; // 12 xpLevel, int, Min value: -1, Max value: 123, Default value: 0
public uint XPLevelRange; // 12 XP Level Range, References: ContentTuning, NoValue = 0
public uint xpDifficulty; // 13 xpDifficulty, enum { No Exp, Trivial, Very Small, Small, Substandard, Standard, High, Epic, Dungeon, 5, }; Default: No Exp
public uint spell; // 14 spell, References: Spell, NoValue = 0
public uint GiganticAOI; // 15 Gigantic AOI, enum { false, true, }; Default: false
@@ -1041,12 +1062,44 @@ namespace Game.Entities
public uint MaxNumberofLoots; // 18 Max Number of Loots, int, Min value: 1, Max value: 40, Default value: 10
public uint logloot; // 19 log loot, enum { false, true, }; Default: false
public uint linkedTrap; // 20 linkedTrap, References: GameObjects, NoValue = 0
public uint PlayOpenAnimationonOpening; // 21 Play Open Animation on Opening, enum { false, true, }; Default: false
}
public struct challengemodereward
{
public uint chestLoot; // 0 chestLoot, References: Treasure, NoValue = 0
public uint WhenAvailable; // 1 When Available, References: GameObjectDisplayInfo, NoValue = 0
public uint open; // 2 open, References: Lock_, NoValue = 0
public uint openTextID; // 3 openTextID, References: BroadcastText, NoValue = 0
}
public struct multi
{
public uint MultiProperties; // 0 Multi Properties, References: MultiProperties, NoValue = 0
}
public struct siegeableMulti
{
public uint MultiProperties; // 0 Multi Properties, References: MultiProperties, NoValue = 0
public uint InitialDamage; // 1 Initial Damage, enum { None, Raw, Ratio, }; Default: None
}
public struct siegeableMO
{
public uint SiegeableProperties; // 0 Siegeable Properties, References: SiegeableProperties, NoValue = 0
public uint DoodadSetA; // 1 Doodad Set A, int, Min value: 0, Max value: 2147483647, Default value: 0
public uint DoodadSetB; // 2 Doodad Set B, int, Min value: 0, Max value: 2147483647, Default value: 0
public uint DoodadSetC; // 3 Doodad Set C, int, Min value: 0, Max value: 2147483647, Default value: 0
public int SpawnMap; // 4 Spawn Map, References: Map, NoValue = -1
public int AreaNameSet; // 5 Area Name Set (Index), int, Min value: -2147483648, Max value: 2147483647, Default value: 0
}
public struct pvpReward
{
public uint chestLoot; // 0 chestLoot, References: Treasure, NoValue = 0
public uint WhenAvailable; // 1 When Available, References: GameObjectDisplayInfo, NoValue = 0
public uint open; // 2 open, References: Lock_, NoValue = 0
public uint openTextID; // 3 openTextID, References: BroadcastText, NoValue = 0
}
#endregion
}
+16 -83
View File
@@ -39,7 +39,6 @@ namespace Game.Entities
objectTypeMask |= TypeMask.Item;
objectTypeId = TypeId.Item;
m_updateFlag = UpdateFlag.None;
valuesCount = (int)ItemFields.End;
_dynamicValuesCount = (int)ItemDynamicFields.End;
uState = ItemUpdateState.New;
@@ -75,17 +74,6 @@ namespace Game.Entities
{
if (i < 5)
SetSpellCharges(i, itemProto.Effects[i].Charges);
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo((uint)itemProto.Effects[i].SpellID);
if (spellInfo != null)
{
if (spellInfo.HasEffect(SpellEffectName.GiveArtifactPower))
{
uint artifactKnowledgeLevel = WorldConfig.GetUIntValue(WorldCfg.CurrencyStartArtifactKnowledge);
if (artifactKnowledgeLevel != 0)
SetModifier(ItemModifier.ArtifactKnowledgeLevel, artifactKnowledgeLevel + 1);
}
}
}
SetUInt32Value(ItemFields.Duration, itemProto.GetDuration());
@@ -1484,7 +1472,7 @@ namespace Game.Entities
Player owner = GetOwner();
for (byte i = 0; i < ItemConst.MaxStats; ++i)
{
if ((owner ? GetItemStatValue(i, owner) : proto.GetItemStatValue(i)) != 0)
if ((owner ? GetItemStatValue(i, owner) : proto.GetItemStatAllocation(i)) != 0)
return true;
}
@@ -1498,7 +1486,7 @@ namespace Game.Entities
for (byte i = 0; i < ItemConst.MaxStats; ++i)
{
if (bonus.ItemStatValue[i] != 0)
if (bonus.ItemStatAllocation[i] != 0)
return true;
}
@@ -1781,55 +1769,6 @@ namespace Game.Entities
return proto.GetSellPrice();
}
public int GetReforgableStat(ItemModType statType)
{
ItemTemplate proto = GetTemplate();
for (uint i = 0; i < ItemConst.MaxStats; ++i)
if ((ItemModType)proto.GetItemStatType(i) == statType)
return proto.GetItemStatValue(i);
int randomPropId = GetItemRandomPropertyId();
if (randomPropId == 0)
return 0;
if (randomPropId < 0)
{
ItemRandomSuffixRecord randomSuffix = CliDB.ItemRandomSuffixStorage.LookupByKey(-randomPropId);
if (randomSuffix == null)
return 0;
for (var e = EnchantmentSlot.Prop0; e <= EnchantmentSlot.Prop4; ++e)
{
var enchant = CliDB.SpellItemEnchantmentStorage.LookupByKey(GetEnchantmentId(e));
if (enchant != null)
for (uint f = 0; f < ItemConst.MaxItemEnchantmentEffects; ++f)
if (enchant.Effect[f] == ItemEnchantmentType.Stat && (ItemModType)enchant.EffectArg[f] == statType)
for (int k = 0; k < 5; ++k)
if (randomSuffix.Enchantment[k] == enchant.Id)
return (int)((randomSuffix.AllocationPct[k] * GetItemSuffixFactor()) / 10000);
}
}
else
{
var randomProp = CliDB.ItemRandomPropertiesStorage.LookupByKey(randomPropId);
if (randomProp == null)
return 0;
for (var e = EnchantmentSlot.Prop0; e <= EnchantmentSlot.Prop4; ++e)
{
var enchant = CliDB.SpellItemEnchantmentStorage.LookupByKey(GetEnchantmentId(e));
if (enchant != null)
for (uint f = 0; f < ItemConst.MaxItemEnchantmentEffects; ++f)
if (enchant.Effect[f] == ItemEnchantmentType.Stat && (ItemModType)enchant.EffectArg[f] == statType)
for (int k = 0; k < ItemConst.MaxItemRandomProperties; ++k)
if (randomProp.Enchantment[k] == enchant.Id)
return (int)(enchant.EffectPointsMin[k]);
}
}
return 0;
}
public void ItemContainerSaveLootToDB()
{
// Saves the money and item loot associated with an openable item to the DB
@@ -2038,12 +1977,12 @@ namespace Game.Entities
if (fixedLevel != 0)
level = fixedLevel;
else
level = Math.Min(Math.Max(level, ssd.MinLevel), ssd.MaxLevel);
level = (uint)Math.Min(Math.Max(level, ssd.MinLevel), ssd.MaxLevel);
SandboxScalingRecord sandbox = CliDB.SandboxScalingStorage.LookupByKey(bonusData.SandboxScalingId);
if (sandbox != null)
if ((Convert.ToBoolean(sandbox.Flags & 2) || sandbox.MinLevel != 0 || sandbox.MaxLevel != 0) && !Convert.ToBoolean(sandbox.Flags & 4))
level = Math.Min(Math.Max(level, sandbox.MinLevel), sandbox.MaxLevel);
ContentTuningRecord contentTuning = CliDB.ContentTuningStorage.LookupByKey(bonusData.ContentTuningId);
if (contentTuning != null)
if ((Convert.ToBoolean(contentTuning.Flags & 2) || contentTuning.MinLevel != 0 || contentTuning.MaxLevel != 0) && !Convert.ToBoolean(contentTuning.Flags & 4))
level = (uint)Math.Min(Math.Max(level, contentTuning.MinLevel), contentTuning.MaxLevel);
uint heirloomIlvl = (uint)Global.DB2Mgr.GetCurveValueAt(ssd.PlayerLevelToItemLevelCurveID, level);
if (heirloomIlvl != 0)
@@ -2090,7 +2029,7 @@ namespace Game.Entities
return (int)(Math.Floor(statValue + 0.5f));
}
return _bonusData.ItemStatValue[index];
return 0;
}
public ItemDisenchantLootRecord GetDisenchantLoot(Player owner)
@@ -2114,7 +2053,7 @@ namespace Game.Entities
byte expansion = itemTemplate.GetRequiredExpansion();
foreach (ItemDisenchantLootRecord disenchant in CliDB.ItemDisenchantLootStorage.Values)
{
if (disenchant.ClassID != itemClass)
if (disenchant.Class != itemClass)
continue;
if (disenchant.Subclass >= 0 && itemSubClass != 0)
@@ -2404,8 +2343,6 @@ namespace Game.Entities
uint artifactKnowledgeLevel = 1;
if (sourceItem != null && sourceItem.GetModifier(ItemModifier.ArtifactKnowledgeLevel) != 0)
artifactKnowledgeLevel = sourceItem.GetModifier(ItemModifier.ArtifactKnowledgeLevel);
else if (artifactCategoryId == ArtifactCategory.Primary)
artifactKnowledgeLevel = WorldConfig.GetUIntValue(WorldCfg.CurrencyStartArtifactKnowledge) + 1;
GtArtifactKnowledgeMultiplierRecord artifactKnowledge = CliDB.ArtifactKnowledgeMultiplierGameTable.GetRow(artifactKnowledgeLevel);
if (artifactKnowledge != null)
@@ -2437,12 +2374,12 @@ namespace Game.Entities
ScalingStatDistributionRecord ssd = CliDB.ScalingStatDistributionStorage.LookupByKey(_bonusData.ScalingStatDistribution);
if (ssd != null)
{
level = Math.Min(Math.Max(level, ssd.MinLevel), ssd.MaxLevel);
level = (uint)Math.Min(Math.Max(level, ssd.MinLevel), ssd.MaxLevel);
SandboxScalingRecord sandbox = CliDB.SandboxScalingStorage.LookupByKey(_bonusData.SandboxScalingId);
if (sandbox != null)
if ((sandbox.Flags.HasAnyFlag(2u) || sandbox.MinLevel != 0 || sandbox.MaxLevel != 0) && !sandbox.Flags.HasAnyFlag(4u))
level = Math.Min(Math.Max(level, sandbox.MinLevel), sandbox.MaxLevel);
ContentTuningRecord contentTuning = CliDB.ContentTuningStorage.LookupByKey(_bonusData.ContentTuningId);
if (contentTuning != null)
if ((contentTuning.Flags.HasAnyFlag(2) || contentTuning.MinLevel != 0 || contentTuning.MaxLevel != 0) && !contentTuning.Flags.HasAnyFlag(4))
level = (uint)Math.Min(Math.Max(level, contentTuning.MinLevel), contentTuning.MaxLevel);
SetModifier(ItemModifier.ScalingStatDistributionFixedLevel, level);
}
@@ -2838,9 +2775,6 @@ namespace Game.Entities
for (uint i = 0; i < ItemConst.MaxStats; ++i)
ItemStatType[i] = proto.GetItemStatType(i);
for (uint i = 0; i < ItemConst.MaxStats; ++i)
ItemStatValue[i] = proto.GetItemStatValue(i);
for (uint i = 0; i < ItemConst.MaxStats; ++i)
ItemStatAllocation[i] = proto.GetItemStatAllocation(i);
@@ -2948,7 +2882,7 @@ namespace Game.Entities
if (values[1] < _state.ScalingStatDistributionPriority)
{
ScalingStatDistribution = (uint)values[0];
SandboxScalingId = (uint)values[2];
ContentTuningId = (uint)values[2];
_state.ScalingStatDistributionPriority = values[1];
HasFixedLevel = type == ItemBonusType.ScalingStatDistributionFixed;
}
@@ -2969,7 +2903,6 @@ namespace Game.Entities
public int ItemLevelBonus;
public int RequiredLevel;
public int[] ItemStatType = new int[ItemConst.MaxStats];
public int[] ItemStatValue = new int[ItemConst.MaxStats];
public int[] ItemStatAllocation = new int[ItemConst.MaxStats];
public float[] ItemStatSocketCostMultiplier = new float[ItemConst.MaxStats];
public SocketColor[] socketColor = new SocketColor[ItemConst.MaxGemSockets];
@@ -2977,7 +2910,7 @@ namespace Game.Entities
public uint AppearanceModID;
public float RepairCostMultiplier;
public uint ScalingStatDistribution;
public uint SandboxScalingId;
public uint ContentTuningId;
public uint DisenchantLootId;
public uint[] GemItemLevelBonus = new uint[ItemConst.MaxGemSockets];
public int[] GemRelicType = new int[ItemConst.MaxGemSockets];
+1 -6
View File
@@ -223,7 +223,7 @@ namespace Game.Entities
if (GetFlags().HasAnyFlag(ItemFlags.IsBoundToAccount) && alwaysAllowBoundToAccount)
return true;
uint spec = player.GetUInt32Value(PlayerFields.LootSpecId);
uint spec = player.GetUInt32Value(ActivePlayerFields.LootSpecId);
if (spec == 0)
spec = player.GetUInt32Value(PlayerFields.CurrentSpecId);
if (spec == 0)
@@ -277,11 +277,6 @@ namespace Game.Entities
Cypher.Assert(index < ItemConst.MaxStats);
return ExtendedData.StatModifierBonusStat[index];
}
public int GetItemStatValue(uint index)
{
Cypher.Assert(index < ItemConst.MaxStats);
return ExtendedData.ItemStatValue[index];
}
public int GetItemStatAllocation(uint index)
{
Cypher.Assert(index < ItemConst.MaxStats);
+153 -78
View File
@@ -52,7 +52,7 @@ namespace Game.Entities
_fieldNotifyFlags = UpdateFieldFlags.Dynamic;
m_movementInfo = new MovementInfo();
m_updateFlag = UpdateFlag.None;
m_updateFlag.Clear();
}
public virtual void Dispose()
@@ -110,7 +110,6 @@ namespace Game.Entities
InitValues();
SetGuidValue(ObjectFields.Guid, guid);
SetUInt16Value(ObjectFields.Type, 0, (ushort)objectTypeMask);
}
public string _ConcatFields(object startIndex, uint size)
@@ -148,10 +147,17 @@ namespace Game.Entities
return;
UpdateType updateType = UpdateType.CreateObject;
UpdateFlag flags = m_updateFlag;
TypeId tempObjectType = objectTypeId;
TypeMask tempObjectTypeMask = objectTypeMask;
CreateObjectBits flags = m_updateFlag;
if (target == this)
flags |= UpdateFlag.Self;
{
flags.ThisIsYou = true;
flags.ActivePlayer = true;
tempObjectType = TypeId.Player;
tempObjectTypeMask |= TypeMask.Player;
}
switch (GetGUID().GetHigh())
{
@@ -176,16 +182,13 @@ namespace Game.Entities
break;
}
if (!flags.HasAnyFlag(UpdateFlag.Living))
{
if (!m_movementInfo.transport.guid.IsEmpty())
flags |= UpdateFlag.TransportPosition;
if (!flags.MovementUpdate && !m_movementInfo.transport.guid.IsEmpty())
flags.MovementTransport = true;
if (GetAIAnimKitId() != 0 || GetMovementAnimKitId() != 0 || GetMeleeAnimKitId() != 0)
flags |= UpdateFlag.AnimKits;
}
if (GetAIAnimKitId() != 0 || GetMovementAnimKitId() != 0 || GetMeleeAnimKitId() != 0)
flags.AnimKit = true;
if (flags.HasAnyFlag(UpdateFlag.StationaryPosition))
if (flags.Stationary)
{
// UPDATETYPE_CREATE_OBJECT2 for some gameobject types...
if (isTypeMask(TypeMask.GameObject))
@@ -206,12 +209,13 @@ namespace Game.Entities
Unit unit = ToUnit();
if (unit)
if (unit.GetVictim())
flags |= UpdateFlag.HasTarget;
flags.CombatVictim = true;
WorldPacket buffer = new WorldPacket();
buffer.WriteUInt8(updateType);
buffer.WritePackedGuid(GetGUID());
buffer.WriteUInt8(objectTypeId);
buffer.WriteUInt8(tempObjectType);
buffer.WriteUInt32(tempObjectTypeMask);
BuildMovementUpdate(buffer, flags);
BuildValuesUpdate(updateType, buffer, target);
@@ -305,25 +309,8 @@ namespace Game.Entities
return new ObjectGuid(GetUInt64Value((int)index + 2), GetUInt64Value(index));
}
public void BuildMovementUpdate(WorldPacket data, UpdateFlag flags)
public void BuildMovementUpdate(WorldPacket data, CreateObjectBits flags)
{
bool NoBirthAnim = false;
bool EnablePortals = false;
bool PlayHoverAnim = false;
bool HasMovementUpdate = flags.HasAnyFlag(UpdateFlag.Living);
bool HasMovementTransport = flags.HasAnyFlag(UpdateFlag.TransportPosition);
bool Stationary = flags.HasAnyFlag(UpdateFlag.StationaryPosition);
bool CombatVictim = flags.HasAnyFlag(UpdateFlag.HasTarget);
bool ServerTime = flags.HasAnyFlag(UpdateFlag.Transport);
bool VehicleCreate = flags.HasAnyFlag(UpdateFlag.Vehicle);
bool AnimKitCreate = flags.HasAnyFlag(UpdateFlag.AnimKits);
bool Rotation = flags.HasAnyFlag(UpdateFlag.Rotation);
bool HasAreaTrigger = flags.HasAnyFlag(UpdateFlag.Areatrigger);
bool HasGameObject = flags.HasAnyFlag(UpdateFlag.Gameobject);
bool ThisIsYou = flags.HasAnyFlag(UpdateFlag.Self);
bool SmoothPhasing = false;
bool SceneObjCreate = false;
bool PlayerCreateData = GetTypeId() == TypeId.Player && ToUnit().GetPowerIndex(PowerType.Runes) != (int)PowerType.Max;
int PauseTimesCount = 0;
GameObject go = ToGameObject();
@@ -333,26 +320,27 @@ namespace Game.Entities
PauseTimesCount = go.m_goValue.Transport.StopFrames.Count;
}
data.WriteBit(NoBirthAnim);
data.WriteBit(EnablePortals);
data.WriteBit(PlayHoverAnim);
data.WriteBit(HasMovementUpdate);
data.WriteBit(HasMovementTransport);
data.WriteBit(Stationary);
data.WriteBit(CombatVictim);
data.WriteBit(ServerTime);
data.WriteBit(VehicleCreate);
data.WriteBit(AnimKitCreate);
data.WriteBit(Rotation);
data.WriteBit(HasAreaTrigger);
data.WriteBit(HasGameObject);
data.WriteBit(SmoothPhasing);
data.WriteBit(ThisIsYou);
data.WriteBit(SceneObjCreate);
data.WriteBit(PlayerCreateData);
data.WriteBit(flags.NoBirthAnim);
data.WriteBit(flags.EnablePortals);
data.WriteBit(flags.PlayHoverAnim);
data.WriteBit(flags.MovementUpdate);
data.WriteBit(flags.MovementTransport);
data.WriteBit(flags.Stationary);
data.WriteBit(flags.CombatVictim);
data.WriteBit(flags.ServerTime);
data.WriteBit(flags.Vehicle);
data.WriteBit(flags.AnimKit);
data.WriteBit(flags.Rotation);
data.WriteBit(flags.AreaTrigger);
data.WriteBit(flags.GameObject);
data.WriteBit(flags.SmoothPhasing);
data.WriteBit(flags.ThisIsYou);
data.WriteBit(flags.SceneObject);
data.WriteBit(flags.ActivePlayer);
data.WriteBit(flags.Conversation);
data.FlushBits();
if (HasMovementUpdate)
if (flags.MovementUpdate)
{
Unit unit = ToUnit();
bool HasFallDirection = unit.HasUnitMovementFlag(MovementFlag.Falling);
@@ -432,7 +420,7 @@ namespace Game.Entities
data.WriteUInt32(PauseTimesCount);
if (Stationary)
if (flags.Stationary)
{
WorldObject self = this;
data.WriteFloat(self.GetStationaryX());
@@ -441,10 +429,10 @@ namespace Game.Entities
data.WriteFloat(self.GetStationaryO());
}
if (CombatVictim)
if (flags.CombatVictim)
data.WritePackedGuid(ToUnit().GetVictim().GetGUID()); // CombatVictim
if (ServerTime)
if (flags.ServerTime)
{
GameObject go1 = ToGameObject();
/** @TODO Use IsTransport() to also handle type 11 (TRANSPORT)
@@ -458,21 +446,21 @@ namespace Game.Entities
data.WriteUInt32(Time.GetMSTime());
}
if (VehicleCreate)
if (flags.Vehicle)
{
Unit unit = ToUnit();
data.WriteUInt32(unit.GetVehicleKit().GetVehicleInfo().Id); // RecID
data.WriteFloat(unit.GetOrientation()); // InitialRawFacing
}
if (AnimKitCreate)
if (flags.AnimKit)
{
data.WriteUInt16(GetAIAnimKitId()); // AiID
data.WriteUInt16(GetMovementAnimKitId()); // MovementID
data.WriteUInt16(GetMeleeAnimKitId()); // MeleeID
}
if (Rotation)
if (flags.Rotation)
data.WriteInt64(ToGameObject().GetPackedWorldRotation()); // Rotation
if (go)
@@ -481,13 +469,13 @@ namespace Game.Entities
data.WriteUInt32(go.m_goValue.Transport.StopFrames[i]);
}
if (HasMovementTransport)
if (flags.MovementTransport)
{
WorldObject self = this;
MovementExtensions.WriteTransportInfo(data, self.m_movementInfo.transport);
}
if (HasAreaTrigger)
if (flags.AreaTrigger)
{
AreaTrigger areaTrigger = ToAreaTrigger();
AreaTriggerMiscTemplate areaTriggerMiscTemplate = areaTrigger.GetMiscTemplate();
@@ -508,9 +496,10 @@ namespace Game.Entities
bool hasMorphCurveID = areaTriggerMiscTemplate.MorphCurveId != 0;
bool hasFacingCurveID = areaTriggerMiscTemplate.FacingCurveId != 0;
bool hasMoveCurveID = areaTriggerMiscTemplate.MoveCurveId != 0;
bool hasUnk2 = areaTriggerTemplate.HasFlag(AreaTriggerFlags.Unk2);
bool hasAnimation = areaTriggerTemplate.HasFlag(AreaTriggerFlags.HasAnimID);
bool hasUnk3 = areaTriggerTemplate.HasFlag(AreaTriggerFlags.Unk3);
bool hasUnk4 = areaTriggerTemplate.HasFlag(AreaTriggerFlags.Unk4);
bool hasAnimKitID = areaTriggerTemplate.HasFlag(AreaTriggerFlags.HasAnimKitID);
bool hasAnimProgress = false;
bool hasAreaTriggerSphere = areaTriggerTemplate.IsSphere();
bool hasAreaTriggerBox = areaTriggerTemplate.IsBox();
bool hasAreaTriggerPolygon = areaTriggerTemplate.IsPolygon();
@@ -529,9 +518,10 @@ namespace Game.Entities
data.WriteBit(hasMorphCurveID);
data.WriteBit(hasFacingCurveID);
data.WriteBit(hasMoveCurveID);
data.WriteBit(hasUnk2);
data.WriteBit(hasAnimation);
data.WriteBit(hasAnimKitID);
data.WriteBit(hasUnk3);
data.WriteBit(hasUnk4);
data.WriteBit(hasAnimProgress);
data.WriteBit(hasAreaTriggerSphere);
data.WriteBit(hasAreaTriggerBox);
data.WriteBit(hasAreaTriggerPolygon);
@@ -567,10 +557,13 @@ namespace Game.Entities
if (hasMoveCurveID)
data.WriteUInt32(areaTriggerMiscTemplate.MoveCurveId);
if (hasUnk2)
data.WriteInt32(0);
if (hasAnimation)
data.WriteInt32(areaTriggerMiscTemplate.AnimId);
if (hasUnk4)
if (hasAnimKitID)
data.WriteUInt32(areaTriggerMiscTemplate.AnimKitId);
if (hasAnimProgress)
data.WriteUInt32(0);
if (hasAreaTriggerSphere)
@@ -627,7 +620,7 @@ namespace Game.Entities
areaTrigger.GetCircularMovementInfo().Value.Write(data);
}
if (HasGameObject)
if (flags.GameObject)
{
bool bit8 = false;
uint Int1 = 0;
@@ -642,7 +635,7 @@ namespace Game.Entities
data.WriteUInt32(Int1);
}
//if (SmoothPhasing)
//if (flags.SmoothPhasing)
//{
// data.WriteBit(ReplaceActive);
// data.WriteBit(HasReplaceObjectt);
@@ -651,7 +644,7 @@ namespace Game.Entities
// *data << ObjectGuid(ReplaceObject);
//}
//if (SceneObjCreate)
//if (flags.SceneObject)
//{
// data.WriteBit(HasLocalScriptData);
// data.WriteBit(HasPetBattleFullUpdate);
@@ -761,7 +754,7 @@ namespace Game.Entities
// }
//}
if (PlayerCreateData)
if (flags.ActivePlayer)
{
bool HasSceneInstanceIDs = false;
bool HasRuneState = ToUnit().GetPowerIndex(PowerType.Runes) != (int)PowerType.Max;
@@ -788,6 +781,14 @@ namespace Game.Entities
data.WriteUInt8((baseCd - (float)player.GetRuneCooldown(i)) / baseCd * 255);
}
}
if (flags.Conversation)
{
Conversation self = ToConversation();
if (data.WriteBit(self.GetTextureKitId() != 0))
data.WriteUInt32(self.GetTextureKitId());
data.FlushBits();
}
}
public virtual void BuildValuesUpdate(UpdateType updatetype, ByteBuffer data, Player target)
@@ -819,13 +820,17 @@ namespace Game.Entities
if (!target)
return;
uint valueCount = _dynamicValuesCount;
if (target != this && GetTypeId() == TypeId.Player)
valueCount = (uint)PlayerDynamicFields.End;
ByteBuffer fieldBuffer = new ByteBuffer();
UpdateMask fieldMask = new UpdateMask(_dynamicValuesCount);
UpdateMask fieldMask = new UpdateMask(valueCount);
uint[] flags;
uint visibleFlag = GetDynamicUpdateFieldData(target, out flags);
for (var index = 0; index < _dynamicValuesCount; ++index)
for (var index = 0; index < valueCount; ++index)
{
ByteBuffer valueBuffer = new ByteBuffer();
var values = _dynamicValues[index];
@@ -909,7 +914,17 @@ namespace Game.Entities
{
case TypeId.Item:
case TypeId.Container:
flags = UpdateFieldFlags.ItemUpdateFieldFlags;
flags = UpdateFieldFlags.ContainerUpdateFieldFlags;
if (((Item)this).GetOwnerGUID() == target.GetGUID())
visibleFlag |= UpdateFieldFlags.Owner | UpdateFieldFlags.ItemOwner;
break;
case TypeId.AzeriteEmpoweredItem:
flags = UpdateFieldFlags.AzeriteEmpoweredItemUpdateFieldFlags;
if (((Item)this).GetOwnerGUID() == target.GetGUID())
visibleFlag |= UpdateFieldFlags.Owner | UpdateFieldFlags.ItemOwner;
break;
case TypeId.AzeriteItem:
flags = UpdateFieldFlags.AzeriteItemUpdateFieldFlags;
if (((Item)this).GetOwnerGUID() == target.GetGUID())
visibleFlag |= UpdateFieldFlags.Owner | UpdateFieldFlags.ItemOwner;
break;
@@ -954,6 +969,7 @@ namespace Game.Entities
flags = UpdateFieldFlags.ConversationUpdateFieldFlags;
break;
case TypeId.Object:
case TypeId.ActivePlayer:
Cypher.Assert(false);
break;
}
@@ -971,6 +987,8 @@ namespace Game.Entities
{
case TypeId.Item:
case TypeId.Container:
case TypeId.AzeriteEmpoweredItem:
case TypeId.AzeriteItem:
flags = UpdateFieldFlags.ItemDynamicUpdateFieldFlags;
if (((Item)this).GetOwnerGUID() == target.GetGUID())
visibleFlag |= UpdateFieldFlags.Owner | UpdateFieldFlags.ItemOwner;
@@ -1660,6 +1678,16 @@ namespace Game.Entities
corpseVisibility = true;
}
}
Unit target = obj.ToUnit();
if (target)
{
// Don't allow to detect vehicle accessories if you can't see vehicle
Unit vehicle = target.GetVehicleBase();
if (vehicle)
if (!thisPlayer.HaveAtClient(vehicle))
return false;
}
}
WorldObject viewpoint = this;
@@ -1802,7 +1830,7 @@ namespace Game.Entities
if (!HasInArc(MathFunctions.PI, obj))
return false;
GameObject go = ToGameObject();
GameObject go = obj.ToGameObject();
for (int i = 0; i < (int)StealthType.Max; ++i)
{
if (!Convert.ToBoolean(obj.m_stealth.GetFlags() & (1 << i)))
@@ -1896,6 +1924,9 @@ namespace Game.Entities
public virtual void ResetMap()
{
if (_currMap == null)
return;
Cypher.Assert(_currMap != null);
Cypher.Assert(!IsInWorld);
if (IsWorldObject())
@@ -2337,7 +2368,7 @@ namespace Game.Entities
return distsq < maxdist * maxdist;
}
public bool IsWithinLOSInMap(WorldObject obj)
public bool IsWithinLOSInMap(WorldObject obj, ModelIgnoreFlags ignoreFlags = ModelIgnoreFlags.Nothing)
{
if (!IsInMap(obj))
return false;
@@ -2348,7 +2379,7 @@ namespace Game.Entities
else
obj.GetHitSpherePointFor(GetPosition(), out x, out y, out z);
return IsWithinLOS(x, y, z);
return IsWithinLOS(x, y, z, ignoreFlags);
}
public float GetDistance(WorldObject obj)
@@ -2426,7 +2457,7 @@ namespace Game.Entities
return obj && IsInMap(obj) && IsInPhase(obj) && _IsWithinDist(obj, dist2compare, is3D);
}
public bool IsWithinLOS(float ox, float oy, float oz)
public bool IsWithinLOS(float ox, float oy, float oz, ModelIgnoreFlags ignoreFlags = ModelIgnoreFlags.Nothing)
{
if (IsInWorld)
{
@@ -2436,7 +2467,7 @@ namespace Game.Entities
else
GetHitSpherePointFor(new Position(ox, oy, oz), out x, out y, out z);
return GetMap().isInLineOfSight(GetPhaseShift(), x, y, z + 2.0f, ox, oy, oz + 2.0f);
return GetMap().isInLineOfSight(GetPhaseShift(), x, y, z + 2.0f, ox, oy, oz + 2.0f, ignoreFlags);
}
return true;
@@ -2853,7 +2884,7 @@ namespace Game.Entities
#region Fields
public TypeMask objectTypeMask { get; set; }
protected TypeId objectTypeId { get; set; }
protected UpdateFlag m_updateFlag { get; set; }
protected CreateObjectBits m_updateFlag;
protected UpdateValues[] updateValues;
protected uint[][] _dynamicValues;
@@ -2997,4 +3028,48 @@ namespace Game.Entities
public float xyspeed;
}
}
public struct CreateObjectBits
{
public bool NoBirthAnim;
public bool EnablePortals;
public bool PlayHoverAnim;
public bool MovementUpdate;
public bool MovementTransport;
public bool Stationary;
public bool CombatVictim;
public bool ServerTime;
public bool Vehicle;
public bool AnimKit;
public bool Rotation;
public bool AreaTrigger;
public bool GameObject;
public bool SmoothPhasing;
public bool ThisIsYou;
public bool SceneObject;
public bool ActivePlayer;
public bool Conversation;
public void Clear()
{
NoBirthAnim = false;
EnablePortals = false;
PlayHoverAnim = false;
MovementUpdate = false;
MovementTransport = false;
Stationary = false;
CombatVictim = false;
ServerTime = false;
Vehicle = false;
AnimKit = false;
Rotation = false;
AreaTrigger = false;
GameObject = false;
SmoothPhasing = false;
ThisIsYou = false;
SceneObject = false;
ActivePlayer = false;
Conversation = false;
}
}
}
+2 -2
View File
@@ -1461,9 +1461,9 @@ namespace Game.Entities
return base.GetOwner().ToPlayer();
}
public override void SetDisplayId(uint modelId)
public override void SetDisplayId(uint modelId, float displayScale = 1f)
{
base.SetDisplayId(modelId);
base.SetDisplayId(modelId, displayScale);
if (!isControlled())
return;
@@ -70,14 +70,14 @@ namespace Game.Entities
public void LoadToys()
{
foreach (var value in _toys.Keys)
_owner.GetPlayer().AddDynamicValue(PlayerDynamicFields.Toys, value);
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.Toys, value);
}
public bool AddToy(uint itemId, bool isFavourite = false)
{
if (UpdateAccountToys(itemId, isFavourite))
{
_owner.GetPlayer().AddDynamicValue(PlayerDynamicFields.Toys, itemId);
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.Toys, itemId);
return true;
}
@@ -198,8 +198,8 @@ namespace Game.Entities
{
foreach (var item in _heirlooms)
{
_owner.GetPlayer().AddDynamicValue(PlayerDynamicFields.Heirlooms, item.Key);
_owner.GetPlayer().AddDynamicValue(PlayerDynamicFields.HeirloomsFlags, (uint)item.Value.flags);
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.Heirlooms, item.Key);
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.HeirloomFlags, (uint)item.Value.flags);
}
}
@@ -207,8 +207,8 @@ namespace Game.Entities
{
if (UpdateAccountHeirlooms(itemId, flags))
{
_owner.GetPlayer().AddDynamicValue(PlayerDynamicFields.Heirlooms, itemId);
_owner.GetPlayer().AddDynamicValue(PlayerDynamicFields.HeirloomsFlags, (uint)flags);
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.Heirlooms, itemId);
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.HeirloomFlags, (uint)flags);
}
}
@@ -249,10 +249,10 @@ namespace Game.Entities
item.AddBonuses(bonusId);
// Get heirloom offset to update only one part of dynamic field
var fields = player.GetDynamicValues(PlayerDynamicFields.Heirlooms);
var fields = player.GetDynamicValues(ActivePlayerDynamicFields.Heirlooms);
ushort offset = (ushort)Array.IndexOf(fields, itemId);
player.SetDynamicValue(PlayerDynamicFields.HeirloomsFlags, offset, (uint)flags);
player.SetDynamicValue(ActivePlayerDynamicFields.HeirloomFlags, offset, (uint)flags);
data.flags = flags;
data.bonusId = bonusId;
}
@@ -292,11 +292,11 @@ namespace Game.Entities
if (newItemId != 0)
{
var heirloomFields = player.GetDynamicValues(PlayerDynamicFields.Heirlooms);
var heirloomFields = player.GetDynamicValues(ActivePlayerDynamicFields.Heirlooms);
ushort offset = (ushort)Array.IndexOf(heirloomFields, item.GetEntry());
player.SetDynamicValue(PlayerDynamicFields.Heirlooms, offset, newItemId);
player.SetDynamicValue(PlayerDynamicFields.HeirloomsFlags, offset, 0);
player.SetDynamicValue(ActivePlayerDynamicFields.Heirlooms, offset, newItemId);
player.SetDynamicValue(ActivePlayerDynamicFields.HeirloomFlags, offset, 0);
_heirlooms.Remove(item.GetEntry());
_heirlooms[newItemId] = null;
@@ -432,11 +432,11 @@ namespace Game.Entities
{
foreach (uint blockValue in _appearances.ToBlockRange())
{
_owner.GetPlayer().AddDynamicValue(PlayerDynamicFields.Transmog, blockValue);
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.Transmog, blockValue);
}
foreach (var value in _temporaryAppearances.Keys)
_owner.GetPlayer().AddDynamicValue(PlayerDynamicFields.ConditionalTransmog, value);
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.ConditionalTransmog, value);
}
public void LoadAccountItemAppearances(SQLResult knownAppearances, SQLResult favoriteAppearances)
@@ -661,18 +661,18 @@ namespace Game.Entities
_appearances.Length = (int)itemModifiedAppearance.Id + 1;
numBlocks = (uint)(_appearances.Count << 2) - numBlocks;
while (numBlocks-- != 0)
_owner.GetPlayer().AddDynamicValue(PlayerDynamicFields.Transmog, 0);
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.Transmog, 0);
}
_appearances.Set((int)itemModifiedAppearance.Id, true);
uint blockIndex = itemModifiedAppearance.Id / 32;
uint bitIndex = itemModifiedAppearance.Id % 32;
uint currentMask = _owner.GetPlayer().GetDynamicValue(PlayerDynamicFields.Transmog, (ushort)blockIndex);
_owner.GetPlayer().SetDynamicValue(PlayerDynamicFields.Transmog, (ushort)blockIndex, (uint)((int)currentMask | (1 << (int)bitIndex)));
uint currentMask = _owner.GetPlayer().GetDynamicValue(ActivePlayerDynamicFields.Transmog, (ushort)blockIndex);
_owner.GetPlayer().SetDynamicValue(ActivePlayerDynamicFields.Transmog, (ushort)blockIndex, (uint)((int)currentMask | (1 << (int)bitIndex)));
var temporaryAppearance = _temporaryAppearances.LookupByKey(itemModifiedAppearance.Id);
if (!temporaryAppearance.Empty())
{
_owner.GetPlayer().RemoveDynamicValue(PlayerDynamicFields.ConditionalTransmog, itemModifiedAppearance.Id);
_owner.GetPlayer().RemoveDynamicValue(ActivePlayerDynamicFields.ConditionalTransmog, itemModifiedAppearance.Id);
_temporaryAppearances.Remove(itemModifiedAppearance.Id);
}
@@ -694,7 +694,7 @@ namespace Game.Entities
{
var itemsWithAppearance = _temporaryAppearances[itemModifiedAppearance.Id];
if (itemsWithAppearance.Empty())
_owner.GetPlayer().AddDynamicValue(PlayerDynamicFields.ConditionalTransmog, itemModifiedAppearance.Id);
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.ConditionalTransmog, itemModifiedAppearance.Id);
itemsWithAppearance.Add(itemGuid);
}
@@ -712,7 +712,7 @@ namespace Game.Entities
guid.Remove(item.GetGUID());
if (guid.Empty())
{
_owner.GetPlayer().RemoveDynamicValue(PlayerDynamicFields.ConditionalTransmog, itemModifiedAppearance.Id);
_owner.GetPlayer().RemoveDynamicValue(ActivePlayerDynamicFields.ConditionalTransmog, itemModifiedAppearance.Id);
_temporaryAppearances.Remove(itemModifiedAppearance.Id);
}
}
+3 -3
View File
@@ -118,7 +118,7 @@ namespace Game.Entities
}
public float GetRatingBonusValue(CombatRating cr)
{
float baseResult = GetFloatValue(PlayerFields.CombatRating1 + (int)cr) * GetRatingMultiplier(cr);
float baseResult = GetFloatValue(ActivePlayerFields.CombatRating + (int)cr) * GetRatingMultiplier(cr);
if (cr != CombatRating.ResiliencePlayerDamage)
return baseResult;
return (float)(1.0f - Math.Pow(0.99f, baseResult)) * 100.0f;
@@ -189,9 +189,9 @@ namespace Game.Entities
switch (attType)
{
case WeaponAttackType.BaseAttack:
return baseExpertise + GetUInt32Value(PlayerFields.Expertise) / 4.0f;
return baseExpertise + GetUInt32Value(ActivePlayerFields.Expertise) / 4.0f;
case WeaponAttackType.OffAttack:
return baseExpertise + GetUInt32Value(PlayerFields.OffhandExpertise) / 4.0f;
return baseExpertise + GetUInt32Value(ActivePlayerFields.OffhandExpertise) / 4.0f;
default:
break;
}
+83 -84
View File
@@ -348,7 +348,6 @@ namespace Game.Entities
}
void _LoadSkills(SQLResult result)
{
var professionCount = 0;
var count = 0;
Dictionary<uint, uint> loadedSkillValues = new Dictionary<uint, uint>();
if (!result.IsEmpty())
@@ -396,7 +395,7 @@ namespace Game.Entities
var field = (ushort)(count / 2);
var offset = (byte)(count & 1);
SetUInt16Value(PlayerFields.SkillLineId + field, offset, skill);
SetUInt16Value(ActivePlayerFields.SkillLineId + field, offset, skill);
ushort step = 0;
SkillLineRecord skillLine = CliDB.SkillLineStorage.LookupByKey(rcEntry.SkillID);
@@ -409,16 +408,20 @@ namespace Game.Entities
{
step = (ushort)(max / 75);
if (professionCount < 2)
SetUInt32Value(PlayerFields.ProfessionSkillLine1 + professionCount++, skill);
if (skillLine.ParentSkillLineID != 0 && skillLine.ParentTierIndex != 0)
{
int professionSlot = FindProfessionSlotFor(skill);
if (professionSlot != -1)
SetUInt32Value(ActivePlayerFields.ProfessionSkillLine + professionSlot, skill);
}
}
}
SetUInt16Value(PlayerFields.SkillLineStep + field, offset, step);
SetUInt16Value(PlayerFields.SkillLineRank + field, offset, value);
SetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset, max);
SetUInt16Value(PlayerFields.SkillLineTempBonus + field, offset, 0);
SetUInt16Value(PlayerFields.SkillLinePermBonus + field, offset, 0);
SetUInt16Value(ActivePlayerFields.SkillLineStep + field, offset, step);
SetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset, value);
SetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset, max);
SetUInt16Value(ActivePlayerFields.SkillLineTempBonus + field, offset, 0);
SetUInt16Value(ActivePlayerFields.SkillLinePermBonus + field, offset, 0);
mSkillStatus.Add(skill, new SkillStatusData((uint)count, SkillState.Unchanged));
@@ -445,12 +448,12 @@ namespace Game.Entities
var field = (ushort)(count / 2);
var offset = (byte)(count & 1);
SetUInt16Value(PlayerFields.SkillLineId + field, offset, 0);
SetUInt16Value(PlayerFields.SkillLineStep + field, offset, 0);
SetUInt16Value(PlayerFields.SkillLineRank + field, offset, 0);
SetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset, 0);
SetUInt16Value(PlayerFields.SkillLineTempBonus + field, offset, 0);
SetUInt16Value(PlayerFields.SkillLinePermBonus + field, offset, 0);
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);
}
}
void _LoadSpells(SQLResult result)
@@ -846,7 +849,7 @@ namespace Game.Entities
if (quest == null)
continue;
AddDynamicValue(PlayerDynamicFields.DailyQuests, quest_id);
AddDynamicValue(ActivePlayerDynamicFields.DailyQuests, quest_id);
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(quest_id);
if (questBit != 0)
SetQuestCompletedBit(questBit, true);
@@ -953,14 +956,17 @@ namespace Game.Entities
}
void _LoadPvpTalents(SQLResult result)
{
// "SELECT TalentID, TalentGroup FROM character_pvp_talent WHERE guid = ?"
// "SELECT talentID0, talentID1, talentID2, talentID3, talentGroup FROM character_pvp_talent WHERE guid = ?"
if (!result.IsEmpty())
{
do
{
PvpTalentRecord talent = CliDB.PvpTalentStorage.LookupByKey(result.Read<uint>(0));
if (talent != null)
AddPvpTalent(talent, result.Read<byte>(1), false);
for (byte slot = 0; slot < PlayerConst.MaxPvpTalentSlots; ++slot)
{
PvpTalentRecord talent = CliDB.PvpTalentStorage.LookupByKey(result.Read<uint>(slot));
if (talent != null)
AddPvpTalent(talent, result.Read<byte>(4), slot);
}
}
while (result.NextRow());
}
@@ -1000,7 +1006,7 @@ namespace Game.Entities
if (!result.IsEmpty() && !HasAtLoginFlag(AtLoginFlags.Resurrect))
{
_corpseLocation = new WorldLocation(result.Read<ushort>(0), result.Read<float>(1), result.Read<float>(2), result.Read<float>(3), result.Read<float>(4));
ApplyModFlag(PlayerFields.LocalFlags, PlayerLocalFlags.ReleaseTimer, !CliDB.MapStorage.LookupByKey(_corpseLocation.GetMapId()).Instanceable());
ApplyModFlag(ActivePlayerFields.LocalFlags, PlayerLocalFlags.ReleaseTimer, !CliDB.MapStorage.LookupByKey(_corpseLocation.GetMapId()).Instanceable());
}
else
ResurrectPlayer(0.5f);
@@ -1576,8 +1582,8 @@ namespace Game.Entities
var field = (ushort)(skill.Value.Pos / 2);
var offset = (byte)(skill.Value.Pos & 1);
var value = GetUInt16Value(PlayerFields.SkillLineRank + field, offset);
var max = GetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset);
var value = GetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset);
var max = GetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset);
switch (skill.Value.State)
{
@@ -1607,7 +1613,7 @@ namespace Game.Entities
{
PreparedStatement stmt = null;
foreach (var spell in m_spells)
foreach (var spell in m_spells.ToList())
{
if (spell.Value.State == PlayerSpellState.Removed || spell.Value.State == PlayerSpellState.Changed)
{
@@ -1884,7 +1890,7 @@ namespace Game.Entities
stmt.AddValue(0, GetGUID().GetCounter());
trans.Append(stmt);
var dailies = GetDynamicValues(PlayerDynamicFields.DailyQuests);
var dailies = GetDynamicValues(ActivePlayerDynamicFields.DailyQuests);
foreach (var questId in dailies)
{
stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHARACTER_QUESTSTATUS_DAILY);
@@ -1976,7 +1982,7 @@ namespace Game.Entities
for (byte group = 0; group < PlayerConst.MaxSpecializations; ++group)
{
Dictionary<uint, PlayerSpellState> talents = GetTalentMap(group);
var talents = GetTalentMap(group);
foreach (var pair in talents.ToList())
{
if (pair.Value == PlayerSpellState.Removed)
@@ -1999,21 +2005,15 @@ namespace Game.Entities
for (byte group = 0; group < PlayerConst.MaxSpecializations; ++group)
{
Dictionary<uint, PlayerSpellState> talents = GetPvpTalentMap(group);
foreach (var pair in talents.ToList())
{
if (pair.Value == PlayerSpellState.Removed)
{
talents.Remove(pair.Key);
continue;
}
stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHAR_PVP_TALENT);
stmt.AddValue(0, GetGUID().GetCounter());
stmt.AddValue(1, pair.Key);
stmt.AddValue(2, group);
trans.Append(stmt);
}
var talents = GetPvpTalentMap(group);
stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHAR_PVP_TALENT);
stmt.AddValue(0, GetGUID().GetCounter());
stmt.AddValue(1, talents[0]);
stmt.AddValue(2, talents[1]);
stmt.AddValue(3, talents[2]);
stmt.AddValue(4, talents[3]);
stmt.AddValue(5, group);
trans.Append(stmt);
}
}
public void _SaveMail(SQLTransaction trans)
@@ -2102,18 +2102,18 @@ namespace Game.Entities
stmt.AddValue(index++, GetStat((Stats)i));
for (int i = 0; i < (int)SpellSchools.Max; ++i)
stmt.AddValue(index++, GetResistance((SpellSchools)i));
stmt.AddValue(index++, GetResistance((SpellSchools)i) + GetBonusResistanceMod((SpellSchools)i));
stmt.AddValue(index++, GetFloatValue(PlayerFields.BlockPercentage));
stmt.AddValue(index++, GetFloatValue(PlayerFields.DodgePercentage));
stmt.AddValue(index++, GetFloatValue(PlayerFields.ParryPercentage));
stmt.AddValue(index++, GetFloatValue(PlayerFields.CritPercentage));
stmt.AddValue(index++, GetFloatValue(PlayerFields.RangedCritPercentage));
stmt.AddValue(index++, GetFloatValue(PlayerFields.SpellCritPercentage1));
stmt.AddValue(index++, GetFloatValue(ActivePlayerFields.BlockPercentage));
stmt.AddValue(index++, GetFloatValue(ActivePlayerFields.DodgePercentage));
stmt.AddValue(index++, GetFloatValue(ActivePlayerFields.ParryPercentage));
stmt.AddValue(index++, GetFloatValue(ActivePlayerFields.CritPercentage));
stmt.AddValue(index++, GetFloatValue(ActivePlayerFields.RangedCritPercentage));
stmt.AddValue(index++, GetFloatValue(ActivePlayerFields.SpellCritPercentage1));
stmt.AddValue(index++, GetUInt32Value(UnitFields.AttackPower));
stmt.AddValue(index++, GetUInt32Value(UnitFields.RangedAttackPower));
stmt.AddValue(index++, GetBaseSpellPowerBonus());
stmt.AddValue(index, GetUInt32Value(PlayerFields.CombatRating1 + (int)CombatRating.ResiliencePlayerDamage));
stmt.AddValue(index, GetUInt32Value(ActivePlayerFields.CombatRating + (int)CombatRating.ResiliencePlayerDamage));
trans.Append(stmt);
}
@@ -2408,8 +2408,8 @@ namespace Game.Entities
SetUInt32Value(UnitFields.Level, result.Read<uint>(6));
SetXP(result.Read<uint>(7));
_LoadIntoDataField(result.Read<string>(66), (int)PlayerFields.ExploredZones1, PlayerConst.ExploredZonesSize);
_LoadIntoDataField(result.Read<string>(67), (int)PlayerFields.KnownTitles, PlayerConst.KnowTitlesSize * 2);
_LoadIntoDataField(result.Read<string>(66), (int)ActivePlayerFields.ExploredZones, PlayerConst.ExploredZonesSize);
_LoadIntoDataField(result.Read<string>(67), (int)ActivePlayerFields.KnownTitles, PlayerConst.KnowTitlesSize * 2);
SetObjectScale(1.0f);
SetFloatValue(UnitFields.HoverHeight, 1.0f);
@@ -2441,7 +2441,7 @@ namespace Game.Entities
SetByteValue(PlayerFields.Bytes3, PlayerFieldOffsets.Bytes3OffsetInebriation, result.Read<byte>(55));
SetUInt32Value(PlayerFields.Flags, result.Read<uint>(20));
SetUInt32Value(PlayerFields.FlagsEx, result.Read<uint>(21));
SetInt32Value(PlayerFields.WatchedFactionIndex, (int)result.Read<uint>(54));
SetInt32Value(ActivePlayerFields.WatchedFactionIndex, (int)result.Read<uint>(54));
if (!ValidateAppearance((Race)result.Read<byte>(3), (Class)result.Read<byte>(4), (Gender)gender,
GetByteValue(PlayerFields.Bytes, PlayerFieldOffsets.BytesOffsetHairStyleId),
@@ -2455,7 +2455,7 @@ namespace Game.Entities
}
// set which actionbars the client has active - DO NOT REMOVE EVER AGAIN (can be changed though, if it does change fieldwise)
SetByteValue(PlayerFields.FieldBytes, PlayerFieldOffsets.FieldBytesOffsetActionBarToggles, result.Read<byte>(68));
SetByteValue(ActivePlayerFields.Bytes, PlayerFieldOffsets.FieldBytesOffsetActionBarToggles, result.Read<byte>(68));
m_fishingSteps = result.Read<byte>(72);
@@ -2464,7 +2464,7 @@ namespace Game.Entities
// cleanup inventory related item value fields (its will be filled correctly in _LoadInventory)
for (byte slot = EquipmentSlot.Start; slot < EquipmentSlot.End; ++slot)
{
SetGuidValue(PlayerFields.InvSlotHead + (slot * 4), ObjectGuid.Empty);
SetGuidValue(ActivePlayerFields.InvSlotHead + (slot * 4), ObjectGuid.Empty);
SetVisibleItemSlot(slot, null);
m_items[slot] = null;
@@ -2518,9 +2518,9 @@ namespace Game.Entities
}
_LoadCurrency(holder.GetResult(PlayerLoginQueryLoad.Currency));
SetUInt32Value(PlayerFields.LifetimeHonorableKills, result.Read<uint>(50));
SetUInt16Value(PlayerFields.Kills, PlayerFieldOffsets.FieldKillsOffsetTodayKills, result.Read<ushort>(51));
SetUInt16Value(PlayerFields.Kills, PlayerFieldOffsets.FieldKillsOffsetYesterdayKills, result.Read<ushort>(52));
SetUInt32Value(ActivePlayerFields.LifetimeHonorableKills, result.Read<uint>(50));
SetUInt16Value(ActivePlayerFields.Kills, PlayerFieldOffsets.FieldKillsOffsetTodayKills, result.Read<ushort>(51));
SetUInt16Value(ActivePlayerFields.Kills, PlayerFieldOffsets.FieldKillsOffsetYesterdayKills, result.Read<ushort>(52));
_LoadBoundInstances(holder.GetResult(PlayerLoginQueryLoad.BoundInstances));
_LoadInstanceTimeRestrictions(holder.GetResult(PlayerLoginQueryLoad.InstanceLockTimes));
@@ -2843,14 +2843,14 @@ namespace Game.Entities
SetGuidValue(UnitFields.CharmedBy, ObjectGuid.Empty);
SetGuidValue(UnitFields.Charm, ObjectGuid.Empty);
SetGuidValue(UnitFields.Summon, ObjectGuid.Empty);
SetGuidValue(PlayerFields.Farsight, ObjectGuid.Empty);
SetGuidValue(ActivePlayerFields.Farsight, ObjectGuid.Empty);
SetCreatorGUID(ObjectGuid.Empty);
RemoveFlag(UnitFields.Flags2, UnitFlags2.ForceMove);
// reset some aura modifiers before aura apply
SetUInt32Value(PlayerFields.TrackCreatures, 0);
SetUInt32Value(PlayerFields.TrackResources, 0);
SetUInt32Value(ActivePlayerFields.TrackCreatures, 0);
SetUInt32Value(ActivePlayerFields.TrackResources, 0);
// make sure the unit is considered out of combat for proper loading
ClearInCombat();
@@ -3061,7 +3061,7 @@ namespace Game.Entities
SetFlag(ObjectFields.DynamicFlags, UnitDynFlags.ReferAFriend);
if (m_grantableLevels > 0)
SetByteValue(PlayerFields.FieldBytes, PlayerFieldOffsets.FieldBytesOffsetRafGrantableLevel, 0x01);
SetByteValue(ActivePlayerFields.Bytes, PlayerFieldOffsets.FieldBytesOffsetRafGrantableLevel, 0x01);
_LoadDeclinedNames(holder.GetResult(PlayerLoginQueryLoad.DeclinedNames));
@@ -3078,9 +3078,9 @@ namespace Game.Entities
holder.GetResult(PlayerLoginQueryLoad.GarrisonFollowerAbilities)))
_garrison = garrison;
_InitHonorLevelOnLoadFromDB(result.Read<uint>(73), result.Read<uint>(74), result.Read<uint>(75));
_InitHonorLevelOnLoadFromDB(result.Read<uint>(73), result.Read<uint>(74));
_restMgr.LoadRestBonus(RestTypes.Honor, (PlayerRestState)result.Read<byte>(76), result.Read<float>(77));
_restMgr.LoadRestBonus(RestTypes.Honor, (PlayerRestState)result.Read<byte>(75), result.Read<float>(76));
if (time_diff > 0)
{
//speed collect rest bonus in offline, in logout, far from tavern, city (section/in hour)
@@ -3132,7 +3132,7 @@ namespace Game.Entities
stmt.AddValue(index++, (byte)GetClass());
stmt.AddValue(index++, GetByteValue(PlayerFields.Bytes3, PlayerFieldOffsets.Bytes3OffsetGender));
stmt.AddValue(index++, getLevel());
stmt.AddValue(index++, GetUInt32Value(PlayerFields.Xp));
stmt.AddValue(index++, GetUInt32Value(ActivePlayerFields.Xp));
stmt.AddValue(index++, GetMoney());
stmt.AddValue(index++, GetByteValue(PlayerFields.Bytes, PlayerFieldOffsets.BytesOffsetSkinId));
stmt.AddValue(index++, GetByteValue(PlayerFields.Bytes, PlayerFieldOffsets.BytesOffsetFaceId));
@@ -3143,7 +3143,7 @@ namespace Game.Entities
stmt.AddValue(index++, GetByteValue(PlayerFields.Bytes2, (byte)(PlayerFieldOffsets.Bytes2OffsetCustomDisplayOption + i)));
stmt.AddValue(index++, GetInventorySlotCount());
stmt.AddValue(index++, GetBankBagSlotCount());
stmt.AddValue(index++, (byte)GetUInt32Value(PlayerFields.RestInfo + PlayerFieldOffsets.RestStateXp));
stmt.AddValue(index++, (byte)GetUInt32Value(ActivePlayerFields.RestInfo + PlayerFieldOffsets.RestStateXp));
stmt.AddValue(index++, GetUInt32Value(PlayerFields.Flags));
stmt.AddValue(index++, GetUInt32Value(PlayerFields.FlagsEx));
stmt.AddValue(index++, (ushort)GetMapId());
@@ -3191,11 +3191,11 @@ namespace Game.Entities
ss.Append(m_taxi.SaveTaxiDestinationsToString());
stmt.AddValue(index++, ss.ToString());
stmt.AddValue(index++, GetUInt32Value(PlayerFields.LifetimeHonorableKills));
stmt.AddValue(index++, GetUInt16Value(PlayerFields.Kills, 0));
stmt.AddValue(index++, GetUInt16Value(PlayerFields.Kills, 1));
stmt.AddValue(index++, GetUInt32Value(ActivePlayerFields.LifetimeHonorableKills));
stmt.AddValue(index++, GetUInt16Value(ActivePlayerFields.Kills, 0));
stmt.AddValue(index++, GetUInt16Value(ActivePlayerFields.Kills, 1));
stmt.AddValue(index++, (uint)GetInt32Value(PlayerFields.ChosenTitle));
stmt.AddValue(index++, GetUInt32Value(PlayerFields.WatchedFactionIndex));
stmt.AddValue(index++, GetUInt32Value(ActivePlayerFields.WatchedFactionIndex));
stmt.AddValue(index++, GetDrunkValue());
stmt.AddValue(index++, GetHealth());
@@ -3222,7 +3222,7 @@ namespace Game.Entities
ss.Clear();
for (var i = 0; i < PlayerConst.ExploredZonesSize; ++i)
ss.AppendFormat("{0} ", GetUInt32Value(PlayerFields.ExploredZones1 + i));
ss.AppendFormat("{0} ", GetUInt32Value(ActivePlayerFields.ExploredZones + i));
stmt.AddValue(index++, ss.ToString());
ss.Clear();
@@ -3248,10 +3248,10 @@ namespace Game.Entities
ss.Clear();
for (var i = 0; i < PlayerConst.KnowTitlesSize * 2; ++i)
ss.AppendFormat("{0} ", GetUInt32Value(PlayerFields.KnownTitles + i));
ss.AppendFormat("{0} ", GetUInt32Value(ActivePlayerFields.KnownTitles + i));
stmt.AddValue(index++, ss.ToString());
stmt.AddValue(index++, GetByteValue(PlayerFields.FieldBytes, PlayerFieldOffsets.FieldBytesOffsetActionBarToggles));
stmt.AddValue(index++, GetByteValue(ActivePlayerFields.Bytes, PlayerFieldOffsets.FieldBytesOffsetActionBarToggles));
stmt.AddValue(index++, m_grantableLevels);
stmt.AddValue(index++, Global.WorldMgr.GetRealm().Build);
}
@@ -3264,7 +3264,7 @@ namespace Game.Entities
stmt.AddValue(index++, (byte)GetClass());
stmt.AddValue(index++, GetByteValue(PlayerFields.Bytes3, PlayerFieldOffsets.Bytes3OffsetGender));
stmt.AddValue(index++, getLevel());
stmt.AddValue(index++, GetUInt32Value(PlayerFields.Xp));
stmt.AddValue(index++, GetUInt32Value(ActivePlayerFields.Xp));
stmt.AddValue(index++, GetMoney());
stmt.AddValue(index++, GetByteValue(PlayerFields.Bytes, PlayerFieldOffsets.BytesOffsetSkinId));
stmt.AddValue(index++, GetByteValue(PlayerFields.Bytes, PlayerFieldOffsets.BytesOffsetFaceId));
@@ -3276,7 +3276,7 @@ namespace Game.Entities
PlayerFieldOffsets.Bytes2OffsetCustomDisplayOption + i)));
stmt.AddValue(index++, GetInventorySlotCount());
stmt.AddValue(index++, GetBankBagSlotCount());
stmt.AddValue(index++, (byte)GetUInt32Value(PlayerFields.RestInfo + PlayerFieldOffsets.RestStateXp));
stmt.AddValue(index++, (byte)GetUInt32Value(ActivePlayerFields.RestInfo + PlayerFieldOffsets.RestStateXp));
stmt.AddValue(index++, GetUInt32Value(PlayerFields.Flags));
stmt.AddValue(index++, GetUInt32Value(PlayerFields.FlagsEx));
@@ -3340,11 +3340,11 @@ namespace Game.Entities
ss.Append(m_taxi.SaveTaxiDestinationsToString());
stmt.AddValue(index++, ss.ToString());
stmt.AddValue(index++, GetUInt32Value(PlayerFields.LifetimeHonorableKills));
stmt.AddValue(index++, GetUInt16Value(PlayerFields.Kills, 0));
stmt.AddValue(index++, GetUInt16Value(PlayerFields.Kills, 1));
stmt.AddValue(index++, GetUInt32Value(ActivePlayerFields.LifetimeHonorableKills));
stmt.AddValue(index++, GetUInt16Value(ActivePlayerFields.Kills, 0));
stmt.AddValue(index++, GetUInt16Value(ActivePlayerFields.Kills, 1));
stmt.AddValue(index++, GetUInt32Value(PlayerFields.ChosenTitle));
stmt.AddValue(index++, (uint)GetInt32Value(PlayerFields.WatchedFactionIndex));
stmt.AddValue(index++, (uint)GetInt32Value(ActivePlayerFields.WatchedFactionIndex));
stmt.AddValue(index++, GetDrunkValue());
stmt.AddValue(index++, GetHealth());
@@ -3371,7 +3371,7 @@ namespace Game.Entities
ss.Clear();
for (var i = 0; i < PlayerConst.ExploredZonesSize; ++i)
ss.AppendFormat("{0} ", GetUInt32Value(PlayerFields.ExploredZones1 + i));
ss.AppendFormat("{0} ", GetUInt32Value(ActivePlayerFields.ExploredZones + i));
stmt.AddValue(index++, ss.ToString());
ss.Clear();
@@ -3397,17 +3397,16 @@ namespace Game.Entities
ss.Clear();
for (var i = 0; i < PlayerConst.KnowTitlesSize * 2; ++i)
ss.AppendFormat("{0} ", GetUInt32Value(PlayerFields.KnownTitles + i));
ss.AppendFormat("{0} ", GetUInt32Value(ActivePlayerFields.KnownTitles + i));
stmt.AddValue(index++, ss.ToString());
stmt.AddValue(index++, GetByteValue(PlayerFields.FieldBytes, PlayerFieldOffsets.FieldBytesOffsetActionBarToggles));
stmt.AddValue(index++, GetByteValue(ActivePlayerFields.Bytes, PlayerFieldOffsets.FieldBytesOffsetActionBarToggles));
stmt.AddValue(index++, m_grantableLevels);
stmt.AddValue(index++, IsInWorld && !GetSession().PlayerLogout() ? 1 : 0);
stmt.AddValue(index++, GetUInt32Value(PlayerFields.Honor));
stmt.AddValue(index++, GetUInt32Value(ActivePlayerFields.Honor));
stmt.AddValue(index++, GetHonorLevel());
stmt.AddValue(index++, GetPrestigeLevel());
stmt.AddValue(index++, (byte)GetUInt32Value(PlayerFields.RestInfo + PlayerFieldOffsets.RestStateHonor));
stmt.AddValue(index++, (byte)GetUInt32Value(ActivePlayerFields.RestInfo + PlayerFieldOffsets.RestStateHonor));
stmt.AddValue(index++, _restMgr.GetRestBonus(RestTypes.Honor));
stmt.AddValue(index++, Global.WorldMgr.GetRealm().Build);
+3 -2
View File
@@ -237,6 +237,7 @@ namespace Game.Entities
ulong m_GuildIdInvited;
DeclinedName _declinedname;
Runes m_runes = new Runes();
uint m_hostileReferenceCheckTimer;
uint m_drunkTimer;
long m_logintime;
long m_Last_tick;
@@ -319,13 +320,13 @@ namespace Game.Entities
for (byte i = 0; i < PlayerConst.MaxSpecializations; ++i)
{
Talents[i] = new Dictionary<uint, PlayerSpellState>();
PvpTalents[i] = new Dictionary<uint, PlayerSpellState>();
PvpTalents[i] = new Array<uint>(PlayerConst.MaxPvpTalentSlots);
Glyphs[i] = new List<uint>();
}
}
public Dictionary<uint, PlayerSpellState>[] Talents = new Dictionary<uint, PlayerSpellState>[PlayerConst.MaxSpecializations];
public Dictionary<uint, PlayerSpellState>[] PvpTalents = new Dictionary<uint, PlayerSpellState>[PlayerConst.MaxSpecializations];
public Array<uint>[] PvpTalents = new Array<uint>[PlayerConst.MaxSpecializations];
public List<uint>[] Glyphs = new List<uint>[PlayerConst.MaxSpecializations];
public uint ResetTalentsCost;
public long ResetTalentsTime;
@@ -233,6 +233,8 @@ namespace Game.Entities
return IsInSameRaidWith(p);
case 2:
return GetTeam() == p.GetTeam();
case 3:
return false;
}
}
public bool IsInSameGroupWith(Player p)
+26 -35
View File
@@ -1132,7 +1132,7 @@ namespace Game.Entities
if (pBag == null)
{
m_items[slot] = pItem;
SetGuidValue(PlayerFields.InvSlotHead + (slot * 4), pItem.GetGUID());
SetGuidValue(ActivePlayerFields.InvSlotHead + (slot * 4), pItem.GetGUID());
pItem.SetGuidValue(ItemFields.Contained, GetGUID());
pItem.SetGuidValue(ItemFields.Owner, GetGUID());
@@ -1975,7 +1975,7 @@ namespace Game.Entities
}
m_items[slot] = null;
SetGuidValue(PlayerFields.InvSlotHead + (slot * 4), ObjectGuid.Empty);
SetGuidValue(ActivePlayerFields.InvSlotHead + (slot * 4), ObjectGuid.Empty);
if (slot < EquipmentSlot.End)
{
@@ -3399,7 +3399,7 @@ namespace Game.Entities
// if current back slot non-empty search oldest or free
if (m_items[slot] != null)
{
uint oldest_time = GetUInt32Value(PlayerFields.BuyBackTimestamp1);
uint oldest_time = GetUInt32Value(ActivePlayerFields.BuyBackTimestamp);
uint oldest_slot = InventorySlots.BuyBackStart;
for (byte i = InventorySlots.BuyBackStart + 1; i < InventorySlots.BuyBackEnd; ++i)
@@ -3411,7 +3411,7 @@ namespace Game.Entities
break;
}
uint i_time = GetUInt32Value(PlayerFields.BuyBackTimestamp1 + i - InventorySlots.BuyBackStart);
uint i_time = GetUInt32Value(ActivePlayerFields.BuyBackTimestamp + i - InventorySlots.BuyBackStart);
if (oldest_time > i_time)
{
@@ -3432,13 +3432,13 @@ namespace Game.Entities
uint etime = (uint)(time - m_logintime + (30 * 3600));
int eslot = (int)slot - InventorySlots.BuyBackStart;
SetGuidValue(PlayerFields.InvSlotHead + ((int)slot * 4), pItem.GetGUID());
SetGuidValue(ActivePlayerFields.InvSlotHead + ((int)slot * 4), pItem.GetGUID());
ItemTemplate proto = pItem.GetTemplate();
if (proto != null)
SetUInt32Value(PlayerFields.BuyBackPrice1 + eslot, proto.GetSellPrice() * pItem.GetCount());
SetUInt32Value(ActivePlayerFields.BuyBackPrice + eslot, proto.GetSellPrice() * pItem.GetCount());
else
SetUInt32Value(PlayerFields.BuyBackPrice1 + eslot, 0);
SetUInt32Value(PlayerFields.BuyBackTimestamp1 + eslot, etime);
SetUInt32Value(ActivePlayerFields.BuyBackPrice + eslot, 0);
SetUInt32Value(ActivePlayerFields.BuyBackTimestamp + eslot, etime);
// move to next (for non filled list is move most optimized choice)
if (m_currentBuybackSlot < InventorySlots.BuyBackEnd - 1)
@@ -3890,9 +3890,9 @@ namespace Game.Entities
m_items[slot] = null;
int eslot = (int)slot - InventorySlots.BuyBackStart;
SetGuidValue(PlayerFields.InvSlotHead + (int)(slot * 4), ObjectGuid.Empty);
SetUInt32Value(PlayerFields.BuyBackPrice1 + eslot, 0);
SetUInt32Value(PlayerFields.BuyBackTimestamp1 + eslot, 0);
SetGuidValue(ActivePlayerFields.InvSlotHead + (int)(slot * 4), ObjectGuid.Empty);
SetUInt32Value(ActivePlayerFields.BuyBackPrice + eslot, 0);
SetUInt32Value(ActivePlayerFields.BuyBackTimestamp + eslot, 0);
// if current backslot is filled set to now free slot
if (m_items[m_currentBuybackSlot])
@@ -4137,6 +4137,9 @@ namespace Game.Entities
case ItemModType.MasteryRating:
ApplyRatingMod(CombatRating.Mastery, (int)(val * combatRatingMultiplier), apply);
break;
case ItemModType.ExtraArmor:
HandleStatModifier(UnitMods.Armor, UnitModifierType.TotalValue, (float)val, apply);
break;
case ItemModType.FireResistance:
HandleStatModifier(UnitMods.ResistanceFire, UnitModifierType.BaseValue, (float)val, apply);
break;
@@ -4219,27 +4222,8 @@ namespace Game.Entities
uint armor = item.GetArmor(this);
if (armor != 0)
{
UnitModifierType modType = UnitModifierType.TotalValue;
if (proto.GetClass() == ItemClass.Armor)
{
switch ((ItemSubClassArmor)proto.GetSubClass())
{
case ItemSubClassArmor.Cloth:
case ItemSubClassArmor.Leather:
case ItemSubClassArmor.Mail:
case ItemSubClassArmor.Plate:
case ItemSubClassArmor.Shield:
modType = UnitModifierType.BaseValue;
break;
}
}
HandleStatModifier(UnitMods.Armor, modType, armor, apply);
}
HandleStatModifier(UnitMods.Armor, UnitModifierType.BaseValue, (float)armor, apply);
//if (proto.GetArmorDamageModifier() > 0)
// HandleStatModifier(UnitMods.Armor, UnitModifierType.TotalValue, (float)proto.GetArmorDamageModifier(), apply);
WeaponAttackType attType = WeaponAttackType.BaseAttack;
if (slot == EquipmentSlot.MainHand && (proto.GetInventoryType() == InventoryType.Ranged || proto.GetInventoryType() == InventoryType.RangedRight))
{
@@ -5617,7 +5601,7 @@ namespace Game.Entities
Log.outDebug(LogFilter.Player, "STORAGE: EquipItem slot = {0}, item = {1}", slot, pItem.GetEntry());
m_items[slot] = pItem;
SetGuidValue(PlayerFields.InvSlotHead + (int)(slot * 4), pItem.GetGUID());
SetGuidValue(ActivePlayerFields.InvSlotHead + (int)(slot * 4), pItem.GetGUID());
pItem.SetGuidValue(ItemFields.Contained, GetGUID());
pItem.SetGuidValue(ItemFields.Owner, GetGUID());
pItem.SetSlot((byte)slot);
@@ -5661,7 +5645,7 @@ namespace Game.Entities
Bag pBag;
if (bag == InventorySlots.Bag0)
{
SetGuidValue(PlayerFields.InvSlotHead + (slot * 4), ObjectGuid.Empty);
SetGuidValue(ActivePlayerFields.InvSlotHead + (slot * 4), ObjectGuid.Empty);
// equipment and equipped bags can have applied bonuses
if (slot < InventorySlots.BagEnd)
@@ -6031,7 +6015,7 @@ namespace Game.Entities
}
}
public byte GetInventorySlotCount() { return GetByteValue(PlayerFields.FieldBytes2, PlayerFieldOffsets.FieldBytes2OffsetNumBackpackSlots); }
public byte GetInventorySlotCount() { return GetByteValue(ActivePlayerFields.Bytes2, PlayerFieldOffsets.FieldBytes2OffsetNumBackpackSlots); }
public void SetInventorySlotCount(byte slots)
{
//ASSERT(slots <= (INVENTORY_SLOT_ITEM_END - INVENTORY_SLOT_ITEM_START));
@@ -6074,7 +6058,7 @@ namespace Game.Entities
}
}
SetByteValue(PlayerFields.FieldBytes2, PlayerFieldOffsets.FieldBytes2OffsetNumBackpackSlots, slots);
SetByteValue(ActivePlayerFields.Bytes2, PlayerFieldOffsets.FieldBytes2OffsetNumBackpackSlots, slots);
}
public byte GetBankBagSlotCount() { return GetByteValue(PlayerFields.Bytes3, PlayerFieldOffsets.Bytes3OffsetBankBagSlots); }
@@ -6109,6 +6093,13 @@ namespace Game.Entities
return;
}
// dont allow protected item to be looted by someone else
if (!item.rollWinnerGUID.IsEmpty() && item.rollWinnerGUID != GetGUID())
{
SendLootRelease(GetLootGUID());
return;
}
List<ItemPosCount> dest = new List<ItemPosCount>();
InventoryResult msg = CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, item.itemid, item.count);
if (msg == InventoryResult.Ok)
+5 -2
View File
@@ -305,7 +305,7 @@ namespace Game.Entities
if (save != null)
{
InstanceBind bind = new InstanceBind();
if (m_boundInstances[save.GetDifficultyID()].ContainsKey(save.GetMapId()))
if (m_boundInstances.ContainsKey(save.GetDifficultyID()) && m_boundInstances[save.GetDifficultyID()].ContainsKey(save.GetMapId()))
bind = m_boundInstances[save.GetDifficultyID()][save.GetMapId()];
if (extendState == BindExtensionState.Keep) // special flag, keep the player's current extend state when updating for new boss down
@@ -364,6 +364,9 @@ namespace Game.Entities
Global.ScriptMgr.OnPlayerBindToInstance(this, save.GetDifficultyID(), save.GetMapId(), permanent, extendState);
if (!m_boundInstances.ContainsKey(save.GetDifficultyID()))
m_boundInstances[save.GetDifficultyID()] = new Dictionary<uint, InstanceBind>();
m_boundInstances[save.GetDifficultyID()][save.GetMapId()] = bind;
return bind;
}
@@ -406,7 +409,7 @@ namespace Game.Entities
{
InstanceSave save = instanceBind.save;
InstanceLockInfos lockInfos;
InstanceLock lockInfos;
lockInfos.InstanceID = save.GetInstanceId();
lockInfos.MapID = save.GetMapId();
lockInfos.DifficultyID = (uint)save.GetDifficultyID();
+67 -109
View File
@@ -46,15 +46,15 @@ namespace Game.Entities
if (m_lastHonorUpdateTime >= yesterday)
{
// this is the first update today, reset today's contribution
ushort killsToday = GetUInt16Value(PlayerFields.Kills, 0);
SetUInt16Value(PlayerFields.Kills, 0, 0);
SetUInt16Value(PlayerFields.Kills, 1, killsToday);
ushort killsToday = GetUInt16Value(ActivePlayerFields.Kills, 0);
SetUInt16Value(ActivePlayerFields.Kills, 0, 0);
SetUInt16Value(ActivePlayerFields.Kills, 1, killsToday);
}
else
{
// no honor/kills yesterday or today, reset
SetUInt32Value(PlayerFields.Kills, 0);
SetUInt32Value(ActivePlayerFields.Kills, 0);
}
}
@@ -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(PlayerFields.Kills, 0, 1, true);
ApplyModUInt16Value(ActivePlayerFields.Kills, 0, 1, true);
// and those in a lifetime
ApplyModUInt32Value(PlayerFields.LifetimeHonorableKills, 1, true);
ApplyModUInt32Value(ActivePlayerFields.LifetimeHonorableKills, 1, true);
UpdateCriteria(CriteriaTypes.EarnHonorableKill);
UpdateCriteria(CriteriaTypes.HkClass, (uint)victim.GetClass());
UpdateCriteria(CriteriaTypes.HkRace, (uint)victim.GetRace());
@@ -215,15 +215,12 @@ namespace Game.Entities
return true;
}
void _InitHonorLevelOnLoadFromDB(uint honor, uint honorLevel, uint prestigeLevel)
void _InitHonorLevelOnLoadFromDB(uint honor, uint honorLevel)
{
SetUInt32Value(PlayerFields.HonorLevel, honorLevel);
SetUInt32Value(PlayerFields.Prestige, prestigeLevel);
UpdateHonorNextLevel();
AddHonorXP(honor);
if (CanPrestige())
Prestige();
}
void RewardPlayerWithRewardPack(uint rewardPackID)
@@ -253,12 +250,12 @@ namespace Game.Entities
public void AddHonorXP(uint xp)
{
uint currentHonorXP = GetUInt32Value(PlayerFields.Honor);
uint nextHonorLevelXP = GetUInt32Value(PlayerFields.HonorNextLevel);
uint currentHonorXP = GetUInt32Value(ActivePlayerFields.Honor);
uint nextHonorLevelXP = GetUInt32Value(ActivePlayerFields.HonorNextLevel);
uint newHonorXP = currentHonorXP + xp;
uint honorLevel = GetHonorLevel();
if (xp < 1 || getLevel() < PlayerConst.LevelMinHonor || IsMaxHonorLevelAndPrestige())
if (xp < 1 || getLevel() < PlayerConst.LevelMinHonor || IsMaxHonorLevel())
return;
while (newHonorXP >= nextHonorLevelXP)
@@ -269,72 +266,34 @@ namespace Game.Entities
SetHonorLevel((byte)(honorLevel + 1));
honorLevel = GetHonorLevel();
nextHonorLevelXP = GetUInt32Value(PlayerFields.HonorNextLevel);
nextHonorLevelXP = GetUInt32Value(ActivePlayerFields.HonorNextLevel);
}
SetUInt32Value(PlayerFields.Honor, IsMaxHonorLevelAndPrestige() ? 0 : newHonorXP);
SetUInt32Value(ActivePlayerFields.Honor, IsMaxHonorLevel() ? 0 : newHonorXP);
}
void SetHonorLevel(byte level)
{
byte oldHonorLevel = (byte)GetHonorLevel();
byte prestige = (byte)GetPrestigeLevel();
if (level == oldHonorLevel)
return;
uint rewardPackID = Global.DB2Mgr.GetRewardPackIDForPvpRewardByHonorLevelAndPrestige(level, prestige);
RewardPlayerWithRewardPack(rewardPackID);
SetUInt32Value(PlayerFields.HonorLevel, level);
UpdateHonorNextLevel();
UpdateCriteria(CriteriaTypes.HonorLevelReached);
// This code is here because no link was found between those items and this reward condition in the db2 files.
// Interesting CriteriaTree found: Tree ids: 51140, 51156 (criteria id 31773, modifier tree id 37759)
if (level == 50 && prestige == 1)
{
if (GetTeam() == Team.Alliance)
AddItem(138992, 1);
else
AddItem(138996, 1);
}
if (CanPrestige())
Prestige();
}
public void Prestige()
{
SetUInt32Value(PlayerFields.Prestige, GetPrestigeLevel() + 1);
SetUInt32Value(PlayerFields.HonorLevel, 1);
UpdateHonorNextLevel();
UpdateCriteria(CriteriaTypes.PrestigeReached);
}
public bool CanPrestige()
{
if (GetSession().GetExpansion() >= Expansion.Legion && getLevel() >= PlayerConst.LevelMinHonor && GetHonorLevel() >= PlayerConst.MaxHonorLevel && GetPrestigeLevel() < Global.DB2Mgr.GetMaxPrestige())
return true;
return false;
}
bool IsMaxPrestige()
{
return GetPrestigeLevel() == Global.DB2Mgr.GetMaxPrestige();
}
void UpdateHonorNextLevel()
{
uint prestige = Math.Min(16 - 1, GetPrestigeLevel());
SetUInt32Value(PlayerFields.HonorNextLevel, (uint)CliDB.HonorLevelGameTable.GetRow(GetHonorLevel()).Prestige[prestige]);
// 5500 at honor level 1
// no idea what between here
// 8800 at honor level ~14 (never goes above 8800)
SetUInt32Value(ActivePlayerFields.HonorNextLevel, 8800);
}
public uint GetPrestigeLevel() { return GetUInt32Value(PlayerFields.Prestige); }
public uint GetHonorLevel() { return GetUInt32Value(PlayerFields.HonorLevel); }
public bool IsMaxHonorLevelAndPrestige() { return IsMaxPrestige() && GetHonorLevel() == PlayerConst.MaxHonorLevel; }
public bool IsMaxHonorLevel() { return GetHonorLevel() == PlayerConst.MaxHonorLevel; }
public void ActivatePvpItemLevels(bool activate) { _usePvpItemLevels = activate; }
public bool IsUsingPvpItemLevels() { return _usePvpItemLevels; }
@@ -343,7 +302,7 @@ namespace Game.Entities
{
foreach (var talentInfo in CliDB.PvpTalentStorage.Values)
{
if (talentInfo.ClassID != 0 && talentInfo.ClassID != (int)GetClass())
if (talentInfo == null)
continue;
RemovePvpTalent(talentInfo);
@@ -355,62 +314,61 @@ namespace Game.Entities
DB.Characters.CommitTransaction(trans);
}
public TalentLearnResult LearnPvpTalent(uint talentID, ref uint spellOnCooldown)
public TalentLearnResult LearnPvpTalent(uint talentID, byte slot, ref uint spellOnCooldown)
{
if (slot >= PlayerConst.MaxPvpTalentSlots)
return TalentLearnResult.FailedUnknown;
if (IsInCombat())
return TalentLearnResult.FailedAffectingCombat;
if (getLevel() < PlayerConst.LevelMinHonor)
return TalentLearnResult.FailedUnknown;
if (IsDead())
return TalentLearnResult.FailedCantDoThatRightNow;
PvpTalentRecord talentInfo = CliDB.PvpTalentStorage.LookupByKey(talentID);
if (talentInfo == null)
return TalentLearnResult.FailedUnknown;
if (talentInfo.SpecID != 0)
{
if (talentInfo.SpecID != GetInt32Value(PlayerFields.CurrentSpecId))
return TalentLearnResult.FailedUnknown;
}
else if (talentInfo.Role < 7)
{
if (talentInfo.Role != CliDB.ChrSpecializationStorage.LookupByKey(GetUInt32Value(PlayerFields.CurrentSpecId)).Role)
return TalentLearnResult.FailedUnknown;
}
// prevent learn talent for different class (cheating)
if (talentInfo.ClassID != 0 && talentInfo.ClassID != (int)GetClass())
if (talentInfo.SpecID != GetInt32Value(PlayerFields.CurrentSpecId))
return TalentLearnResult.FailedUnknown;
if (GetPrestigeLevel() == 0)
if (Global.DB2Mgr.GetRequiredHonorLevelForPvpTalent(talentInfo) > GetHonorLevel())
if (talentInfo.LevelRequired > getLevel())
return TalentLearnResult.FailedUnknown;
if (Global.DB2Mgr.GetRequiredLevelForPvpTalentSlot(slot, GetClass()) > getLevel())
return TalentLearnResult.FailedUnknown;
PvpTalentCategoryRecord talentCategory = CliDB.PvpTalentCategoryStorage.LookupByKey(talentInfo.PvpTalentCategoryID);
if (talentCategory != null)
if (!Convert.ToBoolean(talentCategory.TalentSlotMask & (1 << slot)))
return TalentLearnResult.FailedUnknown;
// Check if player doesn't have any talent in current tier
for (uint c = 0; c < PlayerConst.MaxPvpTalentColumns; ++c)
// Check if player doesn't have this talent in other slot
if (HasPvpTalent(talentID, GetActiveTalentGroup()))
return TalentLearnResult.FailedUnknown;
PvpTalentRecord talent = CliDB.PvpTalentStorage.LookupByKey(GetPvpTalentMap(GetActiveTalentGroup())[slot]);
if (talent != null)
{
foreach (PvpTalentRecord talent in Global.DB2Mgr.GetPvpTalentsByPosition((uint)GetClass(), (uint)talentInfo.TierID, c))
if (!HasFlag(PlayerFields.Flags, PlayerFlags.Resting) && !HasFlag(UnitFields.Flags2, UnitFlags2.AllowChangingTalents))
return TalentLearnResult.FailedRestArea;
if (GetSpellHistory().HasCooldown(talent.SpellID))
{
if (HasPvpTalent(talent.Id, GetActiveTalentGroup()) && !HasFlag(PlayerFields.Flags, PlayerFlags.Resting) && HasFlag(UnitFields.Flags, UnitFlags.ImmuneToNpc))
return TalentLearnResult.FailedRestArea;
if (GetSpellHistory().HasCooldown(talent.SpellID))
{
spellOnCooldown = talent.SpellID;
return TalentLearnResult.FailedCantRemoveTalent;
}
RemovePvpTalent(talent);
spellOnCooldown = talent.SpellID;
return TalentLearnResult.FailedCantRemoveTalent;
}
RemovePvpTalent(talent);
}
if (!AddPvpTalent(talentInfo, GetActiveTalentGroup(), true))
if (!AddPvpTalent(talentInfo, GetActiveTalentGroup(), slot))
return TalentLearnResult.FailedUnknown;
return TalentLearnResult.LearnOk;
}
bool AddPvpTalent(PvpTalentRecord talent, byte activeTalentGroup, bool learning)
bool AddPvpTalent(PvpTalentRecord talent, byte activeTalentGroup, byte slot)
{
//ASSERT(talent);
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(talent.SpellID);
@@ -433,10 +391,7 @@ namespace Game.Entities
if (talent.OverridesSpellID != 0)
AddOverrideSpell(talent.OverridesSpellID, talent.SpellID);
if (learning)
GetPvpTalentMap(activeTalentGroup)[talent.Id] = PlayerSpellState.New;
else
GetPvpTalentMap(activeTalentGroup)[talent.Id] = PlayerSpellState.Unchanged;
GetPvpTalentMap(activeTalentGroup)[slot] = talent.Id;
return true;
}
@@ -453,27 +408,30 @@ namespace Game.Entities
if (talent.OverridesSpellID != 0)
RemoveOverrideSpell(talent.OverridesSpellID, talent.SpellID);
//todo check this
// if this talent rank can be found in the PlayerTalentMap, mark the talent as removed so it gets deleted
if (!GetPvpTalentMap(GetActiveTalentGroup()).ContainsKey(talent.Id))
GetPvpTalentMap(GetActiveTalentGroup())[talent.Id] = PlayerSpellState.Removed;
GetPvpTalentMap(GetActiveTalentGroup()).Remove(talent.Id);
}
public void TogglePvpTalents(bool enable)
{
var pvpTalents = GetPvpTalentMap(GetActiveTalentGroup());
foreach (var pair in pvpTalents)
foreach (uint pvpTalentId in pvpTalents)
{
PvpTalentRecord pvpTalentInfo = CliDB.PvpTalentStorage.LookupByKey(pair.Key);
if (enable && pair.Value != PlayerSpellState.Removed)
LearnSpell(pvpTalentInfo.SpellID, false);
else
RemoveSpell(pvpTalentInfo.SpellID, true);
PvpTalentRecord pvpTalentInfo = CliDB.PvpTalentStorage.LookupByKey(pvpTalentId);
if (pvpTalentInfo != null)
{
if (enable)
LearnSpell(pvpTalentInfo.SpellID, false);
else
RemoveSpell(pvpTalentInfo.SpellID, true);
}
}
}
bool HasPvpTalent(uint talentID, byte activeTalentGroup)
{
return GetPvpTalentMap(activeTalentGroup).ContainsKey(talentID) && GetPvpTalentMap(activeTalentGroup)[talentID] != PlayerSpellState.Removed;
return GetPvpTalentMap(activeTalentGroup).Contains(talentID);
}
public void EnablePvpRules(bool dueToCombat = false)
@@ -554,7 +512,7 @@ namespace Game.Entities
return false;
}
public Dictionary<uint, PlayerSpellState> GetPvpTalentMap(uint spec) { return _specializationInfo.PvpTalents[spec]; }
public Array<uint> GetPvpTalentMap(byte spec) { return _specializationInfo.PvpTalents[spec]; }
//BGs
public Battleground GetBattleground()
@@ -913,7 +871,7 @@ namespace Game.Entities
//Arenas
public void SetArenaTeamInfoField(byte slot, ArenaTeamInfoType type, uint value)
{
SetUInt32Value(PlayerFields.ArenaTeamInfo11 + (slot * (int)ArenaTeamInfoType.End) + (int)type, value);
SetUInt32Value(ActivePlayerFields.ArenaTeamInfo + (slot * (int)ArenaTeamInfoType.End) + (int)type, value);
}
public void SetInArenaTeam(uint ArenaTeamId, byte slot, byte type)
@@ -956,8 +914,8 @@ namespace Game.Entities
}
while (result.NextRow());
}
public uint GetArenaTeamId(byte slot) { return GetUInt32Value(PlayerFields.ArenaTeamInfo11 + (slot * (int)ArenaTeamInfoType.End) + (int)ArenaTeamInfoType.Id); }
public uint GetArenaPersonalRating(byte slot) { return GetUInt32Value(PlayerFields.ArenaTeamInfo11 + (slot * (int)ArenaTeamInfoType.End) + (int)ArenaTeamInfoType.PersonalRating); }
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 void SetArenaTeamIdInvited(uint ArenaTeamId) { m_ArenaTeamIdInvited = ArenaTeamId; }
public uint GetArenaTeamIdInvited() { return m_ArenaTeamIdInvited; }
public uint GetRBGPersonalRating() { return 0; }
+40 -19
View File
@@ -44,6 +44,35 @@ namespace Game.Entities
public List<uint> getRewardedQuests() { return m_RewardedQuests; }
Dictionary<uint, QuestStatusData> getQuestStatusMap() { return m_QuestStatus; }
public int GetQuestMinLevel(Quest quest)
{
if (quest.Level == -1 && quest.ScalingFactionGroup != 0)
{
ChrRacesRecord race = CliDB.ChrRacesStorage.LookupByKey(GetRace());
FactionTemplateRecord raceFaction = CliDB.FactionTemplateStorage.LookupByKey(race.FactionID);
if (raceFaction == null || raceFaction.FactionGroup != quest.ScalingFactionGroup)
return quest.MaxScalingLevel;
}
return quest.MinLevel;
}
public int GetQuestLevel(Quest quest)
{
if (quest == null)
return 0;
if (quest.Level == -1)
{
int minLevel = GetQuestMinLevel(quest);
int maxLevel = quest.MaxScalingLevel;
int level = (int)getLevel();
if (level >= minLevel)
return Math.Min(level, maxLevel);
return minLevel;
}
return quest.Level;
}
public int GetRewardedQuestCount() { return m_RewardedQuests.Count; }
public void LearnQuestRewardedSpells(Quest quest)
@@ -116,7 +145,7 @@ namespace Game.Entities
public void DailyReset()
{
foreach (uint questId in GetDynamicValues(PlayerDynamicFields.DailyQuests))
foreach (uint questId in GetDynamicValues(ActivePlayerDynamicFields.DailyQuests))
{
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(questId);
if (questBit != 0)
@@ -124,10 +153,10 @@ namespace Game.Entities
}
DailyQuestsReset dailyQuestsReset = new DailyQuestsReset();
dailyQuestsReset.Count = GetDynamicValues(PlayerDynamicFields.DailyQuests).Length;
dailyQuestsReset.Count = GetDynamicValues(ActivePlayerDynamicFields.DailyQuests).Length;
SendPacket(dailyQuestsReset);
ClearDynamicValue(PlayerDynamicFields.DailyQuests);
ClearDynamicValue(ActivePlayerDynamicFields.DailyQuests);
m_DFQuests.Clear(); // Dungeon Finder Quests.
@@ -210,14 +239,6 @@ namespace Game.Entities
return false;
}
public uint GetQuestLevel(Quest quest)
{
if (quest == null)
return getLevel();
return (uint)(quest.Level > 0 ? quest.Level : Math.Min((int)getLevel(), quest.MaxScalingLevel));
}
public bool IsQuestRewarded(uint quest_id)
{
return m_RewardedQuests.Contains(quest_id);
@@ -389,7 +410,7 @@ namespace Game.Entities
SatisfyQuestPrevChain(quest, false) && SatisfyQuestDay(quest, false) && SatisfyQuestWeek(quest, false) &&
SatisfyQuestMonth(quest, false) && SatisfyQuestSeasonal(quest, false))
{
return getLevel() + WorldConfig.GetIntValue(WorldCfg.QuestHighLevelHideDiff) >= quest.MinLevel;
return getLevel() + WorldConfig.GetIntValue(WorldCfg.QuestHighLevelHideDiff) >= GetQuestMinLevel(quest);
}
return false;
@@ -796,7 +817,7 @@ namespace Game.Entities
public uint GetQuestMoneyReward(Quest quest)
{
return (uint)(quest.MoneyValue(getLevel()) * WorldConfig.GetFloatValue(WorldCfg.RateMoneyQuest));
return (uint)(quest.MoneyValue(this) * WorldConfig.GetFloatValue(WorldCfg.RateMoneyQuest));
}
public uint GetQuestXPReward(Quest quest)
@@ -807,7 +828,7 @@ namespace Game.Entities
if (rewarded && !quest.IsDFQuest())
return 0;
uint XP = (uint)(quest.XPValue(getLevel()) * WorldConfig.GetFloatValue(WorldCfg.RateXpQuest));
uint XP = (uint)(quest.XPValue(this) * WorldConfig.GetFloatValue(WorldCfg.RateXpQuest));
// handle SPELL_AURA_MOD_XP_QUEST_PCT auras
var ModXPPctAuras = GetAuraEffectsByType(AuraType.ModXpQuestPct);
@@ -1231,7 +1252,7 @@ namespace Game.Entities
public bool SatisfyQuestLevel(Quest qInfo, bool msg)
{
if (getLevel() < qInfo.MinLevel)
if (getLevel() < GetQuestMinLevel(qInfo))
{
if (msg)
{
@@ -1588,7 +1609,7 @@ namespace Game.Entities
return true;
}
var dailies = GetDynamicValues(PlayerDynamicFields.DailyQuests);
var dailies = GetDynamicValues(ActivePlayerDynamicFields.DailyQuests);
foreach (var dailyQuestId in dailies)
if (dailyQuestId == qInfo.Id)
return false;
@@ -2018,7 +2039,7 @@ namespace Game.Entities
if (fieldOffset >= PlayerConst.QuestsCompletedBitsSize)
return;
ApplyModFlag(PlayerFields.QuestCompleted + fieldOffset, (uint)(1 << (((int)questBit - 1) & 31)), completed);
ApplyModFlag(ActivePlayerFields.QuestCompleted + fieldOffset, (uint)(1 << (((int)questBit - 1) & 31)), completed);
}
public void AreaExploredOrEventHappens(uint questId)
@@ -2993,7 +3014,7 @@ namespace Game.Entities
{
if (!qQuest.IsDFQuest())
{
AddDynamicValue(PlayerDynamicFields.DailyQuests, quest_id);
AddDynamicValue(ActivePlayerDynamicFields.DailyQuests, quest_id);
m_lastDailyQuestTime = Time.UnixTime; // last daily quest time
m_DailyQuestChanged = true;
@@ -3012,7 +3033,7 @@ namespace Game.Entities
bool found = false;
if (Global.ObjectMgr.GetQuestTemplate(quest_id) != null)
{
var dailies = GetDynamicValues(PlayerDynamicFields.DailyQuests);
var dailies = GetDynamicValues(ActivePlayerDynamicFields.DailyQuests);
foreach (uint dailyQuestId in dailies)
{
if (dailyQuestId == quest_id)
+161 -79
View File
@@ -48,20 +48,20 @@ namespace Game.Entities
if (Global.SpellMgr.GetSkillRangeType(rcEntry) == SkillRangeType.Level)
{
ushort max = GetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset);
ushort max = GetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset);
// update only level dependent max skill values
if (max != 1)
{
SetUInt16Value(PlayerFields.SkillLineRank + field, offset, maxSkill);
SetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset, maxSkill);
SetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset, maxSkill);
SetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset, maxSkill);
if (pair.Value.State != SkillState.New)
pair.Value.State = SkillState.Changed;
}
}
// Update level dependent skillline spells
LearnSkillRewardedSpells(rcEntry.SkillID, GetUInt16Value(PlayerFields.SkillLineRank + field, offset));
LearnSkillRewardedSpells(rcEntry.SkillID, GetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset));
}
}
@@ -86,10 +86,10 @@ namespace Game.Entities
ushort field = (ushort)(skill.Value.Pos / 2);
byte offset = (byte)(skill.Value.Pos & 1);
ushort max = GetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset);
ushort max = GetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset);
if (max > 1)
{
SetUInt16Value(PlayerFields.SkillLineRank + field, offset, max);
SetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset, max);
if (skill.Value.State != SkillState.New)
skill.Value.State = SkillState.Changed;
@@ -109,9 +109,9 @@ namespace Game.Entities
var field = (ushort)(skillStatusData.Pos / 2);
var offset = (byte)(skillStatusData.Pos & 1);
int result = GetUInt16Value(PlayerFields.SkillLineRank + field, offset);
result += GetUInt16Value(PlayerFields.SkillLineTempBonus + field, offset);
result += GetUInt16Value(PlayerFields.SkillLinePermBonus + field, offset);
int result = GetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset);
result += GetUInt16Value(ActivePlayerFields.SkillLineTempBonus + field, offset);
result += GetUInt16Value(ActivePlayerFields.SkillLinePermBonus + field, offset);
return (ushort)(result < 0 ? 0 : result);
}
@@ -127,9 +127,9 @@ namespace Game.Entities
var field = (ushort)(skillStatusData.Pos / 2);
var offset = (byte)(skillStatusData.Pos & 1);
int result = GetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset);
result += GetUInt16Value(PlayerFields.SkillLineTempBonus + field, offset);
result += GetUInt16Value(PlayerFields.SkillLinePermBonus + field, offset);
int result = GetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset);
result += GetUInt16Value(ActivePlayerFields.SkillLineTempBonus + field, offset);
result += GetUInt16Value(ActivePlayerFields.SkillLinePermBonus + field, offset);
return (ushort)(result < 0 ? 0 : result);
}
@@ -145,7 +145,7 @@ namespace Game.Entities
var field = (ushort)(skillStatusData.Pos / 2);
var offset = (byte)(skillStatusData.Pos & 1);
return GetUInt16Value(PlayerFields.SkillLineRank + field, offset);
return GetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset);
}
public ushort GetSkillStep(SkillType skill)
@@ -160,7 +160,7 @@ namespace Game.Entities
var field = (ushort)(skillStatusData.Pos / 2);
var offset = (byte)(skillStatusData.Pos & 1);
return GetUInt16Value(PlayerFields.SkillLineStep + field, offset);
return GetUInt16Value(ActivePlayerFields.SkillLineStep + field, offset);
}
public ushort GetPureMaxSkillValue(SkillType skill)
@@ -175,7 +175,7 @@ namespace Game.Entities
var field = (ushort)(skillStatusData.Pos / 2);
var offset = (byte)(skillStatusData.Pos & 1);
return GetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset);
return GetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset);
}
public ushort GetBaseSkillValue(SkillType skill)
@@ -190,8 +190,8 @@ namespace Game.Entities
var field = (ushort)(skillStatusData.Pos / 2);
var offset = (byte)(skillStatusData.Pos & 1);
var result = (int)GetUInt16Value(PlayerFields.SkillLineRank + field, offset);
result += GetUInt16Value(PlayerFields.SkillLinePermBonus + field, offset);
var result = (int)GetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset);
result += GetUInt16Value(ActivePlayerFields.SkillLinePermBonus + field, offset);
return (ushort)(result < 0 ? 0 : result);
}
@@ -207,7 +207,7 @@ namespace Game.Entities
var field = (ushort)(skillStatusData.Pos / 2);
var offset = (byte)(skillStatusData.Pos & 1);
return GetUInt16Value(PlayerFields.SkillLinePermBonus + field, offset);
return GetUInt16Value(ActivePlayerFields.SkillLinePermBonus + field, offset);
}
public ushort GetSkillTempBonusValue(uint skill)
@@ -222,12 +222,12 @@ namespace Game.Entities
var field = (ushort)(skillStatusData.Pos / 2);
var offset = (byte)(skillStatusData.Pos & 1);
return GetUInt16Value(PlayerFields.SkillLineTempBonus + field, offset);
return GetUInt16Value(ActivePlayerFields.SkillLineTempBonus + field, offset);
}
void InitializeSelfResurrectionSpells()
{
ClearDynamicValue(PlayerDynamicFields.SelfResSpells);
ClearDynamicValue(ActivePlayerDynamicFields.SelfResSpells);
uint[] spells = new uint[3];
@@ -248,7 +248,7 @@ namespace Game.Entities
foreach (uint selfResSpell in spells)
if (selfResSpell != 0)
AddDynamicValue(PlayerDynamicFields.SelfResSpells, selfResSpell);
AddDynamicValue(ActivePlayerDynamicFields.SelfResSpells, selfResSpell);
}
public void PetSpellInitialize()
@@ -415,8 +415,7 @@ namespace Game.Entities
// levels sync. with spell requirement for skill levels to learn
// bonus abilities in sSkillLineAbilityStore
// Used only to avoid scan DBC at each skill grow
uint[] bonusSkillLevels = { 75, 150, 225, 300, 375, 450, 525 };
int bonusSkillLevelsSize = bonusSkillLevels.Length / sizeof(uint);
uint[] bonusSkillLevels = { 75, 150, 225, 300, 375, 450, 525, 600, 700, 850 };
Log.outDebug(LogFilter.Player, "UpdateSkillPro(SkillId {0}, Chance {0:D3}%)", skillId, chance / 10.0f);
if (skillId == 0)
@@ -435,8 +434,8 @@ namespace Game.Entities
ushort field = (ushort)(skillStatusData.Pos / 2);
byte offset = (byte)(skillStatusData.Pos & 1);
ushort value = GetUInt16Value(PlayerFields.SkillLineRank + field, offset);
ushort max = GetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset);
ushort value = GetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset);
ushort max = GetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset);
if (max == 0 || value == 0 || value >= max)
return false;
@@ -451,13 +450,12 @@ namespace Game.Entities
if (new_value > max)
new_value = max;
SetUInt16Value(PlayerFields.SkillLineRank + field, offset, new_value);
SetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset, new_value);
if (skillStatusData.State != SkillState.New)
skillStatusData.State = SkillState.Changed;
for (int i = 0; i < bonusSkillLevelsSize; ++i)
foreach (uint bsl in bonusSkillLevels)
{
uint bsl = bonusSkillLevels[i];
if (value < bsl && new_value >= bsl)
{
LearnSkillRewardedSpells(skillId, new_value);
@@ -941,7 +939,7 @@ namespace Game.Entities
if (skill == null || skill.State == SkillState.Deleted)
return;
int field = (int)(skill.Pos / 2 + (talent ? PlayerFields.SkillLinePermBonus : PlayerFields.SkillLineTempBonus));
int field = (int)(skill.Pos / 2 + (talent ? ActivePlayerFields.SkillLinePermBonus : ActivePlayerFields.SkillLineTempBonus));
byte offset = (byte)(skill.Pos & 1);
ushort bonus = GetUInt16Value(field, offset);
@@ -1125,7 +1123,7 @@ namespace Game.Entities
{
var field = (ushort)(skillStatusData.Pos / 2);
var offset = (byte)(skillStatusData.Pos & 1);
currVal = GetUInt16Value(PlayerFields.SkillLineRank + field, offset);
currVal = GetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset);
if (newVal != 0)
{
// if skill value is going down, update enchantments before setting the new value
@@ -1133,10 +1131,10 @@ namespace Game.Entities
UpdateSkillEnchantments(id, currVal, (ushort)newVal);
// update step
SetUInt16Value(PlayerFields.SkillLineStep + field, offset, (ushort)step);
SetUInt16Value(ActivePlayerFields.SkillLineStep + field, offset, (ushort)step);
// update value
SetUInt16Value(PlayerFields.SkillLineRank + field, offset, (ushort)newVal);
SetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset, (ushort)maxVal);
SetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset, (ushort)newVal);
SetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset, (ushort)maxVal);
if (skillStatusData.State != SkillState.New)
skillStatusData.State = SkillState.Changed;
@@ -1154,12 +1152,12 @@ namespace Game.Entities
//remove enchantments needing this skill
UpdateSkillEnchantments(id, currVal, 0);
// clear skill fields
SetUInt16Value(PlayerFields.SkillLineId + field, offset, 0);
SetUInt16Value(PlayerFields.SkillLineStep + field, offset, 0);
SetUInt16Value(PlayerFields.SkillLineRank + field, offset, 0);
SetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset, 0);
SetUInt16Value(PlayerFields.SkillLineTempBonus + field, offset, 0);
SetUInt16Value(PlayerFields.SkillLinePermBonus + field, offset, 0);
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);
// mark as deleted or simply remove from map if not saved yet
if (skillStatusData.State != SkillState.New)
@@ -1168,15 +1166,21 @@ namespace Game.Entities
mSkillStatus.Remove(id);
// remove all spells that related to this skill
foreach (var pAbility in CliDB.SkillLineAbilityStorage.Values)
if (pAbility.SkillLine == id)
RemoveSpell(Global.SpellMgr.GetFirstSpellInChain(pAbility.Spell));
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)
{
if (childSkillLine.ParentSkillLineID == id)
SetSkill(childSkillLine.Id, 0, 0, 0);
}
// Clear profession lines
if (GetUInt32Value(PlayerFields.ProfessionSkillLine1) == id)
SetUInt32Value(PlayerFields.ProfessionSkillLine1, 0);
else if (GetUInt32Value(PlayerFields.ProfessionSkillLine1 + 1) == id)
SetUInt32Value(PlayerFields.ProfessionSkillLine1 + 1, 0);
if (GetUInt32Value(ActivePlayerFields.ProfessionSkillLine) == id)
SetUInt32Value(ActivePlayerFields.ProfessionSkillLine, 0);
else if (GetUInt32Value(ActivePlayerFields.ProfessionSkillLine + 1) == id)
SetUInt32Value(ActivePlayerFields.ProfessionSkillLine + 1, 0);
}
}
else if (newVal != 0) //add
@@ -1186,7 +1190,7 @@ namespace Game.Entities
{
var field = (ushort)(i / 2);
var offset = (byte)(i & 1);
if (GetUInt16Value(PlayerFields.SkillLineId + field, offset) == 0)
if (GetUInt16Value(ActivePlayerFields.SkillLineId + field, offset) == 0)
{
var skillEntry = CliDB.SkillLineStorage.LookupByKey(id);
if (skillEntry == null)
@@ -1195,18 +1199,31 @@ namespace Game.Entities
return;
}
SetUInt16Value(PlayerFields.SkillLineId + field, offset, (ushort)id);
if (skillEntry.CategoryID == SkillCategory.Profession)
if (skillEntry.ParentSkillLineID != 0 && skillEntry.ParentTierIndex > 0)
{
if (GetUInt32Value(PlayerFields.ProfessionSkillLine1) == 0)
SetUInt32Value(PlayerFields.ProfessionSkillLine1, id);
else if (GetUInt32Value(PlayerFields.ProfessionSkillLine1 + 1) == 0)
SetUInt32Value(PlayerFields.ProfessionSkillLine1 + 1, id);
SkillRaceClassInfoRecord rcEntry = Global.DB2Mgr.GetSkillRaceClassInfo(skillEntry.ParentSkillLineID, GetRace(), GetClass());
if (rcEntry != null)
{
SkillTiersEntry tier = Global.ObjectMgr.GetSkillTier(rcEntry.SkillTierID);
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]);
}
}
if (skillEntry.CategoryID == SkillCategory.Profession)
{
int freeProfessionSlot = FindProfessionSlotFor(id);
if (freeProfessionSlot != -1)
SetUInt32Value(ActivePlayerFields.ProfessionSkillLine + freeProfessionSlot, id);
}
}
SetUInt16Value(PlayerFields.SkillLineStep + field, offset, (ushort)step);
SetUInt16Value(PlayerFields.SkillLineRank + field, offset, (ushort)newVal);
SetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset, (ushort)maxVal);
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);
UpdateSkillEnchantments(id, currVal, (ushort)newVal);
UpdateCriteria(CriteriaTypes.ReachSkillLevel, id);
@@ -1222,8 +1239,8 @@ namespace Game.Entities
mSkillStatus.Add(id, new SkillStatusData((uint)i, SkillState.New));
// apply skill bonuses
SetUInt16Value(PlayerFields.SkillLineTempBonus + field, offset, 0);
SetUInt16Value(PlayerFields.SkillLinePermBonus + field, offset, 0);
SetUInt16Value(ActivePlayerFields.SkillLineTempBonus + field, offset, 0);
SetUInt16Value(ActivePlayerFields.SkillLinePermBonus + field, offset, 0);
// temporary bonuses
var mModSkill = GetAuraEffectsByType(AuraType.ModSkill);
@@ -1264,22 +1281,22 @@ namespace Game.Entities
foreach (var _spell_idx in bounds)
{
if (_spell_idx.SkillLine != 0)
if (_spell_idx.SkillupSkillLineID != 0)
{
uint SkillValue = GetPureSkillValue((SkillType)_spell_idx.SkillLine);
uint SkillValue = GetPureSkillValue((SkillType)_spell_idx.SkillupSkillLineID);
// Alchemy Discoveries here
SpellInfo spellEntry = Global.SpellMgr.GetSpellInfo(spellid);
if (spellEntry != null && spellEntry.Mechanic == Mechanics.Discovery)
{
uint discoveredSpell = SkillDiscovery.GetSkillDiscoverySpell(_spell_idx.SkillLine, spellid, this);
uint discoveredSpell = SkillDiscovery.GetSkillDiscoverySpell(_spell_idx.SkillupSkillLineID, spellid, this);
if (discoveredSpell != 0)
LearnSpell(discoveredSpell, false);
}
uint craft_skill_gain = _spell_idx.NumSkillUps * WorldConfig.GetUIntValue(WorldCfg.SkillGainCrafting);
return UpdateSkillPro(_spell_idx.SkillLine, SkillGainChance(SkillValue, _spell_idx.TrivialSkillLineRankHigh,
return UpdateSkillPro(_spell_idx.SkillupSkillLineID, SkillGainChance(SkillValue, _spell_idx.TrivialSkillLineRankHigh,
(uint)(_spell_idx.TrivialSkillLineRankHigh + _spell_idx.TrivialSkillLineRankLow) / 2, _spell_idx.TrivialSkillLineRankLow), craft_skill_gain);
}
}
@@ -1299,15 +1316,39 @@ namespace Game.Entities
switch (SkillId)
{
case SkillType.Herbalism:
case SkillType.Herbalism2:
case SkillType.OutlandHerbalism:
case SkillType.NorthrendHerbalism:
case SkillType.CataclysmHerbalism:
case SkillType.PandariaHerbalism:
case SkillType.DraenorHerbalism:
case SkillType.LegionHerbalism:
case SkillType.KulTiranHerbalism:
case SkillType.Jewelcrafting:
case SkillType.Inscription:
return UpdateSkillPro(SkillId, SkillGainChance(SkillValue, RedLevel + 100, RedLevel + 50, RedLevel + 25) * (int)Multiplicator, gathering_skill_gain);
case SkillType.Skinning:
case SkillType.Skinning2:
case SkillType.OutlandSkinning:
case SkillType.NorthrendSkinning:
case SkillType.CataclysmSkinning:
case SkillType.PandariaSkinning:
case SkillType.DraenorSkinning:
case SkillType.LegionSkinning:
case SkillType.KulTiranSkinning:
if (WorldConfig.GetIntValue(WorldCfg.SkillChanceSkinningSteps) == 0)
return UpdateSkillPro(SkillId, SkillGainChance(SkillValue, RedLevel + 100, RedLevel + 50, RedLevel + 25) * (int)Multiplicator, gathering_skill_gain);
else
return UpdateSkillPro(SkillId, (int)(SkillGainChance(SkillValue, RedLevel + 100, RedLevel + 50, RedLevel + 25) * Multiplicator) >> (int)(SkillValue / WorldConfig.GetIntValue(WorldCfg.SkillChanceSkinningSteps)), gathering_skill_gain);
case SkillType.Mining:
case SkillType.Mining2:
case SkillType.OutlandMining:
case SkillType.NorthrendMining:
case SkillType.CataclysmMining:
case SkillType.PandariaMining:
case SkillType.DraenorMining:
case SkillType.LegionMining:
case SkillType.KulTiranMining:
if (WorldConfig.GetIntValue(WorldCfg.SkillChanceMiningSteps) == 0)
return UpdateSkillPro(SkillId, SkillGainChance(SkillValue, RedLevel + 100, RedLevel + 50, RedLevel + 25) * (int)Multiplicator, gathering_skill_gain);
else
@@ -1585,9 +1626,11 @@ namespace Game.Entities
void LearnSkillRewardedSpells(uint skillId, uint skillValue)
{
long raceMask = getRaceMask();
ulong raceMask = getRaceMask();
uint classMask = getClassMask();
foreach (var ability in CliDB.SkillLineAbilityStorage.Values)
List<SkillLineAbilityRecord> skillLineAbilities = Global.DB2Mgr.GetSkillLineAbilitiesBySkill(skillId);
foreach (var ability in skillLineAbilities)
{
if (ability.SkillLine != skillId)
continue;
@@ -1596,11 +1639,11 @@ namespace Game.Entities
if (spellInfo == null)
continue;
if (ability.AcquireMethod != AbilytyLearnType.OnSkillValue && ability.AcquireMethod != AbilytyLearnType.OnSkillLearn)
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).
if (skillId == (uint)SkillType.Riding && (ability.AcquireMethod != AbilytyLearnType.OnSkillLearn || ability.NumSkillUps != 1))
if (skillId == (uint)SkillType.Riding && (ability.AcquireMethod != AbilityLearnType.OnSkillLearn || ability.NumSkillUps != 1))
continue;
// Check race if set
@@ -1616,7 +1659,7 @@ namespace Game.Entities
continue;
// need unlearn spell
if (skillValue < ability.MinSkillLineRank && ability.AcquireMethod == AbilytyLearnType.OnSkillValue)
if (skillValue < ability.MinSkillLineRank && ability.AcquireMethod == AbilityLearnType.OnSkillValue)
RemoveSpell(ability.Spell);
// need learn
else if (!IsInWorld)
@@ -1627,6 +1670,49 @@ namespace Game.Entities
}
}
int FindProfessionSlotFor(uint skillId)
{
SkillLineRecord skillEntry = CliDB.SkillLineStorage.LookupByKey(skillId);
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;
}
// if there is no same profession, find any free slot
for (var slot = professionsBegin; slot < professionsEnd; ++slot)
if (GetUInt32Value(slot) == 0)
return slot - professionsBegin;
return -1;
}
void RemoveItemDependentAurasAndCasts(Item pItem)
{
foreach (var pair in GetOwnedAuras())
@@ -1920,19 +2006,15 @@ namespace Game.Entities
break;
case SkillRangeType.Rank:
{
ushort rank = 1;
if (GetClass() == Class.Deathknight && skillId == SkillType.FirstAid)
rank = 4;
SkillTiersEntry tier = Global.ObjectMgr.GetSkillTier(rcInfo.SkillTierID);
ushort maxValue = (ushort)tier.Value[Math.Max(rank - 1, 0)];
ushort maxValue = (ushort)tier.Value[0];
ushort skillValue = 1;
if (rcInfo.Flags.HasAnyFlag(SkillRaceClassInfoFlags.AlwaysMaxValue))
skillValue = maxValue;
else if (GetClass() == Class.Deathknight)
skillValue = (ushort)Math.Min(Math.Max(1, (getLevel() - 1) * 5), maxValue);
SetSkill(skillId, rank, skillValue, maxValue);
SetSkill(skillId, 1, skillValue, maxValue);
break;
}
default:
@@ -1945,7 +2027,7 @@ namespace Game.Entities
SendKnownSpells knownSpells = new SendKnownSpells();
knownSpells.InitialLogin = false; // @todo
foreach (var spell in m_spells)
foreach (var spell in m_spells.ToList())
{
if (spell.Value.State == PlayerSpellState.Removed)
continue;
@@ -2484,7 +2566,7 @@ namespace Game.Entities
continue;
// Runeforging special case
if ((_spell_idx.AcquireMethod == AbilytyLearnType.OnSkillLearn && !HasSkill((SkillType)_spell_idx.SkillLine))
if ((_spell_idx.AcquireMethod == AbilityLearnType.OnSkillLearn && !HasSkill((SkillType)_spell_idx.SkillLine))
|| ((_spell_idx.SkillLine == (int)SkillType.Runeforging) && _spell_idx.TrivialSkillLineRankHigh == 0))
{
SkillRaceClassInfoRecord rcInfo = Global.DB2Mgr.GetSkillRaceClassInfo(_spell_idx.SkillLine, GetRace(), GetClass());
@@ -3157,10 +3239,10 @@ namespace Game.Entities
// Check no reagent use mask
FlagArray128 noReagentMask = new FlagArray128();
noReagentMask[0] = GetUInt32Value(PlayerFields.NoReagentCost1);
noReagentMask[1] = GetUInt32Value(PlayerFields.NoReagentCost1 + 1);
noReagentMask[2] = GetUInt32Value(PlayerFields.NoReagentCost1 + 2);
noReagentMask[3] = GetUInt32Value(PlayerFields.NoReagentCost1 + 3);
noReagentMask[0] = GetUInt32Value(ActivePlayerFields.NoReagentCost);
noReagentMask[1] = GetUInt32Value(ActivePlayerFields.NoReagentCost + 1);
noReagentMask[2] = GetUInt32Value(ActivePlayerFields.NoReagentCost + 2);
noReagentMask[3] = GetUInt32Value(ActivePlayerFields.NoReagentCost + 3);
if (spellInfo.SpellFamilyFlags & noReagentMask)
return true;
+14 -53
View File
@@ -33,7 +33,7 @@ namespace Game.Entities
if (level < PlayerConst.MinSpecializationLevel)
ResetTalentSpecialization();
uint talentTiers = CalculateTalentsTiers();
uint talentTiers = (uint)Global.DB2Mgr.GetNumTalentsAtLevel(level, GetClass());
if (level < 15)
{
// Remove all talent points
@@ -50,7 +50,7 @@ namespace Game.Entities
}
}
SetUInt32Value(PlayerFields.MaxTalentTiers, talentTiers);
SetUInt32Value(ActivePlayerFields.MaxTalentTiers, talentTiers);
if (!GetSession().PlayerLoading())
SendTalentsInfoData(); // update at client
@@ -127,7 +127,7 @@ namespace Game.Entities
return TalentLearnResult.FailedUnknown;
// check if we have enough talent points
if (talentInfo.TierID >= GetUInt32Value(PlayerFields.MaxTalentTiers))
if (talentInfo.TierID >= GetUInt32Value(ActivePlayerFields.MaxTalentTiers))
return TalentLearnResult.FailedUnknown;
// TODO: prevent changing talents that are on cooldown
@@ -244,8 +244,8 @@ namespace Game.Entities
void SetActiveTalentGroup(byte group) { _specializationInfo.ActiveGroup = group; }
// Loot Spec
public void SetLootSpecId(uint id) { SetUInt32Value(PlayerFields.LootSpecId, id); }
uint GetLootSpecId() { return GetUInt32Value(PlayerFields.LootSpecId); }
public void SetLootSpecId(uint id) { SetUInt32Value(ActivePlayerFields.LootSpecId, id); }
uint GetLootSpecId() { return GetUInt32Value(ActivePlayerFields.LootSpecId); }
public uint GetDefaultSpecId()
{
@@ -312,15 +312,6 @@ namespace Game.Entities
foreach (var talentInfo in CliDB.PvpTalentStorage.Values)
{
// unlearn only talents for character class
// some spell learned by one class as normal spells or know at creation but another class learn it as talent,
// to prevent unexpected lost normal learned spell skip another class talents
if (talentInfo.ClassID != 0 && talentInfo.ClassID != (int)GetClass())
continue;
if (talentInfo.SpellID == 0)
continue;
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(talentInfo.SpellID);
if (spellInfo == null)
continue;
@@ -364,17 +355,16 @@ namespace Game.Entities
}
}
foreach (var talentInfo in CliDB.PvpTalentStorage.Values)
for (byte slot = 0; slot < PlayerConst.MaxPvpTalentSlots; ++slot)
{
// learn only talents for character class (or x-class talents)
if (talentInfo.ClassID != 0 && talentInfo.ClassID != (int)GetClass())
PvpTalentRecord talentInfo = CliDB.PvpTalentStorage.LookupByKey(GetPvpTalentMap(GetActiveTalentGroup())[slot]);
if (talentInfo == null)
continue;
if (talentInfo.SpellID == 0)
continue;
if (HasPvpTalent(talentInfo.Id, GetActiveTalentGroup()))
AddPvpTalent(talentInfo, GetActiveTalentGroup(), true);
AddPvpTalent(talentInfo, GetActiveTalentGroup(), slot);
}
LearnSpecializationSpells();
@@ -558,9 +548,6 @@ namespace Game.Entities
continue;
}
if (talentInfo.ClassID != (uint)GetClass())
continue;
SpellInfo spellEntry = Global.SpellMgr.GetSpellInfo(talentInfo.SpellID);
if (spellEntry == null)
{
@@ -571,21 +558,18 @@ namespace Game.Entities
groupInfoPkt.TalentIDs.Add((ushort)pair.Key);
}
foreach (var pair in pvpTalents)
for (byte slot = 0; slot < PlayerConst.MaxPvpTalentSlots; ++slot)
{
if (pair.Value == PlayerSpellState.Removed)
if (pvpTalents[slot] == 0)
continue;
PvpTalentRecord talentInfo = CliDB.PvpTalentStorage.LookupByKey(pair.Key);
PvpTalentRecord talentInfo = CliDB.PvpTalentStorage.LookupByKey(pvpTalents[slot]);
if (talentInfo == null)
{
Log.outError(LogFilter.Player, $"Player.SendTalentsInfoData: Player '{GetName()}' ({GetGUID().ToString()}) has unknown pvp talent id: {pair.Key}");
Log.outError(LogFilter.Player, $"Player.SendTalentsInfoData: Player '{GetName()}' ({GetGUID().ToString()}) has unknown pvp talent id: {pvpTalents[slot]}");
continue;
}
if (talentInfo.ClassID != 0 && talentInfo.ClassID != (int)GetClass())
continue;
SpellInfo spellEntry = Global.SpellMgr.GetSpellInfo(talentInfo.SpellID);
if (spellEntry == null)
{
@@ -593,7 +577,7 @@ namespace Game.Entities
continue;
}
groupInfoPkt.PvPTalentIDs.Add((ushort)pair.Key);
groupInfoPkt.PvPTalentIDs.Add((ushort)pvpTalents[slot]);
}
packet.Info.TalentGroups.Add(groupInfoPkt);
@@ -610,28 +594,5 @@ namespace Game.Entities
respecWipeConfirm.RespecType = SpecResetType.Talents;
SendPacket(respecWipeConfirm);
}
uint CalculateTalentsTiers()
{
uint[] rowLevels = new uint[0];
switch (GetClass())
{
case Class.Deathknight:
rowLevels = new uint[] { 57, 58, 59, 60, 75, 90, 100 };
break;
case Class.DemonHunter:
rowLevels = new uint[] { 99, 100, 102, 104, 106, 108, 110 };
break;
default:
rowLevels = new uint[] { 15, 30, 45, 60, 75, 90, 100 };
break;
}
for (uint i = PlayerConst.MaxTalentTiers; i != 0; --i)
if (getLevel() >= rowLevels[i - 1])
return i;
return 0;
}
}
}
+100 -102
View File
@@ -48,8 +48,8 @@ namespace Game.Entities
objectTypeMask |= TypeMask.Player;
objectTypeId = TypeId.Player;
valuesCount = (int)PlayerFields.End;
_dynamicValuesCount = (int)PlayerDynamicFields.End;
valuesCount = (int)ActivePlayerFields.End;
_dynamicValuesCount = (int)ActivePlayerDynamicFields.End;
Session = session;
// players always accept
@@ -214,7 +214,7 @@ namespace Game.Entities
SetFlag(UnitFields.Flags2, UnitFlags2.RegeneratePower);
SetFloatValue(UnitFields.HoverHeight, 1.0f); // default for players in 3.0.3
SetUInt32Value(PlayerFields.WatchedFactionIndex, 0xFFFFFFFF); // -1 is default value
SetUInt32Value(ActivePlayerFields.WatchedFactionIndex, 0xFFFFFFFF); // -1 is default value
SetByteValue(PlayerFields.Bytes, PlayerFieldOffsets.BytesOffsetSkinId, createInfo.Skin);
SetByteValue(PlayerFields.Bytes, PlayerFieldOffsets.BytesOffsetFaceId, createInfo.Face);
@@ -223,23 +223,23 @@ namespace Game.Entities
SetByteValue(PlayerFields.Bytes2, PlayerFieldOffsets.Bytes2OffsetFacialStyle, createInfo.FacialHairStyle);
for (byte i = 0; i < PlayerConst.CustomDisplaySize; ++i)
SetByteValue(PlayerFields.Bytes2, (byte)(PlayerFieldOffsets.Bytes2OffsetCustomDisplayOption + i), createInfo.CustomDisplay[i]);
SetUInt32Value(PlayerFields.RestInfo + PlayerFieldOffsets.RestStateXp, (uint)((GetSession().IsARecruiter() || GetSession().GetRecruiterId() != 0) ? PlayerRestState.RAFLinked : PlayerRestState.NotRAFLinked));
SetUInt32Value(PlayerFields.RestInfo + PlayerFieldOffsets.RestStateHonor, (uint)PlayerRestState.NotRAFLinked);
SetUInt32Value(ActivePlayerFields.RestInfo + PlayerFieldOffsets.RestStateXp, (uint)((GetSession().IsARecruiter() || GetSession().GetRecruiterId() != 0) ? PlayerRestState.RAFLinked : PlayerRestState.NotRAFLinked));
SetUInt32Value(ActivePlayerFields.RestInfo + PlayerFieldOffsets.RestStateHonor, (uint)PlayerRestState.NotRAFLinked);
SetByteValue(PlayerFields.Bytes3, PlayerFieldOffsets.Bytes3OffsetGender, (byte)createInfo.Sex);
SetByteValue(PlayerFields.Bytes4, PlayerFieldOffsets.Bytes4OffsetArenaFaction, 0);
SetInventorySlotCount(InventorySlots.DefaultSize);
SetGuidValue(ObjectFields.Data, ObjectGuid.Empty);
SetGuidValue(UnitFields.GuildGuid, ObjectGuid.Empty);
SetUInt32Value(PlayerFields.GuildRank, 0);
SetGuildLevel(0);
SetUInt32Value(PlayerFields.GuildTimestamp, 0);
for (int i = 0; i < PlayerConst.KnowTitlesSize; ++i)
SetUInt64Value(PlayerFields.KnownTitles + i, 0); // 0=disabled
SetUInt64Value(ActivePlayerFields.KnownTitles + i, 0); // 0=disabled
SetUInt32Value(PlayerFields.ChosenTitle, 0);
SetUInt32Value(PlayerFields.Kills, 0);
SetUInt32Value(PlayerFields.LifetimeHonorableKills, 0);
SetUInt32Value(ActivePlayerFields.Kills, 0);
SetUInt32Value(ActivePlayerFields.LifetimeHonorableKills, 0);
// set starting level
uint start_level = WorldConfig.GetUIntValue(WorldCfg.StartPlayerLevel);
@@ -274,7 +274,7 @@ namespace Game.Entities
InitRunes();
SetUInt64Value(PlayerFields.Coinage, WorldConfig.GetUIntValue(WorldCfg.StartPlayerMoney));
SetUInt64Value(ActivePlayerFields.Coinage, WorldConfig.GetUIntValue(WorldCfg.StartPlayerMoney));
SetCurrency(CurrencyTypes.ApexisCrystals, WorldConfig.GetUIntValue(WorldCfg.CurrencyStartApexisCrystals));
SetCurrency(CurrencyTypes.JusticePoints, WorldConfig.GetUIntValue(WorldCfg.CurrencyStartJusticePoints));
@@ -282,7 +282,7 @@ namespace Game.Entities
if (WorldConfig.GetBoolValue(WorldCfg.StartAllExplored))
{
for (ushort i = 0; i < PlayerConst.ExploredZonesSize; i++)
SetFlag(PlayerFields.ExploredZones1 + i, 0xFFFFFFFF);
SetFlag(ActivePlayerFields.ExploredZones + i, 0xFFFFFFFF);
}
//Reputations if "StartAllReputation" is enabled, -- TODO: Fix this in a better way
@@ -741,6 +741,18 @@ namespace Game.Entities
if (pet != null && !pet.IsWithinDistInMap(this, GetMap().GetVisibilityRange()) && !pet.isPossessed())
RemovePet(pet, PetSaveMode.NotInSlot, true);
if (IsAlive())
{
if (m_hostileReferenceCheckTimer <= diff)
{
m_hostileReferenceCheckTimer = 15 * Time.InMilliseconds;
if (!GetMap().IsDungeon())
getHostileRefManager().deleteReferencesOutOfRange(GetVisibilityRange());
}
else
m_hostileReferenceCheckTimer -= diff;
}
//we should execute delayed teleports only for alive(!) players
//because we don't want player's ghost teleported from graveyard
if (IsHasDelayedTeleport() && IsAlive())
@@ -783,7 +795,7 @@ namespace Game.Entities
if (IsAlive() && !oldIsAlive)
//clear aura case after resurrection by another way (spells will be applied before next death)
ClearDynamicValue(PlayerDynamicFields.SelfResSpells);
ClearDynamicValue(ActivePlayerDynamicFields.SelfResSpells);
}
public override void DestroyForPlayer(Player target)
@@ -1662,15 +1674,15 @@ namespace Game.Entities
continue;
if (quest.IsDaily())
rep = CalculateReputationGain(ReputationSource.DailyQuest, GetQuestLevel(quest), rep, (int)quest.RewardFactionId[i], noQuestBonus);
rep = CalculateReputationGain(ReputationSource.DailyQuest, (uint)GetQuestLevel(quest), rep, (int)quest.RewardFactionId[i], noQuestBonus);
else if (quest.IsWeekly())
rep = CalculateReputationGain(ReputationSource.WeeklyQuest, GetQuestLevel(quest), rep, (int)quest.RewardFactionId[i], noQuestBonus);
rep = CalculateReputationGain(ReputationSource.WeeklyQuest, (uint)GetQuestLevel(quest), rep, (int)quest.RewardFactionId[i], noQuestBonus);
else if (quest.IsMonthly())
rep = CalculateReputationGain(ReputationSource.MonthlyQuest, GetQuestLevel(quest), rep, (int)quest.RewardFactionId[i], noQuestBonus);
rep = CalculateReputationGain(ReputationSource.MonthlyQuest, (uint)GetQuestLevel(quest), rep, (int)quest.RewardFactionId[i], noQuestBonus);
else if (quest.IsRepeatable())
rep = CalculateReputationGain(ReputationSource.RepeatableQuest, GetQuestLevel(quest), rep, (int)quest.RewardFactionId[i], noQuestBonus);
rep = CalculateReputationGain(ReputationSource.RepeatableQuest, (uint)GetQuestLevel(quest), rep, (int)quest.RewardFactionId[i], noQuestBonus);
else
rep = CalculateReputationGain(ReputationSource.Quest, GetQuestLevel(quest), rep, (int)quest.RewardFactionId[i], noQuestBonus);
rep = CalculateReputationGain(ReputationSource.Quest, (uint)GetQuestLevel(quest), rep, (int)quest.RewardFactionId[i], noQuestBonus);
bool noSpillover = Convert.ToBoolean(quest.RewardReputationMask & (1 << i));
GetReputationMgr().ModifyReputation(factionEntry, rep, noSpillover);
@@ -4180,7 +4192,7 @@ namespace Game.Entities
if (m_unitMovedByMe == obj)
return true;
ObjectGuid guid = GetGuidValue(PlayerFields.Farsight);
ObjectGuid guid = GetGuidValue(ActivePlayerFields.Farsight);
if (!guid.IsEmpty())
if (obj.GetGUID() == guid)
return true;
@@ -4542,7 +4554,7 @@ namespace Game.Entities
setDeathState(DeathState.Corpse);
SetUInt32Value(ObjectFields.DynamicFlags, 0);
ApplyModFlag(PlayerFields.LocalFlags, PlayerLocalFlags.ReleaseTimer, !CliDB.MapStorage.LookupByKey(GetMapId()).Instanceable() && !HasAuraType(AuraType.PreventResurrection));
ApplyModFlag(ActivePlayerFields.LocalFlags, PlayerLocalFlags.ReleaseTimer, !CliDB.MapStorage.LookupByKey(GetMapId()).Instanceable() && !HasAuraType(AuraType.PreventResurrection));
// 6 minutes until repop at graveyard
m_deathTimer = 6 * Time.Minute * Time.InMilliseconds;
@@ -5009,6 +5021,7 @@ namespace Game.Entities
displayPlayerChoice.CloseChoiceFrame = false;
displayPlayerChoice.HideWarboardHeader = playerChoice.HideWarboardHeader;
displayPlayerChoice.KeepOpenAfterChoice = playerChoice.KeepOpenAfterChoice;
for (var i = 0; i < playerChoice.Responses.Count; ++i)
{
@@ -5017,6 +5030,9 @@ namespace Game.Entities
playerChoiceResponse.ResponseID = playerChoiceResponseTemplate.ResponseId;
playerChoiceResponse.ChoiceArtFileID = playerChoiceResponseTemplate.ChoiceArtFileId;
playerChoiceResponse.Flags = playerChoiceResponseTemplate.Flags;
playerChoiceResponse.WidgetSetID = playerChoiceResponseTemplate.WidgetSetID;
playerChoiceResponse.GroupID = playerChoiceResponseTemplate.GroupID;
playerChoiceResponse.Answer = playerChoiceResponseTemplate.Answer;
playerChoiceResponse.Header = playerChoiceResponseTemplate.Header;
playerChoiceResponse.Description = playerChoiceResponseTemplate.Description;
@@ -5173,7 +5189,7 @@ namespace Game.Entities
public int GetTeamId() { return m_team == Team.Alliance ? TeamId.Alliance : TeamId.Horde; }
//Money
public ulong GetMoney() { return GetUInt64Value(PlayerFields.Coinage); }
public ulong GetMoney() { return GetUInt64Value(ActivePlayerFields.Coinage); }
public bool HasEnoughMoney(ulong amount) { return GetMoney() >= amount; }
public bool HasEnoughMoney(long amount)
{
@@ -5205,7 +5221,7 @@ namespace Game.Entities
}
public void SetMoney(ulong value)
{
SetUInt64Value(PlayerFields.Coinage, value);
SetUInt64Value(ActivePlayerFields.Coinage, value);
MoneyChanged((uint)value);
UpdateCriteria(CriteriaTypes.HighestGoldValueOwned);
}
@@ -5246,19 +5262,18 @@ namespace Game.Entities
public void SetInGuild(ulong guildId)
{
if (guildId != 0)
SetGuidValue(ObjectFields.Data, ObjectGuid.Create(HighGuid.Guild, guildId));
SetGuidValue(UnitFields.GuildGuid, ObjectGuid.Create(HighGuid.Guild, guildId));
else
SetGuidValue(ObjectFields.Data, ObjectGuid.Empty);
SetGuidValue(UnitFields.GuildGuid, ObjectGuid.Empty);
ApplyModFlag(PlayerFields.Flags, PlayerFlags.GuildLevelEnabled, guildId != 0);
SetUInt16Value(ObjectFields.Type, 1, (ushort)(guildId != 0 ? 1 : 0));
}
public void SetGuildRank(uint rankId) { SetUInt32Value(PlayerFields.GuildRank, rankId); }
byte GetGuildRank() { return (byte)GetUInt32Value(PlayerFields.GuildRank); }
public void SetGuildLevel(uint level) { SetUInt32Value(PlayerFields.GuildLevel, level); }
uint GetGuildLevel() { return GetUInt32Value(PlayerFields.GuildLevel); }
public void SetGuildIdInvited(ulong GuildId) { m_GuildIdInvited = GuildId; }
public uint GetGuildId() { return GetUInt32Value(ObjectFields.Data); }
public uint GetGuildId() { return GetUInt32Value(UnitFields.GuildGuid); }
public Guild GetGuild()
{
uint guildId = GetGuildId();
@@ -5270,7 +5285,7 @@ namespace Game.Entities
return GetGuildId() != 0 ? Global.GuildMgr.GetGuildById(GetGuildId()).GetName() : "";
}
public void SetFreePrimaryProfessions(uint profs) { SetUInt32Value(PlayerFields.CharacterPoints, profs); }
public void SetFreePrimaryProfessions(uint profs) { SetUInt32Value(ActivePlayerFields.CharacterPoints, profs); }
public void GiveLevel(uint level)
{
var oldLevel = getLevel();
@@ -5301,13 +5316,12 @@ namespace Game.Entities
for (Stats i = Stats.Strength; i < Stats.Max; ++i)
packet.StatDelta[(int)i] = info.stats[(int)i] - (int)GetCreateStat(i);
uint[] rowLevels = (GetClass() != Class.Deathknight) ? PlayerConst.DefaultTalentRowLevels : PlayerConst.DKTalentRowLevels;
packet.Cp = rowLevels.Any(p => p == level) ? 1 : 0;
packet.NumNewTalents = (int)(Global.DB2Mgr.GetNumTalentsAtLevel(level, GetClass()) - Global.DB2Mgr.GetNumTalentsAtLevel(oldLevel, GetClass()));
packet.NumNewPvpTalentSlots = Global.DB2Mgr.GetPvpTalentNumSlotsAtLevel(level, GetClass()) - Global.DB2Mgr.GetPvpTalentNumSlotsAtLevel(oldLevel, GetClass());
SendPacket(packet);
SetUInt32Value(PlayerFields.NextLevelXp, Global.ObjectMgr.GetXPForLevel(level));
SetUInt32Value(ActivePlayerFields.NextLevelXp, Global.ObjectMgr.GetXPForLevel(level));
//update level, max level of skills
m_PlayedTimeLevel = 0; // Level Played Time reset
@@ -5377,8 +5391,8 @@ namespace Game.Entities
{
++m_grantableLevels;
if (!HasByteFlag(PlayerFields.FieldBytes, PlayerFieldOffsets.FieldBytesOffsetRafGrantableLevel, 0x01))
SetByteFlag(PlayerFields.FieldBytes, PlayerFieldOffsets.FieldBytesOffsetRafGrantableLevel, 0x01);
if (!HasByteFlag(ActivePlayerFields.Bytes, PlayerFieldOffsets.FieldBytesOffsetRafGrantableLevel, 0x01))
SetByteFlag(ActivePlayerFields.Bytes, PlayerFieldOffsets.FieldBytesOffsetRafGrantableLevel, 0x01);
}
}
}
@@ -5449,6 +5463,8 @@ namespace Game.Entities
Log.outError(LogFilter.Player, "Player {0} ({1}) has invalid gender {2}", GetName(), GetGUID().ToString(), gender);
return;
}
SetUInt32Value(UnitFields.StateAnimId, (uint)CliDB.AnimationDataStorage.Count);
}
//Creature
@@ -5782,8 +5798,8 @@ namespace Game.Entities
PlayerLevelInfo info = Global.ObjectMgr.GetPlayerLevelInfo(GetRace(), GetClass(), getLevel());
SetUInt32Value(PlayerFields.MaxLevel, WorldConfig.GetUIntValue(WorldCfg.MaxPlayerLevel));
SetUInt32Value(PlayerFields.NextLevelXp, Global.ObjectMgr.GetXPForLevel(getLevel()));
SetUInt32Value(ActivePlayerFields.MaxLevel, WorldConfig.GetUIntValue(WorldCfg.MaxPlayerLevel));
SetUInt32Value(ActivePlayerFields.NextLevelXp, Global.ObjectMgr.GetXPForLevel(getLevel()));
// reset before any aura state sources (health set/aura apply)
SetUInt32Value(UnitFields.AuraState, 0);
@@ -5813,26 +5829,26 @@ namespace Game.Entities
//set create powers
SetCreateMana(basemana);
SetArmor((int)(GetCreateStat(Stats.Agility) * 2));
SetArmor((int)(GetCreateStat(Stats.Agility) * 2), 0);
InitStatBuffMods();
//reset rating fields values
for (var index = PlayerFields.CombatRating1; index < PlayerFields.CombatRating1 + (int)CombatRating.Max; ++index)
SetUInt32Value(index, 0);
for (var index = 0; index < (int)CombatRating.Max; ++index)
SetUInt32Value(ActivePlayerFields.CombatRating + index, 0);
SetUInt32Value(PlayerFields.ModHealingDonePos, 0);
SetFloatValue(PlayerFields.ModHealingPct, 1.0f);
SetFloatValue(PlayerFields.ModHealingDonePct, 1.0f);
SetFloatValue(PlayerFields.ModPeriodicHealingDonePercent, 1.0f);
SetUInt32Value(ActivePlayerFields.ModHealingDonePos, 0);
SetFloatValue(ActivePlayerFields.ModHealingPct, 1.0f);
SetFloatValue(ActivePlayerFields.ModHealingDonePct, 1.0f);
SetFloatValue(ActivePlayerFields.ModPeriodicHealingDonePercent, 1.0f);
for (byte i = 0; i < 7; ++i)
{
SetInt32Value(PlayerFields.ModDamageDoneNeg + i, 0);
SetInt32Value(PlayerFields.ModDamageDonePos + i, 0);
SetFloatValue(PlayerFields.ModDamageDonePct + i, 1.0f);
SetInt32Value(ActivePlayerFields.ModDamageDoneNeg + i, 0);
SetInt32Value(ActivePlayerFields.ModDamageDonePos + i, 0);
SetFloatValue(ActivePlayerFields.ModDamageDonePct + i, 1.0f);
}
SetFloatValue(PlayerFields.ModSpellPowerPct, 1.0f);
SetFloatValue(ActivePlayerFields.ModSpellPowerPct, 1.0f);
//reset attack power, damage and attack speed fields
for (byte i = 0; i < (int)WeaponAttackType.Max; ++i)
@@ -5846,8 +5862,8 @@ namespace Game.Entities
SetFloatValue(UnitFields.MaxRangedDamage, 0.0f);
for (var i = 0; i < 3; ++i)
{
SetFloatValue(PlayerFields.WeaponDmgMultipliers + i, 1.0f);
SetFloatValue(PlayerFields.WeaponAtkSpeedMultipliers + i, 1.0f);
SetFloatValue(ActivePlayerFields.WeaponDmgMultipliers + i, 1.0f);
SetFloatValue(ActivePlayerFields.WeaponAtkSpeedMultipliers + i, 1.0f);
}
SetInt32Value(UnitFields.AttackPower, 0);
@@ -5856,44 +5872,42 @@ namespace Game.Entities
SetFloatValue(UnitFields.RangedAttackPowerMultiplier, 0.0f);
// Base crit values (will be recalculated in UpdateAllStats() at loading and in _ApplyAllStatBonuses() at reset
SetFloatValue(PlayerFields.CritPercentage, 0.0f);
SetFloatValue(PlayerFields.OffhandCritPercentage, 0.0f);
SetFloatValue(PlayerFields.RangedCritPercentage, 0.0f);
SetFloatValue(ActivePlayerFields.CritPercentage, 0.0f);
SetFloatValue(ActivePlayerFields.OffhandCritPercentage, 0.0f);
SetFloatValue(ActivePlayerFields.RangedCritPercentage, 0.0f);
// Init spell schools (will be recalculated in UpdateAllStats() at loading and in _ApplyAllStatBonuses() at reset
SetFloatValue(PlayerFields.SpellCritPercentage1, 0.0f);
SetFloatValue(ActivePlayerFields.SpellCritPercentage1, 0.0f);
SetFloatValue(PlayerFields.ParryPercentage, 0.0f);
SetFloatValue(PlayerFields.BlockPercentage, 0.0f);
SetFloatValue(ActivePlayerFields.ParryPercentage, 0.0f);
SetFloatValue(ActivePlayerFields.BlockPercentage, 0.0f);
// Static 30% damage blocked
SetUInt32Value(PlayerFields.ShieldBlock, 30);
SetUInt32Value(ActivePlayerFields.ShieldBlock, 30);
// Dodge percentage
SetFloatValue(PlayerFields.DodgePercentage, 0.0f);
SetFloatValue(ActivePlayerFields.DodgePercentage, 0.0f);
// set armor (resistance 0) to original value (create_agility*2)
SetArmor((int)(GetCreateStat(Stats.Agility) * 2));
SetResistanceBuffMods(SpellSchools.Normal, true, 0.0f);
SetResistanceBuffMods(SpellSchools.Normal, false, 0.0f);
SetArmor((int)(GetCreateStat(Stats.Agility) * 2), 0);
SetBonusResistanceMod(SpellSchools.Normal, 0);
// set other resistance to original value (0)
for (var spellSchool = SpellSchools.Holy; spellSchool < SpellSchools.Max; ++spellSchool)
{
SetResistance(spellSchool, 0);
SetResistanceBuffMods(spellSchool, true, 0.0f);
SetResistanceBuffMods(spellSchool, false, 0.0f);
SetBonusResistanceMod(spellSchool, 0);
}
SetUInt32Value(PlayerFields.ModTargetResistance, 0);
SetUInt32Value(PlayerFields.ModTargetPhysicalResistance, 0);
SetUInt32Value(ActivePlayerFields.ModTargetResistance, 0);
SetUInt32Value(ActivePlayerFields.ModTargetPhysicalResistance, 0);
for (var i = 0; i < (int)SpellSchools.Max; ++i)
{
SetUInt32Value(UnitFields.PowerCostModifier + i, 0);
SetFloatValue(UnitFields.PowerCostMultiplier + i, 0.0f);
}
// Reset no reagent cost field
for (byte i = 0; i < 3; ++i)
SetUInt32Value(PlayerFields.NoReagentCost1 + i, 0);
for (byte i = 0; i < 4; ++i)
SetUInt32Value(ActivePlayerFields.NoReagentCost + i, 0);
// Init data for form but skip reapply item mods for form
InitDataForForm(reapplyMods);
@@ -5925,9 +5939,9 @@ namespace Game.Entities
RemoveByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, (UnitBytes2Flags.FFAPvp | UnitBytes2Flags.Sanctuary));
// restore if need some important flags
SetByteValue(PlayerFields.FieldBytes2, PlayerFieldOffsets.FieldBytes2OffsetIgnorePowerRegenPredictionMask, 0);
SetByteValue(PlayerFields.FieldBytes2, PlayerFieldOffsets.FieldBytes2OffsetAuraVision, 0);
SetByteValue(PlayerFields.FieldBytes2, 3, 0);
SetByteValue(ActivePlayerFields.Bytes2, PlayerFieldOffsets.FieldBytes2OffsetIgnorePowerRegenPredictionMask, 0);
SetByteValue(ActivePlayerFields.Bytes2, PlayerFieldOffsets.FieldBytes2OffsetAuraVision, 0);
SetByteValue(ActivePlayerFields.Bytes2, 3, 0);
if (reapplyMods) // reapply stats values only on .reset stats (level) command
_ApplyAllStatBonuses();
@@ -6258,11 +6272,11 @@ namespace Game.Entities
}
uint val = 1u << (areaEntry.AreaBit % 32);
uint currFields = GetUInt32Value(PlayerFields.ExploredZones1 + offset);
uint currFields = GetUInt32Value(ActivePlayerFields.ExploredZones + offset);
if (!Convert.ToBoolean(currFields & val))
{
SetUInt32Value(PlayerFields.ExploredZones1 + offset, currFields | val);
SetUInt32Value(ActivePlayerFields.ExploredZones + offset, currFields | val);
UpdateCriteria(CriteriaTypes.ExploreArea);
@@ -6488,15 +6502,15 @@ namespace Game.Entities
void SetXP(uint xp)
{
SetUInt32Value(PlayerFields.Xp, xp);
SetUInt32Value(ActivePlayerFields.Xp, xp);
int playerLevelDelta = 0;
// If XP < 50%, player should see scaling creature with -1 level except for level max
if (getLevel() < SharedConst.MaxLevel && xp < (GetUInt32Value(PlayerFields.NextLevelXp) / 2))
if (getLevel() < SharedConst.MaxLevel && xp < (GetUInt32Value(ActivePlayerFields.NextLevelXp) / 2))
playerLevelDelta = -1;
SetInt32Value(PlayerFields.ScalingLevelDelta, playerLevelDelta);
SetInt32Value(UnitFields.ScalingLevelDelta, playerLevelDelta);
}
public void GiveXP(uint xp, Unit victim, float group_rate = 1.0f)
@@ -6539,8 +6553,8 @@ namespace Game.Entities
packet.ReferAFriendBonusType = (byte)(recruitAFriend ? 1 : 0);
SendPacket(packet);
uint curXP = GetUInt32Value(PlayerFields.Xp);
uint nextLvlXP = GetUInt32Value(PlayerFields.NextLevelXp);
uint curXP = GetUInt32Value(ActivePlayerFields.Xp);
uint nextLvlXP = GetUInt32Value(ActivePlayerFields.NextLevelXp);
uint newXP = curXP + xp + bonus_xp;
while (newXP >= nextLvlXP && level < WorldConfig.GetIntValue(WorldCfg.MaxPlayerLevel))
@@ -6551,7 +6565,7 @@ namespace Game.Entities
GiveLevel(level + 1);
level = getLevel();
nextLvlXP = GetUInt32Value(PlayerFields.NextLevelXp);
nextLvlXP = GetUInt32Value(ActivePlayerFields.NextLevelXp);
}
SetXP(newXP);
@@ -6758,22 +6772,6 @@ namespace Game.Entities
return false;
}
// check node starting pos data set case if provided
if (node.Pos.X != 0.0f || node.Pos.Y != 0.0f || node.Pos.Z != 0.0f)
{
if (node.ContinentID != GetMapId() || !IsInDist(node.Pos.X, node.Pos.Y, node.Pos.Z, 2 * SharedConst.InteractionDistance))
{
GetSession().SendActivateTaxiReply(ActivateTaxiReply.TooFarAway);
return false;
}
}
// node must have pos if taxi master case (npc != NULL)
else if (npc != null)
{
GetSession().SendActivateTaxiReply(ActivateTaxiReply.UnspecifiedServerError);
return false;
}
// Prepare to flight start now
// stop combat at start taxi flight if any
@@ -7084,7 +7082,7 @@ namespace Game.Entities
}
public bool IsSpellFitByClassAndRace(uint spell_id)
{
long racemask = getRaceMask();
ulong racemask = getRaceMask();
uint classmask = getClassMask();
var bounds = Global.SpellMgr.GetSkillLineAbilityMapBounds(spell_id);
@@ -7113,8 +7111,8 @@ namespace Game.Entities
{
SetFreePrimaryProfessions(WorldConfig.GetUIntValue(WorldCfg.MaxPrimaryTradeSkill));
}
public uint GetFreePrimaryProfessionPoints() { return GetUInt32Value(PlayerFields.CharacterPoints); }
void SetFreePrimaryProfessions(ushort profs) { SetUInt32Value(PlayerFields.CharacterPoints, profs); }
public uint GetFreePrimaryProfessionPoints() { return GetUInt32Value(ActivePlayerFields.CharacterPoints); }
void SetFreePrimaryProfessions(ushort profs) { SetUInt32Value(ActivePlayerFields.CharacterPoints, profs); }
public bool HaveAtClient(WorldObject u)
{
bool one = u.GetGUID() == GetGUID();
@@ -7130,7 +7128,7 @@ namespace Game.Entities
int fieldIndexOffset = (int)bitIndex / 32;
uint flag = (uint)(1 << ((int)bitIndex % 32));
return HasFlag(PlayerFields.KnownTitles + fieldIndexOffset, flag);
return HasFlag(ActivePlayerFields.KnownTitles + fieldIndexOffset, flag);
}
public void SetTitle(CharTitlesRecord title, bool lost = false)
{
@@ -7139,17 +7137,17 @@ namespace Game.Entities
if (lost)
{
if (!HasFlag(PlayerFields.KnownTitles + fieldIndexOffset, flag))
if (!HasFlag(ActivePlayerFields.KnownTitles + fieldIndexOffset, flag))
return;
RemoveFlag(PlayerFields.KnownTitles + fieldIndexOffset, flag);
RemoveFlag(ActivePlayerFields.KnownTitles + fieldIndexOffset, flag);
}
else
{
if (HasFlag(PlayerFields.KnownTitles + fieldIndexOffset, flag))
if (HasFlag(ActivePlayerFields.KnownTitles + fieldIndexOffset, flag))
return;
SetFlag(PlayerFields.KnownTitles + fieldIndexOffset, flag);
SetFlag(ActivePlayerFields.KnownTitles + fieldIndexOffset, flag);
}
TitleEarned packet = new TitleEarned(lost ? ServerOpcodes.TitleLost : ServerOpcodes.TitleEarned);
@@ -7163,7 +7161,7 @@ namespace Game.Entities
{
Log.outDebug(LogFilter.Maps, "Player.CreateViewpoint: Player {0} create seer {1} (TypeId: {2}).", GetName(), target.GetEntry(), target.GetTypeId());
if (!AddGuidValue(PlayerFields.Farsight, target.GetGUID()))
if (!AddGuidValue(ActivePlayerFields.Farsight, target.GetGUID()))
{
Log.outFatal(LogFilter.Player, "Player.CreateViewpoint: Player {0} cannot add new viewpoint!", GetName());
return;
@@ -7181,7 +7179,7 @@ namespace Game.Entities
{
Log.outDebug(LogFilter.Maps, "Player.CreateViewpoint: Player {0} remove seer", GetName());
if (!RemoveGuidValue(PlayerFields.Farsight, target.GetGUID()))
if (!RemoveGuidValue(ActivePlayerFields.Farsight, target.GetGUID()))
{
Log.outFatal(LogFilter.Player, "Player.CreateViewpoint: Player {0} cannot remove current viewpoint!", GetName());
return;
@@ -7196,7 +7194,7 @@ namespace Game.Entities
}
public WorldObject GetViewpoint()
{
ObjectGuid guid = GetGuidValue(PlayerFields.Farsight);
ObjectGuid guid = GetGuidValue(ActivePlayerFields.Farsight);
if (!guid.IsEmpty())
return Global.ObjAccessor.GetObjectByTypeMask(this, guid, TypeMask.Seer);
return null;
+2 -2
View File
@@ -225,13 +225,13 @@ namespace Game.Entities
public bool IsTaximaskNodeKnown(uint nodeidx)
{
byte field = (byte)((nodeidx - 1) / 8);
uint field = (nodeidx - 1) / 8;
uint submask = (uint)(1 << (int)((nodeidx - 1) % 8));
return (m_taximask[field] & submask) == submask;
}
public bool SetTaximaskNode(uint nodeidx)
{
byte field = (byte)((nodeidx - 1) / 8);
uint field = (nodeidx - 1) / 8;
uint submask = (uint)(1 << (int)((nodeidx - 1) % 8));
if ((m_taximask[field] & submask) != submask)
{
+12 -12
View File
@@ -13,7 +13,7 @@ namespace Game.Entities
{
byte rest_rested_offset;
byte rest_state_offset;
PlayerFields next_level_xp_field;
ActivePlayerFields next_level_xp_field;
bool affectedByRaF = false;
switch (restType)
@@ -25,17 +25,17 @@ namespace Game.Entities
rest_rested_offset = PlayerFieldOffsets.RestRestedXp;
rest_state_offset = PlayerFieldOffsets.RestStateXp;
next_level_xp_field = PlayerFields.NextLevelXp;
next_level_xp_field = ActivePlayerFields.NextLevelXp;
affectedByRaF = true;
break;
case RestTypes.Honor:
// Reset restBonus (Honor only) for players with max honor level.
if (_player.IsMaxHonorLevelAndPrestige())
if (_player.IsMaxHonorLevel())
restBonus = 0;
rest_rested_offset = PlayerFieldOffsets.RestRestedHonor;
rest_state_offset = PlayerFieldOffsets.RestStateHonor;
next_level_xp_field = PlayerFields.HonorNextLevel;
next_level_xp_field = ActivePlayerFields.HonorNextLevel;
break;
default:
return;
@@ -53,17 +53,17 @@ namespace Game.Entities
// update data for client
if (affectedByRaF && _player.GetsRecruitAFriendBonus(true) && (_player.GetSession().IsARecruiter() || _player.GetSession().GetRecruiterId() != 0))
_player.SetUInt32Value(PlayerFields.RestInfo + rest_state_offset, (uint)PlayerRestState.RAFLinked);
_player.SetUInt32Value(ActivePlayerFields.RestInfo + rest_state_offset, (uint)PlayerRestState.RAFLinked);
else
{
if (_restBonus[(int)restType] > 10)
_player.SetUInt32Value(PlayerFields.RestInfo + rest_state_offset, (uint)PlayerRestState.Rested);
_player.SetUInt32Value(ActivePlayerFields.RestInfo + rest_state_offset, (uint)PlayerRestState.Rested);
else if (_restBonus[(int)restType] <= 1)
_player.SetUInt32Value(PlayerFields.RestInfo + rest_state_offset, (uint)PlayerRestState.NotRAFLinked);
_player.SetUInt32Value(ActivePlayerFields.RestInfo + rest_state_offset, (uint)PlayerRestState.NotRAFLinked);
}
// RestTickUpdate
_player.SetUInt32Value(PlayerFields.RestInfo + rest_rested_offset, (uint)_restBonus[(int)restType]);
_player.SetUInt32Value(ActivePlayerFields.RestInfo + rest_rested_offset, (uint)_restBonus[(int)restType]);
}
public void AddRestBonus(RestTypes restType, float restBonus)
@@ -135,8 +135,8 @@ namespace Game.Entities
public void LoadRestBonus(RestTypes restType, PlayerRestState state, float restBonus)
{
_restBonus[(int)restType] = restBonus;
_player.SetUInt32Value(PlayerFields.RestInfo + (int)restType * 2, (uint)state);
_player.SetUInt32Value(PlayerFields.RestInfo + (int)restType * 2 + 1, (uint)restBonus);
_player.SetUInt32Value(ActivePlayerFields.RestInfo + (int)restType * 2, (uint)state);
_player.SetUInt32Value(ActivePlayerFields.RestInfo + (int)restType * 2 + 1, (uint)restBonus);
}
public float CalcExtraPerSec(RestTypes restType, float bubble)
@@ -144,9 +144,9 @@ namespace Game.Entities
switch (restType)
{
case RestTypes.Honor:
return (_player.GetUInt32Value(PlayerFields.HonorNextLevel)) / 72000.0f * bubble;
return (_player.GetUInt32Value(ActivePlayerFields.HonorNextLevel)) / 72000.0f * bubble;
case RestTypes.XP:
return (_player.GetUInt32Value(PlayerFields.NextLevelXp)) / 72000.0f * bubble;
return (_player.GetUInt32Value(ActivePlayerFields.NextLevelXp)) / 72000.0f * bubble;
default:
return 0.0f;
}
+70 -74
View File
@@ -193,7 +193,17 @@ namespace Game.Entities
public virtual bool UpdateStats(Stats stat) { return false; }
public virtual bool UpdateAllStats() { return false; }
public virtual void UpdateResistances(SpellSchools school) { }
public virtual void UpdateResistances(SpellSchools school)
{
if (school > SpellSchools.Normal)
{
UnitMods unitMod = UnitMods.ResistanceStart + (int)school;
SetResistance(school, (int)m_auraModifiersGroup[(int)unitMod][(int)UnitModifierType.BaseValue]);
SetBonusResistanceMod(school, (int)(GetTotalAuraModValue(unitMod) - GetResistance(school)));
}
else
UpdateArmor();
}
public virtual void UpdateArmor() { }
public virtual void UpdateMaxHealth() { }
public virtual void UpdateMaxPower(PowerType power) { }
@@ -257,30 +267,43 @@ namespace Game.Entities
}
public uint GetArmor()
{
return GetResistance(SpellSchools.Normal);
return (uint)(GetResistance(SpellSchools.Normal) + GetBonusResistanceMod(SpellSchools.Normal));
}
public void SetArmor(int val)
public void SetArmor(int val, int bonusVal)
{
SetResistance(SpellSchools.Normal, val);
SetBonusResistanceMod(SpellSchools.Normal, bonusVal);
}
public uint GetResistance(SpellSchools school)
public int GetResistance(SpellSchools school)
{
return GetUInt32Value(UnitFields.Resistances + (int)school);
return GetInt32Value(UnitFields.Resistances + (int)school);
}
public uint GetResistance(SpellSchoolMask mask)
public int GetBonusResistanceMod(SpellSchools school)
{
int resist = -1;
return GetInt32Value(UnitFields.BonusResistanceMods + (int)school);
}
public int GetResistance(SpellSchoolMask mask)
{
int? resist = null;
for (int i = (int)SpellSchools.Normal; i < (int)SpellSchools.Max; ++i)
if (Convert.ToBoolean((int)mask & (1 << i)) && (resist < 0 || resist > GetResistance((SpellSchools)i)))
resist = (int)GetResistance((SpellSchools)i);
{
int schoolResistance = GetResistance((SpellSchools)i) + GetBonusResistanceMod((SpellSchools)i);
if (Convert.ToBoolean((int)mask & (1 << i)) && (!resist.HasValue || resist.Value > schoolResistance))
resist = schoolResistance;
}
// resist value will never be negative here
return (uint)resist;
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 float GetCreateStat(Stats stat)
{
return CreateStats[(int)stat];
@@ -293,23 +316,6 @@ namespace Game.Entities
SetFloatValue(UnitFields.NegStat + (int)i, 0);
}
}
public float GetResistanceBuffMods(SpellSchools school, bool positive)
{
return GetFloatValue((positive ? UnitFields.ResistanceBuffModsPositive : UnitFields.ResistanceBuffModsNegative) + (int)school);
}
public void SetResistanceBuffMods(SpellSchools school, bool positive, float val)
{
SetFloatValue((positive ? UnitFields.ResistanceBuffModsPositive : UnitFields.ResistanceBuffModsNegative) + (int)school, val);
}
public void ApplyResistanceBuffModsMod(SpellSchools school, bool positive, float val, bool apply)
{
ApplyModSignedFloatValue((positive ? UnitFields.ResistanceBuffModsPositive : UnitFields.ResistanceBuffModsNegative) + (int)school, val, apply);
}
public void ApplyResistanceBuffModsPercentMod(SpellSchools school, bool positive, float val, bool apply)
{
ApplyPercentModFloatValue((positive ? UnitFields.ResistanceBuffModsPositive : UnitFields.ResistanceBuffModsNegative) + (int)school, val, apply);
}
public bool CanModifyStats()
{
@@ -634,13 +640,13 @@ namespace Game.Entities
switch (attackType)
{
case WeaponAttackType.BaseAttack:
chance = GetFloatValue(PlayerFields.CritPercentage);
chance = GetFloatValue(ActivePlayerFields.CritPercentage);
break;
case WeaponAttackType.OffAttack:
chance = GetFloatValue(PlayerFields.OffhandCritPercentage);
chance = GetFloatValue(ActivePlayerFields.OffhandCritPercentage);
break;
case WeaponAttackType.RangedAttack:
chance = GetFloatValue(PlayerFields.RangedCritPercentage);
chance = GetFloatValue(ActivePlayerFields.RangedCritPercentage);
break;
}
}
@@ -679,7 +685,7 @@ namespace Game.Entities
float chance = 0.0f;
float levelBonus = 0.0f;
if (victim.IsTypeId(TypeId.Player))
chance = victim.GetFloatValue(PlayerFields.DodgePercentage);
chance = victim.GetFloatValue(ActivePlayerFields.DodgePercentage);
else
{
if (!victim.IsTotem())
@@ -723,7 +729,7 @@ namespace Game.Entities
tmpitem = playerVictim.GetWeaponForAttack(WeaponAttackType.OffAttack, true);
if (tmpitem)
chance = playerVictim.GetFloatValue(PlayerFields.ParryPercentage);
chance = playerVictim.GetFloatValue(ActivePlayerFields.ParryPercentage);
}
}
else
@@ -771,7 +777,7 @@ namespace Game.Entities
{
Item tmpitem = playerVictim.GetUseableItemByPos(InventorySlots.Bag0, EquipmentSlot.OffHand);
if (tmpitem && !tmpitem.IsBroken() && tmpitem.GetTemplate().GetInventoryType() == InventoryType.Shield)
chance = playerVictim.GetFloatValue(PlayerFields.BlockPercentage);
chance = playerVictim.GetFloatValue(ActivePlayerFields.BlockPercentage);
}
}
else
@@ -909,8 +915,7 @@ namespace Game.Entities
{
if (school > SpellSchools.Normal)
{
float value = GetTotalAuraModValue(UnitMods.ResistanceStart + (int)school);
SetResistance(school, (int)value);
base.UpdateResistances(school);
Pet pet = GetPet();
if (pet != null)
@@ -1025,18 +1030,18 @@ namespace Game.Entities
// Magic damage modifiers implemented in Unit.SpellDamageBonusDone
// This information for client side use only
// Get healing bonus for all schools
SetStatInt32Value(PlayerFields.ModHealingDonePos, (int)SpellBaseHealingBonusDone(SpellSchoolMask.All));
SetStatInt32Value(ActivePlayerFields.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)
{
SetInt32Value(PlayerFields.ModDamageDoneNeg + (int)i, modDamageAuras.Aggregate(0, (negativeMod, aurEff) =>
SetInt32Value(ActivePlayerFields.ModDamageDoneNeg + (int)i, modDamageAuras.Aggregate(0, (negativeMod, aurEff) =>
{
if (aurEff.GetAmount() < 0 && Convert.ToBoolean(aurEff.GetMiscValue() & (1 << (int)i)))
negativeMod += aurEff.GetAmount();
return negativeMod;
}));
SetStatInt32Value(PlayerFields.ModDamageDonePos + (int)i, SpellBaseDamageBonusDone((SpellSchoolMask)(1 << (int)i)) - GetInt32Value(PlayerFields.ModDamageDoneNeg + (int)i));
SetStatInt32Value(ActivePlayerFields.ModDamageDonePos + (int)i, SpellBaseDamageBonusDone((SpellSchoolMask)(1 << (int)i)) - GetInt32Value(ActivePlayerFields.ModDamageDoneNeg + (int)i));
}
if (HasAuraType(AuraType.OverrideAttackPowerBySpPct))
@@ -1085,11 +1090,11 @@ namespace Game.Entities
}
else
{
int minSpellPower = GetInt32Value(PlayerFields.ModHealingDonePos);
int minSpellPower = GetInt32Value(ActivePlayerFields.ModHealingDonePos);
for (var i = SpellSchools.Holy; i < SpellSchools.Max; ++i)
minSpellPower = Math.Min(minSpellPower, GetInt32Value(PlayerFields.ModDamageDonePos + (int)i));
minSpellPower = Math.Min(minSpellPower, GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)i));
val2 = MathFunctions.CalculatePct(minSpellPower, GetFloatValue(PlayerFields.OverrideApBySpellPowerPercent));
val2 = MathFunctions.CalculatePct(minSpellPower, GetFloatValue(ActivePlayerFields.OverrideApBySpellPowerPercent));
}
SetModifierValue(unitMod, UnitModifierType.BaseValue, val2);
@@ -1146,6 +1151,7 @@ namespace Game.Entities
UnitMods unitMod = UnitMods.Armor;
float value = GetModifierValue(unitMod, UnitModifierType.BaseValue); // base armor (from items)
float baseValue = value;
value *= GetModifierValue(unitMod, UnitModifierType.BasePCT); // armor percent from items
value += GetModifierValue(unitMod, UnitModifierType.TotalValue);
@@ -1159,7 +1165,7 @@ namespace Game.Entities
value *= GetModifierValue(unitMod, UnitModifierType.TotalPCT);
SetArmor((int)value);
SetArmor((int)baseValue, (int)(value - baseValue));
Pet pet = GetPet();
if (pet)
@@ -1214,8 +1220,8 @@ namespace Game.Entities
if (amount < 0)
amount = 0;
uint oldRating = GetUInt32Value(PlayerFields.CombatRating1 + (int)cr);
SetUInt32Value(PlayerFields.CombatRating1 + (int)cr, (uint)amount);
uint oldRating = GetUInt32Value(ActivePlayerFields.CombatRating + (int)cr);
SetUInt32Value(ActivePlayerFields.CombatRating + (int)cr, (uint)amount);
bool affectStats = CanModifyStats();
@@ -1314,13 +1320,13 @@ namespace Game.Entities
{
if (!CanUseMastery())
{
SetFloatValue(PlayerFields.Mastery, 0.0f);
SetFloatValue(ActivePlayerFields.Mastery, 0.0f);
return;
}
float value = GetTotalAuraModifier(AuraType.Mastery);
value += GetRatingBonusValue(CombatRating.Mastery);
SetFloatValue(PlayerFields.Mastery, value);
SetFloatValue(ActivePlayerFields.Mastery, value);
ChrSpecializationRecord chrSpec = CliDB.ChrSpecializationStorage.LookupByKey(GetUInt32Value(PlayerFields.CurrentSpecId));
if (chrSpec == null)
@@ -1349,7 +1355,7 @@ namespace Game.Entities
public void UpdateVersatilityDamageDone()
{
// No proof that CR_VERSATILITY_DAMAGE_DONE is allways = PLAYER_VERSATILITY
SetUInt32Value(PlayerFields.Versatility, GetUInt32Value(PlayerFields.CombatRating1 + (int)CombatRating.VersatilityDamageDone));
SetUInt32Value(ActivePlayerFields.Versatility, GetUInt32Value(ActivePlayerFields.CombatRating + (int)CombatRating.VersatilityDamageDone));
if (GetClass() == Class.Hunter)
UpdateDamagePhysical(WeaponAttackType.RangedAttack);
@@ -1366,13 +1372,13 @@ namespace Game.Entities
foreach (AuraEffect auraEffect in GetAuraEffectsByType(AuraType.ModHealingDonePercent))
MathFunctions.AddPct(ref value, auraEffect.GetAmount());
SetStatFloatValue(PlayerFields.ModHealingDonePct, value);
SetStatFloatValue(ActivePlayerFields.ModHealingDonePct, value);
}
void UpdateArmorPenetration(int amount)
{
// Store Rating Value
SetInt32Value(PlayerFields.CombatRating1 + (int)CombatRating.ArmorPenetration, amount);
SetInt32Value(ActivePlayerFields.CombatRating + (int)CombatRating.ArmorPenetration, amount);
}
public void UpdateParryPercentage()
{
@@ -1410,7 +1416,7 @@ namespace Game.Entities
value = value < 0.0f ? 0.0f : value;
}
SetFloatValue(PlayerFields.ParryPercentage, value);
SetFloatValue(ActivePlayerFields.ParryPercentage, value);
}
public void UpdateDodgePercentage()
@@ -1445,7 +1451,7 @@ namespace Game.Entities
value = value > WorldConfig.GetFloatValue(WorldCfg.StatsLimitsDodge) ? WorldConfig.GetFloatValue(WorldCfg.StatsLimitsDodge) : value;
value = value < 0.0f ? 0.0f : value;
SetStatFloatValue(PlayerFields.DodgePercentage, value);
SetStatFloatValue(ActivePlayerFields.DodgePercentage, value);
}
public void UpdateBlockPercentage()
{
@@ -1465,31 +1471,31 @@ namespace Game.Entities
value = value < 0.0f ? 0.0f : value;
}
SetFloatValue(PlayerFields.BlockPercentage, value);
SetFloatValue(ActivePlayerFields.BlockPercentage, value);
}
public void UpdateCritPercentage(WeaponAttackType attType)
{
BaseModGroup modGroup;
PlayerFields index;
ActivePlayerFields index;
CombatRating cr;
switch (attType)
{
case WeaponAttackType.OffAttack:
modGroup = BaseModGroup.OffhandCritPercentage;
index = PlayerFields.OffhandCritPercentage;
index = ActivePlayerFields.OffhandCritPercentage;
cr = CombatRating.CritMelee;
break;
case WeaponAttackType.RangedAttack:
modGroup = BaseModGroup.RangedCritPercentage;
index = PlayerFields.RangedCritPercentage;
index = ActivePlayerFields.RangedCritPercentage;
cr = CombatRating.CritRanged;
break;
case WeaponAttackType.BaseAttack:
default:
modGroup = BaseModGroup.CritPercentage;
index = PlayerFields.CritPercentage;
index = ActivePlayerFields.CritPercentage;
cr = CombatRating.CritMelee;
break;
}
@@ -1522,10 +1528,10 @@ namespace Game.Entities
switch (attack)
{
case WeaponAttackType.BaseAttack:
SetInt32Value(PlayerFields.Expertise, expertise);
SetInt32Value(ActivePlayerFields.Expertise, expertise);
break;
case WeaponAttackType.OffAttack:
SetInt32Value(PlayerFields.OffhandExpertise, expertise);
SetInt32Value(ActivePlayerFields.OffhandExpertise, expertise);
break;
default: break;
}
@@ -1617,7 +1623,7 @@ namespace Game.Entities
crit += GetRatingBonusValue(CombatRating.CritSpell);
// Store crit value
SetFloatValue(PlayerFields.SpellCritPercentage1, crit);
SetFloatValue(ActivePlayerFields.SpellCritPercentage1, crit);
}
public void UpdateMeleeHitChances()
@@ -1682,7 +1688,7 @@ namespace Game.Entities
public void ApplySpellPenetrationBonus(int amount, bool apply)
{
ApplyModInt32Value(PlayerFields.ModTargetResistance, -amount, apply);
ApplyModInt32Value(ActivePlayerFields.ModTargetResistance, -amount, apply);
m_spellPenetrationItemMod += apply ? amount : -amount;
}
@@ -1705,9 +1711,9 @@ namespace Game.Entities
apply = _ModifyUInt32(apply, ref m_baseSpellPower, ref amount);
// For speed just update for client
ApplyModUInt32Value(PlayerFields.ModHealingDonePos, amount, apply);
ApplyModUInt32Value(ActivePlayerFields.ModHealingDonePos, amount, apply);
for (int i = (int)SpellSchools.Holy; i < (int)SpellSchools.Max; ++i)
ApplyModUInt32Value(PlayerFields.ModDamageDonePos + i, amount, apply);
ApplyModUInt32Value(ActivePlayerFields.ModDamageDonePos + i, amount, apply);
if (HasAuraType(AuraType.OverrideAttackPowerBySpPct))
{
@@ -1776,21 +1782,11 @@ namespace Game.Entities
return true;
}
public override void UpdateResistances(SpellSchools school)
{
if (school > SpellSchools.Normal)
{
float value = GetTotalAuraModValue(UnitMods.ResistanceStart + (int)school);
SetResistance(school, (int)value);
}
else
UpdateArmor();
}
public override void UpdateArmor()
{
float baseValue = GetModifierValue(UnitMods.Armor, UnitModifierType.BaseValue);
float value = GetTotalAuraModValue(UnitMods.Armor);
SetArmor((int)value);
SetArmor((int)baseValue, (int)(value - baseValue));
}
public override void UpdateMaxHealth()
-515
View File
@@ -1,515 +0,0 @@
/*
* Copyright (C) 2012-2018 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 System;
using System.Collections.Generic;
using System.Text;
namespace Game.Entities
{
/// <summary>
/// The IndexMinPriorityQueue class represents an indexed priority queue of generic keys.
/// </summary>
/// <seealso href="http://algs4.cs.princeton.edu/24pq/IndexMinPQ.java.html">IndexMinPQ class from Princeton University's Java Algorithms</seealso>
/// <typeparam name="T">Type must implement IComparable interface</typeparam>
public class IndexMinPriorityQueue<T> where T : IComparable<T>
{
private readonly T[] _keys;
private readonly int _maxSize;
private readonly int[] _pq;
private readonly int[] _qp;
/// <summary>
/// Constructs an empty indexed priority queue with indices between 0 and the specified maxSize - 1
/// </summary>
/// <param name="maxSize">The maximum size of the indexed priority queue</param>
public IndexMinPriorityQueue(int maxSize)
{
_maxSize = maxSize;
Size = 0;
_keys = new T[_maxSize + 1];
_pq = new int[_maxSize + 1];
_qp = new int[_maxSize + 1];
for (int i = 0; i < _maxSize; i++)
{
_qp[i] = -1;
}
}
/// <summary>
/// The number of keys on this indexed priority queue
/// </summary>
public int Size { get; private set; }
/// <summary>
/// Is the indexed priority queue empty?
/// </summary>
/// <returns>True if the indexed priority queue is empty, false otherwise</returns>
public bool IsEmpty()
{
return Size == 0;
}
/// <summary>
/// Is the specified parameter i an index on the priority queue?
/// </summary>
/// <param name="i">An index to check for on the priority queue</param>
/// <returns>True if the specified parameter i is an index on the priority queue, false otherwise</returns>
public bool Contains(int i)
{
return _qp[i] != -1;
}
/// <summary>
/// Associates the specified key with the specified index
/// </summary>
/// <param name="index">The index to associate the key with</param>
/// <param name="key">The key to associate with the index</param>
public void Insert(int index, T key)
{
Size++;
_qp[index] = Size;
_pq[Size] = index;
_keys[index] = key;
Swim(Size);
}
/// <summary>
/// Returns an index associated with a minimum key
/// </summary>
/// <returns>An index associated with a minimum key</returns>
public int MinIndex()
{
return _pq[1];
}
/// <summary>
/// Returns a minimum key
/// </summary>
/// <returns>A minimum key</returns>
public T MinKey()
{
return _keys[_pq[1]];
}
/// <summary>
/// Removes a minimum key and returns its associated index
/// </summary>
/// <returns>An index associated with a minimum key that was removed</returns>
public int DeleteMin()
{
int min = _pq[1];
Exchange(1, Size--);
Sink(1);
_qp[min] = -1;
_keys[_pq[Size + 1]] = default(T);
_pq[Size + 1] = -1;
return min;
}
/// <summary>
/// Returns the key associated with the specified index
/// </summary>
/// <param name="index">The index of the key to return</param>
/// <returns>The key associated with the specified index</returns>
public T KeyAt(int index)
{
return _keys[index];
}
/// <summary>
/// Change the key associated with the specified index to the specified value
/// </summary>
/// <param name="index">The index of the key to change</param>
/// <param name="key">Change the key associated with the specified index to this key</param>
public void ChangeKey(int index, T key)
{
_keys[index] = key;
Swim(_qp[index]);
Sink(_qp[index]);
}
/// <summary>
/// Decrease the key associated with the specified index to the specified value
/// </summary>
/// <param name="index">The index of the key to decrease</param>
/// <param name="key">Decrease the key associated with the specified index to this key</param>
public void DecreaseKey(int index, T key)
{
_keys[index] = key;
Swim(_qp[index]);
}
/// <summary>
/// Increase the key associated with the specified index to the specified value
/// </summary>
/// <param name="index">The index of the key to increase</param>
/// <param name="key">Increase the key associated with the specified index to this key</param>
public void IncreaseKey(int index, T key)
{
_keys[index] = key;
Sink(_qp[index]);
}
/// <summary>
/// Remove the key associated with the specified index
/// </summary>
/// <param name="index">The index of the key to remove</param>
public void Delete(int index)
{
int i = _qp[index];
Exchange(i, Size--);
Swim(i);
Sink(i);
_keys[index] = default(T);
_qp[index] = -1;
}
private bool Greater(int i, int j)
{
return _keys[_pq[i]].CompareTo(_keys[_pq[j]]) > 0;
}
private void Exchange(int i, int j)
{
int swap = _pq[i];
_pq[i] = _pq[j];
_pq[j] = swap;
_qp[_pq[i]] = i;
_qp[_pq[j]] = j;
}
private void Swim(int k)
{
while (k > 1 && Greater(k / 2, k))
{
Exchange(k, k / 2);
k = k / 2;
}
}
private void Sink(int k)
{
while (2 * k <= Size)
{
int j = 2 * k;
if (j < Size && Greater(j, j + 1))
{
j++;
}
if (!Greater(k, j))
{
break;
}
Exchange(k, j);
k = j;
}
}
}
/// <summary>
/// The EdgeWeightedDigrpah class represents an edge-weighted directed graph of vertices named 0 through V-1, where each directed edge
/// is of type DirectedEdge and has real-valued weight.
/// </summary>
/// <seealso href="http://algs4.cs.princeton.edu/44sp/EdgeWeightedDigraph.java.html">EdgeWeightedDigraph class from Princeton University's Java Algorithms</seealso>
public class EdgeWeightedDigraph
{
private readonly LinkedList<DirectedEdge>[] _adjacent;
/// <summary>
/// Constructs an empty edge-weighted digraph with the specified number of vertices and 0 edges
/// </summary>
/// <param name="vertices">Number of vertices in the Graph</param>
public EdgeWeightedDigraph(int vertices)
{
NumberOfVertices = vertices;
NumberOfEdges = 0;
_adjacent = new LinkedList<DirectedEdge>[NumberOfVertices];
for (int v = 0; v < NumberOfVertices; v++)
{
_adjacent[v] = new LinkedList<DirectedEdge>();
}
}
/// <summary>
/// The number of vertices in the edge-weighted digraph
/// </summary>
public int NumberOfVertices { get; private set; }
/// <summary>
/// The number of edges in the edge-weighted digraph
/// </summary>
public int NumberOfEdges { get; private set; }
/// <summary>
/// Adds the specified directed edge to the edge-weighted digraph
/// </summary>
/// <param name="edge">The DirectedEdge to add</param>
/// <exception cref="ArgumentNullException">DirectedEdge cannot be null</exception>
public void AddEdge(DirectedEdge edge)
{
if (edge == null)
{
throw new ArgumentNullException("edge", "DirectedEdge cannot be null");
}
_adjacent[edge.From].AddLast(edge);
}
/// <summary>
/// Returns an IEnumerable of the DirectedEdges incident from the specified vertex
/// </summary>
/// <param name="vertex">The vertex to find incident DirectedEdges from</param>
/// <returns>IEnumerable of the DirectedEdges incident from the specified vertex</returns>
public IEnumerable<DirectedEdge> Adjacent(int vertex)
{
return _adjacent[vertex];
}
/// <summary>
/// Returns an IEnumerable of all directed edges in the edge-weighted digraph
/// </summary>
/// <returns>IEnumerable of of all directed edges in the edge-weighted digraph</returns>
public IEnumerable<DirectedEdge> Edges()
{
for (int v = 0; v < NumberOfVertices; v++)
{
foreach (DirectedEdge edge in _adjacent[v])
{
yield return edge;
}
}
}
/// <summary>
/// Returns the number of directed edges incident from the specified vertex
/// This is known as the outdegree of the vertex
/// </summary>
/// <param name="vertex">The vertex to find find the outdegree of</param>
/// <returns>The number of directed edges incident from the specified vertex</returns>
public int OutDegree(int vertex)
{
return _adjacent[vertex].Count;
}
/// <summary>
/// Returns a string that represents the current edge-weighted digraph
/// </summary>
/// <returns>
/// A string that represents the current edge-weighted digraph
/// </returns>
public override string ToString()
{
var formattedString = new StringBuilder();
formattedString.AppendFormat("{0} vertices, {1} edges {2}", NumberOfVertices, NumberOfEdges, Environment.NewLine);
for (int v = 0; v < NumberOfVertices; v++)
{
formattedString.AppendFormat("{0}: ", v);
foreach (DirectedEdge edge in _adjacent[v])
{
formattedString.AppendFormat("{0} ", edge.To);
}
formattedString.AppendLine();
}
return formattedString.ToString();
}
}
/// <summary>
/// The DirectedEdge class represents a weighted edge in an edge-weighted directed graph.
/// </summary>
/// <seealso href="http://algs4.cs.princeton.edu/44sp/DirectedEdge.java.html">DirectedEdge class from Princeton University's Java Algorithms</seealso>
public class DirectedEdge
{
/// <summary>
/// Constructs a directed edge from one specified vertex to another with the given weight
/// </summary>
/// <param name="from">The start vertex</param>
/// <param name="to">The destination vertex</param>
/// <param name="weight">The weight of the DirectedEdge</param>
public DirectedEdge(uint from, uint to, double weight)
{
From = from;
To = to;
Weight = weight;
}
/// <summary>
/// Returns the destination vertex of the DirectedEdge
/// </summary>
public uint From { get; private set; }
/// <summary>
/// Returns the start vertex of the DirectedEdge
/// </summary>
public uint To { get; private set; }
/// <summary>
/// Returns the weight of the DirectedEdge
/// </summary>
public double Weight { get; private set; }
/// <summary>
/// Returns a string that represents the current DirectedEdge
/// </summary>
/// <returns>
/// A string that represents the current DirectedEdge
/// </returns>
public override string ToString()
{
return $"From: {From}, To: {To}, Weight: {Weight}";
}
}
/// <summary>
/// The DijkstraShortestPath class represents a data type for solving the single-source shortest paths problem
/// in edge-weighted digraphs where the edge weights are non-negative
/// </summary>
/// <seealso href="http://algs4.cs.princeton.edu/44sp/DijkstraSP.java.html">DijkstraSP class from Princeton University's Java Algorithms</seealso>
public class DijkstraShortestPath
{
private readonly double[] _distanceTo;
private readonly DirectedEdge[] _edgeTo;
private readonly IndexMinPriorityQueue<double> _priorityQueue;
/// <summary>
/// Computes a shortest paths tree from the specified sourceVertex to every other vertex in the edge-weighted directed graph
/// </summary>
/// <param name="graph">The edge-weighted directed graph</param>
/// <param name="sourceVertex">The source vertex to compute the shortest paths tree from</param>
/// <exception cref="ArgumentOutOfRangeException">Throws an ArgumentOutOfRangeException if an edge weight is negative</exception>
/// <exception cref="ArgumentNullException">Thrown if EdgeWeightedDigraph is null</exception>
public DijkstraShortestPath(EdgeWeightedDigraph graph, int sourceVertex)
{
if (graph == null)
{
throw new ArgumentNullException("graph", "EdgeWeightedDigraph cannot be null");
}
foreach (DirectedEdge edge in graph.Edges())
{
if (edge.Weight < 0)
{
throw new ArgumentOutOfRangeException($"Edge: '{edge}' has negative weight");
}
}
_distanceTo = new double[graph.NumberOfVertices];
_edgeTo = new DirectedEdge[graph.NumberOfVertices];
for (int v = 0; v < graph.NumberOfVertices; v++)
{
_distanceTo[v] = double.PositiveInfinity;
}
_distanceTo[sourceVertex] = 0.0;
_priorityQueue = new IndexMinPriorityQueue<double>(graph.NumberOfVertices);
_priorityQueue.Insert(sourceVertex, _distanceTo[sourceVertex]);
while (!_priorityQueue.IsEmpty())
{
int v = _priorityQueue.DeleteMin();
foreach (DirectedEdge edge in graph.Adjacent(v))
{
Relax(edge);
}
}
}
private void Relax(DirectedEdge edge)
{
uint v = edge.From;
uint w = edge.To;
if (_distanceTo[w] > _distanceTo[v] + edge.Weight)
{
_distanceTo[w] = _distanceTo[v] + edge.Weight;
_edgeTo[w] = edge;
if (_priorityQueue.Contains((int)w))
{
_priorityQueue.DecreaseKey((int)w, _distanceTo[w]);
}
else
{
_priorityQueue.Insert((int)w, _distanceTo[w]);
}
}
}
/// <summary>
/// Returns the length of a shortest path from the sourceVertex to the specified destinationVertex
/// </summary>
/// <param name="destinationVertex">The destination vertex to find a shortest path to</param>
/// <returns>The length of a shortest path from the sourceVertex to the specified destinationVertex or double.PositiveInfinity if no such path exists</returns>
public double DistanceTo(int destinationVertex)
{
return _distanceTo[destinationVertex];
}
/// <summary>
/// Is there a path from the sourceVertex to the specified destinationVertex?
/// </summary>
/// <param name="destinationVertex">The destination vertex to see if there is a path to</param>
/// <returns>True if there is a path from the sourceVertex to the specified destinationVertex, false otherwise</returns>
public bool HasPathTo(int destinationVertex)
{
return _distanceTo[destinationVertex] < double.PositiveInfinity;
}
/// <summary>
/// Returns an IEnumerable of DirectedEdges representing a shortest path from the sourceVertex to the specified destinationVertex
/// </summary>
/// <param name="destinationVertex">The destination vertex to find a shortest path to</param>
/// <returns>IEnumerable of DirectedEdges representing a shortest path from the sourceVertex to the specified destinationVertex</returns>
public IEnumerable<DirectedEdge> PathTo(int destinationVertex)
{
if (!HasPathTo(destinationVertex))
{
return null;
}
var path = new Stack<DirectedEdge>();
for (DirectedEdge edge = _edgeTo[destinationVertex]; edge != null; edge = _edgeTo[edge.From])
{
path.Push(edge);
}
return path;
}
// TODO: This method should be private and should be called from the bottom of the constructor
/// <summary>
/// check optimality conditions:
/// </summary>
/// <param name="graph">The edge-weighted directed graph</param>
/// <param name="sourceVertex">The source vertex to check optimality conditions from</param>
/// <returns>True if all optimality conditions are met, false otherwise</returns>
/// <exception cref="ArgumentNullException">Thrown on null EdgeWeightedDigraph</exception>
public bool Check(EdgeWeightedDigraph graph, int sourceVertex)
{
if (graph == null)
{
throw new ArgumentNullException("graph", "EdgeWeightedDigraph cannot be null");
}
if (_distanceTo[sourceVertex] != 0.0 || _edgeTo[sourceVertex] != null)
{
return false;
}
for (int v = 0; v < graph.NumberOfVertices; v++)
{
if (v == sourceVertex)
{
continue;
}
if (_edgeTo[v] == null && _distanceTo[v] != double.PositiveInfinity)
{
return false;
}
}
for (int v = 0; v < graph.NumberOfVertices; v++)
{
foreach (DirectedEdge edge in graph.Adjacent(v))
{
uint w = edge.To;
if (_distanceTo[v] + edge.Weight < _distanceTo[w])
{
return false;
}
}
}
for (int w = 0; w < graph.NumberOfVertices; w++)
{
if (_edgeTo[w] == null)
{
continue;
}
DirectedEdge edge = _edgeTo[w];
uint v = edge.From;
if (w != edge.To)
{
return false;
}
if (_distanceTo[v] + edge.Weight != _distanceTo[w])
{
return false;
}
}
return true;
}
}
}
+39 -28
View File
@@ -15,6 +15,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using Framework.Algorithms;
using Framework.Collections;
using Framework.Constants;
using Framework.GameMath;
using Game.DataStorage;
@@ -25,11 +27,15 @@ namespace Game.Entities
{
public class TaxiPathGraph : Singleton<TaxiPathGraph>
{
EdgeWeightedDigraph m_graph;
List<TaxiNodesRecord> m_nodesByVertex = new List<TaxiNodesRecord>();
Dictionary<uint, uint> m_verticesByNode = new Dictionary<uint, uint>();
TaxiPathGraph() { }
public void Initialize()
{
if (GetVertexCount() > 0)
if (m_graph.NumberOfVertices > 0)
return;
List<Tuple<Tuple<uint, uint>, uint>> edges = new List<Tuple<Tuple<uint, uint>, uint>>();
@@ -44,7 +50,7 @@ namespace Game.Entities
}
// create graph
m_graph = new EdgeWeightedDigraph(GetVertexCount());
m_graph = new EdgeWeightedDigraph(m_nodesByVertex.Count);
for (int j = 0; j < edges.Count; ++j)
{
@@ -54,24 +60,21 @@ namespace Game.Entities
uint GetNodeIDFromVertexID(uint vertexID)
{
if (vertexID < m_vertices.Length)
return m_vertices[vertexID].Id;
if (vertexID < m_nodesByVertex.Count)
return m_nodesByVertex[(int)vertexID].Id;
return uint.MaxValue;
}
uint GetVertexIDFromNodeID(TaxiNodesRecord node)
{
return node.CharacterBitNumber;
return m_verticesByNode.ContainsKey(node.Id) ? m_verticesByNode[node.Id] : uint.MaxValue;
}
int GetVertexCount()
void GetTaxiMapPosition(Vector3 position, int mapId, out Vector2 uiMapPosition, out int uiMapId)
{
if (m_graph == null)
return m_vertices.Length;
//So we can use this function for readability, we define either max defined vertices or already loaded in graph count
return m_vertices.Length;// Math.Max(m_graph.getNumberOfVertices(), m_vertices.Length);
if (!Global.DB2Mgr.GetUiMapPosition(position.X, position.Y, position.Z, mapId, 0, 0, 0, UiMapSystem.Adventure, false, out uiMapId, out uiMapPosition))
Global.DB2Mgr.GetUiMapPosition(position.X, position.Y, position.Z, mapId, 0, 0, 0, UiMapSystem.Taxi, false, out uiMapId, out uiMapPosition);
}
void AddVerticeAndEdgeFromNodeInfo(TaxiNodesRecord from, TaxiNodesRecord to, uint pathId, List<Tuple<Tuple<uint, uint>, uint>> edges)
@@ -102,19 +105,19 @@ namespace Game.Entities
if (nodes[i - 1].Flags.HasAnyFlag(TaxiPathNodeFlags.Teleport))
continue;
uint map1, map2;
int uiMap1, uiMap2;
Vector2 pos1, pos2;
Global.DB2Mgr.DeterminaAlternateMapPosition(nodes[i - 1].ContinentID, nodes[i - 1].Loc.X, nodes[i - 1].Loc.Y, nodes[i - 1].Loc.Z, out map1, out pos1);
Global.DB2Mgr.DeterminaAlternateMapPosition(nodes[i].ContinentID, nodes[i].Loc.X, nodes[i].Loc.Y, nodes[i].Loc.Z, out map2, out pos2);
GetTaxiMapPosition(nodes[i - 1].Loc, nodes[i - 1].ContinentID, out pos1, out uiMap1);
GetTaxiMapPosition(nodes[i].Loc, nodes[i].ContinentID, out pos2, out uiMap2);
if (map1 != map2)
if (uiMap1 != uiMap2)
continue;
totalDist += (float)Math.Sqrt((float)Math.Pow(pos2.X - pos1.X, 2) + (float)Math.Pow(pos2.Y - pos1.Y, 2) + (float)Math.Pow(nodes[i].Loc.Z - nodes[i - 1].Loc.Z, 2));
totalDist += (float)Math.Sqrt((float)Math.Pow(pos2.X - pos1.X, 2) + (float)Math.Pow(pos2.Y - pos1.Y, 2));
}
uint dist = (uint)totalDist;
uint dist = (uint)(totalDist * 32767.0f);
if (dist > 0xFFFF)
dist = 0xFFFF;
@@ -152,7 +155,7 @@ namespace Game.Entities
foreach (var edge in path)
{
//todo test me No clue about this....
var To = m_vertices[edge.To];
var To = m_nodesByVertex[(int)edge.To];
TaxiNodeFlags requireFlag = (player.GetTeam() == Team.Alliance) ? TaxiNodeFlags.Alliance : TaxiNodeFlags.Horde;
if (!To.Flags.HasAnyFlag(requireFlag))
continue;
@@ -169,19 +172,27 @@ namespace Game.Entities
return shortestPath.Count;
}
uint CreateVertexFromFromNodeInfoIfNeeded(TaxiNodesRecord node)
//todo test me
public void GetReachableNodesMask(TaxiNodesRecord from, byte[] mask)
{
//Check if we need a new one or if it may be already created
if (m_vertices.Length <= node.CharacterBitNumber)
Array.Resize(ref m_vertices, (int)node.CharacterBitNumber + 1);
m_vertices[node.CharacterBitNumber] = node;
return node.CharacterBitNumber;
DepthFirstSearch depthFirst = new DepthFirstSearch(m_graph, GetVertexIDFromNodeID(from), vertex =>
{
TaxiNodesRecord taxiNode = CliDB.TaxiNodesStorage.LookupByKey(GetNodeIDFromVertexID(vertex));
if (taxiNode != null)
mask[(taxiNode.Id - 1) / 8] |= (byte)(1 << (int)((taxiNode.Id - 1) % 8));
});
}
TaxiNodesRecord[] m_vertices = new TaxiNodesRecord[0];
EdgeWeightedDigraph m_graph;
uint CreateVertexFromFromNodeInfoIfNeeded(TaxiNodesRecord node)
{
if (!m_verticesByNode.ContainsKey(node.Id))
{
m_verticesByNode.Add(node.Id, (uint)m_nodesByVertex.Count);
m_nodesByVertex.Add(node);
}
return m_verticesByNode[node.Id];
}
}
}
+26 -15
View File
@@ -367,7 +367,7 @@ namespace Game.Entities
// Shaman pet
public bool IsSpiritWolf() { return GetEntry() == (uint)PetEntry.SpiritWolf; } // Spirit wolf from feral spirits
Unit m_owner;
protected Unit m_owner;
float m_followAngle;
}
@@ -467,8 +467,12 @@ namespace Game.Entities
}
// Resistance
for (int i = (int)SpellSchools.Holy; i < (int)SpellSchools.Max; ++i)
SetModifierValue(UnitMods.ResistanceStart + i, UnitModifierType.BaseValue, cinfo.Resistance[i]);
// Hunters pet should not inherit resistances from creature_template, they have separate auras for that
if (!IsHunterPet())
{
for (int i = (int)SpellSchools.Holy; i < (int)SpellSchools.Max; ++i)
SetModifierValue(UnitMods.ResistanceStart + i, UnitModifierType.BaseValue, cinfo.Resistance[i]);
}
// Health, Mana or Power, Armor
PetLevelInfo pInfo = Global.ObjectMgr.GetPetLevelInfo(creature_ID, petlevel);
@@ -513,8 +517,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(PlayerFields.ModDamageDonePos + (int)SpellSchools.Fire);
int shadow = GetOwner().GetInt32Value(PlayerFields.ModDamageDonePos + (int)SpellSchools.Shadow);
int fire = GetOwner().GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)SpellSchools.Fire);
int shadow = GetOwner().GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)SpellSchools.Shadow);
int val = (fire > shadow) ? fire : shadow;
if (val < 0)
val = 0;
@@ -754,13 +758,18 @@ namespace Game.Entities
{
if (school > SpellSchools.Normal)
{
float value = GetTotalAuraModValue(UnitMods.ResistanceStart + (int)school);
float baseValue = GetModifierValue( UnitMods.ResistanceStart + (int)school, UnitModifierType.BaseValue);
float bonusValue = GetTotalAuraModValue(UnitMods.ResistanceStart + (int)school) - baseValue;
// hunter and warlock pets gain 40% of owner's resistance
if (IsPet())
value += MathFunctions.CalculatePct(GetOwner().GetResistance(school), 40);
{
baseValue += (float)MathFunctions.CalculatePct(m_owner.GetResistance(school), 40);
bonusValue += (float)MathFunctions.CalculatePct(m_owner.GetBonusResistanceMod(school), 40);
}
SetResistance(school, (int)value);
SetResistance(school, (int)baseValue);
SetBonusResistanceMod(school, (int)bonusValue);
}
else
UpdateArmor();
@@ -768,6 +777,7 @@ namespace Game.Entities
public override void UpdateArmor()
{
float baseValue = 0.0f;
float value = 0.0f;
float bonus_armor = 0.0f;
UnitMods unitMod = UnitMods.Armor;
@@ -779,11 +789,12 @@ namespace Game.Entities
bonus_armor = GetOwner().GetArmor();
value = GetModifierValue(unitMod, UnitModifierType.BaseValue);
baseValue = value;
value *= GetModifierValue(unitMod, UnitModifierType.BasePCT);
value += GetModifierValue(unitMod, UnitModifierType.TotalValue) + bonus_armor;
value *= GetModifierValue(unitMod, UnitModifierType.TotalPCT);
SetArmor((int)value);
SetArmor((int)baseValue, (int)(value - baseValue));
}
public override void UpdateMaxHealth()
@@ -877,8 +888,8 @@ namespace Game.Entities
//demons benefit from warlocks shadow or fire damage
else if (IsPet())
{
int fire = owner.GetInt32Value(PlayerFields.ModDamageDonePos + (int)SpellSchools.Fire) - owner.GetInt32Value(PlayerFields.ModDamageDoneNeg + (int)SpellSchools.Fire);
int shadow = owner.GetInt32Value(PlayerFields.ModDamageDonePos + (int)SpellSchools.Shadow) - owner.GetInt32Value(PlayerFields.ModDamageDoneNeg + (int)SpellSchools.Shadow);
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 maximum = (fire > shadow) ? fire : shadow;
if (maximum < 0)
maximum = 0;
@@ -888,7 +899,7 @@ namespace Game.Entities
//water elementals benefit from mage's frost damage
else if (GetEntry() == ENTRY_WATER_ELEMENTAL)
{
int frost = owner.GetInt32Value(PlayerFields.ModDamageDonePos + (int)SpellSchools.Frost) - owner.GetInt32Value(PlayerFields.ModDamageDoneNeg + (int)SpellSchools.Frost);
int frost = owner.GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)SpellSchools.Frost) - owner.GetInt32Value(ActivePlayerFields.ModDamageDoneNeg + (int)SpellSchools.Frost);
if (frost < 0)
frost = 0;
SetBonusDamage((int)(frost * 0.4f));
@@ -921,14 +932,14 @@ namespace Game.Entities
//force of nature
if (GetEntry() == ENTRY_TREANT)
{
int spellDmg = GetOwner().GetInt32Value(PlayerFields.ModDamageDonePos + (int)SpellSchools.Nature) - GetOwner().GetInt32Value(PlayerFields.ModDamageDoneNeg + (int)SpellSchools.Nature);
int spellDmg = GetOwner().GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)SpellSchools.Nature) - GetOwner().GetInt32Value(ActivePlayerFields.ModDamageDoneNeg + (int)SpellSchools.Nature);
if (spellDmg > 0)
bonusDamage = spellDmg * 0.09f;
}
//greater fire elemental
else if (GetEntry() == ENTRY_FIRE_ELEMENTAL)
{
int spellDmg = GetOwner().GetInt32Value(PlayerFields.ModDamageDonePos + (int)SpellSchools.Fire) - GetOwner().GetInt32Value(PlayerFields.ModDamageDoneNeg + (int)SpellSchools.Fire);
int spellDmg = GetOwner().GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)SpellSchools.Fire) - GetOwner().GetInt32Value(ActivePlayerFields.ModDamageDoneNeg + (int)SpellSchools.Fire);
if (spellDmg > 0)
bonusDamage = spellDmg * 0.4f;
}
@@ -957,7 +968,7 @@ namespace Game.Entities
{
m_bonusSpellDamage = damage;
if (GetOwner().IsTypeId(TypeId.Player))
GetOwner().SetUInt32Value(PlayerFields.PetSpellPower, (uint)damage);
GetOwner().SetUInt32Value(ActivePlayerFields.PetSpellPower, (uint)damage);
}
public int GetBonusDamage() { return m_bonusSpellDamage; }
+3 -1
View File
@@ -66,7 +66,9 @@ namespace Game.Entities
{
_isMoving = true;
m_updateFlag = UpdateFlag.Transport | UpdateFlag.StationaryPosition | UpdateFlag.Rotation;
m_updateFlag.ServerTime = true;
m_updateFlag.Stationary = true;
m_updateFlag.Rotation = true;
}
public override void Dispose()
+24 -6
View File
@@ -622,6 +622,7 @@ namespace Game.Entities
damageInfo.damageSchoolMask = (uint)GetMeleeDamageSchoolMask();
damageInfo.attackType = attType;
damageInfo.damage = 0;
damageInfo.originalDamage = 0;
damageInfo.cleanDamage = 0;
damageInfo.absorb = 0;
damageInfo.resist = 0;
@@ -835,7 +836,7 @@ namespace Game.Entities
DamageInfo damageInfo1 = new DamageInfo(this, victim, damage, spellInfo, spellInfo.GetSchoolMask(), DamageEffectType.SpellDirect, WeaponAttackType.BaseAttack);
victim.CalcAbsorbResist(damageInfo1);
damage = damageInfo1.GetDamage();
// No Unit.CalcAbsorbResist here - opcode doesn't send that data - this damage is probably not affected by that
victim.DealDamageMods(this, ref damage);
SpellDamageShield damageShield = new SpellDamageShield();
@@ -843,6 +844,7 @@ namespace Game.Entities
damageShield.Defender = GetGUID();
damageShield.SpellID = spellInfo.Id;
damageShield.TotalDamage = damage;
damageShield.OriginalDamage = (int)damageInfo.originalDamage;
damageShield.OverKill = (uint)Math.Max(damage - GetHealth(), 0);
damageShield.SchoolMask = (uint)spellInfo.SchoolMask;
damageShield.LogAbsorbed = damageInfo1.GetAbsorb();
@@ -1183,6 +1185,7 @@ namespace Game.Entities
dmgInfo.attacker = this;
dmgInfo.target = target;
dmgInfo.damage = Damage - AbsorbDamage - Resist - BlockedAmount;
dmgInfo.originalDamage = Damage;
dmgInfo.damageSchoolMask = (uint)damageSchoolMask;
dmgInfo.absorb = AbsorbDamage;
dmgInfo.resist = Resist;
@@ -1197,6 +1200,7 @@ namespace Game.Entities
packet.AttackerGUID = damageInfo.attacker.GetGUID();
packet.VictimGUID = damageInfo.target.GetGUID();
packet.Damage = (int)damageInfo.damage;
packet.OriginalDamage = (int)damageInfo.originalDamage;
int overkill = (int)(damageInfo.damage - damageInfo.target.GetHealth());
packet.OverDamage = (overkill < 0 ? -1 : overkill);
@@ -1212,9 +1216,9 @@ namespace Game.Entities
packet.BlockAmount = (int)damageInfo.blocked_amount;
packet.LogData.Initialize(damageInfo.attacker);
SandboxScalingData sandboxScalingData = new SandboxScalingData();
if (sandboxScalingData.GenerateDataForUnits(damageInfo.attacker, damageInfo.target))
packet.SandboxScaling = sandboxScalingData;
ContentTuningParams contentTuningParams = new ContentTuningParams();
if (contentTuningParams.GenerateDataForUnits(damageInfo.attacker, damageInfo.target))
packet.ContentTuning = contentTuningParams;
SendCombatLogMessage(packet);
}
@@ -1321,6 +1325,8 @@ namespace Game.Entities
unit.SetInCombatState(PvP, enemy);
unit.SetFlag(UnitFields.Flags, UnitFlags.PetInCombat);
}
ProcSkillsAndAuras(enemy, ProcFlags.EnterCombat, ProcFlags.None, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null);
}
internal void SendCombatLogMessage(CombatLogServerPacket combatLog)
@@ -1770,6 +1776,7 @@ namespace Game.Entities
damageInfo.damageSchoolMask = (uint)SpellSchoolMask.Normal;
damageInfo.attackType = attackType;
damageInfo.damage = 0;
damageInfo.originalDamage = 0;
damageInfo.cleanDamage = 0;
damageInfo.absorb = 0;
damageInfo.resist = 0;
@@ -1838,18 +1845,20 @@ namespace Game.Entities
case MeleeHitOutcome.Evade:
damageInfo.HitInfo |= HitInfo.Miss | HitInfo.SwingNoHitSound;
damageInfo.TargetState = VictimState.Evades;
damageInfo.originalDamage = damageInfo.damage;
damageInfo.damage = 0;
damageInfo.cleanDamage = 0;
return;
case MeleeHitOutcome.Miss:
damageInfo.HitInfo |= HitInfo.Miss;
damageInfo.TargetState = VictimState.Intact;
damageInfo.originalDamage = damageInfo.damage;
damageInfo.damage = 0;
damageInfo.cleanDamage = 0;
break;
case MeleeHitOutcome.Normal:
damageInfo.TargetState = VictimState.Hit;
damageInfo.originalDamage = damageInfo.damage;
break;
case MeleeHitOutcome.Crit:
damageInfo.HitInfo |= HitInfo.CriticalHit;
@@ -1862,19 +1871,25 @@ namespace Game.Entities
if (mod != 0)
MathFunctions.AddPct(ref damageInfo.damage, mod);
damageInfo.originalDamage = damageInfo.damage;
break;
case MeleeHitOutcome.Parry:
damageInfo.TargetState = VictimState.Parry;
damageInfo.originalDamage = damageInfo.damage;
damageInfo.cleanDamage += damageInfo.damage;
damageInfo.damage = 0;
break;
case MeleeHitOutcome.Dodge:
damageInfo.TargetState = VictimState.Dodge;
damageInfo.originalDamage = damageInfo.damage;
damageInfo.cleanDamage += damageInfo.damage;
damageInfo.damage = 0;
break;
case MeleeHitOutcome.Block:
damageInfo.TargetState = VictimState.Hit;
damageInfo.HitInfo |= HitInfo.Block;
damageInfo.originalDamage = damageInfo.damage;
// 30% damage blocked, double blocked amount if block is critical
damageInfo.blocked_amount = MathFunctions.CalculatePct(damageInfo.damage, damageInfo.target.isBlockCritical() ? damageInfo.target.GetBlockPercent() * 2 : damageInfo.target.GetBlockPercent());
damageInfo.damage -= damageInfo.blocked_amount;
@@ -1883,6 +1898,7 @@ namespace Game.Entities
case MeleeHitOutcome.Glancing:
damageInfo.HitInfo |= HitInfo.Glancing;
damageInfo.TargetState = VictimState.Hit;
damageInfo.originalDamage = damageInfo.damage;
int leveldif = (int)victim.getLevel() - (int)getLevel();
if (leveldif > 3)
leveldif = 3;
@@ -1896,6 +1912,7 @@ namespace Game.Entities
damageInfo.TargetState = VictimState.Hit;
// 150% normal damage
damageInfo.damage += (damageInfo.damage / 2);
damageInfo.originalDamage = damageInfo.damage;
break;
default:
@@ -2495,6 +2512,7 @@ namespace Game.Entities
CleanDamage cleanDamage = new CleanDamage(splitDamage, 0, WeaponAttackType.BaseAttack, MeleeHitOutcome.Normal);
DealDamage(caster, splitDamage, cleanDamage, DamageEffectType.Direct, damageInfo.GetSchoolMask(), itr.GetSpellInfo(), false);
log.damage = splitDamage;
log.originalDamage = splitDamage;
log.absorb = split_absorb;
SendSpellNonMeleeDamageLog(log);
@@ -2682,7 +2700,7 @@ namespace Game.Entities
for (var i = SpellSchools.Holy; i < SpellSchools.Max; ++i)
{
if (Convert.ToBoolean((int)spellProto.GetSchoolMask() & (1 << (int)i)))
maxModDamagePercentSchool = Math.Max(maxModDamagePercentSchool, GetFloatValue(PlayerFields.ModDamageDonePct + (int)i));
maxModDamagePercentSchool = Math.Max(maxModDamagePercentSchool, GetFloatValue(ActivePlayerFields.ModDamageDonePct + (int)i));
}
DoneTotalMod *= maxModDamagePercentSchool;
+13 -2
View File
@@ -226,6 +226,7 @@ namespace Game.Entities
m_attacker = attacker;
m_victim = victim;
m_damage = damage;
m_originalDamage = damage;
m_spellInfo = spellInfo;
m_schoolMask = schoolMask;
m_damageType = damageType;
@@ -237,6 +238,7 @@ namespace Game.Entities
m_attacker = dmgInfo.attacker;
m_victim = dmgInfo.target;
m_damage = dmgInfo.damage;
m_originalDamage = dmgInfo.damage;
m_spellInfo = null;
m_schoolMask = (SpellSchoolMask)dmgInfo.damageSchoolMask;
m_damageType = DamageEffectType.Direct;
@@ -357,6 +359,7 @@ namespace Game.Entities
DamageEffectType GetDamageType() { return m_damageType; }
public WeaponAttackType GetAttackType() { return m_attackType; }
public uint GetDamage() { return m_damage; }
public uint GetOriginalDamage() { return m_originalDamage; }
public uint GetAbsorb() { return m_absorb; }
public uint GetResist() { return m_resist; }
uint GetBlock() { return m_block; }
@@ -365,6 +368,7 @@ namespace Game.Entities
Unit m_attacker;
Unit m_victim;
uint m_damage;
uint m_originalDamage;
SpellInfo m_spellInfo;
SpellSchoolMask m_schoolMask;
DamageEffectType m_damageType;
@@ -382,6 +386,7 @@ namespace Game.Entities
_healer = healer;
_target = target;
_heal = heal;
_originalHeal = heal;
_spellInfo = spellInfo;
_schoolMask = schoolMask;
}
@@ -400,6 +405,7 @@ namespace Game.Entities
public Unit GetHealer() { return _healer; }
public Unit GetTarget() { return _target; }
public uint GetHeal() { return _heal; }
public uint GetOriginalHeal() { return _originalHeal; }
public uint GetEffectiveHeal() { return _effectiveHeal; }
public uint GetAbsorb() { return _absorb; }
public SpellInfo GetSpellInfo() { return _spellInfo; }
@@ -409,6 +415,7 @@ namespace Game.Entities
Unit _healer;
Unit _target;
uint _heal;
uint _originalHeal;
uint _effectiveHeal;
uint _absorb;
SpellInfo _spellInfo;
@@ -422,6 +429,7 @@ namespace Game.Entities
public Unit target { get; set; } // Target for damage
public uint damageSchoolMask { get; set; }
public uint damage;
public uint originalDamage;
public uint absorb;
public uint resist;
public uint blocked_amount { get; set; }
@@ -454,6 +462,7 @@ namespace Game.Entities
public uint SpellId;
public uint SpellXSpellVisualID;
public uint damage;
public uint originalDamage;
public SpellSchoolMask schoolMask;
public uint absorb;
public uint resist;
@@ -528,10 +537,11 @@ namespace Game.Entities
public class SpellPeriodicAuraLogInfo
{
public SpellPeriodicAuraLogInfo(AuraEffect _auraEff, uint _damage, int _overDamage, uint _absorb, uint _resist, float _multiplier, bool _critical)
public SpellPeriodicAuraLogInfo(AuraEffect _auraEff, uint _damage, uint _originalDamage, uint _overDamage, uint _absorb, uint _resist, float _multiplier, bool _critical)
{
auraEff = _auraEff;
damage = _damage;
originalDamage = _originalDamage;
overDamage = _overDamage;
absorb = _absorb;
resist = _resist;
@@ -541,7 +551,8 @@ namespace Game.Entities
public AuraEffect auraEff;
public uint damage;
public int overDamage; // overkill/overheal
public uint originalDamage;
public uint overDamage; // overkill/overheal
public uint absorb;
public uint resist;
public float multiplier;
+16 -3
View File
@@ -543,7 +543,8 @@ namespace Game.Entities
return false;
}
bool turn = (GetOrientation() != orientation);
// Check if angular distance changed
bool turn = MathFunctions.fuzzyGt(Math.PI - Math.Abs(Math.Abs(GetOrientation() - orientation) - Math.PI), 0.0f);
// G3D::fuzzyEq won't help here, in some cases magnitudes differ by a little more than G3D::eps, but should be considered equal
bool relocated = (teleport ||
Math.Abs(GetPositionX() - x) > 0.001f ||
@@ -1290,6 +1291,12 @@ namespace Game.Entities
player.UnsummonPetTemporaryIfAny();
}
// if we have charmed npc, stun him also (everywhere)
Unit charm = player.GetCharm();
if (charm)
if (charm.GetTypeId() == TypeId.Unit)
charm.SetFlag(UnitFields.Flags, UnitFlags.Stunned);
player.SendMovementSetCollisionHeight(player.GetCollisionHeight(true));
}
@@ -1335,6 +1342,12 @@ namespace Game.Entities
}
else
player.ResummonPetTemporaryUnSummonedIfAny();
// 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);
}
}
@@ -1345,7 +1358,7 @@ namespace Game.Entities
return false;
m_vehicleKit = new Vehicle(this, vehInfo, creatureEntry);
m_updateFlag |= UpdateFlag.Vehicle;
m_updateFlag.Vehicle = true;
m_unitTypeMask |= UnitTypeMask.Vehicle;
if (!loading)
@@ -1366,7 +1379,7 @@ namespace Game.Entities
m_vehicleKit = null;
m_updateFlag &= ~UpdateFlag.Vehicle;
m_updateFlag.Vehicle = false;
m_unitTypeMask &= ~UnitTypeMask.Vehicle;
RemoveFlag64(UnitFields.NpcFlags, NPCFlags.SpellClick | NPCFlags.PlayerVehicle);
}
+1 -1
View File
@@ -202,7 +202,7 @@ namespace Game.Entities
{
SetCritterGUID(minion.GetGUID());
if (GetTypeId() == TypeId.Player)
minion.SetGuidValue(UnitFields.BattlePetCompanionGuid, GetGuidValue(PlayerFields.SummonedBattlePetId));
minion.SetGuidValue(UnitFields.BattlePetCompanionGuid, GetGuidValue(ActivePlayerFields.SummonedBattlePetId));
}
// PvP, FFAPvP
+21 -33
View File
@@ -47,7 +47,7 @@ namespace Game.Entities
{
if (IsTypeId(TypeId.Player))
{
float overrideSP = GetFloatValue(PlayerFields.OverrideSpellPowerByApPct);
float overrideSP = GetFloatValue(ActivePlayerFields.OverrideSpellPowerByApPct);
if (overrideSP > 0.0f)
return (int)(MathFunctions.CalculatePct(GetTotalAttackPowerValue(WeaponAttackType.BaseAttack), overrideSP) + 0.5f);
}
@@ -190,7 +190,7 @@ namespace Game.Entities
for (int i = 0; i < (int)SpellSchools.Max; ++i)
{
if (Convert.ToBoolean((int)spellProto.GetSchoolMask() & (1 << i)))
maxModDamagePercentSchool = Math.Max(maxModDamagePercentSchool, GetFloatValue(PlayerFields.ModDamageDonePct + i));
maxModDamagePercentSchool = Math.Max(maxModDamagePercentSchool, GetFloatValue(ActivePlayerFields.ModDamageDonePct + i));
}
}
else
@@ -338,7 +338,7 @@ namespace Game.Entities
{
if (IsTypeId(TypeId.Player))
{
float overrideSP = GetFloatValue(PlayerFields.OverrideSpellPowerByApPct);
float overrideSP = GetFloatValue(ActivePlayerFields.OverrideSpellPowerByApPct);
if (overrideSP > 0.0f)
return (uint)(MathFunctions.CalculatePct(GetTotalAttackPowerValue(WeaponAttackType.BaseAttack), overrideSP) + 0.5f);
}
@@ -503,7 +503,7 @@ namespace Game.Entities
return 1.0f;
if (IsPlayer())
return GetFloatValue(PlayerFields.ModHealingDonePct);
return GetFloatValue(ActivePlayerFields.ModHealingDonePct);
float DoneTotalMod = 1.0f;
@@ -640,7 +640,7 @@ namespace Game.Entities
crit_chance = 0.0f;
// For other schools
else if (IsTypeId(TypeId.Player))
crit_chance = GetFloatValue(PlayerFields.CritPercentage);
crit_chance = GetFloatValue(ActivePlayerFields.CritPercentage);
else
crit_chance = m_baseSpellCritChance;
@@ -1588,11 +1588,13 @@ namespace Game.Entities
var schoolList = m_spellImmune[(int)SpellImmunity.School];
foreach (var pair in schoolList)
{
if ((pair.Key & (uint)spellInfo.GetSchoolMask()) == 0)
continue;
SpellInfo immuneSpellInfo = Global.SpellMgr.GetSpellInfo(pair.Value);
if (Convert.ToBoolean(pair.Key & (uint)spellInfo.GetSchoolMask())
&& !(immuneSpellInfo != null && immuneSpellInfo.IsPositive() && spellInfo.IsPositive() && IsFriendlyTo(caster))
&& !spellInfo.CanPierceImmuneAura(immuneSpellInfo))
return true;
if (!(immuneSpellInfo != null && immuneSpellInfo.IsPositive() && spellInfo.IsPositive() && caster && IsFriendlyTo(caster)))
if (!spellInfo.CanPierceImmuneAura(immuneSpellInfo))
return true;
}
return false;
@@ -2234,29 +2236,13 @@ namespace Game.Entities
spellHealLog.TargetGUID = healInfo.GetTarget().GetGUID();
spellHealLog.CasterGUID = healInfo.GetHealer().GetGUID();
spellHealLog.SpellID = healInfo.GetSpellInfo().Id;
spellHealLog.Health = healInfo.GetHeal();
spellHealLog.OriginalHeal = (int)healInfo.GetOriginalHeal();
spellHealLog.OverHeal = healInfo.GetHeal() - healInfo.GetEffectiveHeal();
spellHealLog.Absorbed = healInfo.GetAbsorb();
spellHealLog.Crit = critical;
// @todo: 6.x Has to be implemented
/*
var hasCritRollMade = spellHealLog.WriteBit("HasCritRollMade");
var hasCritRollNeeded = spellHealLog.WriteBit("HasCritRollNeeded");
var hasLogData = spellHealLog.WriteBit("HasLogData");
if (hasCritRollMade)
packet.ReadSingle("CritRollMade");
if (hasCritRollNeeded)
packet.ReadSingle("CritRollNeeded");
if (hasLogData)
SpellParsers.ReadSpellCastLogData(packet);
*/
spellHealLog.LogData.Initialize(healInfo.GetTarget());
SendCombatLogMessage(spellHealLog);
}
@@ -2411,6 +2397,7 @@ namespace Game.Entities
damage = 0;
damageInfo.damage = (uint)damage;
damageInfo.originalDamage = (uint)damage;
DamageInfo dmgInfo = new DamageInfo(damageInfo, DamageEffectType.SpellDirect, WeaponAttackType.BaseAttack, ProcFlagsHit.None);
CalcAbsorbResist(dmgInfo);
damageInfo.absorb = dmgInfo.GetAbsorb();
@@ -2456,6 +2443,7 @@ namespace Game.Entities
packet.CastID = log.castId;
packet.SpellID = (int)log.SpellId;
packet.Damage = (int)log.damage;
packet.OriginalDamage = (int)log.originalDamage;
if (log.damage > log.preHitHealth)
packet.Overkill = (int)(log.damage - log.preHitHealth);
else
@@ -2468,9 +2456,9 @@ namespace Game.Entities
packet.Periodic = log.periodicLog;
packet.Flags = (int)log.HitInfo;
SandboxScalingData sandboxScalingData = new SandboxScalingData();
if (sandboxScalingData.GenerateDataForUnits(log.attacker, log.target))
packet.SandboxScaling.Set(sandboxScalingData);
ContentTuningParams contentTuningParams = new ContentTuningParams();
if (contentTuningParams.GenerateDataForUnits(log.attacker, log.target))
packet.ContentTuning.Set(contentTuningParams);
SendCombatLogMessage(packet);
}
@@ -2488,6 +2476,7 @@ namespace Game.Entities
SpellPeriodicAuraLog.SpellLogEffect spellLogEffect = new SpellPeriodicAuraLog.SpellLogEffect();
spellLogEffect.Effect = (uint)aura.GetAuraType();
spellLogEffect.Amount = info.damage;
spellLogEffect.OriginalDamage = (int)info.originalDamage;
spellLogEffect.OverHealOrKill = (uint)info.overDamage;
spellLogEffect.SchoolMaskOrPower = (uint)aura.GetSpellInfo().GetSchoolMask();
spellLogEffect.AbsorbedOrAmplitude = info.absorb;
@@ -2495,11 +2484,10 @@ namespace Game.Entities
spellLogEffect.Crit = info.critical;
// @todo: implement debug info
SandboxScalingData sandboxScalingData = new SandboxScalingData();
ContentTuningParams contentTuningParams = new ContentTuningParams();
Unit caster = Global.ObjAccessor.GetUnit(this, aura.GetCasterGUID());
if (caster)
if (sandboxScalingData.GenerateDataForUnits(caster, this))
spellLogEffect.SandboxScaling.Set(sandboxScalingData);
if (caster && contentTuningParams.GenerateDataForUnits(caster, this))
spellLogEffect.ContentTuning.Set(contentTuningParams);
data.Effects.Add(spellLogEffect);
+15 -12
View File
@@ -48,7 +48,7 @@ namespace Game.Entities
objectTypeId = TypeId.Unit;
objectTypeMask |= TypeMask.Unit;
m_updateFlag = UpdateFlag.Living;
m_updateFlag.MovementUpdate = true;
m_modAttackSpeedPct = new float[] { 1.0f, 1.0f, 1.0f };
m_deathState = DeathState.Alive;
@@ -2076,9 +2076,9 @@ namespace Game.Entities
{
return (Race)GetByteValue(UnitFields.Bytes0, 0);
}
public long getRaceMask()
public ulong getRaceMask()
{
return (1 << ((int)GetRace() - 1));
return (1ul << ((int)GetRace() - 1));
}
public Class GetClass()
{
@@ -2093,13 +2093,15 @@ namespace Game.Entities
return (Gender)GetByteValue(UnitFields.Bytes0, 3);
}
public void SetNativeDisplayId(uint modelId)
public void SetNativeDisplayId(uint displayId, float displayScale = 1f)
{
SetUInt32Value(UnitFields.NativeDisplayId, modelId);
SetUInt32Value(UnitFields.NativeDisplayId, displayId);
SetFloatValue(UnitFields.NativeXDisplayScale, displayScale);
}
public virtual void SetDisplayId(uint modelId)
public virtual void SetDisplayId(uint modelId, float displayScale = 1f)
{
SetUInt32Value(UnitFields.DisplayId, modelId);
SetFloatValue(UnitFields.DisplayScale, displayScale);
// Set Gender by modelId
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelInfo(modelId);
if (minfo != null)
@@ -2109,7 +2111,10 @@ namespace Game.Entities
{
return GetUInt32Value(UnitFields.NativeDisplayId);
}
public float GetNativeDisplayScale()
{
return GetFloatValue(UnitFields.NativeXDisplayScale);
}
public virtual Unit GetOwner()
{
ObjectGuid ownerid = GetOwnerGUID();
@@ -2570,7 +2575,7 @@ namespace Game.Entities
{
CreatureTemplate ci = Global.ObjectMgr.GetCreatureTemplate((uint)eff.GetMiscValue());
if (ci != null)
if (!IsDisallowedMountForm(eff.GetId(), ShapeShiftForm.None, ObjectManager.ChooseDisplayId(ci)))
if (!IsDisallowedMountForm(eff.GetId(), ShapeShiftForm.None, ObjectManager.ChooseDisplayId(ci).CreatureDisplayID))
handledAura = eff;
}
}
@@ -2642,7 +2647,7 @@ namespace Game.Entities
if (target == this)
visibleFlag |= UpdateFieldFlags.Private;
else if (IsTypeId(TypeId.Player))
valCount = (int)PlayerFields.EndNotSelf;
valCount = (int)PlayerFields.End;
UpdateMask updateMask = new UpdateMask(valCount);
@@ -2684,8 +2689,6 @@ namespace Game.Entities
}
// 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.ResistanceBuffModsPositive && index < ((int)UnitFields.ResistanceBuffModsPositive + (int)SpellSchools.Max)) ||
(index >= (int)UnitFields.ResistanceBuffModsNegative && index < ((int)UnitFields.ResistanceBuffModsNegative + (int)SpellSchools.Max)) ||
(index >= (int)UnitFields.PosStat && index < (int)UnitFields.PosStat + (int)Stats.Max))
{
fieldBuffer.WriteUInt32((uint)GetFloatValue(index));
@@ -2727,7 +2730,7 @@ namespace Game.Entities
if (cinfo.FlagsExtra.HasAnyFlag(CreatureFlagsExtra.Trigger))
if (target.IsGameMaster())
displayId = cinfo.GetFirstVisibleModel();
displayId = cinfo.GetFirstVisibleModel().CreatureDisplayID;
}
fieldBuffer.WriteUInt32(displayId);
+15
View File
@@ -175,6 +175,11 @@ namespace Game.Entities
// why we need to apply this? we can simple add immunities to slow mechanic in DB
_me.ApplySpellImmune(0, SpellImmunity.State, AuraType.ModDecreaseSpeed, true);
break;
case 335: // Salvaged Chopper
case 336: // Salvaged Siege Engine
case 338: // Salvaged Demolisher
_me.ApplySpellImmune(0, SpellImmunity.State, AuraType.ModDamagePercentTaken, false); // Battering Ram
break;
default:
break;
}
@@ -342,6 +347,10 @@ namespace Game.Entities
if (seat.Value.SeatInfo.CanEnterOrExit() && ++UsableSeatNum != 0)
_me.SetFlag64(UnitFields.NpcFlags, (_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)
unit.SetDisableGravity(false);
// 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);
@@ -552,6 +561,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.IsGravityDisabled = Passenger.HasUnitMovementFlag(MovementFlag.DisableGravity);
if (Seat.Value.SeatInfo.CanEnterOrExit())
{
Cypher.Assert(Target.UsableSeatNum != 0);
@@ -585,6 +595,9 @@ namespace Game.Entities
player.UnsummonPetTemporaryIfAny();
}
if (veSeat.Flags.HasAnyFlag(VehicleSeatFlags.DisableGravity))
Passenger.SetDisableGravity(true);
if (Seat.Value.SeatInfo.Flags.HasAnyFlag(VehicleSeatFlags.PassengerNotSelectable))
Passenger.SetFlag(UnitFields.Flags, UnitFlags.NotSelectable);
@@ -657,11 +670,13 @@ namespace Game.Entities
{
public ObjectGuid Guid;
public bool IsUnselectable;
public bool IsGravityDisabled;
public void Reset()
{
Guid = ObjectGuid.Empty;
IsUnselectable = false;
IsGravityDisabled = false;
}
}