Devlog 3



Devlog 3

Contents

  • Pause Menu
  • Main Menu
  • Save and Load System
  • Level Design Item Placement
  • Enemy AI
  • New Quest System
  • Add Interior building Assets
  • Organise File Structure
  • Optimise and Test Level.
  • Package Project

Pause Menu

I created a new widget blueprint named PauseMenu. I used vertical and horizontal boxes to organise the layout. I added buttons to call click events. 

I have a sound playing when the ViewControls button is pressed. It creates and adds the controls menu to the screen and removes the main menu screen. When the main menu button is pressed the player is sent to the main menu level. In the Construct event I get a reference to the player character and Game Instance.

When the ResumeButton is clicked it plays a sound and removes the pause menu and goes back into the normal gameplay.

The P key is used to turn on and off the pause menu. The blueprints display the mouse cursor on and off screen and setting the input mode UI off when returning back to game.

Main Menu

I created a new level named MainMenu to be my starting level. Also I created a new widget blueprint to display buttons to call events and transition to levels based on save data.

I have a sound playing when the ViewControls button is pressed. It 

creates and adds the controls menu to the screen and removes the main menu screen.

The quit button plays a sound then delays the game from quitting for 1 second.

Save load System

I created a Save Game Blueprint to hold my save data for my checkpoint system, quest information and player details of position and experience. Also have an array to hold the destroyed actor in the level when saved and loaded up.

I created an actor named BP_Checkpoint. Then a Structure named S_PlayerCheckpointSave to hold a variable of type BP_Checkpoint. 

In the BP_Checkpoint actor I created a box collision component  to detect the collision of the player and to make a sound once collided. I used the Does Save Game Exist node to check if the slot name exists. If yes, the save game slot is loaded in, or if not the save game object is created. After this the save game object is promoted to a variable to store the value and casted to MySaveData save game object. From here I get the CurrentQuest structure in front of the Master Character blueprint and store this value into the Save Game object’s structure named Quest Information. I also get from the save game object the structure named Player details. Then get the values from the Master Character and store the values in this structure. Next I get the Master Characters AC_Inventory Component and save the current items attached in the inventory menu to the save game object.

I created a structure named S_PlayerDetails to hold information of the players position, current EXP, EXP level, Health and Ammo.

I created a Structure named S_QuestDetails to hold the information for my quests.

In my Master Character blueprint I load my quest details from my save game object into the player characters Current Quest variable in the Beginplay event. I also load the inventory into the game by calling the Load Inventory event in the AC_Inventory component that is attached to my player character.

I get the save data from the save game slot and use it to set the variable PlayerDetails in the Master Character Blueprint. I also set the Destroyed Actor array of the Master Character with save game data.

I created a pause menu that transitions the player to the main menu level. The Save Game button saves the game to slot and the Delete Save Game button deletes the current saved slot. The resume button removes the widget from the screen to allow you to play. Controls button displays controls screen widget. 

When you click the save button it plays a sound. I used the Does Save Game Exist node to check if the slot name exists. If yes, the save game slot is loaded in, or if not the save game object is created. After this the save game object is promoted to a variable to store the value and casted to MySaveData save game object. From here I get the CurrentQuest structure in front of the Master Character blueprint and store this value into the Save Game object’s structure named Quest Information. I also get from the save game object the structure named Player details. Then get the values from the Master Character and store the values in this structure. Next I get the Master Characters AC_Inventory Component and save the current items attached in the inventory menu to the save game object. I use the SaveInventory function in the AC_InventoryComponent class to save the inventory.

When I  click the DeleteSaveButton a sound is played and the saveData, Inventory save game slots are deleted.

In the Main Menu widget I use buttons to transition to levels and to delete or load save data and quit the game.

When you click the load button a sound is played. Then the inventory slot is loaded and the first level is transitioned to.

When the new game button is clicked it plays a sound and then deletes the save game slots and loads level.

The load inventory function is called and loaded from the saved game and added to the variables in the AC_InventoryComponent class variables.

I created a custom event named DestroyItem that takes an input of type name. When called, it adds unique names of objects to the Destroyed Actors array in MyGameInstance. The Init event is used to get a reference to my player character.

I created a Custom Event named LoadGame. When it is called it checks to see if the slot name exists. If it does, it loads the game slot and sets the player character  Current Quest variable.

I created this custom event to load game data if slots exist otherwise create a new save game object. If async bool is true it will load the save game data on a separate thread without effect in the main game thread. It will give a smooth transition when loading a lot of data.

I created this function to stop the array being read when called from under zero as it will cause an error.

Level Design Item Placement

Add 3d models rocks and plants around paths.

Enemy AI

I created a character blueprint named MasterAI_BP to be a parent blueprint for child class enemy AI. In the Beginplay  event Initialize all my components and values for my interface functions. For example setting the location and rotation value of a character.

