Hello! I have a question. The magic of this script has its own animation. For example, 0x36D4 animation works when trying firebolt. Can I set this up individually? For example, I was wondering if it's possible to have such an individual setup where a monster fires 0x36D4 and b monster fires 0x3709.
 
Massapequa may have that answer. I just got it compiling error free and will be doing some tweaking and testing over the next few days. I do like what you are suggesting. Lets see if we can get that working as well.

Cheers
 
Okay Massapequa I finally got this project compiling.

So . . for anyone else having trouble getting Linq to work on their server . . I hope this helps.

I have a UO shard running with RunUO V2.2 and until now have been unable to compile and use scripts that need ' using System.Linq; '

I discovered that Ling is included (or supported) with the latest .NET Framework but in order for your UO scripts to be able to access it you need to check the contents of your "Assemblies.cfg" file which is usually found in the \Data folder. Find that file and make sure to add System.Core.dll

This is what my Assemblies.cfg" file now looks like:

System.dll
System.Web.dll
System.Xml.dll
System.Data.dll
System.Drawing.dll
System.Windows.Forms.dll
System.Core.dll
Ultima.dll

After adding 'System.Core.dll' to my "Assemblies.cfg" file, my compiling problem with files 'using System.Linq;' was solved. My server now compiles with no errors in-spite of some .cs files referring to Linq.

Cheers

Awesome! I'm happy to hear you got the script working!

Another option I was going to suggest was changing 'using System.Linq;' to 'import System.Linq from System.Core;'

it's a very handy thing to have, but there are always work arounds:
Like, CustomAbilitiesAny() would be the same as:
Code:
if( CustomAbilities.Length != 0 )
Or .ToList() could be written as:
Code:
var list = new List<CustomAbility>();

foreach( var a in CustomAbilities)
{
    if( a != ability)
    List.Add(a);
}

This was a bit of a learning experience for me too.

I'm excited it worked out in the end and I hope you enjoy!
Hello! I have a question. The magic of this script has its own animation. For example, 0x36D4 animation works when trying firebolt. Can I set this up individually? For example, I was wondering if it's possible to have such an individual setup where a monster fires 0x36D4 and b monster fires 0x3709.
Hey!
That is actually how the ability Barrage of Bolts is set up, but unfortunately firebolt is not set up like that.
You could add it with something like:
Code:
private int m_ID = 0x36D4;

public int ID
{
    get { return m_ID; }
    set { m_ID = value; }
}

then, in the line where it says 'creature.MovingEffect', change the 0x36D4 to m_ID.

After that, you should be able to set up each individual mob with its own unique projectile animation. (with the default being 0x36D4)
 
Last edited:
Awesome! I'm happy to hear you got the script working!

Another option I was going to suggest was changing 'using System.Linq;' to 'import System.Linq from System.Core;'

it's a very handy thing to have, but there are always work arounds:
Like, CustomAbilitiesAny() would be the same as:
Code:
if( CustomAbilities.Length != 0 )
Or .ToList() could be written as:
Code:
var list = new List<CustomAbility>();

foreach( var a in CustomAbilities)
{
    if( a != ability)
    List.Add(a);
}

This was a bit of a learning experience for me too.

I'm excited it worked out in the end and I hope you enjoy!

Hey!
That is actually how the ability Barrage of Bolts is set up, but unfortunately firebolt is not set up like that.
You could add it with something like:
Code:
private int m_ID = 0x36D4;

public int ID
{
    get { return m_ID; }
    set { m_ID = value; }
}

then, in the line where it says 'creature.MovingEffect', change the 0x36D4 to m_ID.

After that, you should be able to set up each individual mob with its own unique projectile animation. (with the default being 0x36D4)
As expected, you are amazing! Thank you from the bottom of my heart for always helping me!
 
using Server.Items;
using Server.Mobiles;
using Server.Targeting;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace Server.Mobiles
{
public class BrigandOccultist : BaseCreature
{

CustomAbilityList list;
WalkingBomb wb = new WalkingBomb();
ToxicRain tr = new ToxicRain();
HealAllies ha = new HealAllies();

private bool HasSummon = false;
private PatchworkSkeleton summon;

public override bool ClickTitle => false;
public override bool ShowFameTitle => false;

[Constructable]
public BrigandOccultist()
: base(AIType.AI_Necro, FightMode.Closest, 10, 1, 0.2, 0.4)
{
SpeechHue = Utility.RandomDyedHue();
Title = "the brigand occultist";
Hue = Utility.RandomSkinHue();
int clothes = Utility.RandomNeutralHue();

if (Female = Utility.RandomBool())
{
Body = 0x191;
Name = NameList.RandomName("female");
AddItem(new Skirt(clothes));
}
else
{
Body = 0x190;
Name = NameList.RandomName("male");
AddItem(new ShortPants(clothes));
}

SetStr(86, 100);
SetDex(151, 165);
SetInt(361, 475);

SetDamage(4, 6);

SetDamageType(ResistanceType.Physical, 100);

SetResistance(ResistanceType.Physical, 35, 45);
SetResistance(ResistanceType.Fire, 25, 30);
SetResistance(ResistanceType.Cold, 25, 30);
SetResistance(ResistanceType.Poison, 10, 20);
SetResistance(ResistanceType.Energy, 10, 20);

//SetSkill(SkillName.EvalInt, 75.0, 95.5);
SetSkill(SkillName.Meditation, 75.0, 95.5);
SetSkill(SkillName.MagicResist, 73.5, 89.5);
SetSkill(SkillName.Wrestling, 100.0);
SetSkill(SkillName.Tactics, 100.0);
//SetSkill(SkillName.Magery, 95.0, 115.0);
SetSkill(SkillName.Necromancy, 65.0, 89.0);
SetSkill(SkillName.SpiritSpeak, 65.0, 89.0);

Fame = 3000;
Karma = -3000;

AddItem(new Boots());
AddItem(new FancyShirt());
AddItem(new Doublet(clothes));
AddItem(new NecromancerSpellbook());
AddItem(new WizardsHat(clothes));

Utility.AssignRandomHair(this);
}

public BrigandOccultist(Serial serial)
: base(serial)
{
}

public override bool AlwaysMurderer => true;
public override bool AlwaysAttackable => true;

public override void GenerateLoot()
{
AddLoot(LootPack.Rich);
AddLoot(LootPack.MedScrolls, 3);
AddLoot(LootPack.HighScrolls, 1);
}

public override void OnThink()
{
base.OnThink();

if(list == null)
{
list = new CustomAbilityList();
wb.SetDamage(15, 30);
tr.SetDamage(12, 18);

list.Add(tr);
list.Add(wb);
list.Add(ha);
}
else
list.CheckTrigger(this);

CheckSummon();

}

public virtual bool IsFriend(Mobile m)
{
if(m is BrigandPillager || m is Brigand || m is BrigandCutthroat )
return true;
else
return base.IsFriend(m);
}

public void CheckSummon()
{
if( !Alive || Combatant == null || Map == null || Map == Map.Internal)
{
if( HasSummon == true)
{
summon.Delete();
HasSummon = false;
}
else
return;
}
else if( HasSummon == false && Combatant != null)
{
HasSummon = true;
this.Animate(AnimationType.Spell, 0);

Point3D p = Map.GetSpawnPosition(Location, 6);
Effects.SendLocationParticles(EffectItem.Create(p, Map, TimeSpan.FromSeconds(2)), 0x3789, 1, 40, 0x3F, 3, 9907, 0);

Timer.DelayCall(TimeSpan.FromSeconds(2), () =>
{
summon = new PatchworkSkeleton();
summon.MoveToWorld(p, Map);
summon.Team = Team;
summon.Combatant = Combatant;
});

}
}

public override bool OnBeforeDeath()
{
if( summon != null || !summon.Deleted)
summon.Kill();

return base.OnBeforeDeath();
}


public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);

writer.Write(0); // version
}

public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);

int version = reader.ReadInt();
}
}
}
Thank you! I have one more question. There is a monster called "BrigandOccultist" in the file you uploaded. This monster has the ability to summon monsters, but when it's alone, it's easy to summon them without any problems. But if you use the summoning technique when there are two identical monsters, the server reboots. I want to apply this summoning technique to several monsters, is there a way?
 
Thank you! I have one more question. There is a monster called "BrigandOccultist" in the file you uploaded. This monster has the ability to summon monsters, but when it's alone, it's easy to summon them without any problems. But if you use the summoning technique when there are two identical monsters, the server reboots. I want to apply this summoning technique to several monsters, is there a way?
Is the Occultist causing the reboot, or is it a mob you're trying to apply the summoning ability to?
Is there a Crash Log you can post?
 
Is the Occultist causing the reboot, or is it a mob you're trying to apply the summoning ability to?
Is there a Crash Log you can post?
ServUO Version 0.5, Build 8700.38495
Operating System: Microsoft Windows NT 6.2.9200.0
.NET Framework: 4.0.30319.42000
Time: 2023-10-27 Afternoon 12:23:56
Mobiles: 38747
Items: 206783
Exception:
System.NullReferenceException: Object reference is not set as an instance of the object.
Location: Server.Mobiles.BrigandOccultist.CheckSummon()
Location: Server.Mobiles.BaseAI.AITimer.OnTick()
Location: Server.Timer.Slice()
Location: Server.Core.Main(String[] args)
This is my crash log.The summoning capability reboots the moment the summoning is completed.
 
This is my crash log.The summoning capability reboots the moment the summoning is completed.
Alright so it's trying to reference an object that isn't there for whatever reason.
It might be these lines here:
Code:
        if( HasSummon == true)
        {
            summon.Delete();
            HasSummon = false;
        }
try changing that first line to:
Code:
        if( HasSummon == true && summon != null)

Also, it could be:
Code:
                    summon.Combatant = Combatant;
change it to:
Code:
if (Combatant != null)
             summon.Combatant = Combatant;
Keep me updated and if it continues then I'll keep looking for potential issues.

Is it happening when you have multiple BrigandOccultists spawned? Or is there something else happening at the same time?
 
Last edited:
Alright so it's trying to reference an object that isn't there for whatever reason.
It might be these lines here:
Code:
        if( HasSummon == true)
        {
            summon.Delete();
            HasSummon = false;
        }
try changing that first line to:
Code:
        if( HasSummon == true && summon != null)

Also, it could be:
Code:
                    summon.Combatant = Combatant;
change it to:
Code:
if (Combatant != null)
             summon.Combatant = Combatant;
Keep me updated and if it continues then I'll keep looking for potential issues.

Is it happening when you have multiple BrigandOccultists spawned? Or is there something else happening at the same time?
oh! Thanks!
if( HasSummon == true && summon != null)
I changed it to the script above and it was resolved. My problem was that after creating several "BrigandOccultist" monsters, the "BrigandOccultist" was rebooted when I tried to summon them. But there is one more problem. When "BrigandOccultist" summons a monster, it disappears after a while. Is there a solution to this?



