Implemented Basic Creature Scaling

Trainer followup
Misc Fixes
This commit is contained in:
hondacrx
2017-07-31 14:18:07 -04:00
parent 890ce8d81a
commit 473cea0f06
26 changed files with 370 additions and 96 deletions
+103 -17
View File
@@ -288,8 +288,8 @@ namespace Game.Entities
if (updateLevel)
SelectLevel();
UpdateLevelDependantStats();
else
UpdateLevelDependantStats(); // We still re-initialize level dependant stats on entry update
SetMeleeDamageSchool((SpellSchools)cInfo.DmgSchool);
SetModifierValue(UnitMods.ResistanceHoly, UnitModifierType.BaseValue, cInfo.Resistance[(int)SpellSchools.Holy]);
@@ -1090,11 +1090,23 @@ namespace Game.Entities
{
CreatureTemplate cInfo = GetCreatureTemplate();
// level
byte minlevel = (byte)Math.Min(cInfo.Maxlevel, cInfo.Minlevel);
byte maxlevel = (byte)Math.Max(cInfo.Maxlevel, cInfo.Minlevel);
byte level = (byte)(minlevel == maxlevel ? minlevel : RandomHelper.URand(minlevel, maxlevel));
SetLevel(level);
if (!HasScalableLevels())
{
// level
byte minlevel = (byte)Math.Min(cInfo.Maxlevel, cInfo.Minlevel);
byte maxlevel = (byte)Math.Max(cInfo.Maxlevel, cInfo.Minlevel);
byte level = (byte)(minlevel == maxlevel ? minlevel : RandomHelper.URand(minlevel, maxlevel));
SetLevel(level);
}
else
{
SetLevel(cInfo.levelScaling.Value.MaxLevel);
SetUInt32Value(UnitFields.ScalingLevelMin, cInfo.levelScaling.Value.MinLevel);
SetUInt32Value(UnitFields.ScalingLevelMax, cInfo.levelScaling.Value.MaxLevel);
SetUInt32Value(UnitFields.ScalingLevelDelta, (uint)cInfo.levelScaling.Value.DeltaLevel);
}
UpdateLevelDependantStats();
}
void UpdateLevelDependantStats()
@@ -1663,8 +1675,8 @@ namespace Game.Entities
if (m_originalEntry != GetEntry())
UpdateEntry(m_originalEntry);
SelectLevel();
else
SelectLevel();
setDeathState(DeathState.JustRespawned);
@@ -2344,17 +2356,91 @@ namespace Game.Entities
m_respawnTime = m_corpseRemoveTime + m_respawnDelay;
}
public bool HasScalableLevels()
{
CreatureTemplate cinfo = GetCreatureTemplate();
return cinfo.levelScaling.HasValue;
}
ulong GetMaxHealthByLevel(uint level)
{
CreatureTemplate cInfo = GetCreatureTemplate();
CreatureBaseStats stats = Global.ObjectMgr.GetCreatureBaseStats(level, cInfo.UnitClass);
return stats.GenerateHealth(cInfo);
}
float GetHealthMultiplierForTarget(WorldObject target)
{
if (!HasScalableLevels())
return 1.0f;
uint levelForTarget = GetLevelForTarget(target);
if (getLevel() < levelForTarget)
return 1.0f;
return GetMaxHealthByLevel(levelForTarget) / GetCreateHealth();
}
float GetBaseDamageForLevel(uint level)
{
CreatureTemplate cInfo = GetCreatureTemplate();
CreatureBaseStats stats = Global.ObjectMgr.GetCreatureBaseStats(level, cInfo.UnitClass);
return stats.GenerateBaseDamage(cInfo);
}
float GetDamageMultiplierForTarget(WorldObject target)
{
if (!HasScalableLevels())
return 1.0f;
uint levelForTarget = GetLevelForTarget(target);
return GetBaseDamageForLevel(levelForTarget) / GetBaseDamageForLevel(getLevel());
}
float GetBaseArmorForLevel(uint level)
{
CreatureTemplate cInfo = GetCreatureTemplate();
CreatureBaseStats stats = Global.ObjectMgr.GetCreatureBaseStats(level, cInfo.UnitClass);
return stats.GenerateArmor(cInfo);
}
float GetArmorMultiplierForTarget(WorldObject target)
{
if (!HasScalableLevels())
return 1.0f;
uint levelForTarget = GetLevelForTarget(target);
return GetBaseArmorForLevel(levelForTarget) / GetBaseArmorForLevel(getLevel());
}
public override uint GetLevelForTarget(WorldObject target)
{
if (!isWorldBoss() || !target.IsTypeId(TypeId.Unit))
return base.GetLevelForTarget(target);
Unit unitTarget = target.ToUnit();
if (unitTarget)
{
if (isWorldBoss())
{
int level = (int)(unitTarget.getLevel() + WorldConfig.GetIntValue(WorldCfg.WorldBossLevelDiff));
return (uint)MathFunctions.RoundToInterval(ref level, 1u, 255u);
}
uint level = target.ToUnit().getLevel() + WorldConfig.GetUIntValue(WorldCfg.WorldBossLevelDiff);
if (level < 1)
return 1;
if (level > 255)
return 255;
return level;
// If this creature should scale level, adapt level depending of target level
// between UNIT_FIELD_SCALING_LEVEL_MIN and UNIT_FIELD_SCALING_LEVEL_MAX
if (HasScalableLevels())
{
uint targetLevelWithDelta = (uint)(unitTarget.getLevel() + GetCreatureTemplate().levelScaling.Value.DeltaLevel);
if (target.IsPlayer())
targetLevelWithDelta += target.GetUInt32Value(PlayerFields.ScalingLevelDelta);
return MathFunctions.RoundToInterval(ref targetLevelWithDelta, GetUInt32Value(UnitFields.ScalingLevelMin), GetUInt32Value(UnitFields.ScalingLevelMax));
}
}
return base.GetLevelForTarget(target);
}
public string GetAIName()
+9
View File
@@ -19,6 +19,7 @@ using Framework.Collections;
using Framework.Constants;
using System;
using System.Collections.Generic;
using Framework.Dynamic;
namespace Game.Entities
{
@@ -37,6 +38,7 @@ namespace Game.Entities
public string IconName;
public uint GossipMenuId;
public short Minlevel;
public Optional<CreatureLevelScaling> levelScaling;
public short Maxlevel;
public int HealthScalingExpansion;
public uint RequiredExpansion;
@@ -384,4 +386,11 @@ namespace Game.Entities
m_items.Clear();
}
}
public struct CreatureLevelScaling
{
public ushort MinLevel;
public ushort MaxLevel;
public short DeltaLevel;
}
}
+10 -3
View File
@@ -18,7 +18,8 @@ namespace Game.Entities
public Array<uint> ReqAbility = new Array<uint>(3);
public byte ReqLevel;
public uint CastSpellId;
public uint LearnedSpellId;
public bool IsCastable() { return LearnedSpellId != SpellId; }
}
public class Trainer
@@ -84,8 +85,8 @@ namespace Game.Entities
player.SendPlaySpellVisualKit(362, 1, 0); // 113 EmoteSalute
// learn explicitly or cast explicitly
if (trainerSpell.CastSpellId != 0)
player.CastSpell(player, trainerSpell.CastSpellId, true);
if (trainerSpell.IsCastable())
player.CastSpell(player, trainerSpell.SpellId, true);
else
player.LearnSpell(trainerSpell.SpellId, false);
}
@@ -129,6 +130,12 @@ namespace Game.Entities
if (player.getLevel() < trainerSpell.ReqLevel)
return TrainerSpellState.Unavailable;
// check ranks
uint previousRankSpellId = Global.SpellMgr.GetPrevSpellInChain(trainerSpell.LearnedSpellId);
if (previousRankSpellId != 0)
if (!player.HasSpell(previousRankSpellId))
return TrainerSpellState.Unavailable;
// check additional spell requirement
foreach (var spellId in Global.SpellMgr.GetSpellsRequiredForSpellBounds(trainerSpell.SpellId))
if (!player.HasSpell(spellId))