Official development blog

Year 6 of the Cogmind

As we enter the seventh year of Cogmind development, time for another retrospective! Alongside several major releases and events, there’s also been a bit of a shift in development style as we edge our way into (very) late beta… Maybe to be followed by (very very) late beta and (very very very) late beta, but we’ll get to talking about that below :P

Here’s our annual image collage to start us off:

cogmind_development_year_6_small

Selection of images from the past year of Cogmind-related development as posted on this blog, forums, and Twitter (full mega size here).

Development Time

Got pretty close to hitting that 12,000-hour mark this year, but not quite (currently at 11,821 total hours)…

cogmind_monthly_development_hours_201307-201911

Cogmind Monthly Development Hours, 2013.7-2019.11 (click for crisper full-size version). (The color coding is for different aspects of development tackled each month, the subject of a future in-depth article to come at a later time.)

June and August were lower since I was gone for nearly four weeks of vacation during that period, but otherwise it was a pretty typical year overall. In the past 12 months I added another 1,676 hours, a slight 3.5% less than in 2018. However, work on the game itself totaled 852 hours, the first time that figure has outpaced hours spent on community-related work (purple) since prior to launching on Steam. You can see what I mean in the following graph.

cogmind_dev_hours_game_vs_community_2013-2019

Comparing the amount of hours directly spent working on Cogmind vs. community-related work (excludes hours that belong to neither category).

This year I mostly faded out the SITREPs which had been a staple of the announcements board since the Steam release, just occasionally writing one instead of consistently producing several per month. They were a lot of fun, but also a ton of work to put together, seemingly more than they were worth in terms of gains in other areas. Either way, I was kinda burnt out on them and wanted to shift more time back into development itself, and as you can see from the graph that trend has been successfully reversed. In 2017 and 2018, more time was spent on what I call “community efforts” than on coding and adding content to the game, but this year those efforts took a back seat as I was able to focus a greater portion of my time on the latter.

Despite the relative lack of SITREPs, I’ve definitely still been writing! There have been more blog posts this year than last (with even two more already complete ones I have yet to publish xD), funded in part by support on Patreon, which I’ll get to later.

Content that might have been given a cursory treatment in a SITREP is instead given a thorough design analysis on the blog, so we have things like the Ultimate Roguelike Morgue File series, a level design deep dive, several system-focused articles, and many others (the sidebar on the blog makes these easy to find chronologically).

I’ve also continued streaming, including earlier this year putting out a Cogmind: Pwning the Early Game video which has helped a lot of people improve their skills, so maybe check that out if you’re just starting out and having trouble reliably reaching the mid-game.

Aside from participating in all of this year’s timed special events, I also completed about five separate regular runs each using different tech or styles of play.

cogmind_stream_warlord_cheering

We’ve been having some good times :D

Back in March I took time out from development to help review 7DRLs, where I streamed most of the playing part of that process.

Releases

Naturally the highlight of making a game is to, you know, actually release playable stuff, so yeah we had plenty of that, too :)

cogmind_2019_releases_logo_collage

Cogmind release logos from year 6.

By necessity the frequency of major releases was lower this year, but the two big ones were really big:

  • Beta 8 “Forbidden Science” added the Exiles mini-faction, fleshing out the early game with some more lore and fun tech.
  • Beta 9 “Wizardy” was practically two major releases in one, with extensive RIF abilities to complement bothacking, a greatly expanded scoresheet system to power the upcoming new leaderboards and data analysis, and more.

Last year was the first time I’d ever held a timed event for Cogmind, just on a whim, but it was pretty neat so this year I’ve been doing more of that with bigger and crazier ideas. We’ve had another three of these since!

  • Limited Edition Holiday Mode: Last winter/New Year we celebrated with the only time so far that a decent chunk of Cogmind content has been released for a limited time, mainly due to the need to put together the special content for that build very quickly. So this one can’t be played anymore, but it was fun while it lasted, two weeks of different content each day. (Notice that Cogmind’s dev years are calculated starting from December, which is why this one’s included here.)
  • Pay2Buy: This real April Fools joke added ways to earn CogCoins and a persistent Cogshop to spend them in to buy items and loot boxes, with demand-based pricing and other new and modified mechanics.
  • Abominations!: Cogmind’s very own Halloween special, adding a scary new faction of 20 robots with a wide variety of new capabilities as well as a new hidden map complete with boss.

I wrote articles about designing these modes on the blog, and have no doubt there are more special events to come… no doubt at--oh my, look what month it is! ;)

In terms of regular features it’s been quite a full year, giving us the brand new but already much-loved “siege mode” mechanics for treads, an improved manual hacking autocompletion system (voted for by patrons), rebranded difficulty modes, colorblind accessibility options, Stream rich presence, and a ridiculous amount of QoL features. Basically way too much to list here, but that’s what changelogs are for, and you can of course check out all the relevant release notes for info and demos if you missed something.

cogmind_autocompletion_list_hacks

The new menu-based manual machine hack autocompletion system! It’s even more useful when searching for schematics.

Community Support

How are we still going strong after all these years? You! I very much appreciate the support Cogmind and my work have continued to receive, both financial and otherwise.

Part way through the year I decided it was time to start a Patreon (announcement) to help see us through the end of Cogmind beta and also gradually build it up so that by the time Cogmind is finished we have a decent supplementary source of revenue to continue enabling a broader range of work rather than focusing so much on commercial concerns.

Sure there are the transactional perks like guiding some aspects of development through voting and trying out new features in advance, but I prefer to emphasize that it’s more about taking some of the risk out of an inherently risky business to keep it both creative and sustainable.

Anyway, in last year’s annual review I mentioned I was getting worried about revenue, but that has successfully stabilized for now, in part thanks to Patreon which has made up for inevitable lower sales over time. “If only” I was one of those devs who more quickly releases smaller/medium-sized games (even sticking to projects that take a year or two would mean I’d have several out there already!), but I’ve always been more of a big project kinda guy :P. Besides, there’s something to be said for megaprojects as long as there’s a strong community behind it and the design fundamentals are solid!

Outside Patreon, special thanks to PlasticHeart, Reed, Matthew, Karl and others for your donations this year <3

Overwhelmingly Positive

Just a few weeks ago after more than two years of collecting reviews on Steam, Cogmind finally got enough of them at the right ratio to achieve the relatively rare Overwhelmingly Positive rating!

cogmind_steam_reviews_500_191114_overwhelmingly_positive

November 14, 2019, was a nice day :)

As promised, this means I’ll be adding a significant expansion around a new “Merchants Guild” faction. And now that we’ve hit that goal, I’ve already set the next one: if we can maintain this rating up to 800 reviews, I’ll also add a new derelict community.

The concepts for both expansions are fairly fleshed out at this point, but building either/both will take quite some time. I’ve also even added a third but smaller expansion as a Patreon goal… As I see it there’s still room yet to liven up the world even more!

IndieDB

It’s that time of year again when IndieDB does its Game of the Year voting, and although Cogmind is too niche to pull the numbers necessary to compete against mainstream titles for the Top 10 in the second round, for the past five years in a row we’ve made it through the first round of voting to take a spot in the Top 100 list.

So if you have a chance give us a vote there, along with all your other favorite roguelikes/indie games that have a page on the site. (Registration isn’t required, but if you do have an IndieDB account you can maybe win a key for one of many different games if interested.)

2020

With the year coming to an end, what’s in store for 2020…

Well, I originally said I’d like to reach that stage in 2019, and apparently it didn’t happen! We are really close, and it’s been within reach for literally all of the past year, but I’ve been working on fine-tuning or expanding other parts of the game anyway and in hindsight I think that’s been a good use of time given the results. This is especially true with regard to improving the early game and new-player experience by rebranding the difficulty modes and adding the Exiles/FarCom, plus many other related features--going 1.0 brings in new players, and naturally we’d hope that experience would be a good one.

cogmind_dev_roadmap_191112

The current state of the development roadmap from the FAQ (snapshot from 191112).

