Take me to...

What are Blueprints?

Blueprints are the visual scripting system used by Unreal Engine. They can be used to create anything such as characters, weapons, UI, AI, textures, materials, events, functions, interactions, etc..

They work by linking nodes together to give instruction to each actor as to how each actor is going to act in the world.

There are a few different types of blueprints such as Level Blueprints, Blueprint Classes, Animation Blueprints and Widget Blueprints just to name a few. For our intents and purposes it is unlikely that we will need to use most of the others.

 

Creating a Blueprint

To create a new Blueprint you can click on the Blueprints button in the ribbon above the viewport (A), or you can right click in your content browser then select the ‘Blueprint Class’ button in the create basic asset section(B).


A.


B.

 

Once activated a pop up will appear to pick the parent class of the Blueprint being created.

 

With the goals and intentions in mind for the creator kit we will be focusing on the ‘Actor’ parent class moving forward.

Creating the Blueprint by using the button above the viewport will then prompt the user to select a file destination after choosing the parent class. Select the desired save location, rename the Blueprint at the bottom, then press OK.


Creating the Blueprint in the Content Browser will have the Blueprint asset automatically appear in the currently selected folder.


Double click on the asset in the content browser to open the newly created Blueprint.


It is advised to place any objects/assets created in the Content folder. It is possible to create a new folder within the Content folder if so desired (as can be seen with the ‘_BC’ folder above), alternatively the ‘Developers’ folder can be used to organize any content being worked on.

 

Blueprint Orientation

Upon opening a new actor blueprint for the first time the user will enter into the Viewport tab of the blueprint. This is the physical view of the actor and everything that is happening inside of it.


The user is able to navigate around the viewport by holding the right mouse button and using WASD. The camera can be raised and lowered by holding the right mouse button with Q and E to lower/raise the camera. The cameras speed can also be adjusted by holding the right mouse button and scrolling the wheel up or down depending on the desired speed.  

A screenshot of a computer

Description automatically generated


The menus in the top left of the viewport are used to toggle views, change the camera perspective and render lighting.


The buttons in the top right of the viewport are the exact same as in the World viewport, they are ‘Transform’ settings which determine the location, rotation and scaling of an object.


Components

In the top left tab we have the Components section.

“A Component is a piece of functionality that can be added to an Actor. When you add a Component to an Actor, the Actor can use the functionality that the Component provides.


Components must be attached to an Actor and can’t exist by themselves.”

  • Unreal Engine Documentation

Components are all of the pieces that make up an actor. They are special types of objects that Actors can attach to themselves and give objects the ability to display a visual representation of the actor, to play sounds, enable movement and much more. Components are the only way to render in meshes, implement collision, and are ultimately what allows the player to interact with anything in the world. The Components section is to a Blueprint what the World Outliner is to a level.

 A screenshot of a computer

Description automatically generated

 

New components can be added to a Blueprint by clicking on the green ‘+Add Component’ button. Shown in the example (1) below, a static mesh component and a collision box component have been added and when selected the transform arrows appear in the viewport, as well as many different settings on the side.


Components use a hierarchy system ( Parent/child classes) and it is generally better to have the static mesh as a child component to a collision component. Generally, collisions are handled by the root object, in characters/objects this is the capsule. Every child object under that will not contribute to movement check collisions, but will still be able to trigger overlaps. Everything under it inherits the root’s data. Character components work on the principal that the capsule IS the character, and everything under it is visual.


The white sphere shown in the viewport is NOT the static mesh, it is called the DefaultSceneRoot and is basically a placeholder meant to show it’s location in relation to the world. It is an Actor Component that exists at a specific physical position in the world that the rest of the components use as reference.

 


Details

The details panel contains all of the settings related to what the user has selected and will often appear different. In the example (2) above, the settings being shown belong to the StaticMesh component.

In the example to the right 1M_Cube was selected as the static mesh. This object is much larger than the collision box so the collision components transform was edited so that it would surround the mesh.

A few noteworthy sections of the details section are listed below.

  • Transform
    1. Settings that change the location/rotation/scale of an object in relation to it’s parent component.
  • Static Mesh
    1. This is how to set a physical representation of the static mesh component. Use the drop down menu to select a static mesh actor.
  • Materials
    1. Appears after selecting a static mesh, this setting is used to decide which materials will ‘paint’ your actor.
  • Collision
    1. Basic collision settings with many different Presets. Can be customized as needed by the user, also contains channels which can be used to create collision groups which is useful for managing the specific collision properties of large groups of assets.

 

My Blueprint

The My Blueprint section contains everything that is inside the opened blueprint, ranging from events, functions, macros, variables, and event dispatchers.

  • Event Graph
    1. Shows all of the events taking place within the selected event graph. It is possible to have multiple event graphs in a single blueprint that focus on the specific needs of the user.
    2. Double clicking on any of these events will bring the user to the event node for quick navigation. If there are multiple event graphs this will open any of the selected graphs.
  • Functions
    1. Functions are node graphs belonging to a particular Blueprint that can be executed, or called, from another graph within the Blueprint. Functions have a single entry point designated by a node with the name of the Function containing a single exec output pin. When the Function is called from another graph, the output exec pin is activated causing the connected network to execute.
  • Macros
    1. Blueprint Macros, are essentially the same as collapsed graphs of nodes. They have an entry point and exit point designated by tunnel nodes. Each tunnel can have any number of execution or data pins which are visible on the macro node when used in other Blueprints and graphs.
    2. Macros are not able to be called from outside of it’s respective blueprint. One of the advantages of macros is that they can have latent functions (delays, etc…), while a function cannot. A macro can also take advantage of wildcard variables, and multiple execution pins, while a function cannot.
  • Variables
    1. Variables are properties that hold a value or reference an Object or Actor in the world. These properties can be accessible internally to the Blueprint containing them, or they can be made accessible externally so that their values can be modified by users working with instances of the Blueprint placed in a level.
  • Event Dispatchers
    1. Event Dispatchers in Unreal Engine are used to enable communication between different Blueprints by broadcasting events and allowing other Blueprints to respond.
    2. Events in Unreal Engine are crucial for triggering actions and responses in your game. They allow you to execute specific functions or logic when certain conditions are met, such as player interactions, collisions, or custom triggers.
      1. Trigger Actions: Execute functions or scripts when predefined conditions or interactions occur.
      2. Handle Inputs: Respond to player inputs, such as button presses or mouse clicks, to drive game mechanics.
      3. Manage Collisions: React to physical interactions between objects, like impacts or overlaps, to alter gameplay.
      4. Custom Events: Define and use custom events to handle specific game logic or interactions unique to your project.
      5. Event Dispatchers: Facilitate communication between different Blueprints by broadcasting events and responding to them dynamically.

