Jump to content

Sleep INSIDE bedrolls - looking for lightest way to do this


Hoamaii

Recommended Posts

Hi guys,

 

I need some advice on a new mod I'm working on. I'm trying to implement the "sleep inside bedrolls" feature I created for my latest mod "Clearsky Hideout" to all bedrolls in Skryim.

 

The way I did this in Clearsky is very basic: I attached a trigger box to the bedrolls which enables and disables "blankets" while detecting the actor's sleep states.

 

The reason why I did not attach any script to the furniture itself so far is that I wanted to leave that Vanilla form completely untouched - if only for compatibility with player sleep mods or other mods that may modify NPCs sleep behaviors.

 

Now if I'm looking for a way to implement the same feature on all bedrolls in Skyrim, I believe I'm left with 3 choices (correct me if I'm wrong):

 

1. manually add the same trigger box to the 800 or 900 bedrolls which are scattered around Skyrim. Not only would it take forever, but I'm also very reluctant to adding so many trigger boxes all around Skyrim, which may cause dozens of instances of the same script running at the same time and bloating players' saves.

 

2. create a quest for bedrolls' use which would trigger a script on bedrolls aliases whenever: a. the player is around, b. any actor, NPC or player, activates a bedroll. That'd mean a very different script from the one I've written for Clearsky because I'd be using the "PlaceAtMe" function, then deleting the created reference once it's no longer needed. Instinctively, I'd think this is the "lightest" way to do this and it's not so much the script that is a problem to me as the quest itself : other than very basic quests involving actors (quests which have a beginning and an end), I've never created recurring quests, like "Sit Anywhere" for instance or "PlayerHeadTracking", and I'm not sure I wouldn't be risking to bloat players' saves either...

 

3. attach a script directly to the furniture (the way it's done for Vanilla furniture markers like the OreMining for instance) - but that'd may also bring up lots of compatibility issues...

 

So I really could use some advice, or direct guidance, in doing this: first to tell me what you think would be the lightest solution, then, if quest is the appropriate solution, to guide or help me create that kind of quest the cleanest possible way.

 

Many thanks in advance to whomever may be willing to give me a hand :smile:

 

Hoamaii

Link to comment
Share on other sites

1. manually add the same trigger box to the 800 or 900 bedrolls which are scattered around Skyrim. Not only would it take forever, but I'm also very reluctant to adding so many trigger boxes all around Skyrim, which may cause dozens of instances of the same script running at the same time and bloating players' saves.

Only if they all have an OnInit event handler, I think. Set them up OnAttach, and they should only process tasks when the player enters the cell or when the player uses them (assuming you don't mess something else up).

 

Of course, you still have to place a ton of trigger boxes (or write a TES5Edit script to do it), and then you run into compatibility issues with mods that move, remove, or spawn new bedrolls.

 

2. create a quest for bedrolls' use which would trigger a script on bedrolls aliases whenever: a. the player is around, b. any actor, NPC or player, activates a bedroll. That'd mean a very different script from the one I've written for Clearsky because I'd be using the "PlaceAtMe" function, then deleting the created reference once it's no longer needed. Instinctively, I'd think this is the "lightest" way to do this and it's not so much the script that is a problem to me as the quest itself : other than very basic quests involving actors (quests which have a beginning and an end), I've never created recurring quests, like "Sit Anywhere" for instance or "PlayerHeadTracking", and I'm not sure I wouldn't be risking to bloat players' saves either...

I think you'd need to do something like this:

 

Set up a script to detect when the player changes cells. (There are little hacks to accomplish this.) When the player changes cells, stop and start your quest (via a script), which should have more than enough aliases to tag every single bedroll in the cell. Slap your script on each alias, and have it respond OnActivate or something. Easy-peasy.

 

You'd be potentially spawning blankets en masse, but Chesko's multithreading methods could allow you to do it more efficiently.

 

You could clean up any blankets you spawn at run-time pretty reliably. What I'd try is adding the blankets to a FormList via script, when they're created. (FormLists are thread-safe; arrays, maybe not so much.) Then, instead of stopping the quest directly, I'd set it to a stage whose script fragment runs through the FormList, deleting every blanket (and removing it from the FormList after!) before stopping the quest. If you take this approach, you'll likely need to use booleans to guard against concurrency (you don't want to try starting the quest while it's still cleaning up and shutting down).

 

What I mean about guarding against concurrency is this:

Bool Property pbBusy = False Auto Hidden
Bool Property pbQueued = False Auto Hidden
Function OneAtATime()
   If pbBusy
      pbQueued = True
      Return
   EndIf
   pbBusy = True
   pbQueued = False
   ;
   ; ...
   ;
   pbBusy = False
   If pbQueued
      ;
      ; To keep call stacks from getting too deep, you may want to have the 
      ; function call itself indirectly, e.g. with OnUpdate or an SKSE mod 
      ; event.
      ;
      OneAtATime()
   EndIf
EndFunction

3. attach a script directly to the furniture (the way it's done for Vanilla furniture markers like the OreMining for instance) - but that'd may also bring up lots of compatibility issues...

Plus, if you don't clean up properly, you'll run into bloat. SkyBirds has that problem. Edited by DavidJCobb
Link to comment
Share on other sites

Hi DavidJCobb,

 

Thank you so much for the detailed answer :).

 

I've sort of been pursuing my own trials and investigations since I posted these questions - and reverted my point of view about placing trigger boxes all around skyrim when it occured to me that as long as the cell they're placed in are not loaded by the game and the player is not around, nothing can trigger them + I can set them to be completely independant from bedrolls. If I only use bedrolls for placement coordinates, that will leave them completely Vanilla + after cleaning it all with TES5edit, I should be pretty much ok and minimize compatibility issues with mods which remove bedrolls (if a bedroll is deleted and an actor enters the trigger box, the trigger box won't detect any "SleepState" and no event will be triggered). And no, the script I'm using doesn't have an OnInit() event.

 

Of course, that will mean manually placing hundreds of trigger boxes and disabled blankets around Skyrim - and it'd also mean that other mod-places bedrolls won't work with this, but I can also release a modder's resource for modders who want to make their bedrolls behave the same way.

 

I pretty much eliminated altogether the (bad) idea to attach a script to the furniture itself which was my option 3.

 

As for option 2, doing this all through a quest, I ran into the problem that player changing cell in exterior is a tough one to rely on: a player may have changed cell but still have perfect Line Of Sight of these bedrolls. I tried a few things around "OnCellLoad", "OnLoad", "OnCellAttach", "OnUnLoad", "OnDetach" or "onCellDetach" - and got some strange behaviors. When savegames are made in between, or quit and reload - some functions just don't run the way they're expected - like "onUnload" never running for instance because the player loaded a savegame while still attached to the same cell, so "OnLoad" never had to run and as a consequence "OnUload" would never run either... (incidentally, that's when I realised it may be something like that from the Vanilla "OreMiningFurnitureScript" which prevents Ores to reset properly and forces us to leave and reenter the cell to make them work properly again...)

 

But to be quite honest, what really made me think twice about that is my inexperience in designing such quests. The mere fact that you're mentioning Chesko as a reference comforts that idea. I am hundreds of light years behind Chesko as far as my scripting experience goes. Chances are too high that I'd be forgetting something crucial in cleaning up behind my mod - and be messing with people's games without even completely understanding where I may have goofed...

 

Like you said, while I was writing a new script for bedrolls aliases, I realized I was spawning blankets "en masse" in the game, and I also realized that if I don't clean up properly behind that, I'll be bloating saves in no time at all...

 

I still want to try my hand at writing such quests, but it'd probably be wiser that I do it first for furnitures or objects which are less common in the game than bedrolls - it may be ok to experiment for 20 or 30 refs, but not for several hundreds.

 

Anyway, I'm really grateful for your very detailed and clear answer (English is not my native language - but wow!.. everything you said was very clear to me!..) and have taken careful notes of it all. Thanks for the script too, I had felt the need to use bool properties too, but not quite as efficiently as you do here.

 

So, I've started to add triggerboxes to the game - it'll take a while but I believe now that it may be the "lightest" way to do all this. Unless of course you have some other warning for me. Plus it's a type of script I've been testing over and over in my latest mod (and thousands of players have been testing it too now). I'm thinking also that this approach will be easier to uninstall if need be - no quest to stop, no variables to clean (I only use keywords) and only one script attached to a custom trigger box which'll be gone when the mod is uninstalled.

 

I'll try it for some hundred bedrolls and see if this suddenly bloats my saves or not. If it does, well... I'll have to think of something else... ;)

 

Thanks again, man :). And cheers from Paris,

 

Hoamaii

Link to comment
Share on other sites

  • Recently Browsing   0 members

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