Inventaire et boutiques dans Godot ! | Thomas Yanuziello | Skillshare
Search

Playback Speed


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

Inventory & Shops in Godot!

teacher avatar Thomas Yanuziello, Indie Game Developer

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

    • 1.

      Promo

      1:38

    • 2.

      Coins

      14:38

    • 3.

      Polish

      16:41

    • 4.

      Pick Up

      17:39

    • 5.

      Inventory

      15:34

    • 6.

      Items

      15:21

    • 7.

      Consumables

      17:32

    • 8.

      Equipment

      12:11

    • 9.

      Shop

      13:43

    • 10.

      What's Next?

      0:32

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

24

Students

--

Project

About This Class

This course is a continuation of Game Development Essentials in Godot.

Click on my website link in my profile to join our discord server!

In this course, we will cover different methods of picking up items, managing the player's inventory data, displaying their inventory on the UI in a menu, allowing the player to interact with their inventory in different ways, and trading items with NPCs.

You'll also learn useful skills for working with the Godot game engine, organizing, and designing your projects to be more scalable.  You will be learning how to code with GDscript, with everything explained in detail.  Our scripts will be written to be highly customizable and reusable.  All of the project files will also be available on GitHub if you need to review the project as it was after completing each lesson.  These videos were recorded using Godot version 4.2.2.

This course will be part of a series designed to teach bite-sized pieces of game development that can all be used interchangeably with each other.  So let me know what types of games you're interesting in learning how to make and I'll try to include them in future courses in this series.

Meet Your Teacher

Teacher Profile Image

Thomas Yanuziello

Indie Game Developer

Teacher
Level: All Levels

Class Ratings

