Some cleanup of contains keys and try get values (#246)

This commit is contained in:
Kamron Batman 2020-09-13 20:20:44 -07:00 • committed by GitHub
parent 9cbb0cfd23
commit a236617ad9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
69 changed files with 3508 additions and 350 deletions

View file

@ -82,7 +82,9 @@ namespace Server.Spells
var scalar = 1.0;
if (!MindRotSpell.GetMindRotScalar(m, ref scalar))
{
scalar = 1.0;
}
// Lower Mana Cost = 40%
var lmc = Math.Min(AosAttributes.GetValue(m, AosAttribute.LowerManaCost), 40);
@ -92,7 +94,9 @@ namespace Server.Spells
var total = (int)(mana * scalar);
if (m.Skills[MoveSkill].Value < 50.0 && GetContext(m) != null)
{
total *= 2;
}
return total;
}
@ -113,7 +117,9 @@ namespace Server.Spells
if (consume)
{
if (!DelayedContext)
{
SetContext(from);
}
from.Mana -= mana;
}
@ -124,6 +130,7 @@ namespace Server.Spells
public virtual void SetContext(Mobile from)
{
if (GetContext(from) == null)
{
if (DelayedContext || from.Skills[MoveSkill].Value < 50.0)
{
Timer timer = new SpecialMoveTimer(from);
@ -131,12 +138,15 @@ namespace Server.Spells
AddContext(from, new SpecialMoveContext(timer, GetType()));
}
}
}
public virtual bool Validate(Mobile from)
{
if (!from.Player)
{
return true;
}
if (HonorableExecution.IsUnderPenalty(from))
{
@ -153,24 +163,42 @@ namespace Server.Spells
string option = null;
if (this is Backstab)
{
option = "Backstab";
}
else if (this is DeathStrike)
{
option = "Death Strike";
}
else if (this is FocusAttack)
{
option = "Focus Attack";
}
else if (this is KiAttack)
{
option = "Ki Attack";
}
else if (this is SurpriseAttack)
{
option = "Surprise Attack";
}
else if (this is HonorableExecution)
{
option = "Honorable Execution";
}
else if (this is LightningStrike)
{
option = "Lightning Strike";
}
else if (this is MomentumStrike)
{
option = "Momentum Strike";
}
if (option != null && !DuelContext.AllowSpecialMove(from, option, this))
{
return false;
}
return CheckSkills(from) && CheckMana(from, false);
}
@ -187,14 +215,18 @@ namespace Server.Spells
var moveID = kvp.Key;
if (moveID != -1)
{
m.Send(new ToggleSpecialAbility(moveID + 1, false));
}
}
}
public static SpecialMove GetCurrentMove(Mobile m)
{
if (m == null)
{
return null;
}
if (!Core.SE)
{
@ -230,7 +262,9 @@ namespace Server.Spells
ClearCurrentMove(m);
if (sameMove)
{
return true;
}
if (move != null)
{
@ -243,7 +277,9 @@ namespace Server.Spells
var moveID = SpellRegistry.GetRegistryNumber(move);
if (moveID > 0)
{
m.Send(new ToggleSpecialAbility(moveID + 1, true));
}
TextDefinition.SendMessageTo(m, move.AbilityMessage);
}
@ -253,17 +289,17 @@ namespace Server.Spells
public static void ClearCurrentMove(Mobile m)
{
if (Table.TryGetValue(m, out var move))
if (Table.Remove(m, out var move))
{
move.OnClearMove(m);
var moveID = SpellRegistry.GetRegistryNumber(move);
if (moveID > 0)
{
m.Send(new ToggleSpecialAbility(moveID + 1, false));
}
}
Table.Remove(m);
}
private static void AddContext(Mobile m, SpecialMoveContext context)

View file

@ -86,7 +86,9 @@ namespace Server.Spells
// Confirm: Monsters and pets cannot be disturbed.
if (Caster.Player && IsCasting && ProtectionSpell.Registry.TryGetValue(Caster, out var d) &&
d <= Utility.RandomDouble() * 100.0)
{
Disturb(DisturbType.Hurt, false, true);
}
}
public virtual void OnCasterKilled()
@ -113,7 +115,9 @@ namespace Server.Spells
public virtual bool OnCasterEquipping(Item item)
{
if (IsCasting)
{
Disturb(DisturbType.EquipRequest);
}
return true;
}
@ -121,7 +125,9 @@ namespace Server.Spells
public virtual bool OnCasterUsingObject(IEntity entity)
{
if (State == SpellState.Sequencing)
{
Disturb(DisturbType.UseRequest);
}
return true;
}
@ -133,16 +139,22 @@ namespace Server.Spells
State = SpellState.None;
if (Caster.Spell == this)
{
Caster.Spell = null;
}
}
public void StartDelayedDamageContext(Mobile m, Timer t)
{
if (DelayedDamageStacking)
{
return; // Sanity
}
if (!m_ContextTable.TryGetValue(GetType(), out var contexts))
{
m_ContextTable[GetType()] = contexts = new DelayedDamageContextWrapper();
}
contexts.Add(m, t);
}
@ -150,7 +162,9 @@ namespace Server.Spells
public void RemoveDelayedDamageContext(Mobile m)
{
if (m_ContextTable.TryGetValue(GetType(), out var contexts))
{
contexts.Remove(m);
}
}
public void HarmfulSpell(Mobile m)
@ -161,6 +175,7 @@ namespace Server.Spells
public virtual int GetNewAosDamage(int bonus, uint dice, uint sides, Mobile singleTarget)
{
if (singleTarget != null)
{
return GetNewAosDamage(
bonus,
dice,
@ -168,6 +183,7 @@ namespace Server.Spells
Caster.Player && singleTarget.Player,
GetDamageScalar(singleTarget)
);
}
return GetNewAosDamage(bonus, dice, sides, false);
}
@ -189,14 +205,18 @@ namespace Server.Spells
var sdiBonus = AosAttributes.GetValue(Caster, AosAttribute.SpellDamage);
// PvP spell damage increase cap of 15% from an item<65>s magic property
if (playerVsPlayer && sdiBonus > 15)
{
sdiBonus = 15;
}
damageBonus += sdiBonus;
var context = TransformationSpellHelper.GetContext(Caster);
if (context?.Spell is ReaperFormSpell spell)
{
damageBonus += spell.SpellDamageBonus;
}
damage = AOS.Scale(damage, 100 + damageBonus);
@ -242,15 +262,21 @@ namespace Server.Spells
// m_Caster.CheckSkill( DamageSkill, 0.0, 120.0 );
if (casterEI > targetRS)
{
scalar = 1.0 + (casterEI - targetRS) / 500.0;
}
else
{
scalar = 1.0 + (casterEI - targetRS) / 200.0;
}
// magery damage bonus, -25% at 0 skill, +0% at 100 skill, +5% at 120 skill
scalar += (Caster.Skills[CastSkill].Value - 100.0) / 400.0;
if (!target.Player && !target.Body.IsHuman /*&& !Core.AOS*/)
{
scalar *= 2.0; // Double magery damage to monsters/animals if not AOS
}
}
(target as BaseCreature)?.AlterDamageScalarFrom(Caster, ref scalar);
@ -258,12 +284,16 @@ namespace Server.Spells
(Caster as BaseCreature)?.AlterDamageScalarTo(target, ref scalar);
if (Core.SE)
{
scalar *= GetSlayerDamageScalar(target);
}
target.Region.SpellDamageScalar(Caster, target, ref scalar);
if (Evasion.CheckSpellEvasion(target)) // Only single target spells an be evaded
{
scalar = 0;
}
return scalar;
}
@ -288,10 +318,14 @@ namespace Server.Spells
if ((atkBook.Slayer == SlayerName.Silver || atkBook.Slayer2 == SlayerName.Silver) && context != null &&
context.Type != typeof(HorrificBeastSpell))
{
scalar += .25; // Every necromancer transformation other than horrific beast take an additional 25% damage
}
if (scalar != 1.0)
{
return scalar;
}
}
var defISlayer = Spellbook.FindEquippedSpellbook(defender) ?? defender.Weapon as ISlayer;
@ -303,7 +337,9 @@ namespace Server.Spells
if (defSlayer?.Group.OppositionSuperSlays(Caster) == true ||
defSlayer2?.Group.OppositionSuperSlays(Caster) == true)
{
scalar = 2.0;
}
}
return scalar;
@ -316,9 +352,13 @@ namespace Server.Spells
if (Caster.Player)
{
if (Core.AOS)
{
Caster.FixedParticles(0x3735, 1, 30, 9503, EffectLayer.Waist);
}
else
{
Caster.FixedEffect(0x3735, 6, 30);
}
Caster.PlaySound(0x5C);
}
@ -330,12 +370,16 @@ namespace Server.Spells
public void Disturb(DisturbType type, bool firstCircle = true, bool resistable = false)
{
if (!CheckDisturb(type, firstCircle, resistable))
{
return;
}
if (State == SpellState.Casting)
{
if (!firstCircle && !Core.AOS && this is MagerySpell && ((MagerySpell)this).Circle == SpellCircle.First)
{
return;
}
State = SpellState.None;
Caster.Spell = null;
@ -347,14 +391,18 @@ namespace Server.Spells
m_AnimTimer?.Stop();
if (Core.AOS && Caster.Player && type == DisturbType.Hurt)
{
DoHurtFizzle();
}
Caster.NextSpellTime = Core.TickCount + (int)GetDisturbRecovery().TotalMilliseconds;
}
else if (State == SpellState.Sequencing)
{
if (!firstCircle && !Core.AOS && this is MagerySpell && ((MagerySpell)this).Circle == SpellCircle.First)
{
return;
}
State = SpellState.None;
Caster.Spell = null;
@ -364,7 +412,9 @@ namespace Server.Spells
Target.Cancel(Caster);
if (Core.AOS && Caster.Player && type == DisturbType.Hurt)
{
DoHurtFizzle();
}
}
}
@ -377,7 +427,9 @@ namespace Server.Spells
public virtual void OnDisturb(DisturbType type, bool message)
{
if (message)
{
Caster.SendLocalizedMessage(500641); // Your concentration is disturbed, thus ruining thy spell.
}
}
public virtual bool CheckCast() => true;
@ -385,10 +437,14 @@ namespace Server.Spells
public virtual void SayMantra()
{
if (Scroll is BaseWand)
{
return;
}
if (!string.IsNullOrEmpty(Info.Mantra) && Caster.Player)
{
Caster.PublicOverheadMessage(MessageType.Spell, Caster.SpeechHue, true, Info.Mantra, false);
}
}
public bool Cast()
@ -396,9 +452,14 @@ namespace Server.Spells
StartCastTime = Core.TickCount;
if (Core.AOS && Caster.Spell is Spell spell && spell.State == SpellState.Sequencing)
{
spell.Disturb(DisturbType.NewCast);
}
if (!Caster.CheckAlive()) return false;
if (!Caster.CheckAlive())
{
return false;
}
if (Scroll is BaseWand && Caster.Spell?.IsCasting == true)
{
@ -438,7 +499,9 @@ namespace Server.Spells
Caster.Spell = this;
if (!(Scroll is BaseWand) && RevealOnCast)
{
Caster.RevealingAction();
}
SayMantra();
@ -455,17 +518,25 @@ namespace Server.Spells
}
if (Info.LeftHandEffect > 0)
{
Caster.FixedParticles(0, 10, 5, Info.LeftHandEffect, EffectLayer.LeftHand);
}
if (Info.RightHandEffect > 0)
{
Caster.FixedParticles(0, 10, 5, Info.RightHandEffect, EffectLayer.RightHand);
}
}
if (ClearHandsOnCast)
{
Caster.ClearHands();
}
if (Core.ML)
{
WeaponAbility.ClearCurrentAbility(Caster);
}
m_CastTimer = new CastTimer(this, castDelay);
// m_CastTimer.Start();
@ -473,9 +544,13 @@ namespace Server.Spells
OnBeginCast();
if (castDelay > TimeSpan.Zero)
{
m_CastTimer.Start();
}
else
{
m_CastTimer.Tick();
}
return true;
}
@ -504,12 +579,16 @@ namespace Server.Spells
public virtual bool CheckFizzle()
{
if (Scroll is BaseWand)
{
return true;
}
GetCastSkills(out var minSkill, out var maxSkill);
if (DamageSkill != CastSkill)
{
Caster.CheckSkill(DamageSkill, 0.0, Caster.Skills[DamageSkill].Cap);
}
return Caster.CheckSkill(CastSkill, minSkill, maxSkill);
}
@ -521,12 +600,16 @@ namespace Server.Spells
var scalar = 1.0;
if (!MindRotSpell.GetMindRotScalar(Caster, ref scalar))
{
scalar = 1.0;
}
// Lower Mana Cost = 40%
var lmc = AosAttributes.GetValue(Caster, AosAttribute.LowerManaCost);
if (lmc > 40)
{
lmc = 40;
}
scalar -= (double)lmc / 100;
@ -536,7 +619,9 @@ namespace Server.Spells
public virtual TimeSpan GetDisturbRecovery()
{
if (Core.AOS)
{
return TimeSpan.Zero;
}
var delay = Math.Max(
1.0 - Math.Sqrt((Core.TickCount - StartCastTime) / 1000.0 / GetCastDelay().TotalSeconds),
@ -549,7 +634,9 @@ namespace Server.Spells
public virtual TimeSpan GetCastRecovery()
{
if (!Core.AOS)
{
return NextSpellDelay;
}
var fcr = AosAttributes.GetValue(Caster, AosAttribute.CastRecovery) -
ThunderstormSpell.GetCastRecoveryMalus(Caster);
@ -559,7 +646,9 @@ namespace Server.Spells
var delay = CastRecoveryBase + fcrDelay;
if (delay < CastRecoveryMinimum)
{
delay = CastRecoveryMinimum;
}
return TimeSpan.FromSeconds((double)delay / CastRecoveryPerSecond);
}
@ -572,7 +661,9 @@ namespace Server.Spells
public virtual TimeSpan GetCastDelay()
{
if (Scroll is BaseWand)
{
return Core.ML ? CastDelayBase : TimeSpan.Zero; // TODO: Should FC apply to wands?
}
// Faster casting cap of 2 (if not using the protection spell)
// Faster casting cap of 0 (if using the protection spell)
@ -582,15 +673,21 @@ namespace Server.Spells
if (CastSkill == SkillName.Magery || CastSkill == SkillName.Necromancy ||
CastSkill == SkillName.Chivalry && Caster.Skills.Magery.Value >= 70.0)
{
fcMax = 2;
}
var fc = Math.Min(AosAttributes.GetValue(Caster, AosAttribute.CastSpeed), fcMax);
if (ProtectionSpell.Registry.ContainsKey(Caster))
{
fc -= 2;
}
if (EssenceOfWindSpell.IsDebuffed(Caster))
{
fc -= EssenceOfWindSpell.GetFCMalus(Caster);
}
var fcDelay = TimeSpan.FromSeconds(-(CastDelayFastScalar * fc * CastDelaySecondsPerTick));
@ -652,27 +749,35 @@ namespace Server.Spells
Scroll.Movable = false;
if (ClearHandsOnCast)
{
Caster.ClearHands();
}
Scroll.Movable = m;
}
else
{
if (ClearHandsOnCast)
{
Caster.ClearHands();
}
}
var karma = ComputeKarmaAward();
if (karma != 0)
{
Titles.AwardKarma(Caster, karma, true);
}
if (TransformationSpellHelper.UnderTransformation(Caster, typeof(VampiricEmbraceSpell)))
{
var garlic = false;
for (var i = 0; !garlic && i < Info.Reagents.Length; ++i)
{
garlic = Info.Reagents[i] == Reagent.Garlic;
}
if (garlic)
{
@ -770,13 +875,19 @@ namespace Server.Spells
if (!m_Spell.Caster.Mounted && m_Spell.Info.Action >= 0)
{
if (m_Spell.Caster.Body.IsHuman)
{
m_Spell.Caster.Animate(m_Spell.Info.Action, 7, 1, true, false, 0);
}
else if (m_Spell.Caster.Player && m_Spell.Caster.Body.IsMonster)
{
m_Spell.Caster.Animate(12, 7, 1, true, false, 0);
}
}
if (!Running)
{
m_Spell.m_AnimTimer = null;
}
}
}
@ -793,7 +904,10 @@ namespace Server.Spells
protected override void OnTick()
{
if (m_Spell?.Caster == null) return;
if (m_Spell?.Caster == null)
{
return;
}
if (m_Spell.State == SpellState.Casting && m_Spell.Caster.Spell == m_Spell)
{
@ -809,7 +923,9 @@ namespace Server.Spells
m_Spell.OnCast();
if (m_Spell.Caster.Player && m_Spell.Caster.Target != originalTarget)
{
m_Spell.Caster.Target?.BeginTimeout(m_Spell.Caster, TimeSpan.FromSeconds(30.0));
}
m_Spell.m_CastTimer = null;
}

View file

@ -23,7 +23,9 @@ namespace Server
public static void Nullify(Mobile from)
{
if (!from.CanBeginAction<DefensiveSpell>())
{
new InternalTimer(from).Start();
}
}
private class InternalTimer : Timer
@ -155,7 +157,9 @@ namespace Server.Spells
public static bool CheckMulti(Point3D p, Map map, bool houses = true, int housingrange = 0)
{
if (map == null || map == Map.Internal)
{
return false;
}
var sector = map.GetSector(p.X, p.Y);
@ -166,7 +170,9 @@ namespace Server.Spells
if (multi is BaseHouse bh)
{
if (houses && bh.IsInside(p, 16) || housingrange > 0 && bh.InRange(p, housingrange))
{
return true;
}
}
else if (multi.Contains(p))
{
@ -180,12 +186,16 @@ namespace Server.Spells
public static void Turn(Mobile from, object to)
{
if (!(to is IPoint3D target))
{
return;
}
if (target is Item item)
{
if (item.RootParent != from)
{
from.Direction = from.GetDirectionTo(item.GetWorldLocation());
}
}
else if (from != target)
{
@ -196,24 +206,32 @@ namespace Server.Spells
public static bool CheckCombat(Mobile m)
{
if (!RestrictTravelCombat)
{
return false;
}
for (var i = 0; i < m.Aggressed.Count; ++i)
{
var info = m.Aggressed[i];
if (info.Defender.Player && DateTime.UtcNow - info.LastCombatTime < CombatHeatDelay)
{
return true;
}
}
if (Core.Expansion == Expansion.AOS)
{
for (var i = 0; i < m.Aggressors.Count; ++i)
{
var info = m.Aggressors[i];
if (info.Attacker.Player && DateTime.UtcNow - info.LastCombatTime < CombatHeatDelay)
{
return true;
}
}
}
return false;
}
@ -221,7 +239,9 @@ namespace Server.Spells
public static bool AdjustField(ref Point3D p, Map map, int height, bool mobsBlock)
{
if (map == null)
{
return false;
}
for (var offset = 0; offset < 10; ++offset)
{
@ -250,7 +270,9 @@ namespace Server.Spells
var z = t.Z;
if ((t.Flags & TileFlag.Surface) == 0)
{
z -= TileData.ItemTable[t.ItemID & TileData.MaxItemValue].CalcHeight;
}
p = new Point3D(t.X, t.Y, z);
}
@ -331,9 +353,13 @@ namespace Server.Spells
double percent;
if (curse)
{
percent = 8 + caster.Skills.EvalInt.Fixed / 100 - target.Skills.MagicResist.Fixed / 100;
}
else
{
percent = 1 + caster.Skills.EvalInt.Fixed / 100;
}
percent *= 0.01;
@ -349,7 +375,9 @@ namespace Server.Spells
caster.CheckSkill(SkillName.EvalInt, 0.0, 120.0);
if (curse)
{
target.CheckSkill(SkillName.MagicResist, 0.0, 120.0);
}
}
var percent = GetOffsetScalar(caster, target, curse);
@ -377,14 +405,18 @@ namespace Server.Spells
m = c.ControlMaster;
if (m != null)
{
g = m.Guild as Guild;
}
if (g == null)
{
m = c.SummonMaster;
if (m != null)
{
g = m.Guild as Guild;
}
}
}
@ -394,10 +426,14 @@ namespace Server.Spells
public static bool ValidIndirectTarget(Mobile from, Mobile to)
{
if (from == to)
{
return true;
}
if (to.Hidden && to.AccessLevel > from.AccessLevel)
{
return false;
}
var bcFrom = from as BaseCreature;
var bcTarg = to as BaseCreature;
@ -406,48 +442,70 @@ namespace Server.Spells
PlayerMobile pmTarg;
if (bcFrom?.Summoned == true)
{
pmFrom = bcFrom.SummonMaster as PlayerMobile;
}
else
{
pmFrom = from as PlayerMobile;
}
if (bcTarg?.Summoned == true)
{
pmTarg = bcTarg.SummonMaster as PlayerMobile;
}
else
{
pmTarg = to as PlayerMobile;
}
if (pmFrom?.DuelContext != null && pmFrom.DuelContext == pmTarg?.DuelContext && pmFrom.DuelContext.Started &&
pmFrom.DuelPlayer != null && pmTarg?.DuelPlayer != null)
{
return pmFrom.DuelPlayer.Participant != pmTarg.DuelPlayer.Participant;
}
var fromGuild = GetGuildFor(from);
var toGuild = GetGuildFor(to);
if (fromGuild != null && toGuild != null && (fromGuild == toGuild || fromGuild.IsAlly(toGuild)))
{
return false;
}
var p = Party.Get(from);
if (p?.Contains(to) == true)
{
return false;
}
if (bcTarg != null && (bcTarg.Controlled || bcTarg.Summoned))
{
if (bcTarg.ControlMaster == from || bcTarg.SummonMaster == from)
{
return false;
}
if (p != null && (p.Contains(bcTarg.ControlMaster) || p.Contains(bcTarg.SummonMaster)))
{
return false;
}
}
if (bcFrom != null && (bcFrom.Controlled || bcFrom.Summoned))
{
if (bcFrom.ControlMaster == to || bcFrom.SummonMaster == to)
{
return false;
}
p = Party.Get(to);
if (p != null && (p.Contains(bcFrom.ControlMaster) || p.Contains(bcFrom.SummonMaster)))
{
return false;
}
}
return bcTarg?.Controlled == false && bcTarg.InitialInnocent ||
@ -462,12 +520,16 @@ namespace Server.Spells
var map = caster.Map;
if (map == null)
{
return;
}
var scale = 1.0 + (caster.Skills.Magery.Value - 100.0) / 200.0;
if (scaleDuration)
{
duration = TimeSpan.FromSeconds(duration.TotalSeconds * scale);
}
if (scaleStats)
{
@ -491,12 +553,12 @@ namespace Server.Spells
/*
int offset = Utility.Random( 8 ) * 2;
for ( int i = 0; i < m_Offsets.Length; i += 2 )
{
int x = caster.X + m_Offsets[(offset + i) % m_Offsets.Length];
int y = caster.Y + m_Offsets[(offset + i + 1) % m_Offsets.Length];
if (map.CanSpawnMobile( x, y, caster.Z ))
{
BaseCreature.Summon( creature, caster, new Point3D( x, y, caster.Z ), sound, duration );
@ -505,7 +567,7 @@ namespace Server.Spells
else
{
int z = map.GetAverageZ( x, y );
if (map.CanSpawnMobile( x, y, z ))
{
BaseCreature.Summon( creature, caster, new Point3D( x, y, z ), sound, duration );
@ -522,7 +584,9 @@ namespace Server.Spells
public static bool FindValidSpawnLocation(Map map, ref Point3D p, bool surroundingsOnly)
{
if (map == null) // sanity
{
return false;
}
if (!surroundingsOnly)
{
@ -569,11 +633,17 @@ namespace Server.Spells
public static void SendInvalidMessage(Mobile caster, TravelCheckType type)
{
if (type == TravelCheckType.RecallTo || type == TravelCheckType.GateTo)
{
caster.SendLocalizedMessage(1019004); // You are not allowed to travel there.
}
else if (type == TravelCheckType.TeleportTo)
{
caster.SendLocalizedMessage(501035); // You cannot teleport from here to the destination.
}
else
{
caster.SendLocalizedMessage(501802); // Thy spell doth not appear to work...
}
}
public static bool CheckTravel(Mobile caster, TravelCheckType type) =>
@ -586,7 +656,9 @@ namespace Server.Spells
if (IsInvalid(map, loc)) // null, internal, out of bounds
{
if (caster != null)
{
SendInvalidMessage(caster, type);
}
return false;
}
@ -594,7 +666,9 @@ namespace Server.Spells
// Always allow monsters to teleport
if (caster is BaseCreature bc && !bc.Controlled && !bc.Summoned &&
(type == TravelCheckType.TeleportTo || type == TravelCheckType.TeleportFrom))
{
return true;
}
m_TravelCaster = caster;
m_TravelType = type;
@ -608,14 +682,20 @@ namespace Server.Spells
var current = Region.Find(caster.Location, map) as BaseRegion;
if (destination?.CheckTravel(caster, loc, type) == false || current?.CheckTravel(caster, loc, type) == false)
{
isValid = false;
}
}
for (var i = 0; isValid && i < m_Validators.Length; ++i)
{
isValid = m_Rules[v, i] || !m_Validators[i](map, loc);
}
if (!isValid && caster != null)
{
SendInvalidMessage(caster, type);
}
return isValid;
}
@ -669,7 +749,9 @@ namespace Server.Spells
public static bool IsCrystalCave(Map map, Point3D loc)
{
if (map != Map.Malas || loc.Z >= -80)
{
return false;
}
int x = loc.X, y = loc.Y;
@ -691,7 +773,9 @@ namespace Server.Spells
public static bool IsDoomFerry(Map map, Point3D loc)
{
if (map != Map.Malas)
{
return false;
}
int x = loc.X, y = loc.Y;
@ -702,7 +786,9 @@ namespace Server.Spells
{
// The tokuno dungeons are really inside malas
if (map != Map.Malas)
{
return false;
}
int x = loc.X, y = loc.Y, z = loc.Z;
@ -715,7 +801,9 @@ namespace Server.Spells
public static bool IsDoomGauntlet(Map map, Point3D loc)
{
if (map != Map.Malas)
{
return false;
}
int x = loc.X - 256, y = loc.Y - 304;
@ -725,7 +813,9 @@ namespace Server.Spells
public static bool IsLampRoom(Map map, Point3D loc)
{
if (map != Map.Malas)
{
return false;
}
int x = loc.X, y = loc.Y;
@ -735,7 +825,9 @@ namespace Server.Spells
public static bool IsGuardianRoom(Map map, Point3D loc)
{
if (map != Map.Malas)
{
return false;
}
int x = loc.X, y = loc.Y;
@ -754,7 +846,9 @@ namespace Server.Spells
public static bool IsInvalid(Map map, Point3D loc)
{
if (map == null || map == Map.Internal)
{
return true;
}
int x = loc.X, y = loc.Y;
@ -765,7 +859,9 @@ namespace Server.Spells
public static bool IsTown(IPoint3D ip, Mobile caster)
{
if (ip is Item item)
{
ip = item.GetWorldLocation();
}
return IsTown(new Point3D(ip), caster);
}
@ -775,11 +871,17 @@ namespace Server.Spells
var map = caster.Map;
if (map == null)
{
return false;
}
if (Region.Find(loc, map).GetRegion<SafeZone>() != null)
{
if (caster is PlayerMobile pm && (pm.DuelContext?.Started != true || pm.DuelPlayer?.Eliminated != false))
{
return true;
}
}
var reg = Region.Find(loc, map).GetRegion<GuardedRegion>();
@ -789,7 +891,9 @@ namespace Server.Spells
public static bool CheckTown(IPoint3D ip, Mobile caster)
{
if (ip is Item item)
{
ip = item.GetWorldLocation();
}
return CheckTown(new Point3D(ip), caster);
}
@ -953,7 +1057,9 @@ namespace Server.Spells
var damageGiven = AOS.Damage(target, from, dmg, phys, fire, cold, pois, nrgy, chaos);
if (from != null) // sanity check
{
DoLeech(damageGiven, from, target);
}
WeightOverloading.DFA = DFAlgorithm.Standard;
}
@ -974,7 +1080,9 @@ namespace Server.Spells
var context = TransformationSpellHelper.GetContext(from);
if (context == null) /* cleanup */
{
return;
}
if (context.Type == typeof(WraithFormSpell))
{
@ -1019,7 +1127,9 @@ namespace Server.Spells
m_Spell = s;
if (m_Spell?.DelayedDamage == true && !m_Spell.DelayedDamageStacking)
{
m_Spell.StartDelayedDamageContext(target, this);
}
Priority = TimerPriority.TwentyFiveMS;
}
@ -1067,7 +1177,9 @@ namespace Server.Spells
m_DFA = dfa;
m_Spell = s;
if (m_Spell?.DelayedDamage == true && !m_Spell.DelayedDamageStacking)
{
m_Spell.StartDelayedDamageContext(target, this);
}
Priority = TimerPriority.TwentyFiveMS;
}
@ -1078,17 +1190,23 @@ namespace Server.Spells
var bcTarg = m_Target as BaseCreature;
if (bcFrom != null && m_Target != null)
{
bcFrom.AlterSpellDamageTo(m_Target, ref m_Damage);
}
if (bcTarg != null && m_From != null)
{
bcTarg.AlterSpellDamageFrom(m_From, ref m_Damage);
}
WeightOverloading.DFA = m_DFA;
var damageGiven = AOS.Damage(m_Target, m_From, m_Damage, m_Phys, m_Fire, m_Cold, m_Pois, m_Nrgy, m_Chaos);
if (m_From != null) // sanity check
{
DoLeech(damageGiven, m_From, m_Target);
}
WeightOverloading.DFA = DFAlgorithm.Standard;
@ -1133,7 +1251,9 @@ namespace Server.Spells
public static bool OnCast(Mobile caster, Spell spell)
{
if (!(spell is ITransformationSpell transformSpell))
{
return false;
}
if (Sigil.ExistsOn(caster))
{
@ -1180,33 +1300,47 @@ namespace Server.Spells
var mods = new List<ResistanceMod>();
if (transformSpell.PhysResistOffset != 0)
{
mods.Add(new ResistanceMod(ResistanceType.Physical, transformSpell.PhysResistOffset));
}
if (transformSpell.FireResistOffset != 0)
{
mods.Add(new ResistanceMod(ResistanceType.Fire, transformSpell.FireResistOffset));
}
if (transformSpell.ColdResistOffset != 0)
{
mods.Add(new ResistanceMod(ResistanceType.Cold, transformSpell.ColdResistOffset));
}
if (transformSpell.PoisResistOffset != 0)
{
mods.Add(new ResistanceMod(ResistanceType.Poison, transformSpell.PoisResistOffset));
}
if (transformSpell.NrgyResistOffset != 0)
{
mods.Add(new ResistanceMod(ResistanceType.Energy, transformSpell.NrgyResistOffset));
}
if (!((Body)transformSpell.Body).IsHuman)
{
var mt = caster.Mount;
if (mt != null)
{
mt.Rider = null;
}
}
caster.BodyMod = transformSpell.Body;
caster.HueMod = transformSpell.Hue;
for (var i = 0; i < mods.Count; ++i)
{
caster.AddResistanceMod(mods[i]);
}
transformSpell.DoEffect(caster);
@ -1231,20 +1365,24 @@ namespace Server.Spells
var context = GetContext(m);
if (context != null)
{
RemoveContext(m, context, resetGraphics);
}
}
public static void RemoveContext(Mobile m, TransformContext context, bool resetGraphics)
{
if (!m_Table.ContainsKey(m))
if (!m_Table.Remove(m))
{
return;
m_Table.Remove(m);
}
var mods = context.Mods;
for (var i = 0; i < mods.Count; ++i)
{
m.RemoveResistanceMod(mods[i]);
}
if (resetGraphics)
{

View file

@ -75,8 +75,7 @@ namespace Server.Spells
m_Types[spellID] = type;
if (!m_IDsFromTypes.ContainsKey(type))
m_IDsFromTypes.Add(type, spellID);
m_IDsFromTypes.TryAdd(type, spellID);
if (type.IsSubclassOf(typeof(SpecialMove)))
{

View file

@ -62,10 +62,9 @@ namespace Server.Spells.Bushido
public static void EndConfidence(Mobile m)
{
if (m_Table.TryGetValue(m, out var timer))
if (m_Table.Remove(m, out var timer))
{
timer.Stop();
m_Table.Remove(m);
}
OnEffectEnd(m, typeof(Confidence));
@ -85,10 +84,9 @@ namespace Server.Spells.Bushido
public static void StopRegenerating(Mobile m)
{
if (m_RegenTable.TryGetValue(m, out var timer))
if (m_RegenTable.Remove(m, out var timer))
{
timer.Stop();
m_RegenTable.Remove(m);
}
}

View file

@ -77,10 +77,9 @@ namespace Server.Spells.Bushido
public static void StopCountering(Mobile m)
{
if (m_Table.TryGetValue(m, out var timer))
if (m_Table.Remove(m, out var timer))
{
timer.Stop();
m_Table.Remove(m);
}
OnEffectEnd(m, typeof(CounterAttack));

View file

@ -181,10 +181,9 @@ namespace Server.Spells.Bushido
public static void EndEvasion(Mobile m)
{
if (m_Table.TryGetValue(m, out var timer))
if (m_Table.Remove(m, out var timer))
{
timer.Stop();
m_Table.Remove(m);
}
OnEffectEnd(m, typeof(Evasion));

View file

@ -25,7 +25,9 @@ namespace Server.Spells.Bushido
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker) || !CheckMana(attacker, true))
{
return;
}
ClearCurrentMove(attacker);
@ -64,7 +66,9 @@ namespace Server.Spells.Bushido
var resSpells = attacker.Skills.MagicResist.Value;
if (resSpells > 0.0)
{
mods.Add(new DefaultSkillMod(SkillName.MagicResist, true, -resSpells));
}
info = new HonorableExecutionInfo(attacker, mods);
info.m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(7.0), RemovePenalty, info.m_Mobile);
@ -81,12 +85,13 @@ namespace Server.Spells.Bushido
public static void RemovePenalty(Mobile target)
{
if (!m_Table.TryGetValue(target, out var info) || !info.m_Penalty)
if (!m_Table.Remove(target, out var info) || !info.m_Penalty)
{
return;
}
info.Clear();
info.m_Timer?.Stop();
m_Table.Remove(target);
}
private class HonorableExecutionInfo
@ -114,32 +119,44 @@ namespace Server.Spells.Bushido
public void Apply()
{
if (m_Mods == null)
{
return;
}
for (var i = 0; i < m_Mods.Count; ++i)
{
var mod = m_Mods[i];
if (mod is ResistanceMod resistanceMod)
{
m_Mobile.AddResistanceMod(resistanceMod);
}
else if (mod is SkillMod skillMod)
{
m_Mobile.AddSkillMod(skillMod);
}
}
}
public void Clear()
{
if (m_Mods == null)
{
return;
}
for (var i = 0; i < m_Mods.Count; ++i)
{
var mod = m_Mods[i];
if (mod is ResistanceMod resistanceMod)
{
m_Mobile.RemoveResistanceMod(resistanceMod);
}
else if (mod is SkillMod skillMod)
{
m_Mobile.RemoveSkillMod(skillMod);
}
}
}
}

View file

@ -25,7 +25,9 @@ namespace Server.Spells.Fifth
public override bool CheckCast()
{
if (Core.AOS)
{
return true;
}
if (Caster.MagicDamageAbsorb > 0)
{
@ -57,15 +59,15 @@ namespace Server.Spells.Fifth
{
var targ = Caster;
if (m_Table.TryGetValue(targ, out var mods))
if (m_Table.Remove(targ, out var mods))
{
targ.PlaySound(0x1ED);
targ.FixedParticles(0x375A, 10, 15, 5037, EffectLayer.Waist);
m_Table.Remove(targ);
for (var i = 0; i < mods.Length; ++i)
{
targ.RemoveResistanceMod(mods[i]);
}
BuffInfo.RemoveBuff(targ, BuffIcon.MagicReflection);
}
@ -89,7 +91,9 @@ namespace Server.Spells.Fifth
m_Table[targ] = mods;
for (var i = 0; i < mods.Length; ++i)
{
targ.AddResistanceMod(mods[i]);
}
var buffFormat = $"{physiMod}\t+{otherMod}\t+{otherMod}\t+{otherMod}\t+{otherMod}";
@ -133,13 +137,16 @@ namespace Server.Spells.Fifth
public static void EndReflect(Mobile m)
{
if (!m_Table.TryGetValue(m, out var mods))
if (!m_Table.Remove(m, out var mods))
{
return;
}
for (var i = 0; i < mods?.Length; ++i)
{
m.RemoveResistanceMod(mods[i]);
}
m_Table.Remove(m);
BuffInfo.RemoveBuff(m, BuffIcon.MagicReflection);
}
}

View file

@ -26,7 +26,9 @@ namespace Server.Spells.First
public override bool CheckCast()
{
if (Core.AOS)
{
return true;
}
if (Caster.MeleeDamageAbsorb > 0)
{
@ -59,15 +61,15 @@ namespace Server.Spells.First
{
var targ = Caster;
if (m_Table.TryGetValue(targ, out var mods))
if (m_Table.Remove(targ, out var mods))
{
targ.PlaySound(0x1ED);
targ.FixedParticles(0x376A, 9, 32, 5008, EffectLayer.Waist);
m_Table.Remove(targ);
for (var i = 0; i < mods.Length; ++i)
{
targ.RemoveResistanceMod(mods[i]);
}
BuffInfo.RemoveBuff(Caster, BuffIcon.ReactiveArmor);
}
@ -91,7 +93,9 @@ namespace Server.Spells.First
m_Table[targ] = mods;
for (var i = 0; i < mods.Length; ++i)
{
targ.AddResistanceMod(mods[i]);
}
var physresist = 15 + (int)(targ.Skills.Inscribe.Value / 20);
var args = $"{physresist}\t{5}\t{5}\t{5}\t{5}";
@ -140,13 +144,16 @@ namespace Server.Spells.First
public static void EndArmor(Mobile m)
{
if (!m_Table.TryGetValue(m, out var mods))
if (!m_Table.Remove(m, out var mods))
{
return;
}
for (var i = 0; i < mods?.Length; ++i)
{
m.RemoveResistanceMod(mods[i]);
}
m_Table.Remove(m);
BuffInfo.RemoveBuff(m, BuffIcon.ReactiveArmor);
}
}

View file

@ -97,9 +97,8 @@ namespace Server.Spells.Fourth
public static void RemoveEntry(Mobile m)
{
if (_Table.TryGetValue(m, out var v))
if (_Table.Remove(m, out var v))
{
_Table.Remove(m);
m.EndAction<ArchProtectionSpell>();
m.VirtualArmorMod -= Math.Min(v, m.VirtualArmorMod);
}

View file

@ -95,7 +95,9 @@ namespace Server.Spells.Mysticism
var mount = Caster.Mount;
if (mount != null)
{
mount.Rider = null;
}
Caster.BodyMod = 0x2C1;
Caster.HueMod = 0;
@ -112,7 +114,9 @@ namespace Server.Spells.Mysticism
};
for (var i = 0; i < mods.Length; ++i)
{
Caster.AddResistanceMod(mods[i]);
}
m_Table[Caster] = mods;
@ -141,17 +145,19 @@ namespace Server.Spells.Mysticism
public static void RemoveEffects(Mobile m)
{
if (!m_Table.TryGetValue(m, out var mods))
if (!m_Table.Remove(m, out var mods))
{
return;
}
for (var i = 0; i < mods.Length; ++i)
{
m.RemoveResistanceMod(mods[i]);
}
m.BodyMod = 0;
m.HueMod = -1;
m_Table.Remove(m);
BuffInfo.RemoveBuff(m, BuffIcon.StoneForm);
}

View file

@ -151,7 +151,10 @@ namespace Server.Spells.Necromancy
{
Type type = null;
if (c.Owner != null) type = c.Owner.GetType();
if (c.Owner != null)
{
type = c.Owner.GetType();
}
if (c.ItemID != 0x2006 || c.Animated || type == typeof(PlayerMobile) || type == null ||
c.Owner != null && c.Owner.Fame < 100 ||
@ -217,10 +220,14 @@ namespace Server.Spells.Necromancy
var contains = types.Length == 0;
for (var j = 0; !contains && j < types.Length; ++j)
{
contains = types[j].IsAssignableFrom(type);
}
if (contains)
return group;
{
return @group;
}
}
return null;
@ -228,41 +235,52 @@ namespace Server.Spells.Necromancy
public static void Unregister(Mobile master, Mobile summoned)
{
if (master == null)
return;
if (!m_Table.TryGetValue(master, out var list))
if (master == null || !m_Table.TryGetValue(master, out var list))
{
return;
}
list.Remove(summoned);
if (list.Count == 0)
{
m_Table.Remove(master);
}
}
public static void Register(Mobile master, Mobile summoned)
{
if (master == null)
{
return;
}
if (!m_Table.TryGetValue(master, out var list))
{
m_Table[master] = list = new List<Mobile>();
}
for (var i = list.Count - 1; i >= 0; --i)
{
if (i >= list.Count)
{
continue;
}
var mob = list[i];
if (mob.Deleted)
{
list.RemoveAt(i--);
}
}
list.Add(summoned);
if (list.Count > 3)
{
Timer.DelayCall(list[0].Kill);
}
Timer.DelayCall(TimeSpan.FromSeconds(2.0), TimeSpan.FromSeconds(2.0), Summoned_Damage, summoned);
}
@ -270,20 +288,28 @@ namespace Server.Spells.Necromancy
private static void Summoned_Damage(Mobile mob)
{
if (mob.Hits > 0)
{
--mob.Hits;
}
else
{
mob.Kill();
}
}
private static void SummonDelay_Callback(Mobile caster, Corpse corpse, Point3D loc, Map map, CreatureGroup group)
{
if (corpse.Animated)
{
return;
}
var owner = corpse.Owner;
if (owner == null)
{
return;
}
var necromancy = caster.Skills.Necromancy.Value;
var spiritSpeak = caster.Skills.SpiritSpeak.Value;
@ -299,7 +325,9 @@ namespace Server.Spells.Necromancy
var entry = entries[i];
if (casterAbility < entry.m_Requirement)
{
continue;
}
var animates = entry.m_ToSummon;
@ -307,7 +335,9 @@ namespace Server.Spells.Necromancy
}
if (toSummon == null)
{
return;
}
Mobile summoned = null;
@ -321,7 +351,9 @@ namespace Server.Spells.Necromancy
}
if (summoned == null)
{
return;
}
if (summoned is BaseCreature bc)
{
@ -336,7 +368,9 @@ namespace Server.Spells.Necromancy
}
if (summoned is SkeletalDragon dragon)
{
Scale(dragon, 50); // lose 50% hp and strength
}
summoned.Fame = 0;
summoned.Karma = -1500;
@ -357,7 +391,9 @@ namespace Server.Spells.Necromancy
toScale = bc.HitsMaxSeed;
if (toScale > 0)
{
bc.HitsMaxSeed = AOS.Scale(toScale, scalar);
}
bc.Hits = bc.Hits; // refresh hits
}

View file

@ -45,9 +45,13 @@ namespace Server.Spells.Necromancy
else if (m_OathTable.ContainsKey(m))
{
if (m.Player)
{
Caster.SendLocalizedMessage(1061608); // That player is already bonded in a Blood Oath.
}
else
{
Caster.SendLocalizedMessage(1061609); // That creature is already bonded in a Blood Oath.
}
}
else if (CheckHSequence(m))
{
@ -128,21 +132,22 @@ namespace Server.Spells.Necromancy
protected override void OnTick()
{
if (m_Caster.Deleted || m_Target.Deleted || !m_Caster.Alive || !m_Target.Alive ||
DateTime.UtcNow >= m_End) DoExpire();
DateTime.UtcNow >= m_End)
{
DoExpire();
}
}
public void DoExpire()
{
if (m_OathTable.ContainsKey(m_Caster))
if (m_OathTable.Remove(m_Caster))
{
m_Caster.SendLocalizedMessage(1061620); // Your Blood Oath has been broken.
m_OathTable.Remove(m_Caster);
}
if (m_OathTable.ContainsKey(m_Target))
if (m_OathTable.Remove(m_Target))
{
m_Target.SendLocalizedMessage(1061620); // Your Blood Oath has been broken.
m_OathTable.Remove(m_Target);
}
Stop();

View file

@ -57,7 +57,9 @@ namespace Server.Spells.Necromancy
var mod = new DefaultSkillMod(SkillName.MagicResist, false, 50.0);
if (m.Skills.MagicResist.Base > 50.0)
{
m.AddSkillMod(mod);
}
m_Table[m] = mod;
}
@ -81,10 +83,11 @@ namespace Server.Spells.Necromancy
public static bool TryEndEffect(Mobile m)
{
if (!m_Table.TryGetValue(m, out var mod))
if (!m_Table.Remove(m, out var mod))
{
return false;
}
m_Table.Remove(m);
mod?.Remove();
return true;

View file

@ -73,12 +73,13 @@ namespace Server.Spells.Necromancy
public static void ClearMindRotScalar(Mobile m)
{
if (!m_Table.TryGetValue(m, out var tmpB))
if (!m_Table.Remove(m, out var tmpB))
{
return;
}
BuffInfo.RemoveBuff(m, BuffIcon.Mindrot);
tmpB.m_MRExpireTimer.Stop();
m_Table.Remove(m);
m.SendLocalizedMessage(1060872); // Your mind feels normal again.
}

View file

@ -29,7 +29,9 @@ namespace Server.Spells.Necromancy
public void Target(Mobile m)
{
if (m == null)
{
return;
}
if (CheckHSequence(m))
{
@ -70,7 +72,10 @@ namespace Server.Spells.Necromancy
// Calculations for the buff bar
var spiritlevel = Caster.Skills.SpiritSpeak.Value / 10;
if (spiritlevel < 4)
{
spiritlevel = 4;
}
var d_MinDamage = 4;
var d_MaxDamage = ((int)spiritlevel + 1) * 3;
var args = $"{d_MinDamage}\t{d_MaxDamage}";
@ -113,13 +118,13 @@ namespace Server.Spells.Necromancy
public static bool RemoveCurse(Mobile m)
{
if (!m_Table.TryGetValue(m, out var timer))
if (!m_Table.Remove(m, out var timer))
{
return false;
}
timer.Stop();
m.SendLocalizedMessage(1061687); // You can breath normally again.
m_Table.Remove(m);
return true;
}
@ -153,7 +158,9 @@ namespace Server.Spells.Necromancy
m_Count = (int)spiritLevel;
if (m_Count < 4)
{
m_Count = 4;
}
m_MaxCount = m_Count;
}
@ -167,7 +174,9 @@ namespace Server.Spells.Necromancy
}
if (!m_Target.Alive || DateTime.UtcNow < m_NextHit)
{
return;
}
--m_Count;
@ -182,9 +191,13 @@ namespace Server.Spells.Necromancy
var delay = (int)Math.Ceiling((1.0 + 5 * m_Count) / m_MaxCount);
if (delay <= 5)
{
m_HitDelay = delay;
}
else
{
m_HitDelay = 5;
}
}
}
@ -203,16 +216,22 @@ namespace Server.Spells.Necromancy
damage *= 3 - (double)m_Target.Stam / m_Target.StamMax * 2;
if (damage < 1)
{
damage = 1;
}
if (!m_Target.Player)
{
damage *= 1.75;
}
AOS.Damage(m_Target, m_From, (int)damage, 0, 0, 0, 100, 0);
if (Utility.RandomDouble() >= 0.60
) // OSI: randomly revealed between first and third damage tick, guessing 60% chance
{
m_Target.RevealingAction();
}
}
}
}

View file

@ -20,7 +20,9 @@ namespace Server.Spells.Ninjitsu
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker) || !CheckMana(attacker, true))
{
return;
}
ClearCurrentMove(attacker);
@ -32,9 +34,13 @@ namespace Server.Spells.Ninjitsu
var isRanged = attacker.Weapon is BaseRanged;
if (ninjitsu < 100) // This formula is an approximation from OSI data. TODO: find correct formula
{
chance = 30 + (ninjitsu - 85) * 2.2;
}
else
{
chance = 63 + (ninjitsu - 100) * 1.1;
}
if (chance / 100 < Utility.RandomDouble())
{
@ -44,16 +50,16 @@ namespace Server.Spells.Ninjitsu
var damageBonus = 0;
if (m_Table.TryGetValue(defender, out var info))
if (m_Table.Remove(defender, out var info))
{
defender.SendLocalizedMessage(1063092); // Your opponent lands another Death Strike!
if (info.m_Steps > 0)
{
damageBonus = attacker.Skills.Ninjitsu.Fixed / 150;
}
info.m_Timer?.Stop();
m_Table.Remove(defender);
}
else
{
@ -78,13 +84,17 @@ namespace Server.Spells.Ninjitsu
public static void AddStep(Mobile m)
{
if (m_Table.TryGetValue(m, out var info) && ++info.m_Steps >= 5)
{
ProcessDeathStrike(m);
}
}
private static void ProcessDeathStrike(Mobile defender)
{
if (!m_Table.TryGetValue(defender, out var info))
if (!m_Table.Remove(defender, out var info))
{
return;
}
int damage;
@ -97,16 +107,24 @@ namespace Server.Spells.Ninjitsu
info.m_Attacker.Skills.Stealth.Value) / 220;
if (scalar > 1)
{
scalar = 1;
}
// New formula doesn't apply DamageBonus anymore, caps must be, directly, 60/30.
if (info.m_Steps >= 5)
{
damage = (int)Math.Floor(Math.Min(60, ninjitsu / 3 * (0.3 + 0.7 * scalar) + stalkingBonus));
}
else
{
damage = (int)Math.Floor(Math.Min(30, ninjitsu / 9 * (0.3 + 0.7 * scalar) + stalkingBonus));
}
if (info.m_isRanged)
{
damage /= 2;
}
}
else
{
@ -118,8 +136,11 @@ namespace Server.Spells.Ninjitsu
}
if (Core.ML)
{
info.m_Target.Damage(damage, info.m_Attacker); // Damage is direct.
}
else
{
AOS.Damage(
info.m_Target,
info.m_Attacker,
@ -136,10 +157,9 @@ namespace Server.Spells.Ninjitsu
false,
true
); // Damage is physical.
}
info.m_Timer?.Stop();
m_Table.Remove(info.m_Target);
}
private class DeathStrikeInfo

View file

@ -81,11 +81,10 @@ namespace Server.Spells.Ninjitsu
public override void OnClearMove(Mobile from)
{
if (!m_Table.TryGetValue(from, out var info))
return;
info.m_Timer.Stop();
m_Table.Remove(info.m_Mobile);
if (m_Table.Remove(from, out var info))
{
info.m_Timer.Stop();
}
}
public static double GetBonus(Mobile from)

View file

@ -53,11 +53,9 @@ namespace Server.Spells.Ninjitsu
attacker.RevealingAction();
if (m_Table.TryGetValue(defender, out var info))
if (m_Table.Remove(defender, out var info))
{
info.m_Timer?.Stop();
m_Table.Remove(defender);
}
var ninjitsu = attacker.Skills.Ninjitsu.Fixed;

View file

@ -29,7 +29,9 @@ namespace Server.Spells.Second
public override bool CheckCast()
{
if (Core.AOS)
{
return true;
}
if (Registry.ContainsKey(Caster))
{
@ -38,7 +40,9 @@ namespace Server.Spells.Second
}
if (Caster.CanBeginAction<DefensiveSpell>())
{
return true;
}
Caster.SendLocalizedMessage(1005385); // The spell will not adhere to you at this time.
return false;
@ -55,12 +59,11 @@ namespace Server.Spells.Second
* even after dying<EFBFBD>until you <EFBFBD>turn them off<EFBFBD> by casting them again.
*/
if (m_Table.TryGetValue(target, out var mods))
if (m_Table.Remove(target, out var mods))
{
target.PlaySound(0x1ED);
target.FixedParticles(0x375A, 9, 20, 5016, EffectLayer.Waist);
m_Table.Remove(target);
Registry.Remove(target);
target.RemoveResistanceMod(mods.Item1);
@ -100,10 +103,11 @@ namespace Server.Spells.Second
public static void EndProtection(Mobile m)
{
if (!m_Table.TryGetValue(m, out var mods))
if (!m_Table.Remove(m, out var mods))
{
return;
}
m_Table.Remove(m);
Registry.Remove(m);
m.RemoveResistanceMod(mods.Item1);
@ -117,7 +121,9 @@ namespace Server.Spells.Second
if (Core.AOS)
{
if (CheckSequence())
{
Toggle(Caster, Caster);
}
FinishSequence();
}

View file

@ -93,11 +93,10 @@ namespace Server.Spells.Sixth
public static void RemoveTimer(Mobile m)
{
if (!m_Table.TryGetValue(m, out var t))
return;
t.Stop();
m_Table.Remove(m);
if (m_Table.Remove(m, out var t))
{
t.Stop();
}
}
private class InternalTimer : Timer

View file

@ -27,7 +27,9 @@ namespace Server.Spells.Spellweaving
public void Target(Mobile m)
{
if (m == null)
{
return;
}
if (!Caster.CanSee(m))
{
@ -94,10 +96,10 @@ namespace Server.Spells.Spellweaving
public static bool StopEffect(Mobile m)
{
if (!m_Table.TryGetValue(m, out var info))
if (!m_Table.Remove(m, out var info))
{
return false;
m_Table.Remove(m);
}
info.m_Timer.Stop();
BuffInfo.RemoveBuff(m, BuffIcon.GiftOfRenewal);
@ -151,7 +153,9 @@ namespace Server.Spells.Spellweaving
}
if (m.Hits >= m.HitsMax)
{
return;
}
var toHeal = m_GiftInfo.m_HitsPerRound;

View file

@ -77,17 +77,20 @@ namespace Server.Spells.Spellweaving
private static void FinishEffect(DelayedEffectEntry effect)
{
if (m_WeaponDamageTable.TryGetValue(effect.m_Weapon, out var entry))
{
AOS.Damage(effect.m_Target, entry.m_Caster, entry.m_Damage, 0, 100, 0, 0, 0);
}
}
public static void StopImmolating(BaseWeapon weapon)
{
if (!m_WeaponDamageTable.TryGetValue(weapon, out var entry))
if (!m_WeaponDamageTable.Remove(weapon, out var entry))
{
return;
}
entry.m_Caster?.PlaySound(0x27);
entry.m_Timer.Stop();
m_WeaponDamageTable.Remove(weapon);
weapon.InvalidateProperties();
}

View file

@ -48,7 +48,9 @@ namespace Server.Spells.Spellweaving
{
if (Caster == m || !SpellHelper.ValidIndirectTarget(Caster, m) || !Caster.CanBeHarmful(m, false) ||
!Caster.InLOS(m))
{
continue;
}
Caster.DoHarmful(m);
@ -57,7 +59,9 @@ namespace Server.Spells.Spellweaving
SpellHelper.Damage(this, m, m.Player && Caster.Player ? pvpDamage : pvmDamage, 0, 0, 0, 0, 100);
if (oldSpell == null || oldSpell == m.Spell || CheckResisted(m))
{
continue;
}
m_Table[m] = Timer.DelayCall(duration, DoExpire, m);
@ -77,11 +81,12 @@ namespace Server.Spells.Spellweaving
public static void DoExpire(Mobile m)
{
if (!m_Table.TryGetValue(m, out var t))
if (!m_Table.Remove(m, out var t))
{
return;
}
t.Stop();
m_Table.Remove(m);
BuffInfo.RemoveBuff(m, BuffIcon.Thunderstorm);
}