Jump to content
  • Advertisement

Battletech Developer Journal - 01



I'm Chris Eck, and I'm tools developer at HBS for the Battletech project. I've recently been given permission to write up articles about some of the things I work on which I hope to post on a semi regular basis. Feel free to ask questions about these posts or give me suggestions for future topics. However, please note I am unable to answer any questions about new/unconfirmed features.

What's a tools developer?

I don't work directly on the game, instead I work on the tools that help make the game. My "customers" are the other game developers in the studio, and my goal is to make their lives easier, increase their productivity, or enable them to do new and exciting things. The main areas I'm responsible for are the Maps and Encounter logic and the tools that Designers use to build encounters, contracts, events, and flashpoints. 

I really enjoy the Tools Developer position as a job. It's literally a different problem to solve every day. I also like interacting directly with the people who use what I code, which is something most game developers don't get the chance to do.

For example, here are a few of the things I worked on last week:

Vertical Dropship Animation Style

In Urban Warfare environments, there are quite a few buildings scattered around (I hope that didn't spoil the surprise for anyone...) Our normal Leopard Dropship flyby animation comes in at a bit of an angle. In Urban maps, the wings would occasionally clip through a nearby building so I needed to give designers the ability to configure that behavior.

I added the configuration bit to the Lance so when units are spawning via dropship, designers can choose the animation style. One of our animators worked up some new animations, and our tech artist wired them up into an AnimatorOverrideController.


The AnimatorOverrideController is a Unity component that does just what it says. The original AnimatorController contains all the logic  for transitioning between various animation states based on animation variables set by the code. The  OverrideController basically maps any calls to the original animation over to the new vertical set.


Notice how we didn't override leopard_moveCoreGroundIdle? That's because nothing special needs to happen here. When the dropship has landed on the ground, it's just sitting there so there's no need to change the animation. Sittin' still is just sittin' still. :) When a particular override is unset, the original animation is used.


Design Mask System for Urban Environments

Urban maps are quite a bit different than the normal maps we've shipped in the past. For one, the ground isn't a Unity Terrain object. Instead, it's a bunch of GroundPlate "Obstructions" (an Obstruction is anything that can block movement, line of sight, or have units stand on - so big rocks, buildings, foundations, etc.). For normal terrain maps, Designers would paint down DesignMasks directly on the terrain. So they might paint a swath of trees down next to a little patch of rough terrain, and paint a road through them both. However, no No visible terrain meant designers couldn't paint down any design masks. 


