The 2019 NOVA Open concluded yesterday - here are my thoughts about it.
I had an incredible time at the event. Being surrounded by thousands of people who felt the same way about playing and painting with expensive miniature toys was quite the treat.
Next year, I will enter the GT and take more seminars. Everyone who was in the GT looked like they were having an absolute blast, and the seminars were apparently packed.
The “Activation Wars” are a real thing, and it seems like all of the top-tier lists had some way of making units fight last, or having their units fight first. I walked past a lot of tables where people were groaning “Oh right, you get to go first for some reason.”
In my own Narrative games, I noticed that people really hated playing against Slaanesh. I was lucky enough to be on the same side of the table, so I didn’t have to deal with it, but I could see the frustration and helplessness that our opoonents felt. No matter how they approached a battle, they were essentially useless in combat until Slaanesh had done their thing.
I’m not a rules writer, so I won’t be proposing fixes for this. But I can definitely say that it sucks to play against armies that modify combat activation.
I saw like… one Seraphon army in the GT. I don’t think they are in the best place.
I saw a lot of Shootcast, a lot of Skaven, and of course, FEC, DoK, and Slaanesh. I saw some beautifully painted Kharadron Overlords, but I’m not sure how they fared in battle.
As far as my army list went, I went with a spell-heavy build centered around Kroak and the new Meteoric Convocation. It’s fun to drop global mortal wounds on the map :) Combined with a 6-model Ripperdactyl detachment with a Shadowstrike battalion, I was able to cripple my opponent early with a devastating alpha strike, and then follow it up by clustering around Kroak and sending Skinks to take objectives.
There were five or six floors absolutely packed with wargaming action. I walked around and just soaked up the ambient sportsmanship, good will, and good humor that permeated the air. There is something very special about being around people who have a strong passion - and this was a passionate group of people.
The orchestras playing pop music, the random “WAAAAAAGH”s coming from the vendor stalls, the food trucks, and the general feeling of closeness with other tabletop players - incredible. I think the Hyatt did a great job of hosting this event!
I walked around the tournament halls wearing my AoS Reminders shirt.
I was amazed at the response that the tool has generated. Every row of tables had at least a few people using the printout. When AoS players noticed my shirt, they would gush about how much it helps them, their significant other, their kids, or their local tournaments.
The competitive players talked a lot about using the tool to find hidden synergies in their lists - theorycrafting by adding/removing units and seeing where they could stack abilities in certain phases.
The casual players (like me!) were just happy that they weren’t forgetting their abilities anymore.
I asked just about everyone I talked to one question:
"What would you change about AoS Reminders?"
The responses I got were astounding. Some people had noticed typos. Others had various UI tweaks - great ideas that I’ll implement within the month.
I would estimate that 70% of the people I talked to mentioned one thing - they want to be able to save and load their army rosters. I’m happy to announce that… you’ll be able to learn more about that feature in about a week, when the next Rolling Bad podcast comes out. I did an interview talking about AoS Reminders and my future plans for the tool.
Speaking of which…
The past few weeks have been a whirlwind regarding AoS Reminders.
I made the decision to move the tool from this website (daviseford.com) to its new home - aosreminders.com. As much as I enjoyed getting ~40,000 visitors to my site in just a couple months, I realized that it’s better for the long-term success of the project to move it to an actual URL.
Our number of contributors grew even higher - 15 people have now contributed code to the tool!
We’ve added more armies, more rules, and a better mobile experience.
There’s more to come, too. I’ve got some pretty big plans in the works!
Three months ago, I posted on my website about a tool I had built for my Warhammer army. At the time, it only supported one army - Seraphon - and it only had a few basic features. I received an overwhelming amount of positive feedback from Lustria Online, TGA, and Reddit.
It seemed like everyone wanted me to add their army, ASAP. No problem, except… there are a lot of armies in Age of Sigmar. People also wanted to be able to add spells, endless spells, realmscapes, soup armies, command traits, triumphs, and more.
For those who aren’t familiar, Warhammer: Age of Sigmar is the successor to Warhammer Fantasy. Battles are fought over the course of five turns. Each turn consists of your round, and your opponent’s round. A single round has the following phases:
Each of those phases is further divided into three sections:
Let’s say we have a powerful artifact equipped by our general. A typical artifact may have rules that specifically activate at the “start of the combat phase” and “during the battleshock phase”.
A Wizard may have a spell that is cast during the Hero phase, but affects units during the Movement and Shooting phase.
One of the things about Warhammer is that you can’t “go back” during a phase. If you start using your rules that are triggered during combat, you can’t go “oh, wait, I need to use this start of combat rule first!” This makes remembering your rules of paramount importance.
As you might imagine, the amount of rules for a large army can be staggering - and a lot of Warhammer battles boil down to endlessly consulting your rulebook to make sure you’re not missing a rule. However, there’s not a single Warhammer player on the planet that hasn’t exclaimed “Awww shit, I forgot to activate a rule last phase!”
A lot of players build custom spreadsheets and handwritten notes reminding them when to use certain abilities. I decided to overengineer my solution a little bit by building AoS Reminders.
I started to realize that building this thing was a daunting task after I added my first few armies to the application. I was pretty pleased at this point - I had a decently architected codebase, and data entry was fairly painless. For the most part, adding an army just worked.
However, as I moved through the first four armies, I started to notice there were units, abilities, and rules that didn’t exactly match my early mental model of how an AoS army worked. This meant that I had to add more logic and options to the code.
At this point, I wasn’t using any sort of store management - the app is written in React - all of the application state was simply stored in my
App.tsx file and passed down to child elements when necessary. I started to have tons of handlers for updating state littered across the codebase. Which obviously begs the question…
It just didn’t feel necessary when I was first building out the page. Remember, this started out as a toy application that handled one use case - letting me dynamically build a list of reminders for my Seraphon army.
With the amount of information that I was tucking into my state, the whole app was re-rendering constantly whenever a single change was made. I started out by building my Redux store the old fashioned way - which I hate doing. And then - I found Redux Starter Kit - and my whole life changed.
Redux Starter Kit comes with a ton of features out of the box. It automatically manages different slices of your state, provides actionHandlers, selectors, and reducers, and uses Immer to produce immutable state updates. It was super easy to install and use, and it only took me one night to convert the application from local state management to a Redux store.
Whenever I posted my latest progress on Reddit or other forums, I got essentially two pieces of feedback:
I spent night after night adding Sylvaneth, Gloomspite Gitz, and Idoneth Deepkin, and I started to think… this is going to be nearly impossible to pull off alone. I started changing the tone of my forum posts, soliciting help and reminding people that they could add their army with only a basic level of dev experience.
My first contributor added a patch to the codebase 12 days after I released it on Reddit. I was thrilled - no one had ever contributed to any of my side projects before. I quickly wrote up a better README, created a sample army for contributors to base their armies on, and added a contribution guide. I created a Discord channel after someone asked me where they could chat with me.
Before long, I had quite a few contributors, an active Discord, and thriving Github activity. It seemed like every morning I woke up to a couple PR’s and tons of new issues. I was trying to keep ahead of the curve - I added pre-commit tooling to the codebase, tests, and helper utilities to check code quality. I was also making sure to properly type everything using Typescript - this helped ensure that contributors were entering data in the correct format.
After a while, I was able to almost entirely give away the task of data entry - people were submitting code for their favorite armies, spells, and abilities constantly. I began to get a little overwhelmed with requests for features - all of them good, but I was the only person really working on the React side of things.
As of today, I am really proud of the fact that we have fourteen contributors to the project, some of which have contributed thousands of lines of data and code. I am enormously grateful to each and every one of them.
We’ve currently closed 143 pull requests and 119 issues. We have 7 issues currently open. If you’re feeling adventurous, why not check out our Github? We’d love to have you.
This project started as a simple Create React App build (with Typescript, of course).
At this point, we’re using these libraries (and more) to accomplish our goals.
masterbranch to production automatically.
The entire project is written with React Hooks and functional components. There are no references to
this, no ugly classes, and certainly no
Using Hooks made this project fun to write and debug. I really fell in love with
useMemo when writing utilities to fetch army metadata - the average army has anywhere from 3,000 - 5,000 lines of rules associated with it. Quickly parsing those rules and delivering them to the user became a fun challenge for my coding skills.
Deployment of this project was initially handled by me running a basic bash script. The script ran
yarn build and then uploaded the results to an S3 bucket. As the number of contributors and PR’s grew, an automated solution became more and more necessary. Enter Codeship! They offer 100 free builds a month, a great UI, and easy integration with Github. I really enjoy using them.
When a PR is submitted, approved, and squashed and merged to
master, Codeship automatically kicks off a build - it checks for the latest dependencies, runs
yarn build, and if there are no errors, deploys the result to an S3 bucket. It’s fast, easy, and most of all, automated!
In the span of three months, the page has received 34,000 pageviews (the real number is higher - I’m sure a large portion of the gaming community blocks the Google Analytics script).
It has been a labor of love for me and my contributors, and I’ll list some of our features here:
At this point, the bulk of the work is done. We’ve added all of the current Age of Sigmar armies, and even a few that aren’t officially supported.
We have a few UI things we’d like to change around. We’re going to add drag and drop capabilities.
One of my most frequent requests is for a native iOS/Android application. I may tackle this down the line, once all of the current issues are resolved.
I could foresee this expanding to Warhammer 40k - however, as someone who’s never played a game of 40k, it is a daunting thought!
When I started writing this codebase, I thought it would just be a fun little indulgence, like most of the code I write. I never thought I would have over a dozen contributors, tens of thousands of users, and fans all over the world. It has really been great!
Three months after getting this beautiful model for my birthday, I’m calling it finished. Here’s my Dread Saurian.
I ran into an issue with my side project AoS Reminders recently where I was mutating an object that wasn’t supposed to be mutated.
I was having trouble tracking down the mutation, until I stumbled upon the
This can be useful for detecting when your objects are being accessed.
Another great example of using
Proxy is for object validation:
While useful, you should really be using Typescript and enforcing your object keys that way ;)
Hope this helps someone! Just thought I’d share a small, neat feature of JS I hadn’t used before.