public bool CalculateManaUsage(CastingPreCheckStatus castingPreCheckStatus, Spell spell, WorldObject target, bool isWeaponSpell, out uint manaUsed) { manaUsed = 0; if (castingPreCheckStatus == CastingPreCheckStatus.Success) { manaUsed = CalculateManaUsage(this, spell, target); } else if (castingPreCheckStatus == CastingPreCheckStatus.CastFailed) { manaUsed = 5; // todo: verify with retail } var currentMana = Mana.Current; if (isWeaponSpell) { var caster = GetEquippedWand(); currentMana = (uint)(caster.ItemCurMana ?? 0); } if (manaUsed > currentMana) { SendUseDoneEvent(WeenieError.YouDontHaveEnoughManaToCast); return(false); } Proficiency.OnSuccessUse(this, GetCreatureSkill(Skill.ManaConversion), spell.PowerMod); return(true); }
public void DoCastSpell_Inner(Spell spell, bool isWeaponSpell, uint manaUsed, WorldObject target, CastingPreCheckStatus castingPreCheckStatus) { // consume mana if (!isWeaponSpell) { UpdateVitalDelta(Mana, -(int)manaUsed); } else { var caster = GetEquippedWand(); // TODO: persist this from the beginning, since this is done with delay caster.ItemCurMana -= (int)manaUsed; } // consume spell components if (!isWeaponSpell) { TryBurnComponents(spell); } // check windup move distance cap var endPos = new Position(Location); var dist = StartPos.DistanceTo(endPos); bool movedTooFar = false; // only PKs affected by these caps? if (dist > Windup_MaxMove && PlayerKillerStatus != PlayerKillerStatus.NPK) { castingPreCheckStatus = CastingPreCheckStatus.CastFailed; movedTooFar = true; } var pk_error = CheckPKStatusVsTarget(this, target, spell); if (pk_error != null) { castingPreCheckStatus = CastingPreCheckStatus.InvalidPKStatus; } var useDone = WeenieError.None; switch (castingPreCheckStatus) { case CastingPreCheckStatus.Success: if ((spell.Flags & SpellFlags.FellowshipSpell) == 0) { CreatePlayerSpell(target, spell); } else { var fellows = GetFellowshipTargets(); foreach (var fellow in fellows) { CreatePlayerSpell(fellow, spell); } } // handle self procs if (spell.IsHarmful && target != this) { TryProcEquippedItems(this, true); } break; case CastingPreCheckStatus.InvalidPKStatus: if (spell.NumProjectiles > 0) { switch (spell.School) { case MagicSchool.WarMagic: WarMagic(target, spell); break; case MagicSchool.VoidMagic: VoidMagic(target, spell); break; case MagicSchool.LifeMagic: LifeMagic(spell, out uint damage, out bool critical, out var enchantmentStatus, target); break; } } break; default: useDone = WeenieError.YourSpellFizzled; EnqueueBroadcast(new GameMessageScript(Guid, PlayScript.Fizzle, 0.5f)); break; } if (pk_error != null && spell.NumProjectiles == 0) { Session.Network.EnqueueSend(new GameEventWeenieErrorWithString(Session, pk_error[0], target.Name)); if (target is Player targetPlayer) { targetPlayer.Session.Network.EnqueueSend(new GameEventWeenieErrorWithString(targetPlayer.Session, pk_error[1], Name)); } } if (movedTooFar) { //player.Session.Network.EnqueueSend(new GameEventWeenieError(player.Session, WeenieError.YouHaveMovedTooFar)); Session.Network.EnqueueSend(new GameMessageSystemChat("Your movement disrupted spell casting!", ChatMessageType.Magic)); } FinishCast(useDone); }
public void DoCastSpell(Spell spell, bool isWeaponSpell, uint magicSkill, uint manaUsed, WorldObject target, CastingPreCheckStatus castingPreCheckStatus) { //var actionChain = new ActionChain(); if (target != null) { // verify target still exists var targetCategory = GetTargetCategory(target.Guid.Full, spell.Id, out target); if (target == null) { FinishCast(WeenieError.TargetNotAcquired); return; } // do second rotate, if applicable // TODO: investigate this more, difference for GetAngle() between ACE and ac physics engine /*var angle = 0.0f; * if (target != this) * { * if (target.CurrentLandblock == null) * { * FindObject(target.Guid.Full, SearchLocations.Everywhere, out _, out var rootOwner, out _); * * if (rootOwner == null) * log.Error($"{Name}.DoCastSpell({spell.Name}, {isWeaponSpell}, {manaUsed}, {target.Name} ({target.Guid}), {castingPreCheckStatus}) - couldn't find rootTarget"); * * else if (rootOwner != this) * { * angle = GetAngle(rootOwner.Location); * target = rootOwner; * } * } * else * angle = GetAngle(target.Location); * } * * if (angle > MaxAngle) * { * var rotateTime = Rotate(target); * actionChain.AddDelaySeconds(rotateTime); * }*/ // verify spell range if (!VerifySpellRange(target, targetCategory, spell, magicSkill)) { FinishCast(WeenieError.None); return; } } //actionChain.AddAction(this, () => DoCastSpell_Inner(spell, isWeaponSpell, manaUsed, target, castingPreCheckStatus)); //actionChain.EnqueueChain(); DoCastSpell_Inner(spell, isWeaponSpell, manaUsed, target, castingPreCheckStatus); }