fix: Fixes disarm, strangle, curse, summons, looting rights, creatures attacking, and items going to the floor (#1174)

* Fixes disarm
* Fixes strangle not refreshing
* Fixes curse not refreshing
* Fixes 125% bonus to looting rights
* Fixes mobs attacking each other, or not attacking each other
* Fixes items dropping to the floor
* Fixes protection spell
* Fixes cure sending wrong message
This commit is contained in:
mark1145 2022-09-28 15:19:15 +10:00 • committed by GitHub
parent 906ec095b9
commit 060edaa76a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 127 additions and 112 deletions

View file

@ -147,8 +147,6 @@ namespace Server.Spells
private static Mobile m_TravelCaster;
private static TravelCheckType m_TravelType;
public static bool DisableSkillCheck { get; set; }
public static TimeSpan GetDamageDelayForSpell(Spell sp) =>
!sp.DelayedDamage ? TimeSpan.Zero :
Core.AOS ? AosDamageDelay : OldDamageDelay;
@ -225,7 +223,7 @@ namespace Server.Spells
{
var info = m.Aggressors[i];
if (info.Attacker.Player && Core.Now - info.LastCombatTime < CombatHeatDelay)
if (info.Attacker.Player && info.Attacker == m && Core.Now - info.LastCombatTime < CombatHeatDelay)
{
return true;
}
@ -292,13 +290,14 @@ namespace Server.Spells
? AddStatBonus(m, m, type, offset, duration)
: offset >= 0 || AddStatCurse(m, m, type, -offset, duration);
public static bool AddStatBonus(Mobile caster, Mobile target, StatType type) => AddStatBonus(
caster,
target,
type,
GetOffset(caster, target, type, false),
GetDuration(caster, target)
);
public static bool AddStatBonus(Mobile caster, Mobile target, StatType type, TimeSpan duration, bool skillCheck = true) =>
AddStatBonus(
caster,
target,
type,
GetOffset(caster, target, type, false, skillCheck),
duration
);
public static bool AddStatBonus(Mobile caster, Mobile target, StatType type, int bonus, TimeSpan duration)
{
@ -322,13 +321,14 @@ namespace Server.Spells
return false;
}
public static bool AddStatCurse(Mobile caster, Mobile target, StatType type) => AddStatCurse(
caster,
target,
type,
GetOffset(caster, target, type, true),
GetDuration(caster, target)
);
public static bool AddStatCurse(Mobile caster, Mobile target, StatType type, TimeSpan duration, bool skillCheck = true) =>
AddStatCurse(
caster,
target,
type,
GetOffset(caster, target, type, true, skillCheck),
duration
);
public static bool AddStatCurse(Mobile caster, Mobile target, StatType type, int curse, TimeSpan duration)
{
@ -374,34 +374,32 @@ namespace Server.Spells
return Math.Max(percent, 0);
}
public static int GetOffset(Mobile caster, Mobile target, StatType type, bool curse)
public static int GetOffset(Mobile caster, Mobile target, StatType type, bool curse, bool skillCheck)
{
if (Core.AOS)
if (!Core.AOS)
{
if (!DisableSkillCheck)
return 1 + (int)(caster.Skills.Magery.Value * 0.1);
}
if (skillCheck)
{
caster.CheckSkill(SkillName.EvalInt, 0.0, 120.0);
if (curse)
{
caster.CheckSkill(SkillName.EvalInt, 0.0, 120.0);
if (curse)
{
target.CheckSkill(SkillName.MagicResist, 0.0, 120.0);
}
}
var percent = GetOffsetScalar(caster, target, curse);
switch (type)
{
case StatType.Str:
return (int)(target.RawStr * percent);
case StatType.Dex:
return (int)(target.RawDex * percent);
case StatType.Int:
return (int)(target.RawInt * percent);
target.CheckSkill(SkillName.MagicResist, 0.0, 120.0);
}
}
return 1 + (int)(caster.Skills.Magery.Value * 0.1);
var percent = GetOffsetScalar(caster, target, curse);
return type switch
{
StatType.Str => (int)(target.RawStr * percent),
StatType.Dex => (int)(target.RawDex * percent),
StatType.Int => (int)(target.RawInt * percent),
_ => 1 + (int)(caster.Skills.Magery.Value * 0.1)
};
}
public static Guild GetGuildFor(Mobile m)

View file

@ -65,7 +65,7 @@ namespace Server.Spells.Chivalry
}
else
{
m.SendLocalizedMessage(1010060); // You have failed to cure your target!
Caster.SendLocalizedMessage(1010060); // You have failed to cure your target!
}
}

