﻿1
00:00:04,120 --> 00:00:04,510
‫Hey.

2
00:00:04,510 --> 00:00:05,440
‫Welcome back.

3
00:00:05,470 --> 00:00:11,740
‫Now we've set ourselves up with a callback function bound to the delegate on take any damage.

4
00:00:11,830 --> 00:00:16,210
‫And the last step is to actually generate that damage event.

5
00:00:16,210 --> 00:00:19,690
‫And we want to do this when our projectile hits something.

6
00:00:19,690 --> 00:00:25,540
‫Once we broadcast for this delegate, we can apply damage to the thing that we hit.

7
00:00:25,540 --> 00:00:32,110
‫And we're going to broadcast this event using applied damage, which belongs to the gameplay statics

8
00:00:32,110 --> 00:00:32,830
‫class.

9
00:00:32,860 --> 00:00:36,310
‫So let's take a look at the applied damage function.

10
00:00:36,400 --> 00:00:44,050
‫Now here's the documentation for applied damage it says hurts the specified actor with generic damage.

11
00:00:44,050 --> 00:00:47,590
‫So this is a generic function for applying damage.

12
00:00:47,590 --> 00:00:52,510
‫And what we do in response to broadcasting for this delegate is up to us.

13
00:00:52,540 --> 00:00:59,140
‫Now here we see we need to include gameplay statics and in the syntax we see several input parameters.

14
00:00:59,140 --> 00:01:02,110
‫Now we actually get some description of the parameters.

15
00:01:02,110 --> 00:01:08,290
‫If we keep scrolling down, we see that damaged actor is well, the actor that will be damaged base

16
00:01:08,290 --> 00:01:13,660
‫damage is the base damage to apply really descriptive documentation here.

17
00:01:13,690 --> 00:01:14,170
‫Thanks.

18
00:01:14,170 --> 00:01:19,930
‫Epic event instigator is the controller that was responsible for causing this damage.

19
00:01:19,930 --> 00:01:23,020
‫And it says, for instance, the player who shot the weapon.

20
00:01:23,020 --> 00:01:26,260
‫When it says player, it's referring to that controller.

21
00:01:26,260 --> 00:01:31,120
‫Then we have the damage causer, which is the actor that actually caused the damage.

22
00:01:31,120 --> 00:01:33,160
‫It says the grenade that exploded.

23
00:01:33,160 --> 00:01:35,980
‫In our case, it'll be the projectile that exploded.

24
00:01:35,980 --> 00:01:43,000
‫And finally, we have damage type class, which is a class that describes the damage that was done.

25
00:01:43,000 --> 00:01:49,690
‫Now back up in the syntax section, we can see the types of these inputs and we see that damage type

26
00:01:49,690 --> 00:01:56,350
‫class is a subclass of and we've seen before that TW subclass of will satisfy an input parameter of

27
00:01:56,350 --> 00:01:57,550
‫type U class.

28
00:01:57,550 --> 00:02:03,730
‫Well when we call apply damage, we can pass in a U class representing the damage type we'd like to

29
00:02:03,730 --> 00:02:04,360
‫use.

30
00:02:04,360 --> 00:02:09,280
‫So we'll talk about how we're going to satisfy this input parameter in just a moment.

31
00:02:09,280 --> 00:02:15,190
‫So the hue gameplay statics function, applied damage is going to take a few input parameters.

32
00:02:15,190 --> 00:02:20,920
‫So let's strategize on how we're going to pass in the appropriate values when we call this function,

33
00:02:20,920 --> 00:02:24,100
‫we saw that first we need the damaged actor.

34
00:02:24,310 --> 00:02:30,220
‫Well, let's go back into projectile CP where we'd like to call apply damage.

35
00:02:30,220 --> 00:02:34,660
‫We'd like to do it here in on hit and we no longer need these logs.

36
00:02:34,660 --> 00:02:42,190
‫So I'm simply going to remove them and notice that our on hit callback gets some inputs passed in once

37
00:02:42,190 --> 00:02:43,450
‫it gets called.

38
00:02:43,450 --> 00:02:49,240
‫When the on component hit delegate is broadcast, we'll see that we have other actor.

