Free YouTube Transcribe

Video transcript

Smart Enemy AI | (Part 12: Team Combat System) | Tutorial in Unreal Engine 5 (UE5)

Ali Elzoheiry · 6,857 words · 32 min read

Want to search this transcript, jump the video from any line, or download it as TXT, SRT, or VTT?

Open in the transcript tool

Full transcript

Outcome of This Part

0:00[Music]

0:05welcome back everyone to Part 12 of our

0:08smart enemy AI Series in this part we're

0:10going to be setting up our team system

0:12so right now I have all these teams all

0:15these enemies in team number one as you

0:16can see here and I'm also team number

0:18one as a player so none of them will be

0:21attacking me because we're on the same

0:22team

0:24now if I change this guy to be team

0:26number two

0:27then he's gonna try to attack me and as

0:30soon as they see him they're all gonna

0:31try to attack him so we're not only

0:33going to be looking at

0:35um how to get enemies to perceive people

0:37on their team or not on their team but

0:39we're also going to make sure that the

0:41melee enemy and ranged enemy can't

0:43damage people that are not uh that's

0:45sorry that are on their same team so

0:47we're pretty much disabling Friendly

0:49Fire

0:50so let's get started

0:52all right so before we start with

Improving the Block Functionality of the Melee Enemy

0:54setting up our team system I want to fix

0:57um something annoying which is uh when

0:59you have multiple melee enemies and you

1:01attack them they all block at the same

1:04time

1:06um this is quite annoying because they

1:07detect when their attack Target is

1:10attacking they don't detect if they're

1:12the ones being attacked or if the attack

1:14is actually going to hit them or not so

1:16we're going to modify the block Behavior

1:17to make the group enemy combat look a

1:20bit more realistic so let's start by

1:22doing that

1:24so first thing we need is in our AI

1:27folder uh Behavior trees and our melee

1:30enemy tree we're going to delete our

1:35where is it our block branch

1:40is yeah so this one so we checked the

1:42target's attacking and then we do a

1:44block I'm going to delete this Branch

1:46completely okay we're not going to

1:47handle the block functionality now in

1:49the behavior tree

1:50why is that because I want the melee

1:53enemy to block as soon as they take

1:55damage and that means we're going to

1:57handle it in the take damage function

1:59so let's see how we can do that

2:02let's now open up our

2:05enemies our melee enemy

2:10all right

2:12and where we

2:15um

2:18so over here this is where we do our

2:20blocking right I'm gonna keep these

2:22functions so the start block unblocked

2:25and N block we're still going to use

2:26them but we're going to modify them a

2:27bit uh but what we actually want to do

2:30is override the take damage function so

2:33we have take damage here that's

2:35implemented in the base enemy and in the

2:38base enemy all it does so take damage

2:40all it does is call take damage from the

2:43um damage system from the damage system

2:46component now the nice thing about using

2:48a actor component is that we can keep

2:51this function call but over or do things

2:53before or after it in our melee enemy so

2:56I'm going to go back to the melee enemy

2:58and double click on my damage to take

2:59damage function now I've overridden this

3:03function so it's now not under

3:05interfaces but under functions that

3:06means I'm overriding whatever base

3:08implementation was already there

3:10and I'm going to just paste the take

3:13damage function from the bpc damage

3:15system as is

3:18plug everything in like it was but now

3:21right before

3:23uh I call take damage I'm going to try

3:27to block and I say try because I'm going

3:29to have it be a percentage so there's a

3:31chance that the melee enemy will block

3:32so let's create a function a new

3:35function here and call it try to block

3:39all right and this function

3:42um we'll call start block

3:44but it won't always call it it will call

3:46it under a condition right so we're

3:48going to put a branch here and this

3:50condition is if uh we generate a random

3:53float so let's say random floats this

3:57will give you a random number between 0

3:59and 1 and we're going to check is this

4:01number uh greater than or equal

4:05if we say for example greater than or

4:07equal 0.1 then there is a 90 chance that

4:13the sorry actually let's make it less

4:14than or equal

4:15I'll show you one so if we say if it's

4:18less than or equal

4:20um 0.9 that means there's a 90 chance

4:23that the enemy will block if it's less

4:26than or equal 0.3 there's a 30 chance to

4:29enable block and so on

4:31so I'm gonna make it