We've solved the phenomenon of the monster disappearing. It was my mistake. Thank you from the bottom of my heart for your help!!
 
Last edited:
I have spent the past couple of days working with these scripts . . . amazing system for us.

I did run into a few 'hiccups' but they were the result of us being a RunUO setup and having our own custom .MULs

That said, there is one script I can't get performing the way I believe it was intended to.

The script in question (atm) is the IceImp.cs script. It compiles with no errors but when spawned in game the IceImp creature preforms none of the custom effects.

Here is the IceImp.cs script:
Code:
using Server.Items;
using System;

namespace Server.Mobiles
{
    [CorpseName("an ice imp corpse")]
    public class IceImp : BaseCreature
    {

    Firebolt fb = new Firebolt();
    FlameStrikeTargeted fst = new FlameStrikeTargeted();
    IcePrison ip = new IcePrison();
    FlameStrikeAoe fsa = new FlameStrikeAoe();
    CustomAbilityList list = new CustomAbilityList();

        [Constructable]
        public IceImp()
            : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4)
        {
            Name = "an ice imp";
            Body = 74;
        Hue = 1165; //Utility.RandomMinMax(1150,1154);
            BaseSoundID = 422;

            SetStr(91, 115);
            SetDex(61, 80);
            SetInt(86, 105);

            SetHits(55, 70);

            SetDamage(10, 14);

            SetDamageType(ResistanceType.Physical, 50);
            SetDamageType(ResistanceType.Cold, 50);

            SetResistance(ResistanceType.Physical, 25, 35);
            SetResistance(ResistanceType.Fire, 40, 50);
            SetResistance(ResistanceType.Cold, 20, 30);
            SetResistance(ResistanceType.Poison, 30, 40);
            SetResistance(ResistanceType.Energy, 30, 40);

            SetSkill(SkillName.EvalInt, 20.1, 30.0);
            SetSkill(SkillName.Magery, 90.1, 100.0);
            SetSkill(SkillName.MagicResist, 30.1, 50.0);
            SetSkill(SkillName.Tactics, 42.1, 50.0);
            SetSkill(SkillName.Wrestling, 40.1, 44.0);
            SetSkill(SkillName.Necromancy, 20);
            SetSkill(SkillName.SpiritSpeak, 20);

            Fame = 2500;
            Karma = -2500;
            switch (Utility.Random(104))
            {
                case 0: PackItem(new BloodOathScroll()); break;
                case 1: PackItem(new CorpseSkinScroll()); break;
                case 2: PackItem(new CurseWeaponScroll()); break;
                case 3: PackItem(new EvilOmenScroll()); break;
                case 4: PackItem(new HorrificBeastScroll()); break;
                case 5: PackItem(new LichFormScroll()); break;
                case 6: PackItem(new MindRotScroll()); break;
                case 7: PackItem(new PainSpikeScroll()); break;
                case 8: PackItem(new PoisonStrikeScroll()); break;
                case 9: PackItem(new StrangleScroll()); break;
                case 10: PackItem(new SummonFamiliarScroll()); break;
                case 11: PackItem(new WitherScroll()); break;
                case 12: PackItem(new WraithFormScroll()); break;
            }

            Tamable = true;
            ControlSlots = 2;
            MinTameSkill = 83.1;

            SetSpecialAbility(SpecialAbility.Heal);
    
        }

        public IceImp(Serial serial)
            : base(serial)
        {
        }

        public override int Meat => 1;
        public override int Hides => 6;
        public override HideType HideType => HideType.Spined;
        public override FoodType FavoriteFood => FoodType.Meat;
        public override PackInstinct PackInstinct => PackInstinct.Daemon;
        public override bool CanFly => true;
        public override void GenerateLoot()
        {
            AddLoot(LootPack.Meager);
            AddLoot(LootPack.MedScrolls );
        }


        public override void OnThink()
        {
            base.OnThink();


        if( list == null)
        {
            fst.Type = FlameStrikeTargeted.StrikeType.Ice;
            fb.Type = Firebolt.BoltType.Ice;
            fb.SetDamage(10, 14);
            fst.SetDamage(18, 21);
            list.Add(fst);
            list.Add(fb);
            list.Add(ip);
            //flameStrikeAoe is not added to the list b/c it's only used on death in this case.
        }
        else
            list.CheckTrigger(this);


        }

        public override bool OnBeforeDeath()
        {
        fsa.Type = FlameStrikeAoe.StrikeType.Ice;
        fsa.Range = 2;
        fsa.DoEffects(this, this, 0, 0);

            return base.OnBeforeDeath();
        }

        public override void Serialize(GenericWriter writer)
        {
            base.Serialize(writer);
            writer.Write(0);
        }

        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);
            int version = reader.ReadInt();
        }
    }
}

I am at a loss as to why this one creature does nothing when all the others seem to work fine.

Obviously I am missing something but . . . sorry I am dead ending on it. Can you see why this one would not work?

Many Thanks
 
I have spent the past couple of days working with these scripts . . . amazing system for us.

I did run into a few 'hiccups' but they were the result of us being a RunUO setup and having our own custom .MULs

That said, there is one script I can't get performing the way I believe it was intended to.

The script in question (atm) is the IceImp.cs script. It compiles with no errors but when spawned in game the IceImp creature preforms none of the custom effects.

Here is the IceImp.cs script:
Code:
using Server.Items;
using System;

namespace Server.Mobiles
{
    [CorpseName("an ice imp corpse")]
    public class IceImp : BaseCreature
    {

    Firebolt fb = new Firebolt();
    FlameStrikeTargeted fst = new FlameStrikeTargeted();
    IcePrison ip = new IcePrison();
    FlameStrikeAoe fsa = new FlameStrikeAoe();
    CustomAbilityList list = new CustomAbilityList();

        [Constructable]
        public IceImp()
            : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4)
        {
            Name = "an ice imp";
            Body = 74;
        Hue = 1165; //Utility.RandomMinMax(1150,1154);
            BaseSoundID = 422;

            SetStr(91, 115);
            SetDex(61, 80);
            SetInt(86, 105);

            SetHits(55, 70);

            SetDamage(10, 14);

            SetDamageType(ResistanceType.Physical, 50);
            SetDamageType(ResistanceType.Cold, 50);

            SetResistance(ResistanceType.Physical, 25, 35);
            SetResistance(ResistanceType.Fire, 40, 50);
            SetResistance(ResistanceType.Cold, 20, 30);
            SetResistance(ResistanceType.Poison, 30, 40);
            SetResistance(ResistanceType.Energy, 30, 40);

            SetSkill(SkillName.EvalInt, 20.1, 30.0);
            SetSkill(SkillName.Magery, 90.1, 100.0);
            SetSkill(SkillName.MagicResist, 30.1, 50.0);
            SetSkill(SkillName.Tactics, 42.1, 50.0);
            SetSkill(SkillName.Wrestling, 40.1, 44.0);
            SetSkill(SkillName.Necromancy, 20);
            SetSkill(SkillName.SpiritSpeak, 20);

            Fame = 2500;
            Karma = -2500;
            switch (Utility.Random(104))
            {
                case 0: PackItem(new BloodOathScroll()); break;
                case 1: PackItem(new CorpseSkinScroll()); break;
                case 2: PackItem(new CurseWeaponScroll()); break;
                case 3: PackItem(new EvilOmenScroll()); break;
                case 4: PackItem(new HorrificBeastScroll()); break;
                case 5: PackItem(new LichFormScroll()); break;
                case 6: PackItem(new MindRotScroll()); break;
                case 7: PackItem(new PainSpikeScroll()); break;
                case 8: PackItem(new PoisonStrikeScroll()); break;
                case 9: PackItem(new StrangleScroll()); break;
                case 10: PackItem(new SummonFamiliarScroll()); break;
                case 11: PackItem(new WitherScroll()); break;
                case 12: PackItem(new WraithFormScroll()); break;
            }

            Tamable = true;
            ControlSlots = 2;
            MinTameSkill = 83.1;

            SetSpecialAbility(SpecialAbility.Heal);
  
        }

        public IceImp(Serial serial)
            : base(serial)
        {
        }

        public override int Meat => 1;
        public override int Hides => 6;
        public override HideType HideType => HideType.Spined;
        public override FoodType FavoriteFood => FoodType.Meat;
        public override PackInstinct PackInstinct => PackInstinct.Daemon;
        public override bool CanFly => true;
        public override void GenerateLoot()
        {
            AddLoot(LootPack.Meager);
            AddLoot(LootPack.MedScrolls );
        }


        public override void OnThink()
        {
            base.OnThink();


        if( list == null)
        {
            fst.Type = FlameStrikeTargeted.StrikeType.Ice;
            fb.Type = Firebolt.BoltType.Ice;
            fb.SetDamage(10, 14);
            fst.SetDamage(18, 21);
            list.Add(fst);
            list.Add(fb);
            list.Add(ip);
            //flameStrikeAoe is not added to the list b/c it's only used on death in this case.
        }
        else
            list.CheckTrigger(this);


        }

        public override bool OnBeforeDeath()
        {
        fsa.Type = FlameStrikeAoe.StrikeType.Ice;
        fsa.Range = 2;
        fsa.DoEffects(this, this, 0, 0);

            return base.OnBeforeDeath();
        }

        public override void Serialize(GenericWriter writer)
        {
            base.Serialize(writer);
            writer.Write(0);
        }

        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);
            int version = reader.ReadInt();
        }
    }
}

I am at a loss as to why this one creature does nothing when all the others seem to work fine.

Obviously I am missing something but . . . sorry I am dead ending on it. Can you see why this one would not work?

Many Thanks
Oh wow this was a big oversight on my part.
find the line:
Code:
CustomAbilityList list = new CustomAbilityList();
and make it:
Code:
CustomAbilityList list;


Then go down to the OnThink Method where it says:
Code:
        if( list == null)
        {
            fst.Type = FlameStrikeTargeted.StrikeType.Ice;
            fb.Type = Firebolt.BoltType.Ice;
            fb.SetDamage(10, 14);
            fst.SetDamage(18, 21);
            list.Add(fst);
            list.Add(fb);
            list.Add(ip);
            //flameStrikeAoe is not added to the list b/c it's only used on death in this case.
        }
        else
            list.CheckTrigger(this);
And add a line so it looks like:
Code:
        if( list == null)
        {
            list = new CustomAbilityList();
            fst.Type = FlameStrikeTargeted.StrikeType.Ice;
            fb.Type = Firebolt.BoltType.Ice;
            fb.SetDamage(10, 14);
            fst.SetDamage(18, 21);
            list.Add(fst);
            list.Add(fb);
            list.Add(ip);
            //flameStrikeAoe is not added to the list b/c it's only used on death in this case.
        }
        else
            list.CheckTrigger(this);