Expectations Met?
    Exceeded!
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. Promo: Welcome to my course on inventory and shops in Gado. This course is a continuation of dialogue and events in Gado but can be followed and applied to any project that involves picking up items, adding them to an inventory, dropping, using or equipping items from an inventory menu, and trading items with an MPC. You're welcome to join our discord server to work on this course alongside your peers. In this course, we will cover different methods of picking up items, managing the players inventory data, displaying their inventory on the UI in a menu, allowing the player to interact with their inventory in different ways, and trading items with NPCs. When you're done, you'll have a simple inventory system for your game that is easily customizable in its presentation and function. You'll also learn useful skills for working with the Gada game engine, organizing and designing your projects to be more scalable. You'll be learning how to code with GD script with everything explained in detail. We will apply object oriented design principles in our scripts, inheritance, encapsulation, abstraction, and polymorphism, to keep them organized, customizable, and reusable for a project of any size. All of the project files are also available on GitHub, if you need to review the project as it was after completing each lesson. These videos were recorded using Gdoersion 4.2 0.2. The project starts with assets from K Kits, character and Dungeon remastered packs made by K Lauberg. Basic Guy bundle made by Penzilla, and icons made by Shakahi. All are available to download for free on it. Sound effects made by Valensbyer are also included and are available on freesound.org. 2. Coins: Hello, friends. Before we get started, you should have a game seen in your project, which contains a character that the player can control and a level they can walk around in. You should have at least one other character to act as a shopkeeper, as well as assets for coins and items for the player to pick up, use and equip. Throughout this course, we will give the player an inventory to keep track of their money and items, display them on the user interface, use consumables, equip items to the character, and buy or sell them from NPCs. You can use your own project to follow along with this course or download a starter project from my GitHub, titled Godo Inventory course, Main branch. Your project can be two D or three D and almost any game genre that involves the character having money and or items in an inventory and the ability to trade with NPCs. Let's start by adding a variable to keep track of the players currency in their save file, which in this project is the progress resource. Exporting the variables, so it will be serialized and saved. Let's call it coins. It will be an integer with a default value of zero. Next, let's display this information on the Canvas, using a label node. After setting the font and font size, it's a good idea to decide on the limit of how large a number you want to allow to be displayed, experimenting with a placeholder number. Suma limit of 10 million. It would be nice to have an icon beside this number to tell the player what it means. Using a texture wrecked node, populated with a coin icon, We can put both as children of a horizontal box container to arrange them for us. Let's rename the parent node wallet. And move it to be behind the fade. I think the coin counter will look best in the upper left corner, which it is already anchored to, but with 32 pixels of padding from the edge of the window. The icon is too large, so I'll change its stretch mode to keep aspect to maintain its aspect ratio and have it automatically resize to fit its width proportional to its height. Resetting the height of the parent container. It will now be set by the label nodes font size, which is apparently 42 pixels. The height of the icon will also be 42 pixels, and thus with a one to one aspect ratio, the icon will also have its width set to 42. I'll also have the text centered vertically and add a 16 point black outline to the number to match the outline around the icon. Thinking ahead, I would like to have the icon pulse slightly when the number changes. Setting its custom minimum size y value to 42. Click and drag it to the right, and we can see the effects of increasing and then decreasing this value over time. Doing this rapidly, we can see the effect of applying a quick, but subtle pulse effect, which will also slightly move the label, grabbing the player's attention. I would also like to keep the Canvas clear of irrelevant information while the player is playing the game. So we'll have the money counter hidden when it isn't needed. Selecting the wallet node. We can click and drag the position y value to see how it can move up off the screen to hide and back down again to show itself. Let's start the wallet in its closed position, where its position y value will be the same as its size y value but negative. After displaying the wallet, we can start a timer to automatically hide it after a duration of time using a timer node. Let's name it auto hide, and set its one shot property to true, so it will only count down once when requested to keep the demonstration short. I'll auto hide the wallet after just 3 seconds. Adding a script to this node, let's call it counter and save it in the UI scripts folder. It can inherit from control since it doesn't need any behaviors of the horizontal box container. We'll need references to all of the child notes set during the ready phase. And a private tween variable. Public functions will be available to tell this note to open or close, returning the tween finished signal when done, and one to set the value of the counter. Opening the counter will be accomplished by tweening its y position to positive 32, and closing it will do the same to the negative of its size dot y. It would be a good idea to export these as variables to make the script more reusable for other counters. Adding on screen position and off screen position variables, both as vector two, O pen can now tween the nodes position to be on screen and close tweens to offscreen. Changing the float argument into a vector two. Tweening the nodes position, accepting a new position as a vector two parameter, and returning the tween finished signal. We'll first check if a tween exists and is running. If so, kill it and create a new one. We can then tween the nodes position to reach the new position over a duration of time. Let's export this as another variable and give it a default value of 1 second. Remember to set the values of the onscreen and offscreen positions of this control node in the inspector. To set the value, we need a new value to set it to, which should be an integer. We will be setting the text property of the label node to match this integer after casting its type to a string, but clamping it to be between zero and the maximum value allowed buyer display. But first, we should check if the counter is currently being displayed, and if not, await the open function. For that, we will need a Boolean variable telling us whether or not the counter is currently open, which will be set to true during the open function, but only after the tween has finished. Then also await the icon pulse animation before updating the actual number. Or you can omit the a weight here to have the pulse and the number update simultaneously. Adding a pulse function, returning the tween finished signal after doing the usual tween checks, I'll simply tween the icons custom minimum y property to be slightly larger. Let's say 46 pixels. Over a duration of one tenth of a second, then tween back to its original size over the same duration. We can also export variables for the duration and size of the pulse if we want to. Note that because of the node settings I'm using, shrinking the icon to be any smaller than 42 pixels will be ignored. You can always change the type of the horizontal box to be a normal control node and manually position its children if you want more flexibility. Selecting the auto hid timer node, we can connect its time out signal to the counter's close function. By selecting it from the list, the green arrow shows the function is connected to a signal. Sometimes we may want to disable the auto hide feature. Let's add that functionality with an optional Boolean parameter called stay open, defaulting to true. Storing this in a local variable of the same name, We can use this as a condition before requesting the auto hide timer to start, disableling the auto hide behavior and keeping this counter open. When setting the value of the counter, if the counter is not already open, then it stands to reason that the counter has not been told to stay open. So we should await its opening and pass false as the argument to trigger the auto hide, and set is open back to false when closing. Now let's switch to the level scene and create a stack of coins that the player can pick up. Starting with an Aa three D node, let's call it coin stack Small. Then drag the model asset onto the area three D node to add it as a child. Right clicking on the coin stack, select make Local to separate this node from the imported asset, making it just a local copy, instead of a reference to the asset. Now we can extract just the mesh instance three D node that is drawing the coin stack and remove everything else. Make sure the coins are resting cleanly on the floor, adjusting your perspective if necessary. Next, we'll add a collision shape for the area three D node. I'll use a sphere, give it a radius that surrounds it sufficiently and move it up above the ground. Let's attach a new script to this coin stack called coin stack. I'll put it in the event scripts folder. T. And have it inherit from proximity event to automatically react to collisions with the player. For more information on events, see the dialog and events course in the series. Let's export a variable for the amount of coins that are in the stack, a an integer with a default value of ten. We can also restrict this value to be contained within a range using the export range tag, specifying a minimum and maximum value allowed for this variable. A stack of coins should not be empty, so the minimum value would be one, and I'll just put the maximum at 10 million. A providing a definition for the event manager to call the scripts run event function, accepting the event manager as a parameter, we won't need to use it, so it can be proceeded with an underscore. We need to set the progress variable to be plus the value of this stack of coins, then destroy it using Q free. We'll also need to override the on body entered function to tell the game manager not to disable the player node during this event. Let's make this stack of coins its own scene, saving it in the scenes folder and create a new sub folder for items. Then move the stack away from the player's starting position. The last thing we need to do is update the UI when the coins are collected. There's probably going to be a lot of coins in the game and we don't want to manage their signals manually. That would be a waste of time. An easy way to accomplish this is to use auto loaded signals. Creating a new auto load script, let's call it global and give it a signal called coins dated with an integer parameter for the new coins amount. This script is also useful for providing values for commonly used variables across different scripts throughout your project, particularly ones that are not meant to be adjustable by the player in the game settings. We can then add the global script to the list of auto loaded nodes in the project settings. The counter script attached to our wallet can now use the ready function to connect this signal to its set value function. Setting the label on the UI to match the argument passed through the signal emitted by the global auto load. And also initialize the value to whatever is stored in the players save file when the game first loads. But this is no longer a repurposable script. So let's give it a class name counter. Then create a new script inherited from counter called Wallet. Which will have this ready function directly tying it to the player's coins. Replacing the script attached to the wall by dragging it onto the node. The counter script can now be used to count anything displayed on the UY, such as keys or health potions, for example. In the progress script, adding a setter function to the coins variable, we can tell this signal to emit automatically anytime the value changes. Using an if statement, we can make sure the number isn't being set to what it already was. Let's try it out. Walking over to the coins, they disappear. The wallet appears with the balance of zero, which pulses and updates to be ten. Then after a three second wait time, the wallet hides itself. We now have coins that the player can pick up and keep track of on the game's Canvas. In the next lesson, we'll add visual and audio effects to improve the look and feel of these game mechanics. I'll see you in the next lesson. 3. Polish: Hello, friends. In the previous lesson, we added collectible coins to our game. In this lesson, we'll use all kinds of special effects to polish the coin collection process to make it more satisfying. Starting in the counter script, we can add a variety of effects to the behavior of our tweens using transitions and easings, which change how the property changes over the duration of time. Let's export a tween transition type variable. And set it when creating the tween. Looking in the inspector, the default behavior is a linear transition, uniformly changing the property over time. But we can change it to several different options. Taking a look at these graphs, I think it would look nice if the counter used the elastic transition type. And each of these can also be combined with an easing type, applying them to the in half of the tween or the out half or both. Instead of exporting the ease type, I would like to have different easings applied to the open closed functions. Since it would make sense to have the elastic effect play out on screen, so I'll have the open function and the closed function in. Passing the easing type from the open closed functions through to the tween position function in each case. In the coin stack scene, we can wait for the stack to shrink before destroying it instead of it just disappearing. Grabbing a reference to the mess during the ready phase, We can tell the mesh to shrink using a tween. Since there's no possible way this tween can be used more than once, we don't need to worry about it. Just create the tween. I'll use the same elastic transition type and tween the meshes scale property to zero over a short duration and return the signal. But we do need to make sure that the player doesn't collide with this area again while the tween is happening. So let's disable it by adding a function in the proximity event script that sets its collision mask to zero. We can also add extra polish by adding an audio stream player three D node. Populated with a coin clinking sound effect. I'm using the coin sounds pack created by val inspired or. We need to grab a reference to this node using add on. And tell it to play during the event. Then wait for the sound to finish before queuing the node to be freed so it can play out. As an audio stream player three D node, the sound emitted will adjust its volume based on proximity to the default listener, the camera. If we want to add sound effects to the user interface, we should instead use the basic audio stream player node, which will always play its sound effect at the volume it is set to. Grabbing a reference to the audio stream player node. We can play a coin clink sound anytime the counter's value is set. We now have sound effects playing from different nodes and different scenes. One auto loaded node is also playing background music while other nodes are playing sound effects, and we will definitely have a lot more as the game gets bigger, and others might also play dialogue. We should set their volume to match that of the game settings. But managing them individually would be difficult. If we click on the audio tab at the bottom of the editor, Gada has a built in audio bus that we can use to categorize our different audio sources. This allows us to adjust the volumes or other settings of each collectively through the bus, instead of each individual node. Adding a new bus for music and another for sound effects, both will be passed through the master before being output to the speakers. Adjusting the master volume will affect everything in the game. Adjusting the music volume affects only the music and likewise with the sound effects. Selecting the sound effect audio stream nodes, we can change their bus to SFX. Since we can't access the music node outside the auto loaded script, we can use the ready function to set its bus to music. Make sure the spelling is exactly the same. Otherwise, the bus will be set back to the default of master. Save the audio bus layout as a project resource. Then open the project settings Under audio buses, select the audio bus layout to be the default. The music node will no longer need to refer to the volume setting, since the music audio bus will set the cap for its volume and can just fade to a linear volume of one. In the settings resource, we can add variables to store each individual volume setting, master, music, and sound effects, providing default values for each as well. In the settings menu, we can add volume sliders for changing each of these values. I'll change the volume to master volume. Then duplicate it twice, and edit the duplicates to be music volume and sound effects. Grabbing references to each slider during the ready phase. Initializing them to match the game settings when first loaded. We no longer need to manually set the music volume since it will be handled by the bus. And when the player changes their values, change the variables in the settings resource, and also adjust the volumes in the audio bus to match. Audio server set bus volume Decibels audio server bus index Master file dot settings do master volume, converted from linear to decibels. Giving each slider their own value changed function, after we can edit the signal connections of the sliders to connect to the appropriate value changed functions. We also need to initialize the bus volumes when first loaded. Now, we don't need to bother manually adjusting the volumes of any audio nodes as long as they are sorted into the appropriate category. Opening up the coins stack small scene Reset the transforms local origin if it isn't. Let's also add a simple particle effect to the coins when they disappear. Pudo has two different node types for generating particles, one that runs on the CPU and the other on the GPU. CPU particles that are compatible with slower computers or ones that don't have a dedicated graphics processor like mobile devices, but they can't produce as many particles and have less features. A CPU particle system is capable enough to produce a small burst of particles like what we're trying to achieve here. But a GPU particle emitter would be more appropriate for emitting thousands or millions of particles on a modern system. I'll use a CPU particle emitter. Right now, nothing is emitting because there is no particle to draw. Expand the drawing section and add a mesh resource to represent a single particle. I would like to use the coin mesh as the particle. I'll drag a single coin asset from the asset pack into the scene. Make it local, and select the mesh instance three D node. After making this mesh unique, so it is no longer tied to the imported asset. I can save this mesh as a project resource. I'll name it coin mesh. Deleting all these nodes and reselecting the particle emitter, I can now use this mesh as my particle. The particles are now emitting eight times per second and falling down. I would like a one time burst of particles instead of a continuous emission. Expanding the time section, I'll set one shot to true and explosiveness to one. Clicking on the emitting toggle, the eight particles all spawn at the same time and disappear after 1 second, which is the lifetime property. I want the particles to burst upward, so I'll expand the direction section and change the direction to up with a spread of 15 degrees. Next, I'll set the initial velocity to be a random number 2-3 meters/second and set the gravity lower at only negative 4 meters/second squared. I'll have the particles align their local up vectors toward the direction they're moving. Let's see how it looks so far. I would prefer the coins not to suddenly appear or disappear, so I'll expand the scale section, and at a scale curve. Expanding the curve resource to edit it, we have time along the x axis and scale along the y axis. Note that a time of one is not 1 second, nor is a scale of one, 1 meter. These are percentages of the particles lifetime and scale properties. At time zero, I want the coin to be invisible, setting its scale to be zero, and the same at time one. At the halfway point of the particles lifetime, I want its scale to be one or full sized. This creates a wave so the particle will gradually grow and shrink over its lifetime. We can modify the anchors of any point on this curve to adjust how it affects the particles scale. Now it looks like the coins burst upward and rain down after being collected. There are a lot of different settings for adjusting how particles are spawned and how they behave over their lifetime. Try experimenting with different particle effect settings to get the type of effect you want for your game. In the coins stack script, we can grab a reference to the particle emitter node and set its emitting property to true when the coins are collected. Then await its finished signal before queuing this node to be freed. I'll have the shrinking, sound effect, and particle effect, all happen simultaneously. Duplicating the coin stack small scene, we can make a medium and a large stack. Replacing the mesh instance three D node with different stacks of coins. I'll also set the value of these stacks to have a higher default value by changing it in the inspector within their scenes. Change their sound effect and their number of particles emitted by their particle effects. Then add different stacks around the level to be picked up by the player. We can also use particle effects in two D as well. Let's make a similar effect on the wallet icon when the coin encounter updates. Adding a two D particle emitter to the icon node. I'll position it to be in the center. A Using almost all the same properties for this particle emitter, I'll just change the particle to a copy of the coin icon. Use a spread of 180 degrees, so the particles fly in all directions and remove gravity. The velocity is measured in pixels per second, so I'll have it vary 16-32. But apply the same curve so the particles grow and shrink. And set the min and max scale to only 5% of its normal size. Then in the counter script, grabbing a reference to the particle emitter, we can tell it to emit when updating the counter's value. Now when picking up the coins, the behaviors of the coins and the UI look a lot more interesting. Try experimenting with different transition and easing types, sound effects, and particle effects to get the look and feel you want for your game. We now have a more satisfying experience for the player collecting coins in our game thanks to a variety of effects. In the next lesson, we'll allow the player to pick up an item by pressing a button and adding it to their inventory. I'll see you in the next lesson. 4. Pick Up: Hello, friends. In the previous lesson, we added polish to the coin collection mechanics. In this lesson, we'll add items that the player can pick up by pressing a button. Let's start by making a couple of items that the player should be able to pick up. Starting in the character scene, we can use one of the items in their hands. I'll use the Barbarians ax. Making this ax its own scene, saving it in the items scenes folder, Notice how the origin of the axe is at the grip where the character holds it. We can add a rigid body three D node to this scene, which will make it a physics object, indicated by the beach ball icon. Give it a collision shape. I'll just use a box collide. Then adjust the boundaries and position of the box to encapsulate the x model. Using orthographic viewpoints makes this much easier. Right clicking on the rigid body three D node, I'll make this the scenes root node and rename it to X. Let's put this on a new collision layer. I'll use Layer six for items. This object can mask the terrain, other items, the player and MPC. Opening the project settings, Layer names, three D physics, setting aside Layer six for item pickups. Attaching a script to the root node, I'll just call it item. I'll keep it simple for now and just export a display name for the item as a string. We'll expand on the items themselves. Returning to the character scene, we can delete the item node, since we don't have the proper systems in place to handle equipping it yet. In the Dungeon scene, dragging a bottle A labeled brown into the scene and making it local, the asset was imported to already have a rigid body attached to it. We can right click on this node and make it its own scene and name it health potion. Re parent and rename the health potion and delete the Node three D. O pening the scene, the world simulation is toggled off. I'll toggle it back on. Let's rename the root node to health potion as well. And attach the item script, giving the health potion a display name. Using the same collision settings as the axe. The potions origin is at its base where it will sit on the ground, as is its center of mass, leading to some unusual behavior. To make items easier for characters to hold in their hands, it helps to have their origin be where the character will hold onto it. So selecting both the mesh and the collision shape, let's move them down about two thirds of the bottle, positioning the origin around the neck of the bottle. And selecting the rigid body node, expanding the mass distribution section. We can also change the center of mass by switching it from auto to custom, shifting it to be closer to the wider part of the bottle down along the y axis about one third. This will keep the bottle from behaving like a rolly pole. We now have two different items that the player should be able to pick up. Let's place an ax and two potions on the table for the player to collect. But this looks rather boring, and since these are physics objects that can move around, let's put one of the potions on the floor tipped onto its side. Back in the health potent scene, we can try attaching an interaction event to it, using an area three D node and a collision shape. I'll use the same capsule as our NPCs as an example. While this system worked great for interacting with NPCs and doors, which are generally larger and don't rotate, we can now see the limitations of our existing event interactions when dealing with smaller objects and or physics objects that can rotate. For this demonstration, I'll turn on visible collision shapes. Attaching an interaction event to the health potion will make it uninteractable if it tips over and rolls onto the floor. Since the collision area will also rotate about the local origin of the health potion. This becomes much harder to reliably target with a ray cast. We could make the collision shape a sphere and large enough that it will always be detectable by the ray cast. But let's use a different solution. Many games also allow the player to pick up items behind them that are still in close proximity to the character for convenience. A cast that only looks forward isn't going to accomplish this. Another way of interacting with the environment can be achieved using an area three D node attached to the player character, using either a sphere or a cylinder collision shape, setting the radius to an appropriate range limit. I'll use the same range as the interaction ray cast of 2 meters. Set the height at the character colliders height of 2.6 meters and center it on the character at half of that 1.3 meters. But if the character is standing on a downward slope and the player wants to pick up items slightly below them, they should be able to. So I'll add half a meter of height and lower the center by one quarter of a meter. This collision shape will be monitoring for items that the player can pick up when they press the interact button, masking layer six. Attaching a script to this area node. Let's name it pick up radius. I'll make a new folder for player scripts and put this in there. Then move the player and spring arm scripts into this folder as well. Then connect the body entered signal to this script to react to any body on Layer six entering the pick up radius. As well as the body exited signal when they leave the pick up radius. This script will need to maintain a list of every item in range of the player that can be picked up using an array of node three Ds, which will default to an empty array. When a body enters this area, it will be appended to the array. And when it leaves this area, it will be erased from the array. But the downside of using area collisions in this way is that there is no way to detect obstacles in between. This will actually allow the player to pick up items on the other side of a wall. We will need to use another ray cast to determine whether what the player wants to pick up is obstructed by the terrain or other obstacles. Adding a cast three D node to the item pick up radius, I'll move it up along the y axis halfway up the character, 1.3 meters, and have it collide with only the terrain or items. When the player presses the interact button, I'll just have them pick up the nerest item to them. L et's write an algorithm that will get the nerest item to the player within this area, returning a node three D. When writing an algorithm, it's best to first come up with what all the possible cases are that need to be considered. What happens when the array is empty, meaning there are no items within range for the player to pick up. We should return null, meaning nothing. If there is only one item in the array, we will first have to check if there is an unobstructed path between this node and the item node using the ray cast. Setting the ray casts target position to be the difference between the items and the ray cast nodes global positions. The ray points from its own origin directly to the items origin. After changing what the raycast is pointing towards, the collision information will not be updated until the next physics process, but we can force it to update immediately with a function call. If the raycast hits the item, then we can return it. Otherwise, we will still return null, since the only item in the array is obstructed by terrain. Let's make this code reusable by turning it into a private function. I'll call it obstructed, accepting the item as a parameter and returning a boolean if the ray cast was obstructed or not. Since these cases will cover the vast majority of times when the player presses the interact button, they should be checked first and handled as efficiently as possible. In the rare circumstance that there are two or more items in the array, then we will need to compare the distance of each to the player in order to decide which one is the nearest one, Vastly increasing the complexity of the algorithm. We'll need a few extra variables now, the array index of the nerest item, the distance to the nearrest item, and the distance to the next item in the array. After all of our calculations are done, we can return the item at the index of the nearest item. When comparing distances like this, it's more mathematically efficient to use the distance squared instead of the distance. Since the distance between two points in three D space is the square root of x squared plus y squared plus squared, then d squared is equal to x squared plus y squared plus squared. Removing the need to calculate the square root of this number, and if d one is smaller than d two, then d one squared is also smaller than d two squared. We can start by setting the index to zero and the distance to the nearrest item to something larger than the pick up radius squared, so any item within the pick up radius will be considered nearrest by default. Since my radius is two, I'll just use five. For each item in the array, we need to determine the distance squared to it. Using the global position of this node, distance squared to the global position of the item at index. Then compare this distance to the nearest distance. If it's smaller, then also check if the item is unobstructed. If this is true, then this is the nearrest distance that we've found so far, and I is the index of the nearest item so far. Note that Boolean operations are run from left to right. Comparing the distances will be completed first, which is a fairly efficient mathematical calculation. If the distance to the next item is not smaller than the nearest distance, then it doesn't matter if the item is not obstructed. The Boolean operation and will start with false, and therefore, not care what the other side turns out to be, since false and anything is still false, skipping the ray cast entirely, which is a more costly calculation to run. Carefully choosing the order of operations from common and simple checks and putting off the more complex or rarer cases until last where they might be skipped, can help your algorithms run more smoothly. We will repeat this until we reach the end of the array. Then we will have the array index of the nearest item to the player and can return the item to be picked up. This should be not equal to. The player needs an inventory to store their items, which will be part of their progress information. Let's declare a private variable named inventory as a dictionary and initialize it to be empty using braces instead of square brackets. A dictionary is a collection of key value pairs, similar to an array. If you consider the array index to be the key, but a dictionary can use anything as its key. As long as every key is unique. Using the items display name as the key, we can easily stack items by using quantity as the value. This is a very simplistic inventory structure, but sufficient for this demonstration. For now, we'll dirite a function named add to inventory, accepting an item to be added to the player's inventory and an optional quantity with a default value of one. First, checking if the item already exists in the player's inventory. We can increase the value at this key by the quantity. If the item doesn't already exist in the player's inventory, then we can set the value to be the quantity, which also creates this entry in the dictionary. At the end, we'll just print out the inventory so we can see it. In the players script, we can give the interact button multiple context sensitive uses. Grabbing a reference to the item pick up radius, we'll also declare a variable to hold the nearest item to the player. When pressing the interact button, we'll first assign the value of the nearest item to be the nearest item returned by the pick up radius using our algorithm. If the pick up radius script returns an item, anything other than null, then we should pick up that item, adding it to the player's inventory, and queue the item to be freed, removing it from the scene tree. But if there is no item in range to pick up, the script returned null, then we can proceed with the character interaction command. What if the player is both facing an NPC they want to talk to, and there is an item they can pick up at their feet. When creating context sensitive commands, consider which contacts are given priority and how that will affect the player's experience. In this case, pressing the interact button will pick up the item first. Then the player will have to press the button again to talk to the MPC. Sometimes it might be better to use a different button if it will be more convenient for the player. Okay. If we run the game, stand behind the wall and press the interact button, the item is obstructed and we have failed to pick up the item. Moving into the room, pressing the interact button without any obstruction. The two health potions and the ax are added to the player's inventory, each with a separate button press and displayed in the output log. The health potions are also stacked together in a single dictionary entry. We now have the player picking up items with a button press and adding them to their inventory. In the next lesson, we'll display the player's inventory on the Canvas. I'll see you in the next lesson. 5. Inventory: Hello, friends. In the previous lesson, we added items to the player's inventory with a button press. In this lesson, we'll display the contents of the player's inventory in a menu. A good place to start with menus is to assemble a mock up of what information you want to display to the player. This can help give you an idea of how best to use the space available and maybe make you consider things you wouldn't have thought to include otherwise. Let's start with a basic panel node and rename it to inventory. We'll probably want a few label nodes, a title for this panel to tell the player clearly what it's for, as well as an item name and item description of the currently selected item. The title will just say inventory, and I'll use dummy text for the item name and description. I'll have both wraps so they don't spell outside the panel. And also a container, usually either a vertical box container or a grid container to organize all of the items. Whichever container you're going to use, it will likely be filled with buttons, each representing an item or a stack of items. Let's add one now. Next, let's create a theme for this menu. I'll name it inventory. Make a new resource folder for themes and put this in there along with the existing theme. Expanding the theme in the inspector panel, I'll change the default font to the more legible font I'm using for my game and set the default font size to 96, which won't actually be that large after I scale down the panel. In the theme tab, I'll start by adding the panel. Then give the panel a new style box texture. Clicking on the style box texture to open it in the Inspector tab. I'll use the gray box square image with texture margins of 128 pixels on all sides. The image is very large, so I'm going to scale it down to a quarter size. Then set the panels size to double the screen resolution of 12 80 by 720. It takes up half the screen in both width and height. Setting the pivot to be the center by using half of the size property, then anchoring the panel to the center of the screen. With the panel in position, I can now anchor each of the elements to different positions within it. I'll anchor the title to be centered within the panel horizontally and 10% down from the top. Growing in both directions horizontally and vertically, so it is centered about the anchor point. I'll have it used the fancier font and a larger font size of 128. The item name and item description, I'll put inside a vertical box container. Then use custom anchors to position it on the right side of the panel, covering everything 60-95% horizontally and 20 to 90% vertically. Re setting the anchor offsets will snap the boundaries of the control to match the anchor points. I'll use a theme override to space the mode and extra 64 pixels from each other. The label node wants a custom minimum size to be set, so I'll just set them to 64 pixels tall to get rid of the warnings. That leaves the left half of the panel available for the item list or grid. Again, using custom anchors, I'll have the grid cover 5% to 58% horizontally and 20 to 90% vertically. I'll give my sample button a custom minimum size of 256 by 256 pixels. Then also change the font of the item name to make it stand out more from the description. Adding buttons to the inventory theme, we can also change the appearance of the item buttons. I'll use the same gray box for the buttons as the panel. I'll use the same style box for when the button is pressed. Fate it when it's disabled. Change the button to white when it has focus, or yellow when it's hovered over. I'll add a texture wrecked and label to the button to display an icon to represent the item, and a counter for how many of that item the player currently has. I want the icon to maintain its aspect ratio and stay anchored to the center of the button. As for the label node. I'll set it to 99, so I can see how it looks. I'll anchor the counter to the lower right corner of the button and give it a thick outline to stand out against the icon. But when it's a single digit number, I'll want it to be centered horizontally. From my icons, I'll be using a sprite sheet made by Shashi on itch dot IO. Using an atlas texture, we can define this texture as a single s from a sheet. Setting the textur property as the Atlas texture, we can then click on the dit region button, then slice the sprite sheet into individual sprites. Selecting one to act as a placeholder, I'll use a health potion and scale it up to fill the button. These assets are pixel art, which shouldn't be blurry like this. I'll need to change the texture filter to nearest neighbor to get the appropriate look for this icon. I'll set its size to 32 by 32 pixels, and it's pivot to be in its center, so it sits nicely within the button. Now that we have a sample item, let's duplicate it a bunch of times to simulate what a full inventory will look like. The grid container will need to have more than one column. Five columns fits nicely into the space. But we can still only hold 20 items inside the grid container before the items will overflow outside the panel. Remembering the anchor values we used for this container. If we add a scroll container, then copy the same anchors for the scroll container as we had for the grid container. Then nest to the grid container inside the scroll container. Scrolling will be automatically enabled to allow any number of items to be held. I'll reset the anchor offsets of the scroll view container to force it to stay inside the anchors. We can now delete all but one of the placeholder buttons. The last button we should save as its own scene. One that we can use as a blueprint to generate the player's inventory. I'll save it in a new scenes folder for UI scenes. Then move the settings menu into this folder too. Next, we can delete the last button and remove all of the placeholder text, leaving us with an empty inventory screen. Our inventory panel should also include a closed button if we're planning on releasing this game on PC. Let's add a button. Re. And anchor it to the top right corner of the panel. Our theme already has a setting for buttons, but we can change how this button looks without affecting other buttons using a type variation. But add a new type to our inventory theme, and this time just type a custom name for our closed button. In the last tab of our new type, we can specify a base type for this type, which will be button. Then switching to the style box tab, we can overwrite their values to use different style boxes specifically for closed buttons. Using the pre made red X button from the UiPaC for the normal button state, we can then select the closed button node and set its type variation to close button. It will use that theme setting in place of the normal button settings. I'll set its size to be 128 pixels and re anchor it to the top right corner. I'll just use the same style box for every button state for the closed button. It's attach a script to our inventory panel, name it inventory, and save it in the UI scripts folder. It can inherit from a class we wrote in the essential course menu. Inheriting from the menu class, we'll already handle opening and closing the menu, give focus to a default focus item when the menu opens, and provide breadcrumbs if we make this menu accessible from another menu. I'd like to override these behaviors, however, so I can disable the player node while the inventory is open. Copying the definitions of open and close into the inventory script, and calling the super definitions. Our scene tree is getting rather large and complex now, so the node path between the inventory and player node will require going up multiple levels. When accessing a unique node through a complex node path, it's better to mark the node as unique. Right clicking on the player node, select access as unique name. The node is marked with a percentage sign. Now when we grab a reference to it using add on re, the node path is replaced with the percent sign and is now a direct reference to this specific unique node. When opening the, we can set the enabled property of the player node to falls, so the player can't move or jump. And when the closed, if there are no bread crumbs, then we can re enable the player node so the player can continue playing the game. We'll also need to add a button to the input map of the project settings for opening the inventory. I'll use the backspace key or the select button on my controller. In the player script, if the inventory button is pressed, we can tell the game manager to toggle the invent. But the player must be able to close the inventory while the player node is disabled, so that check will need to be separated from the pause functionality. In the game manager script, grabbing a reference to the inventory menu. We can open it if it's closed or close it if it's open. The inventory script then needs to be able to tell the game manager if it is open or not. So Declaring a Boolean variable, it will naturally default to false, and we can set it when the inventory opens or closes. When the inventory menu is first opened, the player's inventory is likely going to be empty, so there's not going to be anything that can grab focus. We can add an if statement to the menu script to first check if the default focus item has been set before telling it to grab focus. Now the inventory which does not have a default focus item will not bother trying to grab focus when it is empty. L et's connect the closed buttons pressed signal to the inventory menus close function. And set the visible property of the inventory default, so it is closed by default. Let's try it out. Opening the menu, the player's inventory is empty, and the player's movement and jumping have been disabled. But we can still close the inventory with the same button used to open it, which re enables the player controls. We now have an inventory menu in our game that we can use to display the contents of the player's inventory. And the next lesson we'll populate this menu with the players items and allow the player to select them to get more information about them. I'll see you in the next lesson. 6. Items: Hello, friends. In the previous lesson, we added an inventory menu to our game. In this lesson, we'll add item buttons to the inventory menu. Our items are going to need a lot more information than just a display name, and we don't want this information to be bound to the three D scene and model of the item. Since when the item is in the player's inventory, it won't be drawn in three D, but instead it will be drawn in two D inside the inventory menu. We can bundle all of the information about our items together into a custom resource script. I'll put it in the custom resources folder and create a new folder for items. I'll name it item inheriting from resource. Then at the top of the script, we'll give this script a class name item. Here we can export any variables we need to describe the item, like its name and description, as well as a Texture two D for its icon to be drawn in the player's inventory. And we can also include a three D scene of the item, but we don't need this yet, and if done incorrectly, we'll break your project. For now, let's just add a comment saying to include this later. Save the script, so the engine will recognize item as a resource class. Right clicking in the new items folder, we can now create a new resource of type item, and name it after the item. I'll start with the At. I will require that every item in my game have a unique name and that the resource file of that item also use the exact spelling of that name for simplicity. The resource should open automatically in the inspector panel when it is created. But if not, it can be opened by double clicking on it. We can then view and edit its properties. Giving it a name and a description, we can populate the icon with an atlas texture, selecting the appropriate sprite from the sprite sheet. I'll change the sprite slicing to a grid of 32 by 32 pixels, and select the x icon. I'll create the health potion item resource as well with a name, description, and an icon. But I want the health potion to be stackable. We can use inheritance to give our items additional properties. Let's create another custom resource inheriting from item named stackable. This script will add a new class name, stackable extending item, and it will just export one additional variable, the stack limit of the item, which I will default to 99. Double clicking on the Health potent resource, under the Rf counted section, we can change the script this resource inherits from to the stackable script. Now we can set the stack size limit. Some other variables may have their values reset when doing this, and we will need to repopulate them. Next, we should open up the item scenes and edit the old item scripts attached to them. These scripts no longer need a display name, but instead a reference to the item resource. Which we can then assign in the inspector for each item. Next, now that we have a proper inventory script, let's go to the progress script, make the inventory variable public and move the add to inventory function to the inventory script where it belongs. I'll rename it to add item, accepting an item as a parameter instead of a node three d and leaving the quantity parameter as it is. Back in the Progress resource script, I would like to allow multiple copies of the same item to appear in the player's inventory, which would be somewhat more difficult with a dictionary. So I'll change the type of the inventory variable to an array. But each element in the inventory array still needs an identifier the item's name, and if the item is stackable, then also a quantity. So the inventory will be an array of dictionaries with each dictionary containing the item name and possibly other details like quantity in that inventory slot. Any specific details about any item that can be changed and needs to be saved would also need to be included as a dictionary entry. If the player picks up 98 health potions and two axes, the inventory will end up looking something like this. In the inventory script, we will need to be able to add item buttons to the inventory menu that represent each item or stack of items in the player's inventory. For that, we will need a prefabricated item button. The one we created in the previous lesson and saved in the UI scenes folder. Dragging a scene file into a script while holding down the control or command key, will declare a constant to hold it and preload the scene with a function call, returning a packed scene type. Constants are conventionally named in all caps, and hold values, which by definition never change. Let's call this prefab. Since it holds a blueprint for a prefabricated button, we will be mass producing. Writing a function which will add a new item button to the inventory menu, it will accept an item and a quantity as parameters. Declaring a new item button variable, we will instantiate a copy of the prefabricated button. Then change the icon nodes texture property to the icon belonging to this item. If the quantity is anything other than one, I'll set the text property of the buttons label node to be the quantity cast to a string type. And if it is one, set its visible property to false to hide it. We will also need a reference to the container node which holds the buttons. We don't need to specify the type of container holding or items, whether it is a vertical box or a grid, so it will still work if we want to change it later. After the button has been created, we just need to add it to the container for it to be drawn in the menu. When the game scene first loads, we will need to initialize the player's inventory to already be populated with the contents of the player's inventory items. Iterating through each item in the player's inventory, we will add a new item button to the container for each entry. Since the value stored in the player's inventory is a string name of the item, we will need to load the resource containing the actual item information. Dragging any item resource from the file system tab into the script will give us a path to it. We can then replace the item name in this string with the name of the item in the player's inventory, since they are all named exactly as their item name. If you want multiple items to have the same name but different properties, then the value stored in the inventory would need to be a unique file name, not the display name. We'll also need the quantity of the item if the item has a quantity value. Otherwise, we can just assume a quantity of one. This will generate the buttons to display the 98 potions and two axes the game has been told to start with. When adding an item to the player's inventory, we can first determine if the item is stackable or not, since the process will differ greatly. Then call separate private functions for adding a stackable item or a single item. Adding a single item, we'll just push a new dictionary onto the back of the player's inventory array. A dictionary containing a name, the item name. We can then add a new item button for this item. Let's make the quantity optional by giving it a default value of one. If the item is stackable, the process is much more complicated. We first need to search through the players inventory to find existing stacks of the same item. Check if those stacks have room for the items being added, check if the stack limit is exceeded, and repeat until either all the items have been added to the existing stacks or every existing stack is full. If there are any items still left to be added, we will then need to create new stacks to hold them. We will need to iterate through each stack in the player's inventory. Checking if the name of the items stored in slot I is the same as this item name. Then we need to check if there's any more room in the stack by comparing the quantity of the stack to the stack size limit. Then we can add the quantity to the stack. Then we can set the quantity to be the stack quantity minus the stack size limit, which is now the number of items which are in excess of the stack size limit. So if quantity is now anything greater than zero, the stack size limit has been exceeded, and we can set the stack size to the limit. If the quantity in the stack did not exceed the limit, we are done and can break out of the loop. Quantity now contains the items yet to be added to a stack, and the loop will continue adding items to stacks until the quantity has been used up or every stack is full. After this loop is completed, if there is any quantity remaining, we will need to generate new item stacks to hold them. Checking if quantity is less than or equal to the stack limit. We can generate a stack of size quantity. Then set quantity to zero. Otherwise, we can create a new full stack and reduce quantity by the stack limit amount and repeat. Adding new buttons to the inventory menu for the new stacks. Anytime the quantity of items in a stack is changed, we'll need to update the label on the button to match the new value. So let's create a new private function that accepts the button and the new quantity as parameters with the button having the same array index within the containers children as the inventory index. The quantity will also need to be updated before breaking out of the loop. Defining this function, accepting the same parameters. We have already written this code when creating our new item buttons. Let's move this code into our new function, and call it here too. In the player script, we can use the same unique name method to grab a reference to the player's inventory. Then when pressing the interact button, add the resource attached to the nearest item to the player's inventory. Returning to the inventory script, To display the items information, we will also need to grab references to the item name and item description nodes. Let's write another function that displays an item's information on the right side of the panel, accepting an item as a parameter. Giving it a default value of null, we can also use this to show no information as well. Setting the item names text property to the item name if the item is not null, otherwise an empty string, and same for the description. Anytime a new item button is added to the menu, we can connect its focus entered signal to this function. But the function requires an item as an argument, and the signal does not have any arguments. We can bind arguments to a callable with a function call, passing the item itself. Lastly, when opening the inventory menu, if the container has any children, we should tell the top child to grab focus. And if it doesn't have children, display item information, passing null is the argument. L et's try it out. We start with 98 health potions and two axes in our inventory, and the health potions information grabbed focus, displaying the information on the right. After picking up the items on the table, one health potion was added to the stack of 98 filling it up, while the other started a new stack along with the other ax. Since the buttons have focus, they're also navigable with the keyboard arrow keys or the controller's directional pad. We now have the players inventory displayed in the menu. In the next lesson will allow the player to drop or consume items in the inventory. I'll see you in the next lesson. 7. Consumables: Hello, friends. In the previous lesson, we added items to the player's inventory and displayed item information. In this lesson, we'll allow the player to drop or consume items in their inventory. In the inventory menu, we will need to present choices to the player of their options for the selected item. To keep things simple, I'll just have two buttons below the item description organized into a horizontal box container, and rename them auxiliary and Drop. Removing the style boxes by overriding the button theme, I'll just have the left button say use and the right one say drop. Not every item in the game will be usable, so it doesn't make sense for the button to say use when the ax is selected. It would make more sense for it to say equip. This button will be context sensitive based on the type of item that is selected. I want these buttons to be evenly spaced out at the bottom of the panel. I'll set their horizontal alignment to align with expand and fill. Then also reset the anchor offsets of the vertical box to keep it contained within the anchors. And also tell the description to align with expand and fill the vertical box as much as it can, pushing the buttons to the bottom of the panel. T. In the project settings, I'll add input mappings for Ue item and drop item. Then set the x button on the Controller for use and the Y button on my Controller for drop. I'll add these button indicators to the text properties of the buttons as well. So the player knows which button on the controller does what. PC players can simply click on the buttons. I would remove the X or Y text and probably add more style boxes for these buttons for the PC export of the game. In the item resource script, we can add a Boolean variable that specifies whether or not an item is usable and another to specify if the item is consumed when it is used. While we're here, we'll also need access to the three D scene containing the actual item, so that when the player drops the item, we can spawn it into the scene, or if they use the item, we can actually make it appear at the character's hand. We can't both give the three D scene a reference to the resource file and also give the resource file a reference to the three D scene. This is a cyclical reference and we'll create an infinite loop that breaks any scene which contains the item. T. Instead, we will just tell the item resource where to find the three D scene, giving it the path to it as a string so we can load it when it's needed. Then in the health potion resource file, we can copy the path of the health potion scene and paste it into the scene field. We can set it to be usable and consumed on use. I don't have any plans in mind to implement an item which is not consumed when it is used, but it's a good idea to make code flexible. And repeat this for the other item. In the inventory script. We'll need to grab a reference to the action buttons using add on ready. When an item button is focused and item information is displayed, we can set the text property of the auxiliary button to say, if the item is able and set its disabled property to false. Otherwise, I'll just disable the button for now. Let's connect the buttons pressed signals to the inventory script. I'll also add an input function which will tell the auxiliary button's pressed signal to emit when the use item button is pressed. But only if the inventory menu is open, and the button is enabled. And do the same if the drop item button is pressed on the controller. I normally wouldn't put an input function directly into a script like this, but for simple shortcuts to press buttons, I think it's fine to skip the step of using a separate input handling script. If either the x button is pressed using the controller or the use button in the menu is clicked with a mouse, this function will be called in either case. But we need to know which item is selected. And it might also be important to know which specific item in the player's inventory if they have multiple of the same item. Anytime an item grabs focus and its information is displayed, let's also accept the button which represents that item in the inventory menu. Giving it a default value of null, so it will be optional, we can also bind this argument to the callable passing the new item button as another argument. Likewise, when these buttons lose focus, it would be a good idea to display no information and disable the buttons. Let's also connect their exited signals to the same function, binding null as the arguments. If no item is selected, then we can't check if it's usable, and we should disable both buttons. Declaring new private variables to hold the selected item and its corresponding button, We can store the selected item and its button when it's selected. When these action buttons grab focus, I would like to tell the item button to grab focus back immediately so the player always knows which item is selected. Connecting their focused entered signals, which can both call the same function. Let's call it on action button focus entered. But by these action buttons entering focus, the selected button has at the same moment exited focus. The selected button is now null. Let's declare another variable called previously selected button that will be set to the selected button every time the selected buttons value changes. So I focus changes from an item button to an action button, the selected button will be set to null. But the previous selected button will retain its reference, so we can tell the previously selected button to grab focus. This way, the player will still be able to see which item is selected if they click on the action buttons. Now, when either action is taken, we can easily access the button which is selected, as well as the item that button represents in the player's inventory. To drop an item, if an item is selected, we can first declare a variable to hold an instance of that item and set its value to load, passing the path to the scene as stored in the items resource file and instantiate it. Then add this item to the scene tree. You'll probably want it to be a child of the level node to be automatically removed along with the level when it's unloaded. For simplicity, I'm just going to add it to the game manager. Declaring a variable to represent a random direction along the xd plane, it will be a random number between zero and T. To represents the full circumference of a circle. We'll then set the global position of the item to be near the player character's global position slightly above the ground, applying sine and cosine to the direction to get the x and Z values of the new position. Let's first make sure we have a reference to the player character using a unique name. And remove the dropped item from the player's inventory, passing the item being removed, a quantity of one, and the selected button which represents the specific item. If the player presses the auxiliary action button, if there is an item selected and that item is usable, we can call a separate private function to use the selected item. As other uses of the auxiliary button become relevant, then more functions can be added here. To use an item. If the player character is on the floor and they are not busy doing anything else, I'll use the can move variable, even though it's marked as private, then we can tell the character to use the item. If the item is consumed on use, then we can remove it from the player's inventory, passing the selected item, a quantity of one, and its button as arguments. Since I will be adding a e item animation to the character and I want the player to see it, I'll close the player's inventory upon requesting to use an item so that we can see the animation play out. Removing an item from the player's inventory is much the same as adding one with the behavior being different for stackable versus single items. So when removing a single item if the button is not null, then we can go ahead and remove the inventory entry whose index matches this button's child index in the array of the containers children. And also remove the item button from the inventory menu and return. I'll do this in another private function to also maintain proper control of the selected and previously selected button references. If the button was not provided, then we'll need to search through the players inventory to find this item. Once we do find it, we can remove it from the inventory and the containers children and return. Before removing any item button, we'll need to check if this button was selected or previously selected. And if so, set these references to null, so we don't accidentally try to reference buttons which no longer exist. We'll use free here instead of Q free to make the effect immediate instead of waiting for the end of the current frame. This way, in the event of needing to remove multiple entries from the player's inventory, the containers children will still match up with the inventory indices. But removing this button which currently has focus, we will need to tell an adjacent button to grab focus. So I'll call a private function to switch focus to the next item in the list here. How this is handled will depend on the number of children the container currently has. If there are fewer than two children, then nothing will need to grab focus and we can return. If no button was provided as a reference point, we can just tell the top child to grab focus. If a button was provided, we'll need to know its child index within the container. If the next index is valid, meaning it is less than the child count of the container, then the next child can grab focus. Otherwise, this is the last child, and we'll instead want the previous child to grab focus. Let's combine this into a turn re statement. We can then proceed with removing the item button now that it no longer has focus. Removing a stackable item will be a bit more complicated. If a specific button was provided, then we can get its child index within the container. Then remove quantity from the stack in the matching inventory slot. If the result of the subtraction is less than or equal to zero, then the stack is empty. Setting the new quantity value to the negative of the current stack size, this value will now contain the amount that the stack was short of the quantity we were trying to remove. So we can remove both the inventory stack and the button which represents it from the menu. If the result of the subtraction was a positive number, then the stack is not empty, and we just need to update its new quantity value. Then return since we are done. Now that we're done checking the suggested button, if there is any quantity left to remove, we will need to search through the player's inventory to find more stacks of this item. We can then repeat the same logic as above, using the index alias I instead of the index of the button. And removing the matching button whose child index matches the inventory index. If we ever reach a quantity of zero, we're done. In a character scene, selecting the animation tree node inside the miscellaneous state machine. We can add the use item animation. Since like other animations here, it also starts and ends with the dopose. Using the same transition settings as the other animations, setting the advanced mode of the transition into the animation to enabled and the switch mode of the transition out of the animation to at end. Pressing the play icon will allow us to preview the animation. In the script, let's add a new public function to use an item, accepting an item as a parameter. For this, we will need a reference to the character's main hand, so we know where to position the item being used. This will also be the main hand position used to equip weapons. So creating a new exported category for equipment, I'll export a new variable for the character's main hand slot with a type of bone attachment three D. Selecting my character's root node. This main hand equipment slot will be the same bone attachment node which previously held the one handed x. When using an item, we will declare a new variable to hold an instance of the item and assign its value to be load. Passing the path to the three D scenes stored in the item resource as the argument and instantiate it. This will create the item, which we will add as a child of the main hand equipment slot. But this item has physics and collisions. It will collide with the character and be affected by gravity. We'll need to set its freeze property to true, so the engine will ignore all of that and just treat it as if it were glued to the character's hand. Next, we'll await the completion of the use item animation. Finally, queuing the item instance to be freed from the scene tree, we are just going to assume that the character's hand is empty before all this happens. This is where the effects of using the item would be activated, but we'll just print out a statement to act as a placeholder, so we know it works. Minor corrections in the inventory script. We can only remove the suggested item button once. If removing multiple single items, then we'll use null every time after the first. And when telling the next button to grab focus, we should not then set it to null immediately after. Let's try it out. Opening the inventory, we have 98 potions. We can use one which closes the inventory, and we can see the character hold a potion in hand, drink it, and it disappears. Re opening the inventory, we now have 97 potions, and we can drop some items, removing them from the inventory, which are now scattered on the floor around the character after closing the inventory. We can even pick the items back up and add them back into the player's inventory. We now have items able to be dropped or used from the game's inventory menu. In the next lesson, we'll allow the player to equip armor and weapons. I'll see you in the next lesson. 8. Equipment: Hello, friends. In the previous lesson, we allowed the player to use or drop items from their inventory through the menu. In this lesson, we'll allow players to equip items to their character. Each of our characters have several different items in their hands, a cape and a hat. Except for the rogue, whose hood is unfortunately not separate from the rest of the model, so we can't use it as equipment. All of these can be turned into items following the methods used in previous lessons that we can pick up and add to the player's inventory. Note that the rogue does not have a hat bone attachment, and the mage does not have an off hand bone attachment. We can fix this by adding our own bone attachment nodes to the character and attaching them to the correct bones within the skeleton. In the Mags character scene, we can add a child node to the skeleton of type bone attachment three D and rename it to something like offhand. Then in the inspector, attach this to the hand slot one, meaning left, and now this node will automatically follow the character's left hand in all of the animations. Dragging the book onto this new bone attachment, we can see how it continues to follow the left hand. Any other items meant to be held in the character's hands can be reparented to the main hand or off hand equipment slots before making them into their own scenes to maintain their relative positions and rotations. We can then repeat this process to add a hat bone attachment for the row character following her head bone. I'll also reorganize and rename the nodes to match exactly with that of the mage. The Mags hat slot is also different from the other characters. It is positioned higher and rotated slightly. To make our lives easier, let's add a new bone attachment node that follows the Majes head and use that as their hats lot instead. Dragging the hat asset from its existing bone attachment to the new one will also give us the exact position and rotation difference of this hat. When we create the Majes hat item scene, we can make this position and rotation a natural part of it. Using these methods, all of our characters should have the same four equipment slots, and any item can be equipped to any character. The equipment slots can be renamed for consistency, if you prefer, and unused bone attachment three N nodes can be deleted from the character scenes. But the hair of some of the characters will clip through some of the hats. In some games, you'll notice that hair is removed from the character when a helmet or hat is equipped to fix this issue. In these assets, the hair is part of the head model, so we will need to either restrict who can wear which hat, scale or reposition the hat depending on who is wearing it, or simply ignore the issue. Especially when using placeholder assets, it's better to take note of the limitations and make sure that the final production assets address the problems instead of replicating them. Before we create any new item resources, let's define a new type of item resource. We'll call it equipment, inheriting from item. This will allow us to add a new variable to items that fall under this category, the type of equipment that it is, which will determine how it can be equipped. In our projects enumerations, we can add an enumerated list of the different equipment slots for our game, main hand, off hand, head, and back, as well as any other equipment slots you want. The equipment type enumeration can now be used as a type for the equipment type variable, so we can easily set it in the inspector. Switching the axis script from item to equipment. It can be set to be equipment for the character's main hand slot. In the character script, we can add more variables for each equipment slot or change the variable into an array of bone attachments named sockets. When using an item, the main hand is now socket zero. Then assign each bone attachment socket in the same order in the array for each character. Next, we can add new public functions to tell the character to do or do pieces of equipment. Donning a piece of equipment will require a reference to the item, and doffing will only require the slot. To D a piece of equipment is much the same as instantiating the potion and putting it in the character's hand. Replacing the main hand socket with whatever socket the item is meant for. Dopping only requires us to check if the socket has a child, and if so, get rid of it. Using an item, we can no longer assume that their hands are empty. Let's declare a new variable to contain what the character was holding before being told to use the item. If the main hand socket has a child, then that is what they were holding, and we should set its visible property to falls to hide it when they use the item. If they were holding something before using the item, then we can set its visible property back to true after using the item has been completed. In the progress resource, we need to keep track of everything the player has equipped. A simple way of referencing items within the inventory would be to use their array index. So our player's equipment is an array of integers with each element in the array containing the equipment's array index in the player's inventory. Defaulting the contents of the array to negative one for every entry, we can use negative one as a signifier that the slot is empty. Now to connect all of this to the inventory menu. When an item button is focused, we are displaying its information, but we will need to create separate cases for when this is a piece of equipment. Then further divide based on if this item is currently equipped or not. In either case, the auxiliary button is enabled, but the drop button should be disabled if the item is equipped. Changing the auxiliary button to equip or equip accordingly. How do we know if the selected item is equipped? We need to know its index within the containers children, since that is the number saved in the equipment array of the progress resource. Then we can check if the equipment array at the index of the selected items designated slot matches this value and return true or false? This can all be done in a single line of code. Whether or not the drop button is disabled will also need to be handled for the consumable items and null cases. When the auxiliary button is pressed, if the selected item is equipment, then we can use the same condition to either unequip or equip the selected item. To equip an item, we will be setting the equipment array in the progress resource at index of the item slot to be the array index of the item within the player's inventory. Then tell the character to do the equipment. I'll repurpose the label on the item but by setting its default text to a capital E for equip and set its visible property to when equipping it. I'll also update the auxiliary buttons text and disable the drop button. To unequip an item, we will set the equipment array at the index of the item slot to negative one, since it is now empty, telling the character to dof whatever they have in the matching socket. Hide the E for equipped on the button, date the auxiliary buttons text and enable the drop button. But before equipping an item, we will need to check if an item is already equipped in that slot, meaning that the value of the equipment array at the index of the item slot is anything other than negative one. In that case, we should tell the character to dof what they have in that socket. Then also find the button in the container whose index matches that of the equipment array value, so we can hide the E for equipped. We can then proceed with equipping the selected item. In order for this to work, the values in the equipment array must always match the array indices of the items in the player's inventory. But the array indices change every time an item button is removed. Let's require the array index as a parameter when removing the item buttons from the inventory menu, since we already find that every time anyway. Then we can search through the equipment array for any values which are larger than the index of the item being removed. If there are, then they can be reduced by one, so they still match the index of the equipped item. In my progress resource, I'll start the player out with a bunch of new items in their inventory and also have some of them. After first initializing the player's inventory, we can also iterate through the equipment array. If the equipment slot is anything other than negative one, then we can find the button whose index matches the value stored here. To make things simple, I'll just use existing functions, telling the button to grab focus and equipping the selected item. Now when the inventory is initialized, so too, is the player equipped with items as stored in their file. Let's try it out. The character starts off equipped with a few items and opening the inventory we have several to choose from. We can unequip items, equip new ones. If we try to equip an item in an occupied slot, the equipped item is unequipped before switching. If we drink a potion, the character's main hand item is hidden during the animation and comes back after they're done. We now have items being equipped to the player character through the inventory menu. In the next lesson, we'll allow the player to trade items with an NPC. I'll see you in the next lesson. 9. Shop: Hello, friends. In the previous lesson, we allowed the player to equip items from the menu. In this lesson, we'll have them buy and sell items from an NPC. To save time, I'm going to reuse the same inventory menu to create the shop. I'll rename the vertical box container to info and duplicate it to create another control with the same anchors and size, and rename it to shop. Instead of the item's name and description, the shop will contain a scroll container, holding a grid container of the shops stock just like the one holding the player's items. The scroll container can fill the space, pushing the buttons to the bottom. In place of the auxiliary button, I'll have a coin icon, the price of the currently selected item, and a context sensitive transaction button to buy or sell the selected item. The coin icon can keep its aspect ratio, but fit proportionally within the space provided. I'll figure out the maximum amount of space the price could possibly occupy and use that as its custom minimum size. Then the button can use the remainder of the space. I'll also add 32 pixels of separation between these three controls within the horizontal box container and change the text property of the transaction to say. Let's fill the shop stock with a bunch of dummy items to see how it looks. The grid columns should fit inside the space nicely. To switch between inventory view and shop view, all we need to do is toggle the visibility between the info and shop nodes, and we can also change the title as well. When you're satisfied with your shop minus layout, you can delete the dummy items from the shop stock. In the script, I'll need to update the node path to the info node to reflect its new name. We will need references to the title, the info, and shop nodes, so we can swap them back and forth, and also the container which will hold the shop stock, the price label, and the transaction button. Our inventory script is getting a bit large. A useful way to keep longer scripts organized is to create code regions using comments. With a region comment above a block of code naming the region and an end region comment at the bottom of the region. The region can be collapsed and expanded to better organize the script. Let's add a new public function which opens the inventory menu as a shop. We'll change the title to say shop instead of inventory, set the visible property of the info view to false and the visibility of the shop view to true. We can then call our existing open function to also do the rest of this other stuff. We'll need to also create a function to open the menu in inventory mode, resetting the title back to inventory and reversing the visibility of the info and shop nodes. The game manager will open the menu as inventory when the inventory button is pressed. Using the event management system we built in the previous course, we can attach an area three D node to any character in our level scene and rename it shop. Adding a collision shape three D as a child, we can give it a size and shape that is easy for the player to target with their interact recast. The area three D will not need to monitor anything but be monitorable existing on the collision layer specifically for interactions and have no collision mask. For more information on interaction events, see the previous dialogue and events course. Let's create a new script for this node, saved in the event scripts folder. Inheriting from interaction event. In this script, we can export an array of items to represent the stock of items that are available for purchase. Like any event script, we'll write a run event function, accepting the event manager as a parameter, which contains all the object references our events might need to do their job. In this case, the event manager will need a reference to the player's inventory and the shop if you're using a separate menu for it. This will also allow the event manager to add or remove items from the player's inventory during events or dialogue if needed. The shop script can then ask the event manager to open the shop menu. Passing a reference to itself is an argument, so the inventory will have access to the stock and any other public variables you may want. Let's give this a class name of shop, so the inventory script can accept a shop as a parameter when opening the menu as a shop. To use the await command during the event, our open as shop function also needs to return a signal to await. Accepting the shop as a parameter, we can store a reference to it when opening the inventory menu as a shop. The signal returned will be when the inventory menu is closed. We can emit that signal anytime the window is closed, even if nobody is listening for it, when the menu is opened as the player's inventory. To make our shops more unique, let's also export a line of dialogue for the vendor as an intro and another as an outro. Then add these to the run event function as extra dialogue before and after the shop is accessed. And tell the game manager to end the event. We can even export a value multiplier named markup to give different vendors different prices for their items. I'll set the default markup to be ten times the value. Let's populate the nights shop to include the health potion and the ax. A as well as an intro and outro line of dialogue. In our item custom resource, we can give each item a value as an integer with a default value of one coin. Each item in the game can then be assigned a different value, which in this case, will be how much the player can sell an item for. But we'll purchase at ten times that price. Back in the inventory script, it would also be useful to display the player's coins. Let's make that a unique node and grab that as well. We can open the wallet counter when the inventory is opened, and tell it to stay open by passing true as an argument. Then tell it to close when the inventory is closed. Unlike with the player's inventory where we initialize the many buttons onload, then add or remove buttons as items are added or removed from the inventory. The shop stock will need to be generated each time the player interacts with the vendor, and completely cleared out when they are done shopping. Clearing the stock is quite straightforward, just iterating through each of the children of the stock container and queuing them to be freed from the scene tree. We can also set shop to null here or in the closed function. We can clear the stock anytime the inventory menu is closed. If the inventory menu was opened as an inventor and not as a shop, the shop stock contents will be empty anyway. Generating the stock is much the same process as generating the player's initial inventory, iterating through each item in the shop's stock array, then calling add item button. But we'll need a new argument to specify which container the button is being added to. Then add the parameter to the function to match, giving it a default value of the player's item container. This information of which container this button is in will also be relevant when displaying the items information, as well as when the transaction button is pressed. We can store this information inside the nodes metadata. Let's add a new entry to the metadata of our newly created button, with the name is in inventory, with a value of whether the container it is being added to is equal to the player's item container. Now every button knows which side of the shop menu it's on. When displaying an items information, if there is a selected button, we can get its metadata using the same identifier is in inventory. If the item is in the player's inventory, then we can set the price label to the value of the item and set the text property of the transaction button to x sell. To keep things simple, I won't allow the player to sell any items they have equipped and disable the transaction button in that case. If the item is in the shop's stock, then the price text will be the items value multiplied by the shop's markup. And the transaction buttons text changed to x by. Whether or not the button is disabled will depend on whether the player's current coins are less than the price. When checking if the selected item is equipped, let's make sure that there is a selected item and that it is also a piece of equipment. In the input function, if the shop variable is not null, we can return to prevent the use item or drop item functions from being checked. If the use item button is pressed, which we are repurposing here to trigger the buy or sell action, as long as the transaction button is not disabled, we can emit its pressed signal. Connecting the transaction button's pressed signal to the script, I'll move it into the shop region. If no item is selected or no shop is currently being interacted with, then we can simply return. If the selected button is in the player's inventory, then the transaction button will sell the currently selected item. Increasing the player's coins by the value of the item, and removing it from the player's inventory. Otherwise, the selected button must be in the shop's stock, which means the transaction button is going to buy it, reducing the player's coins by the value of the item multiplied by the shop's markup, adding the item to the player's inventory, and re checking whether or not the buy button should be disabled. A small correction when updating the quantity on a button will need to set its visible property to true. In the progress script. I'll start the player off with some money. I'll also ignore the narrow wing conversion warning generated by casting this float into an integer. Remember that the inventory menu should start closed. Let's try it out. Speaking with the night, we are welcomed with a line of dialogue before the shop opens, which also displays our coins. The transaction button displays sell when selecting our items. But it is disabled when the selected item is equipped. We can sell items from our inventory, which gives us more gold. The transaction button displays buy when selecting the shop stock items, but is disabled when we do not have enough money to buy the item. We can purchase items from the vendor spending our gold. And when we close the shop nu, the night thanks us. We now have a shop in our game so the player can buy and sell items from an NPC. 10. What's Next?: Hello, friends. Before we get started, you should have a project with a player character that can move around in an environment, and some enemies for them to fight. You may also want to have an inventory menu capable of equipping items, including at least a mala weapon, a arranged weapon, and a shield. Throughout this course, we will add controls, mechanics, and animations to our project for locking onto a target, attacking, dodging, blocking, and shooting projectiles.