39
00:02:49,240 --> 00:02:55,930
‫So we have access to the actor that got hit by the projectile and this is the actor we would like to

40
00:02:55,940 --> 00:02:56,740
‫damage.

41
00:02:56,740 --> 00:02:59,320
‫So that takes care of the first input parameter.

42
00:02:59,320 --> 00:03:01,390
‫It's going to be that other actor.

43
00:03:01,390 --> 00:03:07,990
‫Next, we need the damage amount, which means our projectile should have a damage variable so that

44
00:03:07,990 --> 00:03:10,360
‫we know how much damage to apply.

45
00:03:10,510 --> 00:03:17,650
‫So why don't we go into projectile FX and add a damage variable and this can be a float.

46
00:03:17,650 --> 00:03:23,770
‫So we can simply call this damage and we can initialize it to a value, let's say something like 50

47
00:03:24,040 --> 00:03:29,890
‫F and since this is something we'd probably want to experiment with, we can give this a U property

48
00:03:29,890 --> 00:03:32,860
‫to expose it and make it edit anywhere.

49
00:03:32,860 --> 00:03:37,780
‫So now we have a damage amount to pass in when we call take damage.

50
00:03:38,080 --> 00:03:44,140
‫Now the next parameter is the instigator and we saw that this is of type A controller.

51
00:03:44,140 --> 00:03:46,870
‫So how are we going to get the controller?

52
00:03:46,870 --> 00:03:53,470
‫Well, we've seen that we can get the owner of a particular component with the get owner function.

53
00:03:53,470 --> 00:04:00,820
‫And this returns the actor that owns a particular component, these projectiles are being spawned dynamically.

54
00:04:00,820 --> 00:04:06,640
‫So we need to make sure if we're going to be calling get owner that the owner is set now we're spawning

55
00:04:06,640 --> 00:04:08,410
‫these from base pawn.

56
00:04:08,410 --> 00:04:10,390
‫So if we go into base pawn.

57
00:04:10,600 --> 00:04:18,880
‫CP Here's the line where we're spawning the actor, but Spawn Actor also returns a pointer to the actor

58
00:04:18,880 --> 00:04:22,690
‫that was spawned so we could store this in a local variable.

59
00:04:22,690 --> 00:04:29,220
‫For example, we could say auto projectile and assign the value returned from spawn actor.

60
00:04:29,230 --> 00:04:35,770
‫Now if you're not familiar with auto, it allows the compiler to figure out the type to assign to this

61
00:04:35,770 --> 00:04:36,790
‫new variable.

62
00:04:36,790 --> 00:04:42,620
‫If you hover over it, you'll see that it has the type A projectile pointer because that is what we're

63
00:04:42,670 --> 00:04:45,610
‫signing from the spawn actor function.

64
00:04:45,610 --> 00:04:52,960
‫So this is the same as if we had put a projectile pointer right here and now we can access that newly

65
00:04:52,960 --> 00:04:54,400
‫spawned projectile.

66
00:04:54,400 --> 00:04:57,820
‫And the reason we want to do that is we'd like to set its owner.

67
00:04:57,820 --> 00:05:02,710
‫We would like to make sure that its owner is set to the pawn that spawned it.

68
00:05:02,920 --> 00:05:04,930
‫So we can say projectile.

69
00:05:04,930 --> 00:05:08,010
‫And there's a function for this called set owner.

70
00:05:08,020 --> 00:05:15,400
‫Set owner takes an actor and we're going to pass in this so that whenever one of our pawns spawns a

71
00:05:15,400 --> 00:05:18,250
‫projectile, it will set that projectiles owner.

72
00:05:18,250 --> 00:05:23,380
‫So that way, if we ever call get owner further down the line, we'll get the instance of the class

73
00:05:23,380 --> 00:05:25,700
‫that owns that projectile.

74
00:05:25,720 --> 00:05:33,190
‫So back here in projectile DHCP, we have our get owner function call and we can store this in a local

75
00:05:33,190 --> 00:05:33,910
‫variable.

76
00:05:33,940 --> 00:05:40,600
‫I'm going to go ahead and use auto again and call this my owner and set it to the result returned by

77
00:05:40,600 --> 00:05:41,590
‫get owner.