I believe it's correct on the other Imps. You can look at those for reference too.
Thanks for letting me know about that
 
Thank you Massapaqua. That was the fix needed. I just need to play around with the power and damages now to fit our shard and some quests I have in mind for the creatures involved. As mentioned before . . I intend recognizing you (and the 'historic' Massapaqua people) when this great contribution of yours is introduced to our players. Cheers!
 
Last edited:
fififi.jpg
I'm sorry. I showed up with another question for you. There is a technology called "FlameStrikeLine". I want to make sure that when monsters use this technology, for example, a monster using this technology can send a message saying "a specific monster takes a deep breath" and launch 3 seconds later. I'm asking for help if it's possible. And the "FlameStrikeLine" technology fires straight. I wonder if it is possible to launch in three directions like the picture above.I'm sorry to keep bothering you...
 
Last edited:
View attachment 22492
I'm sorry. I showed up with another question for you. There is a technology called "FlameStrikeLine". I want to make sure that when monsters use this technology, for example, a monster using this technology can send a message saying "a specific monster takes a deep breath" and launch 3 seconds later. I'm asking for help if it's possible. And the "FlameStrikeLine" technology fires straight. I wonder if it is possible to launch in three directions like the picture above.I'm sorry to keep bothering you...
Okay, I managed to create a new ability that does exactly as you asked.
You customize the wait time and the message.
you can just copy this code and place it in a separate file in your custom folder:
Code:
using System;
using Server;using System.Collections.Generic;
using System.Linq;
using Server.Items;
using Server.Network;
using System.Collections;
using Server.Spells;

namespace Server.Mobiles
{
    public class ForkedFlameStrike : CustomAbility
    {
        public override double TriggerChance { get { return 0.8; } }
            public override int MaxRange { get { return 8; } }
            public override TimeSpan CooldownDuration { get { return TimeSpan.FromSeconds(10); } }

        public enum StrikeType
        {
        Fire,
        Ice,
        Poison,
        Energy,
        Water,
        Steam,
        Necrotic,
        Holy
        }

        private StrikeType m_Type = StrikeType.Fire;
        private int hue, rm, phy, fir, col, poi, ene;

        private int m_Range = 5;

        public StrikeType Type
        {
        get { return m_Type; }
        set { m_Type = value; }
        }

        public int Range
        {
        get { return m_Range; }
        set { m_Range = value; }
        }

        public ForkedFlameStrike()
        {
        }

        private int m_Wait = 3;
        private int Wait
        {
        get { return m_Wait; }
        set { m_Wait = value; }
        }

        private string m_Message = "*The creature is preparing to use its fire breath.*";

        public string Message
        {
        get { return m_Message; }
        set { m_Message = value; }
        }

        //default damage
        private int m_Min = 16;
        private int m_Max = 20;

        public void SetDamage(int min, int max)
        {
        m_Min = min;
        m_Max = max;
        }

        public override void Trigger(BaseCreature creature, Mobile defender, int min, int max)
        {

        if(min == 0 && max == 0)
        {
            min = m_Min;
            max = m_Max;
        }

        if(creature.InRange(defender.Location, m_Range) && TriggerChance >= Utility.RandomDouble() && !IsInCooldown(creature))
        {
            DoEffects(creature, defender, min, max);
                    AddToCooldown(creature);
        }
        }

        public override void DoEffects(BaseCreature creature, Mobile defender, int min, int max)
        {    

        switch(Type)
        {
            case StrikeType.Fire: hue = 0; rm = 0;
            phy = 0; fir = 100; col = 0; poi = 0; ene = 0; break;
            case StrikeType.Ice: hue = 1151; rm = 0;
            phy = 0; fir = 0; col = 100; poi = 0; ene = 0; break;
            case StrikeType.Poison: hue = 1366; rm = 0;
            phy = 0; fir = 0; col = 0; poi = 100; ene = 0; break;
            case StrikeType.Energy: hue = 1169; rm = 7;
            phy = 0; fir = 0; col = 0; poi = 0; ene = 100; break;
            case StrikeType.Water: hue = 1365; rm = 0;
            phy = 50; fir = 0; col = 50; poi = 0; ene = 0; break;
            case StrikeType.Steam: hue = 2103; rm = 7;
            phy = 50; fir = 50; col = 0; poi = 0; ene = 0; break;
            case StrikeType.Necrotic: hue = 1174; rm = 7;
            phy = 50; fir = 0; col = 0; poi = 50; ene = 0; break;
            case StrikeType.Holy: hue = 1280; rm = 0;
            phy = 50; fir = 0; col = 0; poi = 0; ene = 50; break;
        }

        if( creature.Body == 0x191 || creature.Body == 0x190)
            creature.Animate(AnimationType.Spell, 0);

        if (!creature.Alive || creature.Map == null)
        return;

        creature.Say(m_Message);
                Timer.DelayCall(TimeSpan.FromSeconds(m_Wait), () => 
        {
            DoFFS(creature, defender, min, max);
            });
        }


        public void DoFFS(BaseCreature creature, Mobile defender, int min, int max)
        {
        Effects.PlaySound(creature.Location, creature.Map, 0x349);

        Point3D p = creature.Location;

        TargetLocationItem e_Item = new TargetLocationItem(p, creature.Map, TimeSpan.FromSeconds(8));

        if(creature.Direction is Direction.North)
        {
            e_Item.X = creature.X;
            e_Item.Y = creature.Y - m_Range;
        }
        else if( creature.Direction is Direction.Right)
        {
            e_Item.X = creature.X + m_Range;
            e_Item.Y = creature.Y - m_Range;

        }
        else if( creature.Direction is Direction.East)
        {
            e_Item.X = creature.X + m_Range;
            e_Item.Y = creature.Y;
        }
        else if( creature.Direction is Direction.Down)
        {
            e_Item.X = creature.X + m_Range;
            e_Item.Y = creature.Y + m_Range;
        }
        else if( creature.Direction is Direction.South)
        {
            e_Item.X = creature.X;
            e_Item.Y = creature.Y + m_Range;
        }
        else if( creature.Direction is Direction.Left)
        {
            e_Item.X = creature.X - m_Range;
            e_Item.Y = creature.Y + m_Range;

        }
        else if( creature.Direction is Direction.West)
        {
            e_Item.X = creature.X - m_Range;
            e_Item.Y = creature.Y;
        }
        else if( creature.Direction is Direction.Up)
        {
            e_Item.X = creature.X - m_Range;
            e_Item.Y = creature.Y - m_Range;
        }
        else
            e_Item.Location = defender.Location;



                if (SpellHelper.CheckField(p, creature.Map))
        {
            TargetLocationItem s_Item = new TargetLocationItem();
            s_Item.Location = p;
            s_Item.Map = creature.Map;
        }

                for (int i = 1; i <= MaxRange; ++i)
                {
                    Timer.DelayCall<int>(TimeSpan.FromMilliseconds(i * 200), index =>
                    {
            Point3D point = new Point3D(p);
            Point3D pL = new Point3D(p);
            Point3D pR = new Point3D(p);

        creature.Direction = creature.GetDirectionTo(e_Item);
        if(creature.GetDirectionTo(e_Item) is Direction.North)
        {
            point.X = creature.X;
            point.Y = creature.Y - index;

            pL.X = creature.X - index;
            pL.Y = creature.Y - index;

            pR.X = creature.X + index;
            pR.Y = creature.Y - index;
        }
        else if(creature.GetDirectionTo(e_Item) is Direction.Right)
        {
            point.X = creature.X + index;
            point.Y = creature.Y - index;

            pL.X = creature.X;
            pL.Y = creature.Y - index;

            pR.X = creature.X + index;
            pR.Y = creature.Y;
        }
        else if(creature.GetDirectionTo(e_Item) is Direction.East)
        {
            point.X = creature.X + index;
            point.Y = creature.Y;

            pL.X = creature.X + index;
            pL.Y = creature.Y - index;

            pR.X = creature.X + index;
            pR.Y = creature.Y + index;
        }
        else if(creature.GetDirectionTo(e_Item) is Direction.Down)
        {
            point.X = creature.X + index;
            point.Y = creature.Y + index;

            pL.X = creature.X + index;
            pL.Y = creature.Y;

            pR.X = creature.X;
            pR.Y = creature.Y + index;
        }
        else if(creature.GetDirectionTo(e_Item) is Direction.South)
        {
            point.X = creature.X;
            point.Y = creature.Y + index;

            pL.X = creature.X + index;
            pL.Y = creature.Y + index;

            pR.X = creature.X - index;
            pR.Y = creature.Y + index;
        }
        else if(creature.GetDirectionTo(e_Item) is Direction.Left)
        {
            point.X = creature.X - index;
            point.Y = creature.Y + index;

            pL.X = creature.X;
            pL.Y = creature.Y + index;

            pR.X = creature.X - index;
            pR.Y = creature.Y;
        }
        else if(creature.GetDirectionTo(e_Item) is Direction.West)
        {
            point.X = creature.X - index;
            point.Y = creature.Y;

            pL.X = creature.X - index;
            pL.Y = creature.Y + index;

            pR.X = creature.X - index;
            pR.Y = creature.Y - index;
        }
        else if(creature.GetDirectionTo(e_Item) is Direction.Up)
        {
            point.X = creature.X - index;
            point.Y = creature.Y - index;

            pL.X = creature.X - index;
            pL.Y = creature.Y;

            pR.X = creature.X;
            pR.Y = creature.Y - index;
        }
                        SpellHelper.AdjustField(ref point, creature.Map, 16, false);

                        if (SpellHelper.CheckField(point, creature.Map))
            {
                TargetLocationItem m_Item = new TargetLocationItem();
                m_Item.Location = point;
                m_Item.Map = creature.Map;
                Effects.SendLocationParticles(EffectItem.Create(point, creature.Map, EffectItem.DefaultDuration), 0x3709, 10, 30, hue, rm, 5052, 0);
                            IPooledEnumerable eable = m_Item.GetMobilesInRange(1);

                TargetLocationItem l_Item = new TargetLocationItem();
                l_Item.Location = pL;
                l_Item.Map = creature.Map;
                Effects.SendLocationParticles(EffectItem.Create(pL, creature.Map, EffectItem.DefaultDuration), 0x3709, 10, 30, hue, rm, 5052, 0);
                            IPooledEnumerable lable = l_Item.GetMobilesInRange(1);

                TargetLocationItem r_Item = new TargetLocationItem();
                r_Item.Location = pR;
                r_Item.Map = creature.Map;
                Effects.SendLocationParticles(EffectItem.Create(pR, creature.Map, EffectItem.DefaultDuration), 0x3709, 10, 30, hue, rm, 5052, 0);
                            IPooledEnumerable rable = r_Item.GetMobilesInRange(1);

                            foreach (Mobile m in eable)
                            {
                        if ((m is PlayerMobile || (m is BaseCreature && ((BaseCreature)m).GetMaster() is PlayerMobile)) && creature.CanBeHarmful(m) && !creature.Controlled)
                {
                                    Timer.DelayCall(TimeSpan.FromSeconds(0.75), () => 
                        {
                        int d = Utility.RandomMinMax(min, max);

                                AOS.Damage(m, d, phy, fir, col, poi, ene);
                            });
                }
                        else if (creature.Controlled && (m is BaseCreature && !((BaseCreature)m).Controlled))
                {
                                    Timer.DelayCall(TimeSpan.FromSeconds(0.75), () => 
                        {
                        int d = Utility.RandomMinMax(min, max);

                                AOS.Damage(m, d, phy, fir, col, poi, ene);
                            });
                }
                else
                        return;
                            }

                            eable.Free();

                            foreach (Mobile m in lable)
                            {
                        if ((m is PlayerMobile || (m is BaseCreature && ((BaseCreature)m).GetMaster() is PlayerMobile)) && creature.CanBeHarmful(m) && !creature.Controlled)
                {
                                    Timer.DelayCall(TimeSpan.FromSeconds(0.75), () => 
                        {
                        int d = Utility.RandomMinMax(min, max);

                                AOS.Damage(m, d, phy, fir, col, poi, ene);
                            });
                }
                        else if (creature.Controlled && (m is BaseCreature && !((BaseCreature)m).Controlled))
                {
                                    Timer.DelayCall(TimeSpan.FromSeconds(0.75), () => 
                        {
                        int d = Utility.RandomMinMax(min, max);

                                AOS.Damage(m, d, phy, fir, col, poi, ene);
                            });
                }
                else
                        return;
                            }
                            lable.Free();

                            foreach (Mobile m in rable)
                            {
                        if ((m is PlayerMobile || (m is BaseCreature && ((BaseCreature)m).GetMaster() is PlayerMobile)) && creature.CanBeHarmful(m) && !creature.Controlled)
                {
                                    Timer.DelayCall(TimeSpan.FromSeconds(0.75), () => 
                        {
                        int d = Utility.RandomMinMax(min, max);

                                AOS.Damage(m, d, phy, fir, col, poi, ene);
                            });
                }
                        else if (creature.Controlled && (m is BaseCreature && !((BaseCreature)m).Controlled))
                {
                                    Timer.DelayCall(TimeSpan.FromSeconds(0.75), () => 
                        {
                        int d = Utility.RandomMinMax(min, max);

                                AOS.Damage(m, d, phy, fir, col, poi, ene);
                            });
                }
                else
                        return;
                            }

                            rable.Free();
            }

                        }, i);
                }
        }
    }
}
 
