Archive:
None of the NPCs that I've put in the game allow you to re-enter into a conversation. You need to move outside, and then back into, their trigger area, which restarts the process. Obviously, this is not ideal, so today I went through each NPC and their ABRs and added the missing code to revert and restart.
I'm at the point where I know how I want this entire thing to work: how NPCs are built, how their ABRs interact, and what communicates with the player, so I went through all the NPC related code and made sure everything that should be in the base classes was, and that it all had sensible defaults.
Now the timeline and main inventory is in place, the UI and player controls need to be updated to respect it. I've gone through the Quick Select Wheel and made sure that it's only showing you what you've collected, and under the hood, started adding checks in the correct places. But... PlayerState is not carried across a map load, and all my main inventory items are given to the player in external maps, so...
Tomorrow I'll be adding some basic persistence.
Dipped my toe into persistent state. What I need to save is incredibly simple, a few bit-flags, so I can literally bounce them up to the game instance when classes are torn down, and then read them back from the game instance when they're re-instantiated. This led me down the rabbit hole of "when exactly does UE recreate these classes" and the answer was "not when I expected".
LoadLevel is a blocking call, leading you to expect that it'd begin the tear down process straight away, but nope. Loads of the framework classes remain for many many many frames, and the order they're brought up wasn't quite what I was expecting either...
I was looking for one, tidy place, to re-import all the state, but I'm going to have to devolve back to constructors and/or init functions in the individual classes. I can smell race bugs around the corner if I'm not mindful.
For now I've pushed it up to the Level Blueprint. It was setting up the PlayerCharacter for each location, it can tell the PlayerState to sort itself out, as well.
Once I dug myself out of that hole, I decided to update the Inventory Quick Select UI. I hadn't tidied up all the bits and bobs that were in the UI related to making the sword to arm and disarm itself, so things could break. The Inventory Wheel also needed to track if the player's collected an item, before allowing them to use it…
I thought today was going to be simple, but I went down another rabbit hole...
I want all the entrances to interiors (in the first village) to be locked when the player first encounters them, so I can funnel them to where I want them in the first half hour without distraction. This is a bespoke hack for new games, so I'm not massively worried about how it's implemented. The doors have ToD locks and can bring up statement dialogs -- that was done last week -- so this should be an extra little override. Nothing fancy. Except when I want to test it...
There's no easy way to flush all the quest state so I can repeat a test while running. I looked at a bunch of things to help with this, even playing with Editor Widgets so I could have some buttons floating about in the editor (definitely need to find a use for those in the future) but getting world context proved to be a ball-ache, and then I realised that I wasn't actually clearing the quests at the start of a PIE game, anyway. You need to go through the main menu...
I have a pattern in Unity where, when I press play, I detect I'm in a random scene and do some magic to short circuit having to go through any menus. I knew I'd have to do something similar for UE at some point, and that was today. Except, it's a doddle! Override StartPlayInEditorGameInstance(...) and do any cheaty setup stuff in there.
I still need a way to change Quest state dynamically, so I'm going to have to add a list to the Dev Menu. At some point...
After that diversion I started looking at the Baby Dungeon. I want the player to look at a specific object in the world and interact with it, so I can kick off a cut-scene, and there's nothing like this in the build atm. After a lot of umming and ahhing, and a bit of Googling, I realised I can use my new toy: multicast delegates, and have things attach to specific action button responder to receive event updates. This worked so well that I ended up putting a bunch of BlueprintAssignable delegates in the base class of the ActionButtonResponder, as it'll be an ideal way for NPCs to trigger Anim Montages on themselves during conversations.
Now I have a hammer, everything looks like a nail!
Worked in the baby dungeon today, completing the timeline for giving the sword to the player. There're a few placeholder bits, here and there, but the scaffold is in place. More importantly, it's re-entrant, so doesn't reset across level loads.
The only reason NPCs have bespoke ABRs is so they can play animations when talking. Now that there're delegates in the base, the derived classes don't need to manually move the conversation forward. I created a couple of helpers in the baseclass and deleted looots of code from all the NPC's ABRs. Feels very good indeed.
Went through the C++ code, top to bottom, and reviewed all the GNTODO comments. I'm well past the point of being able to memorise all the code I've written, much less all the things I've left half-written, so this was long overdue. I deleted stale comments and wrote code for the low-hanging fruit. The stuff that's left is either audio/player feedback, or stuff around systems (such as save/load) that I'm not writing yet.
Made a packaged Development build and a packaged Shipping build and played through both looking for bugs. The cook is clean as a whistle, and both builds appear to be fine.
That makes two days in a row where I've ended the day with less code. Quite happy…
Previous Post: "Nice UE4 related video..."Friends:
If you like any of my work, please consider checking out some of the fantastic games made by the following super talented people: