February '21 Update

Published March 06, 2021
Advertisement

Let's just dive right into all the details of this update, shall we!

Recap

  • Missiles Design
  • Separate out some code to a new plugin
  • Begin Work on Squadrons
    • New equipment system needed

Results

The sprint went okay. The way I layout my goals for you, dear reader, and the way I plan them out in my project management tool are a little different. So while I was a bit vague in my last post I was considerably more specific about what I wanted to accomplish. And I missed that mark by quite a bit. But that was a planning problem and not an execution one. I'm happy with what I accomplished in the time that I had available and everything else can just be done later (this is the upside of no real deadlines). I've been wondering if this is a result of using a “real” tool for task tracking and it's causing me to put more pressure to complete the things that I plan for a sprint than I should. It would probably be better to start undershooting planning wise and then bring in new stuff. Or split the middle and have things that are planned for the sprint but more as stretch goals so that there is still a narrow focus sprint goals and I'm not flailing about on semi-random things when I've got extra time available.

Missiles Design

Again I wiff'd on this one pretty hard and didn't get anything designed. It's sort of annoying, but maybe it's for the best. I've got plenty of work to do now on the squadrons so I'm going to try leaving this to bounce around the back of my mind while I work on other things for the foreseeable future.

New Plugin

My project structure used to include 2 plugins that I'd written to organize the code that I wanted to share with other projects. Well now I've got 3! I moved a few core elements from my highest level plugin down into a new plugin that rests between the 2 that I previously had. Overall this went really well. The engine provides some good tools for doing these sorts of moves so I was able to easily preserve all the type references. The move also had the added benefit of finding a class derivation that was probably backwards. So finding and fixing that was encouraging that this was a good decision.

Starship Modules

Before getting started on squadrons, I needed to make a minor tweak to some of my data. Previously my starships just had the list of weapons that were currently equipped to each of its available slots. But the equipment that would support squadrons aren't really weapons and most of the configuration for weapons don't make sense for equipment that doesn't provide an action. So I decided to introduce another level of indirection: starship modules. The modules allow for separating out the data specific to assignment from function and providing a common element for starships and strikecraft to reference. Between the strong static typing in C++ and Blueprints, this went very smoothly. Changing a couple of core variables resulted in a string of compiler errors (and eventually Blueprint compiler errors) that when fixed, everything just worked. The main functionality provided by the base module type is stat adjustments and slot compatibility. You can't necessarily place a hanger bay in the same places you could a laser cannon, so the module has the information (gameplay tags) that can be matched up to the slot data of the starship or strikecraft. It's also possible to create new module types that have additional information for the module. Currently that means a weapons module with a reference to the weapon data I was equipping before so that those objects are still available properly when in the tactical game mode.

Squadrons & Strikecraft

As I mentioned in the recap, I was hoping to make it a bit further but overall I'm happy with how much I was able to do. What I was able to do was 1) the overall game data from tracking squadron information over the course of the entire game and 2) a UI screen for managing the allotments of squadron to starships and strikecraft to squadrons. I decided to punt on a real solution for building the strikecraft and did a quick and dirty console command. Which overall isn't terrible since I would want a console command for doing that anyway.

Here's the current state of the UI for strikecraft management:

To the right you find the current reserves of the strikecraft of each type that are available to assign to starships.

To the left are widgets for each of the starships that have hanger capacity. The top of the widget show the general information of the ship: icon, name, squadron count and capacity. The bottom of the widget is a button that can add a new squadron and a drop down for selecting the type of squadron to create. When the squadron count meets capacity, that button and drop down are hidden. If there aren't any strikecraft available for the selected type, the add button is disabled (as seen in the image with Medium Fighters selected).

In-between are widgets for each of the squadrons showing the icon, squadron name, strength, maximum and equipment. There's also an extra button on the far right for deleting the squadron entirely. I don't really like the drop downs solution for the equipment, but it was expediate and reasonable solution for now. I already know this UI isn't final, so I opt'd for something functional over final. It's also easy identify the difference in squadrons, the Light Fighter only having one weapon and the Heavy's having three. The plus and minus buttons also enable/disable based on the size relative to maximum as well as the available reserves.

