Jump to content

AI travel packages when unloaded


SKKmods

Recommended Posts

I am creating spawn points as far as possible from the player datum, but still in the loaded cell area (10K to 15K units). With some complex XYZ calcs (Z navmesh height the hardest) it can take up to 30 seconds to generate 8 intercardinal spawn points.

 

NPCs spawn at those points with AI travel packages that head to the center datum, which was the player location when the spawn points were generated.

 

If the player runs off whilst spawn points are being generated, and happens to head 180 from any one, that point can pop in an unloaded cell and the NPCs PlaceAtMe in unloaded 3D state.

 

If the NPCs started travelling before the unload they keep travelling. If they pop unloaded they dont ever seem to start travelling until the player gets near enough to load cell & NPC 3d.

 

How odd, is this known behavior and any suggestions ?

 

There is no min distance that the player cant outrun with END, and I wont disable controls.

Link to comment
Share on other sites

It looks like Cell Unloaded is not the actual issue, masking a stack of other considerations that a lot of debug logging and watching stuff through a long scope exposes:

 

1. Loaded distance: The CK suggests that the loaded cells are 5x5 @4,096 units around the playerref which is a radius of 10,240 units. I have thousands of measurements of .IsLoaded() and Is3DLoaded() returning true/false boundary from 9K to nearly 16K units (of XY map distance) so that graphics or render bias "loaded" language does not seem appropriate.

 

2.1 Off screen pathing: NPCs will spawn on what .MoveToNearestNavmeshLocation() reports as good navmesh but there may be no clear path, like on roofs or rocks. If the spawn happens within 10K of the player, the NPC will jump down (below a fall height threshold) and start travelling. If the spawn happens over 10K from the player the NPC {may nor may not} freeze until the player gets within 10K units ... then they unfreeze, jump down and start to travel. Occasionally a distant NPC will teleport to within their travel package minradius of the player and start shooting, I have yet to track that edge-case condition (may be stuck, unloaded or just magic).

 

2.2 Off screen combat: NPCs that are hostile to each other will enter into combat mode off screen, but if over 10K from the player that combat {may, or may not} resolve. If it does not resolve the NPCs freeze and resume combat when the player gets within 10K units. Sometimes I can watch it resolve through a long scope at 15K distance, and if the combat produces a death ... see (3) below. When the combat is not observable, some participants can become like Schrodinger's cat returning both alive (.IsInCombat() == true) and dead (.IsDead() == true) statuses until observed by the player, so when you rock up to the area ... that .IsDead() NPC ref is actually alive and kicking and can even be the akKiller source of deferred stream of OnDeath() calls having just killed a bunch of others. I kid you not.

 

Workaround: Since I cant stop the player legging it away from a spawn datum, then wondering where the targets are, and micro-managing the movement and combat of 64 NPCs is a bit much, all I can do is notify the player that hostiles are waiting for them (testing for delta movement of the nearest on an XYZ location hash) with a bearing and distance incase they have hardcore map markers off.

 

3. Off screen Death: what is really sketchy are events like OnHit and OnDeath registering over 10K from the playerref. Mostly they do, but sometimes they just bloody don't, so stuff that is actually dead is still showing as alive in the quest and blocking completion. Oh, and you have live NPCs returning dead status.

 

 

Spawned hostiles are in a quest RefCollAlias which is the source of quest objective markers and the kill completion count. The RefCollAlias has a script that registers member OnDeath() and removes them to stop tracking and completion count. Without OnDeath() they hang around persistent in the RefCollAlias holding the quest and livecounts open.

 

If hostiles die "off screen" more than 10K from the player (IsLoaded && Is3DLoaded still true and death can be seen though a long scope) from hostile on hostile aggro, the quest {may, or may not} (mostly it does) run the script or process OnDeath. Sometimes it seems to batch up and hold the events until the player is within 10K. When the player gets to within 10K a stream of OnDeath() events fire and debug logs record the akKiller NPC ref ... which on several occasions has already traveled to the player and been itself killed in the debug log some time ago. They are clearly historic queued events, from lots of comparing this output:

