Xen

Member
Friends, Mates and Camrades, whatever,

I want to propose you a different way to generate Items, spells, Mobs without need for creating 1 script for each one of them. I'm going to propose you a good system to have Items, Spells and Mobs at runtime and edit them without writing any line of code.


1) We will use in this explication Modules -> BaseModules written by @Insanity and present in our ServUO framework. It means that this approach can be used only in ServUO (it could be a very huge difference between ServUO and RunUO)

This is a Scheme about how we will use Modules in our pattern :

adocs_google_com_drawings_d_1ziKwA9B877VndnxMo32WBK_vlpmhpxBlgca5a179189c4ae60c4bbd3e8de6bc378.png

2) We will generate a Definition class for each kind of stuff we will need to generate:
  • Weapons
  • Armors
  • Spells
  • Mobs
  • Talismans
  • etc... etc.
What will be the differences between now and before? Simple : All weapons will have only 1 definition class, all spells will have only one definition class (or as many as we need). all armors will have only a defintion class and so on.

I will illustrate you only one example about a knife:


adocs_google_com_drawings_d_1og_JLDnjXXeGIpGz34MoqqSd4y18OHoAca252a7ad6f3353695edcd5a06ed636ca.png

We can have a "definition" class which will include all props we need to generate all weapons we want.

adocs_google_com_drawings_d_118kRLGzR_SLL11ynneTUANTTrtt_ooifY20b2aaa40c6f754aa38feabd7e844f8f.png


we can divide raw data in more modules or just use only one module as we like. It's not much important, it's important only what we want to do next.


3) Now we need a way to manage all definitions we want to create. I.e. we need a Core which will handle all the data we put inside it and generates items when the proper command is called.



adocs_google_com_drawings_d_1YYPBBhQz6MxDIE8Yooj_xYmiN7bvOR9By4f294697ab4a7867cbc6eac25adbba1d.png

Each definition will have its own "string" keyword, so we can put it in a Dictionary. When the dictionary it's called it will grant the access to the right istance of the definition we need.



4) Class Modification or how to write the right class in the right way?

As I wrote before, each class will be rapresentative of all its istances, I.E. it will be a class to rapresent all melee weapons (or ranged weapons too it depends by you) each for all armors and so on.

And each class will have a reference to the right istance of its own definition.


adocs_google_com_drawings_d_18ZIP3wtX6Y5a_cDiligC3GtSL4Wdefn3O8ed219c94bf2b42ca02d06e5ed18475f.png
Always speaking about our knife, we will have only one class for each weapon and we just will change data inside our definitions and its own keyword.


5)

Ok let's suppose that we want to generare our Knife and we want to call it "StellarKnife"

adocs_google_com_drawings_d_12X_opGgnBtbY7NLkMgVHKOm_D_748FS90339290404b7b8f0ef54561b96a2664d1.png



Pros :
  • Items / Weapons / spells generation will be faster
  • It will allow you to avoid having 20000 scripts which have only few different stuffs

Sample : Axe and Double Axe right now have the same identical kind of class BUT they have different values. In a normal class-oriented paradigm it could not be done.

Double Axe
Code:
using System;

namespace Server.Items
{
    [FlipableAttribute(0xf4b, 0xf4c)]
    public class DoubleAxe : BaseAxe
    {
        [Constructable]
        public DoubleAxe()
            : base(0xF4B)
        {
            this.Weight = 8.0;
        }

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

