 This video was brought to you by my patrons. Thank you so much for your support. Hello there! Yeah, now I have a camera. Actually, it's a beauty camera because I have a new computer, my first ever laptop. So, without further ado, let's get to the topic. Today we will talk about the decorator pattern, a very interesting pattern because it's hard to see its actual value until you realize that once you have the setup, you can go wild and do a lot of other stuff. So, let's get started. I already made a setup and please know that this is not a tutorial. I am sharing my studies with you so don't follow this strictly because I actually made some very poor implementations. But the real thing here is that you get how this pattern works. So, try to understand how you can make the setup for this pattern and just take off everything poor that I did here. But before we get into this setup that I made here, let's try to understand what this pattern actually do and what it tries to achieve. What's the problem that it tries to solve. So, I will switch to my books here. These books will be on the description and on the pinned comment so you can have access to them. Actually, the one in the left is an upgrade of the one in the right so you can have access to the one in the left instead. Anyway, the decorator pattern is a structural pattern that lets you attach new behaviors to objects by placing these objects inside special wrappers. Objects that contain the behaviors. This is very, very cool. Because as you can see, we have a... I think that is a Machiavra doll. I don't know how to call it in English. But this is basically how the decorator pattern works. You have something and then you wrap it with other thing. And you see that since the decorator pattern is what it is wrapping. So, if you are wrapping a node, the decorator will also be a node. So you can also wrap a decorator. You can have a decorator wrapping a decorator wrapping a decorator and so on. So, on the right, you can try to understand the problem that we are trying to solve with this pattern. You want to add behaviors or state to individual objects at runtime. So, notice that we are not switching as we do with the strategy pattern. We are adding or changing the behavior of the object in runtime. And inheritance is not feasible because it is static and you add it to an entire class. So, everyone inheriting from this class will also have this new behavior. So, if you want to extend it, you will have to extend a lot of other objects together with it. While with a decorator, you can have one object, another object that inherits the same thing. But you want this one at some point of the running of the software. You want this one to have another behavior. You want to improve it, upgrade it somehow. So, you unwrap it with another object with a decorator. And you have a new behavior only on these objects, only on these instances of the class. And the other one will keep the original behavior. So, let's go back to Godot and try to understand how I implemented it. So, first let me change this layout here because you cannot see what's on the bottom here. And let me open the script here. So, let's start by understanding what I'm trying to achieve here. I've played the game and you see that let's suppose that this is a character. And this character has some attributes. So, it has strength, agility and intelligence. And it also has some skills. It can blast a curse itself or others. So, it can blast or curse a target. And when we blast, we get an improvement on these status. And when we curse, we have some debuff. So, we have a buff and a debuff. And you can see that we always go back to the original value. So, the curse goes back to the original value, the blast goes back to the original value. And this is it. It's basically just a buff and debuff system. You can say that it's a power-up system somehow. So, I will close it here. And let's try to understand how this was done. So, first of all, I have here an attribute class, an attribute node. Let's say that. And this attribute node has just an amount. So, an amount of strength or an amount of agility or intelligence. And when we set this amount, we emit a signal. And when we get this amount and pay attention to this method, the get amount, because this is what we will use in the creator. So, we have this get amount. We are encapsulating the amount variable inside these two methods here. Okay? Also, let me know if you would like to have a series about the four pillars of objective-oriented design. So, polymorphism, encapsulation, inheritance, and abstraction. Let me know if you want to get something about this. Comment below. But, anyway, after this, after the attribute, we have the attribute decorator. And the attribute decorator, as you can see, it inherits from attribute. So, as I said, it is what it wraps. So, if we are wrapping an attribute, we will be an attribute as well. And the very interesting thing about this pattern is that it is what it wraps. So, it is something and it has the same thing. So, it is an attribute and it has an attribute. In this case, I call this the Decorate T. So, we have the decorator and the Decorate T. And this Decorate T will be the attribute. It has to be an attribute. And notice that I use polymorphism to overwrite the get amount method. So, instead of just returning the amount that we have here, in this specific decorator, we will try to get the amount of the Decorate T and we will decorate it. So, we will make it fancier, let's say that way. So, we have this amount here and then we multiply this by this amount. So, we have the Decorate T status. So, let's say we have 10 strength. And when we decorate it with this specific decorator, we will multiply this strength by something that is the decorator amount. So, if the strength is 10 and the decorator is 1.5, we will improve the strength by 50%. Okay? And then we adjust at this line so we don't go below 0 because it's not realistic to have negative strength. And here we return this decorated amount. So, we take the Decorate T amount, we decorate this and we return the decorated amount. So, notice that we have something here, we wrap it and we go down to this onion structure and then we take what is inside it and we pass through some operations, some calculations here because we are decorating this thing that is on the core of this onion structure. So, we can also have a decorator, another decorator wrapping this new decorator, this base decorator, and we can go inside this onion structure until we reach what is the actual base thing that is being decorated and then we go back to whoever is asking for this value and we pass through these operations. So, this is basically what is done here into this example. So, if we go back here to the game, we have the blast and the curse. They are basically the same thing. So, if I open this script here, they will point to the same script and we apply this buff to a target and we can pass the attribute that should be applied and when we buff it, we will take a decorator. So, if I go here, we have a decorator here that is basically the effect of this skill and we go here and we will take the decorator and create an instance of it and then we will set this decorator. We will inject into this decorator the attribute of the target that we are trying to decorate. So, we will get this attribute here. Actually, we will get this attribute here. So, we are going to the target and we are getting a property that is this attribute that we are trying to get here. And then on the decorator amount, we will set it to be the multiplier of this skill. So, if you see here, we have a duration that will be the duration of this buff, of this power-up, you can say. And then we have the attribute multiplier that will be what will be used to improve the status. After that, we set this attribute and this is the most important thing. Actually, let me emphasize this. Wherever the decorator is, you have to inject the decorator instead. So, in this case, let me show you the attribute here. The attribute has a pointer to the strength, a pointer to the agility and a pointer to the intelligence. So, when we decorate these objects, when we decorate these attributes, we have to inject the decorator inside these variables here. So, it can point out to the decorator instead of the decorator. This is the most painful part to do because you have to find a way to inject the decorator inside everywhere that the decorator is being pointed to. And then, when you want to take out this decorator, you have to find a way to go back. You have to inject back the decorator in these variables. So, if you don't have a base structure to do this easily, you will have some bad time trying to implement this pattern. In my case, I inject these variables into this buff and I inject the decorator back into this remove method here. So, I'm just setting it back. And since the decorator also points to the decorator, we always have access to it. So, we always have access to the base value. So, when we want to remove the decorator, we can basically just say, okay, whatever decorator this is pointing to, will now be injected back into its original pointer. So, this is what this is doing here. And if we try to test this, let me put this to the remote. So, to the remote scene, open this, open this, open this, and this. What we will see is that it will instantiate some decorators inside this BLAST class here, inside this BLAST node. So, when I BLAST it, we will have some children here. Let me BLAST again. We'll have some children decorators here. And when the status, the buff goes out, so when the buff times out, it will inject the decorators back into these attributes here. To this attributes node, because this is what it's been using to carry and to reference what's the value of the status of the attributes of the character. Well, if we go here into the decorator, this might sound trivial, so you could do this just by making some calculations, some hard-coded calculations. But now that you have this into your tool shell, into your toolbox, imagine the possibilities of this kind of system. So, imagine that instead of having just some multiplications, you can have any kind of decoration in these nodes. And you don't have to actually just work with integers. You don't have to work with numbers. You can work with any kind of value. So, let's say that you have a skill system, and somehow a character can forge some weapons, and then you can say, okay, so these weapons will also decorate the character's status. So, these weapons will have a modifier inside of it that will be a decorator. And when the character equips these weapons, it will basically do the same thing as I'm doing here into the skill. But instead of passing just these, it will pass, let's say, just strength, or just agility, or just intelligence. So, if you have a knife, it will improve the character agility. If you have a staff, it will improve the character intelligence, and so on and so forth. And with this, you can also improve the way the character forges the weapon. So, let's say you have a system for forging, and on the level one it always returns a basic weapon. But at some point you can have an improved skill, or a perk, or something like this, that says, okay, every weapon that you forge will also have a modifier. Something like this. Instead of having a returning weapon, let's say this would be a forging system, and you go here, and you have some method that returns a weapon here. So, forge, something like forge a weapon, and it would search in a database or something, and then it will return a weapon here. But on the decorator, you will have something like, instead of returning this weapon, you will return this weapon that we just find with a modifier inside of it. So you can use these decorations everywhere in your game, and this is very cool, because this makes so that your game adapts dynamically. You make emerging mechanics inside your game. This is so... Well, this is it. Tell me what other systems that you are designing that maybe the decorator pattern can solve your problems. And, well, don't forget to leave a thumbs up. Oops. To leave a thumbs up if you enjoy this kind of content, so I know that you are actually enjoying it. Also, don't forget to subscribe below and turn on the notifications so you can get notified when I release more of this kind of content. And if you want to get more on game development content and get some exclusive perks and rewards, you can become one of my patrons. So go there, check out the tiers, we have some very cool rewards and perks. So pick one tier and become one of my beloved supporters. So, this is it. Thank you so much for watching. Keep developing, and to the next time.