View file

@ -46,7 +46,7 @@ namespace Server.Spells.Eighth
{
Expansion.None => TimeSpan.FromSeconds(Caster.Skills.Magery.Value),
// T2A -> Current
_ => TimeSpan.FromSeconds(4 * Math.Min(5, Caster.Skills.Magery.Value)),
_ => TimeSpan.FromSeconds(4 * Math.Max(5, Caster.Skills.Magery.Value)),
};
if (Core.AOS)

View file

@ -46,7 +46,7 @@ namespace Server.Spells.Eighth
{
Expansion.None => TimeSpan.FromSeconds(Caster.Skills.Magery.Value),
// T2A -> Current
_ => TimeSpan.FromSeconds(4 * Math.Min(5, Caster.Skills.Magery.Value)),
_ => TimeSpan.FromSeconds(4 * Math.Max(5, Caster.Skills.Magery.Value)),
};
if (Core.AOS)

View file

@ -47,7 +47,7 @@ namespace Server.Spells.Eighth
{
Expansion.None => TimeSpan.FromSeconds(Caster.Skills.Magery.Value),
// T2A -> Current
_ => TimeSpan.FromSeconds(4 * Math.Min(5, Caster.Skills.Magery.Value)),
_ => TimeSpan.FromSeconds(4 * Math.Max(5, Caster.Skills.Magery.Value)),
};
if (Core.AOS)

View file

@ -47,7 +47,7 @@ namespace Server.Spells.Eighth
{
Expansion.None => TimeSpan.FromSeconds(Caster.Skills.Magery.Value),
// T2A -> Current
_ => TimeSpan.FromSeconds(4 * Math.Min(5, Caster.Skills.Magery.Value)),
_ => TimeSpan.FromSeconds(4 * Math.Max(5, Caster.Skills.Magery.Value)),
};
if (Core.AOS) /* Why two diff daemons? TODO: solve this */

View file

@ -46,7 +46,7 @@ namespace Server.Spells.Eighth
{
Expansion.None => TimeSpan.FromSeconds(Caster.Skills.Magery.Value),
// T2A -> Current
_ => TimeSpan.FromSeconds(4 * Math.Min(5, Caster.Skills.Magery.Value)),
_ => TimeSpan.FromSeconds(4 * Math.Max(5, Caster.Skills.Magery.Value)),
};
if (Core.AOS)

View file

@ -27,7 +27,8 @@ namespace Server.Spells.First
SpellHelper.CheckReflect((int)Circle, Caster, ref m);
SpellHelper.AddStatCurse(Caster, m, StatType.Dex);
var length = SpellHelper.GetDuration(Caster, m);
SpellHelper.AddStatCurse(Caster, m, StatType.Dex, length, false);
m.Spell?.OnCasterHurt();
@ -37,7 +38,6 @@ namespace Server.Spells.First
m.PlaySound(0x1DF);
var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100);
var length = SpellHelper.GetDuration(Caster, m);
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Clumsy, 1075831, length, m, percentage.ToString()));

View file

@ -29,7 +29,8 @@ namespace Server.Spells.First
// TODO: StoneForm immunity
SpellHelper.AddStatCurse(Caster, m, StatType.Int);
var length = SpellHelper.GetDuration(Caster, m);
SpellHelper.AddStatCurse(Caster, m, StatType.Int, length, false);
m.Spell?.OnCasterHurt();
@ -39,7 +40,6 @@ namespace Server.Spells.First
m.PlaySound(0x1E4);
var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100);
var length = SpellHelper.GetDuration(Caster, m);
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.FeebleMind, 1075833, length, m, percentage.ToString()));

View file

@ -27,7 +27,8 @@ namespace Server.Spells.First
SpellHelper.CheckReflect((int)Circle, Caster, ref m);
SpellHelper.AddStatCurse(Caster, m, StatType.Str);
var length = SpellHelper.GetDuration(Caster, m);
SpellHelper.AddStatCurse(Caster, m, StatType.Str, length, false);
m.Spell?.OnCasterHurt();
@ -37,7 +38,6 @@ namespace Server.Spells.First
m.PlaySound(0x1E6);
var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100);
var length = SpellHelper.GetDuration(Caster, m);
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Weaken, 1075837, length, m, percentage.ToString()));