4:340.25 so 25 chance block and I'm actually

4:37going to promote it to a variable and

4:39call it blockchains

4:43all right and this will be the condition

4:44to our try to block function

4:48so that's really it

4:49um which checks if we have a chance to

4:52block and if so we call start block and

4:55if you recall start block stops movement

4:58sets is blocking to true this is the

5:00most important thing and does some other

5:02things we'll look at it in a bit

5:05over here in our take damage function we

5:07want to call our

5:08try to block

5:11all right

5:14um but there's also one condition you

5:15want to add here and if you recall not

5:18all attacks can be blocked so we have

5:20attacks that are blockable and attacks

5:22are not and this is in the damage info

5:24so if I pull off damage info and say

5:26break here I will have can be blocked so

5:29I'm going to first check if can be

5:31blocked is true because I don't want to

5:33try to block if I know this attack can't

5:35be blocked that's kind of useless

5:39um and by the way if I click here and

5:40say hide unconnected pins then it's

5:42going to make this a bit cleaner and

5:44only show the pin that I connected

5:46all right so now I check if I if this

5:49attack can be blocked then I try to

5:51block otherwise I continue and also on

5:54the false I'm going to just skip the try

5:55block and go right to take damage

5:57because if the attack can't be blocked

6:00then I just want to continue and not try

6:02to block

6:04all right

6:05let me just clean these up a bit because

6:08of my

6:09OCD

6:13all right

6:15looks better

6:17um

6:18great so now before we take damage we

6:21try to block

6:22um now let's modify our start block a

6:25bit

6:25if you recall we used to play a montage

6:27this is the Montage where the enemy

6:29first takes the block stance and then if

6:31they successfully block we play another

6:33Montage which is the one where they

6:35actually do the moving back a bit with

6:37their sword so we don't need this

6:39Montage anymore because

6:41the time between a getting starting to

6:44block and actually blocking or not is

6:46the time it takes for this Branch to go

6:49from here to here so it's pretty much

6:51instantly so this Montage will never get

6:53the chance to play so we're gonna remove

6:55it and we're gonna remove all of this as

6:56well

6:58um but actually let's keep end block

7:00because we still want to end block if

7:03something happens uh what do I mean by

7:05if something happens well in the normal

7:07flow we're going to try to block if we

7:10are successful we're going to block the

7:13damage and then

7:15um unblocked will be called and then n

7:18block will be called after the Montage

7:20is finished right

7:21but something could happen where uh we

7:24try to block which we set is blocking to

7:27true but we don't actually take the

7:29damage

7:30so in that case we need a way to end

7:32block as well

7:33so I'm going to set a timer so I'm gonna

7:35go over here and say set timer by events

7:40and this event will be say create event

7:43and it will be end block

7:46um actually we don't need this then

7:47because I'm calling it as an event

7:49and we're going to say after maybe two

7:52seconds so if you are blocking

7:56if you start to block two seconds later

7:57end the block

7:59and we're going to create a timer sorry

8:02variable for this timer we're going to

8:03call it the

8:05um hold block timer

8:11um

8:12and if

8:14we call end block before this timer ends

8:17we want to stop the timer because we

8:18don't want to call end block twice right

8:20so over here in the end block well

8:24actually no not if we unblock if we

8:26block successfully so right here before

8:28doing this we want to get a reference to

8:31our timer

8:32and say clear and invalidate timer by

8:36handle so that if we block successfully

8:38then ignore this timer clear it we don't

8:40need to block anymore

8:44um and also we need to do the same thing

8:47when we start blocking if there's

8:48already a timer running

8:50um delete that timer because we're going

8:52to be creating a new one

8:54so I'm going to move all of these this

8:56one to this one

8:59and paste this here

9:01so now we clear the timer when we start

9:03to block as well

9:05excellent now let's uh let's take a look

9:08at Let's test this out and see what it

9:09looks like

9:11all right so now I have multiple enemies

9:14all right he did not block he did not

9:17block we have a 25 chance

9:19remember but as you can see now they're

9:22not all gonna block oh that he blocked

9:24nice

9:25let me increase it to this blockchains

9:29here let me increase it to a hundred so

9:30one that means they'll always block just

9:32to see how it works

9:34so this guy nice and you see only the

9:36one that was attacked is the one that's

9:38blocking

9:42and let me show you one last time

