EvilSeedlet Posted January 22, 2021 Share Posted January 22, 2021 (edited) 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 endSTATEI 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 January 22, 2021 by EvilSeedlet Link to comment Share on other sites More sharing options...
dylbill Posted January 22, 2021 Share Posted January 22, 2021 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. Link to comment Share on other sites More sharing options...
EvilSeedlet Posted January 22, 2021 Author Share Posted January 22, 2021 (edited) 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 January 22, 2021 by EvilSeedlet Link to comment Share on other sites More sharing options...
dylbill Posted January 22, 2021 Share Posted January 22, 2021 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 More sharing options...
EvilSeedlet Posted January 22, 2021 Author Share Posted January 22, 2021 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 More sharing options...
EvilSeedlet Posted January 22, 2021 Author Share Posted January 22, 2021 (edited) 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 January 22, 2021 by EvilSeedlet Link to comment Share on other sites More sharing options...
dylbill Posted January 22, 2021 Share Posted January 22, 2021 No problem, glad you got it working :) Link to comment Share on other sites More sharing options...
ReDragon2013 Posted January 23, 2021 Share Posted January 23, 2021 (edited) 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 January 23, 2021 by ReDragon2013 Link to comment Share on other sites More sharing options...
Recommended Posts