View file

@ -15,7 +15,7 @@ namespace Server.Spells.Fourth
Reagent.SulfurousAsh
);
private static readonly HashSet<Mobile> _underEffect = new();
private static readonly Dictionary<Mobile, Timer> _table = new();
public CurseSpell(Mobile caster, Item scroll = null) : base(caster, scroll, _info)
{
@ -30,20 +30,16 @@ namespace Server.Spells.Fourth
SpellHelper.Turn(Caster, m);
SpellHelper.CheckReflect((int)Circle, Caster, ref m);
var length = SpellHelper.GetDuration(Caster, m);
SpellHelper.AddStatCurse(Caster, m, StatType.Str);
SpellHelper.DisableSkillCheck = true;
SpellHelper.AddStatCurse(Caster, m, StatType.Dex);
SpellHelper.AddStatCurse(Caster, m, StatType.Int);
SpellHelper.DisableSkillCheck = false;
SpellHelper.AddStatCurse(Caster, m, StatType.Str, length, false);
SpellHelper.AddStatCurse(Caster, m, StatType.Dex, length);
SpellHelper.AddStatCurse(Caster, m, StatType.Int, length);
// On OSI you CAN curse yourself and get this effect.
if (Caster.Player && m.Player /*&& Caster != m */ && !UnderEffect(m))
if (Caster.Player && m.Player)
{
var duration = SpellHelper.GetDuration(Caster, m);
_underEffect.Add(m);
Timer.StartTimer(duration, () => RemoveEffect(m));
m.UpdateResistances();
RemoveEffect(m);
_table[m] = Timer.DelayCall(length, () => RemoveEffect(m));
}
m.Spell?.OnCasterHurt();
@ -54,8 +50,6 @@ namespace Server.Spells.Fourth
m.PlaySound(0x1E1);
var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100);
var length = SpellHelper.GetDuration(Caster, m);
var args = $"{percentage}\t{percentage}\t{percentage}\t{10}\t{10}\t{10}\t{10}";
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Curse, 1075835, 1075836, length, m, args));
@ -73,11 +67,16 @@ namespace Server.Spells.Fourth
public static bool RemoveEffect(Mobile m)
{
var effectRemoved = _underEffect.Remove(m);
m.UpdateResistances();
return effectRemoved;
if (_table.Remove(m, out var timer))
{
timer.Stop();
m.UpdateResistances();
return true;
}
return false;
}
public static bool UnderEffect(Mobile m) => _underEffect.Contains(m);
public static bool UnderEffect(Mobile m) => _table.ContainsKey(m);
}
}

View file