9:44foreign

9:47I think this looks

9:50um a lot better than what we had before

9:52and now we can jump into our team system

Setting Up Team Numbers

9:57all right so the first thing we need to

9:58do is uh let me close the melee here

10:03um first thing we need to do is we're

10:04going to modify our

10:07um

10:08damageable interface so in our damage

10:10system and BPI damageable

10:13and we're going to add a function here

10:14we're going to call it get team number

10:18so we're going to have teams assigned by

10:20number so there's team one team two team

10:22three and so on so you can have as many

10:23teams as you want

10:25and of course enemies with the same

10:26number are on the same team or even the

10:28player can be of the same number as an

10:30enemy and it's just going to return the

10:32team number which is going to be an

10:34integer

10:37all right so this is in the damageable

10:38interface so there are two actors that

10:41implement this interface now our player

10:44and our base enemy

10:47so if I go to my player here I should

10:50see the get team number and it just

10:54wants me to return a number now I'm not

10:56going to set it here I'm going to create

10:57a new variable for it and call it team

11:00number

11:02an integer

11:05and we're gonna plug it in here

11:09compile to add a default value and let's

11:11say the player defaults to one and we're

11:13going to do the same thing the base

11:14enemy gets our uh get team number where

11:19is it so many functions okay

11:22um and well you can also right click

11:24promote the variable and call it team

11:26number

11:28and for the enemy let's default to T

11:31number two

11:33and also one thing to note for the enemy

11:35make sure to click on this uh I icon and

11:38say also uh you don't have to say expose

11:40on spawn but let's do it so instance

11:42editable and expose on spawn because

11:44that way you can click here and search

11:46for team number

11:49team did I not compile I did not compile

11:54now I can search for T number and I can

11:55change it so I can say this guy is team

11:57three this guy's team two for example

12:00you get the idea

12:03um

12:03all right so now we have a way to

Preventing Team Members from Sensing Each Other

12:06um assign team numbers uh now what's

12:09what what do we need to check where do

12:12we need to call this get team number

12:13well it's going to be in a few places

12:15but first one is in our enemy AI

12:18controller because this is where we have

12:19our senses right so when you sense sites

12:23we want to check did I see a team member

12:25or did I see an enemy when you sense

12:27um damage you want to see was I damaged

12:29by team member or otherwise I damaged by

12:31a non-team member

12:33um so to check if we're on the same team

12:37as someone or not we're going to create

12:38a function here and we're going to call

12:40it

12:41um on same team

12:44and it takes an input the other actor

12:47that we're checking so other actor of

12:49type actor object reference

12:53and it returns

12:56um a Boolean value same team yes or no

12:58or true or false

13:02but since uh we added the get team

13:04number as a interface then we can call

13:07it as an interface function and we can

13:09call it without casting of course so we

13:11can say get team number

13:13so now we're getting the team number of

13:15the uh actor that we just sensed or the

13:18other actor and we're also going to get

13:20team number of our self of the person

13:23the pawn that's this controller is

13:25controlling so to do that you can say

13:27get controlled upon this gets to the

13:30pawn that this AI controller is

13:32controlling and call get team number on

13:34that

13:36all right and they are the same team if

13:38these two numbers are equal so if this

13:41number equals this number then same team

13:45is true

13:47otherwise of course it's false

13:51all right so let's look at our handle

13:55sense site

13:57so here

13:59um we don't need this because this we

14:00were checking if the player is if the

14:03person we sensed is a player we're going

14:05to delete all of this

14:07because now we're going to do a new

14:08check we're going to check

14:11um is and what's it called on same team

14:15so we're going to check if this other

14:18actor we can get it from from here

14:22if this other actor is on the same team

14:25uh and if not so if they're not on the

14:28same team let me

14:30move this

14:33let's create a branch if they are not

14:38on the same team

14:41then we will continue

14:43and if they are on the same team we're

14:44not going to do anything I just saw

14:46someone on my same team don't have to do

14:48anything about it

14:51all right

14:53um and that's oh sorry and that's it for

14:56the sense site sent sound we're going to

14:59keep the same because you don't know if

15:01the sound is coming from your team

15:02member or not just hear a sound You're

15:04Gonna Go investigate even if it's coming

15:05from a team member

15:07uh damage though is an interesting one

15:09because

