Jump to content

[LE] Activator Script Help


EvilSeedlet

Recommended Posts

Hello! Standard disclaimer, I'm pretty new to scripting, so please excuse any stupid mistakes. My husband is a programmer (not super familiar with skyrim modding or papyrus though) and has helped me get to this point.

 

Basically what I want is to have an activator (in this case a loom) that gives you a buff when you activate it. For the loom, I duplicated the tanning rack and replaced its mesh/texture with my own and removed its workbench menu functionality. Having done ONLY this, when you interact with it in game, you do the tanning rack animation on it, and can back out of it by hitting a movement key. great. wonderful.

 

I decided to get fancy with it and have it give you a small buff. I wanted there to be a "downside," so when you interact with it, the screen fades out, it gives you the buff, and the game moves time forward 6 hours. Screen fades back in with you still working on the loom, which you can then choose to back out of. After a lot of n00bish frustration, I .. sort of got that to work. The problem became the fact that you "activate" the loom when you sit down AND when you get up, causing the fade out/buff/time skip/fade in to happen twice.

 

Frustration. Husband steps in, helps me discover states! We find two ways to do it. The first one is this. This script works in game with the ONLY problem being that if you activate the loom too many times in quick succession (like spam clicking it) then it will quickly double fire and move the important activation that does all of the fun stuff to the getting-off-the-loom animation, which kinda sucks.

 

 

Scriptname PGRLoomScript extends ObjectReference

Spell property PGRLoomSpell Auto
GlobalVariable Property GameHour auto
Idle Property IdleStop_Loose Auto
ImageSpaceModifier Property FadeToBlackImod Auto
ImageSpaceModifier Property FadeToBlackHoldImod Auto
ImageSpaceModifier Property FadeToBlackBackImod Auto
Int PGRLoomState

EVENT OnActivate(ObjectReference akActionRef)

if PGRLoomState == 0
; fade screen to black
	FadeToBlackImod.Apply()
		Utility.wait(2.75)
FadeToBlackImod.PopTo(FadeToBlackHoldImod)

; Cast a spell on player
	PGRLoomSpell.Cast(akActionRef, akActionRef)

; Move time forward 6 hours
	float newTime = GameHour.Mod(6.0)

; Fade back in
	Utility.Wait(2)
	FadeToBlackHoldImod.PopTo(FadeToBlackBackImod)
	FadeToBlackHoldImod.Remove()

; Set state to 1
	PGRLoomState = 1

; If state is off, turn it on then do nothing
	elseif PGRLoomState == 1
		PGRLoomState = 0
endif

endEvent

 

Soooo we then look into proper state blocks. I come up with this, which does nothing, except for the one bit I put in to the empty state when I was at my wit's end and started trying to do some debugging. Anything I put into the empty state works, nothing else fires at all. And I have no idea why.

 

Scriptname PGRLoomScript extends ObjectReference

Spell property PGRLoomSpell Auto
GlobalVariable Property GameHour auto
ImageSpaceModifier Property FadeToBlackImod Auto
ImageSpaceModifier Property FadeToBlackHoldImod Auto
ImageSpaceModifier Property FadeToBlackBackImod Auto


EVENT onActivate (objectReference akActionRef)
		Debug.Notification("empty state")
endEVENT


auto STATE PGRLoomOn

EVENT onActivate (objectReference akActionRef)

 		gotoState("busy")

		Debug.Notification("on")

; fade screen to black
	FadeToBlackImod.Apply()
		Utility.wait(2.75)
	FadeToBlackImod.PopTo(FadeToBlackHoldImod)

; Cast a spell on player
	PGRLoomSpell.Cast(akActionRef, akActionRef)

; Move time forward 6 hours
	float newTime = GameHour.Mod(6.0)

; Fade back in
	Utility.Wait(2)
	FadeToBlackHoldImod.PopTo(FadeToBlackBackImod)
	FadeToBlackHoldImod.Remove()

 		gotoState("PGRLoomOff")
Debug.Notification("fades")
endEVENT


 endSTATE
 
 STATE busy
 	; don't do a thing!
 	EVENT onActivate (objectReference akActionRef)
Debug.Notification("busy")
ENDEVENT
 endSTATE		
 
 STATE PGRLoomOff
 	EVENT onActivate (objectReference akActionRef)
Debug.Notification("off")
 		gotoState("PGRLoomOn")
 	endEVENT
 endSTATE