@ -38,9 +38,9 @@ namespace Server.Spells.Necromancy
SpellHelper.Turn(Caster, m);
// SpellHelper.CheckReflect( (int)this.Circle, Caster, ref m );
// Irrelevent after AoS
// Irrelevant after AoS
/* Temporarily chokes off the air suply of the target with poisonous fumes.
/* Temporarily chokes off the air supply of the target with poisonous fumes.
* The target is inflicted with poison damage over time.
* The amount of damage dealt each "hit" is based off of the caster's Spirit Speak skill and the Target's current Stamina.
* The less Stamina the target has, the more damage is done by Strangle.
@ -60,12 +60,16 @@ namespace Server.Spells.Necromancy
m.FixedParticles(0x36CB, 1, 9, 9911, 67, 5, EffectLayer.Head);
m.FixedParticles(0x374A, 1, 17, 9502, 1108, 4, (EffectLayer)255);
if (!_table.TryGetValue(m, out var timer))
// According to testing on OSI, it is refreshed.
if (_table.TryGetValue(m, out var timer))
{
_table[m] = timer = new InternalTimer(m, Caster);
timer.Start();
timer.Stop();
}
timer = new InternalTimer(m, Caster);
_table[m] = timer;
timer.Start();
HarmfulSpell(m);
}

View file

@ -26,13 +26,13 @@ namespace Server.Spells.Second
{
SpellHelper.Turn(Caster, m);
SpellHelper.AddStatBonus(Caster, m, StatType.Dex);
var length = SpellHelper.GetDuration(Caster, m);
SpellHelper.AddStatBonus(Caster, m, StatType.Dex, length, false);
m.FixedParticles(0x375A, 10, 15, 5010, EffectLayer.Waist);
m.PlaySound(0x1e7);
var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, false) * 100);
var length = SpellHelper.GetDuration(Caster, m);
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Agility, 1075841, length, m, percentage.ToString()));
}

View file

@ -26,13 +26,13 @@ namespace Server.Spells.Second
{
SpellHelper.Turn(Caster, m);
SpellHelper.AddStatBonus(Caster, m, StatType.Int);
var length = SpellHelper.GetDuration(Caster, m);
SpellHelper.AddStatBonus(Caster, m, StatType.Int, length, false);
m.FixedParticles(0x375A, 10, 15, 5011, EffectLayer.Head);
m.PlaySound(0x1EB);
var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, false) * 100);
var length = SpellHelper.GetDuration(Caster, m);
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Cunning, 1075843, length, m, percentage.ToString()));
}

View file

@ -48,7 +48,7 @@ namespace Server.Spells.Second
}
else
{
m.SendLocalizedMessage(1010060); // You have failed to cure your target!
Caster.SendLocalizedMessage(1010060); // You have failed to cure your target!
}
}

View file

@ -77,8 +77,8 @@ namespace Server.Spells.Second
target.PlaySound(0x1E9);
target.FixedParticles(0x375A, 9, 20, 5016, EffectLayer.Waist);
var physLoss = Math.Max(0, -15 + (int)(caster.Skills.Inscribe.Value / 20));
var resistLoss = Math.Max(0, -35 + (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 physMod = new ResistanceMod(ResistanceType.Physical, physLoss);
var resistMod = new DefaultSkillMod(SkillName.MagicResist, true, resistLoss);

View file

@ -26,13 +26,13 @@ namespace Server.Spells.Second
{
SpellHelper.Turn(Caster, m);
SpellHelper.AddStatBonus(Caster, m, StatType.Str);
var length = SpellHelper.GetDuration(Caster, m);
SpellHelper.AddStatBonus(Caster, m, StatType.Str, length, false);
m.FixedParticles(0x375A, 10, 15, 5017, EffectLayer.Waist);
m.PlaySound(0x1EE);
var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, false) * 100);
var length = SpellHelper.GetDuration(Caster, m);
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Strength, 1075845, length, m, percentage.ToString()));
}

View file

@ -44,11 +44,10 @@ namespace Server.Spells.Sixth
Caster.DoHarmful(m);
SpellHelper.AddStatCurse(Caster, m, StatType.Str);
SpellHelper.DisableSkillCheck = true;
SpellHelper.AddStatCurse(Caster, m, StatType.Dex);
SpellHelper.AddStatCurse(Caster, m, StatType.Int);
SpellHelper.DisableSkillCheck = false;
var length = SpellHelper.GetDuration(Caster, m);
SpellHelper.AddStatCurse(Caster, m, StatType.Str, length, false);
SpellHelper.AddStatCurse(Caster, m, StatType.Dex, length);
SpellHelper.AddStatCurse(Caster, m, StatType.Int, length);
m.FixedParticles(0x374A, 10, 15, 5028, EffectLayer.Waist);
m.PlaySound(0x1FB);

View file

@ -26,17 +26,15 @@ namespace Server.Spells.Third
{
SpellHelper.Turn(Caster, m);
SpellHelper.AddStatBonus(Caster, m, StatType.Str);
SpellHelper.DisableSkillCheck = true;
SpellHelper.AddStatBonus(Caster, m, StatType.Dex);
SpellHelper.AddStatBonus(Caster, m, StatType.Int);
SpellHelper.DisableSkillCheck = false;
var length = SpellHelper.GetDuration(Caster, m);
SpellHelper.AddStatBonus(Caster, m, StatType.Str, length, false);
SpellHelper.AddStatBonus(Caster, m, StatType.Dex, length);
SpellHelper.AddStatBonus(Caster, m, StatType.Int, length);
m.FixedParticles(0x373A, 10, 15, 5018, EffectLayer.Waist);
m.PlaySound(0x1EA);
var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, false) * 100);
var length = SpellHelper.GetDuration(Caster, m);
var args = $"{percentage}\t{percentage}\t{percentage}";