• Announcements

    • Ashal

      SITE MOVED - IN READ ONLY MODE   12/08/2015

      Please use http://www.loverslab.com moving forward. Site has been restored to a previous version, and this one placed into a read-only mode. This is available for a limited time so users may reference/copy content that has been lost in the transition. This will no longer be accessible by December 22nd, 2015.
Sign in to follow this  
Followers 0
randomtguy

Please help me with my script / using StorageUtil

I'm trying to create a mod that bypasses the need to use Death Alternative with Simple Slavery as I can never get the former to damn well work. It's supposed to check when the player has been defeated through any Defeat type mod (by checking a player's health at the moment an aggressive SexLab animation starts) and give a configurable chance of teleporting you to the Simple Slavery market.


 


But I'm clearly missing something key as the only debug message I've inserted that I've managed to trigger is the one to check whether the mod's active. It may be because I'm iffy on how to use StorageUtil - do I need to declare it in the scripts like you do with SexLab or something? It may be any number of other things as I'm still so new at scripting. Here's the MCM menu script:


 





ScriptName SimplerSlaveryMCMScript Extends SKI_ConfigBase

; OIDs
int aOID
int MinhealththresholdOID_S
int ChanceofenslavementOID_S

; Toggle states
bool aVal = true
float Minhealththreshold = 25.0
float Chanceofenslavement = 25.0

event OnLoad()
StorageUtil.SetIntValue(none, "SRSModOn", aOID)
StorageUtil.SetIntValue(none, "SRSMinHealth", MinhealththresholdOID_S)
StorageUtil.SetIntValue(none, "SRSChanceofEnslave", ChanceofenslavementOID_S)
endEvent

event OnPageReset(string page)
{Called when a new page is selected, including the initial empty page}
SetCursorFillMode(LEFT_TO_RIGHT)
AddToggleOption("Simpler Slavery active", aVal)
MinhealththresholdOID_S = AddSliderOption("Minimum health threshold", Minhealththreshold, "{0}%")
ChanceofenslavementOID_S = AddSliderOption("Chance of enslavement", Chanceofenslavement, "{1}%")
endEvent

event OnOptionSelect(int option)
{Called when a non-interactive option has been selected}
if (option == aOID)
aVal = !aVal
SetToggleOptionValue(aOID, aVal)
StorageUtil.SetIntValue(none, "SRSModOn", aOID)
endIf
endEvent

event OnOptionDefault(int option)
if (option == aOID)
aVal = true ; default value
SetToggleOptionValue(aOID, aVal)
StorageUtil.SetIntValue(none, "SRSModOn", aOID)
elseif (option == MinhealththresholdOID_S)
SetSliderOptionValue(MinhealththresholdOID_S, Minhealththreshold, "{0}%")
StorageUtil.SetIntValue(none, "SRSMinHealth", MinhealththresholdOID_S)
elseif (option == ChanceofenslavementOID_S)
SetSliderOptionValue(ChanceofenslavementOID_S, Chanceofenslavement, "{0}%")
StorageUtil.SetIntValue(none, "SRSChanceofEnslave", ChanceofenslavementOID_S)
endIf
endEvent

Event OnOptionHighlight(int option)
if (option == aOID)
SetInfoText("Select to activate or deactivate this mod")
elseif (option == MinhealththresholdOID_S)
SetInfoText("Minimum health threshold required to trigger slavery")
elseif (option == ChanceofenslavementOID_S)
SetInfoText("Chance of being enslaved. Set to just above your defeat threshold")
endIf
endEvent

event OnOptionSliderOpen(int option)
if (option == MinhealththresholdOID_S)
SetSliderDialogStartValue(Minhealththreshold)
SetSliderDialogDefaultValue(25)
SetSliderDialogRange(1.0, 100.0)
SetSliderDialogInterval(1.0)
elseIf (option == ChanceofenslavementOID_S)
SetSliderDialogStartValue(Chanceofenslavement)
SetSliderDialogDefaultValue(25)
SetSliderDialogRange(1.0, 100.0)
SetSliderDialogInterval(1.0)
endif
endevent

event OnOptionSliderAccept(int option, float value)
if (option == MinhealththresholdOID_S)
Minhealththreshold = value
SetSliderOptionValue(MinhealththresholdOID_S, Minhealththreshold, "{0}%")
StorageUtil.SetIntValue(none, "SRSMinHealth", MinhealththresholdOID_S)
elseif (option == ChanceofenslavementOID_S)
Chanceofenslavement = value
SetSliderOptionValue(ChanceofenslavementOID_S, Chanceofenslavement, "{0}%")
StorageUtil.SetIntValue(none, "SRSChanceofEnslave", ChanceofenslavementOID_S)
endIf
endEvent


 


And here's the trigger script:


 





ScriptName SimplerSlaveryTriggerScript Extends Quest

SexLabFramework Property SexLab Auto
SimplerSlaveryMCMScript Property Config Auto
ObjectReference Property sslv_cagemark2 Auto
Actor Player

Event OnInit()
RegisterForModEvent("AnimationStart", "CheckDefeated")
Debug.Notification("Simpler Slavery Detected")
EndEvent

event CheckDefeated(string eventName, string argString, float argNum, form sender)
int SRSModOnInt = StorageUtil.GetIntValue(none, "SRSModOn")
if SRSModOnInt == 0
Debug.Notification("Mod active check failed")
return
endif
Debug.Notification("Mod active check passed")
int SRSMinHealthInt = StorageUtil.GetIntValue(none, "SRSMinHealth")
If Player.getav("Health") > SRSMinHealthInt
Debug.Notification("Health threshold check failed")
return
endif
Debug.Notification("Health threshold check passed")
sslThreadController controller = SexLab.HookController(argString)
if !controller.HasPlayer
Debug.Notification("Player involvement check failed")
return
endif
Debug.Notification("Player involvement check passed")
actor victim = SexLab.HookVictim(argString)
if victim != player
Debug.Notification("Player is victim check failed")
return
endif
RegisterForModEvent("AnimationEnd", "EnslavePlayerEvent")
Debug.Notification("Player is victim check passed")
EndEvent

event EnslavePlayerEvent(string eventName, string argString, float argNum, form sender)
UnregisterForModEvent("AnimationEnd")
int SRSEnslaveInt = StorageUtil.GetIntValue(none, "SRSChanceofEnslave")
int random = Utility.RandomInt(0, 99)
if random > SRSEnslaveInt
Debug.Notification("Random roll failed")
return
endif
Debug.Notification("Random roll passed")
Game.GetPlayer().MoveTo(sslv_cagemark2)
EndEvent


0

Share this post


Link to post

One issue, the script appears to be using StorageUtil to store the OID of the MCM elements rather than the value those elements are returning.



StorageUtil.SetIntValue(none, "SRSMinHealth", MinhealththresholdOID_S)

Should be



StorageUtil.SetFloatValue(none, "SRSMinHealth", Minhealththreshold)

or



StorageUtil.SetIntValue(none, "SRSMinHealth", Minhealththreshold as Int)

0

Share this post


Link to post

 

One issue, the script appears to be using StorageUtil to store the OID of the MCM elements rather than the value those elements are returning.

StorageUtil.SetIntValue(none, "SRSMinHealth", MinhealththresholdOID_S)

Should be

StorageUtil.SetFloatValue(none, "SRSMinHealth", Minhealththreshold)

or

StorageUtil.SetIntValue(none, "SRSMinHealth", Minhealththreshold as Int)

 

Thanks for that, that was definitely part of the problem, though clearly not all of it as the other debug messages still aren't showing.

 

0

Share this post


Link to post

In your code you are never initializing the "Player" variable.

 

Change it with:

Actor Property PlayerRef Auto

 


Second point:

It is good and wise to specify the actual storage area for Storage Utils. Saving it globally can lead to reading the value in not the correct way.

You can switch (if this values are written and read just by you) on a JSON file, like:

 

JSONUtil.setFloatValue("RandomTGuyMod", "SRSMinHealth", Minhealththreshold)

 

0

Share this post


Link to post

In your code you are never initializing the "Player" variable.

 

Change it with:

Actor Property PlayerRef Auto

 

Second point:

It is good and wise to specify the actual storage area for Storage Utils. Saving it globally can lead to reading the value in not the correct way.

You can switch (if this values are written and read just by you) on a JSON file, like:

 

JSONUtil.setFloatValue("RandomTGuyMod", "SRSMinHealth", Minhealththreshold)

 

Ah, that makes a lot of sense. If I did that, then can and should I attach the script to PlayerRef in the CK (rather than in the quest window)? It wasn't working when I tried before. As for JSONUtil, why would I want to use a float instead of an int? If I do can I still call it in the trigger script the same way? Thanks a lot for your help once again.

 

0

Share this post


Link to post

 

Ah, that makes a lot of sense. If I did that, then can and should I attach the script to PlayerRef in the CK (rather than in the quest window)? It wasn't working when I tried before. As for JSONUtil, why would I want to use a float instead of an int? If I do can I still call it in the trigger script the same way? Thanks a lot for your help once again.

 

 

Your script extends a Quest, so it should be attached to a quest.

I just added a property PlayerRef, because you are using the Player actor, and this property is the fastest possible way to get it.

 

I used for JSON a SetFloatValue because your variable has a Float type.

You should use the appropriate function to avoid casting: if your variable is a float but you store it as an Int, then you have to cast it.

 

I don't know what is the best type for you, but for sure you can use the most appropriate value, and use the set/get functions specific for the type of the variable:

 

int function SetIntValue(string FileName, string KeyName, int value)
float function SetFloatValue(string FileName, string KeyName, float value)
string function SetStringValue(string FileName, string KeyName, string value)
form function SetFormValue(string FileName, string KeyName, form value)
0

Share this post


Link to post

 

 

Ah, that makes a lot of sense. If I did that, then can and should I attach the script to PlayerRef in the CK (rather than in the quest window)? It wasn't working when I tried before. As for JSONUtil, why would I want to use a float instead of an int? If I do can I still call it in the trigger script the same way? Thanks a lot for your help once again.
 

 

Your script extends a Quest, so it should be attached to a quest.

I just added a property PlayerRef, because you are using the Player actor, and this property is the fastest possible way to get it.

 

I used for JSON a SetFloatValue because your variable has a Float type.

You should use the appropriate function to avoid casting: if your variable is a float but you store it as an Int, then you have to cast it.

 

I don't know what is the best type for you, but for sure you can use the most appropriate value, and use the set/get functions specific for the type of the variable:

 

int function SetIntValue(string FileName, string KeyName, int value)
float function SetFloatValue(string FileName, string KeyName, float value)
string function SetStringValue(string FileName, string KeyName, string value)
form function SetFormValue(string FileName, string KeyName, form value)

 

 

 

Thanks for that, I rewrote it to use JSON floats, and to mostly avoid casting except I don't know how to use JSON to store boolean values. But I'm clearly still missing something key as none of the debug messages are showing up except the first still, showing it's still not working. The JSON file is generating and storing the values but apparently to no avail. Here's the rewritten MCM script:

ScriptName SimplerSlaveryMCMScript Extends SKI_ConfigBase; OIDsint aOIDint MinhealththresholdOID_S int ChanceofenslavementOID_S ; Toggle statesbool aVal = truefloat Minhealththreshold = 25.0float Chanceofenslavement = 25.0event OnInit()	parent.OnInit()	JSONUtil.setFloatValue("SimplerSlavery", "SRSModOn", aVal as float)	JSONUtil.setFloatValue("SimplerSlavery", "SRSMinHealth", Minhealththreshold)	JSONUtil.setFloatValue("SimplerSlavery", "SRSChanceofEnslave", Chanceofenslavement)endEventevent OnPageReset(string page)    {Called when a new page is selected, including the initial empty page}	SetCursorFillMode(LEFT_TO_RIGHT) 	AddToggleOption("Simpler Slavery active", aVal)	MinhealththresholdOID_S = AddSliderOption("Minimum health threshold", Minhealththreshold, "{0}%")	ChanceofenslavementOID_S = AddSliderOption("Chance of enslavement", Chanceofenslavement, "{1}%")endEventevent OnOptionSelect(int option)    {Called when a non-interactive option has been selected}	 if (option == aOID)    	 	aVal = !aVal        	SetToggleOptionValue(aOID, aVal)		JSONUtil.setFloatValue("SimplerSlavery", "SRSModOn", aVal as float)  	 endIfendEventevent OnOptionDefault(int option)	if (option == aOID)        	aVal = true ; default value		SetToggleOptionValue(aOID, aVal)		JSONUtil.setFloatValue("SimplerSlavery", "SRSModOn", aVal as float)	elseif (option == MinhealththresholdOID_S)		SetSliderOptionValue(MinhealththresholdOID_S, Minhealththreshold, "{0}%")		JSONUtil.setFloatValue("SimplerSlavery", "SRSMinHealth", Minhealththreshold)	elseif (option == ChanceofenslavementOID_S)        	SetSliderOptionValue(ChanceofenslavementOID_S, Chanceofenslavement, "{0}%")		JSONUtil.setFloatValue("SimplerSlavery", "SRSChanceofEnslave", Chanceofenslavement)     endIfendEventEvent OnOptionHighlight(int option)    if (option == aOID)        SetInfoText("Select to activate or deactivate this mod")    elseif (option == MinhealththresholdOID_S)	SetInfoText("Minimum health threshold required to trigger slavery")    elseif (option == ChanceofenslavementOID_S)	SetInfoText("Chance of being enslaved. Set to just above your defeat threshold")    endIfendEventevent OnOptionSliderOpen(int option)    if (option == MinhealththresholdOID_S)         SetSliderDialogStartValue(Minhealththreshold)        SetSliderDialogDefaultValue(25)        SetSliderDialogRange(1.0, 100.0)        SetSliderDialogInterval(1.0)    elseIf (option == ChanceofenslavementOID_S)        SetSliderDialogStartValue(Chanceofenslavement)        SetSliderDialogDefaultValue(25)        SetSliderDialogRange(1.0, 100.0)        SetSliderDialogInterval(1.0)    endifendeventevent OnOptionSliderAccept(int option, float value)    if (option == MinhealththresholdOID_S)        Minhealththreshold = value        SetSliderOptionValue(MinhealththresholdOID_S, Minhealththreshold, "{0}%")	JSONUtil.setFloatValue("SimplerSlavery", "SRSMinHealth", Minhealththreshold)    elseif (option == ChanceofenslavementOID_S)        Chanceofenslavement = value        SetSliderOptionValue(ChanceofenslavementOID_S, Chanceofenslavement, "{0}%")	JSONUtil.setFloatValue("SimplerSlavery", "SRSChanceofEnslave", Chanceofenslavement)  endIfendEvent


And the rewritten trigger script:

ScriptName SimplerSlaveryTriggerScript Extends QuestSexLabFramework Property SexLab AutoSimplerSlaveryMCMScript Property Config AutoObjectReference Property sslv_cagemark2 AutoActor Property PlayerRef AutoActor PlayerEvent OnInit()		RegisterForModEvent("AnimationStart", "CheckDefeated")	Debug.Notification("Simpler Slavery Detected")EndEventevent CheckDefeated(string eventName, string argString, float argNum, form sender)	if JSONUtil.GetFloatValue("SimplerSlavery", "SRSModOn") == 0	Debug.Notification("Mod active check failed")       		return   	endif 	Debug.Notification("Mod active check passed")	If Player.getav("Health") > JSONUtil.GetFloatValue("SimplerSlavery", "SRSMinHealth")	Debug.Notification("Health threshold check failed")		return	endif	Debug.Notification("Health threshold check passed")	sslThreadController controller = SexLab.HookController(argString)	if !controller.HasPlayer	Debug.Notification("Player involvement check failed")		return	endif	Debug.Notification("Player involvement check passed")	  actor victim = SexLab.HookVictim(argString)	if victim != player	Debug.Notification("Player is victim check failed")		return	endif	RegisterForModEvent("AnimationEnd", "EnslavePlayerEvent")	Debug.Notification("Player is victim check passed")EndEventevent EnslavePlayerEvent(string eventName, string argString, float argNum, form sender)	UnregisterForModEvent("AnimationEnd")	Int random = Utility.RandomInt(0, 99)	      if random > JSONUtil.GetFloatValue("SimplerSlavery", "SRSChanceofEnslave")		Debug.Notification("Random roll failed")	 	 return	endif	Debug.Notification("Random roll passed")	Game.GetPlayer().MoveTo(sslv_cagemark2)EndEvent

 

Edit: Seems the problem may be with the Player.GetAV section, as my Papyrus logs say this:

 

 

ERROR: Cannot call GetAV() on a None object, aborting function call stack:     [simplerSlaveryQuest (64001826)].SimplerSlaveryTriggerScript.CheckDefeated() - "SimplerSlaveryTriggerScript.psc" Line 20
[08/20/2015 - 06:03:11PM] warning: Assigning None to a non-object variable named "::temp1" stack:  [simplerSlaveryQuest(64001826)].SimplerSlaveryTriggerScript.CheckDefeated() - "SimplerSlaveryTriggerScript.psc" Line 20

Double edit: Nope, I changed it to Game.GetPlayer().GetAV("health"), which removed the error, but still no messages.

0

Share this post


Link to post

My friend. Just do a simple search/replace of "Player." with "PlayerRef.".


And get rid of the source of your problems that is "Actor Player".


 


 


Just to explain: A variable has not a value just because of its name. A variable like "Actor Player" has nothing inside until you set a value in. Not just because it is called "Player" it will get the player inside. Normal variable have no "Auto-Fill". Properties are slightly different but just in a few cases. PlayerRef is a magical one that can be auto-filled. But you still have to auto-fill it.


 


0

Share this post


Link to post

My friend. Just do a simple search/replace of "Player." with "PlayerRef.".

And get rid of the source of your problems that is "Actor Player".

 

 

Just to explain: A variable has not a value just because of its name. A variable like "Actor Player" has nothing inside until you set a value in. Not just because it is called "Player" it will get the player inside. Normal variable have no "Auto-Fill". Properties are slightly different but just in a few cases. PlayerRef is a magical one that can be auto-filled. But you still have to auto-fill it.

 

That was very educational and it's not like it wasn't necessary, but it still doesn't do anything. I just don't understand, at the bare minimum it should be giving me the debug message about checking whether the mod's enabled in the MCM. I'm feeling very discouraged now, but thanks a lot for trying to help anyway.

 

0

Share this post


Link to post

This evening I will check in detail all your code and logs. And I will write something to explain what is going on.


Now it is real work time, for me.


0

Share this post


Link to post

This evening I will check in detail all your code and logs. And I will write something to explain what is going on.

Now it is real work time, for me.

 

Thanks my friend, you're a star. Take all the time you need. Sigh, but I was really hoping (before starting this thread) that this script would work and you'd be proud of me for figuring out how to write one on my own.

 

0

Share this post


Link to post

I am proud of you.


1) You try


