PJMail Posted September 8, 2023 Share Posted September 8, 2023 I have a persistent, unique, essential NPC that will 'occasionally' revert back to wearing their default gear (their new gear is still in their inventory). VERY occasionally they will completely reset body as well (changing sex and loosing all added inventory). Their FormId DOES NOT change. Happens on 3D reload (after an unload) - but only very occasionally. I can't tell if it happens on the unload part as you can't check the NPC's equipped items when 3D unloaded. I cannot work out the circumstances, but using MoveTo on the NPC, and the player fast traveling (between locations far from the NPC), seems to aggravate it - which is nonsensical... i.e. 1) Send NPC from Cell "A" (NPC.moveto) to some far away cell "B". NPC 3D unloads.2) Player fast travels from Cell "A" to a different far away cell "C"3) Move NPC back to Cell "C" - NPC 3D loads and 'occasionally' has reset. If you don't do 2) (move the player) and just move the NPC back to "A" it does NOT reset.Also if you instead fast travel the player to cell "C" (where the NPC is) they will NOT reset. Clearly there is another factor involved but I can't see what it is. Does anyone have any ideas? NOTE: there is no Additem/equipitem operations occurring on the NPC - so not that known bug. The NPC is linked to a settlement (via a linkedref) but has no scripts on it (it is not a settler).It is however created partially from a settler template (where it gets it's outfit and body from). The cell "B" it is moved to is normally (random) wilderness - so could have any settings - is that important? Thanks for any clues. Link to comment Share on other sites More sharing options...
PJMail Posted September 8, 2023 Author Share Posted September 8, 2023 I tried putting the NPC in a holding cell when they unload. This reduced the incidence.HOWEVER - if the player fast traveled while the NPC is in the holding Cell then when they are moved back to the player they are reset!If the Player does not fast travel then they come back correctly equipped. This makes no sense. Link to comment Share on other sites More sharing options...
LarannKiar Posted September 8, 2023 Share Posted September 8, 2023 (edited) So you mean you place (in the editor) or spawn a templated Unique actor with PlaceAtMe(), or PlaceActorAtMe() or Quest >> Quest Alias >> Create Ref, then they get reset on certain 3D load events? The cause of this issue is can be that the game doesn't save their created actor template data. Without that, the engine will always render the NPC based on their editor-set ActorBase data. To avoid triggering this bug, you can try setting up the actor like this: - Unique actor (not actually necessary, the game keeps an array of struct of unique NPC data (e.g., unique actor's RefID) probably for the Story Manager to be able to find them without their ActorReference being persistent; it's not always able to find them though..) - non-Templated (so that the system can't bug out by "forgetting" to lock the NPC; without saving the created actor template data (contains the actual appearance of the actor), the game will always create a new one for them, causing them to get "reset") - spawn them in an interior cell (interior cell data is kept in the memory all the time unlike exterior cell data; cell data seems to contain certain object rereference data.. I'm not sure what it contains, but the engine won't necessarily create a template for an ActorBase on 3D load if there's already a template for the actor in the memory; it can also be part of the cell buffer data as that keeps all kinds of cell related data.. maybe that's why your testing results were different based on traveling between cells; Disable()-Enable() causes the game to create a new template) - interior cell should be part of a Location (Unique actor data is part of the (their Editor) Location data) - use a "Never Resets" Encounter Zone for the location (as CellReset (which is based on the layers of Encounter Zone >> Location >> Cell) can be a bit buggy sometimes) Actor inventory seems to become "locked" (flagged as "not to reset") if you trade items with the actor through the inventory menu ("ContainerMenu"). Normally, it won't be reset unless the NPC gets reset. (For example, if you have a NPC like a settler whose equip data or inventory data keeps resetting, equipping some items on them through the menu may lock their inventory). Edited September 8, 2023 by LarannKiar Link to comment Share on other sites More sharing options...
PJMail Posted September 8, 2023 Author Share Posted September 8, 2023 Thank you LarannKiar for you detailed explanation. Seems like I have been doing everything wrong. I suppose I brought this on myself by effectively turning my 'dummy' NPC (that was always temporary and random - like a settler) into one you could equip with your own gear. Now people expect it to stay the way they equipped them (rightly so). I couple of questions if you don't mind - - When you say non-templated, are you saying any templated bits will cause a reset? I have only the body (Traits and Stats) templated as I wanted them to have a random sex and look - yet occasionally the inventory will reset too (which is worse). - How would yet set up this 'interior' creation cell to not reset? I have looked at many other interior holding cells (including Bethesda ones) and they seem to leave the encounter zone field blank. As there is no "no reset" flag on interior cells (or locations) I assume this is equivolent to a 'no reset' encounter zone? No holding cell I have looked at uses the "NoResetZone" encounter zone - so I assumed it was ok just to leave it blank. Link to comment Share on other sites More sharing options...
PJMail Posted September 9, 2023 Author Share Posted September 9, 2023 Mmm. I seem to have made it worse be creating the NPC in an internal Cell (rather than a settlement)... Link to comment Share on other sites More sharing options...
LarannKiar Posted September 9, 2023 Share Posted September 9, 2023 (edited) - When you say non-templated, are you saying any templated bits will cause a reset? I have only the body (Traits and Stats) templated as I wanted them to have a random sex and look - yet occasionally the inventory will reset too (which is worse). I forgot to mention that actor inventory gets reset on CellReset if their inventory contains LeveledItems as Outfit or Inventory items so make sure to add actual forms to their inventory in the editor. - How would yet set up this 'interior' creation cell to not reset? I have looked at many other interior holding cells (including Bethesda ones) and they seem to leave the encounter zone field blank. As there is no "no reset" flag on interior cells (or locations) I assume this is equivolent to a 'no reset' encounter zone? No holding cell I have looked at uses the "NoResetZone" encounter zone - so I assumed it was ok just to leave it blank. If you fast traveled between cells and the actors' inventory and facial data got reset then it's probably not a CellReset issue but an actor template one. I've had some (occasional) issues with resetting templated actors in the past and I don't why but placing or spawning them in Never Resets cells fixed those reset bugs for me. Honestly, I rarely place/spawn actors in Never Resets cells because I rarely use (Traits) templated actors. Few years ago I run a few CellReset and inventory tests but now that I made some F4SE plugins I rerun the tests.. Here's what I did: - Created 3 Interior Cells: - cell A), "plain" interior, No Location or Encounter Zone - cell B), has a Location whose Encounter Zone is "Never Resets" - cell B), has a "Never Resets" Encounter Zone - Editor-placed the same (about 20) actors in each cell: - most actors had LeveledItems in their inventory (for both Inventory items and Outfit) while some of them had editor-set ("fixed") inventory items and Outfit (which had exact, non-LeveledItem Armors) - certain actors had only a Default Template - certain actors had only FaceTemplate (Actor >> Template >> Traits) - certain actors had only StatsTemplate - certain actors had only InventoryTemplate - certain actors had only KeywordTemplate - certain actors had their Actor flags >> "Respawn" set - Traveled between the 3 cells with a cleared CellBuffer (console command PCB) - the FindActors() function I used from the function library acquires actors from the game's actor table which is actually worldmap based (e.g., the distance between an actor at Sanctuary Hills and another in the Root cellar can even be below 100 game units). - in other words, it ignores interior - exterior cell distance (which is practially infinite with the vanilla GetDistance() function). - I added an ai3DLoadedState parameter to the function to support a GetDistance()-like actor search but CellBuffer seem to keep loaded 3D data in the memory (as if they were rendered but they don't) so purging the CellBuffer is mandatory otherwise FindActors() could have found actors from the player's previous parent cell - Equipped an armor on them (Trade) in the actor inventory menu ("ContainerMenu") - cell A) actors: Baseball Uniform - cell B) actors: Greaser Jacket and Jeans - cell C) actors: Courser Uniform - left everything in their inventory - Fast traveled away to an exterior cell; performed a global CellReset with sped up timescale and the console commands "SetGS iHoursToRespawnCell 1" and "SetGS iHoursToRespawnCellCleared 1" (in case the parent location of cell B) was "Cleared" but actually it wasn't) - this made cell A) reset; cell B) and cell C) didn't get reset (tested it with taken respawnable items (e.g., Purified Water) placed in each cell: in cell A) they respawned, in cell B) and cell C) they didn't) - Used a while loop to output the actors' data (I forgot about to include IsEquipped in the function library's inventory item handlers... so that's not in the output but equipped armors were pretty much visible anyway) - Run the tests with the actors being Persistent and non-Persistent - (unfortunately SetTemporary() is currently not in the script extender and I didn't run the tests with the temporary flag but I doubt that would have any effect on inventory or equip data) The results: - first of all, persistency didn't affect the results - different template flags (e.g., with/without Default Template, FaceTemplate, KeywordTemplate, etc.) didn't affect the results either - Respawn flag didn't matter either (that flag is used by the CellReset by the way: on CellReset, if the actor is dead and Respawn is not set, the game marks them Deleted (console [D]) and skips rendering them) - all actors who had LeveledItems in their inventory: inventory and equip data got reset on CellReset - however, those actors that I equipped an armor on in the inventory menu: inventory and equip data remained the same - all actors who had fixed (not leveled) items and outfit in their inventory: inventory and equip data did not get reset on CellReset - equipping an armor on them didn't change this - appearance never got reset - note: I didn't use LeveledCharacters (LChar) as FaceTemplates; in that case the game would have created a temporary ActorBase form ("leveled actor base" whose BaseID starts with FF) with a randomly picked face from the LChar and (unless a bug occurs) linked it to the actor; I used an actual actor for each template. Here's some actor data from the output: Actor in cell A) who has checked Respawn flag and only a FaceTemplate. Before CellReset: [09/09/2023 - 03:24:11AM] +++++++++++++ [09/09/2023 - 03:24:11AM] FindAll :: looping :: LoopActor [Actor: [Actor < (3B000FCA)>]]. [DisplayName: Test_TemplTraits_Respawn]. [ActorBase: [ActorBase < (3B000FC6)>]]. [ActorBaseName: Test_TemplTraits_Respawn]. [LeveledActorBase: [ActorBase < (3B000FC6)>]]. [LeveledActorBaseName: Test_TemplTraits_Respawn]. [FaceTemplate: [ActorBase < (00113346)>]]. [FaceTemplateName: Settler]... [09/09/2023 - 03:24:11AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0xaf0e2] | Index: [0] | Count: [1] | Name: [Road Leathers]. [09/09/2023 - 03:24:11AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0x34595] | Index: [1] | Count: [1] | Name: [Radstag Hide Outfit]. [09/09/2023 - 03:24:11AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0x24f55] | Index: [2] | Count: [1] | Name: [Pipe Pistol]*. [09/09/2023 - 03:24:11AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0x4ce87] | Index: [3] | Count: [12] | Name: [.38 Round]. [09/09/2023 - 03:24:11AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0xf] | Index: [4] | Count: [9] | Name: [Bottlecap]. [09/09/2023 - 03:24:11AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0xa] | Index: [5] | Count: [1] | Name: [Bobby Pin]. [09/09/2023 - 03:24:11AM] [Test_TemplTraits_Respawn | 0x3b000fca] has [6] different items in her inventory of which [1] appear to have an ingame modified (override) name. After CellReset: [09/09/2023 - 03:27:42AM] +++++++++++++ [09/09/2023 - 03:27:42AM] FindAll :: looping :: LoopActor [Actor: [Actor < (3B000FCA)>]]. [DisplayName: Test_TemplTraits_Respawn]. [ActorBase: [ActorBase < (3B000FC6)>]]. [ActorBaseName: Test_TemplTraits_Respawn]. [LeveledActorBase: [ActorBase < (3B000FC6)>]]. [LeveledActorBaseName: Test_TemplTraits_Respawn]. [FaceTemplate: [ActorBase < (00113346)>]]. [FaceTemplateName: Settler]... [09/09/2023 - 03:27:42AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0xaf0e2] | Index: [0] | Count: [1] | Name: [Road Leathers]. [09/09/2023 - 03:27:42AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0x732ac] | Index: [1] | Count: [1] | Name: [Explorer Outfit]. [09/09/2023 - 03:27:42AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0x1f9793] | Index: [2] | Count: [1] | Name: [Dirty Postman Hat]. [09/09/2023 - 03:27:42AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0x24f55] | Index: [3] | Count: [1] | Name: [Pipe Pistol]*. [09/09/2023 - 03:27:42AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0x4ce87] | Index: [4] | Count: [12] | Name: [.38 Round]. [09/09/2023 - 03:27:42AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0xf] | Index: [5] | Count: [7] | Name: [Bottlecap]. [09/09/2023 - 03:27:42AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0xa] | Index: [6] | Count: [1] | Name: [Bobby Pin]. [09/09/2023 - 03:27:42AM] [Test_TemplTraits_Respawn | 0x3b000fca] has [7] different items in her inventory of which [1] appear to have an ingame modified (override) name. After CellReset, equipped a Baseball Uniform on them: [09/09/2023 - 03:35:29AM] +++++++++++++ [09/09/2023 - 03:35:29AM] FindAll :: looping :: LoopActor [Actor: [Actor < (3B000FCA)>]]. [DisplayName: Test_TemplTraits_Respawn]. [ActorBase: [ActorBase < (3B000FC6)>]]. [ActorBaseName: Test_TemplTraits_Respawn]. [LeveledActorBase: [ActorBase < (3B000FC6)>]]. [LeveledActorBaseName: Test_TemplTraits_Respawn]. [FaceTemplate: [ActorBase < (00113346)>]]. [FaceTemplateName: Settler]... [09/09/2023 - 03:35:29AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0xaf0e2] | Index: [0] | Count: [1] | Name: [Road Leathers]. [09/09/2023 - 03:35:29AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0x732ac] | Index: [1] | Count: [1] | Name: [Explorer Outfit]. [09/09/2023 - 03:35:29AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0x1f9793] | Index: [2] | Count: [1] | Name: [Dirty Postman Hat]. [09/09/2023 - 03:35:29AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0x24f55] | Index: [3] | Count: [1] | Name: [Pipe Pistol]*. [09/09/2023 - 03:35:29AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0x4ce87] | Index: [4] | Count: [12] | Name: [.38 Round]. [09/09/2023 - 03:35:29AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0xf] | Index: [5] | Count: [7] | Name: [Bottlecap]. [09/09/2023 - 03:35:29AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0xa] | Index: [6] | Count: [1] | Name: [Bobby Pin]. [09/09/2023 - 03:35:29AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0xd981d] | Index: [7] | Count: [1] | Name: [Tarberry]. [09/09/2023 - 03:35:29AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0x144f03] | Index: [8] | Count: [1] | Name: [Baseball Uniform]. [09/09/2023 - 03:35:29AM] [Test_TemplTraits_Respawn | 0x3b000fca] has [9] different items in her inventory of which [1] appear to have an ingame modified (override) name. After equipping a Baseball Uniform on them, I fast traveled away, performed another CellReset, traveled back: [09/09/2023 - 03:46:19AM] +++++++++++++ [09/09/2023 - 03:46:20AM] FindAll :: looping :: LoopActor [Actor: [Actor < (3B000FCA)>]]. [DisplayName: Test_TemplTraits_Respawn]. [ActorBase: [ActorBase < (3B000FC6)>]]. [ActorBaseName: Test_TemplTraits_Respawn]. [LeveledActorBase: [ActorBase < (3B000FC6)>]]. [LeveledActorBaseName: Test_TemplTraits_Respawn]. [FaceTemplate: [ActorBase < (00113346)>]]. [FaceTemplateName: Settler]... [09/09/2023 - 03:46:20AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0xaf0e2] | Index: [0] | Count: [1] | Name: [Road Leathers]. [09/09/2023 - 03:46:20AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0x732ac] | Index: [1] | Count: [1] | Name: [Explorer Outfit]. [09/09/2023 - 03:46:20AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0x1f9793] | Index: [2] | Count: [1] | Name: [Dirty Postman Hat]. [09/09/2023 - 03:46:20AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0x24f55] | Index: [3] | Count: [1] | Name: [Pipe Pistol]*. [09/09/2023 - 03:46:20AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0x4ce87] | Index: [4] | Count: [12] | Name: [.38 Round]. [09/09/2023 - 03:46:20AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0xf] | Index: [5] | Count: [7] | Name: [Bottlecap]. [09/09/2023 - 03:46:20AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0xa] | Index: [6] | Count: [1] | Name: [Bobby Pin]. [09/09/2023 - 03:46:20AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0xd981d] | Index: [7] | Count: [1] | Name: [Tarberry]. [09/09/2023 - 03:46:20AM] PrintInventoryInfo :: looping :: InventoryItem :: | FormID: [0x144f03] | Index: [8] | Count: [1] | Name: [Baseball Uniform]. [09/09/2023 - 03:46:20AM] [Test_TemplTraits_Respawn | 0x3b000fca] has [9] different items in her inventory of which [1] appear to have an ingame modified (override) name. Edited September 9, 2023 by LarannKiar Link to comment Share on other sites More sharing options...
PJMail Posted September 9, 2023 Author Share Posted September 9, 2023 That is very comprehensive and needs to be noted somewhere - if not on one of the user created wiki's then at least on the mod author's discord. A last question: - You said "I didn't use LeveledCharacters (LChar) as FaceTemplates;...".I do because I want random Sex and face (and I assume this is the only way to get it) - does this change anything?You suggested not (unless there is a game bug) but a temporary (FF) Actorbase will be created. Oh, and I tried creating the actor via PlaceActorAtMe with the 'NoReset' Encounter Zone - had no effect. Link to comment Share on other sites More sharing options...
LarannKiar Posted September 9, 2023 Share Posted September 9, 2023 (edited) - You said "I didn't use LeveledCharacters (LChar) as FaceTemplates;...".I do because I want random Sex and face (and I assume this is the only way to get it) - does this change anything?You suggested not (unless there is a game bug) but a temporary (FF) Actorbase will be created. Oh, and I tried creating the actor via PlaceActorAtMe with the 'NoReset' Encounter Zone - had no effect. Normally it shouldn't matter because the game shouldn't create new templates for already 3D initialized actors. I'm still not sure why it happens to you. Settlers also use LChars but they don't get reset. I assume it has to do something with the EditorLocation that's why I suggested a Never Resets zone. I haven't deleted the test mod so I may rerun the tests later with LChars.. Yes, in the vanilla game LChars are the only way to get randomized Traits. Edited September 9, 2023 by LarannKiar Link to comment Share on other sites More sharing options...
PJMail Posted September 10, 2023 Author Share Posted September 10, 2023 Well, this is so buggy. I make sure NPC is created (PlaceActorAtMe()) in an interior cell with noreset, and I have removed any Leveled inventory items.Doing a NPC.GetEncounterzone() returns the expected EZ for the interior Cell.Note - Traits are still templated via a Lchar. UNFORTUNATELY When I create the NPC it still resets on unload, even if I transfer and equip a new outfit via script.HOWEVER, if I manually transfer and equip something on the NPC (via containermenu) it DOESNT reset. Is there no way to lock their inventory without having to manually make a change?Also the NPC's ActorBase is always the NPC I use as the Template (it does not create a new FF template even though I use Lchar Traits) This is all quite discouraging. Link to comment Share on other sites More sharing options...
PJMail Posted September 11, 2023 Author Share Posted September 11, 2023 Further update. Recreating the NPC with a Leveled Item in their inventory makes no difference.The only important thing to stop the resets is to have manually transferred/equipped an item in their inventory beforehand. I can't reproduce your result of no reset with no leveled items in the inventory. Not sure what I am doing differently to you. Link to comment Share on other sites More sharing options...
Recommended Posts