Okay, I managed to create a new ability that does exactly as you asked.
You customize the wait time and the message.
you can just copy this code and place it in a separate file in your custom folder:
Code:
using System;
using Server;using System.Collections.Generic;
using System.Linq;
using Server.Items;
using Server.Network;
using System.Collections;
using Server.Spells;

namespace Server.Mobiles
{
    public class ForkedFlameStrike : CustomAbility
    {
        public override double TriggerChance { get { return 0.8; } }
            public override int MaxRange { get { return 8; } }
            public override TimeSpan CooldownDuration { get { return TimeSpan.FromSeconds(10); } }

        public enum StrikeType
        {
        Fire,
        Ice,
        Poison,
        Energy,
        Water,
        Steam,
        Necrotic,
        Holy
        }

        private StrikeType m_Type = StrikeType.Fire;
        private int hue, rm, phy, fir, col, poi, ene;

        private int m_Range = 5;

        public StrikeType Type
        {
        get { return m_Type; }
        set { m_Type = value; }
        }

        public int Range
        {
        get { return m_Range; }
        set { m_Range = value; }
        }

        public ForkedFlameStrike()
        {
        }

        private int m_Wait = 3;
        private int Wait
        {
        get { return m_Wait; }
        set { m_Wait = value; }
        }

        private string m_Message = "*The creature is preparing to use its fire breath.*";

        public string Message
        {
        get { return m_Message; }
        set { m_Message = value; }
        }

        //default damage
        private int m_Min = 16;
        private int m_Max = 20;

        public void SetDamage(int min, int max)
        {
        m_Min = min;
        m_Max = max;
        }

        public override void Trigger(BaseCreature creature, Mobile defender, int min, int max)
        {

        if(min == 0 && max == 0)
        {
            min = m_Min;
            max = m_Max;
        }

        if(creature.InRange(defender.Location, m_Range) && TriggerChance >= Utility.RandomDouble() && !IsInCooldown(creature))
        {
            DoEffects(creature, defender, min, max);
                    AddToCooldown(creature);
        }
        }

        public override void DoEffects(BaseCreature creature, Mobile defender, int min, int max)
        {   

        switch(Type)
        {
            case StrikeType.Fire: hue = 0; rm = 0;
            phy = 0; fir = 100; col = 0; poi = 0; ene = 0; break;
            case StrikeType.Ice: hue = 1151; rm = 0;
            phy = 0; fir = 0; col = 100; poi = 0; ene = 0; break;
            case StrikeType.Poison: hue = 1366; rm = 0;
            phy = 0; fir = 0; col = 0; poi = 100; ene = 0; break;
            case StrikeType.Energy: hue = 1169; rm = 7;
            phy = 0; fir = 0; col = 0; poi = 0; ene = 100; break;
            case StrikeType.Water: hue = 1365; rm = 0;
            phy = 50; fir = 0; col = 50; poi = 0; ene = 0; break;
            case StrikeType.Steam: hue = 2103; rm = 7;
            phy = 50; fir = 50; col = 0; poi = 0; ene = 0; break;
            case StrikeType.Necrotic: hue = 1174; rm = 7;
            phy = 50; fir = 0; col = 0; poi = 50; ene = 0; break;
            case StrikeType.Holy: hue = 1280; rm = 0;
            phy = 50; fir = 0; col = 0; poi = 0; ene = 50; break;
        }

        if( creature.Body == 0x191 || creature.Body == 0x190)
            creature.Animate(AnimationType.Spell, 0);

        if (!creature.Alive || creature.Map == null)
        return;

        creature.Say(m_Message);
                Timer.DelayCall(TimeSpan.FromSeconds(m_Wait), () =>
        {
            DoFFS(creature, defender, min, max);
            });
        }


        public void DoFFS(BaseCreature creature, Mobile defender, int min, int max)
        {
        Effects.PlaySound(creature.Location, creature.Map, 0x349);

        Point3D p = creature.Location;

        TargetLocationItem e_Item = new TargetLocationItem(p, creature.Map, TimeSpan.FromSeconds(8));

        if(creature.Direction is Direction.North)
        {
            e_Item.X = creature.X;
            e_Item.Y = creature.Y - m_Range;
        }
        else if( creature.Direction is Direction.Right)
        {
            e_Item.X = creature.X + m_Range;
            e_Item.Y = creature.Y - m_Range;

        }
        else if( creature.Direction is Direction.East)
        {
            e_Item.X = creature.X + m_Range;
            e_Item.Y = creature.Y;
        }
        else if( creature.Direction is Direction.Down)
        {
            e_Item.X = creature.X + m_Range;
            e_Item.Y = creature.Y + m_Range;
        }
        else if( creature.Direction is Direction.South)
        {
            e_Item.X = creature.X;
            e_Item.Y = creature.Y + m_Range;
        }
        else if( creature.Direction is Direction.Left)
        {
            e_Item.X = creature.X - m_Range;
            e_Item.Y = creature.Y + m_Range;

        }
        else if( creature.Direction is Direction.West)
        {
            e_Item.X = creature.X - m_Range;
            e_Item.Y = creature.Y;
        }
        else if( creature.Direction is Direction.Up)
        {
            e_Item.X = creature.X - m_Range;
            e_Item.Y = creature.Y - m_Range;
        }
        else
            e_Item.Location = defender.Location;



                if (SpellHelper.CheckField(p, creature.Map))
        {
            TargetLocationItem s_Item = new TargetLocationItem();
            s_Item.Location = p;
            s_Item.Map = creature.Map;
        }

                for (int i = 1; i <= MaxRange; ++i)
                {
                    Timer.DelayCall<int>(TimeSpan.FromMilliseconds(i * 200), index =>
                    {
            Point3D point = new Point3D(p);
            Point3D pL = new Point3D(p);
            Point3D pR = new Point3D(p);

        creature.Direction = creature.GetDirectionTo(e_Item);
        if(creature.GetDirectionTo(e_Item) is Direction.North)
        {
            point.X = creature.X;
            point.Y = creature.Y - index;

            pL.X = creature.X - index;
            pL.Y = creature.Y - index;

            pR.X = creature.X + index;
            pR.Y = creature.Y - index;
        }
        else if(creature.GetDirectionTo(e_Item) is Direction.Right)
        {
            point.X = creature.X + index;
            point.Y = creature.Y - index;

            pL.X = creature.X;
            pL.Y = creature.Y - index;

            pR.X = creature.X + index;
            pR.Y = creature.Y;
        }
        else if(creature.GetDirectionTo(e_Item) is Direction.East)
        {
            point.X = creature.X + index;
            point.Y = creature.Y;

            pL.X = creature.X + index;
            pL.Y = creature.Y - index;

            pR.X = creature.X + index;
            pR.Y = creature.Y + index;
        }
        else if(creature.GetDirectionTo(e_Item) is Direction.Down)
        {
            point.X = creature.X + index;
            point.Y = creature.Y + index;

            pL.X = creature.X + index;
            pL.Y = creature.Y;

            pR.X = creature.X;
            pR.Y = creature.Y + index;
        }
        else if(creature.GetDirectionTo(e_Item) is Direction.South)
        {
            point.X = creature.X;
            point.Y = creature.Y + index;

            pL.X = creature.X + index;
            pL.Y = creature.Y + index;

            pR.X = creature.X - index;
            pR.Y = creature.Y + index;
        }
        else if(creature.GetDirectionTo(e_Item) is Direction.Left)
        {
            point.X = creature.X - index;
            point.Y = creature.Y + index;

            pL.X = creature.X;
            pL.Y = creature.Y + index;

            pR.X = creature.X - index;
            pR.Y = creature.Y;
        }
        else if(creature.GetDirectionTo(e_Item) is Direction.West)
        {
            point.X = creature.X - index;
            point.Y = creature.Y;

            pL.X = creature.X - index;
            pL.Y = creature.Y + index;

            pR.X = creature.X - index;
            pR.Y = creature.Y - index;
        }
        else if(creature.GetDirectionTo(e_Item) is Direction.Up)
        {
            point.X = creature.X - index;
            point.Y = creature.Y - index;

            pL.X = creature.X - index;
            pL.Y = creature.Y;

            pR.X = creature.X;
            pR.Y = creature.Y - index;
        }
                        SpellHelper.AdjustField(ref point, creature.Map, 16, false);

                        if (SpellHelper.CheckField(point, creature.Map))
            {
                TargetLocationItem m_Item = new TargetLocationItem();
                m_Item.Location = point;
                m_Item.Map = creature.Map;
                Effects.SendLocationParticles(EffectItem.Create(point, creature.Map, EffectItem.DefaultDuration), 0x3709, 10, 30, hue, rm, 5052, 0);
                            IPooledEnumerable eable = m_Item.GetMobilesInRange(1);

                TargetLocationItem l_Item = new TargetLocationItem();
                l_Item.Location = pL;
                l_Item.Map = creature.Map;
                Effects.SendLocationParticles(EffectItem.Create(pL, creature.Map, EffectItem.DefaultDuration), 0x3709, 10, 30, hue, rm, 5052, 0);
                            IPooledEnumerable lable = l_Item.GetMobilesInRange(1);

                TargetLocationItem r_Item = new TargetLocationItem();
                r_Item.Location = pR;
                r_Item.Map = creature.Map;
                Effects.SendLocationParticles(EffectItem.Create(pR, creature.Map, EffectItem.DefaultDuration), 0x3709, 10, 30, hue, rm, 5052, 0);
                            IPooledEnumerable rable = r_Item.GetMobilesInRange(1);

                            foreach (Mobile m in eable)
                            {
                        if ((m is PlayerMobile || (m is BaseCreature && ((BaseCreature)m).GetMaster() is PlayerMobile)) && creature.CanBeHarmful(m) && !creature.Controlled)
                {
                                    Timer.DelayCall(TimeSpan.FromSeconds(0.75), () =>
                        {
                        int d = Utility.RandomMinMax(min, max);

                                AOS.Damage(m, d, phy, fir, col, poi, ene);
                            });
                }
                        else if (creature.Controlled && (m is BaseCreature && !((BaseCreature)m).Controlled))
                {
                                    Timer.DelayCall(TimeSpan.FromSeconds(0.75), () =>
                        {
                        int d = Utility.RandomMinMax(min, max);

                                AOS.Damage(m, d, phy, fir, col, poi, ene);
                            });
                }
                else
                        return;
                            }

                            eable.Free();

                            foreach (Mobile m in lable)
                            {
                        if ((m is PlayerMobile || (m is BaseCreature && ((BaseCreature)m).GetMaster() is PlayerMobile)) && creature.CanBeHarmful(m) && !creature.Controlled)
                {
                                    Timer.DelayCall(TimeSpan.FromSeconds(0.75), () =>
                        {
                        int d = Utility.RandomMinMax(min, max);

                                AOS.Damage(m, d, phy, fir, col, poi, ene);
                            });
                }
                        else if (creature.Controlled && (m is BaseCreature && !((BaseCreature)m).Controlled))
                {
                                    Timer.DelayCall(TimeSpan.FromSeconds(0.75), () =>
                        {
                        int d = Utility.RandomMinMax(min, max);

                                AOS.Damage(m, d, phy, fir, col, poi, ene);
                            });
                }
                else
                        return;
                            }
                            lable.Free();

                            foreach (Mobile m in rable)
                            {
                        if ((m is PlayerMobile || (m is BaseCreature && ((BaseCreature)m).GetMaster() is PlayerMobile)) && creature.CanBeHarmful(m) && !creature.Controlled)
                {
                                    Timer.DelayCall(TimeSpan.FromSeconds(0.75), () =>
                        {
                        int d = Utility.RandomMinMax(min, max);

                                AOS.Damage(m, d, phy, fir, col, poi, ene);
                            });
                }
                        else if (creature.Controlled && (m is BaseCreature && !((BaseCreature)m).Controlled))
                {
                                    Timer.DelayCall(TimeSpan.FromSeconds(0.75), () =>
                        {
                        int d = Utility.RandomMinMax(min, max);

                                AOS.Damage(m, d, phy, fir, col, poi, ene);
                            });
                }
                else
                        return;
                            }

                            rable.Free();
            }

                        }, i);
                }
        }
    }
}
Wow! It works perfectly! You are a hero to me! Thank you for always energizing my Ultima life.
 
