Construct Quarter – Postmortem


Construct Quarter Project Page

Overview

This post reflects on a few aspects of the Construct Quarter project with the benefit of hindsight towards the goal of learning and improving my next project. Specifically, this will focus on my Patchwerk Prototype, Hero Data Framework, and overall goals for the Construct Quarter and the extent to which they were achieved.

Patchwerk Prototype

Before starting this project, I made a prototype project with five heroes and one boss. All the functionality worked as intended but I never got it to a nice balanced state because it wasn’t set up well to easily change and iterate on balance numbers. Although I attempted to make this easier by centralizing all the inputs into variables, using the variable GUI was still very tedious and time consuming.

Relying too much on the Warcraft 3 World Editor GUI was a mistake for this prototype. It significantly hampered my progress and led to me spending too much time on tedious repeated interaction. Luckily, I had already learned this lesson before starting the Construct Quarter. I mention in my first project post that it was my regret in wasting time with the GUI that made me go looking for a better solution and find Drake53’s C# toolchain, which enabled me to be vastly more productive. Furthermore, working in C# gave me valuable practice and learning that will directly apply to both future hobby game development projects and my professional career.

Another mistake was spending so much time on custom assets and special effects for the prototype. There was probably learning value in adding one or two custom assets but each of the five heroes had multiple custom assets for their abilities. I noted in my EcoSim Postmortem that every hobby game development decision doesn’t need to be viewed through the lens of maximizing productivity and learning. There was probably a certain amount of my wanting to polish the prototype characters because I thought it was cool and I liked having more polished characters. However, it probably would have been better to save the time and then just have cool polished characters in the main project more quickly.

One aspect of the prototype that went great was the hero balancer. I knew this would be the primary component of the prototype that I would be taking with me to the main project so I took some time to get it to a state I was happy with. Healing and mana costs were the most difficult to calculate, but they ended up working well. The mana cost calculation isn’t perfect in that some assumptions that are made for simplicity towards the end of the calculation ended up affecting the results more than I intended. I didn’t notice this until I was finishing up the project and I strongly considered fixing it. However, I decided not to because I was happy with how the mana costs were playing out during boss testing despite their calculation being a bit ‘incorrect’.

All things considered, I’m pretty happy with the prototype. Although I took a bad initial path that restricted my productivity, I learned from this mistake and did not repeat it in the main project. It took much longer than it needed to take, but the majority of time was spent developing the hero balancing system that I was able to bring over to the main project without significant change.

Hero Data Framework

The overall goal of the Hero Data Framework was to make the addition of new spells and tweaking of spell balance values as quick and easy as possible. On the addition of new spells, its success was mixed. However, it worked very well with the hero balancer and was successful in delivering quick and easy balance tweaking.

The issues with adding new spells mostly came from incorrect assumptions about Warcraft3’s functionality. The ideal scenario would have been that every single spell could be based on channel, a dummy spell, and handled entirely in code. These code-based spells would then rely mostly on common code shared by similar spells. However, I didn’t know that channel couldn’t apply buffs and couldn’t fire projectiles. I incorrectly assumed Warcraft3 would actually use these values if they were set because they were exposed in the object editor. In general, Warcraft3’s functionality limits custom spells to be similar to their base spell much more than I expected. To fire a projectile, a custom spell must be based on an existing spell that fires a projectile. The same is true for applying buffs and status effects. In addition, some spells have properties that cannot be changed. For a while, the frost mage had Ice Lance, based on Death Coil. However, abilities based on Death Coil have an irremovable green special effect on the target. Trying to replace this effect with a different one doesn’t work. I eventually changed the spell to Ice Beam instead. These are the sorts of frustrations that plagued spell implementation. I should have tested these scenarios earlier, it was incorrect to assume they would work as I expected.

Beyond missing functionality that I needed, I also spent too much time building robust support for functionality that was ultimately barely used. Here’s a quick overview of the terms for the chart below:

  • AbilityAction – some general action in code, like damage or healing
  • Override – overrides the value of some existing ability property
  • Condition – checks some value before executing an associated Action
  • SideEffect – sets some value if the owning Action is executed
  • Delay – do Action after a time or repeatedly over time
  • DynamicArt – create some visual or audio effect
  • UnitStorage – relies on storing units relevant to the spell when it’s cast

First, it looks like Dynamic Art was unnecessary. Wind Strike and Whirlwind’s dynamic art could have been replaced by static art set in the world editor. That leaves me with only a single case, Kill Command. Kill Command only deals damage if Rexxar’s pet Misha is alive, so I needed the special effect to only play if Misha was alive. However, it probably would have been better to enable or disable the ability as Misha was summoned or killed. If Kill Command could only be cast when Misha was alive, then that dynamic art could also be replaced with static art set in the world editor. With Kill Command also covered, I’m left with zero spells that really needed dynamic art support.