        public override WeaponAbility PrimaryAbility
        {
            get
            {
                return WeaponAbility.DoubleStrike;
            }
        }
        public override WeaponAbility SecondaryAbility
        {
            get
            {
                return WeaponAbility.WhirlwindAttack;
            }
        }
        public override int AosStrengthReq
        {
            get
            {
                return 45;
            }
        }
        public override int AosMinDamage
        {
            get
            {
                return 15;
            }
        }
        public override int AosMaxDamage
        {
            get
            {
                return 17;
            }
        }
        public override int AosSpeed
        {
            get
            {
                return 33;
            }
        }
        public override float MlSpeed
        {
            get
            {
                return 3.25f;
            }
        }
        public override int OldStrengthReq
        {
            get
            {
                return 45;
            }
        }
        public override int OldMinDamage
        {
            get
            {
                return 5;
            }
        }
        public override int OldMaxDamage
        {
            get
            {
                return 35;
            }
        }
        public override int OldSpeed
        {
            get
            {
                return 37;
            }
        }
        public override int InitMinHits
        {
            get
            {
                return 31;
            }
        }
        public override int InitMaxHits
        {
            get
            {
                return 110;
            }
        }
        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();
        }
    }
}

Axe
Code:
using System;

namespace Server.Items
{
    [FlipableAttribute(0xF49, 0xF4a)]
    public class Axe : BaseAxe
    {
        [Constructable]
        public Axe()
            : base(0xF49)
        {
            this.Weight = 4.0;
        }

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

