Jump to content

[LE] Simple Polling Script.


ThatGuyYeah

Recommended Posts

I am looking for some pointers on the best way to approach doing a simple polling script for an NPC. Essentially, I want this script to check every 24 hours to see if the NPC is following the player and is within a relative distance of the player. If so, the variable I have is incremented by 1 (or whatever value).

 

I am aware that registerforSingleUpdateGameTime(24) would be the better way of working with what I am doing. So my script would look something like this:

bool Property bKeepUpdating auto ; Make Global in Script so can be altered by if the NPC is following player

Function StartChain()
    RegisterForSingleUpdateGameTime(24.0) ; Register to be notified every in-game day
EndFunction

Event OnUpdate()
    ; Add Increment Here
    If bKeepUpdating
        RegisterForSingleUpdateGameTime(24.0)
    EndIf
EndEvent

My idea is 'simple:' when the NPC is following the player, this script will run. Once the player dismisses the NPC, the script stops until NPC is following the player again.

 

Any advice would be appreciated.

Edited by ThatGuyYeah
Link to comment
Share on other sites

Well I am a beginner myself, but something i found recently during my research is that while statements are used for loops.

 

What I think might be happening with your script is that it only checks for the OnUpdate once and it finishes, if you want it to check every 24 hours AND only if the npc is following you, then maybe you can use this example with an entirely different script to get a general idea on how you should approach this.

int ListSize = MyEmptyPotion.GetSize()
int CurrentItems = 0
int ItemsLeft = 1

while CurrentItems <= ListSize && ItemsLeft > 0 
  Form CurrentItem1 = MyEmptyPotion.GetAt(CurrentItems)
  int ItemCount = PlayerREF.GetItemCount(CurrentItem1)

  PlayerREF.RemoveItem(CurrentItem1, ItemsLeft)
  ItemsLeft -= ItemCount
  CurrentItems += 1
endwhile

This I used it to take empty wine bottles from the player inventory. The gist of it is:

 

