Modding:Block and Item Interactions: Difference between revisions

From Vintage Story Wiki
No edit summary
No edit summary
(5 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
This tutorial should introduce you into the basics of custom interactions. We will create a magic wand which should spawn particles when holding right click.
Custom collectible, will be available soon.


== Preparations ==
== Preparations ==


I highly recommend to read about [[Advanced Items|The Item Class]] first. Additionally you can download the assets [http://wiki.vintagestory.at/images/4/4d/MagicWand_-_No_CS_File.zip here].
I highly recommend to read about [[Advanced Items|The Item Class]] first. Additionally you can download the assets [https://wiki.vintagestory.at/images/4/4d/MagicWand_-_No_CS_File.zip here].


Furthermore we need to create and register the item class ...
All of this should be familiar to you, creating and registering the item class ...


<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
Line 28: Line 27:
== Adding particles ==
== Adding particles ==


Now we need to implement the actual spawning function. First of all we need to specify that the player can "use" this tool, therefore we return <code>true</code> ...
Now we need to implement the interact function. First of all we need to specify that the player can "use" this tool, therefore we need to return <code>true</code> ...


<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
         public override bool OnBeginInteract(IItemSlot slot, IEntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
         public override bool OnHeldInteractStart(IItemSlot slot, IEntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
         {
         {
             return true;
             return true;
Line 37: Line 36:
</syntaxhighlight>
</syntaxhighlight>


The <code>OnInteracting</code> allows is to do something per tick while the player is using the item ...
The method <code>OnHeldInteractStep</code> allows us to spawn particles per tick while the player is using the item, but it would be better to implement an animation first. Particles should spawn after the animation is done ...


<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
         public override bool OnInteracting(float secondsUsed, IItemSlot slot, IEntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
         public override bool OnHeldInteractStep(float secondsUsed, IItemSlot slot, IEntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
         {
         {
             if (byEntity.World is IClientWorldAccessor)
             if (byEntity.World is IClientWorldAccessor)
Line 64: Line 63:
[[File:Magic Stick Interact.gif|300px]]
[[File:Magic Stick Interact.gif|300px]]


So let's mess around with particles. This will create a static particle type ...
So let's start to mess around with particles, therefore we need a static particle type ...


<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
Line 82: Line 81:
</syntaxhighlight>
</syntaxhighlight>


Particles should spawn once the stick animation is completed. This will be the case after <code>0.6</code> seconds ...
Particles should spawn once the animation is completed. This will be the case after <code>0.6</code> seconds ...


<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
                 if (secondsUsed > 0.6)
                 if (secondsUsed > 0.6)
                 {
                 {
                    //Spawn particles
                }
</syntaxhighlight>
I suggest to read the tutorial about [[Simple Particles]] first. This code will spawn particles in front of the player with a randomized color and a sinus evolving size ...
<syntaxhighlight lang="c#">
                     Vec3d pos =
                     Vec3d pos =
                             byEntity.Pos.XYZ.Add(0, byEntity.EyeHeight(), 0)
                             byEntity.Pos.XYZ.Add(0, byEntity.EyeHeight(), 0)
Line 101: Line 107:
                     particles.SizeEvolve = EvolvingNatFloat.create(EnumTransformFunction.SINUS, 10);
                     particles.SizeEvolve = EvolvingNatFloat.create(EnumTransformFunction.SINUS, 10);
                     byEntity.World.SpawnParticles(particles);
                     byEntity.World.SpawnParticles(particles);
                }
</syntaxhighlight>
</syntaxhighlight>


If we put everything together the <code>OnInteracting</code> method will look like this ...
If we put everything together the <code>OnHeldInteractStep</code> method will look like this ...


<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
         public override bool OnInteracting(float secondsUsed, IItemSlot slot, IEntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
         public override bool OnHeldInteractStep(float secondsUsed, IItemSlot slot, IEntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
         {
         {
             if (byEntity.World is IClientWorldAccessor)
             if (byEntity.World is IClientWorldAccessor)
Line 146: Line 151:
</syntaxhighlight>
</syntaxhighlight>


You can read more about particles and how to use them [[Simple Particles|here]].
== Testing ==


== Testing ==
Now we can run our first test, doesn't it look beautiful?


<youtube>bTPXL97Gfns</youtube>
<youtube>bTPXL97Gfns</youtube>


== Download ==
== Download ==
Feel free to try it out yourself:
[https://wiki.vintagestory.at/images/3/38/MagicWand.zip MagicWand.zip]
{{Navbox/modding|Vintage Story}}

Revision as of 12:15, 7 January 2019

This tutorial should introduce you into the basics of custom interactions. We will create a magic wand which should spawn particles when holding right click.

Preparations

I highly recommend to read about The Item Class first. Additionally you can download the assets here.

All of this should be familiar to you, creating and registering the item class ...

    public class Magic : ModBase
    {

        public override void Start(ICoreAPI api)
        {
            base.Start(api);
            api.RegisterItemClass("ItemMagicWand", typeof(ItemMagicWand));
        }

    }

    public class ItemMagicWand : Item
    {
        
    }

Adding particles

Now we need to implement the interact function. First of all we need to specify that the player can "use" this tool, therefore we need to return true ...

        public override bool OnHeldInteractStart(IItemSlot slot, IEntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
        {
            return true;
        }

The method OnHeldInteractStep allows us to spawn particles per tick while the player is using the item, but it would be better to implement an animation first. Particles should spawn after the animation is done ...

        public override bool OnHeldInteractStep(float secondsUsed, IItemSlot slot, IEntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
        {
            if (byEntity.World is IClientWorldAccessor)
            {
                ModelTransform tf = new ModelTransform();
                tf.EnsureDefaultValues();

                float speed = 5 + 20 * Math.Max(0, secondsUsed - 0.25f);
                float start = secondsUsed * 120;
                float rotationZ = Math.Max(-110, start - Math.Max(0, secondsUsed - 0.25f) * 90 * speed);


                tf.Origin.Set(0, 2f, 0);
                tf.Translation.Set(0, Math.Max(-1f, -5 * Math.Max(0, secondsUsed - 0.25f)), 0);
                tf.Rotation.Z = rotationZ;
                byEntity.Controls.UsingHeldItemTransform = tf;
            }
        }

Holding rightclick ...

Magic Stick Interact.gif

So let's start to mess around with particles, therefore we need a static particle type ...

        public static SimpleParticleProperties particles = new SimpleParticleProperties(
                    1, 1,
                    ColorUtil.ColorFromArgb(50, 220, 220, 220),
                    new Vec3d(),
                    new Vec3d(),
                    new Vec3f(-0.25f, 0.1f, -0.25f),
                    new Vec3f(0.25f, 0.1f, 0.25f),
                    1.5f,
                    -0.075f,
                    0.25f,
                    0.25f,
                    EnumParticleModel.Quad
                );

Particles should spawn once the animation is completed. This will be the case after 0.6 seconds ...

                if (secondsUsed > 0.6)
                {
                    //Spawn particles
                }

I suggest to read the tutorial about Simple Particles first. This code will spawn particles in front of the player with a randomized color and a sinus evolving size ...

                    Vec3d pos =
                            byEntity.Pos.XYZ.Add(0, byEntity.EyeHeight(), 0)
                            .Ahead(1f, byEntity.Pos.Pitch, byEntity.Pos.Yaw)
                        ;

                    Vec3f speedVec = new Vec3d(0, 0, 0).Ahead(5, byEntity.Pos.Pitch, byEntity.Pos.Yaw).ToVec3f();
                    particles.minVelocity = speedVec;
                    Random rand = new Random();
                    particles.color = ColorUtil.ToRGBABytes(ColorUtil.ColorFromArgb(255, rand.Next(0, 255), rand.Next(0, 255), rand.Next(0, 255)));
                    particles.minPos = pos.AddCopy(-0.05, -0.05, -0.05);
                    particles.addPos.Set(0.1, 0.1, 0.1);
                    particles.minSize = 0.1F;
                    particles.SizeEvolve = EvolvingNatFloat.create(EnumTransformFunction.SINUS, 10);
                    byEntity.World.SpawnParticles(particles);

If we put everything together the OnHeldInteractStep method will look like this ...

        public override bool OnHeldInteractStep(float secondsUsed, IItemSlot slot, IEntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
        {
            if (byEntity.World is IClientWorldAccessor)
            {
                ModelTransform tf = new ModelTransform();
                tf.EnsureDefaultValues();

                float speed = 5 + 20 * Math.Max(0, secondsUsed - 0.25f);
                float start = secondsUsed * 120;
                float rotationZ = Math.Max(-110, start - Math.Max(0, secondsUsed - 0.25f) * 90 * speed);


                tf.Origin.Set(0, 2f, 0);
                tf.Translation.Set(0, Math.Max(-1f, -5 * Math.Max(0, secondsUsed - 0.25f)), 0);
                tf.Rotation.Z = rotationZ;
                byEntity.Controls.UsingHeldItemTransform = tf;

                if (secondsUsed > 0.6)
                {
                    Vec3d pos =
                            byEntity.Pos.XYZ.Add(0, byEntity.EyeHeight(), 0)
                            .Ahead(1f, byEntity.Pos.Pitch, byEntity.Pos.Yaw)
                        ;

                    Vec3f speedVec = new Vec3d(0, 0, 0).Ahead(5, byEntity.Pos.Pitch, byEntity.Pos.Yaw).ToVec3f();
                    particles.minVelocity = speedVec;
                    Random rand = new Random();
                    particles.color = ColorUtil.ToRGBABytes(ColorUtil.ColorFromArgb(255, rand.Next(0, 255), rand.Next(0, 255), rand.Next(0, 255)));
                    particles.minPos = pos.AddCopy(-0.05, -0.05, -0.05);
                    particles.addPos.Set(0.1, 0.1, 0.1);
                    particles.minSize = 0.1F;
                    particles.SizeEvolve = EvolvingNatFloat.create(EnumTransformFunction.SINUS, 10);
                    byEntity.World.SpawnParticles(particles);
                }
            }
            return true;
        }

Testing

Now we can run our first test, doesn't it look beautiful?

Download

Feel free to try it out yourself:

MagicWand.zip


Icon Sign.png

Wondering where some links have gone?
The modding navbox is going through some changes! Check out Navigation Box Updates for more info and help finding specific pages.