fix: Adds name support for all mods (#1128)

This commit is contained in:
Kamron Batman 2022-10-15 10:46:31 -07:00 committed by GitHub
parent b1cf95f810
commit ffdc08259f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 404 additions and 343 deletions

View file

@ -1,4 +1,14 @@
{ {
"version": 0, "version": 0,
"type": "Server.MobileMod" "type": "Server.MobileMod",
"properties": [
{
"name": "Name",
"type": "string",
"rule": "PrimitiveTypeMigrationRule",
"ruleArguments": [
""
]
}
]
} }

View file

@ -20,14 +20,6 @@
"type": "Server.StatType", "type": "Server.StatType",
"rule": "EnumMigrationRule" "rule": "EnumMigrationRule"
}, },
{
"name": "Name",
"type": "string",
"rule": "PrimitiveTypeMigrationRule",
"ruleArguments": [
""
]
},
{ {
"name": "Offset", "name": "Offset",
"type": "int", "type": "int",

View file

@ -331,6 +331,9 @@ public class Mobile : IHued, IComparable<Mobile>, ISpawnable, IObjectPropertyLis
private IWeapon m_Weapon; private IWeapon m_Weapon;
private bool m_YellowHealthbar; private bool m_YellowHealthbar;
private List<StatMod> _statMods;
private List<ResistanceMod> _resistanceMods;
private List<SkillMod> _skillMods;
public Mobile() public Mobile()
{ {
@ -402,8 +405,6 @@ public class Mobile : IHued, IComparable<Mobile>, ISpawnable, IObjectPropertyLis
[CommandProperty(AccessLevel.Counselor)] [CommandProperty(AccessLevel.Counselor)]
public virtual int EnergyResistance => GetResistance(ResistanceType.Energy); public virtual int EnergyResistance => GetResistance(ResistanceType.Energy);
public List<ResistanceMod> ResistanceMods { get; set; }
public static int MaxPlayerResistance { get; set; } = 70; public static int MaxPlayerResistance { get; set; } = 70;
public virtual bool NewGuildDisplay => false; public virtual bool NewGuildDisplay => false;
@ -415,7 +416,9 @@ public class Mobile : IHued, IComparable<Mobile>, ISpawnable, IObjectPropertyLis
public object Party { get; set; } public object Party { get; set; }
public HashSet<SkillMod> SkillMods { get; private set; } public List<SkillMod> SkillMods => _skillMods;
public List<StatMod> StatMods => _statMods;
public List<ResistanceMod> ResistanceMods => _resistanceMods;
[CommandProperty(AccessLevel.GameMaster)] [CommandProperty(AccessLevel.GameMaster)]
public int VirtualArmorMod public int VirtualArmorMod
@ -1783,11 +1786,6 @@ public class Mobile : IHued, IComparable<Mobile>, ISpawnable, IObjectPropertyLis
} }
} }
/// <summary>
/// Gets a list of all <see cref="StatMod">StatMod's</see> currently active for the Mobile.
/// </summary>
public HashSet<StatMod> StatMods { get; private set; }
/// <summary> /// <summary>
/// Gets or sets the base, unmodified, strength of the Mobile. Ranges from 1 to 65000, inclusive. /// Gets or sets the base, unmodified, strength of the Mobile. Ranges from 1 to 65000, inclusive.
/// <seealso cref="Str" /> /// <seealso cref="Str" />
@ -1839,7 +1837,7 @@ public class Mobile : IHued, IComparable<Mobile>, ISpawnable, IObjectPropertyLis
get => Math.Clamp(m_Str + GetStatOffset(StatType.Str), 1, 65000); get => Math.Clamp(m_Str + GetStatOffset(StatType.Str), 1, 65000);
set set
{ {
if (StatMods.Count == 0) if (_statMods.Count == 0)
{ {
RawStr = value; RawStr = value;
} }
@ -1897,7 +1895,7 @@ public class Mobile : IHued, IComparable<Mobile>, ISpawnable, IObjectPropertyLis
get => Math.Clamp(m_Dex + GetStatOffset(StatType.Dex), 0, 65000); get => Math.Clamp(m_Dex + GetStatOffset(StatType.Dex), 0, 65000);
set set
{ {
if (StatMods.Count == 0) if (_statMods.Count == 0)
{ {
RawDex = value; RawDex = value;
} }
@ -1955,7 +1953,7 @@ public class Mobile : IHued, IComparable<Mobile>, ISpawnable, IObjectPropertyLis
get => Math.Clamp(m_Int + GetStatOffset(StatType.Int), 0, 65000); get => Math.Clamp(m_Int + GetStatOffset(StatType.Int), 0, 65000);
set set
{ {
if (StatMods.Count == 0) if (_statMods.Count == 0)
{ {
RawInt = value; RawInt = value;
} }
@ -3090,26 +3088,76 @@ public class Mobile : IHued, IComparable<Mobile>, ISpawnable, IObjectPropertyLis
return res; return res;
} }
public virtual void AddResistanceMod(ResistanceMod toAdd) public virtual void AddResistanceMod(ResistanceMod mod)
{ {
ResistanceMods ??= new List<ResistanceMod>(); if (mod == null)
{
return;
}
_resistanceMods ??= new List<ResistanceMod>();
_resistanceMods.Add(mod);
ResistanceMods.Add(toAdd);
UpdateResistances(); UpdateResistances();
} }
public virtual void RemoveResistanceMod(ResistanceMod toRemove) public virtual ResistanceMod GetResistanceMod(string name)
{ {
if (ResistanceMods != null) if (_resistanceMods == null || name == null)
{ {
ResistanceMods.Remove(toRemove); return null;
}
if (ResistanceMods.Count == 0) for (var i = 0; i < _resistanceMods.Count; i++)
{
var mod = _resistanceMods[i];
if (mod.Name == name)
{ {
ResistanceMods = null; return mod;
} }
} }
return null;
}
public virtual void RemoveResistanceMod(string name)
{
if (_resistanceMods == null || name == null)
{
return;
}
for (var i = _resistanceMods.Count - 1; i >= 0; i--)
{
var mod = _resistanceMods[i];
if (mod.Name == name)
{
_resistanceMods.RemoveAt(i);
}
}
if (_resistanceMods.Count == 0)
{
_resistanceMods = null;
}
UpdateResistances();
}
public virtual void RemoveResistanceMod(ResistanceMod mod)
{
if (_resistanceMods == null)
{
return;
}
_resistanceMods.Remove(mod);
if (_resistanceMods.Count == 0)
{
_resistanceMods = null;
}
UpdateResistances(); UpdateResistances();
} }
@ -3128,9 +3176,9 @@ public class Mobile : IHued, IComparable<Mobile>, ISpawnable, IObjectPropertyLis
Resistances[3] += BasePoisonResistance; Resistances[3] += BasePoisonResistance;
Resistances[4] += BaseEnergyResistance; Resistances[4] += BaseEnergyResistance;
for (var i = 0; i < ResistanceMods?.Count; ++i) for (var i = 0; i < _resistanceMods.Count; i++)
{ {
var mod = ResistanceMods[i]; var mod = _resistanceMods[i];
var v = (int)mod.Type; var v = (int)mod.Type;
if (v >= 0 && v < Resistances.Length) if (v >= 0 && v < Resistances.Length)
@ -3362,32 +3410,25 @@ public class Mobile : IHued, IComparable<Mobile>, ISpawnable, IObjectPropertyLis
{ {
} }
public virtual void UpdateSkillMods()
{
ValidateSkillMods();
foreach (var mod in SkillMods)
{
var sk = Skills[mod.Skill];
sk?.Update();
}
}
public virtual void ValidateSkillMods() public virtual void ValidateSkillMods()
{ {
using var queue = PooledRefQueue<SkillMod>.Create(8); if (_skillMods == null)
foreach (var mod in SkillMods)
{ {
return;
}
for (var i = _skillMods.Count - 1; i >= 0; i--)
{
var mod = _skillMods[i];
if (!mod.CheckCondition()) if (!mod.CheckCondition())
{ {
queue.Enqueue(mod); _skillMods.RemoveAt(i);
mod.Owner = null;
Skills[mod.Skill]?.Update();
} }
} }
while (queue.Count > 0)
{
InternalRemoveSkillMod(queue.Dequeue());
}
} }
public virtual void AddSkillMod(SkillMod mod) public virtual void AddSkillMod(SkillMod mod)
@ -3398,35 +3439,77 @@ public class Mobile : IHued, IComparable<Mobile>, ISpawnable, IObjectPropertyLis
} }
ValidateSkillMods(); ValidateSkillMods();
_skillMods ??= new List<SkillMod>();
_skillMods.Add(mod);
mod.Owner = this;
Skills[mod.Skill]?.Update();
}
if (SkillMods.Add(mod)) public virtual SkillMod GetSkillMod(string name)
{
if (_skillMods == null || name == null)
{ {
mod.Owner = this; return null;
}
var sk = Skills[mod.Skill]; ValidateSkillMods();
sk?.Update();
for (var i = 0; i < _skillMods.Count; i++)
{
var mod = _skillMods[i];
if (mod.Name == name)
{
return mod;
}
}
return null;
}
public virtual void RemoveSkillMod(string name)
{
if (_skillMods == null || name == null)
{
return;
}
for (var i = _skillMods.Count - 1; i >= 0; i--)
{
var mod = _skillMods[i];
if (mod.Name == name)
{
mod.Owner = null;
Skills[mod.Skill]?.Update();
_skillMods.RemoveAt(i);
}
}
ValidateSkillMods();
if (_skillMods.Count == 0)
{
_skillMods = null;
} }
} }
public virtual void RemoveSkillMod(SkillMod mod) public virtual void RemoveSkillMod(SkillMod mod)
{ {
if (mod == null) if (_skillMods == null || mod == null)
{ {
return; return;
} }
InternalRemoveSkillMod(mod); if (_skillMods.Remove(mod))
ValidateSkillMods();
}
private void InternalRemoveSkillMod(SkillMod mod)
{
if (SkillMods.Remove(mod))
{ {
mod.Owner = null; mod.Owner = null;
Skills[mod.Skill]?.Update();
}
var sk = Skills[mod.Skill]; ValidateSkillMods();
sk?.Update();
if (_skillMods.Count == 0)
{
_skillMods = null;
} }
} }
@ -6259,8 +6342,8 @@ public class Mobile : IHued, IComparable<Mobile>, ISpawnable, IObjectPropertyLis
m_DexLock = (StatLockType)reader.ReadByte(); m_DexLock = (StatLockType)reader.ReadByte();
m_IntLock = (StatLockType)reader.ReadByte(); m_IntLock = (StatLockType)reader.ReadByte();
StatMods = new HashSet<StatMod>(); _statMods = new List<StatMod>();
SkillMods = new HashSet<SkillMod>(); _skillMods = new List<SkillMod>();
if (version < 32) if (version < 32)
{ {
@ -7608,8 +7691,8 @@ public class Mobile : IHued, IComparable<Mobile>, ISpawnable, IObjectPropertyLis
m_FollowersMax = 5; m_FollowersMax = 5;
Skills = new Skills(this); Skills = new Skills(this);
Items = new List<Item>(); Items = new List<Item>();
StatMods = new HashSet<StatMod>(); _statMods = new List<StatMod>();
SkillMods = new HashSet<SkillMod>(); _skillMods = new List<SkillMod>();
Map = Map.Internal; Map = Map.Internal;
AutoPageNotify = true; AutoPageNotify = true;
Aggressors = new List<AggressorInfo>(); Aggressors = new List<AggressorInfo>();
@ -8293,43 +8376,58 @@ public class Mobile : IHued, IComparable<Mobile>, ISpawnable, IObjectPropertyLis
return false; return false;
} }
public bool RemoveStatMod(string name) public virtual void RemoveStatMod(string name)
{ {
StatMods ??= new HashSet<StatMod>(); if (_statMods == null || name == null)
StatMod mod = GetStatMod(name);
if (mod != null)
{ {
StatMods.Remove(mod); return;
CheckStatTimers();
Delta(MobileDelta.Stat | GetStatDelta(mod.Type));
return true;
} }
return false; for (var i = _statMods.Count - 1; i >= 0; i--)
{
var mod = _statMods[i];
if (mod.Name == name)
{
_statMods.RemoveAt(i);
CheckStatTimers();
Delta(MobileDelta.Stat | GetStatDelta(mod.Type));
}
}
if (_statMods.Count == 0)
{
_statMods = null;
}
} }
public StatMod GetStatMod(string name) public virtual StatMod GetStatMod(string name)
{ {
StatMods ??= new HashSet<StatMod>(); if (_statMods == null || name == null)
foreach (var check in StatMods)
{ {
if (check.Name == name) return null;
}
for (var i = 0; i < _statMods.Count; i++)
{
var mod = _statMods[i];
if (mod.Name == name)
{ {
return check; return mod;
} }
} }
return null; return null;
} }
public void AddStatMod(StatMod mod) public virtual void AddStatMod(StatMod mod)
{ {
RemoveStatMod(mod.Name); if (mod == null)
{
return;
}
StatMods.Add(mod); _statMods.Add(mod);
Delta(MobileDelta.Stat | GetStatDelta(mod.Type)); Delta(MobileDelta.Stat | GetStatDelta(mod.Type));
CheckStatTimers(); CheckStatTimers();
} }
@ -8361,32 +8459,35 @@ public class Mobile : IHued, IComparable<Mobile>, ISpawnable, IObjectPropertyLis
/// </summary> /// </summary>
public int GetStatOffset(StatType type) public int GetStatOffset(StatType type)
{ {
_statMods ??= new List<StatMod>();
if (_statMods.Count <= 0)
{
return 0;
}
var offset = 0; var offset = 0;
StatMods ??= new HashSet<StatMod>(); using var queue = PooledRefQueue<StatMod>.Create(8);
for (var i = 0; i < _statMods.Count; i++)
if (StatMods.Count > 0)
{ {
using var queue = PooledRefQueue<StatMod>.Create(8); var mod = _statMods[i];
foreach (var mod in StatMods) if (mod.HasElapsed())
{ {
if (mod.HasElapsed()) queue.Enqueue(mod);
{
queue.Enqueue(mod);
}
else if ((mod.Type & type) != 0)
{
offset += mod.Offset;
}
} }
else if ((mod.Type & type) != 0)
{
offset += mod.Offset;
}
}
while (queue.Count > 0) while (queue.Count > 0)
{ {
var mod = queue.Dequeue(); var mod = queue.Dequeue();
StatMods.Remove(mod); _statMods.Remove(mod);
Delta(MobileDelta.Stat | GetStatDelta(mod.Type)); Delta(MobileDelta.Stat | GetStatDelta(mod.Type));
CheckStatTimers(); CheckStatTimers();
}
} }
return offset; return offset;

View file

@ -24,7 +24,7 @@ public partial class DefaultSkillMod : SkillMod
{ {
} }
public DefaultSkillMod(SkillName skill, bool relative, double value) : base(skill, relative, value) public DefaultSkillMod(SkillName skill, string name, bool relative, double value) : base(skill, name, relative, value)
{ {
} }

View file

@ -27,8 +27,8 @@ public partial class EquippedSkillMod : SkillMod
{ {
} }
public EquippedSkillMod(SkillName skill, bool relative, double value, Item item, Mobile mobile) public EquippedSkillMod(SkillName skill, string name, bool relative, double value, Item item, Mobile owner)
: base(skill, relative, value, mobile) => _item = item; : base(skill, name, relative, value, owner) => _item = item;
public override bool CheckCondition() => !_item.Deleted && Owner?.Deleted == false && _item.Parent == Owner; public override bool CheckCondition() => !_item.Deleted && Owner?.Deleted == false && _item.Parent == Owner;
} }

View file

@ -23,5 +23,14 @@ public partial class MobileMod
[DirtyTrackingEntity] [DirtyTrackingEntity]
public Mobile Owner { get; set; } public Mobile Owner { get; set; }
[SerializableField(0)]
private string _name;
public MobileMod(Mobile owner) => Owner = owner; public MobileMod(Mobile owner) => Owner = owner;
public MobileMod(Mobile owner, string name)
{
Owner = owner;
Name = name;
}
} }