        public override WeaponAbility PrimaryAbility
        {
            get
            {
                return WeaponAbility.CrushingBlow;
            }
        }
        public override WeaponAbility SecondaryAbility
        {
            get
            {
                return WeaponAbility.Dismount;
            }
        }
        public override int AosStrengthReq
        {
            get
            {
                return 35;
            }
        }
        public override int AosMinDamage
        {
            get
            {
                return 14;
            }
        }
        public override int AosMaxDamage
        {
            get
            {
                return 16;
            }
        }
        public override int AosSpeed
        {
            get
            {
                return 37;
            }
        }
        public override float MlSpeed
        {
            get
            {
                return 3.00f;
            }
        }
        public override int OldStrengthReq
        {
            get
            {
                return 35;
            }
        }
        public override int OldMinDamage
        {
            get
            {
                return 6;
            }
        }
        public override int OldMaxDamage
        {
            get
            {
                return 33;
            }
        }
        public override int OldSpeed
        {
            get
            {
                return 37;
            }
        }
        public override int InitMinHits
        {
            get
            {
                return 31;
            }
        }
        public override int InitMaxHits
        {
            get
            {
                return 110;
            }
        }
        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();
        }
    }
}


  • Memory Costs, less scrips means less compilation time, less need of reflection usage and less memory usage (referecences costs only 64 bits).
  • Easier to manage to not-experted people (handling a gump it's easeir than managing a script) and it can be done via client without needs of recompilation
  • Serialization can be done via XML or JSon to share Items /spells /Mobs etc...
  • Old style (script-based) generation for very customized items can be mantained because it doesn't need any change.
  • It can be a different approach to make people understand that ServUO is not RunUO.
CONS:
  • It needs a gump system to make all this work well.
  • It needs some way to handle (via gump) lists and collections.
  • It needs some start-work to make it be worth. It needs some experience to be implemented
  • It will be a very different system than RunUO and it could have some incompatibility issues with it
  • Very customized script will need to be handled in the old way or it'll be needed to write down more difficult code to have different behavior for custom weapons, spells, etc...
  • It will be needed some wolkaroud some Class attribute [Flippable] or [Constructable] which are written on Classes :( instead in some property inside the class but it's not so impossible to handle this problem.
  • Craft system should be updated (see the point before)


What do you think about? Would you like to help me? Do you see what i tried to explain? Do you think it could be helpfull to ServUO projects?

Thanks for comments
 
Last edited:
It seems like a good idea in theory, but I've never had an issue with speed or memory in regard to creating items, mobs, or even compilation. I have a ton of custom code, and heavily modified core, and compilation rarely takes more than 10-15 seconds after adding a new system. When its a clean restart without new code added, its normally fully running from dbl click in less then 5 seconds. So to me, I'm not sure reinventing the wheel is worth the effort. Just my personal opinion though.
 
It seems like a good idea in theory, but I've never had an issue with speed or memory in regard to creating items, mobs, or even compilation. I have a ton of custom code, and heavily modified core, and compilation rarely takes more than 10-15 seconds after adding a new system. When its a clean restart without new code added, its normally fully running from dbl click in less then 5 seconds. So to me, I'm not sure reinventing the wheel is worth the effort. Just my personal opinion though.

PROS:
  • Old style (script-based) generation for very customized can be mantained because it doesn't need any change.
It means that all your very customized code will stay there untouched as before.
You'll be able to mantain your own code as you did before. It will be only a "service" that will be granted by ServUO like Modules, Cores, Services and so on.


Now let's suppose you want to increase the weight of all "long sword" items in your shard for present and future usage (craft too).
  1. You need to shutdown you shard
  2. Edit your script
  3. restart your shard (recompile)
In my way you can :
  1. [edit "LongSword"
  2. put the new value in the gump
And all long swords in your shard will have the new value.

if you want to add a new weapon, in the old way

  1. Shutdown the shard
  2. Create new Class
  3. Insert values (awfull pratice)
  4. save
  5. recompile
  6. restart
This could be ok if you have a shard with few people connected but in pratice it becomes a awful pratice that could be avoided

In new way it becames :

  1. [CreateNewItem ItemName //it generates the definition
  2. [edit ItemName //(and put your values in the gump)
  3. [Generate ItemName //it's the same that Add command or maybe we can mod add command too
I can understand that it could be difficult to generate some more gump but once we will do that, it will be very easy and fast! It can work with _spells_ and _quest_items_ too with some work ;).
 
Last edited:
I love the idea of being able to create a new object directly in-game with no need to restart. I don't know that it needs to totally replace some of the current scripts but could be added alongside the traditional scripts (giving people the option of doing it either way).

I can think of a million ways this can be useful, especially for events.

Some concerns: (you may have addressed some of these and I may not have understood)

1. Would be difficult to add the new objects to the craft system.
2. Would be easy to lose track of the items created in this manner, would we need a command to interface with the dictionary for removal or editing of objects?
3. Could you still use xmlattachments to the newly created objects?
4. What happens when someone tries to create a new object with the same name as an existing object?
5. If I change the properties of "StellarKnife" what happens to all instances of StellarKnife already in the game? Will it update only on load?

Despite these few concerns, I totally love the idea!
 
I don't know that it needs to totally replace some of the current scripts but could be added alongside the traditional scripts (giving people the option of doing it either way).

It doesn't need any change about our actual system, it's just a external mod (or a walkaround if you prefer)

1. Would be difficult to add the new objects to the craft system.
It should be done a update of that system, i don't think it could be impossibile to do, but i think some expert should wite a wiki page about that system so it'll be easier to mod.

2. Would be easy to lose track of the items created in this manner, would we need a command to interface with the dictionary for removal or editing of objects?
just a command and a related gump should be enough.
3. Could you still use xmlattachments to the newly created objects?
It depends how it works, but if you can mod it to work properly with the new system it could be good. I've never used it, you should ask to its writer but i think in that case you could even avoid to use them adding xml properties directly in definitions if you want. Whaterver, we will see about them i really never used them.

4. What happens when someone tries to create a new object with the same name as an existing object?
The system will give you a "exception" then it will be written in your client console "the item with that name already exists, please change keyword". It's easy to manage ;).

5. If I change the properties of "StellarKnife" what happens to all instances of StellarKnife already in the game? Will it update only on load?
Exactly the same thing that could happen if you change the "stellar Knife" class, if that property is related to the istance : it won't change nothing else it will be updated in all istances.

Code:
public class Weapon{
Def _def;
public int Weight { get{return _def.Weight;}} //it will be updated

public Weapon(Def _def)
{
hp = random(_def.MinHp, _def.MaxHp); //it won't be touched
 
}
}
 
Last edited:
Back