Construction Script and Event Graph

 

Construction Script

The Construction Script is executed when instances of a Blueprint are created to perform initialization actions. It is used primarily to set values to an actor on its initialization in the environment, so when an actor appears in the environment the events in the construction script will occur immediately. This is different to the ‘event begin play’ node in the event graph because event begin play only happens during game time instead of during initialization when an actor appears in the level.


The Construction Script runs following the Components list when an instance of a Blueprint Class is created. It contains a node graph that is executed allowing the Blueprint Class instance to perform initialization operations.


This can be extremely powerful as actions like performing traces into the world, setting meshes and materials, and so on can be used to achieve context-specific setup.

A screen shot of a computer

Description automatically generated


Double Door Blueprint

Follow this is a short step by step guide to make a double door that opens and closes only once on it’s own, perfect for locking the player in a dungeon or a trap room.
 This guide also covers adding a sound when opening/closing.

Warning: This guide assumes some level of knowledge using the Unreal Editor such as converting actors to Blueprints, and the Blueprint system.


Instructions

  1. Find either a single door static mesh that will be duplicated or two doors made to fit together.



  • In this case we are using SM_C_Dun_Gob_Door_Lt and SM_C_Dun_Gob_Door_Rt.
  • If you are using the same door mesh for both sides; Make sure that the door looks the same on both sides, otherwise it may result in unwanted visuals when triggered.
  • Using an already made blueprint will most likely have its own event graph and triggers which might not work with this guide but could otherwise be wiped cleaned and reused for this purpose.
  • A single static mesh using two doors will most likely not work for this guide.

2. Create the blueprint for the door:

  1. Place down an empty actor on the ground, convert it into a blueprint, and rename this new Blueprint.
  2. Place down a static mesh for each door.
  3. Reposition the doors to fit nicely when closed.
  4. Rename the doors to left door and right door respectively.
  5. Place down two box collision components and name them trigger open and trigger closed respectively
  6. Resize and relocate the box collisions to your liking.
  7. Choose an audio kinetic sound file for the door. In this case we are using BP_COM24_Door_01_Open
  8. Apply instance changes to the blueprint.


  • The empty actor is used to mark the core of the blueprint which helps with keeping the asset centered and making moving/rotating/resizing the blueprint smoothly.
  • Make sure to add any new components in the blueprint and not as a seperate actor.

3. In the blueprint editor, replicate the following event graph to open the door:

A screenshot of a computer

Description automatically generated


The yellow nodes in the examples provided are called timelines, these are used to set the targeted start and finish points of the doors, effectively creating an animation.