15:10um after this we're gonna make sure that

15:12actors on your same team can't damage

15:15you but sometimes there's an explosion

15:17for example that damages everyone so we

15:19don't want anything to happen if you

15:21sense damage from a team member so we're

15:23also going to check here

15:25if

15:27on same team this function we created

15:33pass our actor here

15:35and again only if we are not

15:40on the same team

15:45and plug this in of course you don't

15:47have to do the knot you can also plug in

15:49on the false but I feel like this is

15:50easier to read on same team not then do

15:53this I like reading this a bit better

15:59all right

16:02um anywhere else that we need to handle

16:04this

16:07I think this is good for now let's see

16:09how this uh looks like so obviously

16:11right now they are all on the same team

16:14by default so if I just play somewhere

16:16here behind them where they don't see me

16:19um

16:21they shouldn't be attacking each other

16:24why are they attacking he's team number

16:26two

16:28he's team oh he's team number three okay

16:32so actually it was working but yeah

16:34let's make them all the same team let me

16:35just start by two to make sure we don't

16:37have any weird Behavior so he's team two

16:40and he's team two

16:42right if I'm gonna play from here

16:45they're not gonna do anything of course

16:47if they see me now they're gonna attack

16:49me because I'm team number one

16:51and now if I change this guy to team

16:53number one as well

16:56uh and I play from here

16:59then they start attacking each other

17:02great

17:04um

17:05and

17:06um also because uh I'm team number one

17:09if I have only one enemy so if I remove

17:12this guy this guy is now team number one

17:14like me and he sees me he's not gonna do

17:17anything and if I damage him he's just

17:20he's just not gonna be happy about it

17:21but he's not gonna do anything

17:23and by the way we we can still block

17:25even though um

17:28even though it doesn't have a sword

17:29maybe we should check first if he has a

17:31weapon equipped or not uh but anyway

17:34um the team functionality is uh is

17:38working now

17:39so if I have

17:42two enemies here

17:44and two enemies here

17:46and let's make them different teams and

17:49watch them fight each other so this guy

17:53is going to be team three this guy is

17:55going to be team three and these are

17:57both team two and

18:00two

18:02all right let me go behind them so they

18:04don't see me

18:06excellent now they'll all be attacking

18:08each other great

18:12um

18:15yes

18:16seems to be working

Modifying Melee Attack To Not Damage Team Member

18:18now let's make sure that we don't

18:20enemies on the same team can't damage

18:23each other and why is this important

18:26um because

18:28right now if I look at my melee enemy so

18:30if I open up my EP

18:33enemy melee here

18:36uh you can see in my attack I do a

18:38sphere trace and as soon as this sphere

18:41Trace hits something I call take damage

18:43on this actor that we hit I don't check

18:45this actually on the same team or not

18:47so that means if I'm standing between uh

18:50one of my team members and an enemy

18:52I'm the one taking damage and it's not

18:55enough here to just say

18:57um if we're on the same team then don't

18:58take damage because then the person

19:01behind me should take the damage like if

19:05um I'm standing between these two

19:06enemies right here and this enemy is

19:09trying to attack this one

19:10then he should still be able to attack

19:12him even if I'm in between them this

19:15means that we can't do a single sphere

19:17Trace we have to check did the sphere

19:19Trace hit a team member no then do

19:21another sphere trace and check if it

19:23hits another uh one that's not a team

19:25member luckily we don't have to keep

19:26doing multiple sphere traces ourselves

19:28there's something called a multi-sphere

19:31Trace

19:33um and it does the same thing as a

19:35sphere Trace but instead it gets you a

19:37list of everything that it hits so then

19:40we're gonna do a trace we're gonna get

19:41all of the actors that were hit in this

19:43trace and check which one is not a team

19:46member and damage that one because of

19:49course a sword swing can damage multiple

19:51enemies not just one

19:53um so this is really important

19:55so let's replace this sphere Trace with

19:57a multi-sphere Trace

19:59um now everything is going to pretty

20:00much be the same so you can take this

20:02pin here the start is going to still be

20:04the start and it's going to be the end

20:06radius is going to be also 20 object

20:10types take it from here

20:12and also this execution pin goes here

20:15this goes here and now this is the only

20:18thing that's going to be different right

20:19so

20:22um now instead of having one hit

20:27structure we have multiple an array of

20:29hits