Massapequa Dragon.jpg

On our shard:
Coming soon . . . the Lenape people have regained a foothold on their indigenous lands of Massapequa with the help of
sea dwelling Massapequa Dragons and other new found creatures. They have recovered many previously unknown treasures but ferociously defend them and their lands. More details will be known in the near future.

Many Thanks to Massapequa for making this possible for us. *bows*
 
I can't believe I can't solve this problem. I'm sure the solution will embarass me because it must be something minor I should be able to find.

However after 'triple' countless tries . . I still can't get this creature to spawn (using an xmlspawner). Every time I try to spawn it the spawner refuses and gives me an Error saying "invalid type specification: MassapequaShaman".

I'm hoping someone might find time to take a look and show me what I'm missing.

Here is the script:
Code:
using System.Linq;
using Server;
using System;
using Server.Misc;
using Server.Items;
using Server.Spells;
using Server.Mobiles;
using Server.Network;
using Server.Targeting;
using Server.Accounting;
using System.Collections;
using Server.ContextMenus;
using Server.Spells.Fifth;
using Server.Spells.Sixth;
using Server.Spells.Fourth;
using Server.Spells.Seventh;
using Server.Engines.CannedEvil;
using System.Collections.Generic;
using Xanthos.Evo;
using Xanthos.Interfaces;
using Xanthos.ShrinkSystem;

namespace Server.Mobiles
{
    [CorpseName("a massapequa corpse")]
    public class MassapequaShaman : BaseCreature
    {
        CustomAbilityList list;
        WalkingBomb wb = new WalkingBomb();
        ToxicRain tr = new ToxicRain();

        private bool HasSummon = false;
        private PatchworkSkeleton summon;

        [Constructable]
        public MassapequaShaman() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4)
            {
            Name = "Ojistah";
            Title = "a shaman";

            Body = 0x190;
            Hue = 33774;
            HairItemID = 0x2044;
            HairHue = 0x1;

            SetStr( 700 );
            SetDex( 200 );
            SetInt( 1000 );

            SetHits(1000, 1600);
            SetDamage(15, 22);

            SetDamageType(ResistanceType.Physical, 10);
            SetDamageType(ResistanceType.Cold, 45);
            SetDamageType(ResistanceType.Energy, 45);

            SetResistance(ResistanceType.Physical, 40, 70);
            SetResistance(ResistanceType.Fire, 40, 70);
            SetResistance(ResistanceType.Cold, 40, 70);
            SetResistance(ResistanceType.Poison, 40, 70);
            SetResistance(ResistanceType.Energy, 40, 70);

            DivineCountenance head = new DivineCountenance();
            head.Movable = false;
            head.Hue = 2831;
            head.Name = "Shaman Headdress";
            AddItem(head);

            BoneArms arm = new BoneArms();
            arm.Hue = 2112;
            arm.Name = "Bone Armguard";
            arm.Movable = false;
            AddItem(arm);

            LeatherDo chest = new LeatherDo();
            chest.Name = "Tribal Cuirass";
            chest.Movable = false;
            AddItem(chest);

            Cloak back = new Cloak();
            back.Hue = 2957;
            back.Name = "shaman's fur cloak";
            back.Movable = false;
            AddItem(back);

             Sandals foot = new Sandals();
            foot.Hue = 1860;
            foot.Movable = false;
            AddItem(foot);

            SetSkill(SkillName.EvalInt, 120);
            SetSkill(SkillName.Meditation, 110);
            SetSkill(SkillName.MagicResist, 120);
            SetSkill(SkillName.Wrestling, 110.0);
            SetSkill(SkillName.Tactics, 110.0);
            SetSkill(SkillName.Magery, 110);
            SetSkill(SkillName.Necromancy, 120);
            SetSkill(SkillName.SpiritSpeak, 90.0, 100.0);

            Fame = 22000;
            Karma = -22000;

            VirtualArmor = 40;

        }

        public MassapequaShaman(Serial serial) : base(serial)
        {
        }

        public override bool CanRummageCorpses{ get{ return true; } }
        public override bool AlwaysMurderer{ get{ return true; } }
        public override bool ShowFameTitle{ get{ return false; } }

        public override void GenerateLoot()
        {
            AddLoot(LootPack.SuperBoss, 2);
            AddLoot(LootPack.HighScrolls, 2);
        }

        public override void CheckReflect( Mobile caster, ref bool reflect )
        {
            if ( Utility.Random( 3 ) == 0 )
                reflect = true;
        }

        public override void OnGotMeleeAttack( Mobile attacker )
        {
            base.OnGotMeleeAttack( attacker );

            if ( (attacker == null) || (attacker.Deleted) || !(attacker.Alive) || !(attacker.Map == this.Map) )
            {
                return;
            } 

            this.Mana = this.ManaMax;

            if ( 0.1 > Utility.RandomDouble() && attacker is BaseCreature )
            {
                BaseCreature c = (BaseCreature)attacker;

                c.ControlTarget = c.ControlMaster;
                c.ControlOrder = OrderType.Attack;
                c.Combatant = c.ControlMaster;
            }
        }

        public override void OnGaveMeleeAttack( Mobile defender )
        {
            base.OnGaveMeleeAttack( defender );

            if ( (defender == null) || (defender.Deleted) || !(defender.Alive) || !(defender.Map == this.Map) )
            {
                return;
            } 

            this.Mana = this.ManaMax;

            defender.Damage( Utility.Random( 10, 10 ), this );
            defender.Stam -= Utility.Random( 10, 10 );
            defender.Mana -= Utility.Random( 10, 10 );
    
            if ( 0.2 > Utility.RandomDouble() && defender is BaseCreature )
            {
                BaseCreature c = (BaseCreature)defender;

                if ( c.Controlled && c.ControlMaster != null )
                {
                    c.Combatant = null;
                }
            }

            if ( 0.2 > Utility.RandomDouble() )
            {
                defender.Combatant = null;

            }
        }

        public override void OnDamage( int amount, Mobile from, bool willKill )
        {
            if ( (from == null) || (from.Deleted) || !(from.Alive) || !(from.Map == this.Map) )
            {
                return;
            } 

            this.Mana = this.ManaMax;

            base.OnDamage( amount, from, willKill );
        }

