Dev Journal #30: AI and Loot
https://store.steampowered.com/news/app/3796960/view/680752246528410056I really couldn’t think of a good theme for this week’s journal entry. There’s a bunch of things we’re working on simultaneously so let’s tackle them in no particular order.

General polish and bug fixing
Bringing Elemental to the modern age has been pretty challenging to say the least. It wasn’t just a port to 64-bit, but also a complete rewrite of the underlying graphics engine (even the 3D model system was completely replaced – havok to FBX) as well as the underlying data system to support non-English characters. Combined, in a game this big (and it is a really, really big game) you end up with endless edge cases. Thank goodness the tools today are so much better than what they used to be. Let me show you what that looks like below:
From Crash to Cure: Our Bug-Hunting Process
Let me give you a case in point: Tactical battle, player running the Japanese version of the game mouses over an Altarian tactical ability called Rush. That tooltip is translated but the control for it is expecting a CHAR (8 bit) and boom crash. And it’s just that one tooltip, not “the tooltip system”. Luckily, with the tools we have we can see these. But it’s still really unfortunate that this wasn’t found before release.
AI players
The AI in Reforged is much better than the AI in War of Magic and Fallen Enchantress. But we want to make it much better. The issue is fairly straight forward – the snowball effect. Your character and champions get extremely powerful. Stacks of doom are nothing new to the genre but Elemental kind of does a “Heh, stack of doom? Hold my beer, I’ll show you a stack of doom.”
So the player just ends up steamrolling the AI opponents one by one. So we are working on improving how the AI reacts to a runaway player.
The goal is not to create an automatic "everyone declares war on you" system. That would be blunt and annoying. Instead, we are making the existing diplomacy system more aware of what is happening.
If the human player is in first place and starts attacking another major faction, nearby AI players will begin to take that seriously. If you are attacking a Kingdom, other Kingdoms will be more likely to sour on you. If you are attacking an Empire, other Empires will react similarly. Kingdoms in particular will show more solidarity with each other.
This pressure builds over time. Every so many turns that you remain at war while leading the world, diplomatic penalties increase. Capturing cities will matter too. Distance still matters: an AI on the other side of the world should not declare war just because it heard you were being a menace somewhere over the horizon. That looks silly, and we try to reserve silly for intentional features.
We are also making sure the system understands who started the war. If the AI attacks you, you should not be punished as if you were the aggressor. That required some new tracking so the game knows which active wars the player actually started.
On higher difficulties, we also want the AI to be more capable of backing up its diplomacy. If the player is rolling around with a stack of doom, the AI needs to build stronger armies, defend better, and attack player cities more aggressively where appropriate.
The intended result is simple: if you become the dominant power and start conquering the world, the world should notice. Not instantly. Not unfairly. But enough that victory feels earned rather than inevitable.
I am hoping we can get this into v1.2.
Loot Tables
Another big change is the implementation of actual loot tables.

So in our current system, when a unit dies, it drops an item and many times these items are simply dropped based on rarity. But what is common a Balrog is not common for a goblin, so to speak.
You probably noticed in 1.1 that the loot got a lot better and more interesting. This was because we did a poor man’s version of this by actually specifying, by creature, what they dropped. This worked reasonably well, but the downside was that it was incredibly labor intensive for us to do and on top of that, some creatures would end up as pinatas (looking at you, ghouls).
So here’s how that works:
A loot table is a list of possible items. Each item can have a weight, which controls how likely it is to be picked. Higher weight means it comes up more often.
Entries can also be gated by SpawnRating. SpawnRating is basically the game's rough measure of how dangerous or advanced the source is. A weak monster can be limited to weak, scrappy loot. A serious monster can unlock better entries from the same general table.
So a table can say:
-
Dead rats are fine for very low-level creatures.
-
Wolf pelts are fine for early monsters.
-
Demon horns should only appear from stronger monsters.
-
Dragon eyes should only come from things that are actually in dragon territory, power-wise.
What Designers Use A treasure reward can now use:
xml
<GameModifier>
<ModType>GiveLootTable</ModType>
<Attribute>GoblinLoot</Attribute>
</GameModifier>
The important part is GoblinLoot. That name points to a table in LootTables.xml.
A table entry can include:
-
Item: the item that can drop.
-
Weight: how likely it is compared to the other entries.
-
MinSpawnRating: the weakest source allowed to drop it.
-
MaxSpawnRating: the strongest source allowed to drop it.
-
Count: how many to give, if it should give more than one.
-
RarityDisplay: an optional extra rarity filter.
So why is this better?
The old rarity-only system answered one question: "How rare is this?"
The loot table system answers two better questions:
-
What kind of thing dropped this?
-
How strong was that thing?
That gives us more control with less hackery. Goblins can drop goblin-appropriate junk. Big monsters can drop big-monster loot. And when we want a special case, we can make a named table for it instead of trying to smuggle design intent through the word "Common."
And this should be in v1.2, also.