/// <summary> /// Checks caster's position. If they have moved too far from the initial casting position, the spell will be cancelled. /// </summary> /// <param name="stats">The user stats</param> private static void CheckMovement(UserStats stats) { if (stats.IsComplete) { return; } if (!GetIsObjectValid(stats.User)) { return; } var position = GetPosition(stats.User); // Player moved too far from starting position. Cancel the spell. if (Math.Abs(position.X - stats.CastingPosition.X) > 0.01f || Math.Abs(position.Y - stats.CastingPosition.Y) > 0.01f || Math.Abs(position.Z - stats.CastingPosition.Z) > 0.01f) { stats.IsCancelled = true; NWNXPlayer.StopGuiTimingBar(stats.User, string.Empty); SetIsBusy(stats.User, false); SendMessageToPC(stats.User, "You move and interrupt your concentration."); return; } DelayCommand(0.5f, () => CheckMovement(stats)); }
private static void CheckForSpellInterruption(NWCreature activator, string spellUUID, Vector position) { if (activator.GetLocalInt(spellUUID) == (int)SpellStatusType.Completed) { return; } Vector currentPosition = activator.Position; if (currentPosition.X != position.X || currentPosition.Y != position.Y || currentPosition.Z != position.Z) { var effect = activator.Effects.SingleOrDefault(x => _.GetEffectTag(x) == "ACTIVATION_VFX"); if (effect != null) { _.RemoveEffect(activator, effect); } NWNXPlayer.StopGuiTimingBar(activator, "", -1); activator.IsBusy = false; activator.SetLocalInt(spellUUID, (int)SpellStatusType.Interrupted); activator.SendMessage("Your ability has been interrupted."); return; } _.DelayCommand(0.5f, () => { CheckForSpellInterruption(activator, spellUUID, position); }); }