Pim_gd's Mods - DialogueActions v4.08 (15 Jan 2017)

Jaxx

Content Creator
Joined
Aug 15, 2016
Location
France
Does this code really work? I believe you would have to write [*var1*] to get to the proper linetype.
For everything else you're totaly right. I didn't use the [SETVAR] trigger much, but it seems to me I read somewhere on the forum that it was refering to the same memory vars than the ones you set in the options of a line, and I think I remember successfully handling this very variable in both way, so it's reliable yes.
 

SkyHeart

Avid Affiliate
Joined
Apr 17, 2017
Does this code really work? I believe you would have to write [*var1*] to get to the proper linetype.
For everything else you're totaly right. I didn't use the [SETVAR] trigger much, but it seems to me I read somewhere on the forum that it was refering to the same memory vars than the ones you set in the options of a line, and I think I remember successfully handling this very variable in both way, so it's reliable yes.
Yes you're right, it totaly should be [*var1*] my bad :oops:
Thanks a lot
 
Last edited:

SkyHeart

Avid Affiliate
Joined
Apr 17, 2017
Hi

I have a question about how da handles math

I have this:
*( Progress.girl.schedule.hour1 != none ) x ( ( Progress.time + newValue + 1 ) - ( 24 x ( ( Progress.time + newValue + 1 ) > 24 ) ) )*

If "Progress.girl.schedule.hour1 != none" is 0

Does it still do the rest of substitutions and math or does it default the next set of parentheses to 0?
 

Jaxx

Content Creator
Joined
Aug 15, 2016
Location
France
If my memory doesn't fail me, DA uses to parse expressions before it lets AS compute them, so the whole expression will be processed. But it would be best to have Pim_gd Pim_gd confirmation about this.
 

SkyHeart

Avid Affiliate
Joined
Apr 17, 2017
If my memory doesn't fail me, DA uses to parse expressions before it lets AS compute them, so the whole expression will be processed. But it would be best to have Pim_gd Pim_gd confirmation about this.
Thank you, I'll wait for Pim's answer before I go rewrite my expresions
 

Pim_gd

Club Regular
Joined
Jan 25, 2013
Thanks Jaxx Jaxx for pinging me as that gets my attention.

I'll answer SkyHeart SkyHeart 's question.

TL;DR at the bottom, long explanation in between.

If you look at the source code on bitbucket, then you'll see the following functions:

Code:
		public function variableInsert(args:Array) { //No return type, might cause problems
			if (args.length != 4) {
				return;
			}
			var x:* = getVariableValue(args[1]);
			if (x != undefined) {
				return x;
			} else {
				var index:int = findIndexOfNextSplit(args[1]);
				if (index != -1) {
					return evaluateStringQuation(args[1]);
				}
			}
		}
		
		public function evaluateStringQuation(str:String):Number {
			var arr:Array = str.split(" ");
			for (var i:uint = 0, isize:uint = arr.length; i < isize; i++) {
				var variableName:String = arr[i];
				var value:String = getVariableValueViaSDT(variableName);
				if (value != "") {
					arr[i] = value;
				}
			}
			var variable:String = arr.join(" ");
			return StringQuation.equationMath(variable);
		}
The variableInsert function is DA's hook for inserting a variable. If it does not find a result, it falls back to SDT's own variable system to fetch the variable.

For reference, findIndexByNextSplit:

Code:
		public function findIndexOfNextSplit(variable:String):int {
			var operators:Array = ["+", "-", "*", "%", "/", "\\", "(", ")", "==", "!=", "<=", ">=", "||", "&&", ">", "<", "="];
			if (operators.indexOf(variable) != -1) {
				return -2; //Nope, not an operator, truuuust me. Hotfix to prevent false positive errors.
			}
			
			var checkArray:Array = new Array();
			checkArray.push([variable.indexOf("+"), "+"]);
			checkArray.push([variable.indexOf("-"), "-"]);
			checkArray.push([variable.indexOf("*"), "*"]);
			checkArray.push([variable.indexOf("%"), "%"]);
			checkArray.push([variable.indexOf("/"), "/"]);
			checkArray.push([variable.indexOf("\\"), "\\"]);
			checkArray.push([variable.indexOf("("), "("]);
			checkArray.push([variable.indexOf(")"), ")"]);
			checkArray.push([variable.indexOf("=="), "=="]);
			checkArray.push([variable.indexOf("!="), "!="]);
			checkArray.push([variable.indexOf("<="), "<="]);
			checkArray.push([variable.indexOf(">="), ">="]);
			checkArray.push([variable.indexOf("||"), "||"]);
			checkArray.push([variable.indexOf("&&"), "&&"]);
			checkArray.push([variable.indexOf(">"), ">"]); //Yes, I could have skipped <= and >=, but I didn't feel like it.
			checkArray.push([variable.indexOf("<"), "<"]);
			checkArray.push([variable.indexOf("="), "="]);
			checkArray.sortOn([0], [Array.NUMERIC]); //And voila.
			for (var i:uint = 0, isize:uint = checkArray.length; i < isize; i++) {
				if (checkArray[i][0] != -1) {
					return checkArray[i][0];
				}
			}
			return -1;
		}