Debug.Trace ("SKK_Scavenge:" +  ThisRef + " Loaded:" + ThisRef.GetCurrentLocation().IsLoaded() + " 3d:" + ThisRef.Is3DLoaded() + " Combat:" + (ThisRef as Actor).IsInCombat() + " Dead:" + (ThisRef as Actor).IsDead() + " Distance:" + pPlayerRef.GetDistance(ThisRef) )

Debug.Trace( "SKK_OnDeath:" + Alias_HostileLive.GetCount() + " Victim:" + akVictimRef + " Killer:" + akKiller + " Loaded:" + akVictimRef.GetCurrentLocation().IsLoaded() + " 3d:" + akVictimRef.Is3DLoaded() + " Distance:" + pPlayerRef.GetDistance(akVictimRef) )

Workarounds: If I remove the local color and activity of hostile on hostile aggro and player turrets, the issue is totally avoided, but doesn't provide the quality of experience I am after. LOL yeah right, quality. A timed scavenge function that iterates NPCs to test .IsDead() && distance to force reference removal from the quest is what I am going with, but doing a core platform event job in an application scripting layer is not a good sign for stability.


Net net of this is that the 10K unit distance "loaded" radius looks more like a safe or reliable event and NPC activity processing radius. The render functions IsLoaded() or Is3dLoaded() CAN NOT BE USED FOR THIS BEHAVIOR DETECTION, they report on graphics state.

 

 

Trying to repurpose a quest based RPG platform as a real-time combat simulator may be a fools errand better served by the unrealengine, but I love the art and would be a shame to let the potential of the Fallout4 world go to waste.

 

 

PS I am trying to work out the relationship between the various units of measure. As an index, the longest shot I have recorded in event logging of > 1000 kills with a 200/230 unit range weapon is OnHit() 9,920 & OnDeath() 10,017 of XYZ units ... it's that magic 10K again.

Edited by SKK50
Link to comment
Share on other sites

This is one of the most interesting threads I've read in awhile. You've gone way beyond what I did with Scavver and I think your observations will be essential reading for anyone who creates NPCs. Maybe this should all go in the CK wiki too. (Discussion tabs?) Because sooner or later, anyone who tries to make NPCs with advanced behavior will run into the problem of what NPC should do when the player travels away and the cell unloads.

 

Edit: I found an old Scavver test video. Timestamps in description: https://youtu.be/uWDzMrUTK94

Link to comment
Share on other sites

Appreciate the kind words and yes I can publish this stuff in the CK, once it is validated by someone else. There is too much not quite right misdirection sloshing around, so I want to be sure my observations are not just local to me | my code | my config.

 

If you have the opportunity can you follow your scavver and check if behavior changes when you are over & under 10K units ? A long scope is good, recon scopes seem to fill the log with spam.

Edited by SKK50
Link to comment
Share on other sites

It seems that 10K distance {may nor may not} condition may be related to player HasDirectLOS(), so the NPC event behavior variables I'm working with are:

 

In a loaded cell { yes | no } = AI travel package to a loaded cell won't always start when spawning unloaded (dunno about unloaded to unloaded). Could be package or pathing issue.

 

3D loaded { yes | no } = dunno if this has any causal or symptomatic links yet.

 

In player line of sight { yes | no } = pathing and combat events resolve in LOS, or freeze if out of LOS and over 10K

 

More than 10K XY units from player { yes | no } = pathing and combat events resolve within 10K, or freeze if out of LOS and over 10K.

 

In combat { yes | no } = npc can report dead & alive (you spin me right round, baby) if in combat over 10K and out of LOS.

Link to comment
Share on other sites

  • 3 weeks later...

For thread consistency ... more simulations on distant event resolution, that is player hits and npc on npc aggro to see how far out event processing is observable.