Next, general delay support was probably also unnecessary. One major use of delay is spawn effects. I wanted to be able to dynamically set the properties of spawned units, but the units don’t exist yet at the exact moment the spawning spell is cast. Therefore, there needs to be a short delay for the unit to spawn before the system sets its properties. This is needed for every spawn and could have just been built into the spawn action. That removes Summon Misha, Summon Gargoyle, and Serpent Ward. Whirlwind’s delay implements a damage over time effect, and it probably would have just been better to base Whirlwind on Acid Bomb, which already has a damage over time effect. Forked Lightning’s delay implements a period of time where another spell is empowered, which also could have been better implemented by applying a buff. That leaves only two spells left relying on delay: Guardian Spirit and Mirror Image. I think it would have been faster to handle these two remaining cases specifically. This is especially true because I ended up spending a day or two looking into bugs in stress delay scenarios. My actual usage never came close to the complexity of the scenarios that I spent time fixing.

Conditions and Side Effects also went a bit underused. I could go through a similar review process for those abilities but I don’t think it would be that valuable. While I probably could have gotten by with a leaner version of the condition and side-effect system, it wouldn’t have saved me much time. This system was quick to implement and didn’t lead to any trouble during development.

One aspect of the framework that went very well was how easily it connected with the hero balancer. Once the full balance pipeline was up and running, it allowed for quick and easy balance value tweaking. If I felt an ability needed a change, trying that was as simple as changing that ability’s balance input values, running the balancer, and restarting the map.

Project Goals

The most straightforward measure of project success is the extent to which the project met its goals. My goals for this project were to choose an achievable scope, release close to the Warcraft3 Reforged release date, overcome a design challenge, and get a handful downloads.

First, on choosing an achievable scope, I think I did a good job. I was shooting for 8-16 weeks of work for the main project and it ended up taking me about 9 weeks. I didn’t really have a scope in mind for the prototype but I definitely spent more time on it than I needed to. It ended up being more of a mini-project than a prototype.

Next, on getting the project out by the game’s release, I failed. Warcraft3 Reforged released January 28th and I had the map complete on March 9th. Therefore, it was about 6 weeks late. There were a few issues here. First, as mentioned above, I took too long on the prototype. I actually started all the way back in July 2019. During July and August, I took a handful of attempts at trying to get my balance calculations right. I dont fault myself for this, it wasn’t really prototype work and had to get done regardless. In September and October, I had some other stuff come up that forced me to put the project on hold. I resumed and finished the project in November. My systems were pretty well tested in the first week of November, the final 3 weeks were unnecessary GUI nonsense and prototype polish. I took off the first two weeks of December, then spent the last two weeks setting up and learning the C# framework. Some delays weren’t under my control, but I could have saved 5 of the 6 weeks I was late by finishing the prototype and starting the main project more quickly.

The primary design challenge I set out to overcome with this project was the balancing of hero and boss ability values. One of the biggest struggles in my first project, EcoSim, was determining game values. I significantly underestimated how difficult it would be to calculate ranges of values that would facilitate equilibrium in the system. I ultimately gave up on trying to design a simulation game and instead made it sandbox where you can play around with the values yourself. I specifically chose to do the Construct Quarter because it represented a design challenge in an area I’m more interested in. As I’ve previously mentioned in this post, the hero balancer I implemented to solve this problem worked out very well.

The last goal I had for this project was for it to be public facing and get a handful of downloads. EcoSim was basically a private project, I didn’t really put it up anywhere for download. I wanted to make an effort get my next project on some amount of other people’s computers. My download goals were modest, I was optimistically hoping for maybe 20 downloads. I far exceeded this, getting a few hundred downloads. I might have been able to get even more interest if I finished closer to Reforged’s release date, but overall I’m very happy with the amount of interest this project got.

Overall takeaways

Finally, I want to consider what general learning I can take away from this project to improve the development of future projects.

First, I need to work on my prototyping skills. The Patchwerk Protoype was a mini-project rather than a prototype. In general, prototypes should be small and quick. The purpose of a prototype is to get a small version of your game out quickly. With this small version, you can see whether or not the idea is as good and feasible as you hope before you waste time working on further development. If you spend a bunch of time working on the prototype, you’ve defeated the purpose.

Next, I need to more carefully consider developing (allegedly) time-saving systems. Some aspects of the hero data framework cost more time to make than they ended up saving. There are two potential solutions here. First, I could develop in a more agile way: resisting making large systems at the beginning, instead building up functionality over time as it’s needed. Alternatively, if I’m confident a large re-usable system is worth developing early on, that plan should take a moment to consider all the building blocks that will be needed. That’s not saying I should implement every building block I could ever potentially want, it’s saying that I should think about all the specific things I want to do and the specific building blocks that will be needed when planning a large system.

Last, there’s tremendous value in putting effort into discovering and utilizing available resources. I almost used JASS for this project because I initially didn’t look very hard at what middleware or frameworks might be available. However, I looked a little bit harder and found Drake53’s C# framework. A similar situation played out when I was looking to release the map. At first, I just put it up for download in a Warcraft3 lobby for a few nights. I saw maybe 2 or 3 people jump in and download it. However, I tried a bit harder and found a number of third party websites for hosting Warcraft 3 custom maps, which led to many more people downloading the map.