View file

@ -24,7 +24,7 @@ public partial class ResistanceMod : MobileMod
{ {
} }
public ResistanceMod(ResistanceType type, int offset, Mobile owner = null) : base(owner) public ResistanceMod(ResistanceType type, string name, int offset, Mobile owner = null) : base(owner, name)
{ {
_type = type; _type = type;
_offset = offset; _offset = offset;

View file

@ -25,7 +25,7 @@ public abstract partial class SkillMod : MobileMod
{ {
} }
public SkillMod(SkillName skill, bool relative, double value, Mobile owner = null) : base(owner) public SkillMod(SkillName skill, string name, bool relative, double value, Mobile owner = null) : base(owner, name)
{ {
_skill = skill; _skill = skill;
_relative = relative; _relative = relative;

View file

@ -31,19 +31,15 @@ public partial class StatMod : MobileMod
private StatType _type; private StatType _type;
[SerializableField(3, setter: "private")] [SerializableField(3, setter: "private")]
private string _name;
[SerializableField(4, setter: "private")]
private int _offset; private int _offset;
public StatMod(Mobile owner) : base(owner) public StatMod(Mobile owner) : base(owner)
{ {
} }
public StatMod(StatType type, string name, int offset, TimeSpan duration, Mobile owner = null) : base(owner) public StatMod(StatType type, string name, int offset, TimeSpan duration, Mobile owner = null) : base(owner, name)
{ {
_type = type; _type = type;
_name = name;
_offset = offset; _offset = offset;
_duration = duration; _duration = duration;
_added = Core.Now; _added = Core.Now;

View file

@ -28,13 +28,13 @@ public partial class TimedSkillMod : SkillMod
{ {
} }
public TimedSkillMod(SkillName skill, bool relative, double value, TimeSpan delay) public TimedSkillMod(SkillName skill, string name, bool relative, double value, TimeSpan delay)
: this(skill, relative, value, Core.Now + delay) : this(skill, name, relative, value, Core.Now + delay)
{ {
} }
public TimedSkillMod(SkillName skill, bool relative, double value, DateTime expire) public TimedSkillMod(SkillName skill, string name, bool relative, double value, DateTime expire)
: base(skill, relative, value) => _expire = expire; : base(skill, name, relative, value) => _expire = expire;
public override bool CheckCondition() => Core.Now < _expire; public override bool CheckCondition() => Core.Now < _expire;
} }

View file

@ -1329,7 +1329,12 @@ namespace Server.Factions
if (baseValue > 0) if (baseValue > 0)
{ {
SkillMod mod = new DefaultSkillMod(sk.SkillName, true, -(baseValue * SkillLossFactor)); SkillMod mod = new DefaultSkillMod(
sk.SkillName,
$"{sk.Name}FactionSkillLoss",
true,
-(baseValue * SkillLossFactor)
);
mods.Add(mod); mods.Add(mod);
mob.AddSkillMod(mod); mob.AddSkillMod(mod);

View file

@ -38,7 +38,7 @@ namespace Server.Items
} }
else if (m_SkillMod == null && Parent is Mobile mobile) else if (m_SkillMod == null && Parent is Mobile mobile)
{ {
m_SkillMod = new DefaultSkillMod(SkillName.Blacksmith, true, m_Bonus); m_SkillMod = new DefaultSkillMod(SkillName.Blacksmith, "AncientSmithyHammer", true, m_Bonus);
mobile.AddSkillMod(m_SkillMod); mobile.AddSkillMod(m_SkillMod);
} }
else if (m_SkillMod != null) else if (m_SkillMod != null)
@ -59,7 +59,7 @@ namespace Server.Items
{ {
m_SkillMod?.Remove(); m_SkillMod?.Remove();
m_SkillMod = new DefaultSkillMod(SkillName.Blacksmith, true, m_Bonus); m_SkillMod = new DefaultSkillMod(SkillName.Blacksmith, "AncientSmithyHammer", true, m_Bonus);
mobile.AddSkillMod(m_SkillMod); mobile.AddSkillMod(m_SkillMod);
} }
} }
@ -111,7 +111,7 @@ namespace Server.Items
{ {
m_SkillMod?.Remove(); m_SkillMod?.Remove();
m_SkillMod = new DefaultSkillMod(SkillName.Blacksmith, true, m_Bonus); m_SkillMod = new DefaultSkillMod(SkillName.Blacksmith, "AncientSmithyHammer", true, m_Bonus);
mobile.AddSkillMod(m_SkillMod); mobile.AddSkillMod(m_SkillMod);
} }

View file

@ -164,7 +164,7 @@ namespace Server.Items
} }
else if (m_SkillMod == null && Parent is Mobile mobile) else if (m_SkillMod == null && Parent is Mobile mobile)
{ {
m_SkillMod = new DefaultSkillMod(SkillName.Mining, true, m_Bonus); m_SkillMod = new DefaultSkillMod(SkillName.Mining, "MiningGloves", true, m_Bonus);
mobile.AddSkillMod(m_SkillMod); mobile.AddSkillMod(m_SkillMod);
} }
else if (m_SkillMod != null) else if (m_SkillMod != null)
@ -182,7 +182,7 @@ namespace Server.Items
{ {
m_SkillMod?.Remove(); m_SkillMod?.Remove();
m_SkillMod = new DefaultSkillMod(SkillName.Mining, true, m_Bonus); m_SkillMod = new DefaultSkillMod(SkillName.Mining, "MiningGloves", true, m_Bonus);
mobile.AddSkillMod(m_SkillMod); mobile.AddSkillMod(m_SkillMod);
} }
} }
@ -234,7 +234,7 @@ namespace Server.Items
{ {
m_SkillMod?.Remove(); m_SkillMod?.Remove();
m_SkillMod = new DefaultSkillMod(SkillName.Mining, true, m_Bonus); m_SkillMod = new DefaultSkillMod(SkillName.Mining, "MiningGloves", true, m_Bonus);
mobile.AddSkillMod(m_SkillMod); mobile.AddSkillMod(m_SkillMod);
} }
} }