As per the roadmap, the only remaining feature absolutely necessary before 1.0 is to finish the audio, which should be a focus for the upcoming Beta 10 depending on how much else I have to get done before then. In other words, it’s getting harder for me to postpone 1.0 :P

That said, 2019 ain’t over yet, we’ve still got a few weeks here to do something with…

Posted in Annual Review | Tagged , , , | 2 Responses

Movement QoL

Movement is pretty convenient in Cogmind, an important goal to aim for since this is generally the most common action players will perform in a roguelike.

Four different methods are supported out of the box, the mouse along with three different keyboard-based methods (numpad, arrow keys, and hjkl).

cogmind_player_movement_input_preferences_beta8

Movement input preference distribution (*only includes those opting in to reporting).

About the same number of players use the mouse and numpad, with the remaining minority divided between arrows and hjkl.

Moving via mouse cursor is certainly easy to use--simply click somewhere to go there automatically, although the keyboard offers finer control so it’s no surprise that in a tactical roguelike like Cogmind technically a majority of players end up relying on the keyboard for more or even all of their movement.

About one-fifth (21.3%) of players (including myself) even exclusively use the keyboard for everything, so for a while I’ve been mulling potential improvements and additional features for keyboard-based movement. According to the stats, newer players are more likely to start with mouse movement (unless already familiar with traditional roguelikes), but either way the chance of someone becoming a keyboard player goes up over time as they play more and learn how to do some actions faster that way, might as well continue improving the experience!

Keyboard Running

Although players new to the genre tend to assume “running” means a mechanics-relevant action where your character is actually “moving faster,” in terms of roguelike input schemes it actually refers to moving multiple spaces in a (usually straight) line via a single command.

Cogmind has had running ever since the original 7DRL release, because it really saves a lot of time (also more specifically back then mouse-based movement wasn’t a thing, so there needed to be some convenient way to quickly cover long distances!). At that point it was the dumbest implementation possible, though: “automatically move in one direction until something blocks the path.” (okay it could’ve been dumber--it also immediately stops on spotting an enemy, but I’m only talking about layout detection for now)

Smarter approaches need to take more of the layout into account, stopping not only at obstacles, but also where the player might want to reconsider their direction, or perhaps take another action.

That’s what I did for the alpha release, adding a new rule that the player should automatically stop running on reaching a location where the current cells immediately to the left and right are either doors or open space, and one or both of those adjacent to the previous position were not also open. This properly stops when arriving at doors/doorways, or arriving at a side-corridor while following a wall. It doesn’t stop, however, when running straight into a narrow corridor, so that’s a good thing.

cogmind_keyboard_running_diagram_old

Sample stop points from the original running system, demonstrating the direction from which the run is coming from, and the two points which are compared to trigger the stop.

At the time I left a note in my code that this could be better, but would get complicated fast and I wasn’t sure what use cases we might need to address before it was ideal, so that’s as far as I went.

Honestly if your running system gets too complicated it’ll be both annoying and unpredictable. Predictability is important, since mistakes can get you killed and no one’s going to be happy using a UI feature prone to “error” (where UI errors are defined by players as anything they did not expect/want to happen). Basically the system should stop as little as possible while still being as useful as possible.

There was definitely still room for important improvements, so that’s one of the areas I was working on recently.

For one, the original system was only applied when traveling in cardinal directions. While this is sufficient for most use cases since corridors only travel in cardinal directions anyway, sometimes diagonal running through an open area might hit a layout where it should stop. Rulewise it’s not really much different from cardinal movement, just looking at different cells.

cogmind_keyboard_running_diagram_diagonal

Sample stop points from the new diagonal running system, demonstrating the direction from which the run is coming from, and the two points which are compared to trigger the stop (or in the special case of the door, that one is simply checked for explicitly).

Another improvement to address is the fact that the first diagram up there for cardinal running ends up being suboptimal! Although on reaching a corner you may want to move out beyond it in order to look around, there’s also the chance you intend to simply round the corner without looking first, in which case you can move one less space by taking the diagonal, an option which is lost if the running behavior always moves out beyond the end of the corner as it was before. Same goes for arriving at doors--open them by standing out in front, or by stepping into the doorway? The choice should be yours.

cogmind_keyboard_running_diagram

Sample stop points from the new running system, which is like before only it stops one space sooner because it’s looking for the same triggers out ahead.

Here’s a sample of moving around using the latest iteration of the run command:

cogmind_autorunning_behavior_update

Automatic stops managed by the run command.

Other possible steps include automatically turning corners if moving down a narrow corridor that changes directions, although I think this is more suitable for other roguelikes (some have this feature), and not as common or useful in Cogmind. Of course QoL features always need to take a game’s unique characteristics into consideration rather than blindly implementing them.

A more reasonable possibility is to mimic mouse-driven pathfinding’s ability to optionally circumvent temporary obstacles like other robots. This is something that could theoretically be added for keyboard running as long as given the circumstances it won’t change the distance of the path, although I’m not sure I want to go there because it could in some cases have negative consequences and maintaining predictability is important here. Not to mention keyboards are all about that fine control, so running to an obstacle then quickly choosing how you want to deal with it--maybe wait, or choose a direction to go around, is probably preferable.

Keyboard Pathfinding

One of the main features I wanted to tackle with this round of movement updates was keyboard-based pathfinding. Although a lot of keyboard users don’t mind cellwise movement combined with a bit of running here and there, I always thought it would be nice if possible to choose a destination in keyboard mode and use a single command to move there via the quickest route, just like the mouse can by simply clicking on a location, regardless of how far away it is. So I’ve finally added it!

Using the mouse still has the advantage here and there were certainly some UX problems to work through, for example how to continue traveling to the destination after being interrupted--it would’ve been annoying to have to use examine mode to find the destination again!

To use this new feature, players have to be in examine mode (where you move the keyboard cursor around to inspect things) and simply press Shift-Alt-g (for “go”) on the destination. The result is just like a left-click on that location.

cogmind_keyboard_pathfinding

Keyboard pathfinding demo (like using the mouse, holding Ctrl-Alt highlights the path).

Technically this exits examine mode for the move, but key to the UX is that the destination is remembered, so until another destination is set, any time Shift-Alt-g is pressed Cogmind will resume approaching the destination. This is essential for when passing by a move-interrupting hostile like a Watcher.

cogmind_keyboard_pathfinding_continue

Keyboard pathfinding demo w/resuming.

Because it uses examine mode, keyboard pathfinding can also be useful when looking at items on the ground, e.g. while moving the cursor around to inspect salvage, if you find something you want a quick Shift-Alt-g brings you right to it.

For both this and mouse movement I’ve also finally made it so that setting an interactive machine as the destination automatically starts hacking it on arrival. After all, anyone who doesn’t want this effect can choose an adjacent cell as their target instead, and most anyone who is clicking on the machine’s terminal itself quite probably wants to hack it.

cogmind_pathfinding_start_hack

Pathfinding to a machine automatically starting the hack on arrival.

Adjustable Movement Delay

Another optional feature I’ve wanted to add for a while, one I’m quite curious if anyone will actually use, is to make the movement delay adjustable. “Movement delay” determines how long to wait before taking each move while traveling along a predetermined path, be it keyboard running or mouse/keyboard pathfinding.

Cogmind’s default has always been 100ms, a balance between “getting there quickly enough” while still being just slow enough react to unexpected changes. Quite a few potentially dangerous (or at least important to stop and observe) situations in Cogmind will stop automated movement anyway, but moving too quickly is still somewhat dangerous for the same reasons autoexplore is a bad idea in Cogmind. Among them are situations that can’t feasibly stop movement automatically, like threats on sensors changing directions, not to mention the high likelihood of wasting turns, which is generally bad in Cogmind since the passage of global time matters a fair bit.

cogmind_movementDelayInterval_demo

Demo of fast movement with movementDelayInterval=10.

 

cogmind_movementDelayInterval_demo_keyboard