20:31so we're going to Loop over this array

20:35so I'll do a for each Loop

20:37and only if there is a hit

20:40so under the true here Duo for each and

20:43then plug this here

20:46all right so if I do this

20:48um something weird is going to happen

20:50and let me show you before we do

20:51anything first

20:53let me start by deleting all these

20:56enemies and have I deleted the floor and

20:59have one enemy

21:00so just for you to be aware I'm going to

21:03set the damage to 10. so the enemy can

21:05only do 10 damage but look at what

21:07happens uh when I play

21:10obviously my health is a hundred so I

21:12should only take 10 damage but I took a

21:14lot more than 10. I think my health is

21:1650 actually but I took a lot more than

21:1810. and the reason is multi-sphere Trace

21:21can overlap with the same actor multiple

21:23times so if I print here let's say print

21:27this actor

21:29look at what's being printed on the top

21:32left here player was printed one two

21:34three four five six seven like about

21:36eight or nine times

21:37so before actually calling take damage

21:40or checking if we're on the same team or

21:42not we want to check have we previously

21:44hit this actor or not because we want to

21:47make sure we only hit the actor once per

21:50sword swing we don't want to hit the

21:51same actor multiple times

21:54um so we need two things to check

21:56whether we hit this actor or not and

21:58whether they're on the same team or not

21:59so I'm going to create a function for

22:01this but I'm going to create it in our

22:03bpc

22:04attacks so this is our attacks actor

22:07component so right click here and edit

22:09the bpc attacks

22:11and I'm gonna create a function call it

22:13damage all non-team members

22:19and this will take us input the hits

22:21array so this array here because we want

22:25to Loop over it so I was going to take a

22:28hit

22:29hits and it's going to be of type

22:32hit results

22:34and then make sure next to the hit

22:36result click on this and make it an

22:38array so it's going to take this and

22:41it's going to return the uh actors

22:45damaged

22:48and this is going to be of type actor

22:52and is also going to be an array because

22:54it's the array of actors that were

22:55damaged all right so first thing is we

22:59need to Loop

23:00over these array over these hit results

23:04and then we're going to break and break

23:07each hit result and get the actor from

23:10it

23:11and check uh get team number of this

23:14actor

23:15so first we want to check is this actor

23:17on my same team or not

23:20so to get my same team notice that we

23:23are in the bpc attacks so to get the

23:26owner we say get owner the actor that is

23:30using this actor component we're going

23:32to call get team number

23:35so we're going to check again if they

23:37are equal or not so not equal

23:41so if they are not equal then this

23:44person is on a different team right so

23:47then we will proceed by damaging them so

23:49plug this here branch

23:53so we're gonna again get this actor and

23:56call take

23:58damage

24:02all right now the damage causer is also

24:05get owner

24:07uh but what's the damage info well we

24:09want to also make this an input to the

24:11function so the function will provide

24:13this so you can drag off this pin here

24:14and drop it

24:16to make it a input tier damage info

24:21all right so now we handled the check if

24:24we're damaging someone on the same team

24:25or not but what about damaging someone

24:28we've already damaged before

24:31so to do that we're going to create as

24:34soon as we damage someone we're going to

24:35put them into an array and then check

24:37the next time if they're in this array

24:39or not

24:40so we're going to create a local

24:42variable local means it's scoped to this

24:44function it's not used outside this

24:46function so it keeps it cleaner

24:48and it's we're going to call it

24:51currently damaged actors or actors

24:57damaged so far all right and this is

25:01going to be of type actor

25:03object reference and also make sure over

25:06here to click this make it an array

25:09so as soon as we damage an actor we're

25:10going to get this array of actors

25:12damaged so far and we're going to say

25:14add unique make sure not to do add but

25:16add unique

25:18because if we encounter the same actor

25:20again we don't want to add them a second

25:21time

25:22and the actor will be this actor here

25:25from our hit actor

25:28all right

25:30so oops so then we uh

25:33add

25:35to this array the actor that we just

25:37damaged but then before actually

25:39damaging them we need to check are they

25:40already in this array which means that

25:42we damaged them before

25:44so we can check it somewhere here so in

25:47this condition if they're not on the

25:50same team

25:51and we didn't damage them before so to

25:54check if we didn't damage them before we

25:56get this array and say contain items so

26:01again sorry if we say