What findIndexForNextSplit does is finding operators in variable names. Yes, names. Since variable insertions (the things with asterisks on both sides, e.g. *var1* or *var1 + var2* reference variable names, it has to search in variable names.

(I guess there's a bug in there where if you define x to be * it doesn't see it as an operator and thus you need to use parentheses if you want DA to always recognize something as an equation...)

Back to variableInsert.

Code:
			var x:* = getVariableValue(args[1]);
			if (x != undefined) {
				return x;
			} else {
				var index:int = findIndexOfNextSplit(args[1]);
				if (index != -1) {
					return evaluateStringQuation(args[1]);
				}
			}
getVariableValue for reference:

Code:
		public function getVariableValue(name:String):* {
			if (registeredVariablesGet.hasOwnProperty(name)) {
				return registeredVariablesGet[name].call();
			}
		}
getVariableValue checks if there is any hook defined via DA for the variable we're gonna insert. This is to handle things like da.clothes, which are not really variables but functions made to reply if you ask for the variable value of "da.clothes"-like variables.

Right, back to variableInsert for real this time.

Code:
			var x:* = getVariableValue(args[1]);
			if (x != undefined) {
				return x;
			} else {
				var index:int = findIndexOfNextSplit(args[1]);
				if (index != -1) {
					return evaluateStringQuation(args[1]);
				}
			}
If getVariableValue does not return undefined, that is to say, if there is a hook for the variable name you want, then we return the value the hook gives back.

Else, (if there is no hook), check if the variable name contains an operator by asking for the position of the next operator and checking if it is not the error-code for not finding a next operator. Whew, double negations. If that's true, then treat the variable name as a "StringQuation" (a string containing an equation) and evaluate it.

In simpler code:

Code:
			var requestedVariableName:* = args[1];

			if (hasHookFor(requestedVariableName)) {
				var valueFromHook:* = getValueFromHook(requestedVariableName);
				return valueFromHook;
			}

			if (containsOperators(requestedVariableName)) {
				var valueFromEquation:* = evaluateStringQuation(requestedVariableName);
				return valueFromEquation;
			}
			
			//fallback to SDT
Riiiight. Now that we've had that entire infodump which serves as pretext; let's answer the question. If I have an equation, how is it parsed? Does DA shortcircuit?

Well, yes and no. What a useless answer.

So I'll explain using the code again.

For reference, evaluateStringQuation.

Code:
		public function evaluateStringQuation(str:String):Number {
			var arr:Array = str.split(" ");
			for (var i:uint = 0, isize:uint = arr.length; i < isize; i++) {
				var variableName:String = arr[i];
				var value:String = getVariableValueViaSDT(variableName);
				if (value != "") {
					arr[i] = value;
				}
			}
			var variable:String = arr.join(" ");
			return StringQuation.equationMath(variable);
		}
Lot of code here, but basically;

Split the input by spaces. That means, the input string "(var1xvar2)" becomes an array of ["(var1xvar2)"], and the input string of "( var1 x var2 )" becomes an array of ["(", "var1", "x", "var2", ")"].

For each of the values within the array, if SDT has such a variable, replace the variable with its value as String.

So if we have var1 as 10, var2 as 20 and x as *, our array will change to ["(", "10", "*", "20", ")"].

Next, join the string with spaces. That means, take that string representation of the array I just gave, and replace every instance of doublequote-comma-space-doublequote with a single space. That nets us "( 10 * 20 )".

Lastly, hand it off to StringQuation.equationMath, and return its result. Basically, do the equation.

What we see in this section is that ALL referenced variables are replaced. And I have to do this, because, imagine this equation:

0 * variable

Well, 0 times a variable is obviously zero, right? Except we work via substitution, not performing the operation. So what would happen if variable had the value of "0 + 5"?

You'd get this equation:

0 * 0 + 5

Which would resolve to 5 in left-to-right and PEMDAS systems. DA is a left-to-right system, by the way. It was easier to program.

Okay, but how are the equations done?

For that I point you to the StringQuation source code: Pim_gd / SDTDialogueActions / source / src / StringQuation.as — Bitbucket

I'm not going to explain the exact code here, but it works something like this:

Code:
function equationMath( equation:String ):*
	loop over characters in equation
		if we find parenthesis, extract the section in between the parenthesis and run it as a separate equation math call, then replace the parenthesised section with the result from the function call
		otherwise, start trying to determine what we find first in the equation
			if it is an operator, set the operator to be used
			if it is not an operator, add it to the list of values
	once we have processed all the characters in the equation
	set result to be the first value
	loop over operators
		apply operators, with result as left hand value, and the next value in the value list as right hand value
		(for example, - is defined as result = result - values[nextValueIndex]; nextValueIndex = nextValueIndex + 1;)
	once we're done, return the result.
You can see the operator implementations here Pim_gd / SDTDialogueActions / source / src / StringQuation.as — Bitbucket

What this means is that no operator skipping occurs.

To sum all this up:
  • DA inserts all the variables into equations first
  • DA evaluates from left to right
  • DA has a stupid bug where if your operators are hidden in variables then it doesn't know it is an equation, so wrap your equations in parentheses
  • DA uses spaces to separately convert variables in equations, so use spaces around your variables at the very least
  • DA's operators could ignore values in equations if they wanted to (short-circuiting is possible)
  • DA's algorithm of solving equations means there's no real benefit in short-circuiting, as all the processing is done first to get simple numerical equations

What this means is that no, DA does not short circuit, but yes, DA could short-circuit, but no, DA would not benefit from short-circuiting, as the only difference is...

When your gigantic equation of

( Progress.girl.schedule.hour1 != none ) x ( ( Progress.time + newValue + 1 ) - ( 24 x ( ( Progress.time + newValue + 1 ) > 24 ) ) )

is reduced to 0 * 5 after processing for a while, does it matter if we just calculate 0 times 5, or if we say "oh, zero times anything IS zero, so best to just return zero".
 
Last edited:

SkyHeart

Avid Affiliate
Joined
Apr 17, 2017
Pim_gd Pim_gd Thank you so much for the in depth explenation.

I thought maybe DA had a special case if it finds itself multiplying 0 to an expresion inside parantheses, it will just skip to the other side and default it all to 0.

Funny thing is that I only thought about it after I wrote like every other expresion the opposite way :grin::grin:
 

DigitalSmutExports

Content Creator
Joined
Sep 12, 2018
Does the buttons function rely on something other than Dialogue Actions? I can't for the life of me get it to work. I even downloaded some dialogues with buttons in them and they don't work.
 

SkyHeart

Avid Affiliate
Joined
Apr 17, 2017
Does the buttons function rely on something other than Dialogue Actions? I can't for the life of me get it to work. I even downloaded some dialogues with buttons in them and they don't work.
Hi,
No, buttons are entirely DA.

Is DA actually loading? A method I use to see that is to instead of waiting for the play/setting screen to disappear due to moreclothing, I quickly press play and look in the top right corner of the game window, there you should see all of the mods loading in the order you have them in your "mods.txt" file.
 

DigitalSmutExports

Content Creator
Joined
Sep 12, 2018
OK,

One more from me. What on God's green earth is wrong with the following?

Code:
start:"[test]" {"style":"Him"}

test:"[LOAD_FULL_CHARCODE][test2] See if we get this far"{"style":"Him","set":{"da.charcode.load":"charName:Test Chan;mood:Normal;bodyScale:1;arms:onlegs,onlegs;throatResist:50;hair:jillvalentine,1,1,1,1;iris:normal,56,100,137,1;breasts:110;skin:light;nose:normal;ear:normal;lipstick:0,0,0,0,0;eyeshadow:55,26,99,1;sclera:255,255,255,1;blush:196,80,77,0.35;freckles:60,24,24,0.8,0;mascara:0,0,0,1,20;nailpolish:0,0,0,0;eyebrow:normal,45,25,16,1,30,19,19,1;hairhsl:0,1,1,1;skinhsl:0,1,1,1;hisskinhsl:0,1,1,1;bg:3;hisBody:male;hisPenis:0,1.017,1.055;balls:1,1;hisSkin:0;hisTop:none,238,242,245,1;hisBottoms:slacks,27,29,29,1;hisFootwear:loafers,0,0,0,1;collar:leather,0,0,0,1,232,240,255,1;cuffs:leather,0,0,0,1,230,239,255,1;gag:none,0,0,0,1,0,0,0,1;panties:none,255,255,255,1,0,0,0,1;top:none,255,255,255,1,0,0,0,1;armwear:none,0,0,0,1,0,0,0,1;legwear:none,0,0,0,1,0,0,0,1;footwear:none,0,0,0,1,0,0,0,1;eyewear:none,0,0,0,1,0,0,0,1;headwear:none,24,24,24,1,255,255,255,1;tonguePiercing:none,230,239,255,1,0,0,0,1;herTan:none,0;nippleButton:Auto;moremoods:Normal;moreclothingbody:Fangs L;moreclothingBG:School","da.bgm.volume":0.02}}

test2:"Finish line" {"style":"Him"}
test runs, the charcode loads correctly (!), but that's as far as we get. "See if we get this far" (on the test line after the code) doesn't play.
Does anyone have a clue what's wrong? DA bug?
 

DigitalSmutExports

Content Creator
Joined
Sep 12, 2018
Try to put [test2] at the back of the spoken line, not in front.
Nope, that's not the issue. I usually put the [NextLine] at the end. Just put a spoken line there to see where we come to a halt after already having established that it doesn't go to test2 with NO spoken line.
 
Last edited:

Jaxx

Content Creator
Joined
Aug 15, 2016
Location
France
Try this
Code:
start:"[test]" {"style":"Him"}

test:"[LOAD_CHARCODE][test2] See if we get this far"{"style":"Him","set":{"da.charcode.load":"charName:Test Chan;mood:Normal;bodyScale:1;arms:onlegs,onlegs;throatResist:50;hair:jillvalentine,1,1,1,1;iris:normal,56,100,137,1;breasts:110;skin:light;nose:normal;ear:normal;lipstick:0,0,0,0,0;eyeshadow:55,26,99,1;sclera:255,255,255,1;blush:196,80,77,0.35;freckles:60,24,24,0.8,0;mascara:0,0,0,1,20;nailpolish:0,0,0,0;eyebrow:normal,45,25,16,1,30,19,19,1;hairhsl:0,1,1,1;skinhsl:0,1,1,1;hisskinhsl:0,1,1,1;bg:3;hisBody:male;hisPenis:0,1.017,1.055;balls:1,1;hisSkin:0;hisTop:none,238,242,245,1;hisBottoms:slacks,27,29,29,1;hisFootwear:loafers,0,0,0,1;collar:leather,0,0,0,1,232,240,255,1;cuffs:leather,0,0,0,1,230,239,255,1;gag:none,0,0,0,1,0,0,0,1;panties:none,255,255,255,1,0,0,0,1;top:none,255,255,255,1,0,0,0,1;armwear:none,0,0,0,1,0,0,0,1;legwear:none,0,0,0,1,0,0,0,1;footwear:none,0,0,0,1,0,0,0,1;eyewear:none,0,0,0,1,0,0,0,1;headwear:none,24,24,24,1,255,255,255,1;tonguePiercing:none,230,239,255,1,0,0,0,1;herTan:none,0;nippleButton:Auto;moremoods:Normal;moreclothingBG:School","da.bgm.volume":0.02}}

test2:"[MoreclothingBodyON_Fang_space20_L]Finish line" {"style":"Him"}
The [MoreclothingBody[ON|OFF]_myExoticModNameHere] trigger should allow you to bypass the [LOAD_CHARCODE] limitations and do not break your dialog flow. If the mod name has spaces, replace them by _space20_

I do not know if [LOAD_CHARCODE] will be able to process nippleButton, moremood, and moreclothingBG though... (however you can ommit this last one, bg:3 is enough)
Let us know
 

DigitalSmutExports

Content Creator
Joined
Sep 12, 2018
The [MoreclothingBody[ON|OFF]_myExoticModNameHere] trigger should allow you to bypass the [LOAD_CHARCODE] limitations and do not break your dialog flow
Thanks Jaxx. I'm quite new to dialogue coding and it didn't occur to me to check for moreclothing triggers - just been consulting the DA ones. Thanks for that one. I was using a makeshift solution of simply assigning body mods to other menus but that was never going to be sustainable in the long run.

This works just fine ...
Thanks. Lots to digest there. Will get on that.
 
Top Bottom