‫In this lecture, we are going to be putting together a player controller that will receive information
‫that the game has ended from the game mode and will create this restarting behavior that after 5 seconds
‫reloads the level after the player has died.
‫Let's dive in and see how it's done.
‫So when the game is indeed over, we need to notify our player controller and we also need to have a
‫player controller in our C++ so that we can implement the behavior of allowing us to restart the level
‫and such.
‫So the first thing to do is when this point is killed, first of all, we're just logging indiscriminately.
‫We do want to check whether or not the game is over.
‫Now, there are two scenarios.
‫One is where we win and one is where we lose.
‫The lose is the first one I'm going to tackle because it's easiest.
‫If the pawn killed is the player you lose, that's it.
‫You might choose to have multiple lives with different iterations of this game mode, but I'm not going
‫to be doing that.
‫I'm just going to have a single life.
‫If you die, game over.
‫You might want to restart.
‫So how do we check if this pawn is a player controller?
‫Well, that's pretty straightforward.
‫We can just do a cast, so we're going to do a cast to a player controller and for the pawn killed.
‫And then if this is not null.
‫So let's take the pointer, a player controller pointer, call it the player controller and store the
‫result of that pointer in here.
‫And we're going to say basically if this is not null, so if the player controller is not a null pointer,
‫then we know that it's the player that's died and that it's game over for the player.
‫So what we want to do is call on that player controller method.
‫We've already hinted at the fact that there is a game has ended method.
‫Let's have a look at this.
‫If we do a control P and have a look at the player controller and we're going to look for a game has
‫ended and you can see sure enough there is a virtual method here called game has ended and you can see
‫there is an end game focus.
‫What actor should we focus on in the end game by default, this is null pointer and that's probably
‫what we're going to use.
‫And then we're going to say, is this the winner?
‫Basically, you've got to let the player control and know whether or not they have won.
‫And that's fairly straightforward to say in this case.
‫No, they haven't.
‫So we're going to do a play controller arrow game has ended, then I'm going to put null pointer for
‫the end game focus because we don't really need that feature and then is winner.
‫It's just simply going to be false.
‫This is not the winning play controller because it's the one that just died.
‫So it's time for a little bit of a challenge for you to implement.
‫Game has ended in a play controller.
‫That means we need to create a C++ player controller, create its blueprint subclass, spawn that blueprint
‫subclass by default from our game mode and then you want to go ahead and override.
‫The game has ended and put a log message in there to check that we're indeed getting.
‫That game has ended at the right time.
‫Pause the video and have a go.
‫Okay.
‫Welcome back.
‫So step one, create that C++ player controller, create a new C++ class, then go and look for let's
‫see, player controller.
‫Next, we're going to call this the shooter player controller.
‫Go ahead and create that class.
‫Once that's done, we want to go over to our blueprints and create a blueprint class that is based off
‫of it.
‫So we want the shooter player controller as the base select that and we're going to call it beep underscore
‫shooter player controller.
‫This is not currently really needed, but later down the line, we're going to want to hook up some
‫UI assets to this player controller.
‫So we'll have it there ready.
‫Then we're going to go to the beep, more game mode and dock that in because we want to change the default
‫player controller class from the player controller to our beep underscore shooter player controller.
‫Cool.
‫Then we want to override our game has ended.
‫So let's see if we go over to the player controller.
‫We can see that this is in the public section.
‫Here's the signature.
‫Let's copy it.
‫Go over into our shooter play controller H and create public.
‫To that virtual void game has ended.
‫Cool.
‫And we've got an override already because that was clearly being overridden from somewhere to.
‫And then what we can do is we can go ahead and implement it.
‫Control shift p we want to call to super remember.
‫And we want to do game has ended like so.
‫And we want to pass in the end game focus and the B is winner and then we want to log.
‫So you log.
‫Use my macro there.
‫We have finished.
‫It's going to be the log message coming out at the end.
‫So let's compile and see whether that's working.
‫We're going to go to the output log.
‫Hit play, go and get killed.
‫Basically healthy is slowly going down and then we should see a message.
‫Are we getting the message?
‫No.
‫So let's have a look.
‫What's the player controller here?
‫Beep underscore shooter player controller appears to be the correct one.
‫We've got our override game has ended.
‫Now here I spot a bug.
‫Now that is something that some of you may have noticed and have been shouting at the screen about is
‫that here we have got our player controller that we are casting to and I'm getting that confused with
‫the player's actual --.
‫So what we want to do here is we want to say get the controller of the -- that was killed.
‫So -- killed dot get controller Aron so arrow get controller and then we want to cast that to the
‫player controller and if that is null, okay, that should work.
‫So let's go ahead and try that out.
‫Go ahead and hit play.
‫Get ourselves killed again.
‫And this time we also don't get any log message.
‫And this time it's for a subtle reason.
‫That is because we're detaching from the controller.
‫Before we call this -- kill.
‫So when it tries to get the controlling -- that's actually null, there is no controlling -- anymore.
‫So we need to do this notification just before we do the detaching from the controller.
‫That includes moving up the line that gets hold of our game mode.
‫I didn't think that would matter.
‫But now that I actually think about it, yes, of course it does.
‫So let's go over in to our level and play.
‫Let's go and get shot at.
‫And once that is done, you can see that we have finished gets printed as we want.
‫So we had a few hiccups along the way.
‫Not your fault if you didn't get that in the challenge.
‫You've done everything else right up to that point.
‫That is great.
‫So hopefully maybe you had a go at debugging that, but don't worry if you got stuck on those things.
‫The final thing I wanted to do here is to actually restart the game on a timer.
‫Now, the way we can do this is fairly straightforward because the player controller actually has a
‫restart method.
‫So if we go and have a look at this, it should be a restart level.
‫That's the one that we want to be calling and we want to do this on a timer.
‫So we've used timers before to do repeating stuff, but we can also use it just to delay an action by
‫a certain amount.
‫So I'm going to go to the shooter player controller H and create a private property in here.
‫Private can be you property which is edit anywhere.
‫Float.
‫That is going to be the restart delay.
‫You can see why we need a blueprint base for this already.
‫I'm going to give it a 5/2 delay.
‫Then I'm going to go over into the C++ and we're going to want to do a get timer world timer manager.
‫And then we can do on that.
‫Then we need to include.
‫So hash include and it's going to be the timer manager.
‫H Then we should be able to use the DOT operator because the return type here is a reference and we're
‫going to do a set timer and in here we need to pass in a timer handle.
‫So in a private section let's go and create one.
‫So it's going to be an F timer handle, I'll call it the restart timer like.
‫So then that is going to be the handle that we pass into our set timer.
‫The next thing we need on the fifth signature here is actually to have the object that we want to call
‫on, which is just going to be this.
‫And then there's going to be, I think should be just the method itself.
‫So we can do that by doing ampersand.
‫And then it's actually the method, the restart level method, which we want to call on that was defined
‫on the A player controller.
‫So a player controller.
‫Cullen.
‫Cullen restart level and then we just need to pass in the delay which we have already defined as the
‫restart delay.
‫So do that, put a semicolon on the end there and hopefully we should get ourselves restarting after
‫5 seconds.
‫Now going to make the testing a little bit easier by opening up our rifle and making it just a little
‫bit more lethal.
‫So I'm going to go to the defaults, do the damage at 50, so we'll get killed with two shots.
‫Let's go and hit play.
‫Get ourselves killed quickly.
‫And then after 5 seconds, hopefully we should restart the level we restart and we're back in the level.
‫So our timer is working as we expect.
‫Now in later versions, you will find that instead of restarting, what you're going to see is an error
‫message that looks like this and talks about travel failure and says something about UUID, PID, sandbox,
‫blah blah blah.
‫Well, the way we have to get around this when we're trying to restart and want to check whether our
‫restart is working, is we go to our dot, dot, dot menu instead of the play menu and we have to play
‫as a stand alone game.
‫If, if you play as a standalone game, it takes a little bit longer to launch up, but the restarting
‫will work as expected like so.
‫And we see the level reloaded.
‫Now, obviously there's not much indication that the this is going to happen.
‫So we're going to look at UI in the next lectures.
‫I'll see you there.