26:03contains item

26:05and the item is our actor here just make

26:09a redirect node here

26:11so if this array contains this item

26:15not

26:18then we continue right so if the array

26:19doesn't contain this item which means we

26:21haven't damaged this actor before and

26:24let's make an and Boolean here to put

26:26both of these

26:29and this is now our new condition

26:31so our condition is we are not on the

26:34same team and we haven't damaged them

26:36before then proceed to damage them and

26:38add them to the array of damaged actors

26:41and at the very end we want to return

26:43the actors damaged uh don't don't plug

26:46this in here because this is again on

26:48the loop body we want this to be when

26:50the loop has completed so off of

26:53completed here

26:56and let me also just make this a bit

26:58straight

27:01what do we want to return we want to

27:03return our actors damage so far because

27:05we completed the loop so these are all

27:07the actors that we've damaged

27:12and that's it so this function will now

27:16damage all of the actors in This array

27:19but let's see how we can use it so we

27:21don't need this Loop we don't need this

27:23and we don't need the take damage

27:26now all we need to do is off of our bpc

27:28attacks

27:30say damage

27:32damage all non-team members

27:37and we're going to pass the array of

27:39hits from here

27:42oops

27:44and the Damage info will be this

27:48and then you can do something with the

27:49actors that you've damaged if you want

27:51for now I'm not going to do anything

27:53but let's see how this looks like now

27:56um

27:57if I print well actually okay let me

27:58Loop over all of them so for each

28:01and let me print

28:03so we're going to print each actor that

28:05we damaged and now I should only see my

28:08name being printed once

28:09yes perfectly and I took 10 damage and

28:12yes my health was indeed 50. so now I'm

28:15getting damaged only once

28:17now let's see and let's make sure that

28:19multiple enemies can be damaged as well

28:23so

28:24um I am going to create another enemy

28:27here and I'm gonna make him on my same

28:30team so on team one

28:34and I'm going to stand in between them

28:36and make sure that we both get damaged

28:40come on attack yeah

28:43yeah we both got damaged so I got hit

28:46and he got hit from one sword swing

28:48perfect

28:51um oh and I should not be getting hit

28:52from the one that's on my team so let

28:55them hit each other ones first

28:59yeah so we both got damaged but this guy

29:01shouldn't be damaging me right so you

29:04should only damage the other actor

29:06so I'll try to hit perfect yes he didn't

29:08damage me nice

29:10so this is working as expected let me

29:13remove the print now

Modifying Ranged Attack To Not Damage Team Member

29:18also the ranged enemies attacks so in

29:22and this is we do it here in our bpc

29:24attacks we have this uh fire bullet

29:28so fire bullets also does a single line

29:30Trace

29:31um from the ranged enemy to their target

29:34and if it hits something it causes take

29:37damage on that something as well

29:40so here we want to do the same thing we

29:42want to check if

29:44um we're on the same team or not but we

29:47don't want to damage everyone because

29:50well maybe you do maybe you want the

29:51bullet to be able to go through multiple

29:53enemies so it hits the first enemy the

29:54second one and so on in the line but

29:57what I wanted to do is actually so if my

30:00let me get a ranged enemy here

30:03so if this ranged enemy is targeting

30:06this melee enemy

30:08but this one is in the way

30:11if this one is in the way and they're a

30:14team member I want the attack to go

30:16through the team member so this one is

30:18targeting that one and this one is a

30:20team member of the ranged enemy I want

30:21the bullet to go through the team member

30:23but if this one is an enemy

30:26and even though this ranged enemy is

30:30targeting this one

30:31but it hits another enemy while on the

30:34way to their original targets I want the

30:36one in the middle to be hit because it's

30:38more realistic if you're firing a bullet

30:40at someone but it hits someone else then

30:42they're the ones that take damage unless

30:44they're on the same team this is of

30:45course where the unrealism of games

30:48comes into play we'll have the bullet

30:50just go through straight straight

30:51through team members

30:53so we are also going to need a multi

30:55sphere trace for assault multi-line

30:57trace for this so this line Trace we're

30:59going to replace it with a

31:03multi-line trace for objects as well

31:08all right and plug in almost everything

31:11as well let's start to the start and to

31:14the end object types uh

31:20and anything else

31:22plug this here and this condition

31:28all right