        public override void OnDeath( Container c )
        {
            if( summon != null || !summon.Deleted)
                summon.Kill();

            switch ( Utility.Random( 2 ) )
            {
                case 0: c.DropItem( new Bandage(30) ); break;
                case 1: c.DropItem( new Bandage(40) ); break;
            }

            switch ( Utility.Random( 6 ) )
            {
                case 0: c.DropItem( new Blight(  ) ); break;
                case 1: c.DropItem( new CapturedEssence(  ) ); break;
                case 2: c.DropItem( new Corruption(  ) ); break;
                case 3: c.DropItem( new DiseasedBark(  ) ); break;
                case 4: c.DropItem( new DreadHornMane(  ) ); break;
                case 5: c.DropItem( new GrizzledBones(  ) ); break;
            }

            switch ( Utility.Random( 7 ) )
            {
                case 0: c.DropItem( new LardOfParoxysmus(  ) ); break;
                case 1: c.DropItem( new LuminescentFungi(  ) ); break;
                case 2: c.DropItem( new Muculent(  ) ); break;
                case 3: c.DropItem( new ParasiticPlant(  ) ); break;
                case 4: c.DropItem( new Putrefication(  ) ); break;
                case 5: c.DropItem( new Scourge(  ) ); break;
                case 6: c.DropItem( new Taint(  ) ); break;
            }

                  double mapchance = Utility.RandomDouble();

            if (mapchance < 0.55)
            {
                int lvl = 6;
                TreasureMap map = new TreasureMap( lvl, Map.Felucca );
                Point2D loc = map.ChestLocation;
                if ( loc.X >= 5116 && loc.X <= 6144 && loc.Y >= 2304 && loc.Y <= 4095 )  //Lost Lands Area
                    map.ChestMap = Map.Felucca;
                else
                    map.ChestMap = Map.Trammel;
                c.DropItem( map );
            }

            base.OnDeath( c );
        }

        public override void OnThink()
        {
            base.OnThink();

            if(list == null)
            {
                list = new CustomAbilityList();
                wb.SetDamage(15, 30);
                tr.SetDamage(12, 18);

                list.Add(tr);
                list.Add(wb);
            }
            else
                list.CheckTrigger(this);

            CheckSummon();
        }

        public void CheckSummon()
        {
            if( !Alive || Combatant == null || Map == null || Map == Map.Internal)
            {
                if( HasSummon == true && summon != null)
                {
                    summon.Delete();
                    HasSummon = false;
                }
                else
                    return;
            }
            else if( HasSummon == false && Combatant != null)
            {
                HasSummon = true;

                Point3D p = new Point3D(Location);
                p = GetSpawnPosition(6);

                Effects.SendLocationParticles(EffectItem.Create(p, Map, TimeSpan.FromSeconds(2)), 0x3789, 1, 40, 0x3F, 3, 9907, 0);

                Timer.DelayCall(TimeSpan.FromSeconds(2), () => 
                {
                    summon = new PatchworkSkeleton();
                    summon.MoveToWorld(p, Map);
                    summon.Team = Team;

                    if (Combatant != null)
                        summon.Combatant = Combatant;
                });
            }
        }

        public virtual Point3D GetSpawnPosition(int range)
        {
            return GetSpawnPosition(Location, Map, range);
        }

        public static Point3D GetSpawnPosition(Point3D from, Map map, int range)
        {
            if (map == null)
                return from;

            for (int i = 0; i < 10; i++)
            {
                int x = from.X + Utility.Random(range);
                int y = from.Y + Utility.Random(range);
                int z = map.GetAverageZ(x, y);

                if (Utility.RandomBool())
                    x *= -1;

                if (Utility.RandomBool())
                    y *= -1;

                Point3D p = new Point3D(x, y, from.Z);

                if (map.CanSpawnMobile(p) && map.LineOfSight(from, p))
                    return p;

                p = new Point3D(x, y, z);

                if (map.CanSpawnMobile(p) && map.LineOfSight(from, p))
                    return p;
            }
            return from;
        }


        public override void Serialize(GenericWriter writer)
        {
            base.Serialize(writer);

            writer.Write(0); // version 
        }

        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);

            int version = reader.ReadInt();
        }
    }
}

What the heck am I missing here?
Sorry for the trouble . . brighter brains and eyes appreciated.

Many Thanks
 
I can't believe I can't solve this problem. I'm sure the solution will embarass me because it must be something minor I should be able to find.

However after 'triple' countless tries . . I still can't get this creature to spawn (using an xmlspawner). Every time I try to spawn it the spawner refuses and gives me an Error saying "invalid type specification: MassapequaShaman".

I'm hoping someone might find time to take a look and show me what I'm missing.

Here is the script:
Code:
using System.Linq;
using Server;
using System;
using Server.Misc;
using Server.Items;
using Server.Spells;
using Server.Mobiles;
using Server.Network;
using Server.Targeting;
using Server.Accounting;
using System.Collections;
using Server.ContextMenus;
using Server.Spells.Fifth;
using Server.Spells.Sixth;
using Server.Spells.Fourth;
using Server.Spells.Seventh;
using Server.Engines.CannedEvil;
using System.Collections.Generic;
using Xanthos.Evo;
using Xanthos.Interfaces;
using Xanthos.ShrinkSystem;

namespace Server.Mobiles
{
    [CorpseName("a massapequa corpse")]
    public class MassapequaShaman : BaseCreature
    {
        CustomAbilityList list;
        WalkingBomb wb = new WalkingBomb();
        ToxicRain tr = new ToxicRain();

        private bool HasSummon = false;
        private PatchworkSkeleton summon;

        [Constructable]
        public MassapequaShaman() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4)
            {
            Name = "Ojistah";
            Title = "a shaman";

            Body = 0x190;
            Hue = 33774;
            HairItemID = 0x2044;
            HairHue = 0x1;

            SetStr( 700 );
            SetDex( 200 );
            SetInt( 1000 );

            SetHits(1000, 1600);
            SetDamage(15, 22);

            SetDamageType(ResistanceType.Physical, 10);
            SetDamageType(ResistanceType.Cold, 45);
            SetDamageType(ResistanceType.Energy, 45);

            SetResistance(ResistanceType.Physical, 40, 70);
            SetResistance(ResistanceType.Fire, 40, 70);
            SetResistance(ResistanceType.Cold, 40, 70);
            SetResistance(ResistanceType.Poison, 40, 70);
            SetResistance(ResistanceType.Energy, 40, 70);

            DivineCountenance head = new DivineCountenance();
            head.Movable = false;
            head.Hue = 2831;
            head.Name = "Shaman Headdress";
            AddItem(head);

            BoneArms arm = new BoneArms();
            arm.Hue = 2112;
            arm.Name = "Bone Armguard";
            arm.Movable = false;
            AddItem(arm);

            LeatherDo chest = new LeatherDo();
            chest.Name = "Tribal Cuirass";
            chest.Movable = false;
            AddItem(chest);

            Cloak back = new Cloak();
            back.Hue = 2957;
            back.Name = "shaman's fur cloak";
            back.Movable = false;
            AddItem(back);

             Sandals foot = new Sandals();
            foot.Hue = 1860;
            foot.Movable = false;
            AddItem(foot);

            SetSkill(SkillName.EvalInt, 120);
            SetSkill(SkillName.Meditation, 110);
            SetSkill(SkillName.MagicResist, 120);
            SetSkill(SkillName.Wrestling, 110.0);
            SetSkill(SkillName.Tactics, 110.0);
            SetSkill(SkillName.Magery, 110);
            SetSkill(SkillName.Necromancy, 120);
            SetSkill(SkillName.SpiritSpeak, 90.0, 100.0);

            Fame = 22000;
            Karma = -22000;

            VirtualArmor = 40;

        }

        public MassapequaShaman(Serial serial) : base(serial)
        {
        }

        public override bool CanRummageCorpses{ get{ return true; } }
        public override bool AlwaysMurderer{ get{ return true; } }
        public override bool ShowFameTitle{ get{ return false; } }

        public override void GenerateLoot()
        {
            AddLoot(LootPack.SuperBoss, 2);
            AddLoot(LootPack.HighScrolls, 2);
        }

        public override void CheckReflect( Mobile caster, ref bool reflect )
        {
            if ( Utility.Random( 3 ) == 0 )
                reflect = true;
        }

        public override void OnGotMeleeAttack( Mobile attacker )
        {
            base.OnGotMeleeAttack( attacker );

            if ( (attacker == null) || (attacker.Deleted) || !(attacker.Alive) || !(attacker.Map == this.Map) )
            {
                return;
            }

            this.Mana = this.ManaMax;

            if ( 0.1 > Utility.RandomDouble() && attacker is BaseCreature )
            {
                BaseCreature c = (BaseCreature)attacker;

                c.ControlTarget = c.ControlMaster;
                c.ControlOrder = OrderType.Attack;
                c.Combatant = c.ControlMaster;
            }
        }

        public override void OnGaveMeleeAttack( Mobile defender )
        {
            base.OnGaveMeleeAttack( defender );

            if ( (defender == null) || (defender.Deleted) || !(defender.Alive) || !(defender.Map == this.Map) )
            {
                return;
            }

            this.Mana = this.ManaMax;

            defender.Damage( Utility.Random( 10, 10 ), this );
            defender.Stam -= Utility.Random( 10, 10 );
            defender.Mana -= Utility.Random( 10, 10 );
  
            if ( 0.2 > Utility.RandomDouble() && defender is BaseCreature )
            {
                BaseCreature c = (BaseCreature)defender;

                if ( c.Controlled && c.ControlMaster != null )
                {
                    c.Combatant = null;
                }
            }

            if ( 0.2 > Utility.RandomDouble() )
            {
                defender.Combatant = null;

            }
        }

        public override void OnDamage( int amount, Mobile from, bool willKill )
        {
            if ( (from == null) || (from.Deleted) || !(from.Alive) || !(from.Map == this.Map) )
            {
                return;
            }

            this.Mana = this.ManaMax;

            base.OnDamage( amount, from, willKill );
        }

        public override void OnDeath( Container c )
        {
            if( summon != null || !summon.Deleted)
                summon.Kill();

            switch ( Utility.Random( 2 ) )
            {
                case 0: c.DropItem( new Bandage(30) ); break;
                case 1: c.DropItem( new Bandage(40) ); break;
            }

            switch ( Utility.Random( 6 ) )
            {
                case 0: c.DropItem( new Blight(  ) ); break;
                case 1: c.DropItem( new CapturedEssence(  ) ); break;
                case 2: c.DropItem( new Corruption(  ) ); break;
                case 3: c.DropItem( new DiseasedBark(  ) ); break;
                case 4: c.DropItem( new DreadHornMane(  ) ); break;
                case 5: c.DropItem( new GrizzledBones(  ) ); break;
            }

            switch ( Utility.Random( 7 ) )
            {
                case 0: c.DropItem( new LardOfParoxysmus(  ) ); break;
                case 1: c.DropItem( new LuminescentFungi(  ) ); break;
                case 2: c.DropItem( new Muculent(  ) ); break;
                case 3: c.DropItem( new ParasiticPlant(  ) ); break;
                case 4: c.DropItem( new Putrefication(  ) ); break;
                case 5: c.DropItem( new Scourge(  ) ); break;
                case 6: c.DropItem( new Taint(  ) ); break;
            }

                  double mapchance = Utility.RandomDouble();

            if (mapchance < 0.55)
            {
                int lvl = 6;
                TreasureMap map = new TreasureMap( lvl, Map.Felucca );
                Point2D loc = map.ChestLocation;
                if ( loc.X >= 5116 && loc.X <= 6144 && loc.Y >= 2304 && loc.Y <= 4095 )  //Lost Lands Area
                    map.ChestMap = Map.Felucca;
                else
                    map.ChestMap = Map.Trammel;
                c.DropItem( map );
            }

            base.OnDeath( c );
        }