View file

@ -36,7 +36,7 @@ namespace Server.Items
EndDefense(info); EndDefense(info);
} }
var mod = new ResistanceMod(ResistanceType.Physical, 50 + modifier); var mod = new ResistanceMod(ResistanceType.Physical, "PhysicalResistDefenseMastery", 50 + modifier);
attacker.AddResistanceMod(mod); attacker.AddResistanceMod(mod);
info = new DefenseMasteryInfo(attacker, 80 - modifier, mod); info = new DefenseMasteryInfo(attacker, 80 - modifier, mod);

View file

@ -439,7 +439,7 @@ namespace Server.Items
} }
else if (m_SkillMod == null && Parent is Mobile mobile) else if (m_SkillMod == null && Parent is Mobile mobile)
{ {
m_SkillMod = new DefaultSkillMod(AccuracySkill, true, (int)m_AccuracyLevel * 5); m_SkillMod = new DefaultSkillMod(AccuracySkill, "WeaponAccuracy", true, (int)m_AccuracyLevel * 5);
mobile.AddSkillMod(m_SkillMod); mobile.AddSkillMod(m_SkillMod);
} }
else if (m_SkillMod != null) else if (m_SkillMod != null)
@ -966,7 +966,7 @@ namespace Server.Items
{ {
m_SkillMod?.Remove(); m_SkillMod?.Remove();
m_SkillMod = new DefaultSkillMod(AccuracySkill, true, (int)m_AccuracyLevel * 5); m_SkillMod = new DefaultSkillMod(AccuracySkill, "WeaponAccuracy", true, (int)m_AccuracyLevel * 5);
from.AddSkillMod(m_SkillMod); from.AddSkillMod(m_SkillMod);
} }
@ -974,7 +974,7 @@ namespace Server.Items
{ {
m_MageMod?.Remove(); m_MageMod?.Remove();
m_MageMod = new DefaultSkillMod(SkillName.Magery, true, -30 + WeaponAttributes.MageWeapon); m_MageMod = new DefaultSkillMod(SkillName.Magery, "MageWeapon", true, -30 + WeaponAttributes.MageWeapon);
from.AddSkillMod(m_MageMod); from.AddSkillMod(m_MageMod);
} }
@ -3944,7 +3944,7 @@ namespace Server.Items
if (UseSkillMod && m_AccuracyLevel != WeaponAccuracyLevel.Regular && parentMobile != null) if (UseSkillMod && m_AccuracyLevel != WeaponAccuracyLevel.Regular && parentMobile != null)
{ {
m_SkillMod = new DefaultSkillMod(AccuracySkill, true, (int)m_AccuracyLevel * 5); m_SkillMod = new DefaultSkillMod(AccuracySkill, "WeaponAccuracy", true, (int)m_AccuracyLevel * 5);
parentMobile.AddSkillMod(m_SkillMod); parentMobile.AddSkillMod(m_SkillMod);
} }
@ -3956,7 +3956,7 @@ namespace Server.Items
if (Core.AOS && WeaponAttributes.MageWeapon != 0 && WeaponAttributes.MageWeapon != 30 && if (Core.AOS && WeaponAttributes.MageWeapon != 0 && WeaponAttributes.MageWeapon != 30 &&
parentMobile != null) parentMobile != null)
{ {
m_MageMod = new DefaultSkillMod(SkillName.Magery, true, -30 + WeaponAttributes.MageWeapon); m_MageMod = new DefaultSkillMod(SkillName.Magery, "MageWeapon", true, -30 + WeaponAttributes.MageWeapon);
parentMobile.AddSkillMod(m_MageMod); parentMobile.AddSkillMod(m_MageMod);
} }
@ -4111,7 +4111,7 @@ namespace Server.Items
if (UseSkillMod && m_AccuracyLevel != WeaponAccuracyLevel.Regular && parentMobile != null) if (UseSkillMod && m_AccuracyLevel != WeaponAccuracyLevel.Regular && parentMobile != null)
{ {
m_SkillMod = new DefaultSkillMod(AccuracySkill, true, (int)m_AccuracyLevel * 5); m_SkillMod = new DefaultSkillMod(AccuracySkill, "WeaponAccuracy", true, (int)m_AccuracyLevel * 5);
parentMobile.AddSkillMod(m_SkillMod); parentMobile.AddSkillMod(m_SkillMod);
} }

