I think Cleanrot Knight is the final mob cum boss I'll be looking at in this series. There are a few more bosses that go the other way, being primarily bosses that appear as mobs later on, but that's not exactly the same.

(How do I tell the difference? There's no single authoritative answer, and it's possible that this guy was first designed as a boss and only ended up sprinkled around as mobs later on. But the low health of the bosses and the fact that the mobs are found as early as Caelid both make me personally think of this as a mob first and foremost.)

You might think that would mean that it had simplistic AI, but that's actually not the case. There are two variants of this knight, one wielding a spear and one wielding a sickle. (The "sickle" is actually a scythe, but the boss name says "(Sickle)" so that's what I use in the combo chart.) While neither matches the complexity of the major story bosses we've looked at, the spear-wielder in particular has some reasonably interesting logic:


Cleanrot Knight (Spear) combo chart

The coolest thing going on here is definitely that little rectangle that say "Spear Guard". This may look like a single move, but it's much more than that under the covers. Under certain circumstances, which I'll get into in a bit, the knight will cross its spear and sword in front of its chest to block incoming attacks. This puts it into a special "guarding" state unique to this enemy which switches its logic into a totally different mode.

While it's guarding, the knight has access to different moves and reacts differently to attacks. For ease of reading I've represented this out in the combo chart to combos that come off the "Spear Guard" move, but in practice they aren't really combos. It's more like it has a new idle state when it's guarding, in which it can move around with special animations that keep up its guard and from which it can initiate new combos.

This is mediated, of course, by a speffectid. This gets set by its guard animation and has a built-in 3.5-second timer so it doesn't guard indefinitely. In practice, though, it will almost always use another attack before that timer runs out, and almost all of the attacks it can do in the guarding state set override its speffectid and send it back to its default state.

What puzzled me for a long time was how it got into the guard state in the first place. The AI fundamentally works by queueing up "subgoals", each of which has its own logic that can queue up more subgoals, eventually bottoming out on telling the NPC to play a certain animation. Some of these subgoals are implemented in easily-readable Lua, but some of them seem to be defined only in the as-yet-undecoded behavior files. Of the latter set, many are clearly things like "run this animation if the player is in a certain position", but others are more opaque.

In the Cleanrot Knight's interrupt logic, I could clearly see that when it got hit with a projectile it queued up a GOAL_COMMON_Guard subgoal, which presumably ran the guard animation. But that's the only reference to guarding I could find anywhere in the AI... or indeed in the definitions of any Lua-implemented common subgoals. So with no better alternative, I started editing the script myself and injecting it into Elden Ring as a mod to do some empirical testing of how it actually guarded.

I quickly determined that it could indeed enter the guarding state without being shot, but if I deleted all its explicit logic it wouldn't do so. It had to be there somewhere, so I did a binary search: I disabled half the logic and checked if it still guarded. If it did, I knew whatever triggered the guard must be in the logic that was still on; if not, it must be in the logic I'd disabled. By doing this, I was able to figure out that the GOAL_COMMON_LeaveTarget subgoal was invoking the guard animation.

Exactly how this works, I still don't know. LeaveTarget is one of those opaque subgoals that I can't look at directly. I know there are certain animation IDs which have well-defined meanings across many different NPCs for common things like "stagger when you're hit by a big attack" or "walk to the left". Most NPCs don't have a "put up your guard" animation, but my best guess is that one way or another the logic for LeaveTarget is able to say, "if a guard animation does exist play it before you start retreating."


You must log in to comment.