April Update

Published May 05, 2019
Advertisement

My friend @slayemin made a good suggestion after my last journal post which was to be sure to post on a regular schedule. Seems obvious, but sometimes someone's got to say the obvious thing. I'm hoping to keep on a monthly schedule at this point, I even planned to have this posted last weekend but had a technical snafu and had to re-write almost all of it. I think that gives me enough time to make some sort of share-able progress. Personally it's always been a little frustrating how much (or little) I can get done on a hobby project. I probably could have done this whole month's worth of work in a few days, maybe a week, if I were working full-time. There isn't really anything to be done about it, for a hobby project I have to be happy with what I can accomplish in the time I have available. Burnout is potentially a real issue, but it's a nice change to work on a project where I can decide and execute. No consensus, no meetings, just work.

Asset Mangement

UE4 has a pretty slick asset management tool available call the AssetManager (introduced in 4.17 I believe) that does a lot of really great things but it also has a couple really annoying features. The first is that it treats asset types (which exist as normal UE4 C++ classes) differently than the rest of the engine treats types. For example if you were to ask the engine to iterate all Equipment, you'd visit all the Weapons and Armor in the game, but if you ask the AssetManager for all the Equipment it's loaded it will only give you back assets that are the exact type match. The other is that because of this you have to add an ini setting for every asset type you want the AssetManager to support. Now these are really only an issue because basically every one of my assets right now derive from a single type that I call DataDefinition.

A DataDefinition is a pretty classic Flyweight pattern and is the shared static data that all versions of the same object would have. On X2 they were called Templates, at Volition they were called Infos, but everyone seems to have their own version. Mine also act as a sort of factory for game objects, but that's a discussion for another blog. The Definition was an asset so that all the derived types would be able to leverage the AssetManager to do the bulk of asset management for them, unfortunately the interface the AssetManager provides isn't how I want to access my Definitions.
As with most of the UE4 engine types, the AssetManager is designed to be derived from and extended. So I had previously done that and added a whole new API for dealing with Definitions. After having loaded all the definitions at startup (more on that later) I keep track of them in my own maps so that I query them based on classes and get the instances back that I expect (like all the Weapon and Armor when I ask for Equipment). I also made my Definition API only provide access to const instances because the whole point of the static data is that it shouldn't be getting changed during run-time (they're still plenty editable by a user in the Editor though). That basically solved my first issue with the AssetManager.

The thing that I did this month was attempt to fix my other issue with the AssetManager which was the ini configuration for each type that was derived from DataDefinition. I was basically able to hook into the AssetManager before it looks for assets and update the list programatically by going through the UE4 reflection to add entries for every class that is a child of DataDefinition but didn't' have an entry already specified in the ini file. For those that were missing, I looked for the nearest parent type that was included. This way I can just have a config setting for DataDefinition for now, but if I add a type that should live someplace else, I could add a specific entry for that type only when I need it and not as boilerplate when adding any type that derives from DataDefinition. I was pretty happy with it and so reimplemented it at work since we've already had a number of bugs caused by missing ini entries.

Definition Loading

You may think it's crazy to load all my DataDefinitions at the start of the game, but that's the beauty of them being assets within the AssetManager. Firstly, it really helps with game play to have the full breadth of game options available all the time even if there isn't an instance running around the world. Secondly the Definitions themselves are small, almost tiny, and all of the really heavy data like textures or models or sounds are other assets that aren't immediately loaded.

Plasma Weapon

Most of what I've been working on this month has been a new weapon currently being called a Plasma Bolt. I designed it to require quite a few specific elements I wanted to include support for:

  1. The Plasma Bolt requires no energy to fire (already supported) but does require ammo (already supported)
  2. Plasma Bolt ammo starts at zero (already supported)
  3. Includes a supporting action that allows spending energy to create Plasma Bolt ammo
  4. Damage increases for additional ammo above the minimum requirement to fire the weapon
  5. Damage decreases based on distance between the source and target
  6. Firing the Plasma Bolt uses up all the ammo the weapon has

I ended up working my way up from the bottom of the list. Adding a toggle to the ammo feature was trivial. It was also pretty quick to add the two damage modifiers. I wrote a nifty structure of int/float pairs that can be used to calculate a value. One form of calculation is a just a linear interpolation of the input in-between the int's to generate a value between the floats, this is the version I currently use for the damage reduction by range. The other version uses the same data but for every multiple of an int in the value it adds that multiple of the float as the output. It starts at the high values and works backwards so that it will use an entry for 5 before using the 1 entry 5 times.

The biggest change was for the supporting action. I already had a weapon definition that included a lot of what an action would have to have: various display elements, cost handling, game state mutation, etc. But there was also an awful lot that I didn't really need like everything related to targeting. The game play changes were again pretty easy and straight forward, it was the UI that took me a while. I had already made a button that could be used with a weapon and display the icon and stat values, but now a weapon should actually be a collection of those buttons, one for the weapon and a few for it's supporting actions. That took awhile to restructure to having an action button and a weapon button that contained action buttons and showed a hide them based on hover events. The most annoying bit I ran into was that apparently you don't get hover events from disabled buttons. Since the action button was already intercepting the events from the basic button it contained to trigger it's own delegates to anyone interested, I resorted to just adding an invisible button on top that is never disabled, but uses the state of the other button to decide if it should inform listeners about a click event. It's probably something worth revisiting eventually, but not now.

Plasma.thumb.png.08757ab9415267f30fa5430612623db3.png
Here's the redone UI, but like any good refactor it's looks basically the same. You can see the Plasma Bolt is currently disabled due to the lack of ammo available to fire.

Plasma2.thumb.png.d4cb89cfc53d55cc83e3cbc274c58d0d.png
When hovered you can see the extra action button shows up.

Plasma3.thumb.png.15464263e924c810d064220ef2705a38.png
After clicking the action button, the Plasma Bolt now has 2 ammo available and can fire (that's the minimum).

What's Next

So now that I think that I've got enough structure and support for the tactical mode, I'm going to be moving onto a strategy layer that can string tactical battles together. It should be mostly UI, so I've already started trying to get more familiar with some of the other UI elements. Up til now, I've mostly been making do with buttons and static text boxes.

Ideally, I'd like to be able to load into one map with a UI, make a few minor choices (like fleet configuration), load into my tactical map and have those choices be represented in the tactical map.

Games I'm Playing

  •  Fate/Grand Order - my one mobile game.
  •  Battletech - Yeah, the one from last year. Got a key through someone at work recently and finally am getting around to it.
  •  Steamworld Quest - A few guys were talking about it at work and it seemed up my alley. Not too far yet. Looking at picking up Steamworld Heist too, that one looks like it was interesting as well.
Previous Entry Back (Provisionally)
Next Entry May Update
1 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