Bonus - Custom Create Widget K2 Node

I spent a lot of my time in blueprints this sprint working on that UI and I started to become a bit annoyed by some repetitions in my code. This is the code that spawned the widget for showing a single starship, it's current squadron allocation and all the sub-widgets for show individual squadron information.

Moving left to right you can see how I a) create the widget b) store it off for easy reference c) add it to a collection d) add it to a panel e) modify the panel slot a bit (which requires a cast because in this case scroll boxes don't have their own Add Child function that returns their type of panel slot!?) f) call an Init function.
Strictly speaking, I don't really need the Init function. UnrealEngine provides the ability to markup class members as “Expose on Spawn” and when you do calling a function like Create Widget will create input pins as part of the blueprint node (step a). This can actually be pretty convenient, but I'm starting to think they might be too convenient. In many cases I want to use one piece of data to initialize multiple members or after initialization I don't want to worry about storing the value any longer. They also break encapsulation because they're basically public variables, ones that may only be able to be set at construction time, but still directly assigned to. So for most of my custom widgets I've been writing Init functions that actually define what the needs are for construction in a way that is divorced from how it stores any of it's data.

But I at this point I can do some pretty crazy things with custom blueprint nodes so I decided I didn't really have to stand for any of that and could make a custom version of Create Widget that worked better for me and my projects. So now all that code boils down to this:

There is still the assignment to an easy reference (step b), the modification of the panel slot (step e) and the addition of it to a collection (step c). But the other steps of creating the widget, adding it to a panel, casting the panel slot and calling Init are all handled by the custom node. It's flexible enough that you don't have to provide a panel if you're going to do something else “weird” and it will also work if the widget type doesn't have an Init function (maybe all the data is perfectly reasonable as “expose on spawn” members, which this node also supports). Similar to “expose on spawn”, the custom node is able to duplicate the parameters of the Init function so that whatever type you're creating the node will expose the right data to pass through to the Init function. I did have to make one minor engine tweak to make this work in order to get access to the type of the slot used by the panel. Panel Widgets know exactly what type of slot they're going to create, they even have a virtual function to get it, but it was protected. I didn't really see the harm is making it public so I did. I could have built my own table of panel types to slot types, but that'd just be brittle so why bother when I've got the engine source to play with.

K2Node Tutorial

As I mentioned in my last post I published my tutorial on building custom K2 nodes (which you can checkout here on Gamedev.net if you haven't already). I published it Feb 6 and as of March 6 it's at a little over 8K views. That seems pretty good but I don't really have a good point of comparison. These blog posts seem to top out at about 1.5K, but the tutorial was visible from the front page for much longer than a blog post ever does (which I sort of figured and why I posted it as an actual tutorial and not another blog post).
I also posted it to a few reddit communities. Unsurprisingly it did the worst in r/gamedev (currently 1 upvote and 67% upvoted), the most general and highest churn of the ones I posted to. r/truegamedev did a little bit better (10 upvotes and 73% upvoted) and r/unrealengine did the best (30 upvotes and 90% upvoted). I don't do a whole lot of posting on reddit, so I don't really have a sense of how that really translates into how well received it's actually been. A part of me can't fathom why anyone would downvote something like this, maybe because it's not a video tutorial, maybe they were all Unit fanboys that hate on anything Unreal.
I hope it's been able to help people, I haven't really gotten any feedback one way or the other (except from my proof reader). Oh well, I should be proud of what I published even if no one else cares.

Goals

  • Custom method for blueprint delegate binding
    • Another fallout of all my UI work is that I really want a better way to bind to the event delegates I've been adding to my widgets from them to inter-operate. This is almost exclusively done by the UI that creates the widget so that it can be informed something happened in the widget. But I don't really like the two nodes you have to make to do this. This one will probably stretch me a bit on what I've done with custom nodes.
  • Continue work on Squadrons gameplay
    • The primary goals will need to be a) the ability to construct strikecraft for real (instead of using a console command to add them) and b) starting on implementation of the tactical side of squadrons.
    • I also need to do something real with the squadron names.
  • Revisit Tactical HUD UI organization
    • I've done a lot more with UI stuff since I originally built the Tactical HUD. I noticed some weird things that I'm doing that I could do better and simplify the code in certain ways. Ways that should make it easier to do the tweaks that will be necessary to move forward with squadrons.