ItemsLeft is used to know how many items to erase

  1. It goes through the FormList starting with the first form 0 by CurrentItems which is then assigned to CurrentItem1 to cast that FormList item as a form since .GetItemCount can only count forms such as items.
  2. Then it uses .RemoveItem(CurrentItem1, ItemsLeft) to delete the selected item (Which wont do anything of the player doesn't even have the item)
  3. Then ItemCount is finally used modify ItemsLeft depending if ItemCount actually found any amount of the form that was selected.
  4. If ItemCount count returned 0, then it would use CurrentItems += 1 to keep searching through the form list till CurrentItems <= ListSize which would end the loop. OR If ItemsLeft finished deleting up to the amount it's supposed to then eventually it would become ItemsLeft > 0 which would also end the loop.

I know that script does something entire different, but the point is that you can use this as a guide line. You see a loop doesn't permanently modify values such as:

int ListSize = MyEmptyPotion.GetSize()
int CurrentItems = 0
int ItemsLeft = 1

It only modifies them till the loop ends, go ahead and read that wiki page on it, it explains the important stuff about it.

 

I hope this helps you get a little closer to achieving your goal.

Edited by smashballsx88
Link to comment
Share on other sites

The problem is while loops can get nasty in Skyrim and add the script lag and save bloats. I was trying to find a way to avoid that while getting what I am looking at the same time.

 

I was looking for a safer way of doing this without it killing player's games/saves.

Link to comment
Share on other sites

While loops get nasty and bloat saves when they are used incorrectly. Always make sure that the loops will end and use them where they make sense.

 

Your initial approach in my opinion is better than a while loop, because that OnUpdate event is going to fire exactly one time, every 24 hours. If you poll with a while loop for 24 hours, that function/event is going to run that loop for 24 hours.

Edited by Rasikko
Link to comment
Share on other sites

So after doing some research, my approach will be as follows:

Scriptname SDEPollingScript extends Quest
; This script will poll the character with Serana and see if she is near the player.

ObjectReference Property Serana Auto ; Adds Serana as Reference for Code

int Property X = 0 auto conditional

SDECustomModelScript Property SDECMM Auto ; Reference other script for following status

EVENT OnInit()
    Debug.Trace("OnInit() - Quest 'SDECMM' is running. " +self) ; Info only
ENDEVENT

Event OnUpdate()
    If (self as Quest) && self.IsRunning() ; Make sure mod is still running
  
		If (Game.GetPlayer().GetDistance(Serana) < 256) && (SDECMM.IsFollowing == true)
			
			X += 1 ; Not exact but wanted to add increment to script - will add cap to prevent overflow error
			
			Debug.Notification("Your time with Serana has improved your standing with her.") ; Will shorten
			
			RegisterForSingleUpdateGameTime(24.0)
			
		EndIf
		
    EndIf
EndEvent

And with Serana's following scripts, I will add the following:

((self as Quest) as SDEPollingScript).RegisterForSingleUpdateGameTime(24.0)

Does this hold water?

Edited by ThatGuyYeah
Link to comment
Share on other sites

The problem is while loops can get nasty in Skyrim and add the script lag and save bloats. I was trying to find a way to avoid that while getting what I am looking at the same time.

 

I was looking for a safer way of doing this without it killing player's games/saves.

 

Thank you for clarifying, yeah I had a feeling having this count every 24 hours in a while loop would be problematic. Yeah I started maybe a week ago, and I just got this mind set of what exactly I wanted to make, and ever since then I have just none stopped rammed head first into scripting .... I haven't even made my first simple dungeon yet, and I am already making new crafting systems with modified armor types and other neat stuff, a long side a well optimized and decently designed level.

Link to comment
Share on other sites

 

The problem is while loops can get nasty in Skyrim and add the script lag and save bloats. I was trying to find a way to avoid that while getting what I am looking at the same time.

 

I was looking for a safer way of doing this without it killing player's games/saves.

 

Thank you for clarifying, yeah I had a feeling having this count every 24 hours in a while loop would be problematic. Yeah I started maybe a week ago, and I just got this mind set of what exactly I wanted to make, and ever since then I have just none stopped rammed head first into scripting .... I haven't even made my first simple dungeon yet, and I am already making new crafting systems with modified armor types and other neat stuff, a long side a well optimized and decently designed level.

 

 

The best advice I can give is make a dummy esp and just do practice scripts there. I mean RegisterforSingleUpdate when doing what I am doing is technically a loop, but it can easily break itself when it is no longer in use (Which is what I am trying to figure out).

 

But yeah, practice, practice, practice.

Link to comment
Share on other sites

Alright, after tinkering with the code, I manged to get it to work perfectly. If you are wondering how to do it here is what I did:

 

First, I build a quest for the script and write the main script as follows:

Scriptname SDE extends Quest  Conditional
; This script will poll the character with Serana and see if she is near the player.

DLC1_NPCMentalModelScript Property SDECMM Auto ; Reference other script for following status

ObjectReference Property Serana Auto ; Adds Serana as Reference for Code

int Property X = 0 auto conditional

EVENT OnInit()
    Debug.Trace("OnInit() - Quest 'SDETestCode' is running. " +self) ; Info only
ENDEVENT

Event OnUpdateGameTime()
    If (self as Quest) && self.IsRunning() ; Make sure mod is still running
	; Debug.Notification("Seeing this message, code works here.")
	
        ; Utility.Wait(2.0)
	
        ; Debug.Notification("Checking other code.")
	
        ; Utility.Wait(2.0)
		If (Game.GetPlayer().GetDistance(Serana) < 1024) && (SDECMM.IsFollowing == true)		
			X += 1 ; Not exact but wanted to add increment to script - will add cap to prevent overflow error
			
			; Debug.Notification("Your time with Serana has improved your standing with her.") ; Will shorten
			
			RegisterForSingleUpdateGameTime(1.0)

			; if (X == 4)
				; Debug.Notification("Serana Admires You - Just Kidding.")
			; EndIf
		Else
			Debug.Notification("Code failed At Following.")
		EndIf
    Else
		Debug.Notification("Code failed At Check.")
    EndIf
EndEvent

Next, I implement a simple quest stage (called it 0) with an Empty Log Entry so I can write a simple fragment as so:

((self as Quest) as SDE).RegisterForSingleUpdateGameTime(1.0)

With that, the game will check if an in-game hour has passed. Then it will first check to see if the mod is running then it will check to see if Serana is following the player (using her variable that status - will not work for other followers) as well as check if Serana is close by. If all these are true, then my code will do its poll and repeat the cycle in another in-game hour. If any of these fail, the code will stop and will not repeat.

 

I am hoping someone can check to see if the structure of the code will be safe to use and not cause too much issue with saves (i.e bloat).

 

Anyone can now modify this code for 24 hours or for other purposes. Also, ignore the semi-colons, I was using that code for debug and commented it out.

Edited by ThatGuyYeah
Link to comment
Share on other sites

  • Recently Browsing   0 members

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