        public override void OnThink()
        {
            base.OnThink();

            if(list == null)
            {
                list = new CustomAbilityList();
                wb.SetDamage(15, 30);
                tr.SetDamage(12, 18);

                list.Add(tr);
                list.Add(wb);
            }
            else
                list.CheckTrigger(this);

            CheckSummon();
        }

        public void CheckSummon()
        {
            if( !Alive || Combatant == null || Map == null || Map == Map.Internal)
            {
                if( HasSummon == true && summon != null)
                {
                    summon.Delete();
                    HasSummon = false;
                }
                else
                    return;
            }
            else if( HasSummon == false && Combatant != null)
            {
                HasSummon = true;

                Point3D p = new Point3D(Location);
                p = GetSpawnPosition(6);

                Effects.SendLocationParticles(EffectItem.Create(p, Map, TimeSpan.FromSeconds(2)), 0x3789, 1, 40, 0x3F, 3, 9907, 0);

                Timer.DelayCall(TimeSpan.FromSeconds(2), () =>
                {
                    summon = new PatchworkSkeleton();
                    summon.MoveToWorld(p, Map);
                    summon.Team = Team;

                    if (Combatant != null)
                        summon.Combatant = Combatant;
                });
            }
        }

        public virtual Point3D GetSpawnPosition(int range)
        {
            return GetSpawnPosition(Location, Map, range);
        }

        public static Point3D GetSpawnPosition(Point3D from, Map map, int range)
        {
            if (map == null)
                return from;

            for (int i = 0; i < 10; i++)
            {
                int x = from.X + Utility.Random(range);
                int y = from.Y + Utility.Random(range);
                int z = map.GetAverageZ(x, y);

                if (Utility.RandomBool())
                    x *= -1;

                if (Utility.RandomBool())
                    y *= -1;

                Point3D p = new Point3D(x, y, from.Z);

                if (map.CanSpawnMobile(p) && map.LineOfSight(from, p))
                    return p;

                p = new Point3D(x, y, z);

                if (map.CanSpawnMobile(p) && map.LineOfSight(from, p))
                    return p;
            }
            return from;
        }


        public override void Serialize(GenericWriter writer)
        {
            base.Serialize(writer);

            writer.Write(0); // version
        }

        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);

            int version = reader.ReadInt();
        }
    }
}

What the heck am I missing here?
Sorry for the trouble . . brighter brains and eyes appreciated.

Many Thanks

Hey, I can't see anything explicitly wrong with the code. My one suggestion would be to comment out all of the extra functionality and see if the mob spawns with just the necessary bits. Then, keep adding back one method at a time until it fails to spawn.

Also, what happens when you try to create it using the [add command?
 
Last edited:
Okay . . and this is Extremely Weird. After trying everything from the most basic on up everything failed until I changed the creature from "MassapequaShaman" to "Masssham" or anything other than MassapequaShaman. If I use a different naming it works fine.

I have no idea why this happens but for some reason it appears "MassapequaShaman" is prohibited.

Sorry to trouble everyone.
 
Last edited:
Massapequa updated Custom Abilities for your monsters with a new update entry:

More Custom Abilities for your monsters

Custom Abilities 3.0:
The main focus of this update was to make it easier for admins to add these Custom Abilities to their creatures and to change the way that manipulated and saved on the server.
Now, it should be much less of a hassle to create new creatures with these skills.

Implementation changes:
AbilityCreature and AbilityMount have been added as extensions to the BaseCreature class.
This allows everyone to more easily add CustomAbilities to your creatures.
You no longer...

Read the rest of this update entry...
 
it has been a while. I think i have the old old version workin in my server do you think this would work for pub 57? the original?
i had an idea for a special. instead of flams spawning on the ground have blade spirits come up with a slight delay to hit. If it hits you because you didnt move away you get killed and your corpse gets chopped. :p
 
Last edited:
it has been a while. I think i have the old old version workin in my server do you think this would work for pub 57? the original?
i had an idea for a special. instead of flams spawning on the ground have blade spirits come up with a slight delay to hit. If it hits you because you didnt move away you get killed and your corpse gets chopped. :p
Only way to find out is to download and try it. If you get errors, we can usually work through them and get it working for your version. It's usually only a few tweaks. And lol I always like ideas for new abilities
 
Thank you for always uploading the enhanced version. I'm having trouble completing the compilation and trying to use it. I wanted to apply it to Champion Monster as well, so I set it up as below.
namespace Server.Mobiles
{
public abstract class BaseChampion : AbilityCreature
I'm trying to change BaseCreature in the BaseChampion.cs script to AbilityCreature as above and use it, but it keeps telling me to delete champion monsters that are spawning in the field as below. I was wondering if there was a way to fix it.
Regions: Loading...done
World: Loading...
Invalid flag during deserialization.
An error was encountered while loading a saved object
- Type: Server.Mobiles.FrostElfLord
- Serial: 0x00000032
Delete the object? (y/n)
I'm leaving an additional message. When I delete it, create Champion Monster again, save the server, and restart the server, I get another delete message like the above.
 
Last edited:
Thank you for always uploading the enhanced version. I'm having trouble completing the compilation and trying to use it. I wanted to apply it to Champion Monster as well, so I set it up as below.

I'm trying to change BaseCreature in the BaseChampion.cs script to AbilityCreature as above and use it, but it keeps telling me to delete champion monsters that are spawning in the field as below. I was wondering if there was a way to fix it.

I'm leaving an additional message. When I delete it, create Champion Monster again, save the server, and restart the server, I get another delete message like the above.
Yes, the best way to change existing creatures from BaseCreature to AbilityCreature, first delete all spawned instances of those creatures off your server first. It'll make you delete every individual instance of that creature when you try to start it up and then have a fatal error. It'll do this until all of the saved old versions of your creature are gone.
This is because there's a difference in the save data.
You could change them back to BaseCreature, then delete any current instances of that creature, then make the change to AbilityCreature.
Or, just keep restarting the server, which will make you delete all instances of one creature at a time until all instances of those creatures are gone, then it'll start like normal.
 
Yes, the best way to change existing creatures from BaseCreature to AbilityCreature, first delete all spawned instances of those creatures off your server first. It'll make you delete every individual instance of that creature when you try to start it up and then have a fatal error. It'll do this until all of the saved old versions of your creature are gone.
This is because there's a difference in the save data.
You could change them back to BaseCreature, then delete any current instances of that creature, then make the change to AbilityCreature.
Or, just keep restarting the server, which will make you delete all instances of one creature at a time until all instances of those creatures are gone, then it'll start like normal.
If you delete, recreate, save, and compile all existing instances, you'll have the same problem. Only BaseChampion.cs monsters ask if you want to keep deleting them the same. Other monsters work well. I don't know what I'm doing wrong.
 
If you delete, recreate, save, and compile all existing instances, you'll have the same problem. Only BaseChampion.cs monsters ask if you want to keep deleting them the same. Other monsters work well. I don't know what I'm doing wrong.
The error you provided before is stating that there's an existing instance of that creature somewhere in the world. My guess is that there's some stray mobs you lost track of and just have to delete.

What happens when you delete the object by hitting y, accepting the fatal error and restarting like normal?
Do you get the same error, or does it ask you do delete a different creature each time?
 
The error you provided before is stating that there's an existing instance of that creature somewhere in the world. My guess is that there's some stray mobs you lost track of and just have to delete.

What happens when you delete the object by hitting y, accepting the fatal error and restarting like normal?
Do you get the same error, or does it ask you do delete a different creature each time?
Press y to delete the object and restart it normally, and the server works fine. And when you spawn and save the newly applied champion monster in the field, and restart the server, you're prompted again to delete the creature.
 
Press y to delete the object and restart it normally, and the server works fine. And when you spawn and save the newly applied champion monster in the field, and restart the server, you're prompted again to delete the creature.
Ohhhhh! Yeah, that's super odd... I'm not quite sure what it could be.
Try saving/restarting without any of those mobs spawned at all, and delete them off of your spawners.
Once you get a clean save and restart, then try adding them.
 
Ohhhhh! Yeah, that's super odd... I'm not quite sure what it could be.
Try saving/restarting without any of those mobs spawned at all, and delete them off of your spawners.
Once you get a clean save and restart, then try adding them.
using System;
using System.Collections.Generic;
using Server.Engines.CannedEvil;
using Server.Items;
using Server.Services.Virtues;

namespace Server.Mobiles
{
public abstract class BaseChampion : AbilityCreature
{
private int m_StatCap = Config.Get("PlayerCaps.TotalStatCap", 1800);
public BaseChampion(AIType aiType)
: this(aiType, FightMode.Closest)
{
}

public BaseChampion(AIType aiType, FightMode mode)
: base(aiType, mode, 10, 1, 0.1, 0.2)
{
ForceActiveSpeed = 0.18;

}

public BaseChampion(Serial serial)
: base(serial)
{
}
public override bool CanBeParagon { get { return true; } }
public override bool ReacquireOnMovement{ get{ return true; } }
public abstract ChampionSkullType SkullType { get; }
public abstract Type[] UniqueList { get; }
public abstract Type[] SharedList { get; }
public abstract Type[] DecorativeList { get; }
public abstract MonsterStatuetteType[] StatueTypes { get; }
public virtual bool NoGoodies
{
get
{
return false;
}
}

public virtual bool CanGivePowerscrolls { get { return true; } }

public static void GivePowerScrollTo(Mobile m, Item item, BaseChampion champ)
{
if (m == null) //sanity
return;

if (!Core.SE || m.Alive)
m.AddToBackpack(item);
else
{
if (m.Corpse != null && !m.Corpse.Deleted)
m.Corpse.DropItem(item);
else
m.AddToBackpack(item);
}

if (item is PowerScroll && m is PlayerMobile)
{
PlayerMobile pm = (PlayerMobile)m;

for (int j = 0; j < pm.JusticeProtectors.Count; ++j)
{
Mobile prot = pm.JusticeProtectors[j];

if (prot.Map != m.Map || prot.Murderer || prot.Criminal || !prot.InRange(champ, 100))
continue;

int chance = 0;

switch( VirtueHelper.GetLevel(prot, VirtueName.Justice) )
{
case VirtueLevel.Seeker:
chance = 60;
break;
case VirtueLevel.Follower:
chance = 80;
break;
case VirtueLevel.Knight:
chance = 100;
break;
}

if (chance > Utility.Random(100))
{
PowerScroll powerScroll = CreateRandomPowerScroll();

prot.SendLocalizedMessage(1049368); // You have been rewarded for your dedication to Justice!

if (!Core.SE || prot.Alive)
prot.AddToBackpack(powerScroll);
else
{
if (prot.Corpse != null && !prot.Corpse.Deleted)
prot.Corpse.DropItem(powerScroll);
else
prot.AddToBackpack(powerScroll);
}
}
}
}
}

public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);

writer.Write((int)0); // version
}

public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);

int version = reader.ReadInt();
}