The “new track 0” pin only appears on a timeline once you have added a track to it. (refer to step #5 below on how to set up timelines)


The SetRelativeRotation node needs to have it’s pins split in order to target only the Z axis rotation. To do so right click on the purple “New Rotation” pin, and select ‘Split Struct Pin’.


4. In the blueprint editor, replicate the following event graph to close the door:

A screenshot of a computer

Description automatically generated


5. Set up the timelines:

  1. From the event graph, double click a timeline to open it.
  2. Add a float track to the timeline. ( f+ )
  3. Add two keys to each timeline and give them the following values:
    • Open Left Door: [time 0, value 0] & [time 1, value -90]
    • Open Right Door: [time 0, value 0] & [time 1, value 90]
    • Close Left Door: [time 0, value -90] & [time 1, value 0]
    • Close Right Door: [time 0, value 90] & [time 1, value 0]
  • There are four timelines in this blueprint (two for opening and two for closing), each with a float track and two keys each that need to be set up with the following settings to make the doors open and close over 1 second.
  • The correct Z axis rotation timeline values for the door may differ from the provided timeline values because of the initial setup of the blueprint. Check those first if the door doesn’t open correctly during testing.

6. Compile and Save the blueprint.

7. Test your door to ensure they open/close correctly.


Mod Mutators: Replacing existing Blueprints

The Mod Mutator blueprint class is used to replace many existing in-game things, and in this tutorial, it will be used to replace existing blueprints with a different one.

Note: This tutorial assumes you already have a Mod folder and relevant blueprint prepared to replace an existing one.
 It is highly recommended to create a duplicate Blueprint for what you wish to replace and place the new version in your Mod’s folder with a new, recognizable name, as well as keeping the original as a backup should any errors occur.


Instructions

1. Add a Mod Mutator blueprint into the mod folder of your choice:

Right click in the content browser, select “Blueprint Class”, then, in “All classes”, type Mod Mutator, click the result of the same name and click the green “Select” button at the bottom-right of the window.
(Be sure to rename the mod mutator blueprint to a name of your choice, once created)

A screenshot of a computer

Description automatically generatedA screenshot of a computer

Description automatically generated


2. Open the Mod Mutator and select the blueprint you wish to be replaced: 

Open the newly created mutator blueprint by double-clicking it in the content browser, then press the + next to “Array Elements” under UGC > Actor Types to Override. Under the dropdown that defaults to “None”, search for and select the blueprint you wish to replace.

A screenshot of a video game

Description automatically generatedA screenshot of a computer

Description automatically generated

A screenshot of a computer

Description automatically generated


3. Set up the “Request Actor Override” function:

Double click “Open Full Blueprint Editor”, then, under “Functions”, click the “Override” dropdown and select “Request Actor Override”.

A screenshot of a computer

Description automatically generated

A screenshot of a computer

Description automatically generated


4. Add a “Branch” node between the “Request Actor Override” and “Return Node” nodes:

In the “Request Actor Override” event graph, start by clicking and dragging the border of the “Return Node” to make space for a new node. Then, click and drag from the white triangle at the right of the “Request Actor Override” node, release anywhere, and finally, type in “Branch” before clicking the option of the same name.


Note: Branch nodes exist to make an “IF” statement: If Condition is True, follow the nodes' commands connected to True. If False, follow the commands connected to False.

A screenshot of a computer

Description automatically generated

A screenshot of a computer

Description automatically generated


5. Set a Condition for the Branch created in step 4 that targets the desired Blueprint class to replace: 

To make a statement that targets the existing blueprint you’d like to replace, drag from the “Original Actor Type” pin located on the “Request Actor Override” node and release anywhere, then search for the “Equal (Class)” node and click on that option. From there, click the “Select Class” dropdown then search and select the blueprint you wish to be replaced. Finally, drag the red pin at the right of this node and connect it to the Branch node’s Condition pin.


Note: The “Equal (Class)” node can easily be found by typing in the = sign in the search bar. This node states the condition of “If the targeted actor is the same as the desired actor to override”.

A screenshot of a computer

Description automatically generatedA screenshot of a computer

Description automatically generatedA screenshot of a computer

Description automatically generated


6. Set up the “Return Node”s: 

First, duplicate the “Return Node” that was moved earlier by right-clicking it and selecting “Duplicate”, then reposition as you see fit.


Next, drag from the white “False” arrow in the “Branch” node to the white arrow on the new “Return Node”.
Then, click and drag from the “Original Actor Type” pin in the “Request Actor Override” node and release on the “New Widget Type” pin in the new “Return Node”.


Finally, in the original “Return Node” (The one connected to True), click on the “Select Class” dropdown and select the new blueprint you wish to replace with.

A screenshot of a computer

Description automatically generated

A screenshot of a computer

Description automatically generated

A screenshot of a computer

Description automatically generated

A screenshot of a computer

Description automatically generated


Make sure to compile your blueprint, save it, and you’re done!
Now, when an instance of the blueprint is spawned, it should be replaced with the new blueprint you’ve chosen!


How To: Add or Edit an NPC

This document will cover adding two kinds of NPCs, scheduled NPCs and Tier 3 “Seat Filler” NPCs. It will not cover Tier 4 “Seat Filler” NPCs, as they have a number of extra requirements that make their construction more complicated.


Take me to...


How To Open the Character Creator

You need to open and play the level CustomizableCharacter Content/CharacterCreator. It is in a plugin, so you may need to select "View Options" at the bottom right of your content browser and check the "Show Plugin Content" checkbox before it is visible.



Add a Scheduled NPC

A scheduled NPC is placed in the world based on schedule data in a schedule database table. To add a new scheduled NPC to the world, do the following:


1. Open the Registry Database Table under Window → DB Text Entry → Static → Registry and add your NPC’s name, then assign them a SubtypeID category that seems appropriate. 


For example, if we’re making a townsperson named Steve then RegistryID would be “Steve” and SubtypeID would be “Townsperson”.



2. Open the CharacterCreator level and hit Play.


3.In the top left dropdown, make sure you are in “Character” Editor Mode. In the dropdown to the right of that, the “Type” dropdown, select the SubtypeID you set in your registry table entry. 


In the “Character” drop down to the right of that, select your character’s name. In this example, they should read, in order, “Character,” “Townsperson,”, and “Steve” as below.



4. Configure your character’s appearance to your preference. When you’re done, click the “Save” button in the “Character Editor” window as highlighted below (Not the scene window!)



This will create a UCustomizableCharacterDefinition data asset containing your settings. It will be located in Content/Data/CC/#SubtypeName#/DA_#CharacterName#, replacing #Text# as necessary. For this example, it would be Content/Data/CC/Townsperson/DA_Steve.


5. Open the CharacterDefinition database table and add a new row for your character, setting the CharacterID to your character’s name. 


In this example, that would just be “Steve”. Feel free to set the other columns to reasonable values for your character at this point as well.


6. Open the ActorDefinition database table and add a new row for your character, setting the RegistryID to your character’s name, and the GenderID and SkeletonTypeID to appropriate values for your character. 


In this example, RegistryID would be “Steve”, GenderID would be “M”, and SkeletonTypeID would be “AdultMale.”


7. Next, to actually place your NPC in the world, open the appropriate schedule database table.

In this example, that would be Schedule_Overland, which covers most locations. Add a new row to place your NPC in the world. Set the CharacterID to your character’s name (“Steve” in this example), the ActivityID to GoToBed, the OverrideStartTime and OverrideEndTime to “2400”, EntryTypeID to “Time”, and ScheduleKeys to “Main”. 

Last, Set the OverrideLocationID to the location ID you want to be their “bed” point, more or less their home point. 


You can find a list of these location IDs in the Locations database table. For more information on how to make them appear at different locations, see the NPC Schedule Locations sections below.


8. Once you’ve decided where their “bed” should be, you’ll need to add a string for this bed location for your specific NPC to another table.

Open the Locations database table next. Add a new row for your NPC’s bed location. The LocationID must be formatted in a very specific way, it must be “[NPCName][OverrideLocationID][Bed”. Replace [NPCName] with your NPC’s name and [OverrideLocationID] with the OverrideLocationID you set in the last step.

So if you want your character to spawn inside Ollivander’s, you would set OverrideLocationID in the last step to “HM_Ollivanders_Vendor”, and for the example character “Steve”, the final string for the LocationID would be “SteveHM_Ollivanders_VendorBed”. You’ll also need to provide an x/y/z position for this location, as a convention you should just copy the coordinates of the OverrideLocationID you’re using, as well as setting the TypeID to “StationBed”.

Feel free to set a reasonable WorldID, but the other columns are not needed for this part. Note that this whole paragraph might not be necessary when placing an NPC in a custom dungeon.


9. Your NPC should now be spawning at that location.


NPC Schedule Locations

With just a bed schedule entry set, the NPC should spawn there. If you specify a second schedule entry, regardless of the time period assigned for it, the NPC will use that location instead of the bed location. Assigning entries beyond that will have the NPC travel between locations as you would expect.


Note that the ActivityID actually defines the location initially. You can see what locations they map to in the ActivityDefinition database table, each one maps to a LocationID. That LocationID corresponds to entries in the Locations database table that each have vector coordinates for that location’s position in the world. The location override setting is entirely optional.


Seat Fillers

Both tier 3 and 4 NPCs can act as seat fillers, but tier 4s have extra requirements that make them more involved to set up. The following steps will only cover creating tier 3 NPCs to be randomly generated into the world whenever generic tier 3 NPCs are requested.


1. Open the Registry database table and add your new Tier3 seat filler NPC’s name, then assign it the appropriate SubtypeID (Note that the name must begin with “T3” and must not end in “_Look”, otherwise it will be skipped over when reading the table). For this example, lets say we’re making a new male T3Townsperson. The highest numbered male T3Townsperson is currently 14 as of time of writing, so we add a new entry with RegistryID “T3TownspersonMale15” and SubtypeID “T3Townsperson.”


2. Open the CharacterCreator level and hit Play.

3. In the top left drop down, make sure you are in “Character” Editor Mode. In the drop down to the right of that, the “Type” drop down, select the SubtypeID you set in your Registry table entry. In the “Character” drop down to the right of that, select your character’s name. In our example, they should read, in order, “Character,” “T3Townsperson,” and “T3TownspersonMale15.”


4. Configure your character’s appearance to your preference. When you’re done, click the “Save” button in the “Character Editor” window. This will create a data asset containing your settings. It will be located in Content/Data/CC/#Subtype#/DA_#Name#, replacing #Subtype# with your SubtypeID and #Name# with your character’s name. In this example, it would be Content/Data/CC/T3Townsperson/DA_T3TownspersonMale15.


5. Open the ActorDefinition database table and add a row that includes the RegistryID for your character, matching the character’s name. So, in our example, it would be “T3TownspersonMale15.” Feel free to fill out the other fields to sensible settings at this time if you’d like.


6. Your NPC should now be considered as an option for generating T3 NPCs when NPCs of their type are spawned.


Editing Existing NPCs

Editing existing NPCs is largely trivial via the Character Creator. Select “Character” for the Editor Mode in the top left drop down. Then, select the appropriate sub type in the dropdown to the right of that, the “Type” drop down. 

Next, just find the character you wish to edit in the list. Select them, edit their appearance in the “Character Editor” window, and click the “Save” button in that same window when you’re done. 


This process is the same for Scheduled T1/2 NPCs, as well as T3 seat fillers. Note that many cosmetics do not function properly on T4 NPCs, it is advisable not to modify them via the methods described here at this time.


If you’re having trouble finding a specific NPC, you can look for them in the Registry database table. The RegistryID column will match the character name, and the SubtypeID column will match the value in the “Type” drop down.


How To: Add/Edit NPC Schedules

When not in combat, NPC characters in Hogwarts: Legacy are controlled by schedules. Schedules control when, where and what NPCs are doing during discrete time slots of each in-game day. 

During each time slot, each NPC is given an activity as well as a prop and/or location; they then use this information to perform the activity over that time slot. If an NPC does not have any activities to do in a particular time slot, they are sent to their bed until the next time slot in which they have an activity. In addition to their main schedule, quests can assign alternative NPC schedules via schedule keys.


Each level has one schedule assigned to it that governs all of the NPCs present in that level. However, a single schedule can be used across multiple levels if desired.


Take me to...

How to open the Static DB Text Entry Tool

  1. Click “Window” on the top toolbar.
  2. Hover “DB Text Entry”.
  3. Click “Static”.


How to create a New Schedule

  1. Open the Static DB Text Entry tool.
  2. In the center of the Static DB Text Entry window/tab, there are a group of buttons labeled “Create Table”.
  3. Click the “Schedule” button.


  4. Enter the name of the new schedule into the popup that appears, then click “OK”.
  5. By convention, schedule tables should start with the prefix “Schedule_”.


  6. The new schedule table will be created and opened for you.

How to change a Level’s Schedule

  1. Open the Static DB Text Entry tool.
  2. Open the table “SchedulesForLevels”.


  3. Find the level for which you want to change the schedule.

  4. Set the ScheduleName field for the level to the name of the new schedule.

  5. Click somewhere else in the window outside of the ScheduleName field to save your change.
  6. Open the level and play it in the Creator Kit.
  7. The NPCs should now follow the new schedule.

How to modify an Existing Schedule

  1. Open the Static DB Text Entry tool.
  2. Find and open the schedule table that you want to modify.


Adding Row to Existing Schedule

  1. Scroll to the bottom of the table.
  2. Find the empty row at the bottom of the table with the “+” button next to it.
  3. Fill in that empty row with the new schedule data.

  4. Press the “+” button to add the new schedule row to the table.

Change Row in Existing Schedule

  1. Find the row of the table that you want to change.
  2. Find the field within that row that you want to change.
  3. Click on the box for that field and type and/or select in the dropdown a new value for that field.

  4. Click outside of the box to save the change.

Delete Row in a Schedule

  1. Find the row of the table you want to remove.
  2. Right-click on the number on the left side of the row to open a context menu.
  3. Click “Delete” in the context menu.


  4. The row should be removed from the table.

How to delete a Schedule

Schedules cannot currently be deleted using the Creator Kit.

If a schedule is no longer needed, unset it from all of the levels associated with it using the instructions in “Change a Level’s Schedule”.

How to create a New Location

  1. Open the Static DB Text Entry tool.
  2. Open the Locations table.
  3. Scroll to the bottom and enter the LocationID, WorldID, and TypeID into the last row:
    NOTE: The positional data will be added automatically later.

  4. Click the “+” button to save the new row’s data.
  5. Restart the Creator Kit to allow the location drop-downs to be updated with the new location name.
  6. Open the level that the location will be located in.
  7. Find the asset “BP_Station” in the asset browser.
  8. Drag and drop the “BP_Station” blueprint into the level at the desired location
  9. Name the placed blueprint “Area_<LOCATION_NAME>”.
  10. Open the “Station Component” section of the blueprint’s details and set the following:
    1. Location - <LOCATION_NAME>
    2. Volume Type - Box
  11. Save the level.
  12. Open the SchedulesForLevels table.
  13. Find the row in the table corresponding to your level and check the box under DEV_SaveLocations.
  14. Play the level in the Creator Kit and walk to the location point.
  15. In the Creator Kit, click “Window” on the tool bar and select “Save Locations” under the “Station Manager” group.

  16. Stop playing the level.
  17. Close and reopen the Locationstable.
  18. The location’s position data should now be populated.

How to create a New Activity

  1. Open the Static DB Text Entry tool.
  2. Open the ActivityDefinition table.
  3. Scroll to the bottom and enter the activity ID, type and defaults into the last row:

  4. Click the “+” button to save the new row’s data.
  5. The activity should now be available for use in schedule tables.

    If the activity does not appear in the drop-down menus, you may need to close and re-open the schedule table.


How to set Up a New Station

  1. Find an existing station blueprint in the content browser.
    Typically, these will be named “BP_Station*”
  2. Place an instance of that station blueprint into the level.
  3. In the station’s details panel, assign a Location to the station in its Station Component properties.
  4. (Optional) For stations meant for a specific NPC, set the Type to TYPE OWNED and the Character to the NPC.
  5. (Optional) For stations meant to be in a patrol, ensure that the Patrol Priority is set to at least 1.

  6. Expand the box volume for the Area Station for your location so that it encompasses the placed station.

How to enable/Disable Unnamed NPCs in a Level

  1. Open the Static DB Text Entry tool.
  2. Open the SchedulesForLevels table.
  3. Find the row corresponding to the level within which you would like to disable unnamed NPCs.
  4. Un/check the checkbox WantHobos depending on whether you do or do not want unnamed NPCs.

How to add Seat Filler NPCs to a Location

  1. Open the SeatFillerSchedules table.
  2. Scroll to the bottom empty row of the table.
  3. Set the following values in the row:
    1. ScheduleKey - Typically the name of the location, but can be something else
    2. LocationID - The name of the location to which to add NPCs
    3. Start/EndTime - The start and end time at which the NPCs should appear.
    4. SubtypeID - The type of seat-filling NPC that should be added to the table
    5. Count - The number of seat-filling NPCs to spawn.
  4. Click the “+” button to add the new row to the table.

How to add Spline Walker NPCs to a Level

  1. Place an AIPath blueprint in the level using the “Place Actors” menu.

  2. Move the spline for the path to where the NPC should walk.
  3. Add entries to the “Scheduled Path” property for each type of NPC and schedule the walkers should appear during.

How to add World Event NPCs to a Level

  1. Place a “BP_WorldEventLocator” blueprint in the level.
  2. Set the “Location Descriptors” to the tags of the world events for which this locator should spawn.
  3. Set the “Percent Chance of Being Selected” to the chance of spawning if the event is chosen.


Tutorials

Tips and Tricks

Bed Stations and the GoToBed Activity

The GoToBed activity designates the location where an NPC will be when no other activities are scheduled. The activity requires a named location as well as a bed station nearby that location. A bed prop can be provided if the bed location is going to be visible to the player.


All NPC schedules must have a GoToBed activity in order for the NPC to be spawned, as the bed location represents the NPC’s spawn point and default location.


Schedule Keys

By default, all NPCs are assigned to the Main schedule. If an NPC needs to pursue an alternate schedule to support a quest, schedule keys can be used to define and change an NPC to use that alternate schedule.


Schedule keys can be changed for an NPC by using the “<Add/Remove/Replace> Schedule Override” quest tasks.


Schedule Manager

The Schedule Manager is the gameplay debugging UI for NPC schedules. It can be opened from the “System” section of the in-game debug menu and displays detailed information about NPCs, schedules, locations, and activities.

Check Schedule Tutorial 2 - Schedule Manager for a more detailed explanation of the manager and its sections.


Troubleshooting

NPC Not Appearing or Doing Incorrect Activity

  • Check in the “SchedulesForLevels” table that the level you’re playing is using the desired schedule.
  • Check in the schedule table that the NPC has a GoToBed task set with a valid station.
  • Check that the current game time is within the time window specified in your schedule.
    1. If not, the NPC should be performing the activity whose time window contains the current time.
    2. If there are no activities in the schedule at the current game time, the NPC should be at its bed station.
  • Check that there is not a higher-priority activity in the NPC’s schedule.
  • Check that there are no schedule keys active that are overriding the Main schedule and/or your schedule key.
  • Check that there is a valid location, station, and/or prop available for the NPC’s activity.
  • If the character’s name in the Registry data base contains special characters, such as [space], it will probably not spawn in the level.

Location Data Not Being Set In Table

  • Verify that your level has the DEV_SaveLocations value set to true in the SchedulesForLevels table.
  • Ensure that you are actively playing the level and are near the location in the level before running the Station Manager’s “Save Locations” command.

NPCs Using or Blocking an NPC’s Station

  • Ensure the station’s Type is set to TYPE_OWNED.
  • Ensure the station’s Character is set to the correct NPC.

Stats, Locks and What They Can Be Used for

In this guide, we will explore Stats, and Locks, two features that are essential building blocks in Hogwarts Legacy, when it comes to expanding the possibilities offered by some quest design tools.

 

Stats and Locks are two types of variables that can be used in a lot of ways, such as to make Blueprints communicate together or with the Quest Editor. Stats are using integer (whole numbers) whereas Locks are booleans (True or False). Stats can be used to track some actions the player takes, such as killing enemies, using items or interacting with an object. Locks should be used when a result can only have two options, true or false.


Creating Stats and Locks

We can freely add new Stats and Locks to a mod by editing their respective databases. Here’s how:

  1. Open Window>DB Text Entry.
  2. Search and open either StatsDynamic or LockDefinition.
  3. On the bottom row, give your Stat or Lock a name.
  4. For Stats, make the Value 0 by default. For Locks, set the LockTypeID to Simple_Locked.

A screenshot of a computer

Description automatically generated

 

A screenshot of a computer

Description automatically generated

 

That’s it, your new variables are created, now let’s see how we can use them.


Using Stats and Locks with the Quest Editor

These variables can help you communicate with Quest Editor to make your mission progress under certain conditions that are outside of the Tasks available in that tool. Setting up these variables to update via a blueprint can be a useful and relatively easy way to make more complex quests. For this example, we will edit an interactable object to change the state of a new variable and have Quest Editor track the usage of this object.

  1. Let’s start by copying an interactable object in our mod folder. Search for BP_Grindstone_interact in the Content folder.
  2. Drag that asset to your mod folder’s Blueprints folder and choose Copy.
  3. Change its name to avoid bad references when cooking your mod and open this asset’s blueprint.
  4. This asset already has an interaction set up, so drag the arrow from the ‘Parent: Interaction Initiated’ node and search for ‘Update Stat’.
  5. In that node, enter the name of the Stat you have created.
  6. The Delta will determine how much gets added to this Stat’s integer, so selecting 1 would make sense.
  7. Compile and save this blueprint.A screenshot of a graph

Description automatically generated

  8. Open Window>Quest Editor.
  9. Create a New Quest.
  10. On the first step of this Quest, adding an ‘Activate Quest’ task will make it possible to see the Quest in the HUD and menus.
  11. Add a new step below this one.
  12. Search for and choose the ‘Check Stat’ task.
  13. Under StatID, select the Stat you’ve created.
  14. Under StatCheck, let’s put ‘Is At Least’.
  15. Under 'Integer', put 1.A screenshot of a computer

Description automatically generated

At this point, interacting with the Grindstone will complete the Quest!


Using Stats and Locks with dynamic object volumes

An interesting way to use these variables is to make it so the game recognizes when enemies from an encounter have been defeated, and then triggers another event to occur, once again using Quest Editor. For this example, we will use Locks.

  1. Search Dynamic Object Volume in the Place Actor window.
  2. Drag it in you level.
  3. Let’s briefly set up an enemy to spawn from this volume. By going in the Spawning Properties, clicking the + sign next to ‘Items to Spawn’, selecting a database to pull from (EnemyDefinition in this case) and then selecting an entity to be spawned.A screenshot of a computer

Description automatically generated

  4. Turn this asset into a Blueprint by selecting it and clicking the ‘Blueprint/Add Script’ button in the Details panel.
  5. Give it the name you want and press Select.
  6. Open the Event graph tab of this blueprint.
  7. Drag the arrow from the Event BeginPlay node and search and select ‘Bind Event To On All Enemies Dead Event’.A screenshot of a computer program

Description automatically generated

  8. In the ‘My Blueprint’ panel, create a new function by clocking the + Function button.
  9. Give your new function a name ('HandleOnAllEnemiesDead' for this example).A screenshot of a computer program

Description automatically generated

  10. From the Construction Script window that opened, drag the arrow from the function’s node and search and select ‘Set Lock’
  11. Next to Lock ID, enter the name of your Lock.
  12. Next to ‘New State’, let’s put Unlocked.A screenshot of a computer program

Description automatically generated

  13. Going back to the Event Graph tab, drag from the red square of your ‘Bind Event To On All Enemies Dead Event’ node and search and select ‘Create Event’.
  14. In that node, under Signature, search and select the function you’ve created on step 10.
  15. Compile and save this blueprint.A screenshot of a computer

Description automatically generated

This blueprint should now be set up to unlock your custom Lock when all enemies from the volume have been defeated, we can set up a simple quest step that will verify this has been achieved.

  1. In Quest Editor, create a New Quest.
  2. On the first step of this Quest, adding an ‘Activate Quest’ task will make it possible to see the Quest in the HUD and menus.
  3. Add a new step below this one.
  4. Search and choose a ‘Lock Status’ task.
  5. Under ‘Lock ID’, search and select your custom Lock.
  6. Under Lock State, select ‘Unlocked’.

A screenshot of a computer

Description automatically generated

 

At this point walking next to your dynamic object volume should trigger the enemy of your choice and killing it/them will update the Lock state to unlocked and your quest will be completed. You could also use these variables to make blueprints communicate with each other even if they are not located in the same level, as long as one blueprint updates the variable and the other one checks if it’s in the state you want.


Another possibility that Dynamic Object Volumes have is to add a Restriction to them, meaning that nothing will spawn out of them unless the conditions have been met. By scrolling way down until you find the ‘Restriction Properties’ (as seen below), and clicking on Go To Named Restrictions, you can open the database where restrictions are stored.

A screenshot of a computer

Description automatically generated


Try experimenting with different Locks/Restrictions.


How To: Creating Enemy Loot Drops

When an enemy dies it has a chance to drop a bag of loot that contains an item. There are two ways to set up loot in the Creator Kit we can use Loot Groups or by Overriding the Loot Drop Container. This guide will cover how to create and edit enemy loot in the Creator Kit.


Loot Groups

Most enemies use the BP_LootDrop_Container blueprint when dropping loot. This blueprint has the default SM_Loot_Pouch_C.SM_Loot_Pouch_C mesh and won’t contain any items, we can use Loot Groups to determine what item the Loot Pouch will contain.


Enemy blueprints have a LootDrop Component that contains a “Loot Group”. Loot Groups correspond to a LootCategoryID in the LootContainerContents Static Table and determine what item(s) the enemy can drop and how often those items will drop.


Loot Container Content

The LootContainerContent Static Table will define what Virtual Container the enemy will use. To view and edit these categories we’ll open the LootContainerContent Static Table by selecting Windows > DB Text Entries > Static. From there select the LootContainerContent Static Table.


The LootContainerContent Static Table matches the Loot Group with a ContainerID to determine what items will be dropped and how frequently it will drop. For example, the E_Troll Loot Group will cause any enemy with that loot group to drop an item from the ITEM_TrollMucus Virtual Container.


The LootContainerContent Data Table has multiple options that allow use to define the drop rates and set conditions for what level an enemy needs to be to drop certain loot from that Loot Group.


  • LootCategoryID refers to a Loot Type. The table can have multiple instances of a Loot Type and they will all be consolidated into one weighted random roll.
  • ContainerID refers to the Virtual Container that holds a selection of items to pick from. If this container is selected by the weighted random roll, the Min Items # will be added to the loot drop. The items that are picked are evenly randomized (So if there are six items in the container, there's a one of six chance that they player will receive that item from the container.)
  • Weight refers to the number range that will need to be rolled in order to get items from the specific container. This is not a percentage, but rather a range that will be added along with other applicable virtual container weights. The total weight is calculated from the sum of all the weights from all of the entries in the table that match the encounter criteria. A base weight of zero means the item(s) will always be added to the loot drop. This can be used to place quest items on specific mobs.
  • ContainerWeightAdjust refers to the amount of weight adjustment that will happen after each roll to a specific container to ensure a certain container is selected over time. After this container is selected all added amount will be subtracted
  • Min Rolls refers to the minimum number of rolls for this LootCategoryID that needs to take place before the container is considered. This allows us to tune based on requiring a minimum number of kills.
  • NPC Range Low refers to the minimum progression level of the NPC that the container will apply to.
  • NPC Range High refers to the maximum progression level of the NPC that the container will apply to.

Virtual Container Content

A Virtual Container is an abstract container that we can add multiple different items to, we can then assign that container for any Loot Category we want to drop that set of items. For example, the RONE_AllGear Virtual Container contains all of the gear in Hogwarts Legacy. We can assign this Container to a Loot Category to allow that enemy to drop any kind of gear. This will allow us to have multiple items in one Virtual Container to give enemy drops more Variety.


We will use the VirtualContainerContent Static Table to determine what items that Virtual Container will contain. To edit the Virtual Containers, we’ll open the VirtualContainerContent Static Table by selecting Windows > DB Text Entries > Static. from there select the VirtualContainerContents.


The VirtualContainerContents Static Table allows us to choose what item the Virtual Container contains, how much of that item it should give, and the rate that item is chosen. These items can be created and edited from the ItemDefinition Static Table.


  • VContainerID refers to the name of the container being used.
  • ItemID refers to the name of the item being linked with said Virtual Container. 
  • Variation isn’t used
  • ItemQuantity refers to how many stacks of the item will be given for the listed item. 
  • ItemQuantityHigh refers to the upper limit of the number of stacks the item will have if the ItemQuantity is supposed to have a range of stack quantity. Otherwise just mark as 1. 
  • ItemRandomWeight refers to the chances of the item for that container being selected during the systems roll. 
  • ItemWeightAdjust: refers to the change that ItemRandomWeight will have if it's not selected for the current roll. All weight values will reset once the last roll has been completed. 
  • UniqueItem refers to whether this item unique or not. Meaning is there only one item like this available for the player to have. 

Changing Enemy Loot


 Now that we know how the loot system works next, we will look into how to set and change an enemy's loot. We’ll use the Loot Drop Component on the enemy blueprint to set the dropped loot. For this guide we’ll use the BP_DarkWizard_ExtortionistCaptain enemy.


Loot Drop Component 

The LootDrop Component defines what kind of items an enemy can drop. The BP_DarkWizard_ExtortionistCaptain uses the E_Humanoid LootGroup which consists of multiple Virtual Containers. These Virtual Containers each contain of a set of Items the Dark Wizard Capitan can drop mainly Wiggenweld Potions, Gear, and Knuts.


To change the loot the Dark Wizard Capitans can drop we’ll change the Loot Group to E_Troll. This will cause the BP_DarkWizard_ExtortionistCaptain to use the ITEM_TrollMucus which will cause all of the Dark Wizard Capitan enemies to only drop Troll Bogeys. Compile and save the Blueprint.


Creating a New Loot Drop Item

In this section we will cover how to create our own loot drop item. To do this we’ll create an item, assign it to a Virtual Container, assign that to a Loot Category and then assign that Category to an enemies' Loot Group.

Create an Item

For this example, we will create a new potion ingredient called SuperTrollMucus that the BP_DarkWizard_ExtortionistCaptain will drop. We will start by creating an entry in the Registry Static Table. Open the Static Text Entries and Select the Registry Static Table.


The Registry Static Table is the starting point for creating most assets that will be referenced in Static Tables. Scroll to the bottom of the Registry Table and add a new entry with the following data:

  • RegistryID: SuperTrollMucus
  • SubtypeID: PotionIngredient


Now that we’ve made the SuperTrollMucus potion ingredient entry we will define what kind of item it is. We’ll do this creating an entry in the ItemDefinition Static Table. Open the Static Text Entries and select the ItemDefinition Table.

For the SuperTrollMucus we will just set the ItemID to our SuperTrollMucus Registry entry and the ItemType to an EnemyDrop. There are many options in the Item Definition table to choose from to further customize your Item.


  • ItemID refers to the name of the item as it's referred to by the other tables. (This will be the name that you are looking for when tracing the item in other tables.)
  • ItemType refers to the purpose of the item or what kind of item it is. 
  • ItemType2: also refers to the purpose of the item. Items can have multiple purposes and this is where the second use would be stated. 
  • RarityTier refers to the rarity of the item following the design specs. The item can range from rarity 0 to 5, 0 being common and 5 being (Name for high rarity). 
  • EcenomicValue refers to the value that is registered by the player when buying items from vendors. 
  • SellPrice refers to the value that is registered when players want to sell the item on the market. 
  • Inventoryable refers to whether the item can be put into your inventory. An example for an item that wouldn't be inventoryable would be schematics or blueprints for crafting where the item is picked up, but not added to your inventory. Instead this item unlocks knowledge for the player and is then linked to the player's knowledge cards in the compendium. 
  • Persistent refers to If the item is dropped in the game it will or will not be deleted after a set amount of time. Items that are marked as Persistent will never go away and can be picked up later at any time. 
  • Giftable refers to if you can give this item to another character in the game as a gift. 
  • Sellable refers to whether this item be sold. (Items that are marked as Sellable should have a Sell Price as a general rule of thumb.)
  • Dropable refers to whether the Item be picked up by the player. 
  • ItemUsageType refers to the animation/action that is performed when using said item. I.e Eat, Throw, Drink, etc. When the item is used the type of usage will be called. 
  • ItemUsageObjectID refers to the ID for the object will be spawned upon use of the item. 
  • Consumable refers to whether the item will be deleted upon use. 
  • LockID refers to the lock associated with the item. Upon getting the item the lock will be toggled to either locked or unlocked depending on its current state for the item. 
  • PrerequisiteLockID refers to the condition that must be met before the item can be obtained. This could refer to having completed a quest beforehand or meeting certain curriculum criteria before you can get said item. 
  • PrerequisiteLockID2: Items can have multiple prerequisites before they can be obtained. If so this is where those criteria would be stated. 
  • SlotLevel refers to the size of the max inventory stack size. 

Next, we will create a Loot Category for the SuperTrollMucus, this will be the setting we select in the Enemy Blueprint to call the Virtual Container(s). In the LootCategories Static Table we will add an entry with the following data:

  • CategoryID: E_SuperTroll
  • TypeID: EnemyLoot


Next, we’ll create the Virtual Container to let us assign our item(s) to the Loot Container. We will do this by opening the VirtualContainerList table in the Static Tables and create a new entry with the following data:

  • VContainerID: LOOT_SuperTrollMucus
  • TypeID: LootDrop


Now it’s time to hook everything up. Open the VirtualContentContainer Static Table and create an entry with the following data to reference our Super Troll Mucus loot.

  • VContainerID: LOOT_SuperTrollMucus
  • ItemID: SuperTrollMucus


Last but not least we will assign our E_SuperTrollMucus Category ID to our Troll Loot Item. To do this we will open the LootContainerContent Static Table and create an entry with the following data.

  • LootCategoryID: E_SuperTroll
  • Container ID: LOOT_SuperTrollMucus
  • ContainerRandomWeight: 100
  • Item Roll Count: 1


All that’s left is to hook up our Loot Group to our Dark Wizard Capitan. Open the BP_DarkWizard_ExtortionistCaptain and assign E_SuperTroll to the Loot Group. Compile and save the BP_DarkWizard_ExtortionistCaptain Blueprint.

Note: You may need to exit and relaunch the Creator Kit for your Loot Group to appear in the Loot Group list.


All that’s left to do is spawn in a BP_DarkWizard_ExtortionistCaptain, defeat it and collect our SuperTrollMucus loot!


Overriding Loot Drop Container

Enemies use the BP_LootDrop_Container by default, but we can override this by using the “Override Loot Drop Container” field in the Enemy State Component. This will allow us to change the mesh of the dropped loot, it will also let us change what item the loot drops.


For this example, we will use the “Override Loot Drop Container” to cause our SuperTrollMucus to drop as the SM_Potion_TrollMucus.SM_Potion_TrollMucus mesh instead of the default loot pouch.

 The easiest way to create a new enemy drop is to duplicate an existing enemy drop blueprint. We can find the existing enemy drop blueprints in the Creator Kit here: Content / Gameplay / InventoryObjects / EnemyDrops / Blueprints


Create a copy of one of these and paste it into your mods folder. We will also copy and paste the SM_Potion_TrollMucus.SM_Potion_TrollMucus static mesh located here Content / Gameplay / InventoryObjects / PotionIngredients / Meshes / SM_Potion_TrollMucus into our mods folder.


Rename the BP_EnemyDrop_WolfFur to something similar to your item drop (ie. BP_EnemyDrop_TrollMucus). After you’ve renamed it double click the BP_EnemyDrop_TrollMucus to open it.

 Next, we will assign the DB Type and ID in the Object State Component. We will assign this to the SuperTrollMucus item we created in the previous section.


Now this BP_EnemyDrop_TrollMucus will drop the SuperTrollMucus item, but it will still have the Wolf Fur Static Mesh. To change this, we will set the Static Mesh in the StaticMesh Component to the SM_Potion_TrollMucus.SM_Potion_TrollMucus static mesh. Compile and save the BP_EnemyDrop_TrollMucus.


Finally, we’ll set the Override Loot Drop Container” field in the BP_DarkWizard_ExtortionistCaptain’s Enemy State Component to the BP_EnemyDrop_TrollMucus. Compile and save the BP_EnemyDrop_TrollMucus. blueprint.


All that’s left to do is spawn in a BP_DarkWizard_ExtortionistCaptain, defeat it and collect our SuperTrollMucus loot. Now instead of the look pouch it’ll display the SM_Potion_TrollMucus.SM_Potion_TrollMucus static mesh!