31:32yeah and also we want to I'm not sure I

31:34don't really have this actress to ignore

31:36we want to make array and ignore the

31:39owner so we never hit ourselves that's

31:42important

31:44um

31:46all right so now that we have this uh we

31:49are going to

31:50replace a take damage as well

31:53buy something else

31:55this time we're not going to call damage

31:57all non-team members because like I said

31:59I don't want the bullet to go through

32:00all non-team members and damage them

32:02maybe this is what you want but I'm

32:04going to create a new function and call

32:05it damage first

32:08non-team member

32:11so the first non-team member you

32:13encounter damage them and then ignore

32:15all the rest

32:17so this also takes an array of hits

32:22you know not get hit

32:26um and it returns a single damaged actor

32:29because we're only damaging one actor so

32:32actor object reference and make sure to

32:35change this from array back to single

32:38uh oh and it's also going to take the

32:40damage info

32:42oh

32:43damage info which is a damage info

32:47struct

32:52all right so this time we're going to do

32:55a for each Loop but make sure to choose

32:58for each with break

33:00for each with break it gives you this

33:01additional break execution pin which if

33:04you enter this pin you stop the loop you

33:07break from the loop because once we

33:09encounter our first non-team member we

33:11want to break from the loop we don't

33:12want to keep looping

33:14um so we're going to Loop over all of

33:16these hits we're gonna break the hit

33:18result this is a different break than

33:20this one

33:21and we're gonna get the

33:24team number

33:25of this actor

33:29and we're going to get our owner so this

33:33is the ranged enemy or whomever is

33:34calling fire bullets and get team number

33:37of the owner as well

33:39and check if this is not equal to this

33:48a little bit here

33:51um if this is not equal to this then we

33:54are going to

33:57call take damage

34:02on

34:04this actor

34:12and the Damage info will be this damage

34:15info and the Damage causer will be get

34:17owner

34:19and then once this condition is true

34:22we're going to break so pull over off of

34:25here and put it in the break and also

34:29let's clean it up a bit

34:35yep

34:39all right and then we want to return the

34:42damage actor oh if you want to return

34:43actually then we need to do something

34:44before we break we need to call it

34:46sequence because we're going to do two

34:48things

34:49first we're going to break

34:51well

34:52first we're gonna break then we're gonna

34:54return

34:55because you can't do anything after the

34:58return so first you have to break and

35:00then return and in blueprints returning

35:03doesn't automatically break from the

35:04loop if you return the loop will still

35:06continue

35:07and this is our actor

35:13alright so we check if they're not on

35:16the scene we Loop over all the hits we

35:18check on the first one that's not a team

35:20member call take damage on them and then

35:23break from the loop if we don't want to

35:25Loop anymore and return this actor

35:29so back here in our event graph then

35:31we'll call damage first non-team member

35:34pass in the array of hits pass in the

35:37damage info

35:39from here

35:42um and we are doing a report damage

35:46event here which requires a damaged

35:48actor that's why we returned it so we

35:50can just plug this damage back through

35:51here

35:53and of course

35:55um

35:58this is pretty much all we need let's

36:00draw the debug

36:02so that we see what's happening

36:04and let me show you how this works so

36:07I'm going to delete this enemy and I'm

36:09going to make sure these two are on the

36:10same team so this is team two and this

36:13is team two

36:14and I'm gonna try to stand behind him

36:18so

36:20bullets went right through him so you

36:21see there are hits but they're all red

36:23so the Bullet went right through him

36:25again I'm going to show you now this

36:28time it didn't uh hit him I wasn't

36:30standing correctly

36:32all right stand stand come on come on

36:36yes do it hit yes perfect so it goes

36:39right through him and hits me

36:41now if he was an enemy so I'm gonna make

36:43sure he's an enemy now but they're both

36:45going to be attacking me

36:47so this guy is team two and this guy is

36:52team I don't know three so we're all now

36:54enemies of each other we're all on

36:55different teams

36:57um but I'm gonna make them both see me

36:59first so that they attack me

37:02instead of each other

37:05all right so now if I stand between him

37:08come on come on come on shoot

37:11he's the one that got damaged see and he

37:13blocked

37:14all right and I noticed that the and

37:16melee enemy is always blocking and I

37:18think we forgot to return the block

37:19chance yeah so the blockchains is one

