Ryyz Posted January 20, 2018 Author Share Posted January 20, 2018 (edited) Beat to the punch... Tho I'll post what I came up with. I suggest changing your magic effect (the one your script is attached) to have a duration of 90 seconds. Thus you can use the OnEffectFinish event to drop the global value by 25. Other changes are that I kept it as float, I didn't see where it needed to be used as an integer. Also, I used Mod. In theory, Mod is more thread safe but mileage may vary... ScriptName WA_ToxicityScript Extends ActiveMagicEffect ;GlobalVariable that disallows potion. 0 is disallow. 1 is allow. disallow once toxicity is at 100. allow when below GlobalVariable Property DisallowPotion Auto ;Toxicity level integer. default 0. max 100. GlobalVariable Property ToxicityLevel Auto Event OnEffectStart (Actor akTarget, Actor akCaster) ;Check if toxicity level is less than 100. If it is add 25 to toxicityamount. If (ToxicityLevel.GetValue() < 100.0) DisallowPotion.SetValue(1) ToxicityLevel.Mod(25.0) Debug.Notification("You drink the potion. Toxicity is now "+ToxicityLevel.GetValue()) EndIf ;Check is toxicitylevel is 100. if it is set globalvariable to 0. If (ToxicityLevel.GetValue() == 100.0) DisallowPotion.SetValue(0) Debug.Notification("Your toxicity amount is too high. Drinking another potion would kill you.") EndIf EndEvent Event OnEffectFinish(Actor akTarget, Actor akCaster) If ToxicityLevel.GetValue() != 0 ToxicityLevel.Mod(-25.0) Debug.Notification("Your toxicity amount is now "+ToxicityLevel.GetValue()) EndIf EndEvent Hmm. Good idea on the effect duration, but there's a problem with that. If you were to drink another potion before the effect ends, it would take it back down instantly. I feel I'd need a script that checks every 90 seconds or so if the toxicity is above 0, if it is then run the decrease system. Any ideas? Also, upon testing I realized something. The original script, the decrease thing would only do it once after every potion consumption which won't work. Edited January 20, 2018 by Ryyz Link to comment Share on other sites More sharing options...
JonathanOstrus Posted January 20, 2018 Share Posted January 20, 2018 I'm pretty sure you can make stackable effects. I'm not sure of the specifics. Link to comment Share on other sites More sharing options...
Ryyz Posted January 20, 2018 Author Share Posted January 20, 2018 I'm pretty sure you can make stackable effects. I'm not sure of the specifics.I'm sure I could.... but then you run into the problem of it being really OP... for example, one of the potions increases damage output. so if you stack those types of effects it would make the player ridiculously OP. Link to comment Share on other sites More sharing options...
FrankFamily Posted January 21, 2018 Share Posted January 21, 2018 Maybe i'm missing something thatbhas been said previously but couldnt you separate both things? so you have potions that simply add toxicity and then a script running on the player via a an ability or alias that removes X toxicity every Y seconds (registerforupdate or registerforupdategametime). Link to comment Share on other sites More sharing options...
IsharaMeradin Posted January 21, 2018 Share Posted January 21, 2018 Maybe i'm missing something thatbhas been said previously but couldnt you separate both things? so you have potions that simply add toxicity and then a script running on the player via a an ability or alias that removes X toxicity every Y seconds (registerforupdate or registerforupdategametime). That might work in the short term. But will fail when waiting/sleeping for periods longer than the designated duration. The update event would only run once after the sleep/wait menus close. Thus storing the current time when the update is registered and comparing that to the new current time when the update fires and doing a bit of math to determine if multiple stages of toxicity need to be removed would be a necessary step. Link to comment Share on other sites More sharing options...
Ryyz Posted January 22, 2018 Author Share Posted January 22, 2018 (edited) Maybe i'm missing something thatbhas been said previously but couldnt you separate both things? so you have potions that simply add toxicity and then a script running on the player via a an ability or alias that removes X toxicity every Y seconds (registerforupdate or registerforupdategametime). That might work in the short term. But will fail when waiting/sleeping for periods longer than the designated duration. The update event would only run once after the sleep/wait menus close. Thus storing the current time when the update is registered and comparing that to the new current time when the update fires and doing a bit of math to determine if multiple stages of toxicity need to be removed would be a necessary step. That's the reason I used Utility.WaitIdk how else to do it without that happening. So I made a little oninit script. I attached it to a blank quest and had the quest run on startup, the script runs but it doesn't actually work. Basically the debug message box I made telling me its running shows up, but when I drink the potion the debug box telling me that its working doesn't appear and the toxicity doesn't go down. ScriptName WA_ToxicityRemovalScript Extends Quest GlobalVariable Property ToxicityLevel Auto Event OnInit () Debug.MessageBox("Script running.") ;Checks if toxicity level is greater than zero. If it is, remove 25 toxicity every 60 seconds. If (ToxicityLevel.GetValue() > 0) Debug.MessageBox("Script working.") Utility.Wait(60) ToxicityLevel.Mod(-25) Debug.Notification("Toxicity level is now "+ToxicityLevel) EndIf ;Checks if toxicity level is 0. If it is do nothing. If (ToxicityLevel.GetValue() == 0) EndIf ;Checks if toxicity level is less than 0. If it is set the value to 0 If (ToxicityLevel.GetValue() < 0) ToxicityLevel.SetValue(0) EndIf EndEvent I also tried attaching it to a quest alias but the script didn't load at all. I set the reference to player. I don't really understand how quest aliases work anyway.I put the last one as a precaution in case the value ever goes below 0. In case you were wondering, yes I put the correct global property in CK.Also I was already planning on separating them before frank said that. I realized it wouldn't function properly as a magic effect. Edited January 22, 2018 by Ryyz Link to comment Share on other sites More sharing options...
JonathanOstrus Posted January 22, 2018 Share Posted January 22, 2018 (edited) Maybe i'm missing something thatbhas been said previously but couldnt you separate both things? so you have potions that simply add toxicity and then a script running on the player via a an ability or alias that removes X toxicity every Y seconds (registerforupdate or registerforupdategametime). That might work in the short term. But will fail when waiting/sleeping for periods longer than the designated duration. The update event would only run once after the sleep/wait menus close. Thus storing the current time when the update is registered and comparing that to the new current time when the update fires and doing a bit of math to determine if multiple stages of toxicity need to be removed would be a necessary step. That's the reason I used Utility.WaitIdk how else to do it without that happening. So I made a little oninit script. I attached it to a blank quest and had the quest run on startup, the script runs but it doesn't actually work. Basically the debug message box I made telling me its running shows up, but when I drink the potion the debug box telling me that its working doesn't appear and the toxicity doesn't go down. ScriptName WA_ToxicityRemovalScript Extends Quest GlobalVariable Property ToxicityLevel Auto Event OnInit () Debug.MessageBox("Script running.") ;Checks if toxicity level is greater than zero. If it is, remove 25 toxicity every 60 seconds. If (ToxicityLevel.GetValue() > 0) Debug.MessageBox("Script working.") Utility.Wait(60) ToxicityLevel.Mod(-25) Debug.Notification("Toxicity level is now "+ToxicityLevel) EndIf ;Checks if toxicity level is 0. If it is do nothing. If (ToxicityLevel.GetValue() == 0) EndIf ;Checks if toxicity level is less than 0. If it is set the value to 0 If (ToxicityLevel.GetValue() < 0) ToxicityLevel.SetValue(0) EndIf EndEvent I also tried attaching it to a quest alias but the script didn't load at all. I set the reference to player. I don't really understand how quest aliases work anyway.I put the last one as a precaution in case the value ever goes below 0. In case you were wondering, yes I put the correct global property in CK.Also I was already planning on separating them before frank said that. I realized it wouldn't function properly as a magic effect. To identify the first part of the problem I would suspect the reason you get the startup msg but nothing else is because at the time the OnInit() runs the value of ToxicityLevel is probably actually 0. So nothing happens. The times when OnInit is run is "For Quests and Aliases: On game startup, and again whenever the quest starts, due to the quest being reset." as per the wiki https://www.creationkit.com/index.php?title=OnInit. Though the way you describe the events is confusing. You shouldn't get any message from the quest when you drink your potion. Because the quest is already running. Any potential message from the quest should happen immediately upon start of the game. Also semi-relevant, did you make a .SEQ file for your plugin to properly identify the start enabled quest? The OnInit() MUST run very fast. It is also latent(?) or maybe blocking is the right term. Never put a Wait() in there, EVER. In fact almost always you should set an update timer that will trigger a call back to the script to do any work. Something like Event OnInit() RegisterForSingleUpdate(0.01) EndEvent Event OnUpdate() ; do your long running code here EndEvent Another relevant timer choice may be RegisterForSingleUpdateGameTime https://www.creationkit.com/index.php?title=RegisterForSingleUpdateGameTime_-_Form You would probably need to change your code for incrementing toxicity on your magic effect. Perhaps have it call a function on the quest script to do the incrementing via a global.mod() call. That way the whole thing is threadsafe in case you pop multiple drinks at once. Otherwise there's issues where the counter will not increment properly. Edited January 22, 2018 by BigAndFlabby Link to comment Share on other sites More sharing options...
IsharaMeradin Posted January 22, 2018 Share Posted January 22, 2018 The OnInit event runs only when the quest starts up. If you're wanting to catch something after the quest has already started, you don't want to use the OnInit event. You will need to register for an update and track the current time. Here is my suggestion: Quest script: GlobalVariable Property ToxicityLevel Auto Float StartTime Float EndTime Function IncreaseToxicity() ToxicityLevel.Mod(25) RegisterForSingleUpdate(60) ;real time StartTime = Game.GetCurrentRealTime() EndFunction Event OnUpdate() EndTime = Game.GetCurrentRealTime() Float Mult = (EndTime - StartTime) / 60 While (Mult as Int) > 0 ToxicityLevel.Mod(-25) Mult -= 1.0 EndWhile EndEvent Potion script:Manually add a property by writing it directly on the script. It must follow this pattern: NameOfQuestScript Property VariableNameToUse AutoThen when you assign data to the property, the CK will list all objects with the 'NameOfQuestScript' script attached. In your case it should just be your quest. So assign your quest to the property.Then inside your OnEffectStart event add using the following pattern: VariableNameToUse.IncreaseToxicity() What this will accomplish is when a potion is drank it will tell your quest script to run the IncreaseToxicity function which will in turn increase the toxicity global and register for a single update. Then when the update triggers, it should decrease the toxicity level. Calculations are in place to cover scenarios where the player might wait or sleep. So test those situations out. FYI - Papyrus always rounds down when converting a float to an int. Thus if the Mult above turned out to be 2.75, it will be treated as a 2 and remove only 50 total in toxicity Link to comment Share on other sites More sharing options...
Ryyz Posted January 22, 2018 Author Share Posted January 22, 2018 (edited) The OnInit event runs only when the quest starts up. If you're wanting to catch something after the quest has already started, you don't want to use the OnInit event. You will need to register for an update and track the current time. Here is my suggestion: Quest script: GlobalVariable Property ToxicityLevel Auto Float StartTime Float EndTime Function IncreaseToxicity() ToxicityLevel.Mod(25) RegisterForSingleUpdate(60) ;real time StartTime = Game.GetCurrentRealTime() EndFunction Event OnUpdate() EndTime = Game.GetCurrentRealTime() Float Mult = (EndTime - StartTime) / 60 While (Mult as Int) > 0 ToxicityLevel.Mod(-25) Mult -= 1.0 EndWhile EndEvent Potion script:Manually add a property by writing it directly on the script. It must follow this pattern: NameOfQuestScript Property VariableNameToUse AutoThen when you assign data to the property, the CK will list all objects with the 'NameOfQuestScript' script attached. In your case it should just be your quest. So assign your quest to the property.Then inside your OnEffectStart event add using the following pattern: VariableNameToUse.IncreaseToxicity() What this will accomplish is when a potion is drank it will tell your quest script to run the IncreaseToxicity function which will in turn increase the toxicity global and register for a single update. Then when the update triggers, it should decrease the toxicity level. Calculations are in place to cover scenarios where the player might wait or sleep. So test those situations out. FYI - Papyrus always rounds down when converting a float to an int. Thus if the Mult above turned out to be 2.75, it will be treated as a 2 and remove only 50 total in toxicityYeah. The OnInit thing slipped my mind. I wrote that code at 4AM. I make mistakes at that time. I haven't actually tested anything since 5AM. As for that code you put, I completely forgot about while. Also, the quest was a dummy quest. Just there to run the script. Tried a bunch of different things. Probably should have clarified that. My mistake. As for the "FYI" I knew that. I know ints can't have decimals. That's what floats are for.As you can tell I'm still learning papyrus. I learn better by doing. I'm also good at analyzing code and figuring out what does what. But thanks a lot for helping me out. I really appreciate it. PS: All my properties are manually added. I do nothing with the script in CK til after its done and ready to be assigned. I use Notepad++ with the papyrus plugin. Compiles, catches errors, and its easier for me to code in. I'll work on it tomorrow and get back to you. Edited January 22, 2018 by Ryyz Link to comment Share on other sites More sharing options...
Ryyz Posted January 24, 2018 Author Share Posted January 24, 2018 The OnInit event runs only when the quest starts up. If you're wanting to catch something after the quest has already started, you don't want to use the OnInit event. You will need to register for an update and track the current time. Here is my suggestion: Quest script: GlobalVariable Property ToxicityLevel Auto Float StartTime Float EndTime Function IncreaseToxicity() ToxicityLevel.Mod(25) RegisterForSingleUpdate(60) ;real time StartTime = Game.GetCurrentRealTime() EndFunction Event OnUpdate() EndTime = Game.GetCurrentRealTime() Float Mult = (EndTime - StartTime) / 60 While (Mult as Int) > 0 ToxicityLevel.Mod(-25) Mult -= 1.0 EndWhile EndEvent Potion script:Manually add a property by writing it directly on the script. It must follow this pattern: NameOfQuestScript Property VariableNameToUse AutoThen when you assign data to the property, the CK will list all objects with the 'NameOfQuestScript' script attached. In your case it should just be your quest. So assign your quest to the property.Then inside your OnEffectStart event add using the following pattern: VariableNameToUse.IncreaseToxicity() What this will accomplish is when a potion is drank it will tell your quest script to run the IncreaseToxicity function which will in turn increase the toxicity global and register for a single update. Then when the update triggers, it should decrease the toxicity level. Calculations are in place to cover scenarios where the player might wait or sleep. So test those situations out. FYI - Papyrus always rounds down when converting a float to an int. Thus if the Mult above turned out to be 2.75, it will be treated as a 2 and remove only 50 total in toxicity Sorry I'm late getting back, been busy the last couple of days. It works beautifully. Thank you so much. Also, that quest script had a mistake in it. Its Utility.GetCurrentRealTime not Game.GetCurrentRealTime. When I first compiled it shot up a bunch of errors. Looked up the function on the CK wiki and fixed it. But again, thanks. Link to comment Share on other sites More sharing options...
Recommended Posts