78
00:05:41,920 --> 00:05:47,570
‫So now we have a local actor pointer that stores the value of the owner.

79
00:05:47,590 --> 00:05:52,190
‫Now we can access the instigator controller from this actor.

80
00:05:52,210 --> 00:05:57,640
‫Now, before we do so, it's a good idea to check to make sure my owner isn't null.

81
00:05:57,640 --> 00:06:04,460
‫So I'm going to say if my owner is null equals equals null pointer, then I'm simply going to return.

82
00:06:04,480 --> 00:06:09,640
‫Now, if you're if body has a single statement like this, you can place it on the same line without

83
00:06:09,640 --> 00:06:11,890
‫the curly braces in case you didn't know.

84
00:06:11,890 --> 00:06:19,470
‫And null pointer is a keyword in C++ that allows you to check to see if a pointer is a null pointer.

85
00:06:19,480 --> 00:06:25,760
‫So if my owner is null, then we will return out of the function early and not do anything else.

86
00:06:25,780 --> 00:06:31,030
‫Now, as I was saying, we can get the instigator controller from my owner and that's what the use of

87
00:06:31,030 --> 00:06:35,500
‫the function called get instigator controller.

88
00:06:36,400 --> 00:06:40,590
‫And if we hover over this, we'll see that it returns an A controller pointer.

89
00:06:40,600 --> 00:06:48,250
‫I'm simply going to use auto and store this in a local variable that I'll call my owner instigator.

90
00:06:50,660 --> 00:06:54,460
‫So now we know what to pass in as the instigator.

91
00:06:54,470 --> 00:07:00,800
‫The next input is the damage causer and this is the actor doing the damage for the projectile.

92
00:07:00,800 --> 00:07:02,930
‫This is going to simply be this.

93
00:07:02,930 --> 00:07:07,490
‫And that leaves the last input parameter, which is a damage type.

94
00:07:07,490 --> 00:07:12,740
‫And we saw that it's a subclass of which means we need the proper use class to pass.

95
00:07:12,740 --> 00:07:17,960
‫N Now here's the unreal engine documentation for you damage type.

96
00:07:17,960 --> 00:07:24,050
‫It says a damage type is intended to define and describe a particular form of damage and to provide

97
00:07:24,050 --> 00:07:28,370
‫an avenue for customizing responses to damage from various sources.

98
00:07:28,370 --> 00:07:30,890
‫Now, we're not going to customize our damage.

99
00:07:30,890 --> 00:07:38,090
‫We just need to satisfy the input parameter, which means we need a U class value that represents this

100
00:07:38,090 --> 00:07:40,070
‫you damage type class.

101
00:07:40,310 --> 00:07:48,200
‫Now in C++, if we want to get the YOU class of any particular class such as you damage type, we can

102
00:07:48,200 --> 00:07:51,020
‫call a function called static class.

103
00:07:51,020 --> 00:07:54,140
‫This is inherited from the you object class.

104
00:07:54,170 --> 00:07:58,070
‫Now of course we're using you damage type here so we'll need that header.

105
00:07:58,310 --> 00:08:05,690
‫So from the documentation I will copy the include line and I'll paste it up here at the top of projectile

106
00:08:05,960 --> 00:08:14,450
‫CP And now you'll see that this static class function returns a U class pointer and that new class will

107
00:08:14,450 --> 00:08:17,780
‫represent the new damage type C++ class.

108
00:08:17,780 --> 00:08:23,510
‫Now, since we're not creating a blueprint based on you damage type and setting some extra data, we

109
00:08:23,510 --> 00:08:26,030
‫don't really need a subclass of variable.

110
00:08:26,150 --> 00:08:32,750
‫So in this case we can use static class and this will return a U class that represents this type.

111
00:08:32,750 --> 00:08:38,480
‫And we can store this in a variable if we like, and I'll call this damage type class.

112
00:08:40,390 --> 00:08:45,520
‫And this is what we can pass in as the final parameter to apply damage.

113
00:08:45,520 --> 00:08:51,250
‫So we now have all of the information we need to pass into the apply damage function.

114
00:08:51,250 --> 00:08:57,100
‫But before we do so, I'd like to place a couple of checks to make sure it's appropriate that we call

115
00:08:57,100 --> 00:08:58,000
‫this function.