A. Create a hitscan beam behavior projectile and weapon receiver with range and speed of 25,000 which is the highest vanilla projectile value (reported in Pipboy/Workbench as 1,361), debug log player OnHit target distances, then learn how to shoot without leading the target :-)

B. Vary uGridsToLoad in Fallout4Prefs.ini (default 5, radius based on 4,096 cell size) to render scenery and spawned NPC targets.

C. Using the longest pathed line of sight tohand: from the top of the V111 control hut to a datum crate and turrets on the far side of sanctuary bridge 16,000 distance (delta Z height 1.6K). Turrets are hostile/aggressive/confident to engage all spawned NPCs within an aggro radus of 2,048 which should be 18K from player.

D. Spawn hostiles 5k to 10k distance from datum, but always in a loaded cell location. Furthest will be 26K from player.


5 uGridsToLoad (Player radius 10,240) Max NPC render & OnHit 12.4K Datum @16K turrets do not render and no off screen engagement. Npc pathing doesnt use unrendered sanctuary bridge to travel.

7 uGridsToLoad (Player radius 14,336) Max NPC render & OnHit 18.7K Datum @16K turrets do not engage NPCs until they walk past the turrets and get within 14K (uGridsToLoad radius) of the player.

9 uGridsToLoad (Player radius 18,432)ÃÂ Max NPC render & OnHit 18.9K Datum @16K turrets engage NPCs at 18K

11 uGridsToLoad (Player radius 22,528) Max NPC render & OnHit 22.9K Datum @16K turrets engage NPCs at 18K

15 uGridsToLoad (Player radius 30,720)ÃÂ Max NPC render & OnHit 23K Datum @16K turrets engage NPCs at 18K

17 uGridsToLoad (Player radius 34,816) Max NPC render & OnHit 23K Datum @16K turrets engage NPCs at 18K


Stopped at uGridsToLoad 17 with stackdumps in the log suggesting resource limits: Count of suspended stacks is over our warning threshold, dumping stacks: MasterAmbushActorScript [vanilla & my debug] .Actor.Is3DLoaded()

Also rather difficult to find a line of sight that will render over 23K and actually hit without work on weapon aim and zoom models. If you got something that will hit past 25K, do share.

So what, and why should you care ? I'm publishing incase you are the one other person in the whole world trying to manage off screen NPC interactions in Fallout4, else you probably don't ... but thanks for reading. My words in pictures:

 

Edited by SKK50
Link to comment
Share on other sites

Shame that they are cheat shots. I despise hitscan mechanic, but if configured as missile with a realistic speed and gravity drop it takes forever (actually I gave up) to land a moving target onhit at 23k.

Edited by SKK50
Link to comment
Share on other sites

I have observed NPCs in the distance, notably around the 1st and 2nd unloaded cells (10-18k out) doing some strange things. But this right here is the most comprehensive test of the internals I've seen so far, kudos to you.

Mostly I observed them patrolling, without animation (basically hovering along and through LOD objects/terrain. Sometimes I see weapon effects and just plain still NPCs standing there in a paused animation.

I make use of OnDeath and OnKill events to increment scores in my Turf Wars system, but apart from that, dead or alive the actors will be forced to cleanup after a timer has expired on their originating spawn point. I keep up to 4 accumulated arrays on each SpawnPoint as each one can potentially roll out 4 groups.

AI was never going to be hugely special, I simply emulate the patrol packages via the random travel package on the main system with a guard or sandbox when they reach a location, or otherwise use guard and sandbox packages for other systems.

Im gonna have a dig through the Exe and see if there's not a related setting for this. I doubt it but it's worth a look.

 

EDIT: Obviously there is this setting in FalloutPRefs: fLODFadeOutMultActors. Ultra it is on 15. I'm wondering if the actual value is 1000, so x15 = 15,000. I wonder if it is worth setting to 20 or 25 to try and mitigate your issue, but if so it comes with the downside of Actors being loaded far out in general.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...