The HealthBar event delays the second bar on the health bar to decrease in size.

In the Rotate to Player event I make sure the AI_CombatComponent is valid before continuing execution. Also I make sure this character is not dead. If alive it will call the Rotate Using Alpha Rotator function. This function lerps the rotation and chooses the shortest path to aim at the player and accelerate through rotation.

This event changes the character max walk speed through the interface rather than casting to the character when in a child class.

The Alert Capsule Begin Overlap event checks to see if it overlaps with a player or has a tag Pawn Capsule and calls the other within range AI to alert them of the player.

These events make sure the enemy AI character is within a small tolerance of rotation value to the player.

This event is called when the player is in an attack animation and adds a forward direct value to the AI character. It is called from an Anim Notify.

I created a child class of MasterAI_BP and named it Boss_BP. I will be using this character as the main boss and quest.

In beginplay I call the parent beginplay event to initial all my components and values. I then set my health and get reference to the players ExperienceSystem component. I also check to see if it is the main boss by checking for its tag BigBoss. If it has the tag I create a marker for the distance and compass for it and set it hidden. At the end of the Beginplay event I check to see if the current quest is this character and if yes, then display the compass marker.

In the Tick event I check to see if the current quest is number 14 and if yes, then display the compass marker. If not, make it invisible.

In the Initialize HP HUD I check to see what type of AI and if it's the Boss then I create and draw on screen the Boss health bar and get it to update when taking damage.

In the Attack Trace Right and Attack Trace Left events. When called it draws a box collider from one point of the weapon to the second point. If there was a collision hit then the Hit Event is called.

In the Hit Event the hit result value is checked to see if it was the Player character. If yes, Then it's added to the array Damaged Enemy. Before proceeding to take damage off the player it checks to see if it was already damaged. If not then damage is applied to the player character.

The AnyDamage event is called when the player or other enemies of this character applies damage to it. It checks to see if the damage causer is the player character. If yes then apply damage to this character's health equal to the incoming damage. The Update the Health bar with new values.

The Move Along Spline event is used for the jump attack. It takes off the collisions and sets the movement mode to flying. It uses a timeline to make the jump last for 0.7 seconds. When completed, set this AI character back to walking and collisions on.

This event is called by an AnimNotify in the animation blueprint to disable current movement before moving along the spline in jump attack action.

Mini Boss (AI)

I created a new child class called MiniBoss_BP from MasterAI-BP.

I call the Parent Beginplay to initialise all components and values.

These are my default values of my Mini Boss Character. I make changes here for health, enemy type, experience points and more.

I created a Blackboard named General_BB. This holds all my values for my Behaviour tree.

I created a Behavior tree named General BT to be used by all my AI characters who want to use the functionality.  In the beginning I used a sequence node that executed their children from left to right. They stop executing when one of their children fails. The BTT_DoNothing task is used as a loop for when the services attached fail. These services are used to constrain the AI within set values.

Selector nodes execute their children from left to right. They stop executing when one of their children succeeds. The first node to execute is the Entering Combat Sequence. It uses a Blackboard Based Condition to see if the Enum General AI State is set to Enter Combat. If yes, the behaviour tree tasks are executed from left to right and come back up the branch if fully completed or one task failed. Next is the Exiting Combat Sequence, then Combat Selector. First task checks to see if the character is dead. Then if not it checks to see it can turn and then turn. The BTT_Hit checks to see if the Character has been Hit.

In this Behaviour tree task It plays the Equip Animation.

This task waits one second before going into the next action. By calling the Decide Instantly Event.

This task uses the unequip weapon animation when leaving combat.

This task sets all the variables and action to no combat and goes back to patrolling if there are any patrol paths assigned to the character. Otherwise the character is set idle.

In this task the plates AIAction and state are set to Dead. The AI_BPI function Dead AI is called and the enemy carries out its death functionality. 

The BTT_Turn task first checks to see if the character is currently turning. If not, the character's decision for an action is disabled. The Yaw Range Macro checks to see if the yaw rotation value is between the set values. If they are in range then the characters will rotate left by 90 degrees. If not, then it will do another check to see if within the Yaw range and if so, turn to that amount of degrees. The Turning in Place Animation Selector uses the event from the AI_Turning component.

The BTT_Hit task does the hit reaction functionality by using the AI_CombatComponent events and functions. It checks on if the character was hit and what direction it was hit from. It calls the animation to be played depending on hit direction and weapon type. It also checks to see if the character is immune to the hit so it doesn't play a hit reaction animation.

I have under the Combat Selector the Following Selector that moves the AI character towards the player character. Then I have the Strafing Selector that activates strafing when the enemy is close enough to the player. Next I have an Attacking Selector that holds the BTT_AttackMultiRange this task chooses based on values if the attack is a close or mid range attack that is played. If BTT_AttackMultiRange fails then the BTT_AttackFails is called. Depending on the distance the AI Character is away from the player character, it will set strafing if close enough or follow player if out of strafing range.