Running delayed by only 10ms is pretty crazy! (recorded before the addition of rules to autostop diagonal movement near some layouts)

As part of this update I also fixed the issue of the unreliability of stopping running/pathfinding in progress, even more important now that the speed is adjustable because the problem could have become more pronounced with lower movement delays. (Normally any input made while moving should immediately stop the move, but input is also generally blocked while actions are being carried out, and the way it was blocked happened to also sometimes be ignoring even input that should technically be doing the stopping xD)

Still, I don’t really recommend changing this value from the default, I mainly just added it because it was easy to do and options are good, right? :P

Move Blocking

Stopping movement in progress, or even preemptively blocking a move before it begins, is an important part of roguelike QoL. (Technically this principle also applies outside movement as well, extending to other questionable or potentially dangerous actions, but this article is about movement in particular.)

I’ve heard players of some roguelikes (though not Cogmind, to my knowledge) argue that games shouldn’t protect players from their own stupid mistakes, but I think of it as basic QoL because if anything this sort of protection allows for more efficient play without having to waste time thinking about avoiding stupid mistakes, instead focusing on in-game tactical decisions rather than fighting the UI itself.

Anyway, over the years I’ve been adding quite a few of these, and will keep adding more as necessary. Below are some of the movement-related blocks I’ve implemented (none of these are new)

Non-optional blocks:

  • New combat threats entering FOV
  • Ramming (this was one of the first new blocks added in early alpha, and I can remember how chaotic it was back then with players constantly ramming into non-combat bots while moving around)
  • Spotting a new hostile trap
  • Moving onto a known trap
  • Flying while overweight
  • Sudden system corruption effects like heat surge (sometimes responding with an immediate increase in dissipation might be necessary) and part rejection (don’t want to leave some random part behind!)

Optional blocks (all active by default):

  • New non-combat enemies in FOV
  • Exiting to another map
  • Melee attacking a neutral target by moving into them
  • Melee attacking while flying (since the intent may be to simply jump)
  • Speed is very slow (>= 3 turns per cell)

The way temporary blocks generally work is they block the move and continue blocking movement for the next 500ms (while showing a warning message). This is important because movement is often a repeated action and players need time to respond to whatever it is they need to be noticing here, rather than just repeatedly mashing keys. Then once past initial warning period, there’s a window of about 2500ms during which that same warning won’t be shown again and the player is free to do that action (or maybe change their mind and do something else).

The one exception to the block window is spotting threats/enemies/traps, because those happen frequently and the main purpose there is to just block running/pathfinding rather than additional individual moves, so spotting a new enemy continues allowing movement freely.

What Else?

I’m sure more things will eventually pop up!

One internal movement-related feature that needs work is the pathfinding heuristic. The current pathfinding is actually pretty wasteful, and is one of the main processing bottlenecks for the game, but I’ve already done a few rounds of optimization as necessary and it’s fast enough, so that’s still been sitting by the wayside for if/when we need more performance improvements.

In its current state pathfinding (for all the AIs, mind you--just pathfinding for the player is negligible) doesn’t cause problems under normal circumstances, though the heuristic is clearly off when looking at how it searches for a path, checking more cells than should be necessary:

cogmind_pathfinding_visualization_trace

Pathfinding heuristic at work :/

Anyway, I tried before and couldn’t immediately find any way to effectively improve it (the obvious solutions weren’t working for some reason xD), but there are also other ways to optimize pathfinding besides the heuristic ;)

Posted in Design | Tagged , | 2 Responses

Steam Rich Presence

Last year Steam updated its friends list and chat client to support more features, and among them is support for “Rich Presence,” or basically giving games running under Steam the option to share with friends more about the player’s current state.

cogmind_steam_rich_presence_first_test_status_friends_list

My Cogmind Rich Presence status as seen in someone else’s friends list while I was testing it out.

As you can see I’ve now added this feature to Cogmind for the next release :)

Exploring the potential for this feature had been on my TODO list for a good six months since I’d first heard about it, though it just sat there slowly sliding its way to the top as I ticked off higher priority features for Beta 9.

I don’t normally use Steam as a consumer--I only started using their platform for development purposes, but not regularly enough to even notice Rich Presence in action, so that also made it less likely I’d promote the feature in the near term. Then more recently another player brought it up, and at the time I had a free evening and felt like doing a little mini-project, so I decided to give it a boost to the top…

Steam actually makes it extremely easy to do this (unlike Discord, which was also on my list but I dropped it earlier after doing some research, which is kinda funny since reportedly Steam finally rebuilt its friends/chat UI in response to competition from Discord…). You can read about Rich Presence in the Steamworks documentation, though I’ll be covering its main features and my own experience with it here as well.

Content

First thing to consider is exactly what kind of text should be shown for the player’s status in Cogmind?

Back when I initially jotted it down on my TODO list, the most obvious answer at the time was simply their location, as usual in a format like “-7/Factory.” But with the launch of Beta 9 we also have some great new features that would be perfect here: build class and status summary! Originally devised for the purpose of helping contextualize mid-run stat dumps, classes also became a multi-section feature of the final scoresheet, and build class was even later expanded with an optional HUD display. Now these features can perform double/triple duty by including them in the rich presence string.

Why just show “-7/Factory ” when we could show “Playing as Hacker-Skirmisher in -7/Factory. Status: Great”?

The Rich Presence possibilities now seem pretty colorful compared to showing only location, but will it all fit?

That was my next question, just how much room is there to display stuff, and unfortunately Steam’s docs are actually not too clear on this point, just saying that if it’s too long it’ll be truncated or ellipisified (which are sorta two different things, the latter possibly implying it could be expanded and the former suggesting it can’t, but anyway…). The docs don’t get specific enough to base a real decision on, so I did a little research to see what would show for other games.

It turns out longer strings that don’t fit are okay, since users can see the full string by expanding the friends list if necessary, although it’s important to remember that users might only see the first 2~3 words unless their friends list is sized a little wider than the minimum allowed width. (You can see an example in my first screenshot above of the width required to show that string.)

Users who hover over a friend’s avatar can also see the full details, which are just split up into multiple lines like so:

cogmind_steam_rich_presence_first_test_status_detail

Steam friend details with full multiline Rich Presence string.

So the first few words are going to be the most important in the string, and we could technically pack even more information in if we’re willing to abbreviate. That said, while abbreviations are great for players already quite familiar with the game, I’d say Rich Presence is also useful in that it can be suggestive to friends who have never played the game, so non-standard abbreviations are best avoided.

As a traditional roguelike, most of Cogmind is spent controlling the main character rather than having a bunch of separate modes, so the vast majority of Rich Presence strings will simply be of the [build][location][status] variety. 99% of the playtime is covered there, and I ignored the intro/title for now (actually maybe I should just add an “Enjoying the animated intro” status for fun :P), so all that’s left is the game over screen. Fortunately this didn’t require a bunch of extra work because the new scoresheet header now includes the “Result” of the run as a string, which in addition to the “win result strings” we’ve had before was recently updated with even the specific cause of death. Behold:

cogmind_steam_rich_presence_first_test_status_detail_death

Steam friend details with cause of death while viewing the game over screen.

Implementation

The technical side of things is actually quite simple, it’s almost just calling a single function to notify Steam of a new Rich Presence string, although as you’ll see there’s a bit more to it than that.

Before building proper architecture for this feature, I just wanted to call the SteamFriends()->SetRichPresence() function with some dummy text and see it working at a basic level. Other than the function call, doing this just requires one other step: Defining the available strings in a text file uploaded to the Steamworks backend.

Maybe they’ll correct it at some point after I post this, but I discovered that the sample file in the general docs for this feature actually has a formatting error that prevents it from working. I found the proper format on the dedicated localization section of the docs.

Testing what was and wasn’t working was fairly easy, however, since Steam provides a useful Rich Presence testing page (for devs who are logged in and playing their own dev build, even off Steam). It’ll display any errors encountered while trying to load and set Rich Presence data.