View file

@ -590,21 +590,20 @@ namespace Server
if (strBonus != 0 || dexBonus != 0 || intBonus != 0) if (strBonus != 0 || dexBonus != 0 || intBonus != 0)
{ {
var serial = Owner.Serial; var hashCode = GetHashCode();
if (strBonus != 0) if (strBonus != 0)
{ {
to.AddStatMod(new StatMod(StatType.Str, $"{serial}Str", strBonus, TimeSpan.Zero)); to.AddStatMod(new StatMod(StatType.Str, $"{hashCode}Str", strBonus, TimeSpan.Zero));
} }
if (dexBonus != 0) if (dexBonus != 0)
{ {
to.AddStatMod(new StatMod(StatType.Dex, $"{serial}Dex", dexBonus, TimeSpan.Zero)); to.AddStatMod(new StatMod(StatType.Dex, $"{hashCode}Dex", dexBonus, TimeSpan.Zero));
} }
if (intBonus != 0) if (intBonus != 0)
{ {
to.AddStatMod(new StatMod(StatType.Int, $"{serial}Int", intBonus, TimeSpan.Zero)); to.AddStatMod(new StatMod(StatType.Int, $"{hashCode}Int", intBonus, TimeSpan.Zero));
} }
} }
@ -1094,7 +1093,7 @@ namespace Server
m_Mods ??= new HashSet<SkillMod>(); m_Mods ??= new HashSet<SkillMod>();
SkillMod sk = new DefaultSkillMod(skill, true, bonus); SkillMod sk = new DefaultSkillMod(skill, $"{GetHashCode()}{skill}", true, bonus);
sk.ObeyCap = true; sk.ObeyCap = true;
m.AddSkillMod(sk); m.AddSkillMod(sk);
m_Mods.Add(sk); m_Mods.Add(sk);
@ -1346,10 +1345,10 @@ namespace Server
public bool IsEmpty => _names == 0; public bool IsEmpty => _names == 0;
private Item _owner; private IEntity _owner;
[DirtyTrackingEntity] [DirtyTrackingEntity]
public Item Owner => _owner; public IEntity Owner => _owner;
public int GetValue(int bitmask) public int GetValue(int bitmask)
{ {
@ -1483,23 +1482,30 @@ namespace Server
} }
} }
if (Owner?.Parent is Mobile m) if (Owner is Item item)
{ {
m.CheckStatTimers(); if (item.Parent is Mobile m)
m.UpdateResistances();
m.Delta(
MobileDelta.Stat | MobileDelta.WeaponDamage | MobileDelta.Hits | MobileDelta.Stam |
MobileDelta.Mana
);
if (this is AosSkillBonuses)
{ {
((AosSkillBonuses)this).Remove(); m.CheckStatTimers();
((AosSkillBonuses)this).AddTo(m); m.UpdateResistances();
} m.Delta(
} MobileDelta.Stat | MobileDelta.WeaponDamage | MobileDelta.Hits | MobileDelta.Stam |
MobileDelta.Mana
);
Owner?.InvalidateProperties(); if (this is AosSkillBonuses skillBonuses)
{
skillBonuses.Remove();
skillBonuses.AddTo(m);
}
}
item.InvalidateProperties();
}
else if (Owner is Mobile mob)
{
mob.InvalidateProperties();
}
} }
private int GetIndex(uint mask) private int GetIndex(uint mask)

View file

@ -44,7 +44,7 @@ public class GraspingClaw : MonsterAbility
*/ */
var effect = -(target.PhysicalResistance * 15 / 100); var effect = -(target.PhysicalResistance * 15 / 100);
var mod = new ResistanceMod(ResistanceType.Physical, effect); var mod = new ResistanceMod(ResistanceType.Physical, "GraspingClaw", effect);
target.FixedEffect(0x37B9, 10, 5); target.FixedEffect(0x37B9, 10, 5);
target.AddResistanceMod(mod); target.AddResistanceMod(mod);

View file

@ -78,18 +78,17 @@ namespace Server.Mobiles
return; return;
} }
if (m_Table.TryGetValue(defender, out var timer)) if (m_Table.Remove(defender, out var timer))
{ {
timer.DoExpire(); timer.DoExpire();
} }
defender.FixedParticles(0x3709, 10, 30, 5052, EffectLayer.LeftFoot); defender.FixedParticles(0x3709, 10, 30, 5052, EffectLayer.LeftFoot);
defender.PlaySound(0x208); defender.PlaySound(0x208);
defender.SendLocalizedMessage( // The creature fans you with fire, reducing your resistance to fire attacks.
1070833 defender.SendLocalizedMessage(1070833);
); // The creature fans you with fire, reducing your resistance to fire attacks.
var mod = new ResistanceMod(ResistanceType.Fire, -10); var mod = new ResistanceMod(ResistanceType.Fire, "FireResistFanningFire", -10);
defender.AddResistanceMod(mod); defender.AddResistanceMod(mod);
m_Table[defender] = timer = new ExpireTimer(defender, mod); m_Table[defender] = timer = new ExpireTimer(defender, mod);
@ -127,13 +126,13 @@ namespace Server.Mobiles
m_Mobile.RemoveResistanceMod(m_Mod); m_Mobile.RemoveResistanceMod(m_Mod);
Stop(); Stop();
m_Table.Remove(m_Mobile);
} }
protected override void OnTick() protected override void OnTick()
{ {
m_Mobile.SendLocalizedMessage(1070834); // Your resistance to fire attacks has returned. m_Mobile.SendLocalizedMessage(1070834); // Your resistance to fire attacks has returned.
DoExpire(); DoExpire();
m_Table.Remove(m_Mobile);
} }
} }
} }

View file

@ -126,7 +126,7 @@ namespace Server.Mobiles
{ {
var s = target.Skills[i]; var s = target.Skills[i];
target.AddSkillMod(new TimedSkillMod(s.SkillName, true, s.Base * -0.28, delay)); target.AddSkillMod(new TimedSkillMod(s.SkillName, $"{s.Name}Satyr", true, s.Base * -0.28, delay));
} }
var count = (int)Math.Round(delay.TotalSeconds / 1.25); var count = (int)Math.Round(delay.TotalSeconds / 1.25);

View file