We came up with the idea to create these MaterialSlots on the GroundPlates. Pictured here is a blank GroundPlate with four MaterialSlots. When the designer selects the Trees designer mask, it paints that section of the GroundPlate with a nice looking grass texture. As part of the map export process, a DesignMask camera takes a snapshot of all the different Materials (one for each DesignMask (Trees, Water, Roads, etc) and saves png's out for the game to read in later.

In the combat game, we use those PNG's to determine which design masks units are standing in, and will impart different game effects based on that. This was already working since we did a similar export process for Terrain based maps. 

One more thing I had to do though was add a special design mask for ground plates. Normally when a building is sitting inside a forest and a mech jumps on top of it, you wouldn't want the design mask of what's painted on the ground. The mech isn't "in trees" it's on a building. But in the case of GroundPlates - I DO want to use the underlying design mask of the "terrain". So in the GroundPlate BuildingDef I set it to UseTerrain. So whenever a unit is standing on a ground plate, it checks the terrain to get the correct design mask.


Combat Dialogue Sequences

One problem we were having was when multiple dialogues could fire get fired off at the same time, the order was non-deterministic. It just depended on who registered to listen for that message first. Sometimes it was okay, but sometimes was a bit jarring depending on how the dialogue was written. So we made Combat Dialogue Sequences

Instead of individual dialogues firing off onesy-twosy style in whatever order they happen to be registered, the DialogueSequence says we'll fire DialogueA then DialogueB then DialogueC. It also has some smarts in it to skip over dialogue that has been turned off by the contract. Say DialogueB is in a ControlledByContractChunk that's turned off. The sequence will play DialogueA and then DialogueC.


This ensured a specific order that Designers and Contract writers could count on and also cleaned up some weird CameraFocus issues that were occurring.

I decided to also support playing DialogueSequences just in case. So we could have something like DialogueA - DialogueSequenceB (Dialogue B1, B2) - DialogueC. I didn't make the editor component as pretty as I could, but there's . There's a slot for a Dialogue and a slot for a Sequence for each DialogueItem. You're only supposed to set 1 and there's a validation error if you try to set both. Maybe one day I'll go back and pretty it up, but probably not.


Dynamic Structure Points for Buildings

One of the designers was worried about buildings having a static amount of structure points. Give the building too many and it takes forever to beat it down with lighter mechs in the early game. Give them too few and heavier mechs can take down a building too easily when you're trying to defend it in the later game. So we came up with the idea to adjust the amount of structure points based on the difficulty of the contract.

In CombatGameConstants, I defined a structure to hold a row of building hit points per difficulty. The designer then tags specific buildings in the level with scaled_small, scaled_medium, or scaled_large. And when the combat game loads up, the starting structure points of these buildings are overriden appropriately.



That's all for now

So there was a glimpse of a few issues that I tackled last week. If you found this interesting or have any questions, let me know in the comments below. Or via the twitter post below.

Until next time,
- Eck




Recommended Comments

Thank you for posting this Eck - and I look forward to seeing more of these (as your time allows)!  Would love to see a future one that talks about some of the tools you made and are in the bundle (like the Flashpoint maker).

I'm sure it is safe to say that the Modding Community appreciates the work you do, and how you (and many other HBS staff)work to make our lives easier :D

Thanks again!

Share this comment

Link to comment
On 4/7/2019 at 8:01 PM, JustinKase said:

Thank you for posting this Eck - and I look forward to seeing more of these (as your time allows)!  Would love to see a future one that talks about some of the tools you made and are in the bundle (like the Flashpoint maker).

The Flashpoint editor is a beast and would probably need a couple of articles all on it's on. Plus I'd need to learn how to use it! I wrote the tool, but it's just a WinForms app that can load/edit/save the data structures that are there. I don't fully understand what the SimGame calls or how the data is used. However, there's an excellent writeup that Amechwarrior did here: https://forum.paradoxplaza.com/forum/index.php?threads/flashpoint-authors-guide.1153590/

I'll try to do a write-up on the Contract Parser in the next couple of journals and maybe the Event Parser sometime after that. 

On 4/7/2019 at 8:01 PM, JustinKase said:

I'm sure it is safe to say that the Modding Community appreciates the work you do, and how you (and many other HBS staff)work to make our lives easier :D

Thanks again!

Aw thanks man. I'm thrilled to be able to help the modding community. I'll pass your thanks along to the rest of the team.

- Eck

Share this comment

Link to comment
8 minutes ago, Kareem "Daigoji Gai" Harper said:

This was great and, without spoiling, awesome reassurance we're marching towards a summer of urban warfare



Can barely wait as well !


Share this comment

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement
  • Advertisement
  • Blog Entries

  • Similar Content

    • By rogerdv
      Im doing some tests with new Unity3d networking APi and Im moving from sending integers to sending more complex stuff, like coordinates (3 floats). The problem is that Im forced to use fixed byte as the data container for my packets (byte[] doesnt works, must be unmanaged and blittable) and I havent found a way to put my values (floats, strings, etc) into that array of bytes and also get them back. How can I do this?
    • By Onions.ILikeOnions
      My top down character movement script aint working, only the screen moves.
      Mere is the tutorial https://www.youtube.com/watch?v=whzomFgjT50&t=41s
      And here is my Script
      using System.Collections; using System.Collections.Generic; using UnityEngine;   public class waw : MonoBehaviour {        public float moveSpeed = 5f;      public Rigidbody2D rb;   Vector2 movement;     // Update is called once per frame     void Update()     {       movement.x = Input.GetAxisRaw("Horizontal");       movement.y = Input.GetAxisRaw("Vertical");     }   void FixedUpdate (){ //movment rb.MovePosition(rb.position + movement * moveSpeed * Time.fixedDeltaTime); }   }
    • By RoKabium Games
      Lelantos enemies – ”Riverine” is a venomous and poisonous creature that is slow but still very dangerous.
    • By ethancodes
      I'm fairly new to creating full 2d levels, so please feel free to correct me if I use incorrect terminology or if I'm doing something wrong here. Currently, I am using the Tile Palette with several sprites placed on it to create my levels. With that I can just run my mouse across the screen and quickly place tiles. Then on the TIlemap gameobject I place a Tilemap Collider and a Composite Collider. This works great, it's quick, simple, and efficient. However, for the next part of my character controller I'm looking at adding the ability to do a ledge grab. After doing some research, it seems like a common way to do that is to make the ledge he can grab "grabable" by putting a different collider on them. So my question is, is there an efficient way to where I can let the Tile Palette know if I use a specific corner sprite, place the ledge grab collider on it? Is there any way other than going through all the ledges in the game and manually placing them there? I'm also open to any tips on level building and using the Tilemap, etc that may help me out as, like I said, I'm pretty new to it all. Thanks!
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!