cogmind_steam_rich_presence_first_test

Using Steam’s Rich Presence Tester page for devs.

This whole process was pretty quick, probably the only slight roadblock was figuring out what to put on the backend without having to upload a bunch of different strings--ideally everything should be handled in game. (The docs are focused more around localization and fairly modal games, rather than my own needs here.) Cogmind doesn’t have localization, nor does it have a strong need to have a bunch of different “tokens” representing different modes, so I took a different approach: I have only one language, with one token, and it contains no text just a single variable :P

steam_rich_presence_localization

Simple “localization” workaround for Rich Presence in Cogmind, that way I can just drop whatever string I want into the %text% variable and that’ll be the player status.

If you’re interested in how it’s really done when you have multiple languages and more modes, check out the localization docs.

With that in place on the backend ready to accept non-static data, it’s time for proper architecture…

cogmind_steam_rich_presence_source_h

SteamRichPresence header (this should be a class rather than a struct but I’m lazy here since it’s not going to hurt).

There’s so little logic involved in setting a presence string that I started by simply updating it directly from where I wanted to check it in game, but after testing a bit discovered I’d need a second check elsewhere so, sure enough, going the smarter route of centralizing the code into its own thing was clearly the better option. So that simple class was born.

Technically it’s ultimately faster to update this only when necessary, i.e. at the point of a change, but a centralized solution is much simpler to manage across multiple systems, checking every 5 seconds whether the current string should be updated or not. It Just Works, since all the relevant code is contained within the update() routine, and you don’t have to worry about it elsewhere.

cogmind_steam_rich_presence_source_cpp

SteamRichPresence update() method source.

The code is pretty straightforward: After figuring out what the string should be, if it’s different from the most recently uploaded value, it loads the new string into the “text” variable, then writes the #StatusFull token (which as per the definition specified in the earlier file is nothing more than the text variable!) to “steam_display,” which Valve has designated the target for displaying a Rich Presence string for the player.

After this it was just a matter of testing the different scenarios to confirm they actually work.

Rather than repeatedly going to the tester page or my friends list, once the data seemed like it was uploading normally I also implemented a little in-game indicator for debugging so I could more quickly see what Cogmind was sending to Steam:

cogmind_steam_rich_presence_first_test_screenshot

Testing Rich Presence updates with debug view active.

Once it’s all working there’s still one more bit: an option to turn it off! Rich Presence reporting is on by default, but maybe not everyone wants to advertise to their friends their awesome tank build, or sneaking into hidden maps, or winning, or… you know, the opposite of winning ;)

Whatever their reason, I added the disableSteamRichPresence setting in case players want it to just say regular old “Cogmind” like it always has!

Posted in Gamedev | Tagged , , , , | Leave a comment

Special Mode Design: Abominations

Earlier this year I wrote about the hows and whys of alternate modes of play for roguelikes, taking a look at conducts and challenges and other unique ways to enjoy various games, and today I’m back to expand on that with some of the design process behind Cogmind’s latest new mode for Halloween 2019: Abominations!

There actually wasn’t a lot of forethought that went into this mode, as in unlike some plans I didn’t start with some idea but then just take notes and let it continue to incubate for a while as I thought more about its content and balance. It wouldn’t have even happened at all if not for special circumstances. There happened to be a week of down time during which Beta 9 was all but complete and I was waiting on third-party support for the final stretch regarding stat uploading to the new server. Around this time Steam sent out an email like they normally do reminding devs about upcoming events…

steam_notice_halloween_event_2019

Excerpt from Steam’s notice about Halloween 2019.

I’ve done April Fools and Christmas/New Year’s events, but never really considered doing anything for Halloween. But hey here was a chunk of available time, and it happened to be the right time of year, so maybe I could come up with a suitably-themed event.

(This article won’t avoid Halloween mode spoilers at all, so if you want to explore it unspoiled, STOP NOW and come back later for the following in-depth talk about its design.)

My first thought jotted down in my notes was simply “maybe parts on the ground start putting themselves together to attack you :P” and I ran with it immediately. Thus began Abominations mode development, started suddenly and developed very much on the fly.

Now I wasn’t entirely sure how feasible this idea would really be, so at this point the mode was still relatively simple, focusing on the doing rather than the planning, mainly because my initial goal here was to first actually test and confirm that this new “core mechanic” was actually going to be interesting and fun, and work logistically. If not I was just going to scrap it (as I’ve done with one unreleased mode before, as discussed on Patreon if you’re a supporter).

Abominations

Build-wise, Abominations presented some interesting considerations.

Unlike standard bots which have a static loadout and I set their core exposure in reverse by assigning the desired percentage and having the game calculate the exposure value based on their loadout, Abominations using a dynamic loadout (even frequently updating their build) meant they needed an initial static core exposure value.

This means I have less control over how easy it is to destroy a particular Abomination, but this is going to be a pretty chaotic mode as is, given that these new enemies can be composed of almost any combination of parts.

In terms of balance the wide range of potential Abomination effectiveness is okay though, since they don’t strictly work in squads like most other enemies, and individually powerful ones can and should be engaged away from others (or not at all) if possible. In playtesting I met some pretty impressive builds :)

Although Abominations can collect/attach any form of propulsion and you might find them treading, rolling, or even *gasp* flying, because they generally carry a lot they won’t often be moving especially fast, and by default they do have their own form of semi-slow propulsion: Etherial Tendrils.

cogmind_etherial_tendrils_info

Etherial Tendril stats--they’re odd since they don’t actually provide any coverage or absorb damage, but are also indestructible.

I originally tried to avoid giving them explicit propulsion so that they’d be as dynamic as possible, just using whatever happened to be around, but as you can imagine this resulted in a lot of immobile Abominations xD. They either hadn’t been formed near any propulsion parts, or had theirs destroyed in combat and would end up stuck in a room all alone.

cogmind_halloween_abominations_debug_counts

At one point I added an “immobility counter” to my debugging info so I could keep tabs on how many of them were actually probably useless at any given point. The number tended to hover around half the total.

Being immobile was especially problematic if they didn’t have anything but their melee weapon. From the start I had given all Abominations a natural/built-in melee weapon, Etherial Claws, because otherwise they’d have trouble getting their build together by scrapping nearby bots and it would be fairly common to find an unarmed Abomination, which wouldn’t be very fun (at one point I did imagine them attacking you/targets by using non-weapon parts, but that would be rather complex and heading in a fairly different direction).

So each Abomination gets a free decent melee weapon (which is really just backup since they’ll prefer to attack from range with a projectile weapon(s) once they have one) and a semi-slow leg-type propulsion.

To be effective, though, builds really need to take into account how their various parts work together, and clearly a mostly-random compilation of parts is not going to achieve that. So to at least ensure Abomination builds aren’t completely broken and don’t too often rely on lucky synergies, they also automatically get a decent amount of innate power generation and heat dissipation. Hey, they’re etherial in nature, right? (we’ll get to that later)

Like a number of other powerful bots in Cogmind they also get pretty good innate EM resistance, because that damage type tends to just bypass most other defenses and considerations, and would be too reliable and valuable a way to fight Abominations in particular given their possibly low core exposure and other capabilities.

cogmind_halloween_abominations_loadout_sample1

Sample loadout from a random mid-game Abomination. This one’s pretty nasty with some decent synergies going on, and anything with a cannon or two is going to be dangerous, but at least it’s slow.

Abomination AI also has a couple of unique features that correspond to their abilities.

For one they can switch their mode of propulsion. This is something that hasn’t been needed before in Cogmind, since each bot uses a single form of propulsion, but clearly a random collection of parts is often going to include more than one type. So Abominations will check their movement speed assuming different modes, and choose whichever is fastest. Due to different build masses, overweight thresholds, penalties, and drag, “fastest” is not easy to determine! (They ended up using the propulsion cycling function I wrote for the player while working on the new siege tread mechanics, actually switching to different modes then querying their speed in each before comparing the final results and making a decision.)

