Jump to content

Inter-Communication script and local conditions statements


Recommended Posts

Hi guys,

 

I'm having 3 scripts communicating with each other, the simplest way by casting the script which defines the function I want to use.

 

While this works 99% as intended, I'm under the impression that local bool (simple bool, not a property one) are not read remotely. And that's kind of tricky to debug in this particular situation because I'm using arrays, sounds and a fade-to-black in the same time.

 

I'm not sure my English is good enough to make my question clear, so here's an example of what I'm trying to do.

 

Let's say that's my script 1 defining the functions I'm going to use in my 2 other scripts:

Scriptname MyLocalScript01 extends ObjectReference

bool isOn

Function MyFunctionA()				; function used by this script
	If isOn					; non-property bool condition - that's the one not reliably read by my second script
		SomeNativeFunction()
		isOn = false
	EndIf
EndFunction

Function MyFunctionB()				; function used by this script
	If !Self.IsDisabled()		        ; reference state condition - read correctly by my second script
		SomeArrayFunction()
	EndIf
EndFunction

Function MyFunctionC()				; function used by this script
	If MyGlobalVariable.GetValue() == 1	; Global condition - properly read by my second script too
		DoSomethingElse()
	EndIf
EndFunction

Function MyRemoteFunction()
	MyFunctionA()
	MyFunctionB()
	MyFunctionC()
EndFunction

And here's an example of another script trying to communicate with the 1st one:

Scriptname MyLocalScript02 extends ObjectReference

ObjectReference Property MyReference01 Auto
; can't directly set the script as a property because I also call functions on specific references here

Event OnSomeEvent()
	MyReference01.SomeNativeFunction()
EndEvent

Event OnSomeOtherEvent()
	(MyReference01 as MyLocalScript01).MyRemoteFunction()
EndEvent

When script 02 runs and calls "MyRemoteFunction", MyFunctionC() and MyFunctionB() work just as intended while MyFunctionA() is not reliable, at times it works, other times it doesn't.

 

So I was under the impression which may be wrong that if I'm remotely using conditions pointing to a specific state of a reference property or a global condition, they are indeed read properly. However if I'm using a local "If" as this "bool isOn" here, which is not a property, the second script does not always read it properly.

 

Would you say that assuption might be correct?

 

Again not easy to debug, all functions work fine separately on the original script, and there may be other reasons why this bool is not read properly, functions may be overlapping when papyrus execute them, and this bool value changes many times in script01 - so that may be another explanation.

 

Anyway, any input or advice would be very much appreciated - many thanks in advance :smile:

Link to comment
Share on other sites

All you need to do is make your bool a property and then you can change it from outside scripts. But as to your theory, calling script functions remotely doesn't have an adverse impact on how the function runs within the script. In other words your remote script isn't (and doesn't need to) "reading" the bool in the script you're invoking functions.

Edited by Reneer
Link to comment
Share on other sites

Hey thanks Reneer - actually I just tried that, making my bool a property, right after I posted that topic, and it still doesn't always return as I'd want it to in my "remote" function. I'm still unsure whether it's reading the default property value (in this case = false) or the current value in script 1 which should be = true. But that runs in a script that's several hundreds lines long and does a lot of stuff among which changing that bool value frequently, so I gotta run a few more checks before I can say for sure.

 

As for my "theory" (sort of ;)), yeah I know that calling a function remotely doesn't affect the function within the referal script, my question was more the other way around, like "when you call a function remotely, will that remote script fetch current values or variables for their current states within the whole referal script or will it just fetch values as they're set as properties?" (not sure that's any clearer - I'm sorry if my English isn't good enough to be understandable :/)

 

Also I was under the impression that Institute Papyrus runs functions in turns - like in the example above, MyRemoteFunction would run MyFunctionA() first, then run MyFunctionB() once A is done, then again run MyFunctionC() once B is done - maybe I'm wrong thinking that, which could explain one function interfering with another at times and giving me uneven results when they do not run in the order I want them do.

Link to comment
Share on other sites

