Update #16 - Tools of the Trade
Much like a hero is only as good as his weapon (rule #15), a developer is only as good as his tools. So when we switched to Unreal, our main concern was whether or not we'd be able to find our way around the 'blueprints' (Unreal's visual scripting system). We started with Unreal 4.14 and several plug-ins to get the ball rolling and get a quick feel of the engine:
- LE Extended Standard Library (blueprints that add general functionality and improvements)
- Rama's Victory Plugin (C++ Blueprint Function Library)
- Dialogue Plugin (a node-based editor)
#1 - The Dialogue Editor
We managed to combine Unreal's blueprint graph (visual scripting) with DialoguePlugin's tree structure into a new asset and made a proper editor:
This means that both the dialogue structure (text, parts, answers, links) and dialogue scripts (spawn characters, switch mission, add items, unlock door, etc) are all contained within a single asset and not scattered around the build. Whereas in AoD we could only add something from a pre-defined list of scripts to get a list of commands like "do this, then this, then this, ...", now we can code a complex action with checks, loops and whatever UE blueprints allow and they allow pretty much everything.
We can also call functions from the blueprint libraries, if we need to store and reuse some generic scripts (examples from AoD: scheduleEnding, setMapLighting, etc). We've also managed to plug into Unreal context menus and asset categories, so dialogues (and everything else) are created in a convenient manner:
It's very easy to use it and there are only two simple rules:
- In order to qualify as a dialogue check and appear in a dropdown list in dialogue nodes' properties, the function must receive 0 parameters and return 1 bool value. That value is basically a result of your check and tells the dialogue system if this NPC text / PC answer should appear;
- In order to qualify as a dialogue event (action, script, call it whatever you like), your function should have 0 input parameters and 0 output. It's just does inside what you want and doesn't take or return anything.
#2 - The Item Editor
In AoD we used ItemGen and CharGen editors which stored lists of items and characters in their own custom binary databases. We liked them and gotten used to them but Unreal offers its own way of storing, editing and searching data, in many ways greatly superior, so we decided to discard our square-wheeled bicycle and do it the way cool kids do. Here is our new item editing interface:
It does everything our old ItemGen did and then some:
1) One item class now will not contain data fields from other classes, i.e. melee weapon will not have a field "Magazine Capacity", armor will not have "Range" and "Attacks Supported". Now each item class contains only the related data due to the inheritance hierarchy. For example: InvItemInfo (properties for all items, like name, weight, etc) -> InvEquipableItemInfo (adds properties that define 3D visuals) -> InvWeaponInfo (adds properties common for all weapons, like damage type, range, AP cost, attacks) -> InvRangedWeaponInfo (magazine capacity, ammo type, etc);
2) Unreal typed fields: you can enter/select only related data, which is displayed in the most convenient way. Take a look at "Static Mesh" property for a weapon on the image above. It's not a generic text field anymore, where you had to type some string and hope that the mesh/animation named like that is somewhere in our files and the game, with gods' blessing, will hook it up. Now you get a proper menu with a full list of suitable resources to select from, thumbnails, search field, view options and full information about the selected asset:
3) There can be not only properties, but functionality attached to each specific item in a form of custom blueprint graph. Do you want this item to shoot sparks when reloaded or shine when it's thrown? Do you want this grenade to go boom when it hits or spawn a distortion effect instead? Want to inflict some specific status effect when this club hits, but just this club, not others? Well, no more shit code and special cases checking for "if this is acid do this, else if it's net do this, else if it's napalm ...". All specific functionality is completely self-contained in this item - just place, drag around and connect some blueprint nodes to make magic happen. We also can (and surely will) inherit some functionality from parent classes - like, every item derived from ranged weapon will be able to spawn a muzzle flash, every item of every class will spawn a map object when it's dropped because core class (InvItemInfo) will know how to do it, etc.
We've already set up a core hierarchy of items, but we can improve and expand it at any time, from adding new properties to creating new item classes. Check out Gameplay\Items\BaseTypes\ . In order to create a new melee weapon, right-click InvMeleeWeaponInfo and select "Create Child Blueprint Class". That's it! Give it a name, edit its properties and move to an appropriate folder (Gameplay\Items\Weapon\, for example, but we'll sort out specific folder structure later). You can easily find any item out of hundreds we'll have by typing a couple of characters from its name in the Content Browser's search bar. Also, your new item will now appear in all selection menus, where you need to select an item - like character's weapon slot in Character Editor. Speaking of which...
#3 - The Character Editor
It's similar to the item editor - an easy LEGO constructor for all your character editing needs, including a viewport with a paperdoll that will instantly reflect all the equipment you select, appearance customization (later) and derived stats updating in real time as you change stuff:
1) Check Gameplay\Characters\Database\BaseTypes\ - that's where we will store the "creature" types. Each creature will have unique equipment slots, blueprint code that runs animations, a set of meshes and rules that show/hide them and other blueprinted functionality a creature has - what damage it accepts, what status effects it reacts to and so on. For example, a plant in the wasteland is a creature that doesn't has any clothing slots, one body mesh and one (possibly invisible) weapon item. A robot is a creature that has armor, weapon slots and inventory, but not hats or gas masks, etc. So each creature type has its own properties, no more spaghetti code like "if the creature is human and impaled, show the spear, but not if it's a demon, in which case show 200 body pieces if it's dead and broken, but if it's a construct, show only the mesh named "body"; but if it's you're plant, show trunk_01 and 02, ...".
2) To create a new human character, right-click HumanCharacterInfo, select "Create Child Blueprint Class", name it and move one folder up, from BaseTypes. Now you can select your newly created character in CharMarker's dropdown. If you ever rename a character, Unreal will automatically go through all its references in all CharMarkers and update the name everywhere, so there is no chance to mess up dbID.
So in short, the core system is already there - we can start adding dialogues, items and characters right now, which puts us right on schedule (so far).