Abominations are also capable of swapping out their existing parts for better ones! For simplicity this feature relies on the same QoL algorithm I wrote for the player for automatically managing inventory swapping and part replacement, so it means they won’t switch to fundamentally different parts, only better parts of the same general type they’re already using.

cogmind_halloween_abominations_part_swapping

Now here’s a swap I think I can do without!

Origins

But where exactly are these Abominations coming from?

The answer just sorta popped into my head and mechanically I really like how it turned out: power sources.

As far as the locals are concerned, this is some sort of virus sweeping through Complex 0b10. Shortly after Cogmind enters a new map, 30% of all combat bots are instantly converted to wandering Abominations (lots of fighting naturally ensues since many of these bots will have been members of a squad).

After the initial wave, though, any power source already in the open, and any power source that is later created or dropped as salvage, has a chance to be marked as a potential Abomination. And each of these power sources has a random chance each turn to become the center of a new Abomination, sucking parts in from around it.

To maintain some semblance of control and balance, there is a cap on the number of Abominations which can be active at once on the current map, based on the size of the map: cap = [(mapWidth * mapHeight / 1150) + 10]. Also the chance to mark a new power source ranges from 40~80%, depending on how close to the cap we are (closer to the cap it’s less likely that new Abominations will be formed, whereas if the number is falling more Abominations will spawn).

There are actually five tiers of Abominations, from “Lesser Abominations” formed lower in the complex and from the weak engines powering common unarmed bots, to the pretty scary “Ultimate Abominations” resulting from late-game quantum reactors. Essentially the higher rated the power source, the better the Abomination, with better integrity and capable of attracting more parts.

Anomalies

Before even doing any real playtesting, I felt the mode would need more than this. “Robots” collecting parts from their surroundings and using them against everyone else is certainly an interesting enough premise, but theme-wise the event should should get even more creative than just relying on mixing and matching existing parts players are already mostly familiar with.

So I considered giving each Abomination a random special ability, noting down various concepts such as leaving a trail of fire, spewing heat, freezing nearby robots, detonating nearby machines, and more crazy stuff. Basically, adding environmental/area effects would make situations a lot more dynamic and interesting, especially if more than one of these effects is active in the same area.

However, it seemed like encounters would be a lot more dynamic if these abilities were given to a non-combatant entity, rather than concentrating them in what are already potentially powerful enemies (Abominations). Let’s call them “Anomalies,” drone-like objects randomly flying around and which, like Abominations, could also be centered around power sources.

One of the advantages here is that these Anomalies would then take up power sources that might otherwise form new Abominations and cause the latter to propagate out of control (at the time I hadn’t actually yet decided to cap the abomination count), not to mention if wandering non-combat bots are the ones carrying these abilities, that opens the door to neutral or even beneficial effects. Separate from Abominations, their faster speed also allows Anomaly effects to have a greater influence on their surroundings without the design having to worry about a hostile entity that will stick around and keep attacking the player in addition to its ability.

Anomalies are actually created by Abominations: For each surplus power source they’re carrying, there’s a 5% chance per turn to use it to “shed an anomaly.” Anomalies consist purely of that power source plus “Etherial Propulsion,” a unique type of flight. They’re fairly robust, just so that they aren’t quite that easy to instantly pop on sight without a pretty good build, and each has a unique effect, after which they’re named:

  • Fire Anomaly: Significantly heats up nearby bots. These are essentially like the Furnace derelicts, only they move a lot faster and are a lot more common, considering few people ever see Furnaces :P. As far as 0b10 bots go, they might very well quickly meltdown when a Fire Anomaly passes by if they’re unlucky with the side effects of the initial heat.
  • Ice Anomaly: Freezes nearby bots, preventing them from acting for six full turns even if just by passing by them (or you!). Also a good way to cool down, though ;)
  • Corrupting Anomaly: Causes system corruption to build up in all nearby bots, like the Demented derelicts.
  • EM Anomaly: Zaps nearby bots with corrupting electromagnetic blasts, basically like a mobile overloaded Fabricator.
  • Matter Anomaly: Leave random amounts of matter behind as they travel.
  • Resonating Anomaly: Cause nearby explosive machines to explode.
cogmind_halloween_abominations_resonating_anomaly

Following a Resonating Anomaly as it wanders around triggering some machines.

  • Unstable Anomaly: Randomly trigger entropic explosions centered on themselves.
  • Sundering Anomaly: Randomly shoot out waves of energy that rip parts off nearby bots.
  • Hungry Anomaly: Suck in and collect loose parts from a large area. Abominations also might feed on them, taking parts they need! Design-wise this is a nice way to randomly redistribute and deliver parts to Abominations that otherwise haven’t found any/enough in their local area as they move around more slowly. They also make amazing loot piñatas for Cogmind ;)
cogmind_halloween_abominations_hungry_anomaly

Nom nom nom.

  • Disintegrating Anomaly: Disintegrate nearby terrain. Several of these can easily turn large areas of the map into Swiss cheese, which may be a good or bad thing depending on the circumstances :)
cogmind_halloween_abominations_disintegrating_anomaly

I removed enemies from this map to get a much quicker view of what’s happening, but when there are battles out there, corridors widening and walls coming down can have a significant impact on tactical situations.

  • Warp Anomaly: Cause loose parts and robots to randomly teleport. Also randomly teleport themselves via the same effect.
  • Chaotic Anomaly: Randomly open rifts and summon objects through them, anything from common parts to angry powerful robots. They can literally summon almost anything, making it possible that either you (or Abominations!) may find some really rare parts just lying around. Careful out there… However, unlike most other Anomalies, the Chaotic variety only apply their effect while under attack. If you feel safe, attacking one of these might give you something great, or end up being a terrible idea--care to take a gamble?
  • Polymorphing Anomaly: If they come under attack, they randomly morph into a different powerful (if not very powerful) combat robot. Once fairly damaged they’ll then return to Anomaly form.
  • Paradox Anomaly: Fully repair terrain, loose parts, and the parts and core of all robots across a large area! This includes even your parts, but not your core.
cogmind_halloween_abominations_paradox_anomaly

Paradox Anomaly restoring terrain (again I removed enemies for a quicker demonstration).

That’s every single one from my original notes except for one (the Deflecting Anomaly, which would presumably be able to redirect projectiles mid-flight, but getting that mechanic into Cogmind would’ve been a huge amount of work, and probably fraught with bugs).

Note that the detrimental abilities do not affect other Anomalies or Abominations (which would make the mode pretty unbalanced and I think less interesting), though they’re still affected by warping and the paradox effect.

I originally planned to put a description of each Anomaly effect in their info window, but by the time they were all implemented decided it’d be more fun to just let players figure them out. They all have log messages corresponding to what they’re doing anyway, but there could be some added suspense on meeting a new one that hasn’t yet used its ability (plus some have multiple/special interactions to discover!).

Although Anomalies are chosen randomly, not all types have an equal chance of being formed--they’re weighted to allow for some control. Chaotic Anomalies are potentially too powerful, for example, and Matter Anomalies would fill an entire map with matter if there are many of them. Some Anomalies also can’t appear too early in the complex. For example meeting a Polymorphing Anomaly in the first floors could mean a swift death because of what they’re capable of turning into, which wouldn’t be very fair :P

Like Abominations, there’s also a mapwide cap on the number of Anomalies (generally around twice as many as Abominations).

Polish

With the main content complete, it was time to test it out and tweak the many variables involved, especially those affecting spawn rates and caps since they’d form the backbone of a consistent experience.

I didn’t play just yet, though, since 1) that would be quite slow and 2) the real important factor is what’s happening across the map as a whole, of which the player is a pretty small part. So I loaded up maps and would spend hundreds of turns watching each one to see how it played out on its own.

cogmind_halloween_abominations_watching_materials

