Modding:Code Tutorial Simple Item: Difference between revisions

From Vintage Story Wiki
 
Line 106: Line 106:
Note that the value of this property is identical to the value we used in the ''RegisterItemClass'' function. This is how the game links the JSON asset files to your code's registered classes.
Note that the value of this property is identical to the value we used in the ''RegisterItemClass'' function. This is how the game links the JSON asset files to your code's registered classes.


== Testing the Block Class ==
== Testing the Item Class ==
Press F5 again to run the game with the mod. Remember to set the game to windowed mode by pressing F11. Find the thorns blade in the creative menu, and use it to attack an entity.
Press F5 again to run the game with the mod. Remember to set the game to windowed mode by pressing F11. Find the thorns blade in the creative menu, and use it to attack an entity.After doing so, take a look at the console that opened when launching the game. You should be able to see the following logs:<syntaxhighlight>
 
 
 
After doing so, take a look at the console that opened when launching the game. You should be able to see the following logs:<syntaxhighlight>
[Client Event] Got attack with thorns blade!
[Client Event] Got attack with thorns blade!
[Server Event] Got attack with thorns blade!
[Server Event] Got attack with thorns blade!
Line 119: Line 115:


== Thorns Blade Functionality ==
== Thorns Blade Functionality ==
You now need to add the real functionality for the thorns blade. Remove the line of code that logs the attack event, since you don't need that anymore. Your code should look like the following. Feel free to copy and paste this, as it contains some useful code comments too.  
You now need to add the real functionality for the thorns blade. Remove the line of code that logs the attack event, since you don't need that anymore. Your code should look like the following. Feel free to copy and paste this, as it contains some useful code comments too.
{| class="wikitable mw-collapsible mw-collapsed"
{| class="wikitable mw-collapsible mw-collapsed"
|ItemThornsBlade.cs
|ItemThornsBlade.cs
Line 150: Line 146:
</syntaxhighlight>
</syntaxhighlight>
|}
|}
Note that any further code in this function can be placed above or below the 'base' call. In this case, the order does not matter.
=== Reflecting Damage ===
=== Reflecting Damage ===
To inflict damage on an entity, there are two small steps:
To inflict damage on an entity, there are two small steps:
Line 156: Line 154:
# The damage source must be inflicted on the entity using the Entity.ReceiveDamage function.
# The damage source must be inflicted on the entity using the Entity.ReceiveDamage function.