Changelog

  • 1326 Create an empty plugin for History related systems.
  • 1327 Make a pass at cleaning up the public/private dependency settings of build.cs files.
    • Add a few includes that came up as being needed (not entirely sure why they weren't before, probably unity build weirdness).
  • 1328 Create a blank plugin with game, developer and editor modules.
  • 1329 Branch a couple of utility files for blank and history plugins.
  • 1330 Move History, EventManager & VisManager systems into a lower level plugin (but above CoreTech).
    • Create new header for the ConditionEvent structure (for now remaining in StrategyTech).
    • Swap inheritance of VisualizedStateObject & TileOccupierStateObject to allow Visualized to be part of the lower plugin.
    • Leave redirectors in place in SRPG to maintain valid data.
  • 1331 Resave content to fixup type references to those moved from StrategyTech plugin to HistoryTech.
  • 1332 Move source from StrategyTech Developer Module to the HistoryTech Developer Module.
    • Leave redirectors for all the types moved.
  • 1333 Resolve the class redirectors from moving custom K2Nodes.
  • 1334 Update common plugin repository
  • 1335 Update RFtG with lastest plugin source
    • RFtG is a reference to my Race for the Galaxy side-side project mentioned in previous posts but that I haven't done any major work on recently. Feeling too good about the work on SRPG.
  • 1336 Secondary merge to RFtG to pick up file moves properly
  • 1337 Updates to RFtG for newest plugin versions
  • 1338 Update Underworld with latest version of CoreTech plugin.
    • Underworld is another UE4 project that I started but haven't done much with. Currently it's basically just the twin stick shooter template. You may also notice that it's not even using the History or Strategy Tech plugins!
  • 1339 Tweak the tactical cursor so that it is always visible while within the bounds of the map.
  • 1340 Add a thumbnail implementation for Action Definitions.
  • 1341 Create a new definition type that will be new thing that is actually equipped, Modules. Create a subtype that references a weapon definition as the action that the module provides in tactical. Create Weapon Modules for each of the existing Weapon Definitions.
  • 1342 Replace weapons with modules throughout strategy as the "thing that is equipped". Update definitions, update UI, update tactical ship initialization.
    • But once in tactical, weapons are still the thing to actually take actions.
  • 1343 Rename the structure and member tracking possible modules for a starship's loadout.
  • 1344 Allow modules to influence the tactical stats of a starship.
    • Add stats for hangers and launchers.
    • Create modules for initial squadron supporting modules.
    • Add image assets for icons for the squadron modules.
  • 1345 Update the weapon widgets/tactical hud/targeting ruleset to track weapons strictly by ID and not by index into the modules array.
  • 1346 Update the naming of some members and a structure to be Module/Slot based.
    • Resave definitions and blueprints.
  • 1347 Initial add of module types & compatibility.
    • Add types to class configuration.
    • Add allowed types of slots to the modules.
    • Add a utility function for checking compatibility
    • Add validation that loadout definitions only list compatible modules for each slot.
  • 1348 Add TitleProperty meta tags to a few definition array properties.
    • In the case of Starship Loadouts, build that member dynamically specifically for the purpose of the Editor UI display.
    • Refresh and resave the existing loadout assets.
  • 1349 Enforce module slot/module definition compatibility from the UI.
    • Fix a bug with locking an empty slot and trying to assign to it the first time.
  • 1350 Make a renaming pass on the various Loadout blueprints for Hardpoints -> Module Slot.
  • 1351 Privatize the starship loadout and when updating the loadout double check that each element is compatible with the slot it's been assigned to.
  • 1352 Missed a couple function comments.
  • 1353 Basic tracking of strikecraft/squadron data from strategy.
    • Refactor the Starship Definition a bit to share a base type between ships and strikecraft.
    • Create definitions for some basic strikecraft.
    • Tweak the Starfleet dev faction to start with fighters unlocked
    • Tweak the NewConstruction project to be limited to starships
  • 1354 Create the initial strikecraft management screen.
    • Create a widget that can be used to show the reserves count for a single class type.
    • Refactor some code so that a faction can be queried for the classes currently accessible by the faction.
  • 1355 Tweak the name of a function to be a little more accurate.
    • Make it blueprint callable as well.
  • 1356 Create a widget that can be used for each ship to manage their squadron configuration.
  • 1357 Add a dropdown to select the type of squadron to create.
    • Modify how the allowance of new squadrons is determined so that as strikecraft types are selected the AddSquadron button is updated based on reserves availability.
  • 1358 Add events and event handling for changes to the strikecraft reserves and starship squadrons.
    • Add a state change to add a squadron to a starship with hanger space.
  • 1359 Create a new widget to show the properties of an individual squadron.
    • Update the strikecraft assignment widget to create the new widget when a squadron is added to a starship.
  • 1360 Temporary rename of the squadron/strikecraft assignment widgets.
  • 1361 Checkin from Content browser didn't include file deletions.
  • 1362 Finalize the rename to swap the naming of the Strikecraft and Squadron Assignment since the heirarchy of widgets should be Management > Squadron > Strikecraft.
  • 1363 Add widgets for displaying/manipulating the strength of the squadron.
  • 1364 Enable the squadron size buttons with functionality.
    • Track squadron size changes in a queue that can be flushed to be batch applied to the game state.
    • Track pending size changes and update all the controls based on the pending information.
    • Allow access to the Strikecraft Management screen regardless of reserve sizes (because all your strikecraft may be assigned to starships, duh).
  • 1365 Add some ensures on the initial size of a squadron (there shouldn't be squadrons of strength 0)
    • Reorganize the initialization of the Squadron Assignment widget some
    • Update the Squadron Assignment widget to construct Strikecraft Assignment widgets when the screen is open (for any squadron a starship may already have)
    • Add a spacing bar above the controls for a new squadron and a spacer so that the size of that space approximates the size of a Strikecraft Assignment widget
    • When a starship reaches maximum capacity, hide the new squadron controls instead of just disabling the AddSquadron button.
  • 1366 Add functionality to remove a squadron from a starship.
  • 1367 Move the State Condition, State Effect, Tag Resolver down to HistoryTech.
    • Create a TacticalConditionContext that can provide tile context information.
  • 1368 Resolve class redirectors for code moved into the HistoryTech plugin.
  • 1369 Add UI elements and queuing for modifying the loadout of strikecraft.
    • Add state modifications to update the game state with loadout changes.
    • Add tags for strikecraft specific slot types.
    • Update strikecraft definitions with module configuration.
    • Update weapons with reasonable allowances for strikefighter slot types.
  • 1370 Add pins to go with the Settle and Finish exec pins that outputs the visualization that is settling or finishing.
  • 1371 Refactor the creation of pins for a function signature into its own function.
    • Create the initial framework for a "better" version of the Create Widget node.
  • 1372 [[UE4 ENGINE]] Tweak a virtual function on the PanelWidget to be public so that the information can be used for a dynamic k2node pin.
  • 1373 Add logic that makes the panel slot pin change type based on the type of panel that was connected to the panel input pin.
  • 1374 Factor out some code from the ExpandDispatcherPins function so that it's reusable for other function situations.
  • 1375 Finish implementation of a replacement/improved version of the CreateWidget node.
  • 1376 Update the Strikecraft screen and widgets to use the CoreTech Create Widget node.
  • 1377 Update existing nodes to use the commonized param name for "self" pins.
0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement
Advertisement