ServUO Version
Publish 57
Ultima Expansion
Endless Journey
Why can't I use range magic like MeteorSwarm when single target magic is performed without any problems during AIMage monsters or NPC battles? I added range magic to AIMage, but monsters or NPCs can't use magic. Do I need to add a separate command that I can write?
 
post your changes to find out where the problem is.
public virtual Spell GetRandomDamageSpell()
{
int select;

if (SmartAI)
{
if (m_Mobile.Mana > 100)
{
if (!SkillMasterySpell.HasSpell(m_Mobile, typeof(DeathRaySpell)))
select = Utility.RandomMinMax(0, 4);
else
select = Utility.RandomMinMax(1, 4);
}
else if (CheckCanCastMagery(7))
{
select = Utility.Random(5, 11);
}
else
{
select = Utility.Random(5, 8);
}

switch (select)
{
case 0:
return new DeathRaySpell(m_Mobile, null);
case 1:
return new MindBlastSpell(m_Mobile, null);
case 2:
return new EnergyBoltSpell(m_Mobile, null);
case 3:
return new ExplosionSpell(m_Mobile, null);
case 4:
return new FlameStrikeSpell(m_Mobile, null);
case 5:
return new MeteorSwarmSpell(m_Mobile, null);
case 6:
return new HarmSpell(m_Mobile, null);
case 7:
return new FireballSpell(m_Mobile, null);
case 8:
return new LightningSpell(m_Mobile, null);



}
}
else
{
if (CheckCanCastMagery(8))
select = 8;
else if (CheckCanCastMagery(6))
select = 6;
else if (CheckCanCastMagery(5))
select = 5;
else if (CheckCanCastMagery(4))
select = 4;
else if (CheckCanCastMagery(3))
select = 3;
else if (CheckCanCastMagery(2))
select = 2;
else
select = 1;

switch (Utility.Random(select))
{
default:
case 0:
return new MeteorSwarmSpell(m_Mobile, null);
case 1:
return new HarmSpell(m_Mobile, null);
case 2:
return new FireballSpell(m_Mobile, null);
case 3:
return new LightningSpell(m_Mobile, null);
case 4:
return new MindBlastSpell(m_Mobile, null);
case 5:
return new EnergyBoltSpell(m_Mobile, null);
case 6:
return new ExplosionSpell(m_Mobile, null);
case 7:
return new FlameStrikeSpell(m_Mobile, null);
}
}

return null;
}
using System;
using System.Collections.Generic;
using System.Linq;

using Server.Targeting;
using Server.Mobiles;
using Server.Items;

namespace Server.Spells.Seventh
{
public class MeteorSwarmSpell : MagerySpell
{
public override DamageType SpellDamageType { get { return DamageType.SpellAOE; } }
public Item Item { get; set; }

private static readonly SpellInfo m_Info = new SpellInfo(
"Meteor Swarm", "Flam Kal Des Ylem",
233,
9042,
false,
Reagent.Bloodmoss,
Reagent.MandrakeRoot,
Reagent.SulfurousAsh,
Reagent.SpidersSilk);

public MeteorSwarmSpell(Mobile caster, Item scroll, Item item)
: base(caster, scroll, m_Info)
{
Item = item;
}

public MeteorSwarmSpell(Mobile caster, Item scroll)
: base(caster, scroll, m_Info)
{
}

public override int GetMana()
{
if (Item != null)
return 0;

return base.GetMana();
}

public override SpellCircle Circle
{
get
{
return SpellCircle.Seventh;
}
}
public override double RequiredSkill
{
get
{
return 95.0;
}
}
public override bool DelayedDamage
{
get
{
return true;
}
}
public override void OnCast()
{
Caster.Target = new InternalTarget(this, Item);
}

public void Target(IPoint3D p, Item item)
{
if (!Caster.CanSee(p))
{
Caster.SendLocalizedMessage(500237); // Target can not be seen.
}
else if (SpellHelper.CheckTown(p, Caster) && (item != null || CheckSequence()))
{
if (item != null)
{
if (item is MaskOfKhalAnkur)
{
((MaskOfKhalAnkur)item).Charges--;
}

if (item is PendantOfKhalAnkur)
{
((PendantOfKhalAnkur)item).Charges--;
}
}

SpellHelper.Turn(Caster, p);

if (p is Item)
p = ((Item)p).GetWorldLocation();

var targets = AcquireIndirectTargets(p, 2).ToList();
var count = Math.Max(1, targets.Count);

if (count > 0)
{
Effects.PlaySound(p, Caster.Map, 0x160);
}

foreach (var id in targets)
{
Mobile m = id as Mobile;
double damage;

if (Core.AOS)
damage = GetNewAosDamage(51, 1, 5, id is PlayerMobile, id);
else
damage = Utility.Random(27, 22);

if (Core.AOS && count > 2)
damage = (damage * 2) / count;
else if (!Core.AOS)
damage /= count;

if (!Core.AOS && m != null && CheckResisted(m))
{
damage *= 0.5;

m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy.
}

IDamageable source = Caster;
IDamageable target = id;

if (SpellHelper.CheckReflect((int)Circle, ref source, ref target, SpellDamageType))
{
Timer.DelayCall(TimeSpan.FromSeconds(.5), () =>
{
source.MovingParticles(target, item != null ? 0xA1ED : 0x36D4, 7, 0, false, true, 9501, 1, 0, 0x100);
});
}

if (m != null)
{
damage *= GetDamageScalar(m);
}

Caster.DoHarmful(id);
SpellHelper.Damage(this, target, damage, 0, 100, 0, 0, 0);

Caster.MovingParticles(id, item != null ? 0xA1ED : 0x36D4, 7, 0, false, true, 9501, 1, 0, 0x100);
}

ColUtility.Free(targets);
}

FinishSequence();
}

private class InternalTarget : Target
{
private readonly MeteorSwarmSpell m_Owner;
private readonly Item m_Item;

public InternalTarget(MeteorSwarmSpell owner, Item item)
: base(Core.ML ? 10 : 12, true, TargetFlags.None)
{
m_Owner = owner;
m_Item = item;
}

protected override void OnTarget(Mobile from, object o)
{
IPoint3D p = o as IPoint3D;

if (p != null)
m_Owner.Target(p, m_Item);
}

protected override void OnTargetFinish(Mobile from)
{
m_Owner.FinishSequence();
}
}
}
}
Thank you for your answer.
This is my MageAI.cs&MeteorSwarmSpell.cs
If you put MeteorSwarmSpell in case0 and select MageAI for monsters, you'll use all the other single magic, but MeteorSwarmSpell won't just use magic. The Magery skill has been adjusted to 100 and all the requirements are met, but monsters and npc don't just use MeteorSwarmSpell magic
 
Last edited:
You need to define MeteorSwarmSpell in the ProcessTarget method coz now AI gets this target but doesn't know how to use this. Examples of defines spells you can find in ProcessTarget() method.
Or just try to set MeteorSwarmSpell target flag like Harmful and it should work by default like others spell.
Be sure that you're testing not in guard zone, coz mass spells don't work in such type of areas.


C#:
                switch (Utility.Random(select))
                {
                    default:
                    case 0:
                        return new MeteorSwarmSpell(m_Mobile, null);
also in your example you've put the MeteorSwarmSpell in zero case what looks like never cast this spell coz "select" value can be 1 only if you have low skills or low amount of mana, what will be not enought to start casting MeteorSwarmSpell. Try to put this in higher cases which will match conditions.
 
You need to define MeteorSwarmSpell in the ProcessTarget method coz now AI gets this target but doesn't know how to use this. Examples of defines spells you can find in ProcessTarget() method.
Or just try to set MeteorSwarmSpell target flag like Harmful and it should work by default like others spell.
Be sure that you're testing not in guard zone, coz mass spells don't work in such type of areas.


C#:
                switch (Utility.Random(select))
                {
                    default:
                    case 0:
                        return new MeteorSwarmSpell(m_Mobile, null);
also in your example you've put the MeteorSwarmSpell in zero case what looks like never cast this spell coz "select" value can be 1 only if you have low skills or low amount of mana, what will be not enought to start casting MeteorSwarmSpell. Try to put this in higher cases which will match conditions.
protected virtual bool ProcessTarget()
{
var targ = m_Mobile.Target;

if (targ == null)
return false;

var harmful = (targ.Flags & TargetFlags.Harmful) != 0 || targ is MeteorSwarmSpell.InternalTarget ||
targ is WildfireSpell.InternalTarget;
var beneficial = (targ.Flags & TargetFlags.Beneficial) != 0 || targ is ArchCureSpell.InternalTarget;

if (UsesMagery)
{
var isDispel = (targ is DispelSpell.InternalTarget || targ is MassDispelSpell.InternalTarget);
var isParalyze = (targ is ParalyzeSpell.InternalTarget);
var isTeleport = (targ is TeleportSpell.InternalTarget);
var isSummon = (targ is EnergyVortexSpell.InternalTarget || targ is BladeSpiritsSpell.InternalTarget ||
targ is NatureFurySpell.InternalTarget);
var isField = (targ is FireFieldSpell.InternalTarget || targ is PoisonFieldSpell.InternalTarget ||
targ is ParalyzeFieldSpell.InternalTarget);
var isAnimate = (targ is AnimateDeadSpell.InternalTarget);
var isDispelField = (targ is DispelFieldSpell.InternalTarget);
var teleportAway = false;

if (isTeleport && m_Mobile.CanSwim)
targ.Cancel(m_Mobile, TargetCancelType.Canceled);

IDamageable toTarget = null;
Thank you for your reply. Added MeteorSwarmSpell to ProcessTarget().
Errors:
+ Mobiles/AI/Magical AI/MageAI.cs:
CS0122: Line 1261: 'MeteorSwarmSpell.InternalTarget' is inaccessible due to its protection level
Scripts: One or more scripts failed to compile or no script files were found.
- Press return to exit, or R to try again.
However, the following error appears during compilation. Could you tell me what the problem is?
 
Thank you for your reply. Added MeteorSwarmSpell to ProcessTarget().

However, the following error appears during compilation. Could you tell me what the problem is?
It has to do with the access modifier for the class. You cannot call private methods/classes outside of the class body.
Change the private modifier to public in MeteorSwarmSpell.cs for the InternalTarget class:
C#:
public class InternalTarget : Target
 
클래스의 액세스 한정자와 관련이 있습니다. 클래스 본문 외부에서 개인 메서드/클래스를 호출할 수 없습니다.
InternalTarget 클래스에 대해 MeteorSwarmSpell.cs에서 private 한정자를 public으로 변경합니다.
C#:
공개 클래스 InternalTarget: 대상
Wow! It works perfectly! Thank you.
 
Last edited:
Back