@ -105,21 +105,20 @@ namespace Server.Mobiles
return; return;
} }
if (m_Table.TryGetValue(defender, out var timer)) if (m_Table.Remove(defender, out var timer))
{ {
timer.DoExpire(); timer.DoExpire();
defender.SendLocalizedMessage(1070837); // The creature lands another blow in your weakened state. defender.SendLocalizedMessage(1070837); // The creature lands another blow in your weakened state.
} }
else else
{ {
defender.SendLocalizedMessage( // The blow from the creature's claws has made you more susceptible to physical attacks.
1070836 defender.SendLocalizedMessage(1070836);
); // The blow from the creature's claws has made you more susceptible to physical attacks.
} }
var effect = -(defender.PhysicalResistance * 15 / 100); var effect = -(defender.PhysicalResistance * 15 / 100);
var mod = new ResistanceMod(ResistanceType.Physical, effect); var mod = new ResistanceMod(ResistanceType.Physical, "PhysicalResistGraspingClaw", effect);
defender.FixedEffect(0x37B9, 10, 5); defender.FixedEffect(0x37B9, 10, 5);
defender.AddResistanceMod(mod); defender.AddResistanceMod(mod);
@ -159,13 +158,13 @@ namespace Server.Mobiles
{ {
m_Mobile.RemoveResistanceMod(m_Mod); m_Mobile.RemoveResistanceMod(m_Mod);
Stop(); Stop();
m_Table.Remove(m_Mobile);
} }
protected override void OnTick() protected override void OnTick()
{ {
m_Mobile.SendLocalizedMessage(1070838); // Your resistance to physical attacks has returned. m_Mobile.SendLocalizedMessage(1070838); // Your resistance to physical attacks has returned.
DoExpire(); DoExpire();
m_Table.Remove(m_Mobile);
} }
} }
} }

View file

