Modding:Block and Item Interactions: Difference between revisions

From Vintage Story Wiki
No edit summary
No edit summary
(6 intermediate revisions by 2 users not shown)
Line 1: Line 1:
__FORCETOC__
__FORCETOC__
''Mod written for version 1.9 of Vintage Story''
{{GameVersion|1.13}}


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.
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 ==
= Preparations =


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].
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].
Line 66: Line 66:
         public static SimpleParticleProperties particles = new SimpleParticleProperties(
         public static SimpleParticleProperties particles = new SimpleParticleProperties(
                     1, 1,
                     1, 1,
                     ColorUtil.ColorFromArgb(50, 220, 220, 220),
                     ColorUtil.ColorFromRgba(220, 220, 220, 50),
                     new Vec3d(),
                     new Vec3d(),
                     new Vec3d(),
                     new Vec3d(),
Line 92: Line 92:
<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
                     Vec3d pos =
                     Vec3d pos =
                             byEntity.Pos.XYZ.Add(0, byEntity.EyeHeight(), 0)
                             byEntity.Pos.XYZ.Add(0, byEntity.LocalEyePos.Y, 0)
                             .Ahead(1f, byEntity.Pos.Pitch, byEntity.Pos.Yaw)
                             .Ahead(1f, byEntity.Pos.Pitch, byEntity.Pos.Yaw)
                         ;
                         ;


                     Vec3f speedVec = new Vec3d(0, 0, 0).Ahead(5, byEntity.Pos.Pitch, byEntity.Pos.Yaw).ToVec3f();
                     Vec3f speedVec = new Vec3d(0, 0, 0).Ahead(5, byEntity.Pos.Pitch, byEntity.Pos.Yaw).ToVec3f();
                     particles.minVelocity = speedVec;
                     particles.MinVelocity = speedVec;
                     Random rand = new Random();
                     Random rand = new Random();
                     particles.color = ColorUtil.ToRGBABytes(ColorUtil.ColorFromArgb(255, rand.Next(0, 255), rand.Next(0, 255), rand.Next(0, 255)));
                     particles.Color = ColorUtil.ColorFromRgba(rand.Next(0, 255), rand.Next(0, 255), rand.Next(0, 255), 255);
                     particles.minPos = pos.AddCopy(-0.05, -0.05, -0.05);
                     particles.MinPos = pos.AddCopy(-0.05, -0.05, -0.05);
                     particles.addPos.Set(0.1, 0.1, 0.1);
                     particles.AddPos.Set(0.1, 0.1, 0.1);
                     particles.minSize = 0.1F;
                     particles.MinSize = 0.1F;
                     particles.SizeEvolve = EvolvingNatFloat.create(EnumTransformFunction.SINUS, 10);
                     particles.SizeEvolve = EvolvingNatFloat.create(EnumTransformFunction.SINUS, 10);
                     byEntity.World.SpawnParticles(particles);
                     byEntity.World.SpawnParticles(particles);
Line 124: Line 124:
                 {
                 {
                     Vec3d pos =
                     Vec3d pos =
                             byEntity.Pos.XYZ.Add(0, byEntity.EyeHeight, 0)
                             byEntity.Pos.XYZ.Add(0, byEntity.LocalEyePos.Y, 0)
                             .Ahead(1f, byEntity.Pos.Pitch, byEntity.Pos.Yaw)
                             .Ahead(1f, byEntity.Pos.Pitch, byEntity.Pos.Yaw)
                         ;
                         ;


                     Vec3f speedVec = new Vec3d(0, 0, 0).Ahead(5, byEntity.Pos.Pitch, byEntity.Pos.Yaw).ToVec3f();
                     Vec3f speedVec = new Vec3d(0, 0, 0).Ahead(5, byEntity.Pos.Pitch, byEntity.Pos.Yaw).ToVec3f();
                     particles.minVelocity = speedVec;
                     particles.MinVelocity = speedVec;
                     Random rand = new Random();
                     Random rand = new Random();
                     particles.color = ColorUtil.ToRgba(255, rand.Next(0, 255), rand.Next(0, 255), rand.Next(0, 255));
                     particles.Color = ColorUtil.ColorFromRgba(rand.Next(0, 255), rand.Next(0, 255), rand.Next(0, 255), 255);
                     particles.minPos = pos.AddCopy(-0.05, -0.05, -0.05);
                     particles.MinPos = pos.AddCopy(-0.05, -0.05, -0.05);
                     particles.addPos.Set(0.1, 0.1, 0.1);
                     particles.AddPos.Set(0.1, 0.1, 0.1);
                     particles.minSize = 0.1F;
                     particles.MinSize = 0.1F;
                     particles.SizeEvolve = EvolvingNatFloat.create(EnumTransformFunction.SINUS, 10);
                     particles.SizeEvolve = EvolvingNatFloat.create(EnumTransformFunction.SINUS, 10);
                     byEntity.World.SpawnParticles(particles);
                     byEntity.World.SpawnParticles(particles);
Line 149: Line 149:
<youtube>bTPXL97Gfns</youtube>
<youtube>bTPXL97Gfns</youtube>


== Download ==
= Mod Download =


Feel free to try it out yourself:
Feel free to try it out yourself:

Revision as of 13:56, 6 October 2020

This page was last verified for Vintage Story version 1.13.


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 : ModSystem
    {

        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 set handling to handled ...

        public override void OnHeldInteractStart(ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel, bool firstEvent, ref EnumHandHandling handling)
        {
            handling = EnumHandHandling.Handled;
        }

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, ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
        {
            if (byEntity.World is IClientWorldAccessor)
            {
                ModelTransform tf = new ModelTransform();
                tf.EnsureDefaultValues();

                tf.Origin.Set(0, -1, 0);
                tf.Rotation.Z = Math.Min(30, secondsUsed * 40);
                byEntity.Controls.UsingHeldItemTransformAfter = tf;
            }
            return true;
        }

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.ColorFromRgba(220, 220, 220, 50),
                    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.LocalEyePos.Y, 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.ColorFromRgba(rand.Next(0, 255), rand.Next(0, 255), rand.Next(0, 255), 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, ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
        {
            if (byEntity.World is IClientWorldAccessor)
            {
                ModelTransform tf = new ModelTransform();
                tf.EnsureDefaultValues();

                tf.Origin.Set(0, -1, 0);
                tf.Rotation.Z = Math.Min(30, secondsUsed * 40);
                byEntity.Controls.UsingHeldItemTransformAfter = tf;

                if (secondsUsed > 0.6)
                {
                    Vec3d pos =
                            byEntity.Pos.XYZ.Add(0, byEntity.LocalEyePos.Y, 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.ColorFromRgba(rand.Next(0, 255), rand.Next(0, 255), rand.Next(0, 255), 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?

Mod Download

Feel free to try it out yourself:

Here is my version:


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.

Modding
Modding Introduction Getting Started Theme Pack
Content Modding Content Mods Developing a Content Mod Basic Tutorials Intermediate Tutorials Advanced Tutorials Content Mod Concepts
Code Modding Code Mods Setting up your Development Environment
Property Overview ItemEntityBlockBlock BehaviorsBlock ClassesBlock EntitiesBlock Entity BehaviorsWorld properties
Workflows & Infrastructure Modding Efficiency TipsMod-engine compatibilityMod ExtensibilityVS Engine
Additional Resources Community Resources Modding API Updates Programming Languages List of server commandsList of client commandsClient startup parametersServer startup parameters
Example ModsAPI DocsGitHub Repository