Watching chaos spread back and forth across the map (open for full size). Different depths behaved differently based on their general layouts and resident robots/parts, and this particular sample is just the first and smallest map, which tends to be fairly cramped and dangerous in this mode. Later depths tend to be more chaotic with a greater number and variety of Anomalies, and stronger 0b10 forces so they’re not as easily overcome (including lots of reinforcements from Garrisons, which the above sample map is lacking).

This is when I ended up actually adding the cap on Abomination/Anomaly numbers, because they originally just grew like crazy as more bots entered the floor and were slaughtered :P. I also made an exception for this mode to reduce the number of non-combat bots that would continue coming into the map to replace those that had been destroyed, because otherwise they were an endless source of weak engines and therefore a lot of potentially weak Abominations.

cogmind_halloween_abominations_post-carnage_materials

Another scene of post-Abomination carnage in -10/Materials, labeled. This shot was taken before I put more early-game restrictions on the types of things that can appear :P

I also ended up adding more 0b10 dispatches, one of the big reasons being to supply new power sources (better ones!), and so there’s a constant churn of conflict across the map and it doesn’t eventually die down with one side fully overcoming the other.

cogmind_halloween_abominations_0b10_dispatch

The extra dispatches are essentially roaming assault squads.

Halloween mode also required a bit of dedicated QoL for the interface: Since it’s pretty important to know the specific type of Abominations you’re facing off against, or the type of Anomalies just spotted or operating nearby, I modified map labels to show their full name. Normally map labels show only robot class names, which is better in regular Cogmind the way it’s designed, but in this mode having so many robots that appear the same but possess wildly different capabilities or effects means there needs to be a quick way to distinguish them rather than opening their info or even just using the Scan window. So while playing this mode I tend to frequently hit ‘1’ to call up the hostile robot labels to be sure of what types of Anomalies are flying nearby.

cogmind_halloween_abominations_anomaly_labels

I see an opportunity to get repaired coming from the north, and it could also restore walls to put obstacles between myself and pursuers. Not getting too close to the Corrupting Anomaly would be a good idea, though…

In this mode players can also experience what it’s like to play against numerous robots with non-static loadouts, and why such a situation was intentionally avoided in Cogmind’s core design. With static robot designs, players can build up knowledge about enemies and establish expectations and therefore strategies based on that knowledge. Then the dynamic challenges are more about managing tactics, and as familiarity with robot loadouts grows, less time is spent learning basic information like the capabilities of enemies currently faced--i.e. it’s easier to quickly grasp a situation at hand, even as it changes, because the fundamental units making up that situation are all/mostly known. Having to very frequently examine robot info to find out about their build is a time-consuming process and not something I’d want to be a part of the long-term core Cogmind experience, but it’s okay for a special mode that will probably only be played a few times :)

(Aside: For similar reasons Cogmind also doesn’t feature randomly generated parts.)

Path-wise, for Halloween mode I blocked all the branch exits, even to Waste and Garrisons, because things would get weird and complex if this new content could interact with the plot. In that sense it’s rather nice and convenient that Cogmind’s core linear route to the surface is free of plot considerations and special events (at least none that are triggered locally).

Final Abomination

After everything was working nicely, with more dev time left to spare I felt the one thing missing was some kind of goal other than just escaping to the surface. I brainstormed a variety of ideas, even going to so far as to come up with meta possibilities like hiding Steam keys or creating a kind of tie-in ARG with clues and content outside the game.

In the end I decided it’d be cool to add some kind of boss, which could even have its own new map. At first I wasn’t sure I could easily add a new map like that, or that I really wanted to, since this was just for a special mode, but I went ahead with the idea and thus the “Lair” was born :)

Halloween mode can be won simply by escaping to the surface normally, so accessing the Lair is intended as a secret. After killing enough Abominations (at least 50, sometimes a little more), a dimensional gate suddenly opens, complete with sound effects and warning message so it’s pretty obvious something is going on, and all the exits from the current map are redirected to a new destination marked Final Abomination’s Lair.

To facilitate discovery of the secret, I added a special counter to the HUD that records the number of Abominations killed, and more importantly it changes color as the number gets higher, going from green to yellow to orange to red, hinting that there’s something else to that number.

cogmind_halloween_abominations_kill_counter

Demonstrating the special mode’s kill counter on the HUD (via a debug option).

The key number was initially 80, but I lowered it after playtesting the mode myself a couple times, since I didn’t want it to be that cumbersome, and too high a number would also make accidentally discovering it quite unlikely.

Within the Lair is the huge “Final Abomination” with a few Abomination friends which can produce wandering Anomalies as usual. It’s a prefab cave, and not an especially large one, designed just large enough to provide enough space and cover for the final fight. Lots of random high-level parts are scattered throughout the cave, and mechanically speaking the Final Abomination itself is also simply an even bigger Abomination with the same ability, drawing in nearby parts for its own use. It has a decent amount of core integrity though, so combined with its potential loadout it can be rather tough to take down.

cogmind_halloween_abominations_lair

Final Abomination’s Lair. I’ll leave out the boss so you can maybe discover what they look like one day :)

Some of the cave walls also randomly break open to spill out new parts, which might help later on (or hinder, depending on who picks them up xD)

The only way to escape is to destroy the Final Abomination, which creates a door that leads to the surface.

Strategy

I like how special modes can easily take an otherwise familiar environment and turn it on its head to suddenly provide a range of entirely new strategic and tactical considerations to take into account. Yeah we’re still in Complex 0b10, and the usual combat and non-combat bots are around and also may need to be dealt with, plus we’ve got a lot of the usual tools to work with, but with Abominations and Anomalies running around, everything feels different.

I’ll admit it’s quite chaotic, actually, though Cogmind is right at home immersed in chaos since the name of the game has always been about adaptability. It’s true in the regular game some players weave their way around the unpredictable elements and minimize the chance of risk and need for adapting to the unexpected, though for me the game shines brightest when it’s repeatedly throwing unexpected tactical situations at the player, situations that can most likely be overcome, but it’s a question of how well the player performs, and whether the result weakens them too much to take on the next situation, and the next, and so on.

Anyway, while playing I made some observations about Abomination-specific survival as I was blasting my way through the chaos, making it most of the way through on my first run, and on my second facing off against the boss (which I managed to take down about half way, though I entered the area fairly weak):

  • Abominations are often pretty slow, so running away or at least repositioning is often a decent option. Checking their speed is pretty important.
  • Spare parts just lying around can be incredibly scary (hey, it’s Halloween!), since they can be used against you. Spotting a cache of good explosives, for example, I’m immediately imagining how much I’d rather not meet an Abomination that decided to pick up such firepower. Either make a beeline for it and pick them all up, or avoid it like the plague :P. Heck, maybe even consider destroying them! Sometimes you might also consider “feeding” an Abomination some weaker weapons so it doesn’t end up attaching something better!
  • Any power sources in particular needs to be handled carefully. Those already lying on the ground could suddenly become a new enemy (and take nearby parts!), and dropping one on the ground is often even more dangerous since it could create a new Abomination right next to you! (which also sucks up nearby parts and immediately attacks you xD)
  • The existence of Fire Anomalies makes it likely that almost any build will need heat disappation at some point, even if the build doesn’t normally require it. Probably a good idea to at least have one such part in inventory, preferably a Coolant Injector or something similarly effective :). If one of these Anomalies rushes over and parks next to you for a bit, without a way to get rid of the heat you are going to start melting and it’s going to get pretty nasty.
  • It’s important to be very aware of Anomalies flitting about in general, since they move so quickly and can greatly change circumstances for better or worse. Think of how to use them to your advantage! Frequent use of ‘1’ to label them all is a good idea, as is learning what their respective effects look like, since some of them you can easily spot coming a ways off and change your tactics accordingly. Adapt!
  • Use 0b10 forces and Abominations against each other. It’s a three-way battle for survival, after all, so try not the stand in the middle, or maybe even try to invite them to meet each other ;). I remember one case where I actually dropped an engine from my inventory specifically to take on an oncoming 0b10 squad--sure enough it spawned an Abomination, sucked up all the nearby weapons, and started trashing the other bots while I waltzed off to find the exit, haha.
  • It’s possible to reach the Final Abomination more quickly than the late-game, but in doing so you’ll have fewer slots (not as many evolutions!) so it could be pretty dangerous. Once in Access the exit always leads to the surface, though, so you have to open the dimensional gate before then. The ideal depth would theoretically be -2/Research.