Before you can inflict damage on an entity, you must create a damage source. This includes the type of damage, and can contain information about where the damage has come from. Note that it does not contain the amount of damage.<syntaxhighlight lang="csharp">
DamageSource damage = new DamageSource()
{
    Type = EnumDamageType.PiercingAttack,
    CauseEntity = byEntity
};
</syntaxhighlight>
This creates a new instance of damage source called 'damage'. Type can be any instance of [https://github.com/anegostudios/vsapi/blob/cad83424ee89915ef206d0b23845af0a4ef72348/Common/Combat/EnumDamageType.cs#L3 EnumDamageType], but for this purpose you should use PiercingAttack. CauseEntity is the entity that caused the damage, which should be whatever is using our sword.


So, add the following block inside the function:<syntaxhighlight lang="csharp">
Now the damage source is created, you need to inflict it upon the entity. The entity that used the item is 'byEntity', so you'll want to damage them:<syntaxhighlight lang="csharp">
if (isImpact && facing.IsVertical)
byEntity.ReceiveDamage(damage, 0.25f);
{
   
}
</syntaxhighlight>Now, you need to flip the motion of the entity.
To do this, you can change the value at ''entity.Pos.Motion.Y.'' Add the following code inside the ''if'' block.<syntaxhighlight lang="csharp">
entity.Pos.Motion.Y *= -0.8f;
</syntaxhighlight>This is a quicker way of writing:<syntaxhighlight lang="csharp">
entity.Pos.Motion.Y = entity.Pos.Motion.Y * -0.8f;
</syntaxhighlight>
</syntaxhighlight>
Multiplying by -0.8 will result in reversing the velocity, and reducing it by 20%. Feel free to play with this value to see some different effects.
This will inflict 0.25 points of damage onto the entity, using our 'damage' instance we just created.And that's it. When the item is used to attack, 0.25 points of damage will be inflicted on the player using the weapon.


The final script should look like the following:
The full code should be as follows:
{| class="wikitable mw-collapsible mw-collapsed"
{| class="wikitable mw-collapsible mw-collapsed"
|BlockTrampoline.cs
|ItemThornsBlade.cs
|-
|-
|<syntaxhighlight lang="csharp">
|<syntaxhighlight lang="csharp">
//Here are the imports for this script. Most of these will add automatically.
using Vintagestory.API.Common;
using Vintagestory.API.Common;
using Vintagestory.API.Common.Entities;
using Vintagestory.API.Common.Entities;
using Vintagestory.API.MathTools;


/*
namespace VSTutorial.Items
* The namespace the class will be in. This is essentially the folder the script is found in.
* If you need to use the BlockTrampoline class in any other script, you will have to add 'using VSTutorial.Blocks' to that script.
*/
namespace VSTutorial.Blocks
{
{
     /*
     /*
    * The class definition. Here, you define BlockTrampoline as a child of Block, which
    * As this is an item, you need to inherit the Item class. This gives access to functions within Item, and CollectibleObject.
     * means you can 'override' many of the functions within the general Block class.  
    * Take a look at https://apidocs.vintagestory.at/api/Vintagestory.API.Common.Item.html#methods and
    */
     *   https://apidocs.vintagestory.at/api/Vintagestory.API.Common.CollectibleObject.html#methods for all the methods that can be overriden.
     internal class BlockTrampoline : Block
    */
     internal class ItemThornsBlade : Item
     {
     {
         public override void OnEntityCollide(IWorldAccessor world, Entity entity, BlockPos pos, BlockFacing facing, Vec3d collideSpeed, bool isImpact)
        /*
        * This function is called whenever this item is used by an entity to attack another entity.
        * You have access to the world, the entity who is attacking, the entity who is being attacked, and the held item's data.
        */
         public override void OnAttackingWith(IWorldAccessor world, Entity byEntity, Entity attackedEntity, ItemSlot itemslot)
         {
         {
             if (isImpact && facing.IsVertical)
             DamageSource damage = new DamageSource()
             {
             {
                 entity.Pos.Motion.Y *= -0.8f;
                 Type = EnumDamageType.PiercingAttack,
             }
                CauseEntity = byEntity
            };
            byEntity.ReceiveDamage(damage, 0.25f);
             base.OnAttackingWith(world, byEntity, attackedEntity, itemslot);           
         }
         }
     }
     }
}
}
</syntaxhighlight>
</syntaxhighlight>
|}
|}
Give it a test! Falling onto your trampoline block should cause you to bounce!
Go ahead and test the new sword. You'll need to be in survival mode, but you should find that hitting an entity will also inflict damage on yourself.


== Conclusion ==
== Conclusion ==
Congratulations, you've created, registered and tested a new block class! Although it's been a long tutorial, you've covered many topics here that will give you a great understanding of how coding for Vintage Story works.
Congratulations, you've created, registered and tested a new item class!  


=== Next Steps... ===
=== Next Steps... ===
If you want to test your knowledge consider doing the tasks under the ''Going Further'' section below.  
If you want to test your knowledge consider doing the tasks under the ''Going Further'' section below.  


When you're ready, take a look at the next tutorial. This will show you how to give extra functionality to an item.
When you're ready, take a look at the next tutorial. This will show you how to register and add commands into the game!


== Going Further ==
== Going Further ==
Want to make some additional changes to this mod? Try and achieve the following things!
Want to make some additional changes to this mod? Try and achieve the following things!


Make the trampoline super bouncy.
Currently, the sword will damage you even if it is used on mobs that are dead. Make it inflict damage only if the entity being attacked is alive.
{| class="wikitable mw-collapsible mw-collapsed"
{| class="wikitable mw-collapsible mw-collapsed"
|To achieve this...
|To achieve this...
|-
|-
|Replace the -0.8 value with -1.5 or lower. Although setting to -1 would technically reflect the motion perfectly, some velocity is lost on the frame the entity collides with the block.
|Check the 'Alive' field on 'attackedEntity' is true before inflicting damage.<syntaxhighlight lang="csharp">
if (attackedEntity.Alive)
{
    byEntity.ReceiveDamage(damage, 0.25f);
}
</syntaxhighlight>
|}
|}
Change the functionality of the block to allow an entity to bounce on any side of the block. You should use ''facing.IsAxisNS'' and ''facing.IsAxisWE'' to determine what side the entity collides with.
Using the revive function in the Entity class, make the sword revive any dead entities hit by it.
{| class="wikitable mw-collapsible mw-collapsed"
{| class="wikitable mw-collapsible mw-collapsed"
|To achieve this...
|To achieve this...
|-
|-
|You need to replace the contents of the ''OnEntityCollide'' function with something similar to the following:<syntaxhighlight lang="csharp">
|Check the 'alive' field is false, and then call the Revive function on 'attackedEntity'.<syntaxhighlight lang="csharp">
if (isImpact && facing.IsVertical)
if (!attackedEntity.Alive)
{
{
     entity.Pos.Motion.Y *= -0.8f;
     attackedEntity.Revive();
}
}
else if (facing.IsAxisNS)
</syntaxhighlight>
{
    entity.Pos.Motion.Z *= -1.2f;
}
else if (facing.IsAxisWE)
{
    entity.Pos.Motion.X *= -1.2f;
}
</syntaxhighlight>Note that you will need to jump into the trampoline block to bounce off of it.
|}
|}
</translate>
</translate>
{{navbox/codemodding}}
{{navbox/codemodding}}