It does sound like a threading issue. As for remote scripts and properties the remote script will simply read whatever the property is currently set as. That is if you have a bool property that is originally set to false, then your script changes the property to true, then the remote script will read the property as true.
Link to comment
Share on other sites

Yup, thank you both - I had read that wiki page a little while ago (it's actually that page which gave me the impression functions "queue") but that's also where English not being my native language can lead me to misinterpretations, especially since everything I know about coding I learnt modding Skyrim or Fallout - I wouldn't even know how to translate half of this coding vocabulary in my language!.. :ermm:.

 

And you're both right, it is very likely a threading issue. Looks like my remote function reads the value as false, does its thing, then changes it to true - and at some point a few milliseconds later comes back to process the other functions, finds the value to be true and reverses its first action. That's why at times it'll work as expected, and some other times won't. It's probably a threading issue between the 3 functions I call in one. Damn... I don't suppose calling Utility.Wait(0.1) between would help much, right? ;)

Link to comment
Share on other sites

This is where one can get into some complex interprocess control and state management with exciting terms like Mutex, Semaphore and Spinlock.

 

Consider using simple Int or Bool lock flag variables to let other scripts know when they can or can not update local variables.

 

EDIT LOL :)

Edited by SKK50
Link to comment
Share on other sites

LOL... Mutex, Semaphore and Spinlock?.. :teehee: Right... My limited English is having a ball - I'm pretty sure what a semaphore is for me is not at all what you have in mind ;)!.. And spinlock, I roughly get the concept behind the word, I guess it's a lock which revolves around itself... but ok, I'll dig into that ;)

 

States are what I would have instinctively used here, but I'm using this on a hard-coded activator where the "activate" function is a simple toggle states one and I don't want to block activation for many other reasons. Many thanks in any case, guys, you've already convinced me it's a threading issue and my variables are not to blame - I'll get to it, I usely do even if in some cases, I find some "creative" workaround to get there ;)

Link to comment
Share on other sites

Well, turns out I was pretty much like Moliere's Mr Jourdain, and had been using all those spinlocks, semaphores and mutex without even knowing it :laugh:

 

So for those of you guys who are like me, struggling with both Papyrus and coding jargon as well as a language (English) that is not native to them, here's my understanding of it all - with a huge warning, ok, I have no background at all in coding.

 

Pretty much like the old real life semaphores which were used by ships to communicate before we invented Morse code and radio, a Semaphore is a way to send a signal between several scripts or several instances of the same script.

 

My understanding is Semaphores are binary variables, like the use of bools for instance, which are either true or false, or the use of "wait" - either you wait or you don't.

 

A Mutex (means Mutual Exclusion) is pretty much the same thing, except for the fact that only the thread which locked that variable can unlock it. If I create a bool inside a script without making it a property for instance, that bool can only be modified by the script which created it. Whereas if I make it a Property, it can be both accessed and modified by other scripts or other instances of the same script. I suppose it can then be called a semaphore.

 

I also suppose in some instances, a GlobalVariable or a Keyword can provide the same "signaling" usage in Papyrus. Probably truer for a GlobalVariable as GetValue() or SetValue are non-delayed functions.

 

A Spinlock is typically the use of "while" in Papyrus, to make sure a function completes its job before the script (or the VM) moves on to something else.

 

Like this for instance - which will "lock" my thread to loop inside "while" until my "isRunning" bool is no longer false:

 

If !isRunning ; or !is3DLoaded() - or anything else which can either be true or false and may for some reasons be delayed

while !isRunning

utility.Wait(0.1)

endWhile

; now I know for sure that isRunning has become true, I can safely move on to what I need to do next

endIf

 

As for States, which are very useful too, I'm not sure they can be regarded either as semaphores or mutex, because they do not exclude each other, a script can be simultaneously in the "DoSomehing" state and in a "BusyDoNothing" state.

 

I hope my limited English is understable enough - and please, please do correct me if I'm wrong - thanks!.. :smile:

 

As for the script I was working on when I started this thread, I solved my issue by moving things around basically, placing my locks earlier in my script and changing the order in which my functions were called.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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