Yet More Polish

So after writing this entire post and then going on to enjoy actually playing the mode quite a few times before release, although fun from the start I kept seeing areas where a little more work here and there would go a long way towards improving the experience.

A number of balance changes came first, since the early floors were clearly on the very hard side, plus I later also realized it would be nice to have better support for the separate difficulty settings. But then after the gameplay portion felt pretty smooth and on target to me, I turned my eye towards interface QoL aspects that were hard to ignore. It was certainly nice to be ahead of schedule on this side project, leaving time for so much extra polish before the official release :)

One modification was to filter out pop-up labels for Matter specifically in this mode, because Matter Anomalies eventually produce quite a lot of it, otherwise making it hard to mass-label other items on the map to parse them.

cogmind_halloween_abominations_matter_label_filter

Compare the difference between the filtered set and unfiltered. Yeah. As here, quickly labeling a second time does show all Matter, in case there maybe isn’t a lot of it around yet and you’d like to see the actual values (although the Matter tile’s/ASCII’s brightness reflecting the amount is also useful). This is the same type of filter behavior behind the adjustable relative rating feature in the advanced.cfg options for the regular game as well.

Another big improvement was adding different colors for each type of Anomaly. Labels are pretty easy to access, but still, Anomalies move fast, and frequently relying purely on manual labels to optimize tactics is pretty tedious. Tedium is bad. The Anomaly’s ‘n’ character (and corresponding Drone tile) is not all that often seen in the regular game anyway, and certainly even less in this mode aside from Anomalies, so giving them more freedom in terms of color won’t really lead to any confusion. They are one of the two stars of the show, after all!

So I started by just giving Anomalies different colored trails, where color is based on their type--Fire is red, Ice is white, Matter is purple, and so on.

cogmind_halloween_abominations_anomaly_color_trails

Watching only colored Anomaly trails in a debug view as they move around the map.

This is nice, but trails are intentionally kinda faint and only transient, whereas having a more persistent way to differentiate Anomalies would be even more useful.

I didn’t want to completely override their base color since that would remove the faction info it normally reflects, which might come into play at some point (if rarely), so I decided to instead have them blink in the color of their trail (but brighter).

cogmind_halloween_abominations_anomaly_color_blinking

Sample Anomalies blinking their respective colors. The blinking also works for those not currently in view but within range of sensors (with an Advanced or better Signal Interpreter, of course).

Blinking also makes these “environmental hazards” stand out a lot more on the map.

Timing

I decided to make “Abominations mode” a permanent part of the game, so it’ll be available even in future versions.. So far now most special modes have retained their playability, but a similarly content-heavy one last year, Holiday Mode, was only available for that version in order to more freely wreak havoc on the data and code base just for that mode. This time around I had more time to work on this mode, so even though it makes major additions, there was time to ensure each piece was being added in an orderly and futureproof manner.

I think special modes are a good way to add even more longevity to an already highly replayable genre, or bridge gaps between regular releases, although in this case it’s sadly coming a mere week after the massive Beta 9 dropped xD

zyalin_cogmind_beta_9_and_halloween_proximity

Art by Zyalin.

Posted in Design | Tagged , , , | 2 Responses

Siege Tread Mechanics

Hot on the heels of upgradable RIF abilities for bothackers, Cogmind has gotten yet another relatively accessible new mechanic that will lead to a variety of new tactics: all multislot treads have the option to enter “siege mode.”

Patron Item/Mechanic

One of the goals I’d set on my Patreon was to allow players to submit ideas for special items and new mechanics, and we’d all vote on those which we most wanted to see in game. We reached that goal during Beta 9 development, so the idea submission and voting happened in recent months, and the winner of that vote was “siege treads.”

cogmind_patron_mechanic_voting_beta9_190825_final

Patron item/mechanic voting results.

At the time the idea wasn’t super fleshed out, indicated simply as “treads with a special mode that confers more combat bonuses but further reduces/prohibits mobility.”

Towards the end of the voting period I took the top four vote earners and posted a somewhat more detailed proposal about their respective mechanics to help people decide, and at the time for siege treads I wrote:

This would add a range of new parts (treads, clearly :P) that don’t need to be rare, so it would be the most generally accessible mechanics among these options.

They’d be toggleable like overloading currently works for other propulsion, with effects like preventing movement while offering accuracy and defensive bonuses, for example increasing the coverage of all treads and/or armor.

Unlike overloading, however, to balance it out the negative effects would last longer once toggled off--basically fully exiting the mode for movement purposes takes some time, which would be indicated on the HUD.

The actual work would start a few weeks later, and before that there was some more designing to do…

Expanded Siege Concept

With siege treads now confirmed, as I started spending more time thinking about this mechanic and the original assumption that it would only be enabled by a few new parts, I felt that limitation was unnecessary (especially for the amount of work this would involve xD).

Why not expand siege mechanics into something that any treads can do? Three other forms of propulsion already have a use for toggling their active state once already active (overloadable flight/hover/legs), but treads didn’t yet have any corresponding ability--maybe that ability could be siege mode!

This would make the patron mechanic more widely accessible, rather than being some rare effect only a handful of people would ever see much less use.

Even more importantly, generalizing this capability would make it easier to teach players new to the mechanic. Tread info pages are already full, with no room left to add more rules info, especially those as relatively complex as siege effects, so by granting the siege ability to numerous treads while indicating that others cannot do it, or some are even better at it than others, we need a new stat, and that stat in turns gives us access to stat context help (i.e. selecting a stat to learn more about the relevant mechanics).

I actually couldn’t see any other way to do it, essentially requiring that this become a bigger mechanic to justify the stat, and here it was clearly the UI which guided gameplay design, which happens a lot.

However, allowing absolutely all treads to do this seemed excessive, and would also be a missed opportunity to make a subset of treads more unique, so I decided to limit it to heavy (multislot) treads. This makes sense on a number of levels, plus by allowing only heavy treads to use siege mode it indirectly restricts this feature to the mid-game and onward, to avoid adding siege mode mechanical and tactical complexity too early for new players.

Interface Work

By far the most troublesome part of this whole process would be how the player controls the mechanic, so I worked on that first. In fact, I even started before nailing down precisely what all the effects would be :P

On the outside it’s not too complicated (good! also important!)--just click/activate to head into siege mode, click again to exit. While transitioning or in the mode, the usual UI features would reflect the current state. The architecture behind overloading non-tread propulsion is quite simple since there is no delay on the effect, and part states can be toggled as a free action at any time. But internally we’d never had anything like the idea of a delayed toggle effect, so there are actually numerous states to handle here: the treads might be inactive, active, or “overloaded,” and while overloaded might be transitioning into siege mode, fully in the mode, or transitioning out. Plus we’ll have to deal with special conditions during some of these states!

cogmind_siege_treads_mockup_preactive

A GUI mockup in REXPaint including an early concept for the siege mode interface components. Specifically that Movement line  info and SIEGE tags (this was before the need for separate tags during transition became apparent).

Since I hadn’t dealt with anything like this before in Cogmind, my first instinct was to have the architecture centered around the robot itself (rather than entirely based on the parts), i.e. treads would be toggled into different modes, but the parent robot separately stores what mode it’s in.

I actually spent four hours implementing this system, and had it working, but the problems were about to begin when I starting getting ready to tackle all the edge cases and special rules a system like this would need. As it turns out, Cogmind has naturally always had a very part-based architecture, and trying to split this behavior between the involved parts and the robot was going to be a crazy amount of error-prone edge case work.

In hindsight: Duh.