This task is called to delay the next action by 1 second.

In the BTT_StrafingRightOrLeft task it checks to see if the character is currently strafing. If not, strafing is activated and a random time is set for how long the character strafes for. All the keys are set to these values in the blackboard ready to be used in the behavior tree.

The BTT_AttackMultiRange this task chooses based on values if the attack is a close or mid range attack that is played. It makes sure the AI_CombatComponent is valid. It checks to see if it is currently attacking. Depending on range to player the close or mid range attack is activated. Also it checks to see if you do have the component initialise with values and animations before performing attack.

In the  BTTAttackFails task depending on the distance the AI Character is away from the player character, it will set strafing if close enough or follow player if out of strafing range.

This task is called to play parried animation if the parried state is set. 

After leaving the Combat Selector the Patrolling Sequence node checks to see if the enum General AI State is set to Patrolling. If yes the tasks are executed.

In this task the function from the Actor  Component AI_PatrollingComponent is used. The Find Next Point function gets the next patrol point location and sets it in the Blackboard key Location Key.

Enemy AI Controller

This is the main AI Controller blueprint that is used on all the AI characters. In the Initialize Controller event the attached behaviour tree and blackboard is set for this character. Also the Assign values are set with default values.

In these events the AI Perception component checks to see if one of the senses have been detected and to see if that actor is valid. If yes, the function Combat Initialization is called which changes the AI State to Enter Combat. Also the enemy equipped weapon sets distance and rotation of where the player is and displays the health bar above head. After the Alert Other AIs Nearby function is called that sends details of the players location to react to it if they are within range.

These events when called make a decision after 1 second before going into the next action. If in an action the action is cancelled when the Clear AI Decision event is called.

This Disable AI Senses event when called turns of the Sight and Damage detection senses off.

In the Set AI Action event it sets the Combat AI Action Enum plus the blackboard key of the same type. It adjusts movement speed. Depending on what the enum value is in the Combat AI Action it will choose to end the strafe movement or clear the Following Time the character has spent on the player character.

This Set AI General State event when called sets the General AI State in the blackboard.

These are the values I set in the AIPerception component for the Senses sight and damage.

AI_PatrollingComponent - Actor Component

The Initialize Components event is called in the beginplay AI character blueprint MasterAI_BP. In this event the patrol points are collected into an array if there are valid ones attached to the character. If yes then the General AI State is set to patrolling and the values are passed on to the Blackboard key ready to be used by the behaviour tree.

I created an Actor Blueprint BP_PatrolPath to be the location of the patrol points in level. It gets attached to the AI Characters in the Level editor. I gave it a spline component and a billboard to display the icon in the level editor.

AI_Strafing Component

The Initialize Components event is called in the AI Character blueprint to initialise values.

In the Tick event it first checks to see if the Character and player are valid objects. Next it checks to see if the AI Character is dead. If not, the AI character is giving a strafe direction and movement.

In the Strafing Start event the direction on the strafe is passed in and the player character. Then the Animation blueprint of the AI is Set to strafing with weapons.

In the Strafing End event the strafing is cancelled and the Animation Blueprint is set to walk all idle depending if it jas a patrol point to go to.

This event is called when the strafing time limit has been reached and the next action is called after 1 second.

AI_CombatComponent

In this event the values are initialised for the AI_CombatComponent with default values.

In the Tick event if the target is valid which is the player, and the enum Special Rare Attack Type is equal to Spline Jump. Then the Spline Jump Attack is called.

The Melee Attack - Close Range event selects either the normal close attack or if the Rare Attack. If it returns a true value from a random value that is less or equal to the percentage value, then the rare attack is set for the animation. The same happens to the Melee Attack - Mid Range event. At the end of execution the  AI Action enum is set to Attack Melee range. The events are called by the Behavior tree task BTT_AttackMultiRange.

In this event the player sets the target as the player and overrides the current animation, if the AI character has been hit. It gives a Hit reaction animation. The events are called by the Behavior tree task BTT_AttackMultiRange.

The Melee Attack Charge Attack End play animation after the special charge attack like the spline jump attack.

The Increment Charge Attack Index event adds to the Charge Attack Loop index when called. In the last event it checks to see if the Charge Attack Loop Index is more than equal to 3. If yes, the character stops all animation montages being played on it and calls the General Reset event that checks what the values are and determines what state and action it will do next. Lastly the charge attack loop index is set to zero.

