Core/Creatures: Move creature difficulty specific data from creature_template table to creature_template_difficulty
Port From (https://github.com/TrinityCore/TrinityCore/commit/06d0b16f158e8793860d9edd11b990f20b1d0dac)
This commit is contained in:
@@ -12,6 +12,7 @@ namespace Game.Entities
|
||||
{
|
||||
CreatureTemplate m_creatureInfo;
|
||||
CreatureData m_creatureData;
|
||||
CreatureDifficulty m_creatureDifficulty;
|
||||
|
||||
string[] m_stringIds = new string[3];
|
||||
string m_scriptStringId;
|
||||
|
||||
@@ -211,53 +211,30 @@ namespace Game.Entities
|
||||
|
||||
public bool InitEntry(uint entry, CreatureData data = null)
|
||||
{
|
||||
CreatureTemplate normalInfo = Global.ObjectMgr.GetCreatureTemplate(entry);
|
||||
if (normalInfo == null)
|
||||
CreatureTemplate creatureInfo = Global.ObjectMgr.GetCreatureTemplate(entry);
|
||||
if (creatureInfo == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Creature.InitEntry creature entry {0} does not exist.", entry);
|
||||
return false;
|
||||
}
|
||||
|
||||
// get difficulty 1 mode entry
|
||||
CreatureTemplate cInfo = null;
|
||||
DifficultyRecord difficultyEntry = CliDB.DifficultyStorage.LookupByKey(GetMap().GetDifficultyID());
|
||||
while (cInfo == null && difficultyEntry != null)
|
||||
{
|
||||
int idx = CreatureTemplate.DifficultyIDToDifficultyEntryIndex(difficultyEntry.Id);
|
||||
if (idx == -1)
|
||||
break;
|
||||
|
||||
if (normalInfo.DifficultyEntry[idx] != 0)
|
||||
{
|
||||
cInfo = Global.ObjectMgr.GetCreatureTemplate(normalInfo.DifficultyEntry[idx]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (difficultyEntry.FallbackDifficultyID == 0)
|
||||
break;
|
||||
|
||||
difficultyEntry = CliDB.DifficultyStorage.LookupByKey(difficultyEntry.FallbackDifficultyID);
|
||||
}
|
||||
|
||||
if (cInfo == null)
|
||||
cInfo = normalInfo;
|
||||
|
||||
SetEntry(entry); // normal entry always
|
||||
m_creatureInfo = cInfo; // map mode related always
|
||||
m_creatureInfo = creatureInfo;
|
||||
SetEntry(entry);
|
||||
m_creatureDifficulty = creatureInfo.GetDifficulty(GetMap().GetDifficultyID());
|
||||
|
||||
// equal to player Race field, but creature does not have race
|
||||
SetRace(0);
|
||||
SetClass((Class)cInfo.UnitClass);
|
||||
SetClass((Class)creatureInfo.UnitClass);
|
||||
|
||||
// Cancel load if no model defined
|
||||
if (cInfo.GetFirstValidModel() == null)
|
||||
if (creatureInfo.GetFirstValidModel() == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) has no model defined in table `creature_template`, can't load. ", entry);
|
||||
return false;
|
||||
}
|
||||
|
||||
CreatureModel model = ObjectManager.ChooseDisplayId(cInfo, data);
|
||||
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelRandomGender(ref model, cInfo);
|
||||
CreatureModel model = ObjectManager.ChooseDisplayId(creatureInfo, data);
|
||||
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelRandomGender(ref model, creatureInfo);
|
||||
if (minfo == null) // Cancel load if no model defined
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) has invalid model {1} defined in table `creature_template`, can't load.", entry, model.CreatureDisplayID);
|
||||
@@ -277,7 +254,7 @@ namespace Game.Entities
|
||||
LoadEquipment(data.equipmentId);
|
||||
}
|
||||
|
||||
SetName(normalInfo.Name); // at normal entry always
|
||||
SetName(creatureInfo.Name); // at normal entry always
|
||||
|
||||
SetModCastingSpeed(1.0f);
|
||||
SetModSpellHaste(1.0f);
|
||||
@@ -286,25 +263,25 @@ namespace Game.Entities
|
||||
SetModHasteRegen(1.0f);
|
||||
SetModTimeRate(1.0f);
|
||||
|
||||
SetSpeedRate(UnitMoveType.Walk, cInfo.SpeedWalk);
|
||||
SetSpeedRate(UnitMoveType.Run, cInfo.SpeedRun);
|
||||
SetSpeedRate(UnitMoveType.Walk, creatureInfo.SpeedWalk);
|
||||
SetSpeedRate(UnitMoveType.Run, creatureInfo.SpeedRun);
|
||||
SetSpeedRate(UnitMoveType.Swim, 1.0f); // using 1.0 rate
|
||||
SetSpeedRate(UnitMoveType.Flight, 1.0f); // using 1.0 rate
|
||||
|
||||
SetObjectScale(GetNativeObjectScale());
|
||||
|
||||
SetCanDualWield(cInfo.FlagsExtra.HasAnyFlag(CreatureFlagsExtra.UseOffhandAttack));
|
||||
SetCanDualWield(creatureInfo.FlagsExtra.HasAnyFlag(CreatureFlagsExtra.UseOffhandAttack));
|
||||
|
||||
// checked at loading
|
||||
DefaultMovementType = (MovementGeneratorType)(data != null ? data.movementType : cInfo.MovementType);
|
||||
DefaultMovementType = (MovementGeneratorType)(data != null ? data.movementType : creatureInfo.MovementType);
|
||||
if (m_wanderDistance == 0 && DefaultMovementType == MovementGeneratorType.Random)
|
||||
DefaultMovementType = MovementGeneratorType.Idle;
|
||||
|
||||
for (byte i = 0; i < SharedConst.MaxCreatureSpells; ++i)
|
||||
m_spells[i] = GetCreatureTemplate().Spells[i];
|
||||
|
||||
_staticFlags.ApplyFlag(CreatureStaticFlags.NoXp, cInfo.CreatureType == CreatureType.Critter || IsPet() || IsTotem() || cInfo.FlagsExtra.HasFlag(CreatureFlagsExtra.NoXP));
|
||||
_staticFlags.ApplyFlag(CreatureStaticFlags4.TreatAsRaidUnitForHelpfulSpells, cInfo.TypeFlags.HasFlag(CreatureTypeFlags.TreatAsRaidUnit));
|
||||
_staticFlags.ApplyFlag(CreatureStaticFlags.NoXp, creatureInfo.CreatureType == CreatureType.Critter || IsPet() || IsTotem() || creatureInfo.FlagsExtra.HasFlag(CreatureFlagsExtra.NoXP));
|
||||
_staticFlags.ApplyFlag(CreatureStaticFlags4.TreatAsRaidUnitForHelpfulSpells, GetCreatureDifficulty().TypeFlags.HasFlag(CreatureTypeFlags.TreatAsRaidUnit));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -808,6 +785,8 @@ namespace Game.Entities
|
||||
return false;
|
||||
}
|
||||
|
||||
CreatureDifficulty creatureDifficulty = cinfo.GetDifficulty(GetMap().GetDifficultyID());
|
||||
|
||||
//! Relocate before CreateFromProto, to initialize coords and allow
|
||||
//! returning correct zone id for selecting OutdoorPvP/Battlefield script
|
||||
Relocate(pos);
|
||||
@@ -828,7 +807,7 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
// Allow players to see those units while dead, do it here (mayby altered by addon auras)
|
||||
if (cinfo.TypeFlags.HasAnyFlag(CreatureTypeFlags.VisibleToGhosts))
|
||||
if (creatureDifficulty.TypeFlags.HasAnyFlag(CreatureTypeFlags.VisibleToGhosts))
|
||||
m_serverSideVisibility.SetValue(ServerSideVisibilityType.Ghost, GhostVisibilityType.Alive | GhostVisibilityType.Ghost);
|
||||
|
||||
if (!CreateFromProto(guidlow, entry, data, vehId))
|
||||
@@ -1050,7 +1029,7 @@ namespace Game.Entities
|
||||
{
|
||||
base.AtEngage(target);
|
||||
|
||||
if (!GetCreatureTemplate().TypeFlags.HasAnyFlag(CreatureTypeFlags.AllowMountedCombat))
|
||||
if (!GetCreatureDifficulty().TypeFlags.HasFlag(CreatureTypeFlags.AllowMountedCombat))
|
||||
Dismount();
|
||||
|
||||
RefreshCanSwimFlag();
|
||||
@@ -1199,7 +1178,7 @@ namespace Game.Entities
|
||||
if (_lootId.HasValue)
|
||||
return _lootId.Value;
|
||||
|
||||
return GetCreatureTemplate().LootId;
|
||||
return GetCreatureDifficulty().LootID;
|
||||
}
|
||||
|
||||
public void SetLootId(uint? lootId)
|
||||
@@ -1470,7 +1449,7 @@ namespace Game.Entities
|
||||
// mana
|
||||
PowerType powerType = CalculateDisplayPowerType();
|
||||
SetCreateMana(stats.BaseMana);
|
||||
SetStatPctModifier(UnitMods.PowerStart + (int)powerType, UnitModifierPctType.Base, cInfo.ModMana * cInfo.ModManaExtra);
|
||||
SetStatPctModifier(UnitMods.PowerStart + (int)powerType, UnitModifierPctType.Base, GetCreatureDifficulty().ManaModifier);
|
||||
SetPowerType(powerType);
|
||||
|
||||
PowerTypeRecord powerTypeEntry = Global.DB2Mgr.GetPowerTypeEntry(powerType);
|
||||
@@ -2208,7 +2187,7 @@ namespace Game.Entities
|
||||
if (IsPet())
|
||||
return false;
|
||||
|
||||
return Convert.ToBoolean(GetCreatureTemplate().TypeFlags & CreatureTypeFlags.BossMob);
|
||||
return GetCreatureDifficulty().TypeFlags.HasFlag(CreatureTypeFlags.BossMob);
|
||||
}
|
||||
|
||||
// select nearest hostile unit within the given distance (regardless of threat list).
|
||||
@@ -2462,7 +2441,7 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
// dependent from difficulty mode entry
|
||||
return Global.ObjectMgr.GetCreatureTemplateAddon(GetCreatureTemplate().Entry);
|
||||
return Global.ObjectMgr.GetCreatureTemplateAddon(GetEntry());
|
||||
}
|
||||
|
||||
public bool LoadCreaturesAddon()
|
||||
@@ -2716,29 +2695,29 @@ namespace Game.Entities
|
||||
|
||||
public void ApplyLevelScaling()
|
||||
{
|
||||
CreatureLevelScaling scaling = GetCreatureTemplate().GetLevelScaling(GetMap().GetDifficultyID());
|
||||
var levels = Global.DB2Mgr.GetContentTuningData(scaling.ContentTuningID, 0);
|
||||
CreatureDifficulty creatureDifficulty = GetCreatureDifficulty();
|
||||
var levels = Global.DB2Mgr.GetContentTuningData(creatureDifficulty.ContentTuningID, 0);
|
||||
if (levels.HasValue)
|
||||
{
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ScalingLevelMin), levels.Value.MinLevel);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ScalingLevelMax), levels.Value.MaxLevel);
|
||||
}
|
||||
|
||||
int mindelta = Math.Min(scaling.DeltaLevelMax, scaling.DeltaLevelMin);
|
||||
int maxdelta = Math.Max(scaling.DeltaLevelMax, scaling.DeltaLevelMin);
|
||||
int mindelta = Math.Min(creatureDifficulty.DeltaLevelMax, creatureDifficulty.DeltaLevelMin);
|
||||
int maxdelta = Math.Max(creatureDifficulty.DeltaLevelMax, creatureDifficulty.DeltaLevelMin);
|
||||
int delta = mindelta == maxdelta ? mindelta : RandomHelper.IRand(mindelta, maxdelta);
|
||||
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ScalingLevelDelta), delta);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ContentTuningID), scaling.ContentTuningID);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ContentTuningID), creatureDifficulty.ContentTuningID);
|
||||
}
|
||||
|
||||
ulong GetMaxHealthByLevel(uint level)
|
||||
{
|
||||
CreatureTemplate cInfo = GetCreatureTemplate();
|
||||
CreatureLevelScaling scaling = cInfo.GetLevelScaling(GetMap().GetDifficultyID());
|
||||
float baseHealth = Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureHealth, level, cInfo.GetHealthScalingExpansion(), scaling.ContentTuningID, (Class)cInfo.UnitClass);
|
||||
CreatureDifficulty creatureDifficulty = GetCreatureDifficulty();
|
||||
float baseHealth = Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureHealth, level, creatureDifficulty.GetHealthScalingExpansion(), creatureDifficulty.ContentTuningID, (Class)cInfo.UnitClass);
|
||||
|
||||
return (ulong)Math.Max(baseHealth * cInfo.ModHealth * cInfo.ModHealthExtra, 1.0f);
|
||||
return (ulong)Math.Max(baseHealth * creatureDifficulty.HealthModifier, 1.0f);
|
||||
}
|
||||
|
||||
public override float GetHealthMultiplierForTarget(WorldObject target)
|
||||
@@ -2756,8 +2735,8 @@ namespace Game.Entities
|
||||
public float GetBaseDamageForLevel(uint level)
|
||||
{
|
||||
CreatureTemplate cInfo = GetCreatureTemplate();
|
||||
CreatureLevelScaling scaling = cInfo.GetLevelScaling(GetMap().GetDifficultyID());
|
||||
return Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureAutoAttackDps, level, cInfo.GetHealthScalingExpansion(), scaling.ContentTuningID, (Class)cInfo.UnitClass);
|
||||
CreatureDifficulty creatureDifficulty = GetCreatureDifficulty();
|
||||
return Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureAutoAttackDps, level, creatureDifficulty.GetHealthScalingExpansion(), creatureDifficulty.ContentTuningID, (Class)cInfo.UnitClass);
|
||||
}
|
||||
|
||||
public override float GetDamageMultiplierForTarget(WorldObject target)
|
||||
@@ -2773,9 +2752,9 @@ namespace Game.Entities
|
||||
float GetBaseArmorForLevel(uint level)
|
||||
{
|
||||
CreatureTemplate cInfo = GetCreatureTemplate();
|
||||
CreatureLevelScaling scaling = cInfo.GetLevelScaling(GetMap().GetDifficultyID());
|
||||
float baseArmor = Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureArmor, level, cInfo.GetHealthScalingExpansion(), scaling.ContentTuningID, (Class)cInfo.UnitClass);
|
||||
return baseArmor * cInfo.ModArmor;
|
||||
CreatureDifficulty creatureDifficulty = GetCreatureDifficulty();
|
||||
float baseArmor = Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureArmor, level, creatureDifficulty.GetHealthScalingExpansion(), creatureDifficulty.ContentTuningID, (Class)cInfo.UnitClass);
|
||||
return baseArmor * creatureDifficulty.ArmorModifier;
|
||||
}
|
||||
|
||||
public override float GetArmorMultiplierForTarget(WorldObject target)
|
||||
@@ -3317,7 +3296,8 @@ namespace Game.Entities
|
||||
|
||||
public CreatureTemplate GetCreatureTemplate() { return m_creatureInfo; }
|
||||
public CreatureData GetCreatureData() { return m_creatureData; }
|
||||
|
||||
public CreatureDifficulty GetCreatureDifficulty() { return m_creatureDifficulty; }
|
||||
|
||||
public override bool LoadFromDB(ulong spawnId, Map map, bool addToMap, bool allowDuplicate)
|
||||
{
|
||||
if (!allowDuplicate)
|
||||
|
||||
@@ -7,13 +7,13 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using Game.Networking.Packets;
|
||||
using Game.Maps;
|
||||
using Game.DataStorage;
|
||||
|
||||
namespace Game.Entities
|
||||
{
|
||||
public class CreatureTemplate
|
||||
{
|
||||
public uint Entry;
|
||||
public uint[] DifficultyEntry = new uint[SharedConst.MaxCreatureDifficulties];
|
||||
public uint[] KillCredit = new uint[SharedConst.MaxCreatureKillCredit];
|
||||
public List<CreatureModel> Models = new();
|
||||
public string Name;
|
||||
@@ -22,8 +22,7 @@ namespace Game.Entities
|
||||
public string TitleAlt;
|
||||
public string IconName;
|
||||
public List<uint> GossipMenuIds = new();
|
||||
public Dictionary<Difficulty, CreatureLevelScaling> scalingStorage = new();
|
||||
public int HealthScalingExpansion;
|
||||
public Dictionary<Difficulty, CreatureDifficulty> difficultyStorage = new();
|
||||
public uint RequiredExpansion;
|
||||
public uint VignetteID; // @todo Read Vignette.db2
|
||||
public uint Faction;
|
||||
@@ -45,29 +44,15 @@ namespace Game.Entities
|
||||
public CreatureFamily Family;
|
||||
public Class TrainerClass;
|
||||
public CreatureType CreatureType;
|
||||
public CreatureTypeFlags TypeFlags;
|
||||
public uint TypeFlags2;
|
||||
public uint LootId;
|
||||
public uint PickPocketId;
|
||||
public uint SkinLootId;
|
||||
public int[] Resistance = new int[7];
|
||||
public uint[] Spells = new uint[8];
|
||||
public uint VehicleId;
|
||||
public uint MinGold;
|
||||
public uint MaxGold;
|
||||
public string AIName;
|
||||
public uint MovementType;
|
||||
public CreatureMovementData Movement = new();
|
||||
public float ModHealth;
|
||||
public float ModHealthExtra;
|
||||
public float ModMana;
|
||||
public float ModManaExtra;
|
||||
public float ModArmor;
|
||||
public float ModDamage;
|
||||
public float ModExperience;
|
||||
public bool RacialLeader;
|
||||
public uint MovementId;
|
||||
public int CreatureDifficultyID;
|
||||
public int WidgetSetID;
|
||||
public int WidgetSetUnitConditionID;
|
||||
public bool RegenHealth;
|
||||
@@ -77,7 +62,7 @@ namespace Game.Entities
|
||||
public uint ScriptID;
|
||||
public string StringId;
|
||||
|
||||
public QueryCreatureResponse QueryData;
|
||||
public QueryCreatureResponse[] QueryData = new QueryCreatureResponse[(int)Locale.Total];
|
||||
|
||||
public CreatureModel GetModelByIdx(int idx)
|
||||
{
|
||||
@@ -142,74 +127,33 @@ namespace Game.Entities
|
||||
return CreatureModel.DefaultVisibleModel;
|
||||
}
|
||||
|
||||
public int GetHealthScalingExpansion()
|
||||
public bool IsExotic(CreatureDifficulty creatureDifficulty)
|
||||
{
|
||||
return HealthScalingExpansion == (int)Expansion.LevelCurrent ? (int)Expansion.WarlordsOfDraenor : HealthScalingExpansion;
|
||||
return creatureDifficulty.TypeFlags.HasFlag(CreatureTypeFlags.TameableExotic);
|
||||
}
|
||||
|
||||
public SkillType GetRequiredLootSkill()
|
||||
public bool IsTameable(bool canTameExotic, CreatureDifficulty creatureDifficulty)
|
||||
{
|
||||
if (TypeFlags.HasAnyFlag(CreatureTypeFlags.SkinWithHerbalism))
|
||||
return SkillType.Herbalism;
|
||||
else if (TypeFlags.HasAnyFlag(CreatureTypeFlags.SkinWithMining))
|
||||
return SkillType.Mining;
|
||||
else if (TypeFlags.HasAnyFlag(CreatureTypeFlags.SkinWithEngineering))
|
||||
return SkillType.Engineering;
|
||||
else
|
||||
return SkillType.Skinning; // normal case
|
||||
}
|
||||
|
||||
public bool IsExotic()
|
||||
{
|
||||
return (TypeFlags & CreatureTypeFlags.TameableExotic) != 0;
|
||||
}
|
||||
public bool IsTameable(bool canTameExotic)
|
||||
{
|
||||
if (CreatureType != CreatureType.Beast || Family == CreatureFamily.None || !TypeFlags.HasAnyFlag(CreatureTypeFlags.Tameable))
|
||||
if (CreatureType != CreatureType.Beast || Family == CreatureFamily.None || !creatureDifficulty.TypeFlags.HasFlag(CreatureTypeFlags.Tameable))
|
||||
return false;
|
||||
|
||||
// if can tame exotic then can tame any tameable
|
||||
return canTameExotic || !IsExotic();
|
||||
}
|
||||
|
||||
public static int DifficultyIDToDifficultyEntryIndex(uint difficulty)
|
||||
{
|
||||
switch ((Difficulty)difficulty)
|
||||
{
|
||||
case Difficulty.None:
|
||||
case Difficulty.Normal:
|
||||
case Difficulty.Raid10N:
|
||||
case Difficulty.Raid40:
|
||||
case Difficulty.Scenario3ManN:
|
||||
case Difficulty.NormalRaid:
|
||||
return -1;
|
||||
case Difficulty.Heroic:
|
||||
case Difficulty.Raid25N:
|
||||
case Difficulty.Scenario3ManHC:
|
||||
case Difficulty.HeroicRaid:
|
||||
return 0;
|
||||
case Difficulty.Raid10HC:
|
||||
case Difficulty.MythicKeystone:
|
||||
case Difficulty.MythicRaid:
|
||||
return 1;
|
||||
case Difficulty.Raid25HC:
|
||||
return 2;
|
||||
case Difficulty.LFR:
|
||||
case Difficulty.LFRNew:
|
||||
case Difficulty.EventRaid:
|
||||
case Difficulty.EventDungeon:
|
||||
case Difficulty.EventScenario:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return canTameExotic || !IsExotic(creatureDifficulty);
|
||||
}
|
||||
|
||||
public void InitializeQueryData()
|
||||
{
|
||||
QueryData = new QueryCreatureResponse();
|
||||
for (var loc = Locale.enUS; loc < Locale.Total; ++loc)
|
||||
QueryData[(int)loc] = BuildQueryData(loc, Difficulty.None);
|
||||
}
|
||||
|
||||
QueryData.CreatureID = Entry;
|
||||
QueryData.Allow = true;
|
||||
public QueryCreatureResponse BuildQueryData(Locale locale, Difficulty difficulty)
|
||||
{
|
||||
CreatureDifficulty creatureDifficulty = GetDifficulty(difficulty);
|
||||
|
||||
var queryTemp = new QueryCreatureResponse();
|
||||
|
||||
queryTemp.CreatureID = Entry;
|
||||
queryTemp.Allow = true;
|
||||
|
||||
CreatureStats stats = new();
|
||||
stats.Leader = RacialLeader;
|
||||
@@ -217,8 +161,8 @@ namespace Game.Entities
|
||||
stats.Name[0] = Name;
|
||||
stats.NameAlt[0] = FemaleName;
|
||||
|
||||
stats.Flags[0] = (uint)TypeFlags;
|
||||
stats.Flags[1] = TypeFlags2;
|
||||
stats.Flags[0] = (uint)creatureDifficulty.TypeFlags;
|
||||
stats.Flags[1] = creatureDifficulty.TypeFlags2;
|
||||
|
||||
stats.CreatureType = (int)CreatureType;
|
||||
stats.CreatureFamily = (int)Family;
|
||||
@@ -233,15 +177,15 @@ namespace Game.Entities
|
||||
stats.Display.CreatureDisplay.Add(new CreatureXDisplay(model.CreatureDisplayID, model.DisplayScale, model.Probability));
|
||||
}
|
||||
|
||||
stats.HpMulti = ModHealth;
|
||||
stats.EnergyMulti = ModMana;
|
||||
stats.HpMulti = creatureDifficulty.HealthModifier;
|
||||
stats.EnergyMulti = creatureDifficulty.ManaModifier;
|
||||
|
||||
stats.CreatureMovementInfoID = MovementId;
|
||||
stats.RequiredExpansion = RequiredExpansion;
|
||||
stats.HealthScalingExpansion = HealthScalingExpansion;
|
||||
stats.HealthScalingExpansion = creatureDifficulty.HealthScalingExpansion;
|
||||
stats.VignetteID = VignetteID;
|
||||
stats.Class = (int)UnitClass;
|
||||
stats.CreatureDifficultyID = CreatureDifficultyID;
|
||||
stats.CreatureDifficultyID = creatureDifficulty.CreatureDifficultyID;
|
||||
stats.WidgetSetID = WidgetSetID;
|
||||
stats.WidgetSetUnitConditionID = WidgetSetUnitConditionID;
|
||||
|
||||
@@ -249,20 +193,41 @@ namespace Game.Entities
|
||||
stats.TitleAlt = TitleAlt;
|
||||
stats.CursorName = IconName;
|
||||
|
||||
var items = Global.ObjectMgr.GetCreatureQuestItemList(Entry);
|
||||
var items = Global.ObjectMgr.GetCreatureQuestItemList(Entry, difficulty);
|
||||
if (items != null)
|
||||
stats.QuestItems.AddRange(items);
|
||||
|
||||
QueryData.Stats = stats;
|
||||
if (locale != Locale.enUS)
|
||||
{
|
||||
CreatureLocale creatureLocale = Global.ObjectMgr.GetCreatureLocale(Entry);
|
||||
if (creatureLocale != null)
|
||||
{
|
||||
string name = stats.Name[0];
|
||||
string nameAlt = stats.NameAlt[0];
|
||||
|
||||
ObjectManager.GetLocaleString(creatureLocale.Name, locale, ref name);
|
||||
ObjectManager.GetLocaleString(creatureLocale.NameAlt, locale, ref nameAlt);
|
||||
ObjectManager.GetLocaleString(creatureLocale.Title, locale, ref stats.Title);
|
||||
ObjectManager.GetLocaleString(creatureLocale.TitleAlt, locale, ref stats.TitleAlt);
|
||||
}
|
||||
}
|
||||
|
||||
queryTemp.Stats = stats;
|
||||
return queryTemp;
|
||||
}
|
||||
|
||||
public CreatureLevelScaling GetLevelScaling(Difficulty difficulty)
|
||||
public CreatureDifficulty GetDifficulty(Difficulty difficulty)
|
||||
{
|
||||
var creatureLevelScaling = scalingStorage.LookupByKey(difficulty);
|
||||
if (creatureLevelScaling != null)
|
||||
return creatureLevelScaling;
|
||||
var creatureDifficulty = difficultyStorage.LookupByKey(difficulty);
|
||||
if (creatureDifficulty != null)
|
||||
return creatureDifficulty;
|
||||
|
||||
return new CreatureLevelScaling();
|
||||
// If there is no data for the difficulty, try to get data for the fallback difficulty
|
||||
var difficultyEntry = CliDB.DifficultyStorage.LookupByKey(difficulty);
|
||||
if (difficultyEntry != null)
|
||||
return GetDifficulty((Difficulty)difficultyEntry.FallbackDifficultyID);
|
||||
|
||||
return new CreatureDifficulty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,7 +312,7 @@ namespace Game.Entities
|
||||
return $"Ground: {Ground}, Swim: {Swim}, Flight: {Flight} {(Rooted ? ", Rooted" : "")}, Chase: {Chase}, Random: {Random}, InteractionPauseTimer: {InteractionPauseTimer}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class CreatureModelInfo
|
||||
{
|
||||
public float BoundingRadius;
|
||||
@@ -462,10 +427,49 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public class CreatureLevelScaling
|
||||
public class CreatureDifficulty
|
||||
{
|
||||
public short DeltaLevelMin;
|
||||
public short DeltaLevelMax;
|
||||
public uint ContentTuningID;
|
||||
public int HealthScalingExpansion;
|
||||
public float HealthModifier;
|
||||
public float ManaModifier;
|
||||
public float ArmorModifier;
|
||||
public float DamageModifier;
|
||||
public int CreatureDifficultyID;
|
||||
public CreatureTypeFlags TypeFlags;
|
||||
public uint TypeFlags2;
|
||||
public uint LootID;
|
||||
public uint PickPocketLootID;
|
||||
public uint SkinLootID;
|
||||
public uint GoldMin;
|
||||
public uint GoldMax;
|
||||
|
||||
public CreatureDifficulty()
|
||||
{
|
||||
HealthModifier = 1.0f;
|
||||
ManaModifier = 1.0f;
|
||||
ArmorModifier = 1.0f;
|
||||
DamageModifier = 1.0f;
|
||||
}
|
||||
|
||||
// Helpers
|
||||
public int GetHealthScalingExpansion()
|
||||
{
|
||||
return HealthScalingExpansion == (int)Expansion.LevelCurrent ? (int)PlayerConst.CurrentExpansion : HealthScalingExpansion;
|
||||
}
|
||||
|
||||
public SkillType GetRequiredLootSkill()
|
||||
{
|
||||
if (TypeFlags.HasFlag(CreatureTypeFlags.SkinWithHerbalism))
|
||||
return SkillType.Herbalism;
|
||||
else if (TypeFlags.HasFlag(CreatureTypeFlags.SkinWithMining))
|
||||
return SkillType.Mining;
|
||||
else if (TypeFlags.HasFlag(CreatureTypeFlags.SkinWithEngineering))
|
||||
return SkillType.Engineering;
|
||||
else
|
||||
return SkillType.Skinning; // Default case
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2773,7 +2773,7 @@ namespace Game.Entities
|
||||
{
|
||||
Creature creatureTarget = target.ToCreature();
|
||||
if (creatureTarget != null)
|
||||
return creatureTarget.HasFlag(CreatureStaticFlags4.TreatAsRaidUnitForHelpfulSpells) || creatureTarget.GetCreatureTemplate().TypeFlags.HasAnyFlag(CreatureTypeFlags.CanAssist);
|
||||
return creatureTarget.HasFlag(CreatureStaticFlags4.TreatAsRaidUnitForHelpfulSpells) || creatureTarget.GetCreatureDifficulty().TypeFlags.HasFlag(CreatureTypeFlags.CanAssist);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ namespace Game.Entities
|
||||
if (petInfo.Type == PetType.Hunter)
|
||||
{
|
||||
CreatureTemplate creatureInfo = Global.ObjectMgr.GetCreatureTemplate(petInfo.CreatureId);
|
||||
if (creatureInfo == null || !creatureInfo.IsTameable(owner.CanTameExoticPets()))
|
||||
if (creatureInfo == null || !creatureInfo.IsTameable(owner.CanTameExoticPets(), GetCreatureDifficulty()))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -5169,11 +5169,11 @@ namespace Game.Entities
|
||||
return null;
|
||||
|
||||
// Deathstate checks
|
||||
if (!IsAlive() && !Convert.ToBoolean(creature.GetCreatureTemplate().TypeFlags & CreatureTypeFlags.VisibleToGhosts))
|
||||
if (!IsAlive() && !creature.GetCreatureDifficulty().TypeFlags.HasFlag(CreatureTypeFlags.VisibleToGhosts))
|
||||
return null;
|
||||
|
||||
// alive or spirit healer
|
||||
if (!creature.IsAlive() && !Convert.ToBoolean(creature.GetCreatureTemplate().TypeFlags & CreatureTypeFlags.InteractWhileDead))
|
||||
if (!creature.IsAlive() && !creature.GetCreatureDifficulty().TypeFlags.HasFlag(CreatureTypeFlags.InteractWhileDead))
|
||||
return null;
|
||||
|
||||
// appropriate npc type
|
||||
|
||||
@@ -2254,7 +2254,7 @@ namespace Game.Entities
|
||||
float basePct = GetPctModifierValue(unitMod, UnitModifierPctType.Base) * attackSpeedMulti;
|
||||
float totalValue = GetFlatModifierValue(unitMod, UnitModifierFlatType.Total);
|
||||
float totalPct = addTotalPct ? GetPctModifierValue(unitMod, UnitModifierPctType.Total) : 1.0f;
|
||||
float dmgMultiplier = GetCreatureTemplate().ModDamage; // = ModDamage * _GetDamageMod(rank);
|
||||
float dmgMultiplier = GetCreatureDifficulty().DamageModifier; // = DamageModifier * _GetDamageMod(rank);
|
||||
|
||||
minDamage = ((weaponMinDamage + baseValue) * dmgMultiplier * basePct + totalValue) * totalPct;
|
||||
maxDamage = ((weaponMaxDamage + baseValue) * dmgMultiplier * basePct + totalValue) * totalPct;
|
||||
|
||||
@@ -584,7 +584,8 @@ namespace Game.Entities
|
||||
CreatureBaseStats stats = Global.ObjectMgr.GetCreatureBaseStats(petlevel, cinfo.UnitClass);
|
||||
ApplyLevelScaling();
|
||||
|
||||
SetCreateHealth((uint)Math.Max(Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureHealth, petlevel, cinfo.GetHealthScalingExpansion(), m_unitData.ContentTuningID, (Class)cinfo.UnitClass) * cinfo.ModHealth * cinfo.ModHealthExtra * GetHealthMod(cinfo.Rank), 1.0f));
|
||||
CreatureDifficulty creatureDifficulty = GetCreatureDifficulty();
|
||||
SetCreateHealth((uint)Math.Max(Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureHealth, petlevel, creatureDifficulty.GetHealthScalingExpansion(), m_unitData.ContentTuningID, (Class)cinfo.UnitClass) * creatureDifficulty.HealthModifier * GetHealthMod(cinfo.Rank), 1.0f));
|
||||
SetCreateMana(stats.BaseMana);
|
||||
|
||||
SetCreateStat(Stats.Strength, 22);
|
||||
|
||||
@@ -772,7 +772,7 @@ namespace Game.Entities
|
||||
if (dungeonEncounter != null)
|
||||
{
|
||||
creature.m_personalLoot = LootManager.GenerateDungeonEncounterPersonalLoot(dungeonEncounter.Id, creature.GetLootId(),
|
||||
LootStorage.Creature, LootType.Corpse, creature, creature.GetCreatureTemplate().MinGold, creature.GetCreatureTemplate().MaxGold,
|
||||
LootStorage.Creature, LootType.Corpse, creature, creature.GetCreatureDifficulty().GoldMin, creature.GetCreatureDifficulty().GoldMax,
|
||||
(ushort)creature.GetLootMode(), creature.GetMap().GetDifficultyLootItemContext(), tappers);
|
||||
}
|
||||
else if (!tappers.Empty())
|
||||
@@ -787,7 +787,7 @@ namespace Game.Entities
|
||||
loot.FillLoot(lootid, LootStorage.Creature, looter, dungeonEncounter != null, false, creature.GetLootMode(), creature.GetMap().GetDifficultyLootItemContext());
|
||||
|
||||
if (creature.GetLootMode() > 0)
|
||||
loot.GenerateMoneyLoot(creature.GetCreatureTemplate().MinGold, creature.GetCreatureTemplate().MaxGold);
|
||||
loot.GenerateMoneyLoot(creature.GetCreatureDifficulty().GoldMin, creature.GetCreatureDifficulty().GoldMax);
|
||||
|
||||
if (group)
|
||||
loot.NotifyLootList(creature.GetMap());
|
||||
@@ -814,7 +814,7 @@ namespace Game.Entities
|
||||
loot.FillLoot(lootid, LootStorage.Creature, tapper, true, false, creature.GetLootMode(), creature.GetMap().GetDifficultyLootItemContext());
|
||||
|
||||
if (creature.GetLootMode() > 0)
|
||||
loot.GenerateMoneyLoot(creature.GetCreatureTemplate().MinGold, creature.GetCreatureTemplate().MaxGold);
|
||||
loot.GenerateMoneyLoot(creature.GetCreatureDifficulty().GoldMin, creature.GetCreatureDifficulty().GoldMax);
|
||||
|
||||
creature.m_personalLoot[tapper.GetGUID()] = loot;
|
||||
}
|
||||
@@ -918,7 +918,7 @@ namespace Game.Entities
|
||||
else
|
||||
creature.AllLootRemovedFromCorpse();
|
||||
|
||||
if (creature.CanHaveLoot() && LootStorage.Skinning.HaveLootFor(creature.GetCreatureTemplate().SkinLootId))
|
||||
if (creature.CanHaveLoot() && LootStorage.Skinning.HaveLootFor(creature.GetCreatureDifficulty().SkinLootID))
|
||||
{
|
||||
creature.SetDynamicFlag(UnitDynFlags.CanSkin);
|
||||
creature.SetUnitFlag(UnitFlags.Skinnable);
|
||||
|
||||
Reference in New Issue
Block a user