Another hour later and I’d reworked it to instead be a part-based attribute, so that treads could be toggled individually (the first iteration also tried to toggle multiple treads at once), and instead of the robot storing any data at all, it could determine its current mode whenever necessary by querying all of its active treads.

This way the edge cases became much more manageable, so in addition to the delayed effect toggling I applied the other special rules one by one…

  • The transition timer could be reversed in either direction before toggle completion
  • Treads in siege mode or transitioning cannot be affected by EM disruption, corruption, overheating, or any other effect that could break or temporarily disable them
  • Treads in siege mode or transitioning cannot be removed, swapped, or dropped
  • Cogmind can still remove treads in siege mode by purging all parts (“going naked”)
  • While a robot is in siege mode, other propulsion cannot be turned on (or autoactivated when attached), a restriction that would also have to be applied to the propulsion cycling feature

Some of these had to be checked in a fair number of places, but not having to also worry about maintaining a separate robot state at the same time meant it wasn’t too much trouble.

With that up and running, it was time for the “Siege” stat to appear on the item info. Like the weapon stat line which displays either EM Spectrum or Heat Transfer, whichever is applicable for the current weapon, I could simply replace the propulsion Burnout stat with Siege when necessary. That data was wasted on Tread info anyway since none of them can use it anyway (but Cogmind lists inapplicable stats for items so that side-by-side comparisons are easier to make).

Note that although in this case I also did it first because it was going to be a harder part of the feature and possibly introduce limiting factors, I like to work on as many of the interface aspects of a feature as possible before doing the mechanical or logical aspects, since the former is required to better develop, observe, and debug the latter anyway ;)

Siege Treads

Now it was time to lock down the actual effects of siege mode and implement them one by one. As per the original suggestion this mechanic can be summarized as sacrificing mobility for increased combat abilities:

  • +20% accuracy bonus to non-melee attacks
  • Recoil has no effect on accuracy
  • 25% damage resistance to treads in siege mode
  • All armor and heavy treads have double coverage
  • Immune to part destruction from critical hits
  • Cannot move
  • As per standard hit chance modifiers, being immobile gives +10% accuracy to all attackers
  • Entering siege mode requires 5 turns, as does exiting it, and during each transition there are no benefits (only the inherent drawbacks of immobility and being an easier target)
cogmind_siege_tread_activation_immobility_and_coverage

Siege mode UI demo, also showing the relative coverage display.

There are three possible values for a tread’s Siege stat:

  • N/A: Not capable of entering siege mode (applies to all single-slot treads)
  • Standard: Capable of siege mode, as described above (most multislot treads)
  • High: As Standard, but with a +30% accuracy bonus and 50% damage reduction (a select few treads)

Once the effects were known, a new set of specialized “Siege Treads” could be added (but not earlier, in order to know how to balance their various stats against other tread options). Dedicated Siege Treads have average integrity since their incredible damage resistance artificially pumps that up by a lot when put to their greatest use (not to mention their above-normal accuracy bonus for all weapons, which all but guarantees hitting every target)

cogmind_heavy_siege_treads_info

Sample info page for Hvy. Siege Treads.

In addition to the new set, one of the rare unique tread types (spoiler) in the game is also capable of High Siege, making it even more desirable and interesting despite its own drawbacks.

With the mechanics decided, I could also get back to the info page and write the all-important context help, which in this case barely wins out as the longest context help for any stat…

cogmind_siege_stat_help

“Siege” mode context help.

Details and Polish

There was also the usual stuff to take care of as with any stat, like adding it to the gallery item data export formats (TXT/CSV/HTM) as well as some relevant stats for the scoresheet!

cogmind_siege_mode_scoresheet_stats

Sample siege-related scoresheet stats.

It’ll be interesting to see how many times people use this mode, and for how long. There’s also a separate entry for the total amount of incoming damage absorbed by treads in siege mode, though that’s listed under the damage section rather than the section sampled above.

There was no doubt in my mind that siege mode would require sound effect feedback for the activation, so I put together some cool mechanical transformation sfx one for that, too. (And another less exciting one for fully exiting the mode, for completeness and, again, state feedback purposes.)

The Evasion window is also supposed to show the effect of any defensive factors that affect enemy hit chance, so that needed a little addition as well.

cogmind_siege_mode_evasion_window

Evasion’s Speed category can now show a negative value while under the effects of siege mode.

AI Siege

Throughout work on siege mechanics, I intended for it to essentially be a player-only feature, as in the AI would never use it even if they technically had that capability. I was mainly worried about spending forever trying to get the AI to use it properly, and that in turn interfering with other behaviors.

But 1) obviously having them use it would be very FUN, adding more dynamic possibilities to certain situations, and 2) I also remembered that I recently already added turrets (in Beta 8) which are stationary combatants and that ended up okay. (Also having a few hours left to actually work on this played a part!)

So yeah, that’s a thing.

Though once the AI can do this, too, suddenly we need yet more indicators to reflect their state! For that I added a “+S” next to their name in the scan window, and an additional “(Siege)” text to their info window when that’s the reason for their immobility.

cogmind_siege_mode_entity_status

Robot siege mode indicators in the scan window and info window.

There’s also an on-map indicator: a blinking yellow ‘X’ temporarily appears over robots that have just entered siege mode.

This also reminded me I should probably add log messages for siege activation and deactivation, both for the player and others.

Plus of course you’ll hear when other robots enter siege mode (they get the cool sfx, too, although you might not be so happy to hear it when they do it!), so there are numerous avenues of feedback for this situation.

Tactical Implications

I’m eager to see how players make use of this new mechanic, especially given that it’s fairly accessible and comes at a time when other changes are also shaking up the combat meta. Using siege mode is entirely optional, but it does offer some new opportunities to consider alongside its potential drawbacks.

For one, in a tactical game like Cogmind where you’re often engaging numerous enemies, mobility is quite important. You always want to be in the optimal position, but with siege mode you’d have to make that determination further in advance, and be less flexible when things change for the worse.

Repositioning is often important even in the middle of a fight, and especially in dynamic fights where unexpected events lead to more dangerous situations, like a wall suddenly being removed and revealing new enemies, or being flanked, or being in a fight where additional nearby patrols are alerted alerted and start to overwhelm your position, or… much worse? :P

There are quite a few cases where even on treads, as slow as they are, you’ll want to get to a better spot to continue the fight, but if already in siege mode that won’t be such an easy option anymore, so whether or not to use it isn’t always a clear decision.

Due to the transition delays, overall one can’t use siege mode as effectively without prior knowledge of nearby enemy locations*, but the best siege loadouts will be specifically built for it, so whether or not it’s possible to capitalize on that capability requires a certain kind of situational analysis. (*For that reason I think it will be quite an effective combo with FarCom, if not sensors or other forms of tracking/detection.)

The transition requirements also mean you’ll always spend at least 10 turns not moving, plus any time spent in the mode, which might be time wasted. Some of this effect might be mitigated by turns spent doing actions where you’d be stationary anyway, like inventory management, but we’ll see how people react to it. There are certainly more ways to tweak it if necessary--like the transition duration can be modified (although I think 5 turns is a good spot to balance against the effects), or, more likely, certainly actions like firing would not be possible during the transition.

Although the defensive potential in terms of free damage resistance and extra coverage is nice for protecting your other parts regardless of situation, personally I think it’s most effective at range, where you can take advantage of the accuracy bonus better than enemies who would almost certainly hit you if they were close by (given their additional accuracy bonus from your immobility). Of course engaging enemies at range is overall more difficulty to do when slow.

Shortly after implementation, I started streaming a new heavy combat run aiming to use and talk about siege tread mechanics (among other new Beta 9 stuff). Part 1 is here:

After the stream Zyalin shared his impression of a Cogmind in siege mode:

cogmind_siege_treads_fan_art_zyalin

Siege treads concept by Zyalin.

What are treads doing when they’re in siege mode, after all? ;)

Posted in Mechanics | Tagged , | Leave a comment