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
+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))