37:22they'll always be blocking let's put it

37:23back to 0.25 like it was

37:27um

37:29all right

37:30and let's let's also do a uh sort of a

37:35multi

37:37enemy battle here to see so we're gonna

37:39have

37:40uh

37:43let's say melee enemies all on the same

37:46team team two team two

37:49team two versus

37:51ranged enemies all on team three

37:58and let me stand behind them so they

38:00don't see me and let's see what this

38:02looks like

38:04nice so they're all going to be

38:07uh the melee enemy is still pretty good

38:09at blocking

38:10is it still at 100 no no he's okay he's

38:13getting hit it's okay

38:18looks really cool

38:23um and as you can see we have two uh

38:26melee enemies or actually all three are

38:28attacking the same Target uh maybe

38:30because they saw this target first

38:33um one thing we can do to modify our

38:35targeting system is to make sure that uh

38:38let's say if the enemy attacks a Target

38:40and this target already has someone

38:42attacking him by let's say they don't

38:43have any tokens then they can try to

38:45switch to

38:46um to other targets now we can do we

38:49haven't really done anything with

38:51targeting so far so maybe we'll be

38:53touching on targeting systems in the

38:55next tutorial

Fixing Bug

38:57all right sorry one last thing before we

38:58close I noticed a bug that's if

39:01um this enemy is now on my same team but

39:03if I damaged him and he doesn't block

39:06he's gonna try to attack me and then his

39:09damages his attacks won't do anything

39:11because we're on the same team but why

39:12did he try to attack me even though

39:14we're on the same team

39:16I noticed that well we handled the sense

39:19damage and if you sense damage you don't

39:21attack but we didn't handle in our base

39:24enemy on the hit response on the hit

39:26response here we passed the damage

39:30causer

39:31if there is no last known attack Target

39:33if there is a last known attack Target

39:35they'll use that one but otherwise

39:36they'll use or actually the other way

39:38around

39:40um

39:42so attack targets if there is no last

39:46known attack Target yet indeed they will

39:48use the uh this new attack Target

39:51so we need to change this to also check

39:54is this attack Target on your same team

39:56or not otherwise don't do anything

39:59so we're gonna add another check here

40:03um let's get the from this attack causer

40:07let's get the team number and let's

40:10control drag all of these here

40:13and we are going to check if the get

40:16team number is equal to my own team so

40:18I'm going to say get team number make

40:20sure to call this one the function call

40:22that's on target is enemy base

40:25because this is our own get team number

40:27or actually don't need to call again

40:28team number you can just get the team

40:30number variable here

40:32so if

40:34um this get team number is not equal

40:40to this skept team number then proceed

40:44as you would

40:47um

40:48oops sorry we need a a branch here

40:56all right

40:57uh but what if it is equal sorry yeah so

41:00what if I am on the same team

41:03well if I'm on the same team I still

41:05want to

41:06be straight I still want to call set

41:09State as attacking but this time I don't

41:11want to pass

41:13um an attack Target I only want to pass

41:16a

41:17um the use last known Target so actually

41:20instead of a branch you can do a select

41:21node not to be a bit better

41:23so here do a select

41:27on this Boolean value

41:29so if we're not on the same team then

41:31just pass in this

41:36and on the false you don't pass anything

41:37so if we are on the same team then don't

41:40pass anything and keep use last known

41:42attack Target

41:44and by the way if last known attack

41:45Target and attack Target are both not

41:48valid then the enemy won't do anything

41:49so let's test this out now I damaged him

41:52he doesn't do anything because hey he's

41:55my team member what am I gonna do

41:57nice

41:58and that's it

Outro

42:01as always thank you all for watching I

42:03hope you enjoyed this part and if you

42:04did please consider giving a like And

42:06subscribe and if you want to download

42:08the full project files then consider

42:10joining my patreon where you can also

42:13join for a free seven day trial and

42:15download everything if you want to do

42:17that and you can find the link in the

42:19description as well as right here and I

42:22haven't decided yet what to do for the

42:24next part so if you have any suggestions

42:26or if you want to learn something

42:28specific then please leave it in the

42:30comments below and I'll see you there

42:31[Music]

42:45thank you

This transcript was generated from the captions YouTube publishes for this video. Get the transcript of any YouTube video atfreeyoutubetranscribe.com: free, unlimited, no sign-up.