CreatorsOk
Yui
Yui

patreon


[Update] Dark Souls 2: Seamless Co-op - Enemy AI debugging

Hi everyone

I wanted to give an update that leads on from the post previously when I was talking about the challenges of implementing game-wide enemy AI synchronisation between game clients, something that is uniquely challenging in Dark Souls II

The problem

Enemy AI is implemented (in my opinion) poorly in Dark Souls II.

I still strongly believe this is the case, even more so after this week.

In Dark Souls II, there is a list of enemy control flags stored in a map:

std::map<uint16_t, NetworkEnemyInstance>

When an enemy is loaded in and referenced, it will perform a lookup inside NetEnemyManager for the NetworkEnemyInstance relating to that specific enemy (using the enemy's unique ID (stored as a 2-byte value).

If the enemy is not listed, the NetworkEnemyInstance points to your own character ID as the owner, or zeroth bit of the enemy control byte is set to false, then the player's local game client will control the enemy and send packets to other game clients telling them what the enemy is doing. Otherwise, it will disable the enemy's AI and wait for incoming data from the user who is in control.

This makes sense for the vanilla game, however the issue is that the map is generated only once when the map is loaded and never refreshed. Meaning unloading the area will leave references to NetworkEnemyInstance where the memory has already been freed (causing crashes), and moving to a new area will not add the new enemies that load into the map to the list causing significant desync.

The solution

The past week I've been brainstorming how to get around this issue in the least restrictive way possible.

In the vanilla game, only one instance of NetEnemyManager exists, which makes sense since in a multiplayer instance you cannot move between maps without ending and refreshing the session.

In seamless, I have created a list of dynamic instances of NetEnemyManager. This means that when a map loads, a new NetEnemyManager will be created and populated for that specific map, then when it unloads it will be destructed. Whist this might seem like a very easy solution, implementing it was another matter as I had to completely reverse engineer this class which took a couple of days.

Where the game would normally call the main controller for NetEnemyManager, I instead have it iterate over the available mod-based instances and they will populate & run according to the load state of the map.

I don't know how to do code snippets on Patreon

Whilst I'm still testing and debugging it, it looks very promising as I can now pass between maps in a multiplayer session and no longer have enemy desyncs or any crashes at all.

Further development involves me fixing enemy damage networking. In the vanilla game, if the enemy isn't nearby then enemy damage packets will be ignored (in the other Dark Souls games, this worked flawlessly out of the box)

As always - thank you for your patience and a huge thank you to all of my supporters <3

Once I get the enemy AI fully ironed out, I will start (finally) trying to create a teaser video / official announcement for the mod on my YouTube channel.

Take care

~ Yui

[Update] Dark Souls 2: Seamless Co-op - Enemy AI debugging

Comments

I guess it's only right that solutions to this stuff would be obscure and strange in DS2. Thank you for your wonderful work- we're all so excited!

RolandReturns

Can’t wait me and my buddy cant contain our excitement I hope it comes soon😸😸😽😽🫶🫶

Darkest hour S


More Models and Creators