I have been gnawing on this for an embarrassing number of hours over the past few days and done so much more with scripting than I ever have before in a skyrim mod but I've just hit a total wall with this. My only guess is either there's something about state blocks that I'm totally ignorant of, or possibly the tanning rack base is somehow messing with this and putting it in another state that's locking it out? But I thought multiple states in multiple scripts was ok, just not in one script? I dunno. Please help. Thank you.

Edited by EvilSeedlet
Link to comment
Share on other sites

In your second script, take out the OnActivate event in the empty state completely and it should work. Also, be sure to test on a new game, or at least on a save before you had your mod installed because scripts can get baked into a save.

 

Thanks for the reply! That event isn't usually there, I just added it to make sure the script was firing at all. Even when it's not there, nothing happens.

 

edit: or rather, let me be more specific. The player will still use the loom and do the tanning rack animation and can back out of it at will, but the screen will not fade, no buff is applied and time does not move forward.

 

Edit2: I had been reloading from a cell that had never been in the area that held the loom, but this time tried starting a brand new game. it worked, but it's still letting me double activate it :pinch: :wacko: :pinch:

 

Edit3 lmao: Ok I think I see what's happening. it's not double activating, the base tanning rack is allowing me to exit it while the script is in busy mode, therefore it never "activates" a second time to reset it. When I go to activate it again, it then turns it "off" and the switch becomes backwards. I dunno how to solve that yet but I think that's what's going on.

Edited by EvilSeedlet
Link to comment
Share on other sites

I tested your script without the onActivate event in the empty state, and it works, I get the "busy" notification when trying to activate again. I duplicated the DweButton01 to test, so I wasn't using a tanning rack. To prevent double activation, you can also try using Game.DisablePlayerControls() and then Game.EnablePlayerControls() after the fade out / in is complete.

Link to comment
Share on other sites

I tested your script without the onActivate event in the empty state, and it works, I get the "busy" notification when trying to activate again. I duplicated the DweButton01 to test, so I wasn't using a tanning rack. To prevent double activation, you can also try using Game.DisablePlayerControls() and then Game.EnablePlayerControls() after the fade out / in is complete.

 

Thank you so much for looking at it! I'll try that now.

Link to comment
Share on other sites

it works ToT ahh thank you!!!

the script for anyone in the future:

 

 

 

Scriptname PGRLoomScript extends ObjectReference

Spell property PGRLoomSpell Auto
GlobalVariable Property GameHour auto
ImageSpaceModifier Property FadeToBlackImod Auto
ImageSpaceModifier Property FadeToBlackHoldImod Auto
ImageSpaceModifier Property FadeToBlackBackImod Auto


auto STATE PGRLoomOn
	EVENT onActivate (objectReference akActionRef)

 		gotoState("busy")

		Debug.Notification("on")

; disable player controls
Game.DisablePlayerControls()
		Debug.Notification("stop right there")

; fade screen to black
	FadeToBlackImod.Apply()
		Utility.wait(2.75)
	FadeToBlackImod.PopTo(FadeToBlackHoldImod)

; Cast a spell on player
	PGRLoomSpell.Cast(akActionRef, akActionRef)

; Move time forward 6 hours
	float newTime = GameHour.Mod(6.0)

; Fade back in
	Utility.Wait(2)
	FadeToBlackHoldImod.PopTo(FadeToBlackBackImod)
	FadeToBlackHoldImod.Remove()
		Debug.Notification("fades")

		Utility.wait(3)

 		gotoState("PGRLoomOff")

;reactivate player controls
	Game.EnablePlayerControls()
		Debug.Notification("ok u can move")


endEVENT


 endSTATE
 
 STATE busy
 	; don't do a thing!
 	EVENT onActivate (objectReference akActionRef)
Debug.Notification("busy")
ENDEVENT
 endSTATE		
 
 STATE PGRLoomOff
 	EVENT onActivate (objectReference akActionRef)
Debug.Notification("off")
 		gotoState("PGRLoomOn")

 	endEVENT
 endSTATE 

 

 

 

cleaned up version

 

Scriptname PGRLoomScript extends ObjectReference

Spell property PGRLoomSpell Auto
GlobalVariable Property GameHour auto
ImageSpaceModifier Property FadeToBlackImod Auto
ImageSpaceModifier Property FadeToBlackHoldImod Auto
ImageSpaceModifier Property FadeToBlackBackImod Auto


 auto STATE PGRLoomOn
	EVENT onActivate (objectReference akActionRef)

 		gotoState("busy")

