The first thing I do when I start analyzing the AI of a new boss is try to figure out the meanings of any special effect IDs that the code references.
Aside: Special Effect IDs
For those who are new to this series or just want a reminder, a "special effect ID" is a number that can be attached to a given NPC in any number of ways, either permanently or temporarily. They can have inherent effects like increasing damage resistance or adding a visual effect, but just as often they have no effect at all and are just used to pass signals between different systems like AI, animations, and events.
Most combos work using special effect IDs. Specifically:
-
When an NPC is in an idle state during a battle, the game calls its AI's
Activate()function which chooses an attack animation to run and also sets up observers for some special effect IDs. To use Grafted Scion as an example, when it runs the animation for Shield Slam it observes special effect ID5030. -
The animation runs and the attack is performed. Towards the end of the animation, it hits a frame with an attached
AddSpEffectevent whose ID is5030. -
Because the AI is observing special effect ID
5030, the game runs itsInterrupt()function. This is basically the AI's "thinking on the fly" logic: it'll run even when the NPC is actively doing something, and it can queue up attacks that the AI will combo into. It's a giantifstatement that checks for various conditions, including any special effect IDs that the AI has chosen to observe. -
The
Interrupt()function sees that it was activated because of special effect ID5030and does some positioning checks and random rolls to figure out which attack to combo into (if it wants to keep the combo going at all). It queues up the relevant attack animation (let's say Stab), potentially observing more special effect IDs to combo further. -
The animation hits a command that says "cancel this animation and play the next animation in the combo," and the Stab animation begins playing.
In addition to combos, Special Effect IDs are also commonly referred to in AI code in order to distinguish different classes of enemy or even particular individual instances. It's easier to have a single AI module that describes the logic for all Erdtree Burial Watchdogs with an occasional "if this watchdog has a staff ..." clause than it would be to have a bunch of separate AIs for each separate version. But in order to fully understand what the AI is doing and why, I have to parse this all out.
Usually this is fairly easy. Each NPC ID has its own set of special effect IDs, and these are straightforward to find, so that I can tell "okay ID 17331 means this Erdtree Avatar is actually a Putrid Avatar." Other times a long-lived ID will be set by an attack animation, such as the Grafted Scion's Golden Tempering attack which sets 16265 and checks to ensure it doesn't buff itself while it's already buffed.
But Grafted Scion posed a problem. It was clearly checking for special effect ID 16283, but this ID wasn't set in the NPC ID nor by any animation! It triggered an animation of jumping down from a tall starting point, so I assumed it had to be specific to the Grafted Scion that ambushes you from a Mt. Gelmir cliffside—but knowing wasn't enough. I needed to know how as well if I was going to accurately analyze this and future AIs.
The trick lies in the SpEffectSetParam table. I knew this table existed, I knew it held special effect IDs that were applied to NPCs, and I knew its IDs corresponded roughly to those NPC's IDs. I just kind of assumed that it applied the special effects if the IDs matched and not if they didn't. But this clearly wasn't true for Grafted Scion: 16283 was in the SpEffectSetParam table, in the range that looked like Grafted Scion IDs, but not at all the same ID as the Gelmir Scion.
After trying and failing to find a clear correlation between NPC IDs and SpEffectSetParam IDs in the nest of spreadsheets known as "param data", I consulted with the sages (the denizens of the FromSoft modding discord known as "?ServerName?"). They informed me that indeed the param data could not help me here, and that SpEffectSetParams were assigned exclusively in the maps themselves. Each NPC in the game exists somewhere on a map tile, and its placement there includes not only the NPC ID but a handful of additional metadata... including several SpEffectSetParam IDs which in turn caused attached special effect IDs to that particular NPC.
So I was able to open up DS Map Studio, go visit the Gelmir Scion, and verify that it did indeed have the SpEffectSetParam which gave it special effect ID 16283. But it was obviously not going to be scalable for me to manually find every single boss on the map to figure out which special effect IDs it actually had. It was time to break out the big guns: writing my own code.
Fortunately, the From Software modding and datamining community has a fairly robust ecosystem of open source libraries. After fighting a bit with VSCode and the .NET API, I was able to read in all the map tiles and collate them with the param data to spit out a brand new spreadsheet that told me exactly which special effect IDs were assigned to which NPC IDs through the map data. What's more, I now have a functional skeleton for other scripts in case I need to do more such clever processing in the future.
That leaves only one major question which I still find myself unable to answer: why was this special effect ID set via SpEffectSetParam? Since it's possible to just attach a special effect ID directly to the Gelmir Scion, why bother going through two layers of indirection to do the same thing? In fact, why does SpEffectSetParam exist at all?
It's true that NPC IDs aren't one-to-one with NPCs in the overworld. For example, the two Grafted Scions in Fringefolk Hero's Grave have the same NPC IDs because they have the same stats and difficulty level and so on. So I could imagine that SpEffectSetParam would make it possible to re-use NPC IDs while still having some customization... although it's not clear why this would be more valuable than just creating a new NPC ID.
But even that thin explanation doesn't make sense for Grafted Scion, since—other than the two Fringefolk Scions—each instance of the enemy on the map already has its own unique NPC ID. There are no places where SpEffectSetParam is used for a Grafted Scion where directly setting a special effect ID wouldn't be as easy or easier I am truly baffled, and I suspect the true answer will only ever be known by those who worked on the game themselves.
Combo Chart
The irony of all of this is, after all that, none of the SpEffectSetParams actually affect the combo chart anyway. Technically they do control which Scions can use Golden Tempering, but I decided to just mention that directly in the wiki page rather than trying to fit it into the graph. Without further ado, here's the chart:
The most interesting thing here to me is the Stab attack that forms a kind of nexus to which (almost) all combos are inevitably drawn. I've seen this in some other AIs—a single move that everything combos into and that combos back out into a variety of different actions. It's a relatively low-effort way to give an enemy more combos without them feeling too complex or unpredictable, since they mostly end up flowing the same way in the end. But it certainly makes my job harder trying to flow all those arrows around one another without looking like a total rat's nest!