public virtual Item GetArtifact()
{
double random = Utility.RandomDouble();
if (0.05 >= random)
return this.CreateArtifact(this.UniqueList);
else if (0.15 >= random)
return this.CreateArtifact(this.SharedList);
else if (0.30 >= random)
return this.CreateArtifact(this.DecorativeList);
return null;
}

public Item CreateArtifact(Type[] list)
{
if (list.Length == 0)
return null;

int random = Utility.Random(list.Length);

Type type = list[random];

Item artifact = Loot.Construct(type);

if (artifact is MonsterStatuette && this.StatueTypes.Length > 0)
{
((MonsterStatuette)artifact).Type = this.StatueTypes[Utility.Random(this.StatueTypes.Length)];
((MonsterStatuette)artifact).LootType = LootType.Regular;
}

return artifact;
}

public virtual void GivePowerScrolls()
{


List<Mobile> toGive = new List<Mobile>();
List<DamageStore> rights = GetLootingRights();

for (int i = rights.Count - 1; i >= 0; --i)
{
DamageStore ds = rights;

if (ds.m_HasRight && InRange(ds.m_Mobile, 100) && ds.m_Mobile.Map == this.Map)
toGive.Add(ds.m_Mobile);
}

if (toGive.Count == 0)
return;

for (int i = 0; i < toGive.Count; i++)
{
Mobile m = toGive;

if (!(m is PlayerMobile))
continue;

bool gainedPath = false;

int pointsToGain = 800;

if (VirtueHelper.Award(m, VirtueName.Valor, pointsToGain, ref gainedPath))
{
if (gainedPath)
m.SendLocalizedMessage(1054032); // You have gained a path in Valor!
else
m.SendLocalizedMessage(1054030); // You have gained in Valor!
//No delay on Valor gains
}
}

// Randomize - PowerScrolls
for (int i = 0; i < toGive.Count; ++i)
{
int rand = Utility.Random(toGive.Count);
Mobile hold = toGive;
toGive = toGive[rand];
toGive[rand] = hold;
}

for (int i = 0; i < ChampionSystem.PowerScrollAmount; ++i)
{
Mobile m = toGive[i % toGive.Count];

PowerScroll ps = CreateRandomPowerScroll();
m.SendLocalizedMessage(1049524); // You have received a scroll of power!

GivePowerScrollTo(m, ps, this);
}



ColUtility.Free(toGive);
}

public virtual void OnChampPopped(ChampionSpawn spawn)
{
}

public override bool OnBeforeDeath()
{
if (CanGivePowerscrolls && !NoKillAwards)
{
this.GivePowerScrolls();

if (this.NoGoodies)
return base.OnBeforeDeath();

GoldShower.DoForChamp(Location, Map);

this.PlaySound(0x550);
}

return base.OnBeforeDeath();
}

public override void OnDeath(Container c)
{

{
//TODO: Confirm SE change or AoS one too?
List<DamageStore> rights = GetLootingRights();
List<Mobile> toGive = new List<Mobile>();

for (int i = rights.Count - 1; i >= 0; --i)
{
DamageStore ds = rights;

if (ds.m_HasRight)
toGive.Add(ds.m_Mobile);
}

if (SkullType != ChampionSkullType.None)
{
if (toGive.Count > 0)
toGive[Utility.Random(toGive.Count)].AddToBackpack(new ChampionSkull(this.SkullType));
else
c.DropItem(new ChampionSkull(this.SkullType));
}

if(Core.SA)
RefinementComponent.Roll(c, 3, 0.10);
}

base.OnDeath(c);

}

public override void OnKilledBy( Mobile mob )
{
if ( mob.Player )
{
if (0.5 > Utility.RandomDouble())
{
mob.AddToBackpack(new StatCapScroll(m_StatCap + RandomStatScrollLevel()));
}

}

base.OnKilledBy( mob );
}

private static int RandomStatScrollLevel()
{
double random = Utility.RandomDouble();

if (0.01 >= random)
return 500;
else if (0.05 >= random)
return 400;
else if (0.15 >= random)
return 300;
else if (0.20 >= random)
return 200;
return 100;
}

private static PowerScroll CreateRandomPowerScroll()
{
int level;
double random = Utility.RandomDouble();

if (0.009 >= random)
level = 170;
else
if (0.2 >= random)
level = 140;
else
if (0.4 >= random)
level = 110;
else
level = 80;



return PowerScroll.CreateRandomNoCraft(level, level);
}

private static SkillMasteryPrimer CreateRandomPrimer()
{
return SkillMasteryPrimer.GetRandom();
}
}
}

The script above is the one I've changed and been using. Is there any chance that BaseChampion.cs and AbilityCreature.cs could crash? Everything else works fine. If you create a BaseChampion monster in the field, you get this problem. Ewww. It's hard


I downloaded a new version of Servuo57 and tested it with nothing on it. The same thing happens. I think it's because BaseChampion.cs
If you change it to "public act class Base Champion : AbilityCreature", something seems to be wrong. If the champion monster is in the field, it seems to get a delete message. First of all, the test I did shows that there seems to be a very difficult problem..
 
Last edited:
The script above is the one I've changed and been using. Is there any chance that BaseChampion.cs and AbilityCreature.cs could crash? Everything else works fine. If you create a BaseChampion monster in the field, you get this problem. Ewww. It's hard


I downloaded a new version of Servuo57 and tested it with nothing on it. The same thing happens. I think it's because BaseChampion.cs
If you change it to "public act class Base Champion : AbilityCreature", something seems to be wrong. If the champion monster is in the field, it seems to get a delete message. First of all, the test I did shows that there seems to be a very difficult problem..

Okay, when I changed my BaseChampion to use AbilityCreature, I had the same issue.

I made a new class, AbilityChampion, which calls AbilityCreature.This is instead of changing BaseChampion to use my script.
I used these two scripts and they compile/save fine on my end.
Hope this works, good luck!
 

Attachments

  • AbilityChampion.cs
    9.5 KB · Views: 3
  • FleshCollector.cs
    6.1 KB · Views: 3
Okay, when I changed my BaseChampion to use AbilityCreature, I had the same issue.

I made a new class, AbilityChampion, which calls AbilityCreature.This is instead of changing BaseChampion to use my script.
I used these two scripts and they compile/save fine on my end.
Hope this works, good luck!
Thank you so much. I found the cause of the problem. I didn't give Champion Monster any ability, so I kept getting delete messages. I'm so stupid. It was my mistake to try to give Champion Monster magic power later. I really appreciate your help. Besides this script, I always support and bless you for always being helpful and making good scripts.
 
Thank you so much. I found the cause of the problem. I didn't give Champion Monster any ability, so I kept getting delete messages. I'm so stupid. It was my mistake to try to give Champion Monster magic power later. I really appreciate your help. Besides this script, I always support and bless you for always being helpful and making good scripts.
I'm happy you were able to figure it out and get things working! You did uncover a bug though. you shouldn't have to add an ability for the creature to work properly. I'll look into fixing this in the future. Until then, it's good to know that's an issue.
 
I'm happy you were able to figure it out and get things working! You did uncover a bug though. you shouldn't have to add an ability for the creature to work properly. I'll look into fixing this in the future. Until then, it's good to know that's an issue.
Thank you for being happy with me. I'm glad and grateful that I was of some help.
 
Thank you for being happy with me. I'm glad and grateful that I was of some help.
Already found the bug - it's one line in AbilityCreature.
Code:
        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);
            int version = reader.ReadInt();

        int flag = reader.ReadInt();
        if (flag == 1)
        {
        m_List = new CustomAbilityList();
            m_List.Deserialize(reader);
        }
        else
        Console.WriteLine("Invalid flag during deserialization.");


        if (m_List != null)
        {
            for(int i = 0; i < m_List.CustomAbilities.Length; i++)
            {

            string ability = m_List.CustomAbilities[i].GetType().Name;
            switch(ability)
            {
the "if (m_list != null) {" wasn't there
Add that one thing to the deserialize method, and make sure to add the closing bracket "}", and that'll fix everything. You won't need to add an ability for it to work
 
Already found the bug - it's one line in AbilityCreature.
Code:
        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);
            int version = reader.ReadInt();

        int flag = reader.ReadInt();
        if (flag == 1)
        {
        m_List = new CustomAbilityList();
            m_List.Deserialize(reader);
        }
        else
        Console.WriteLine("Invalid flag during deserialization.");


        if (m_List != null)
        {
            for(int i = 0; i < m_List.CustomAbilities.Length; i++)
            {

            string ability = m_List.CustomAbilities[i].GetType().Name;
            switch(ability)
            {
the "if (m_list != null) {" wasn't there
Add that one thing to the deserialize method, and make sure to add the closing bracket "}", and that'll fix everything. You won't need to add an ability for it to work
You are a wonderful person! I am so happy for the super quick feedback!
 
I have a question. If you enter multiple magic tricks into a single monster and let them use them, they pour out multiple magic tricks at once. Can we set the time to use magic individually? For example, Firebolt will use it 3 seconds after the monster recognizes an attack, and other magic will use it 5 seconds later.
 
I have a question. If you enter multiple magic tricks into a single monster and let them use them, they pour out multiple magic tricks at once. Can we set the time to use magic individually? For example, Firebolt will use it 3 seconds after the monster recognizes an attack, and other magic will use it 5 seconds later.
Each ability has a chance to trigger like this:
Code:
        public override double TriggerChance { get { return 0.8; } }

You could modify those chances to make them less likely to occur, and less likely to be used at once.

The scale is 0.0 to 1.0 where 1.0 is 100% chance to use them off cooldown, 0.8 is 80% and so on.

I'm going to look at CustomAbilitiesList and see if I can put some kind of extra cooldown in there as well.
 
Each ability has a chance to trigger like this:
Code:
        public override double TriggerChance { get { return 0.8; } }

You could modify those chances to make them less likely to occur, and less likely to be used at once.

The scale is 0.0 to 1.0 where 1.0 is 100% chance to use them off cooldown, 0.8 is 80% and so on.

I'm going to look at CustomAbilitiesList and see if I can put some kind of extra cooldown in there as well.
Thank you always!! It's not urgent, so you can take your time.
 
Back