In the Collapsed Graph called action there are events. The General Reset event that checks what the values are and determines what state and action it will do next. The Initialize Parried State event set the AI Action (Combat) enum to Parried. If the Start Execution Attack is called then the Execution animation will be played. The Hit Reaction event plays the hit reaction montage based on value passed in. The Reset Hit Reaction clears the current Montage that is being played. The Immunity event sets the character to have no hit reactions and to set a glowing material on the character for 10 seconds. The Initialized Deathblow Victim State event is called when the player uses the assassination attack type on AICharacter. It also checks to see if the AI Action enum is set to parried. If yes then the Anima montage Executed Animation is played. When the Play Montage Based On State event is called it checks to see the AI Action is set to Under Execution and checks to see if this character AI is dead. Then the death animation and set the AI Action to Dead.

AI_TurningComponent

The Rotating While Turning (Time) event is called by an animation notify AN_TurnInPlaceRotate. The AI character turns in place and on the move. The Initialize Components event initialises the value of this actor component. 

In the Tick event it first checks to see if the character should rotate when turning. If true it will check to see if the character is dead and if not. The characters rotation values are updated.

In the Turning in Place Animation Selector event it is called in the BTT_Turn Behavior tree task to provide the correct montage to play for the turn value in degrees. The other 2 events disable turning movement.

AI Animation Blueprint (AI_ABP)

This is the AI Enemy animation blueprint.

In the Beginplay event I get a reference to the AI Character and store it in OwnerBP.

In this event I make sure the Pawn owner is valid. If yes, it will set the Bool Isinair? And the Speed float value on every tick.

In these Anim notifies they get called during the animation montage. One resets the special attack to normal attack. The AnimNotify_Reset resets the animations to clear and run checks on the AI State to see what action it should do next. 

These get called from the animation montages to add or reset values to zero for charaged attack integer.

This gets called from the animation montages and when it does the character moves along a spline and the AI movement is disabled.

This gets called from the animation montages and stops all animation montages from play on this character.

When the Spawn Danger Emitters is called the Danger Indicator is shown in level. The other Anim Notify clears the indicator off screen.

These events set the Movement State enum and Strafing Direction value with input data when called.

When this is called in the animation montage it stops the turn animation.

When this is called, the hit reaction montage.

In the AnimGraph of the Animation Blueprint I just have one State machine named General State.

I have only one state in the State machine that is Idle and Run.

I use the Blend Poses by the enum Movement State. The current value in enum Movement state sets the blendspace to be played. 

Quest System

I deleted the old quest system and made a new one from my own logic.

I created an Actor component named BPC_QuestComponent and attached it to the player character.

I add the user widget W_Tracker to the screen in beginplay. This holds the text of the current quest I am on.

The current quest value is set in beginplay from the values in the save game slot.

This is the Structure I created  to hold values of the Quest and to be used for saving and loading data.

In the Beginplay in the BPC_QuestComponent I get a reference to the player character and the game instance. 

When the CompleteQuest event is called it gets the current row name of the current quest variable from the player character. Whatever the value name is depends on what channel is executed.

When the execution passes the switch node. It prepares the next quest in the datatable.

This is the datatable I created from my Structure named S_QuestDetails.

I use this to display information about the quest and to keep track of what quest I am on.

Collect Quest

This is a quest where you have to collect a key. When the game is loaded it up the compass marker is hidden unless it is part of the current quest that is active. If the game was saved, and has been picked up the item would not appear in the level. 

When the player character overlaps the BP_Key collider it set the compass marker hidden. 

It now checks to see if this was the current quest and if yes it will add a 1 to the integer Quest Quantity. It will do a check to see if the quest quantity value is equal to the value set in the DT_QuestDetails. If yes, the event Complete quest is called and the Quest Active bool is set false. The item is then added to the array of destroyed actors.

This is the W_Tracker User Widget I created. This holds all the text on screen for the current quest the player is on.

Add Interior Assets To World

I added these interior assets to my HQ building.

I added these interior assets to my watch tower.

I got my office interior assets from a asset on EpicGames Marketplace

Organise files

I dragged in the folders in the content browser into their relevant types such as Audio, meshes, blueprints and UI.

Optimise and Test Level

I deleted most of my unused files in my content browser to lower the memory in the project. I updated the reference in the content browser when deleting objects as it can cause errors in the package the game process. Iadded a LightMassImportanceVolume to the world and strected it over it. This help speed upp the process and building light and make them more accurate to look at. I changed my CPU lightmass to GPU Lightmass as its quicker for build times. I read the documentation on the unreal engine website on how to set it up and the limitations pof it. I thought it will suit my project and it does. The GPU Lightmass takes alot of overhead of computation from the CPU.  I lowered the light resolution and the texture resolution from 4k to 2k to save memory and processing power. Some of the material for the objects were close in design, soIdecided to use the same materials for more objects and delete material to save on memory and processing power.

Package Project

Leave a comment

Log in with itch.io to leave a comment.