; disable player controls
Game.DisablePlayerControls()

; fade screen to black
	FadeToBlackImod.Apply()
		Utility.wait(2.75)
	FadeToBlackImod.PopTo(FadeToBlackHoldImod)

; Cast a spell on player
	PGRLoomSpell.Cast(akActionRef, akActionRef)

; Move time forward 6 hours
	float newTime = GameHour.Mod(6.0)

; Fade back in
	Utility.Wait(2)
	FadeToBlackHoldImod.PopTo(FadeToBlackBackImod)
	FadeToBlackHoldImod.Remove()

		Utility.wait(3)

 		gotoState("PGRLoomOff")

;reactivate player controls
	Game.EnablePlayerControls()
 endEVENT
 endSTATE
 
 STATE busy
 	; don't do a thing!
 endSTATE		
 
 STATE PGRLoomOff
 	EVENT onActivate (objectReference akActionRef)
 		gotoState("PGRLoomOn")

 endEVENT
 endSTATE

 

 

Edited by EvilSeedlet
Link to comment
Share on other sites

You wrote: "Soooo we then look into proper state blocks. I come up with this, which does nothing, except for the one bit I put in to the empty state when I was at my wit's end and started trying to do some debugging."

next code was not working

 

Scriptname PGRLoomScript extends ObjectReference

EVENT onActivate (objectReference akActionRef)
    Debug.Notification("empty state")
ENDEVENT


auto STATE PGRLoomOn
    EVENT onActivate (objectReference akActionRef)
        gotoState("busy")
            ; code here
        gotoState("PGRLoomOff")
    ENDEVENT
endSTATE


STATE busy
    EVENT onActivate (objectReference akActionRef)
        Debug.Notification("busy")
    ENDEVENT
endSTATE        


STATE PGRLoomOff
    EVENT onActivate (objectReference akActionRef)
        Debug.Notification("off")
        gotoState("PGRLoomOn")
    endEVENT
endSTATE

 


Why? The OnActivate() event in empty state (or let us say in no state) covers the OnActivate() event in auto state "PGRLoomOn".

See next script code how to make it right this way.
evilPGRLoomScript

 

Scriptname evilPGRLoomScript extends ObjectReference
; https://forums.nexusmods.com/index.php?/topic/9551918-activator-script-help/

  GlobalVariable PROPERTY GameHour auto                   ; this is a vanilla game globalVar

  Spell PROPERTY PGRLoomSpell auto                        ; new created spell

; vanilla game imods
  ImageSpaceModifier PROPERTY FadeToBlackImod     auto
  ImageSpaceModifier PROPERTY FadeToBlackHoldImod auto
  ImageSpaceModifier PROPERTY FadeToBlackBackImod auto


; -- EVENTs --

EVENT OnActivate(ObjectReference akActionRef)
IF (akActionRef == Game.GetPlayer() as ObjectReference)
    gotoState("busy")                 ; ### STATE ###
    Game.DisablePlayerControls()

    FadeToBlackImod.Apply()                              ; fade screen to black
    Utility.Wait(2.75)
    FadeToBlackImod.PopTo(FadeToBlackHoldImod)

    PGRLoomSpell.Cast(akActionRef, akActionRef)          ; Cast the special loom spell on player
    GameHour.Mod(6.0)                                    ; Move gametime forward by 6 hours, we do not need the return value of float

    Utility.Wait(2.0)
    FadeToBlackHoldImod.PopTo(FadeToBlackBackImod)       ; Fade in back to normal game design
    FadeToBlackHoldImod.Remove()
    Utility.Wait(3.0)

    gotoState("off")                 ; ### STATE ###    now we look for next activation by player
    Game.EnablePlayerControls()
ENDIF
ENDEVENT


;============================
STATE busy    ; do not allow another activation while activation process above is running!
;=========
     EVENT OnActivate(ObjectReference akActionRef)
     ENDEVENT
;=======
endState    

    
;============================
STATE off
;========
    EVENT OnActivate(ObjectReference akActionRef)
    IF (akActionRef == Game.GetPlayer() as ObjectReference)
        gotoState("")                ; ### STATE ### back to empty state for next real activation
    ENDIF
    ENDEVENT
;=======
endState

 

 

Edited by ReDragon2013
Link to comment
Share on other sites

  • Recently Browsing   0 members

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