@ -114,7 +114,7 @@ namespace Server.Mobiles
{ {
base.OnGaveMeleeAttack(defender, damage); base.OnGaveMeleeAttack(defender, damage);
if (!IsFanned(defender) && Utility.RandomDouble() < 0.05) if (m_Table.Add(defender) && Utility.RandomDouble() < 0.05)
{ {
/* Fanning Fire /* Fanning Fire
* Graphic: Type: "3" From: "0x57D4F5B" To: "0x0" ItemId: "0x3709" ItemIdName: "fire column" FromLocation: "(994 325, 16)" ToLocation: "(994 325, 16)" Speed: "10" Duration: "30" FixedDirection: "True" Explode: "False" Hue: "0x0" RenderMode: "0x0" Effect: "0x34" ExplodeEffect: "0x1" ExplodeSound: "0x0" Serial: "0x57D4F5B" Layer: "5" Unknown: "0x0" * Graphic: Type: "3" From: "0x57D4F5B" To: "0x0" ItemId: "0x3709" ItemIdName: "fire column" FromLocation: "(994 325, 16)" ToLocation: "(994 325, 16)" Speed: "10" Duration: "30" FixedDirection: "True" Explode: "False" Hue: "0x0" RenderMode: "0x0" Effect: "0x34" ExplodeEffect: "0x1" ExplodeSound: "0x0" Serial: "0x57D4F5B" Layer: "5" Unknown: "0x0"
@ -131,7 +131,7 @@ namespace Server.Mobiles
var effect = -(defender.FireResistance / 10); var effect = -(defender.FireResistance / 10);
var mod = new ResistanceMod(ResistanceType.Fire, effect); var mod = new ResistanceMod(ResistanceType.Fire, "FireResistFanningFire", effect);
defender.FixedParticles(0x37B9, 10, 30, 0x34, EffectLayer.RightFoot); defender.FixedParticles(0x37B9, 10, 30, 0x34, EffectLayer.RightFoot);
defender.PlaySound(0x208); defender.PlaySound(0x208);
@ -143,11 +143,10 @@ namespace Server.Mobiles
var timer = new ExpireTimer(defender, mod, TimeSpan.FromSeconds(10.0)); var timer = new ExpireTimer(defender, mod, TimeSpan.FromSeconds(10.0));
timer.Start(); timer.Start();
m_Table.Add(defender);
} }
} }
public bool IsFanned(Mobile m) => m_Table.Contains(m); public static bool IsFanned(Mobile m) => m_Table.Contains(m);
public override void Serialize(IGenericWriter writer) public override void Serialize(IGenericWriter writer)
{ {

View file

@ -72,21 +72,20 @@ namespace Server.Mobiles
* Effect: Type: "3" From: "0x57D4F5B" To: "0x0" ItemId: "0x37B9" ItemIdName: "glow" FromLocation: "(1048 779, 6)" ToLocation: "(1048 779, 6)" Speed: "10" Duration: "5" FixedDirection: "True" Explode: "False" * Effect: Type: "3" From: "0x57D4F5B" To: "0x0" ItemId: "0x37B9" ItemIdName: "glow" FromLocation: "(1048 779, 6)" ToLocation: "(1048 779, 6)" Speed: "10" Duration: "5" FixedDirection: "True" Explode: "False"
*/ */
if (m_FlurryOfTwigsTable.TryGetValue(defender, out var timer)) if (m_FlurryOfTwigsTable.Remove(defender, out var timer))
{ {
timer.DoExpire(); timer.DoExpire();
defender.SendLocalizedMessage(1070851); // The creature lands another blow in your weakened state. defender.SendLocalizedMessage(1070851); // The creature lands another blow in your weakened state.
} }
else else
{ {
defender.SendLocalizedMessage( // The creature's flurry of twigs has made you more susceptible to physical attacks!
1070850 defender.SendLocalizedMessage(1070850);
); // The creature's flurry of twigs has made you more susceptible to physical attacks!
} }
var effect = -(defender.PhysicalResistance * 15 / 100); var effect = -(defender.PhysicalResistance * 15 / 100);
var mod = new ResistanceMod(ResistanceType.Physical, effect); var mod = new ResistanceMod(ResistanceType.Physical, "PhysicalResistFlurryOfTwigs", effect);
defender.FixedEffect(0x37B9, 10, 5); defender.FixedEffect(0x37B9, 10, 5);
defender.AddResistanceMod(mod); defender.AddResistanceMod(mod);
@ -99,7 +98,7 @@ namespace Server.Mobiles
if (Utility.RandomDouble() < 0.05) if (Utility.RandomDouble() < 0.05)
{ {
/* Chlorophyl Blast /* Chlorophyll Blast
* Start cliloc: 1070827 * Start cliloc: 1070827
* Effect: Energy resistance -50% for 10 seconds * Effect: Energy resistance -50% for 10 seconds
* End cliloc: 1070829 * End cliloc: 1070829
@ -113,14 +112,13 @@ namespace Server.Mobiles
} }
else else
{ {
defender.SendLocalizedMessage( // The creature's attack has made you more susceptible to energy attacks!
1070827 defender.SendLocalizedMessage(1070827);
); // The creature's attack has made you more susceptible to energy attacks!
} }
var effect = -(defender.EnergyResistance / 2); var effect = -(defender.EnergyResistance / 2);
var mod = new ResistanceMod(ResistanceType.Energy, effect); var mod = new ResistanceMod(ResistanceType.Energy, "EnergyResistChlorophyllBlast", effect);
defender.FixedEffect(0x37B9, 10, 5); defender.FixedEffect(0x37B9, 10, 5);
defender.AddResistanceMod(mod); defender.AddResistanceMod(mod);
@ -161,7 +159,6 @@ namespace Server.Mobiles
{ {
m_Mobile.RemoveResistanceMod(m_Mod); m_Mobile.RemoveResistanceMod(m_Mod);
Stop(); Stop();
m_Table.Remove(m_Mobile);
} }
protected override void OnTick() protected override void OnTick()
@ -176,6 +173,7 @@ namespace Server.Mobiles
} }
DoExpire(); DoExpire();
m_Table.Remove(m_Mobile);
} }
} }
} }

View file

@ -110,7 +110,7 @@ namespace Server.Mobiles
* End ASCII: "The corruption of your armor has worn off" * End ASCII: "The corruption of your armor has worn off"
*/ */
if (m_Table.TryGetValue(defender, out var timer)) if (m_Table.Remove(defender, out var timer))
{ {
timer.DoExpire(); timer.DoExpire();
defender.SendLocalizedMessage(1070845); // The creature continues to corrupt your armor! defender.SendLocalizedMessage(1070845); // The creature continues to corrupt your armor!
@ -120,42 +120,59 @@ namespace Server.Mobiles
defender.SendLocalizedMessage(1070846); // The creature magically corrupts your armor! defender.SendLocalizedMessage(1070846); // The creature magically corrupts your armor!
} }
var mods = new List<ResistanceMod>();
if (Core.ML) if (Core.ML)
{ {
if (defender.PhysicalResistance > 0) if (defender.PhysicalResistance > 0)
{ {
mods.Add(new ResistanceMod(ResistanceType.Physical, -(defender.PhysicalResistance / 2))); defender.AddResistanceMod(
new ResistanceMod(
ResistanceType.Physical,
"RuneCorruption",
-(defender.PhysicalResistance / 2)
)
);
} }
if (defender.FireResistance > 0) if (defender.FireResistance > 0)
{ {
mods.Add(new ResistanceMod(ResistanceType.Fire, -(defender.FireResistance / 2))); defender.AddResistanceMod(new ResistanceMod(ResistanceType.Fire, "RuneCorruption", -(defender.FireResistance / 2)));
} }
if (defender.ColdResistance > 0) if (defender.ColdResistance > 0)
{ {
mods.Add(new ResistanceMod(ResistanceType.Cold, -(defender.ColdResistance / 2))); defender.AddResistanceMod(new ResistanceMod(ResistanceType.Cold, "RuneCorruption", -(defender.ColdResistance / 2)));
} }
if (defender.PoisonResistance > 0) if (defender.PoisonResistance > 0)
{ {
mods.Add(new ResistanceMod(ResistanceType.Poison, -(defender.PoisonResistance / 2))); defender.AddResistanceMod(
new ResistanceMod(
ResistanceType.Poison,
"RuneCorruption",
-(defender.PoisonResistance / 2)
)
);
} }
if (defender.EnergyResistance > 0) if (defender.EnergyResistance > 0)
{ {
mods.Add(new ResistanceMod(ResistanceType.Energy, -(defender.EnergyResistance / 2))); defender.AddResistanceMod(
new ResistanceMod(
ResistanceType.Energy,
"RuneCorruption",
-(defender.EnergyResistance / 2)
)
);
} }
} }
else else
{ {
if (defender.PhysicalResistance > 0) if (defender.PhysicalResistance > 0)
{ {
mods.Add( defender.AddResistanceMod(
new ResistanceMod( new ResistanceMod(
ResistanceType.Physical, ResistanceType.Physical,
"RuneCorruption",
defender.PhysicalResistance > 70 ? -70 : -defender.PhysicalResistance defender.PhysicalResistance > 70 ? -70 : -defender.PhysicalResistance
) )
); );
@ -163,9 +180,10 @@ namespace Server.Mobiles
if (defender.FireResistance > 0) if (defender.FireResistance > 0)
{ {
mods.Add( defender.AddResistanceMod(
new ResistanceMod( new ResistanceMod(
ResistanceType.Fire, ResistanceType.Fire,
"RuneCorruption",
defender.FireResistance > 70 ? -70 : -defender.FireResistance defender.FireResistance > 70 ? -70 : -defender.FireResistance
) )
); );
@ -173,9 +191,10 @@ namespace Server.Mobiles
if (defender.ColdResistance > 0) if (defender.ColdResistance > 0)
{ {
mods.Add( defender.AddResistanceMod(
new ResistanceMod( new ResistanceMod(
ResistanceType.Cold, ResistanceType.Cold,
"RuneCorruption",
defender.ColdResistance > 70 ? -70 : -defender.ColdResistance defender.ColdResistance > 70 ? -70 : -defender.ColdResistance
) )
); );
@ -183,9 +202,10 @@ namespace Server.Mobiles
if (defender.PoisonResistance > 0) if (defender.PoisonResistance > 0)
{ {
mods.Add( defender.AddResistanceMod(
new ResistanceMod( new ResistanceMod(
ResistanceType.Poison, ResistanceType.Poison,
"RuneCorruption",
defender.PoisonResistance > 70 ? -70 : -defender.PoisonResistance defender.PoisonResistance > 70 ? -70 : -defender.PoisonResistance
) )
); );
@ -193,23 +213,19 @@ namespace Server.Mobiles
if (defender.EnergyResistance > 0) if (defender.EnergyResistance > 0)
{ {
mods.Add( defender.AddResistanceMod(
new ResistanceMod( new ResistanceMod(
ResistanceType.Energy, ResistanceType.Energy,
"RuneCorruption",
defender.EnergyResistance > 70 ? -70 : -defender.EnergyResistance defender.EnergyResistance > 70 ? -70 : -defender.EnergyResistance
) )
); );
} }
} }
for (var i = 0; i < mods.Count; ++i)
{
defender.AddResistanceMod(mods[i]);
}
defender.FixedEffect(0x37B9, 10, 5); defender.FixedEffect(0x37B9, 10, 5);
timer = new ExpireTimer(defender, mods, TimeSpan.FromSeconds(5.0)); timer = new ExpireTimer(defender, TimeSpan.FromSeconds(5.0));
timer.Start(); timer.Start();
m_Table[defender] = timer; m_Table[defender] = timer;
} }
@ -229,11 +245,12 @@ namespace Server.Mobiles
{ {
for (var i = 0; i < Skills.Length; ++i) for (var i = 0; i < Skills.Length; ++i)
{ {
Skills[i].Cap = Math.Max(100.0, Skills[i].Cap * 0.9); var skill = Skills[i];
skill.Cap = Math.Max(100.0, skill.Cap * 0.9);
if (Skills[i].Base > Skills[i].Cap) if (skill.Base > skill.Cap)
{ {
Skills[i].Base = Skills[i].Cap; skill.Base = skill.Cap;
} }
} }
} }
@ -242,29 +259,20 @@ namespace Server.Mobiles
private class ExpireTimer : Timer private class ExpireTimer : Timer
{ {
private readonly Mobile m_Mobile; private readonly Mobile m_Mobile;
private readonly List<ResistanceMod> m_Mods;
public ExpireTimer(Mobile m, List<ResistanceMod> mods, TimeSpan delay) : base(delay) public ExpireTimer(Mobile m, TimeSpan delay) : base(delay) => m_Mobile = m;
{
m_Mobile = m;
m_Mods = mods;
}
public void DoExpire() public void DoExpire()
{ {
for (var i = 0; i < m_Mods.Count; ++i) m_Mobile.RemoveResistanceMod("RuneCorruption");
{
m_Mobile.RemoveResistanceMod(m_Mods[i]);
}
Stop(); Stop();
m_Table.Remove(m_Mobile);
} }
protected override void OnTick() protected override void OnTick()
{ {
m_Mobile.SendMessage("The corruption of your armor has worn off"); m_Mobile.SendMessage("The corruption of your armor has worn off");
DoExpire(); DoExpire();
m_Table.Remove(m_Mobile);
} }
} }
} }

View file

@ -95,63 +95,24 @@ namespace Server.SkillHandlers
public readonly Mobile m_Creature; public readonly Mobile m_Creature;
public readonly int m_Effect; public readonly int m_Effect;
public readonly Mobile m_From; public readonly Mobile m_From;
public readonly List<object> m_Mods;
public bool m_Ending; public bool m_Ending;
public DateTime m_EndTime; public DateTime m_EndTime;
public TimerExecutionToken _timerToken; public TimerExecutionToken _timerToken;
public DiscordanceInfo(Mobile from, Mobile creature, int effect, List<object> mods) public DiscordanceInfo(Mobile from, Mobile creature, int effect)
{ {
m_From = from; m_From = from;
m_Creature = creature; m_Creature = creature;
m_EndTime = Core.Now; m_EndTime = Core.Now;
m_Ending = false; m_Ending = false;
m_Effect = effect; m_Effect = effect;
m_Mods = mods;
Apply();
}
public void Apply()
{
for (var i = 0; i < m_Mods.Count; ++i)
{
var mod = m_Mods[i];
if (mod is ResistanceMod resistanceMod)
{
m_Creature.AddResistanceMod(resistanceMod);
}
else if (mod is StatMod statMod)
{
m_Creature.AddStatMod(statMod);
}
else if (mod is SkillMod skillMod)
{
m_Creature.AddSkillMod(skillMod);
}
}
} }
public void Clear() public void Clear()
{ {
for (var i = 0; i < m_Mods.Count; ++i) m_Creature.RemoveResistanceMod("Discordance");
{ m_Creature.RemoveStatMod("Discordance");
var mod = m_Mods[i]; m_Creature.RemoveSkillMod("Discordance");
if (mod is ResistanceMod resistanceMod)
{
m_Creature.RemoveResistanceMod(resistanceMod);
}
else if (mod is StatMod statMod)
{
m_Creature.RemoveStatMod(statMod.Name);
}
else if (mod is SkillMod skillMod)
{
m_Creature.RemoveSkillMod(skillMod);
}
}
} }
} }
@ -163,8 +124,7 @@ namespace Server.SkillHandlers
BaseInstrument.GetBardRange(from, SkillName.Discordance), BaseInstrument.GetBardRange(from, SkillName.Discordance),
false, false,
TargetFlags.None TargetFlags.None
) => ) => m_Instrument = inst;
m_Instrument = inst;
protected override void OnTarget(Mobile from, object target) protected override void OnTarget(Mobile from, object target)
{ {
@ -211,7 +171,6 @@ namespace Server.SkillHandlers
m_Instrument.PlayInstrumentWell(from); m_Instrument.PlayInstrumentWell(from);
m_Instrument.ConsumeUse(from); m_Instrument.ConsumeUse(from);
var mods = new List<object>();
int effect; int effect;
double scalar; double scalar;
@ -235,60 +194,53 @@ namespace Server.SkillHandlers
scalar = effect * 0.01; scalar = effect * 0.01;
mods.Add(new ResistanceMod(ResistanceType.Physical, effect)); targ.AddResistanceMod(new ResistanceMod(ResistanceType.Physical, "Discordance", effect));
mods.Add(new ResistanceMod(ResistanceType.Fire, effect)); targ.AddResistanceMod(new ResistanceMod(ResistanceType.Fire, "Discordance", effect));
mods.Add(new ResistanceMod(ResistanceType.Cold, effect)); targ.AddResistanceMod(new ResistanceMod(ResistanceType.Cold, "Discordance", effect));
mods.Add(new ResistanceMod(ResistanceType.Poison, effect)); targ.AddResistanceMod(new ResistanceMod(ResistanceType.Poison, "Discordance", effect));
mods.Add(new ResistanceMod(ResistanceType.Energy, effect)); targ.AddResistanceMod(new ResistanceMod(ResistanceType.Energy, "Discordance", effect));
for (var i = 0; i < targ.Skills.Length; ++i)
{
if (targ.Skills[i].Value > 0)
{
mods.Add(new DefaultSkillMod((SkillName)i, true, targ.Skills[i].Value * scalar));
}
}
} }
else else
{ {
effect = (int)(from.Skills.Discordance.Value / -5.0); effect = (int)(from.Skills.Discordance.Value / -5.0);
scalar = effect * 0.01; scalar = effect * 0.01;
mods.Add( targ.AddStatMod(
new StatMod( new StatMod(
StatType.Str, StatType.Str,
"DiscordanceStr", "Discordance",
(int)(targ.RawStr * scalar), (int)(targ.RawStr * scalar),
TimeSpan.Zero TimeSpan.Zero
) )
); );
mods.Add( targ.AddStatMod(
new StatMod( new StatMod(
StatType.Int, StatType.Int,
"DiscordanceInt", "Discordance",
(int)(targ.RawInt * scalar), (int)(targ.RawInt * scalar),
TimeSpan.Zero TimeSpan.Zero
) )
); );
mods.Add( targ.AddStatMod(
new StatMod( new StatMod(
StatType.Dex, StatType.Dex,
"DiscordanceDex", "Discordance",
(int)(targ.RawDex * scalar), (int)(targ.RawDex * scalar),
TimeSpan.Zero TimeSpan.Zero
) )
); );
}
for (var i = 0; i < targ.Skills.Length; ++i) for (var i = 0; i < targ.Skills.Length; ++i)
{
var skill = targ.Skills[i];
if (skill.Value > 0)
{ {
if (targ.Skills[i].Value > 0) targ.AddSkillMod(new DefaultSkillMod(skill.SkillName, "Discordance", true, skill.Value * scalar));
{
mods.Add(new DefaultSkillMod((SkillName)i, true, targ.Skills[i].Value * scalar));
}
} }
} }
var info = new DiscordanceInfo(from, targ, effect.Abs(), mods); var info = new DiscordanceInfo(from, targ, effect.Abs());
Timer.StartTimer( Timer.StartTimer(
TimeSpan.Zero, TimeSpan.Zero,
TimeSpan.FromSeconds(1.25), TimeSpan.FromSeconds(1.25),

View file

@ -1242,31 +1242,29 @@ namespace Server.Spells
if (!ourTransform) if (!ourTransform)
{ {
var mods = new List<ResistanceMod>();
if (transformSpell.PhysResistOffset != 0) if (transformSpell.PhysResistOffset != 0)
{ {
mods.Add(new ResistanceMod(ResistanceType.Physical, transformSpell.PhysResistOffset)); caster.AddResistanceMod(new ResistanceMod(ResistanceType.Physical, "TransformSpell", transformSpell.PhysResistOffset));
} }
if (transformSpell.FireResistOffset != 0) if (transformSpell.FireResistOffset != 0)
{ {
mods.Add(new ResistanceMod(ResistanceType.Fire, transformSpell.FireResistOffset)); caster.AddResistanceMod(new ResistanceMod(ResistanceType.Fire, "TransformSpell", transformSpell.FireResistOffset));
} }
if (transformSpell.ColdResistOffset != 0) if (transformSpell.ColdResistOffset != 0)
{ {
mods.Add(new ResistanceMod(ResistanceType.Cold, transformSpell.ColdResistOffset)); caster.AddResistanceMod(new ResistanceMod(ResistanceType.Cold, "TransformSpell", transformSpell.ColdResistOffset));
} }
if (transformSpell.PoisResistOffset != 0) if (transformSpell.PoisResistOffset != 0)
{ {
mods.Add(new ResistanceMod(ResistanceType.Poison, transformSpell.PoisResistOffset)); caster.AddResistanceMod(new ResistanceMod(ResistanceType.Poison, "TransformSpell", transformSpell.PoisResistOffset));
} }
if (transformSpell.NrgyResistOffset != 0) if (transformSpell.NrgyResistOffset != 0)
{ {
mods.Add(new ResistanceMod(ResistanceType.Energy, transformSpell.NrgyResistOffset)); caster.AddResistanceMod(new ResistanceMod(ResistanceType.Energy, "TransformSpell", transformSpell.NrgyResistOffset));
} }
if (!((Body)transformSpell.Body).IsHuman) if (!((Body)transformSpell.Body).IsHuman)
@ -1282,17 +1280,12 @@ namespace Server.Spells
caster.BodyMod = transformSpell.Body; caster.BodyMod = transformSpell.Body;
caster.HueMod = transformSpell.Hue; caster.HueMod = transformSpell.Hue;
for (var i = 0; i < mods.Count; ++i)
{
caster.AddResistanceMod(mods[i]);
}
transformSpell.DoEffect(caster); transformSpell.DoEffect(caster);
Timer timer = new TransformTimer(caster, transformSpell); Timer timer = new TransformTimer(caster, transformSpell);
timer.Start(); timer.Start();
AddContext(caster, new TransformContext(timer, mods, ourType, transformSpell)); AddContext(caster, new TransformContext(timer, ourType, transformSpell));
return true; return true;
} }
} }
@ -1322,12 +1315,7 @@ namespace Server.Spells
return; return;
} }
var mods = context.Mods; m.RemoveResistanceMod("TransformSpell");
for (var i = 0; i < mods.Count; ++i)
{
m.RemoveResistanceMod(mods[i]);
}
if (resetGraphics) if (resetGraphics)
{ {
@ -1371,18 +1359,15 @@ namespace Server.Spells
public class TransformContext public class TransformContext
{ {
public TransformContext(Timer timer, List<ResistanceMod> mods, Type type, ITransformationSpell spell) public TransformContext(Timer timer, Type type, ITransformationSpell spell)
{ {
Timer = timer; Timer = timer;
Mods = mods;
Type = type; Type = type;
Spell = spell; Spell = spell;
} }
public Timer Timer { get; } public Timer Timer { get; }
public List<ResistanceMod> Mods { get; }
public Type Type { get; } public Type Type { get; }
public ITransformationSpell Spell { get; } public ITransformationSpell Spell { get; }

View file

@ -46,18 +46,18 @@ namespace Server.Spells.Bushido
{ {
var mods = new List<object> var mods = new List<object>
{ {
new ResistanceMod(ResistanceType.Physical, -40), new ResistanceMod(ResistanceType.Physical, "PhysicalResistHonorableExecution", -40),
new ResistanceMod(ResistanceType.Fire, -40), new ResistanceMod(ResistanceType.Fire, "FireResistHonorableExecution", -40),
new ResistanceMod(ResistanceType.Cold, -40), new ResistanceMod(ResistanceType.Cold, "ColdResistHonorableExecution", -40),
new ResistanceMod(ResistanceType.Poison, -40), new ResistanceMod(ResistanceType.Poison, "PoisonResistHonorableExecution", -40),
new ResistanceMod(ResistanceType.Energy, -40) new ResistanceMod(ResistanceType.Energy, "EnergyResistHonorableExecution", -40)
}; };
var resSpells = attacker.Skills.MagicResist.Value; var resSpells = attacker.Skills.MagicResist.Value;
if (resSpells > 0.0) if (resSpells > 0.0)
{ {
mods.Add(new DefaultSkillMod(SkillName.MagicResist, true, -resSpells)); mods.Add(new DefaultSkillMod(SkillName.MagicResist, "MagicResistHonorableExecution", true, -resSpells));
} }
timer = new HonorableExecutionTimer(attacker, mods); timer = new HonorableExecutionTimer(attacker, mods);

View file

@ -78,15 +78,15 @@ namespace Server.Spells.Fifth
targ.FixedParticles(0x375A, 10, 15, 5037, EffectLayer.Waist); targ.FixedParticles(0x375A, 10, 15, 5037, EffectLayer.Waist);
var physiMod = -25 + (int)(targ.Skills.Inscribe.Value / 20); var physiMod = -25 + (int)(targ.Skills.Inscribe.Value / 20);
var otherMod = 10; const int otherMod = 10;
mods = new[] mods = new[]
{ {
new ResistanceMod(ResistanceType.Physical, physiMod), new ResistanceMod(ResistanceType.Physical, "PhysicalResistMagicResist", physiMod),
new ResistanceMod(ResistanceType.Fire, otherMod), new ResistanceMod(ResistanceType.Fire, "FireResistMagicResist", otherMod),
new ResistanceMod(ResistanceType.Cold, otherMod), new ResistanceMod(ResistanceType.Cold, "ColdResistMagicResist", otherMod),
new ResistanceMod(ResistanceType.Poison, otherMod), new ResistanceMod(ResistanceType.Poison, "PoisonResistMagicResist", otherMod),
new ResistanceMod(ResistanceType.Energy, otherMod) new ResistanceMod(ResistanceType.Energy, "EnergyResistMagicResist", otherMod)
}; };
_table[targ] = mods; _table[targ] = mods;

View file

@ -83,12 +83,13 @@ namespace Server.Spells.First
{ {
new ResistanceMod( new ResistanceMod(
ResistanceType.Physical, ResistanceType.Physical,
"PhysicalResistReactiveArmorSpell",
15 + (int)(targ.Skills.Inscribe.Value / 20) 15 + (int)(targ.Skills.Inscribe.Value / 20)
), ),
new ResistanceMod(ResistanceType.Fire, -5), new ResistanceMod(ResistanceType.Fire, "FireResistReactiveArmorSpell", -5),
new ResistanceMod(ResistanceType.Cold, -5), new ResistanceMod(ResistanceType.Cold, "ColdResistReactiveArmorSpell", -5),
new ResistanceMod(ResistanceType.Poison, -5), new ResistanceMod(ResistanceType.Poison, "PoisonResistReactiveArmorSpell", -5),
new ResistanceMod(ResistanceType.Energy, -5) new ResistanceMod(ResistanceType.Energy, "EnergyResistReactiveArmorSpell", -5)
}; };
_table[targ] = mods; _table[targ] = mods;

View file

@ -101,11 +101,11 @@ namespace Server.Spells.Mysticism
ResistanceMod[] mods = ResistanceMod[] mods =
{ {
new(ResistanceType.Physical, offset), new(ResistanceType.Physical, "PhysicalResistStoneFormSpell", offset),
new(ResistanceType.Fire, offset), new(ResistanceType.Fire, "FireResistStoneFormSpell", offset),
new(ResistanceType.Cold, offset), new(ResistanceType.Cold, "ColdResistStoneFormSpell", offset),
new(ResistanceType.Poison, offset), new(ResistanceType.Poison, "PoisonResistStoneFormSpell", offset),
new(ResistanceType.Energy, offset) new(ResistanceType.Energy, "EnergyResistStoneFormSpell", offset)
}; };
for (var i = 0; i < mods.Length; ++i) for (var i = 0; i < mods.Length; ++i)

View file

@ -71,10 +71,10 @@ namespace Server.Spells.Necromancy
ResistanceMod[] mods = ResistanceMod[] mods =
{ {
new(ResistanceType.Fire, -15), new(ResistanceType.Fire, "FireResistCorpseSkinSpell", -15),
new(ResistanceType.Poison, -15), new(ResistanceType.Poison, "PoisonResistCorpseSkinSpell", -15),
new(ResistanceType.Cold, +10), new(ResistanceType.Cold, "ColdResistCorpseSkinSpell", +10),
new(ResistanceType.Physical, +10) new(ResistanceType.Physical, "PhysicalResistCorpseSkinSpell", +10)
}; };
timer = new ExpireTimer(m, mods, duration); timer = new ExpireTimer(m, mods, duration);

View file

@ -53,7 +53,7 @@ namespace Server.Spells.Necromancy
if (!_table.ContainsKey(m)) if (!_table.ContainsKey(m))
{ {
var mod = new DefaultSkillMod(SkillName.MagicResist, false, m.Skills.MagicResist.Value / 2); var mod = new DefaultSkillMod(SkillName.MagicResist, "EvilOmen", false, m.Skills.MagicResist.Value / 2);
m.AddSkillMod(mod); m.AddSkillMod(mod);
_table[m] = mod; _table[m] = mod;
} }

View file

@ -237,11 +237,12 @@ namespace Server.Spells.Ninjitsu
m.NetState.SendSpeedControl(SpeedControlSetting.Mount); m.NetState.SendSpeedControl(SpeedControlSetting.Mount);
} }
// TODO: Determine if transform spell skill mods to a generic location like stat mods
SkillMod mod = null; SkillMod mod = null;
if (entry.StealthBonus) if (entry.StealthBonus)
{ {
mod = new DefaultSkillMod(SkillName.Stealth, true, 20.0) { ObeyCap = true }; mod = new DefaultSkillMod(SkillName.Stealth, "StealthAnimalForm", true, 20.0) { ObeyCap = true };
m.AddSkillMod(mod); m.AddSkillMod(mod);
} }
@ -249,7 +250,7 @@ namespace Server.Spells.Ninjitsu
if (entry.StealingBonus) if (entry.StealingBonus)
{ {
stealingMod = new DefaultSkillMod(SkillName.Stealing, true, 10.0) { ObeyCap = true }; stealingMod = new DefaultSkillMod(SkillName.Stealing, "StealingAnimalForm", true, 10.0) { ObeyCap = true };
m.AddSkillMod(stealingMod); m.AddSkillMod(stealingMod);
} }

View file

@ -79,8 +79,8 @@ namespace Server.Spells.Second
var physLoss = -15 + (int)(caster.Skills.Inscribe.Value / 20); var physLoss = -15 + (int)(caster.Skills.Inscribe.Value / 20);
var resistLoss = -35 + (int)(caster.Skills.Inscribe.Value / 20); var resistLoss = -35 + (int)(caster.Skills.Inscribe.Value / 20);
var physMod = new ResistanceMod(ResistanceType.Physical, physLoss); var physMod = new ResistanceMod(ResistanceType.Physical, "PhysicalResistProtectionSpell", physLoss);
var resistMod = new DefaultSkillMod(SkillName.MagicResist, true, resistLoss); var resistMod = new DefaultSkillMod(SkillName.MagicResist, "MagicResistProtectionSpell", true, resistLoss);
_table[target] = Tuple.Create(physMod, resistMod); _table[target] = Tuple.Create(physMod, resistMod);
Registry[target] = 1000; // 100.0% protection from disruption Registry[target] = 1000; // 100.0% protection from disruption