2) You are not afraid to ask for help


3) You do great progresses


4) You already released a mod that is appreciated


5) You are not afraid to try new things


6) You are not afraid to learn


 


If you were my son/daughter, I had already put a sticker on my car saying: "Proud of my best new Papyrus learner."


0

Share this post


Link to post

I am proud of you.

1) You try

2) You are not afraid to ask for help

3) You do great progresses

4) You already released a mod that is appreciated

5) You are not afraid to try new things

6) You are not afraid to learn

 

If you were my son/daughter, I had already put a sticker on my car saying: "Proud of my best new Papyrus learner."

 

Aw shucks, I'm genuinely touched, thanks. Helped me be less discouraged.

0

Share this post


Link to post

The key is to track down the disconnect. I would recommend putting unconditional debug notifications at the top of each function and event to make sure they are being called. Are you even getting the "Simpler Slavery Detected" notifiction from the SimplerSlaveryTriggerScript.psc OnInit()? Is the owning quest set to Start Game Enabled?


 


 


Looking at SimplerSlaveryTriggerScript.psc again I think I (or we) may have misunderstood what the intention here is.


 


Right now the MCM is pushing values to JSON and then your trigger script is trying to pull them back again. I've not used the JSON functions myself but I'm sure this is not the way to do it. JSON is really for long term storage and communication between different saves.


 


Rather than send the value to JSON we can just read it straight from the MCM script. In fact you're halfway there since you have the Config property declared in your trigger script (assuming this property is pointed to the SimplerSlaveryMCMScript in CK).


 


So what we have now is:



If Player.getav("Health") > JSONUtil.GetFloatValue("SimplerSlavery", "SRSMinHealth")
    [...]
EndIf

What we should be doing is:



If Player.getav("Health") > Config.Minhealththreshold
    [...]
EndIf

In order for that to work Minhealththreshold must be made a property of SimplerSlaveryTriggerScript rather than just a variable so we edit the declaration in SimplerSlaveryMCMScript from:



Float Minhealththreshold = 25.0

to:



Float Property Minhealththreshold Auto

Then pull up the script in CK and edit that new property value to your default value. Now Your trigger script should have direct access to the value rather than sending it through a different process.


 


Not sure if that will help with the immediate problem but it can't hurt.


0

Share this post


Link to post
Sign in to follow this  
Followers 0