116
00:08:58,000 --> 00:09:00,090
‫So I'll make an if statement here.

117
00:09:00,100 --> 00:09:03,550
‫First, I want to make sure that other actor is not null.

118
00:09:03,550 --> 00:09:06,490
‫So I'm going to place other actor here.

119
00:09:06,490 --> 00:09:13,450
‫I'm going to place an and here so I can check to make sure other actor is not equal to this actor.

120
00:09:13,450 --> 00:09:19,840
‫We don't want to cause damage to ourselves if we are the projectile now I'm going to place another end

121
00:09:19,840 --> 00:09:24,640
‫and make sure that other actor is not equal to my owner.

122
00:09:24,760 --> 00:09:28,930
‫It wouldn't be good if the projectile is causing damage to its owner.

123
00:09:28,930 --> 00:09:35,200
‫And now if we get inside this if statement, then we know that it's appropriate to call apply damage

124
00:09:35,200 --> 00:09:36,550
‫so we can do so.

125
00:09:36,550 --> 00:09:38,290
‫And that's going to be your challenge.

126
00:09:38,290 --> 00:09:45,070
‫So in our new if statement in the on hit function call the you game play statics apply damage function.

127
00:09:45,070 --> 00:09:51,310
‫This means you'll need to include the correct header for gameplay statics and you know which input parameters

128
00:09:51,310 --> 00:09:52,450
‫to pass in.

129
00:09:52,570 --> 00:09:58,660
‫So pause the video and add the function call to apply damage in the on hit function now.

130
00:10:02,740 --> 00:10:03,250
‫Okay.

131
00:10:03,250 --> 00:10:11,020
‫So I'm here in projectile CP and I'm going to include the header file for gameplay statics and we can

132
00:10:11,020 --> 00:10:17,260
‫see from the Applied Damage Documentation page that the include is kismet slash gameplay statics.

133
00:10:17,980 --> 00:10:22,330
‫So I'm going to paste that in there and now I'm ready to call apply damage.

134
00:10:22,330 --> 00:10:28,060
‫So I'm going to call you gameplay statics apply damage.

135
00:10:28,810 --> 00:10:35,140
‫Now as soon as I type that opening parentheses, I get the pop up reminding me of the input parameters

136
00:10:35,140 --> 00:10:35,800
‫I need.

137
00:10:35,800 --> 00:10:40,360
‫And the first one is the damaged actor and that's going to be other actor.

138
00:10:40,360 --> 00:10:42,760
‫So we're going to type other actor next.

139
00:10:42,760 --> 00:10:50,410
‫We need the damage amount and we added this damage float in projectile FX, which we set to 50.

140
00:10:50,410 --> 00:10:53,170
‫So I'm going to pass damage end next.

141
00:10:53,170 --> 00:10:56,920
‫We need the instigator and we have my owner instigator.

142
00:10:56,920 --> 00:11:00,010
‫So I'm going to pass in my owner instigator.

143
00:11:00,010 --> 00:11:01,960
‫Next is the damage causer.

144
00:11:01,960 --> 00:11:05,500
‫And of course, the projectile itself is the damage causer.

145
00:11:05,500 --> 00:11:07,210
‫So we're going to pass in this.

146
00:11:07,210 --> 00:11:14,860
‫And finally we need the subclass of for you damage type which we know a U class pointer will satisfy

147
00:11:14,860 --> 00:11:17,980
‫that and that's why we have our damage type class.

148
00:11:17,980 --> 00:11:21,910
‫So let's pass in damage type class.

149
00:11:21,910 --> 00:11:25,570
‫And with that we're now calling apply damage.

150
00:11:25,720 --> 00:11:33,040
‫So when we call this, we will generate the damage event and the on take any damage delegate will broadcast

151
00:11:33,040 --> 00:11:39,010
‫in response to this, which means in our health component damage taken will be called.

152
00:11:39,010 --> 00:11:42,580
‫So we just need to do something here in damage taken.

153
00:11:42,580 --> 00:11:47,440
‫Well, it would make sense to take this damage and subtract that amount from the health.

154
00:11:47,440 --> 00:11:52,510
‫Before we do that, though, I'd like to make sure that damage is not less than or equal to zero.

