Developers Iteration I of 2023

21

Find out about the last bits and twigs for the first development iteration of the game in 2023. Everything in this topic is merged - you can experiment with these changes yourself by playing the FAF Develop game type. You can choose this game type as you host your game:

a724abb1-a5db-4d84-8734-4fddcbb638ec-image.png

With that said, let us dive right in the latest developments!

References to all development iterations:

A work of art is never finished, merely abandoned

23

Improved structure terrain interactions (#4584 on Github)

Combined with the knowledge of Balthazar we managed to significantly reduce a common source of confusion and disappointment: bad terrain deformations. As you build structures the terrain was flattened underneath, with a bit of (bad) luck this could create sharp edges in the terrain that end up blocking pathing or projectiles all together.

As a few examples:

Seton's Clutch

f3787cae-d488-4666-bd87-d3b226c59470-image.png

Long John Silver

4f5ab8ef-e4dd-47b8-94e3-cd28554a266d-image.png

b1fd76bc-7812-49fe-ac45-98bab33276ef-image.png

We're all too familiar with them, to the degree that it would even limit the creativity of map authors. Terrain has to be flat, or it will cause bad deformations that result in significantly worse gameplay.

But - no more! With the changes we're making to how structures interact with terrain we no longer create a flat plane that needs to be completely horizontal. Instead, we create a gradient between the four points of the build skirt and slightly orient the structure to match the gradient as required. As a result the number of bad deformations is reduced significantly, to the degree that it is really difficult to create a bad deformation.

As a few examples:

Seton's clutch

ba35b039-cd3b-43c5-8f7f-1394cb7ca57b-image.png

Long John Silver

60aa05b9-0a24-4d27-a37d-88c6967e0c0f-image.png

bcd20260-3fec-4aea-b0ed-a02fc3f3788a-image.png

This change is significant - not only does it help you as a player to just enjoy the game. It will also increase the creative possibilities for map authors as terrain no longer necessarily needs to be flat.

Significant performance improvements (#4584 on Github)

We've found one more large performance hiccup and managed to resolve it. The problem and solution is rather technical. Tthroughout the entire game you can expect 10% to 30% more performance on average, depending on what is happening.

I'll try and explain it - I've not found a way to keep it simple. Therefore I'll just write it out and make comparisons where possible.

Table trashing

The first issue was during instantiation of a table with a C reference. Instantiation means the creation (allocation) of something. And the table can reference quite literally anything:

  • A damage instance: any damage in general, regardless whether it hits a unit or prop
  • A decal: tread marks or the small decals we generate when projectiles hit the ground
  • An effect: terrain effects, projectile trail effects, projectile impact effects, build effects - the list goes on
  • A blip: the radar blips that are created for units
  • A manipulator: these are applied to units for animations, and the sliding of barrels as they fire
  • An entity: units, weapons, projectiles, bare entities, props, beams, trails, ...
  • ..., the list goes on but we'll stick with these examples

When we create an instance they inherit functionality and data from a Class. This was done via a table called a ClassFactory, which was defined as:

ClassFactory = {
    __call = function(self, ...)
        -- create the new entity with us as its meta table
        local instance = {&1 &0}
        setmetatable(instance, self)

        -- call class initialisation functions, if they exist
        local initfn = self.__init
        if initfn then
            initfn(instance, unpack(arg))
        end
        local postinitfn = self.__post_init
        if postinitfn then
            postinitfn(instance, unpack(arg))
        end

        return instance
    end
}

The problem is at the very start:

    __call = function(self, ...) <-- note the '...'

The argument ... is called a varargs, and the idea is that it allows a function to be more flexible: you can pass any amount of data to the function and the function can then iterate over that data, as the data is stored in a table. The table is created regardless of whether there is any data to pass along. And that is exactly what the issue was: every example we just described does not use this approach to pass data to the instance. Therefore every example described has an overhead of creating a 80 byte table, just to trash it out again!

And the overhead is significant: 80 bytes sounds like nothing. But let us take a single event as an example: when a weapon fires a projectile. At this event the game creates:

  • 1x manipulator: A slider to mimic recoil
  • 6x effects: two effects for firing the weapon (a flash and smoke for example), two effects for the projectile itself and two impact effects
  • 1x projectile
  • 1x damage
  • 1x decal
  • 1x other things

In total, on average:

  • 11x varargs table created just to trash it again

For this single event we've trashed up to 880 bytes worth of memory. The average unit fires about 1 projectile per second. That means during a battle a single unit can trash up to almost a kilobyte of memory per second! Multiply that by 200 units for the average battle and we're talking about hundreds of kilobytes of data being generated per second, just to trash it again. To put that into perspective:

  • This post is about 5 kilobytes of text, at the moment of writing this sentence. We'd trash the same amount of memory when a Hoplite fires one salvo
  • The average JPEG image is about 50 to 500 kilobytes. It is not unreasonable to trash as much memory as the average JPEG image per second during a relatively small battle

We can continue on - but the impact is quite significant when you take into account the garbage collector and how the CPU cache works. For example, we drastically reduce trashing the caches and increase the chance of a cache hit.

For those that like a puzzle: there are a lot of other very common events that no longer create this dummy table. Can you find some based on this information? I'll add them to a list in this post as they are found 🙂

Pre allocate tables

The second issue is about how tables grow in memory as more elements as attached to it. We'll take the example of the creation of a projectile again. When a projectile is created, we at least add the following fields to it:

OnCreate = function(self, inWater)
    -- store information to prevent engine calls
    self.Blueprint = EntityGetBlueprint(self)
    self.Army = EntityGetArmy(self)
    self.Launcher = ProjectileGetLauncher(self)
    self.Trash = TrashBag()
end,

Just like lists in C# do, a table in Lua starts with no allocated memory by default. As we add elements to the table (the self instance, in other words: the projectile) the table grows accordingly. This is done by logic similar to the following:

static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
  int i;
  int oldasize = t->sizearray;
  int oldhsize = t->lsizenode;
  Node *nold;
  Node temp[1];
  if (oldhsize)
    nold = t->node;  /* save old hash ... */
  else {  /* old hash is `dummynode' */
    lua_assert(t->node == G(L)->dummynode);
    temp[0] = t->node[0];  /* copy it to `temp' */
    nold = temp;
    setnilvalue(gkey(G(L)->dummynode));  /* restate invariant */
    setnilvalue(gval(G(L)->dummynode));
    lua_assert(G(L)->dummynode->next == NULL);
  }
  if (nasize > oldasize)  /* array part must grow? */
    setarrayvector(L, t, nasize);
  /* create new hash part with appropriate size */
  setnodevector(L, t, nhsize);  
  /* re-insert elements */
  if (nasize < oldasize) {  /* array part must shrink? */
    t->sizearray = nasize;
    /* re-insert elements from vanishing slice */
    for (i=nasize; i<oldasize; i++) {
      if (!ttisnil(&t->array[i]))
        setobjt2t(luaH_setnum(L, t, i+1), &t->array[i]);
    }
    /* shrink array */
    luaM_reallocvector(L, t->array, oldasize, nasize, TObject);
  }
  /* re-insert elements in hash part */
  for (i = twoto(oldhsize) - 1; i >= 0; i--) {
    Node *old = nold+i;
    if (!ttisnil(gval(old)))
      setobjt2t(luaH_set(L, t, gkey(old)), gval(old));
  }
  if (oldhsize)
    luaM_freearray(L, nold, twoto(oldhsize), Node);  /* free old array */
}

That is a lot of code, but more importantly: it allocates new memory, re-inserts the existing elements into the new memory and prepares the old memory for deallocation! That is a relatively expensive operation, but it all depends on how often it is run. To understand that, these are the resize thresholds for the hash-based array:

Resize threshold Resizes to Bytes hash part occupies Total bytes
0 or 1 2 40 80
2 4 80 120
4 8 160 200
8 16 320 360
16 32 640 680
... ... ... ...
n 2 * n n * 20 n * 20 + 40

That means when we create a projectile we have to resize at least three times! And in practice it is four times, where as the average projectile can take up to 8 hash entries. That causes it to just resize to 16. This is something we can try and optimize in the future too.

Usually in Lua you can not pre-allocate a table. That is not normal syntax. But the GPG devs introduced that syntax in the Moho engine. And using that syntax, we can size the table as it is created. As an example, this is a special class instantiation factory for projectiles:

ProjectileFactory = {
    ---@param self any
    ---@return table
    __call = function (self)
        -- LOG(string.format("%s -> %s", "ProjectileFactory", tostring(self.__name)))
        -- needs a hash part of one for the _c_object field
        local instance = {&15 &0}
        return setmetatable(instance, self)
    end
}

Where the important line is this:

        local instance = {&15 &0}

Which states that we want to pre-allocate the hash part of the table so that it can at least hold up to 15 elements.

This same principle applies to any instance mentioned earlier, where we properly pre-allocate the table for units, shields, weapons, projectiles, damage instances, effects, decals and all the other parts of this game. We now properly pre-allocate them all, drastically reducing the frequency at which the engine ends up calling the resize function.

Control ... (#4587 on Github)

A Discord user asked in the general chat if there is an easy way to split up your selection. The answer is no - but the question is why? Why are there no tools to manage your current selection?

With this patch we're introducing a first batch of hotkeys that you can use to create subgroups of your selection, through which you can navigate. You can find them in the hotkeys menu:

f8605648-3467-4938-9b38-e4a3e9a444cc-image.png

All these hotkeys divide your selection over a series of subgroups. You can then use an additional hotkey (in the screenshot it is Tab) to navigate through your subgroups. We'll take two examples:

Divides a selection by the line through your mouse position and the center of the selection
bdcf1864-79e4-4011-9dbc-1da63a65096c-image.png

Divides a selection orthogonally to the line from your mouse position to the center of the selection
be226567-5f0a-4d0e-a689-c633a831d31b-image.png

These two hotkeys allows you to divide your selection into two subgroups, which you can then quickly navigate between. The command mode (when the cursor changes to issue orders, for example reclaim, ground attack, launch orders ...) are not reset as you navigate between subgroups.

With this patch we at least introduce the following divisions:

  • Divide over mouse axis
  • Divide over orthogonal mouse axis
  • Divide over major axis
  • Divide over minor axis
  • Divide over tech
  • Divide over layer
  • Divide over tech, but only include engineers
  • Divide over subgroups of size 1
  • Divide over subgroups of size 2
  • Divide over subgroups of size 4
  • Divide over subgroups of size 8
  • Divide over subgroups of size 16

We hope this provides you with more control over your selection, and therefore with more control over your army. If you have ideas of other divisions or selection manipulation: feel free to jump into the suggestions channel in Discord and we can discuss them accordingly!

... and Command! (#4577 on Github)

On top of that we are introducing various quality of life features. The first two features we'll reveal are about adding optional side effects when you issue an assist order. Specifically we're talking about these options:

ad1c2ce5-8b55-44c4-9936-d4c9f542e4ab-image.png

The option Assist to upgrade allows you to immediately queue up the upgrade of a tech 1 mass extractor as you issue the assist order. The option Assist to Unpause allows allows you to unpause extractors and radars as your units start assisting them. The former is useful for quickly queue up (assisted) extractor upgrades. The second makes it easier to focus your build power.

A work of art is never finished, merely abandoned

12

You can find out about all the other changes for this development iteration by reviewing the milestone on Github.

# Game version 3751 (25th of February, 2022)

In this first development update of 2023, we introduce three month's work of bugfixes, quality of life changes, and assorted improvements. It is, by far, the most exciting patch we've released so far. While the full changes are detailed below, a quick summary of those changes we think you'll find most important:

- We've changed how structures interact with the terrain. Previously, structures built on uneven ground could create terrain deformations. On some maps, this resulted in changes to the terrain that prevented the player from placing neighboring structures and created pathing issues for units. With this update, buildings deform the terrain less and may be placed at a slight angle. 

- We've introduced a new series of hotkeys that will make it easier to select and micromanage your units. 

- The process of managing your mex upgrades will now be easier than ever thanks to several small features. You can now choose to have mexes automatically queue an upgrade and (un)pause extractors when you order engineers to assist them.

- Several smaller quality of life changes have been made to existing features, such as no more empty reclaim orders and preventing ground attack orders from snapping to props or units. You can read more about all these changes in the 'Features' section.

In future updates, we'll be shifting our focus to improving the AI we ship with FAF. So far, we've been working on a navigational mesh that can help the AI understand any map you throw at it. The task ahead is to extend this with additional features to help the AI understand specifics about a map. You can read what we've achieved this patch in the 'AI' and 'Navigational mesh' sections.

And last, but certainly not least: this patch contains the largest performance improvement to date; the game is on average 10% to 20% faster in comparison to the last developers patch! This is exciting because with this patch the average game no longer slows down. We've been running tests and a CPU as cheap as a Ryzen 3600 can now run up to 6000 units without slowing down. We find this is extremely exciting: the game is nearing the point where you can just enjoy playing the originally intended experience in real-time!

With appreciation towards all the contributors that made this patch possible,

Jip

## Features

- (#4584, #4607, #4615, #4636, #4714, #4724) Improve terrain structure interactions
    Instead of flattening the ground below structures, they now slightly tilt to reduce terrain deformation.

- (#4474) Ground attack now ignores all props/units
    You can now assign a ground attack exactly where you clicked without it accidentally snapping to props or units

- (3e34599) Prevent being able to issue 'empty' reclaim orders
    It is now impossible to create a reclaim order with no prop or unit attached to it

- (#4474) Move command mode no longer creates patrol orders by accident
    When you specifically issue move commands using the hotkey (usually 'm') or by clicking on the move command button it now ignores the 'convert to patrol' functionality

- (3e34599) Remove the use of CTRL to issue commands with formations
    When you hold control units first move towards each other and create a formation before they would go to where you told them to. This is a hidden feature of the engine and often players were not aware. We patched this out because often people use the same key for hotkeys, after which players (usually accidentally) would issue a formation order instead of a regular move or attack move order

- (#4510) Add a game option to set the zoom threshold at which reclaim values are grouped together in the reclaim-overlay

- (#4586) Add game option to tweak the camera shake multiplier
    When set to zero it will entirely remove shaking from the game. Additionally, the default shake multiplier is now set to 0.5 (instead of 1.0)

- (#4577) Add game option to upgrade and pause tech 1 extractors when you issue an assist order
    A small quality of life feature that reduces the use of a few hotkeys

- (#4577, #4620) Add game option to unpause tech 1 extractors as engineers start assisting
    A small quality of life feature that reduces the need to check up on your extractors

- (#4587) Add hotkeys to divide your current selection into subgroups
    There is a separate hotkey to tab through the subgroups. This feature significantly improves your ability to manage and micro larger chunks of units

    As a few examples of divisions:
     - Divide your selection by tech level
     - Divide your selection into groups of 5
     - Divide your selection over those nearest and furthest from your mouse location
     - Divide your selection into two equally sized groups

    For UI mod authors: the changes introduces a framework that allows you to define additional ways to split a selection into subgroups.

- (#4626) Allow mass storages to be built underwater

- (#4490) Add mission briefings to the lobby for all campaigns that ship with Supreme Commander
    When you are in a co-op lobby the patch notes button is replaced with a briefings button. There you can see the briefing of a map. Only original campaign maps support this feature at the moment.

- (#4689, #4690, #4691) Add hotkey that resembles the 'hard move' functionality introduced by Strogo
    For those unware: it allows you to continiously issue move orders without queueing them and without accidentally converting them to patrol orders. This is particularly useful for ASF battles

- (#4095) Adds a partial share game option
    An alternative variant of full share. While structures and engineers are transferred, all other mobile units are lost.

- (#4463) Add a new key binding to select naval units, excluding sonar structures

## AI

This update adresses several long-standing issues that affected the custom AI that FAF introduces. Further developments and improvements of the AI will remain our focus in future updates.

Additionally, we would like to remind people that there are various mods that provide different AI experiences. We can highly recommend you to download them from the vault and give them a spin too.

A short list of AIs we recommend at this point:

- M27: made by Maudlin
- RNGAI, as made by Relent0r
- Sorian Edit, as made by Marlo
- Uveso AI, as made by Uveso
- Dilli Dally, as made by Softles
- Swarm AI, as made by Azraeel

And not to forget the AI that ships with the Total Annihilation mod that is maintained by Dragun.

- (#4413, #4419, #4450)  Tunes the economic assesments of the AI.
    Throughout the game the AI constantly tries to balance his decisions and those decisions depend on various conditions. These conditions can be tweaked and that is exactly what we did here.

- (#4445, #4447, #4455, #4462, #4461, #4460, #4454, #4475, #4505)
    General tuning and bug fixing of the AIs. This involves all sorts of improvements, such as fixing a bug causing the AI to hoard units in their base and improving their use of naval units.

- (#4386) Separately keep track of radar structures for AIs
    These are interesting and often vulnerable targets for the AI. By keeping track of them separately it can interact with them more easily.

    Better guard those radars from now on!

- (#4412) Add logic to prevent prematurely disbanding a platoon
    A platoon is a group of units that is acting according to some logic that describes the behavior of the platoon. When a platoon disbands it returns to base to receive a new order. We fixed platoons disbanding too soon due to a bug.

- (#4682) AI has been upgraded to make better use of experimentals.

- (#4436, #4450) Improve consistency of builders used by the AI
    A builder is not an engineer, but a set of conditions that the AI uses to determine what to build. These conditions depend on the status of the AI (do I need additional factories given my income?) and the status of the enemy (should I produce more interceptors?)

    These are tweakable and that is what we did here.

- (#4525) Allow AIx multipliers that are lower than 1.0
    Some people asked for this feature and here it is - for new players you can lower the multiplier to below 1.0

## Navigational mesh

The navigational mesh is an abstract representation of a map. The AI can use that representation to gain an understanding of what the map 'looks like'. The navigational mesh is generated at the start of the map and works on any map.  

We're looking for people with an interest in computer science to add features to add many other functions that allow the AI to understand. One example of such a feature is the ability to generate expansions markers: points of interest for the AI when it would like to build an expansion. And we'd like to add so much more so much more so that an AI can understand and properly play on any map. The navigational mesh is only use by the AI and only runs when there are AIs in-game.

- (#4432) Add label utilities
    Allows the AI to understand the value of an area, such as a plateau.

- (#4485, #4495) Only load in the navigational mesh as requested
    Entirely skip the generation of the navigational mesh when it is not used. This prevents allocation a few megabytes to store the navigational mesh in memory

- (#4555, #4559, #4561) Improve retrieval of (nearest) leaf for path finding
    This is an improvement to a macro feature (what is the general path from A to B?) and not a micro feature (how should I move this unit?). It is now more consistent, such that if a unit is remotely able to navigate to some place it will always have a label assigned to it.

- (#4569) Add generation of expansion markers
    These markers are generated for each map. The AI can now identify sane expansion locations on any map

## Bug fixes

- (#4483, #4482, #4496, #4499, #4508, #4519, #4546, #4550, #4580, #4599, #4600, #4605, #4606, #4608, #4631, #4638, #4668, #4669, #4671, #4667, #4672, #4678, #4683, #4692, #4727)
    General bug fixes that are too small to mention. These are usually introduced during the development environment and caught during testing.

- (#4438) Fix Seraphim torpedo bomber being able to apply damage twice

- (#4453) Fix the marker manager being unable to detect spawn markers

- (#4481) Fix UI scaling of lobby messages

- (#4488) Fix UI scaling of lobby map preview tooltips

- (#4500) Fix and improve option keys

- (#4588) Fix the charge icon of the loyalist

- (#4593) Fix the Lighting Tank being unable to fire at targets on water

- (#4617) Fix a bug where the construction menu would consistently reset

- (#4622) Fix wrong LODs for Cybran shields

- (#4623) Fix removing restrictions breaking the HQ system
    This was most notable during co-op

- (#4634) Fix the charge animation of the Emissary

- (#4635, #4639) Fix the direction of adjacency beams for factories

- (#4633) Fix various units being refracted when rendered in front of water

- (#4697) Fix a bug where neutral armies could view the entire map

- (#4699, #4715) Fix the jumping and rotating of units as they start being built

- (#4694) Fix offset of LOD1 of the CZAR

- (#4716) Fix a bug with the creation of templates with 1x1 or 3x3 structures
    The old method of creating templates would create gaps, the new implementation allows you to make proper templates with any structure size

- (#4725) Fix a bug where tech 2 and tech 3 Aeon engineers can not move backwards  

- (#4726) Fix a bug where damage indicators linger on and remain visible

- (#4730) Fix a bug where using recall could make your ACU immune to damage

- (55ddea) Fix a bug where pausing a unit would also stop updating the work progression
    Often noticeable when assisting paused structures

## Performance

We've been consistently improving the performance of the game by re-implementing features and in general by reducing the overhead of functionality. This section may not be as interesting for the average reader, but we add it anyway as good performance is an important aspect of the general user experience.

- (#4399) Improve performance of the heap data structure by 60%
    The heap data structure is used during path finding for AIs

- (#4417) Reduce run-time parsing of categories for AIs
    Replaces all string literals with their respective categories

- (#4376) Reduce overhead of the objective arrow
    Reduces memory usage of certain aspects of co-op missions

- (#4421) Lower case all imports of build conditions
    These are imported during run-time as they are processed, by having them as lower case characters we prevent a string operation to turn them into lower case characters during run time

- (#4150, #4444, #4489, #4512, #4512, #4557, #4680, #4681)
    Remove fields on instance tables to reduce memory usage. In Lua the hash part of tables grow by factors  of two. It can be quite beneficial to refactor the code to remove a few fields as it can prevent the average unit to hit the threshold. As an example:

    - (1) A unit with 33 fields in its instance table will have space for up to 63 fields
    - (2) A unit with 30 fields in its instance table will have space for up to 31 fields

    Where the table occupies 64 * 20 = 1280 bytes in the first example and only 32 * 20 = 640 bytes in the second example.

- (#4426, #4483, #4503) Separate AI and player logic
    AI initialisation is now only performed when there is an AI in the game. For a game with no AIs these procedures are skipped which saves several dozens of megabytes worth of memory

- (#4451) Reduce overhead of passing regeneration values to UI
    These values are no longer passed via the sync, but attached to the state of the unit instead

- (#4466, #4492, #4597, 3e34599, 9c9dda3) Reduce traffic between the sim and the UI layers
    Every bit of data we send to the UI is (deep) copied and usually thrown away afterwards. This involves a lot of memory management and that is the most expensive type of logic that a computer can run these days.

- (#4517, #4534, #4532, #4533, #4531, #4528, #4529, #4530, #4582, #4552, #4585, #4549, #4596, #4611)
    Reduce overhead of projectiles and weapons. The primary change is to reduce the amount of table trashing. An example is the use of a table within the scope of a function: it is allocated and then immediately ready to be de-allocated, which is a waste of performance and a hurdle for the garbage collector.

- (#4539, #4540) Reduce overhead of class instantiation
    Reduces the overhead of all instantiations such as the creation of effects, decals, projectiles, internal data structures and more. This is a significant boost to the performance overall

- (#4536, #4556) Reduce memory footprint of navigational mesh by 50% to 95%
    With thanks to #4523 we can now reliably measure the impact of changes, and as a result we managed to increase our awareness of what is expensive.

- (#4640, #4663) Reduce overhead of unit treads
    The new implementation is a lot more memory aware and reduces the amount of table trashing

- (#4657) Reduce overhead of builder conditions of AI

- (#4558) Replace legacy trashbags with the TrashBag class

- (#4576, 4679, #4703, #4711) Reduce overhead of unit intel management
    The new implementation is a lot more memory aware and drastically reduces the memory footprint of the average unit

- (#4675) Dynamically compute LOD thresholds for units
    The larger the unit the longer it remains in view. These values where all over the place. These changes create a consistent experience for players

- (#4686, #4703, #4712) Reduce overhead of passing veterancy state to UI
    The old implementation could cause stutters due to excessive copying of tables when syncing

- (#4686) Fix memory leak with the veterancy system
    The old implementation would keep a reference alive to essentially every unit in the game that ever received or did damage to another unit. This would create a directional graph of references with the ACUs being the spills. As a result there is a significant build up of memory as the game progresses

- (fd41dce) The game can now use up to 4 gigabytes of memory, instead of just 3 gigabytes
    Due to an assembly patch the game can now use an additional gigabyte of memory. In combination with all the other memory improvements mentioned this should prevent all cases of where players run out of memory

## Physics Based Rendering (PBR)

We're slowly but surely preparing the game for a significant visual improvement. This is a long term project that is going to consume hundreds of hours. We're hoping to find additional contributors that have an interesting in creating (and fixing) meshes and textures.

If you have that interest and/or experience and you'd like to help out then you can introduce yourself in the dedicated channels in the official Discord channel!

- (#4247) Introduces shaders for Physics Based Rendering (PBR)
    The shaders are not used yet but the code is ready to run

- (#4443, #4673) Fix existing cube maps and prepare them for PBR
    Adds a blur to the mip maps to mimic roughness of the surface

- (#4456) Re-create the Cybran land factories

- (#4469) Re-create the Cybran naval factories

- (#4501, #4664, #4665) Re-create the Cybran air factories

- (#4501) Re-create the Aeon air factories

- (#4479, #4613) Re-create the Aeon land factories

- (#4521) Re-create the Aeon naval factories

- (#4471) Fix localisation and colors of default fields of combo

## Other

- (#4317, #4476, #4320, #4515, #4502, #4504, #4517, #4547, #4513, #4603, #4322, #4677)
    All the annotation work that has been merged in. We have an extension that allows you (a developer) to gain basic intellisense support in the repository. This has been, and still is a massive improvement to the workflow of those that work on the game (in)directly.

- (#4468) Fix terrain-type depending mesh selection of structures
    This feature is not used, but technically it allows you to change the (textures) of a structure depending on the terrain type it resides on. As an example: a factory on snow would have snow on it

- (#4303, #4604) Add or improve Chinese translation

- (#4487) Improve the test functionality of movies

- (#4523, #4658) Introduce function to determine size of table in memory
    Allows us to estimate the size of a table in memory

- (#4512) Fix firing sequence of the UEF Cruiser
    This is a visual fix and does not impact gameplay.

- (#4538) Reduce code duplication by introducing 'table.random'

- (#4263) Add division icons

- (#4395) Add MIT licenses to various FAF-introduced files

- (#4659) Add a russian translation for the balance patch

- (#4688) Add a code of conduct to the repository

- (#4731) Fix the auto balance button in the lobby being too large

## Mod incompatibility

There appears to be an issue with the UI mod 'Supreme Economy v2.3'. We've notified the maintainer.

## Contributors

- Rowey (#4317, #4320, #4517, #4515, #4517, #4534, #4532, #4533, #4531, #4528, #4529, #4530, #4547, #4582, #4552, #4588, #4549, #4603, #4322, #4627, #4626, #4657, #4731)
- 4z0t (#4376, #4437, #4472, #4484, #4538)
- Relent0r (#4413, #4417, #4412, #4419, #4435, #4436, #4445, #4447, #4450, #4455, #4462, #4461, #4460, #4454, #4475, #4505, #4682)
- BlackYps (#4247, #4443, #4667, #4673)
- Blodir (#4247)
- Zjonn (#4399)
- MadMax (#4443, #4456, #4469, #4486, #4501, #4501, #4521, #4613, #4622, #4664, #4665, #4694)
- Jip (#4247, 4421, 4386, #4453, #4432, #4444, #4451, #4475, #4426, #4466, #4474, #4483, #4485, #4482, #4492, #4496, #4495, #4489, #4503, #4500, #4512, #4523, #4539, #4540, #4546, #4510, #4536, #4555, #4556, #4557, #4559, #4561, #4560, #4580, #4581, #4585, #4590, #4591, #4596, #4597, #4598, #4599, #4600, #4605, #4586, #4606, #4607, #4577, #4611, #4608, #4587, #4611, #4615, #4617, #4612, #4620, #4623, #4631, #4635, #4634, #4633, #4636, #4640, #4658, #4639, #4639, #4663, #4638, #4558, #4576, #4668, #4669, #4672, #4677, #4675, #4679, #4680, #4569, #4681, #4686, #4689, #4688, #4690, #4691, #4692, #4697, #4699, #4711, #4703, #4712, #4714)
 xXEddieXxx (#4438, #4463)
- speed2 (#4448, #4487, #4488, #4508, #4490)
- hdt80bro (#4471, #4476, #4550, #4513, #4395)
- Yuchenjimmy (#4303, #4604)
- Penguin (#4095, #4491)
- Haifron (#4499, #4526, #4519, #4504, #4593)
- Balthazar (#4479, #4716)
- Senex-x (#4659)
- MostLostNoob (#4669)
- maudlin27 (#4671)
- KionX (3e34599, 9c9dda3, fd41dce, 55ddea)
- BlueAmulet (fd41dce)

At last I'd like to thank Phong for consistently hosting games on the FAF Develop game type. I've watched almost all his games to track down bugs that would otherwise go unnoticed. And my thanks to Prohibitorum for proof reading the changelogs.



A work of art is never finished, merely abandoned

Hello Jip,

this is fantastic news. I didn't think it could be fixed, wow great job.

I understand the attraction of reducing deformity for gameplay sake, but I can't say I am a fan of this.

Having the buildings at different angles is going to make some bases look like a smurf village, the aesthetic should be gritty industrial, not hobbiton.

You will end up with taller buildings like the perimeter system looking like the tower of pizza.

I know the game is not going for hyper-realism, but ask any engineer and they can tell you why building foundations are levelled.

If there was a way to perhaps 'bury' some of the building model in the ground, so that the structure itself is still horizontal, that would be perfect with this.

What about defensive structures and their shooting angle limits?

this also prevents terraforming now?

@black_wriggler said in Developers Iteration I of 2023:

If there was a way to perhaps 'bury' some of the building model in the ground

wouldn't this make some buildings hitboxes harder to hit by weapons?

@mach wouldn't this make some buildings hitboxes harder to hit by weapons?

well looks like this proposal does still form the terrain, just less than currently, having a corner of a structure slightly underneath the level of a slope could be problematic for small buildings perhaps, would require testing

@black_wriggler I think it will look much better with terrain being smooth than some really sharp edges that scream "I'm a 2000s game with bad graphics" Plus less sharp edges might result in better pathfinding so I'm all for this over sharp edges.

FAF Website Developer

@Black_Wriggler / @Melanol / @Mach

The changes are there for you to test and experience on the FAF Develop branch. I highly encourage you to do so and report back with what you find. There are quite some parameters that we can adjust to make it work better for specific units, as an example:

  • Physics.MaxGroundVariation: this is set to 1 for default, but for very high structures we could reduce this to 0.5. The Soothsayer would be a good candidate for this.
  • Physics.StandUpright: this prevents the structure from being tilted

And options that are available for longer units are:

  • Being able to slide them slightly into the ground

Note that the sliding will cause issues for smaller units. Therefore it is only a solution for units higher than, say, a tech 1 radar.

Having the buildings at different angles is going to make some bases look like a smurf village, the aesthetic should be gritty industrial, not hobbiton.

The average map is quite flat, and will still have the same look as before. What this will primarily prevent is large terrain deformations occurring near ramps and slight hills.

On top of that, the average view direction is from top to bottom. A structure being slightly tilted should not be that noticeable.

this also prevents terraforming now?

Terraforming terrain is considered a glitch, see also point 1 and 2 of:

A work of art is never finished, merely abandoned

I've added the second section about performance, see also the second post starting at 'Significant performance improvements'.

A work of art is never finished, merely abandoned

Terraforming comes to Supcom pog

put the xbox units in the game pls u_u

@Jip The new terrain looks awsome great job.

TML is a meme

I guess Physics.MaxGroundVariation 0.5 causes the unit to only tilt half the angle of the ground? Have you tried how setting all structures to a value like 0.5 or 0.8 looks like? I think it would be nice to still keep a hint of a "platform" for the structures. With the new feature it can look kind of wonky sometimes, it deprives the buildings of any sense of weight or heavyness.

Wow I wouldn't have thought terrain deformation was fixable. Very cool.
And Lua continues to be a voodoo language that I refuse to touch.
Good work and all.

@blackyps MaxGroundVariation controls just how much deviation there can be, from edge to edge. This is the value the keeps you from building a factory on the side of mountain, for example.

Why not something like this (assume image is split into image 1, 2, 3 and 4, left to right):
terrain flat.png

How it is

When attempting to build on an incline (figure 1), currently the game finds some average height, plops the building on that height, and proceeds to flatten the terrain around the building (figure 1). This results in these tiny portions of terrain to get extreme angles (red in figure 2), which can prevent further building and/or even prevent units from moving through previously passable terrain.

Currently proposed solution

In figure 3, we can see the 'skew the building to follow the terrain' that has been worked on. As most will agree, it looks odd. But it does fix the problem of not altering the topography.

Maybe this

Figure 4 holds my idea. The idea is you pick the highest edge-point of a structure, and use that as the structure Y position. Rather than highest edge-point, you could also find an average which is heavily biased towards higher-Y points (meaning it will be partially sunk, but mostly 'floating' above the lower parts of the slope). You then add a 'base' to the structure (blue in figure 4), so as it would not look like it floats - kinda like what naval factories do atm, with their 'infinite' legs that go down as deep as need.

Pros are you benefit from 'not altering terrain' while also not skewing the buildings.
A big con is you somehow need to model to 'extend' below it's usual lowest Y value. But I thin that, with diligent work, just extending the base of all non-floaty buildings to go down shouldn't be a big problem. The only problematic buildings are the unit-dispensing ones, where there would be an odd ledge the unit would have to cross - one solution is to just extend the existing ramp to also cover negative Y space, but it might look awkward if the ramp is on a similar angle as the terrain (it might extend like 3 unit widths away from it's usual terminating point, which would look like it's going under other buildings).

Honestly, as a mod this feature would be neat, but as the main FAF branch? I would hate it. So what if it screams "I'm from 2000". One of my favorite parts about FAF is how it improves the quality of life while maintaining the visual fidelity and core gameplay integrity from SC:FA. To make this change would ruin that visual fidelity to me and honestly change so many little things about this game, like attack angles of PD and such. I just don't see this being the best way forward aesthetically for FAF. I liked how I could still make cool, level city-esc bases while still being effective for war. But honestly I would rather see this as a modification or separate branch for FAF because I love the visuals that it has maintained since the original game. You could argue that they've made many visual changes over the years, but those changes at least fit the SupCom feel for the most part.

Do people realize that this won't affect how 95% of structures look? They will be placed on flat ground anyways and will look the same. On the other hand this could reward creative placement of point defense

put the xbox units in the game pls u_u

@BlackYps As Sprouto describes: it is the maximum height difference over the build skirt. Tech 1 power generators are small, therefore the maximum angle would be larger. Factories are large, maximum angle would be smaller. I'm sure this can be computed using trigonometry.

@Fichom You propose a solution with a ton of edge cases for something that is an edge case itself. The majority of the terrain is flat - just generate any map and the majority is flat. Look at any competitive map and the majority is flat. It only matters for those moments where you build near or on top of a ramp / hill.

@GoodRaptor See what I wrote to Fichom - the majority of structures placed in a game are completely unchanged.

@Zeldafanboy thank you, finally someone that understands how niche the impact is in practice. Except for the fact that terrain deformations can be a real pain when they happen, and now it becomes virtually impossible to create terrain deformations that negatively impact gameplay.

For those that have worries: please take the time to experiment on the FAF Develop. We can discuss individual cases and adjust parameters if a structure can indeed end up looking silly. Describing hypothetical situations is - with all due respect - not helping anyone, especially as you can just start the FAF Develop game type as described in the first post:

With all of that said - I'm eagerly looking for a few representative lobbies to play on FAF Develop. I've seen a few replays of the past week and they feel a lot smoother performance wise - but they weren't exactly representative. It also helps a lot with testing the stability 🙂

A work of art is never finished, merely abandoned