155
00:11:52,810 --> 00:11:59,170
‫F It makes sense to make these checks before documenting damage, just to make sure that we don't apply

156
00:11:59,170 --> 00:12:02,890
‫a value that doesn't make any sense, like zero or a negative value.

157
00:12:02,890 --> 00:12:05,740
‫So if that's the case, we'll simply return.

158
00:12:05,740 --> 00:12:11,800
‫And of course, if you'd like to be slick and do what I did in projectile at CP, we can place the return

159
00:12:11,800 --> 00:12:12,700
‫right there.

160
00:12:12,700 --> 00:12:19,840
‫Now, if we make it past this line, damage is a positive value so we can take health and use minus

161
00:12:19,840 --> 00:12:21,460
‫equals damage.

162
00:12:21,550 --> 00:12:25,750
‫And just to make sure that this is working, why don't we place a euy log here?

163
00:12:25,750 --> 00:12:37,960
‫So Yui log log, temp warning text and we can simply print the value of health with percent F and health

164
00:12:37,960 --> 00:12:40,840
‫and with that we can compile.

165
00:12:40,870 --> 00:12:47,200
‫Now with a successful compile, we'll hop back into the editor and with our output log open, let's

166
00:12:47,200 --> 00:12:47,980
‫hit play.

167
00:12:47,980 --> 00:12:51,010
‫Now let's see if we can get hit by a projectile.

168
00:12:51,010 --> 00:12:52,120
‫And there we go.

169
00:12:52,150 --> 00:12:58,810
‫Our health is now down to 50 and if we get hit again, we got quite a few hit events because we were

170
00:12:58,810 --> 00:13:02,410
‫hitting up against the projectile many times very quickly.

171
00:13:02,410 --> 00:13:05,770
‫But we see that our health is documenting properly.

172
00:13:05,770 --> 00:13:11,620
‫So we do need to make sure we implement the correct behavior upon death when health reaches zero.

173
00:13:11,620 --> 00:13:17,290
‫But we also need to make sure that we don't get this hit event spammed multiple times.

174
00:13:17,290 --> 00:13:23,560
‫Now we know that the projectile should be destroyed upon hitting something, so the best way to prevent

175
00:13:23,560 --> 00:13:26,800
‫spamming the hit event is to destroy the projectile.

176
00:13:26,800 --> 00:13:29,290
‫So that's the last thing we'll do in this video.

177
00:13:29,290 --> 00:13:36,460
‫So back in projectile just after applied damage, what we can do is have the projectile destroy itself

178
00:13:36,460 --> 00:13:38,050
‫and that couldn't be easier.

179
00:13:38,050 --> 00:13:41,110
‫We simply call the destroy function.

180
00:13:41,110 --> 00:13:48,880
‫So with one more compile back here in the editor, we can go ahead and get hit by a projectile and look

181
00:13:48,880 --> 00:13:49,330
‫at that.

182
00:13:49,330 --> 00:13:51,520
‫The projectile is gone.

183
00:13:51,520 --> 00:13:55,360
‫So it does its damage and then it disappears.

184
00:13:55,360 --> 00:14:02,110
‫And of course we can test out hitting the towers as well by blasting them with projectiles and making

185
00:14:02,110 --> 00:14:04,570
‫sure that those hit events are triggering.

186
00:14:04,570 --> 00:14:10,750
‫And as you can see, I can spam this with a whole bunch of projectiles and we'll see that the health

187
00:14:10,750 --> 00:14:16,390
‫value for this poor tower here is getting very, very negative.

188
00:14:16,540 --> 00:14:23,650
‫So in summary, we called the apply damage function and this resulted in a broadcast for the on take

189
00:14:23,650 --> 00:14:25,030
‫any damage delegate.

190
00:14:25,030 --> 00:14:30,130
‫We documented the health in the health component and we destroyed the projectile.

191
00:14:30,130 --> 00:14:32,350
‫So we've now taken care of damage.

192
00:14:32,350 --> 00:14:34,390
‫We have not yet taken care of death.

193
00:14:34,390 --> 00:14:38,860
‫So that will be one of the next things we'll cover in a future video.

194
00:14:39,310 --> 00:14:40,270
‫I'll see you soon.

