Jump to content


Photo

[WIP] Expanded Triggers


  • Please log in to reply
88 replies to this topic

#61 i30817

i30817
  • Member
  • 611 posts

Posted 29 April 2012 - 05:27 AM

If I am in a trigger block of 3 triggers, of which trigger 1 and 2 substitute some of the variables in trigger 3, I cannot program so that when the engine is looking at trigger 1, it searches ahead for trigger 3 and replaces some values in it. That would destroy trigger 3 and breaks the GemRB static caching system.


Search ahead is "wait for execution of the script engine to get to it"? I was assuming you could collect the arguments from those new assignment triggers and just wait ("search ahead") for the next trigger that isn't a assigment or triggeroverride or or. Then replace the number of arguments that aren't "DEFAULT" on the trigger struct.
Though i see the problem, you'd wouldn't be able to know which assignment to give to which non-DEFAULT, and would need to use a default order, like "last assignment first" or something like that.
I see now why you're using Eval1 and Eval2.

Hmmm... nasty.

I suppose a compiler trick like WEIDU does for triggeroverride is out of the question?

3 opcode variants (need better names):
EvalBoth(E(0,0),"#1", "#2+5") //E(#1, #2+5)
EvalFirst(E(0,0),"#1")		   //E(#1,0)
EvalSecond(E(0,0),"#1")	 //E(0, #1)

and if possible, to use any trigger... though i don't know how it would work with triggeroverride in the mix
... though it occurs to me that if WEIDU would do a transformation, why not:
Eval(E(#1,0)) => Eval1("#1"), E(-33, 0)
Eval(E(0, #1 + 4)) => Eval2("#1 + 4"), E(0, -33)
Eval(E(#2, #1)) => Eval1("#2"), Eval2("#1"), E(-33,-33)

so there would only be two "real" Eval triggers and one that would appear in the scripts, joined to the trigger it would affect. Not using a string so WEIDU doesn't get confused on a trigger which does have a string argument. Not sure what's best for that - a expression special case that allows #number (math evaluator lib functions would not parse in weidu - but if it passes the lexer it's enough i think - as long as it doesn't get confused by nested "/)/(/," and can distinguish the exp from the ""normal" arguments.)

Edited by i30817, 30 April 2012 - 06:52 PM.


#62 i30817

i30817
  • Member
  • 611 posts

Posted 29 April 2012 - 06:25 AM

I'm not clear yet if E, LT and GT are the only triggers whose arguments can get replaced?

I'm satisfied your mode approach - i'm conditioned to avoid parameter "specialization" arguments, by some years of pedantic professors nagging, don't mind the bite.

I like the "AssignEval" idea, but suggest it to be named "AssignExpr" or something so as not to confuse.
The reason it's not a mode is that it would require two strings right?
Could the mode be a INT argument of "Assign" and thus "AssignExpr" be folded into it
NVM i see why you used a string: so GLOBALS and LOCALS can be assigned with only one string.

Edited by i30817, 29 April 2012 - 06:50 AM.


#63 Ascension64

Ascension64
  • Modder
  • 5983 posts

Posted 30 April 2012 - 01:48 AM

WeiDU compiler tricks

You'll have to pester the bigg about these things. That's not in my thinking at all. TriggerOverride() was never my intention. I was happy to stick with NextTriggerObject() being a completely separate trigger.

I'm not clear yet if E, LT and GT are the only triggers whose arguments can get replaced?

No, the whole point of evaluation in the initial instance is that I can apply it to any trigger of my liking. Hence, the reasons for Eval1() and Eval2() are to replace any qualifying trigger (that is, ones I don't exclude from being detected by Eval*()) with a value: 1 for int1, 2 for int2. If string vars are called for, I use 1 for str1, 2 for str2. So I can do something like:
IF
  Assign("ITEMS", 3, 4, /*#1*/ 1) //ITEMS.2DA x3 y4, say contains some item name
  Eval1("#1")
  PartyHasItem("-33") //-33 gets replaced
THEN...
In the int side of things, I can also do:
IF
  Assign("STAT.LEVEL", /*#1*/ 1)
  Eval1("#1")
  GlobalGT("HighestLevelAllowed", "GLOBAL", -33) //-33 gets replaced
THEN...

I'm satisfied your mode approach - i'm conditioned to avoid parameter "specialization" arguments, by some years of pedantic professors nagging, don't mind the bite.

Fair enough. BGScript is far from ideal. I don't want to add heaps of new triggers for one concept.

I like the "AssignEval" idea, but suggest it to be named "AssignExpr" or something so as not to confuse.

Fine.

The reason it's not a mode is that it would require two strings right?

Well I could make it a mode. Again, I was just overloading to illustrate a a point. The idea would be to use a single Assign() trigger for all assignments.

Edited by Ascension64, 30 April 2012 - 02:16 AM.

--------------
Retired Modder
Note: I do not respond to profile comments/personal messages in regards to troubleshooting my modifications. Please post on the public forums instead.

Baldur's Gate Trilogy-WeiDU and Mods
Throne of Bhaal Extender (TobEx)

Contributions: (NWN2) A Deathstalker (voice acting) - (IWD2) IWD2 NPC Project (soundset editing) - (Misc) SHS PC Soundsets (voice acting)
Legacy: (BG/Tutu/BGT) Beregost Crash Fixer 1.9 (18 Jul 10) - (BG2) Enable conversations with charmed/dominated creatures (18 Jul 10) - (BG2) Experience Corrections (18 Jul 10) - (Misc) Platform Conversion Utility RC2 (13 Feb 10)


#64 i30817

i30817
  • Member
  • 611 posts

Posted 30 April 2012 - 06:42 PM

I really like that preprocessor trick if the compiler itself will not change... it looks like it will prevent errors (besides being shorter)

Other thing: are you planning to "clear"/reset variables on block end? Or after use in Trigger? Because "AssignExpr" would be fairly useless if it could only be used in one trigger.
I think block is much better.

They have to be reset, so as not to corrupt the next block triggers right? (On success and block failure - if Eval2 of a block with Eval1 previously fails for ex).

Edited by i30817, 30 April 2012 - 07:01 PM.


#65 i30817

i30817
  • Member
  • 611 posts

Posted 30 April 2012 - 07:08 PM

Oh i just noticed in your reply that you have overloaded assignments strings too.
That throws a wrench on the "weidu transformation" stuff.
I think i'm going to ask the_bigg for his input on this stuff if you don't mind.

edit: then again, maybe not - if he can use TRIGGER.IDS to see what the type of the argument should be, there should be no problems with the substitution. Just add "" instead of 0 for the string arguments replaced.

Edited by i30817, 30 April 2012 - 07:27 PM.


#66 i30817

i30817
  • Member
  • 611 posts

Posted 30 April 2012 - 08:38 PM

Also, is there really a need of the position argument (the last int) in the Assign functions?

Couldn't it be handled internally? Unless you want reassignment.


edit: Never mind, i can see how 10+ assignments might get confusing.

edit2: just one assignment opcode attempt:

Assign("STAT.LEVEL", 1)
Assign("GLOBAL.xyz", 1)
Assign("LOCAL.xyz", 1)
Assign("HPLEVEL.0.1", 1)//int from 2da - actually, i can't tell if they're supposed to be strings normally instead - they sometimes have strange "default" or marker values. Instead of -1 - this is a problem if you want to use them in expressions. Are you going to error if you read something which is not a int? Ignore the assignment?
Assign("EXPR.#2 + 3 + #1", 1)//not quite sure now if expr assigment is a good idea - recursion is a problem.

And strings?
AssignString("HPLEVEL.0.1", 1)//different opcode, assign var as string for the replacement/script engine
or
Assign("String_HPLEVEL.0.1", 1)//same opcode, parsing inside to distinguish?

edit3: muParserSSE doesn't allow strings in it's expressions. Neither MathPresso i suspect (it's homepage is spare). Since muParserSSE seems to have embedded math functions, i'd prefer it.

edit4: i suspect you might want to setup a limited (and simple) inmemory cache for 2da values that are "assigned". They can't change, and you don't need to parse the 2da again. Unless that data is already inmemory from the engine?
It would be nice if you could compile the expression separately from the variables (so you could cache the compiled code), but this link seems to indicate that you'd need to check that the variables didn't change too - you can't change the variables value after compilation- otherwise, you'd need to recompile. Seems hard to cache - but maybe the jit does it internally.
But if muParserSSE is faster because the benchmark was actually separating the compile function time from the execution - i can't find the benchmark code - then maybe you won't get the "full" performance without caching. But feel free to ignore this stuff, you know the saying about premature optimization.

Edited by i30817, 01 May 2012 - 12:53 AM.


#67 the bigg

the bigg

    2083 is a prime number.

  • Modder
  • 3331 posts

Posted 01 May 2012 - 12:59 AM

Eval(E(#1,0)) => Eval1("#1"), E(-33, 0)
Eval(E(0, #1 + 4)) => Eval2("#1 + 4"), E(0, -33)
Eval(E(#2, #1)) => Eval1("#2"), Eval2("#1"), E(-33,-33)
That could be done, but isn't particularly helpful if the Assign* must be repeated for every trigger and be kept in a separate trigger.

Also note that, while #num is fine inside a string, it isn't when used by itself - the BAF compiler assumes it is a TLK reference and strips the #.

Italian users: help test the Stivan NPC!

Author or Co-Author: WeiDU - Widescreen - Generalized Biffing - Refinements - TB#Tweaks - IWD2Tweaks - TB#Characters - Traify Tool - Some mods that I won't mention in public
Maintainer: Semi-Multi Clerics - Nalia Mod - Nvidia Fix
Code dumps: Detect custom secondary types - Stutter Investigator

If possible, send diffs, translations and other contributions using Git.


#68 i30817

i30817
  • Member
  • 611 posts

Posted 01 May 2012 - 02:48 AM

What are the prefixes which are free in weidu?

I didn't put it in a string because i know that bgscript doesn't have multipart expressions in the arguments (or indeed, anything other than a number, point, object specifier or a string), so i was hoping that weidu could recognize a
multi-part expression | single variable expression | function
in a argument of a trigger inside eval (even better would be generally, so the Eval() pseudo-opcode isn't needed).
If it was a string, i don't see how that transformation would figure out which arguments to replace and which not. Unless you define another string-like construct for the expressions, something which doesn't clash with the lexer/parser - it's the simpler solution and maybe the best one, because it's grammar agnostic in relation to the evaluator library used.

As for the innefficiency with unneeded Evals.... uh, i don't suppose your parser has 2-phases? But i still think it's worth it even if slower than ideal.
Actually, i think that the implementation Ascension64 presented requires the evals of the replaced arguments be right before the affected trigger - to do otherwise would need a cache. At least that's what appeared to me in the examples he showed. Can you confirm Ascension64?

I finally figured out you were talking about Assigns.
The assignments are separate from the Eval triggers, another opcode, and wouldn't need to be part of the transformation. I also doubt they'd need to be repeated for multiple expressions. Do you have a better suggestion that separating them?

Edited by i30817, 01 May 2012 - 03:32 AM.


#69 Ascension64

Ascension64
  • Modder
  • 5983 posts

Posted 01 May 2012 - 03:32 AM

I've settled with single Assign() and Eval() triggers. To make the implementation completely independent of compilers, I've put all the evaluation code in the string argument.
I think this makes it a lot easier to do anything we want.
I'm hoping .BAF and .D files will not evaluate # and @ in strings (in quotes) as TLK and TRA references. If so, please suggest some other symbols I can use.
IF
  Assign("tn[HPCLASS.0.1]", STR, /*@1*/1) //@1 = HPCLASS x0 y1
  Assign("id[STATS.LEVEL]", INT, /*#2*/2) //#2 = Myself.STAT.LEVEL
  Assign("e[#2 - 10]", INT, /*#3*/3) //#3 = #2 - 10 = Myself.STAT.LEVEL - 10
  Assign("tn[@1.1.#3]", INT, /*#4*/4) //#4 = <some table> x1 y(Myself.STAT.LEVEL-10)
  Eval("#4", INT, 1) //int1 = #4
  Assign("v[test.GLOBAL]", /*#5*/5) //#5 = the value of the GLOBAL variable 'test'
  Eval("#5", INT, 2) // int2 = #5
  E(-33,-33) //int1 and int2 get replaced from the above; note: I'm just using a -33 placeholder here, since I have to put some numbers in those places that get substituted
THEN...
Assign() only allows you to assign to one variable. Things that rely on objects uses the owner of the script unless NextTriggerObject() is specified beforehand.
Eval() doesn't let you assign anything. It should not be picked up by NextTriggerObject() since this is object-independent.
Neither get picked up by OR().
Variables keep for the entire trigger block. When the trigger returns a result, the variables are cleared.
I'm in favour of allowing only a fixed number of variables. Currently, I've set a global limit for 25 ints and 25 strings. That should be plenty.

Edited by Ascension64, 01 May 2012 - 03:37 AM.

--------------
Retired Modder
Note: I do not respond to profile comments/personal messages in regards to troubleshooting my modifications. Please post on the public forums instead.

Baldur's Gate Trilogy-WeiDU and Mods
Throne of Bhaal Extender (TobEx)

Contributions: (NWN2) A Deathstalker (voice acting) - (IWD2) IWD2 NPC Project (soundset editing) - (Misc) SHS PC Soundsets (voice acting)
Legacy: (BG/Tutu/BGT) Beregost Crash Fixer 1.9 (18 Jul 10) - (BG2) Enable conversations with charmed/dominated creatures (18 Jul 10) - (BG2) Experience Corrections (18 Jul 10) - (Misc) Platform Conversion Utility RC2 (13 Feb 10)


#70 i30817

i30817
  • Member
  • 611 posts

Posted 01 May 2012 - 03:55 AM

Comments and questions (hope you're not sick of me by now):
1) muParserSSE doesn't have support for string vars. Are you planning to use another?
2) what's the "tn" and "id" prefixes? "e" should be expression right?
3) I like allowing using the evaluator in assignments. I'd forgotten that it might be useful to use a expression to access parts of tables for other assignments etc.
4) What's the reason you put in Types in the Eval function? Is it the expected return value of the expression in the first argument? The expected type of the arguments used in the expression? If it's only that... is it really needed? For the return value; I expect trying to put in a string - 10 would return a error in the evaluator library (maybe not for operator +, which may be string overloaded). For the arguments, just consider TRIGGERS.IDS and ACTION.IDS, the information of the type of argument expected is already there, given the 3rd position parameter.
5) it seems that assignments got a whole lot more complicated, when you start allowing the use of variables inside them. And the Type 2nd argument, it's like a cast right? Try to treat a 2da value as a int, or a global as a string? That stuff only seems useful if your evaluator library will alllow typechecking - which is unlikely to say the least. What's the type going to be used for; since in the eval library all the types need to go as strings arguments?


edit: edited stupid error in last paragraph, reread if it seemed stupid before.
edit2: more edits, now the whole post.
edit3: one more question
edit4: deleted a dumb suggestion
edit5: deleted another dumb suggestion (it would be slower)

Edited by i30817, 01 May 2012 - 04:54 AM.


#71 Galactygon

Galactygon

    Modding since 2002

  • Member
  • 938 posts

Posted 01 May 2012 - 04:07 AM

I'm in favour of allowing only a fixed number of variables. Currently, I've set a global limit for 25 ints and 25 strings. That should be plenty.


As long as there should be a way to set them equal to more permanent variables (LOCALS, GLOBALS, MYAREA, etc.) before they are cleared, I think this is just fine.

-Galactygon

Edited by Galactygon, 01 May 2012 - 04:07 AM.

Posted Image

#72 i30817

i30817
  • Member
  • 611 posts

Posted 01 May 2012 - 05:07 AM

May i suggest another scheme for finding the data to assign? Tell me i'm dumb if it won't work.

[HPCLASS.0.1] for table (starts with [ )
G.data for a global named data (starts with G.)
L.data for a local named data (starts with L.)
C.LEVEL (for stats; character level, character strength etc).
Expression can use the string delimiter that weidu ends up choosing for the transformation, imagine it's < and >:
<#5+5>

(all of these strings)

I'd like this stuff to be easy to read and easy to distinguish. If someone has better suggestions, please post them!

Edited by i30817, 01 May 2012 - 05:10 AM.


#73 the bigg

the bigg

    2083 is a prime number.

  • Modder
  • 3331 posts

Posted 01 May 2012 - 05:10 AM

I'm hoping .BAF and .D files will not evaluate # and @ in strings (in quotes) as TLK and TRA references. If so, please suggest some other symbols I can use.

It doesn't.

Assign("tn[HPCLASS.0.1]", STR, /*@1*/1)

I hope you use that as a comment, not as synthax :)

Assign() only allows you to assign to one variable. Things that rely on objects uses the owner of the script unless NextTriggerObject() is specified beforehand.
Eval() doesn't let you assign anything. It should not be picked up by NextTriggerObject() since this is object-independent.
Neither get picked up by OR().

No peculiar problem as far as WeiDU hacks go then. Some questions that could probably help you conceive more accurate tests:

Assign("e[2]", INT, 4)
NextTriggerObject("Imoen")
Eval("#4",INT,1)
Global("foo", "LOCALS", -33)
Is the Global() trigger evaluated on Imoen or Myself?

Assign("e[2]", INT, 4)
Eval("#4",INT,1)
NextTriggerObject("Imoen")
Global("foo", "LOCALS", -33)
Is foo compared with 2 or -33?

Assign("e[3]", INT, 4)
Eval("#4",INT,1)
Global("foo", "LOCALS", -33)
Is foo compared with 2 or 3?



Expression can use the string delimiter that weidu ends up choosing for the transformation, imagine it's < and >:
<#5+5>

Since they're inside strings, WeiDU isn't really involved with this.

Edited by the bigg, 01 May 2012 - 05:11 AM.

Italian users: help test the Stivan NPC!

Author or Co-Author: WeiDU - Widescreen - Generalized Biffing - Refinements - TB#Tweaks - IWD2Tweaks - TB#Characters - Traify Tool - Some mods that I won't mention in public
Maintainer: Semi-Multi Clerics - Nalia Mod - Nvidia Fix
Code dumps: Detect custom secondary types - Stutter Investigator

If possible, send diffs, translations and other contributions using Git.


#74 i30817

i30817
  • Member
  • 611 posts

Posted 01 May 2012 - 05:14 AM

yeah, it's just so they "look the same", if you implement the
E(<#1 + 7>, 0) -> Eval("#1 + 7", INT, 1) E(-33, 0)
transformation (or another like it)

The 2nd argument (the type) of both functions is bugging me.
As far as i can tell, if the evaluator library support strings it only needs one thing for it's string arguments: to wrap the string in the argument in two \" before replacing the occurrences of it in a expression. Since when you assign the arguments, you know where they come from (if they are supposed to be a string or not), why not mark that automatically?
Even if you want to allow "type conversion" by using that in the "Assign", surely it is not needed in the "Eval", since you already know that #1, #2 etc is a string or a int from the "Assign"

BTW, a isTrue(I:boolean) trigger would be useful to be "variable substitued" with a boolean Eval().

Edited by i30817, 01 May 2012 - 05:43 AM.


#75 the bigg

the bigg

    2083 is a prime number.

  • Modder
  • 3331 posts

Posted 01 May 2012 - 05:26 AM

Oh, right. If Assign() are valid for the entire block, while Eval() must be repeated for every trigger, I can see how Foo(<#1>,5) -> Eval("#5",INT,1) Foo(-33,5) would be a time saver.

Italian users: help test the Stivan NPC!

Author or Co-Author: WeiDU - Widescreen - Generalized Biffing - Refinements - TB#Tweaks - IWD2Tweaks - TB#Characters - Traify Tool - Some mods that I won't mention in public
Maintainer: Semi-Multi Clerics - Nalia Mod - Nvidia Fix
Code dumps: Detect custom secondary types - Stutter Investigator

If possible, send diffs, translations and other contributions using Git.


#76 i30817

i30817
  • Member
  • 611 posts

Posted 01 May 2012 - 09:23 AM

Hmmm. With re-assignment there is no reason not to keep them forever - there's only going to be 25 max anyway.
It's with the Eval that you've got to be careful (so if it fails, it doesn't affect a trigger in the next block for instance).

though to be honest i kinda think that for the script engine to really fly would need to cache the compiled code, and that would require some funky Assign/Eval trick (wouldn't need to recompile... or eval again, if the Eval arguments didn't change, as there is no source of side efffects on the language). How do you know the arguments didn't change? :whistling:

Edited by i30817, 01 May 2012 - 09:33 AM.


#77 i30817

i30817
  • Member
  • 611 posts

Posted 01 May 2012 - 10:00 AM

Is there any script action that saves points in globals/locals?
If there is, a Assign for points X_INT and Y_INT would be nice, to do some geometry.

I'm specifically thinking that if it can get a holdoff the location of the center of the "cloud" spells, can save that in a global somewhere and get my character location and do some simple geometry with those variables, i can avoid/flee the clouds ratio. Maybe something for spell revisions.

Edited by i30817, 01 May 2012 - 10:02 AM.


#78 Ascension64

Ascension64
  • Modder
  • 5983 posts

Posted 02 May 2012 - 12:57 AM

1) muParserSSE doesn't have support for string vars. Are you planning to use another?

I won't be using the variable support from either MathPresso or muParserSSE, whichever one will be used. I'm parsing them myself.

2) what's the "tn" and "id" prefixes? "e" should be expression right?

That will be explained in time. "tn" is table-int (by coordinates) as opposed to "ts" table-string (by col-row name), id is identifiers (I could theoretically want to compare one EA with another EA, etc.). "e" is expression for the expression parser.

3) I like allowing using the evaluator in assignments. I'd forgotten that it might be useful to use a expression to access parts of tables for other assignments etc.

Yes you can.

4) What's the reason you put in Types in the Eval function?

I am forcing the modder to give explicit types for everything. If a type mismatch occurs, TobEx will bail out and not assign anything. If bDebugVerbose is active, you will swamp your TobEx console with warnings/errors.

For the arguments, just consider TRIGGERS.IDS and ACTION.IDS, the information of the type of argument expected is already there, given the 3rd position parameter.

No, the argument is given by the Trigger construction. Assign will always expect an int in the 3rd position. That doesn't tell you whether I should put a int into the position or a string into it.

5) it seems that assignments got a whole lot more complicated, when you start allowing the use of variables inside them.

Not really, variables are replaced first. As stated above, I will parse them myself rather than rely on the math expression library.

And the Type 2nd argument, it's like a cast right?

See above. I am forcing modders to explicitly indicate the type to return (Assign)/replace (Eval). If you tried to Assign("v[GLOBAL.test]", STR, 1), you will just get an error in you have verbose on, and if not, TobEx will bail out without assigning anything.

As long as there should be a way to set them equal to more permanent variables (LOCALS, GLOBALS, MYAREA, etc.) before they are cleared, I think this is just fine.

Yes, always.

May i suggest another scheme for finding the data to assign? Tell me i'm dumb if it won't work.

[HPCLASS.0.1] for table (starts with [ )
G.data for a global named data (starts with G.)
L.data for a local named data (starts with L.)
C.LEVEL (for stats; character level, character strength etc).
Expression can use the string delimiter that weidu ends up choosing for the transformation, imagine it's < and >:
<#5+5>

(all of these strings)

I'd like this stuff to be easy to read and easy to distinguish. If someone has better suggestions, please post them!

I would argue that my current system is easy. I think your method is harder because the syntax is different for each different statement. Plus, you are making my life harder coding the parser to check for multiple syntaxes. Hence, the Statement syntax will always be of the form "<type>[<a>.<b>.<c>....]".

I hope you use that as a comment, not as synthax

Yes, it is a comment.

Assign("e[2]", INT, 4)
NextTriggerObject("Imoen")
Eval("#4",INT,1)
Global("foo", "LOCALS", -33)
Global() is evaluated on "Imoen".
Assign("e[2]", INT, 4)
Eval("#4",INT,1)
NextTriggerObject("Imoen")
Global("foo", "LOCALS", -33)
foo is compared with 2.

Assign("e[3]", INT, 4)
Eval("#4",INT,1)
Global("foo", "LOCALS", -33)
Hmm, epic fail if foo is compared to 2. Where's the 2? foo is compared with 3.

Oh, right. If Assign() are valid for the entire block, while Eval() must be repeated for every trigger, I can see how Foo(<#1>,5) -> Eval("#5",INT,1) Foo(-33,5) would be a time saver.

You can compound this if you want by:
Foo(Eval("<v[GLOBAL.test],INT,1> + 6",INT,1), 5) -> Assign("v[GLOBAL.test],INT,1) Eval("#1 + 6",INT,1) Foo (-33,5)

Is there any script action that saves points in globals/locals?
If there is, a Assign for points X_INT and Y_INT would be nice, to do some geometry.

I'm specifically thinking that if it can get a holdoff the location of the center of the "cloud" spells, can save that in a global somewhere and get my character location and do some simple geometry with those variables, i can avoid/flee the clouds ratio. Maybe something for spell revisions.

As I said, let's fix up the trigger implementation before thinking about actions. In fact, when thinking about this, the action implementations should be exactly the same, just you get more options. Essentially, Eval() can specified to replace the pt.x or pt.y in addition to the three ints.

And here are the trigger constructions:
0x411A Assign(S:Statement*,I:Type*ArgType,I:Local*)
0x411B Eval(S:Expression*,I:Type*ArgType,I;Loc*)

Edited by Ascension64, 02 May 2012 - 01:00 AM.

--------------
Retired Modder
Note: I do not respond to profile comments/personal messages in regards to troubleshooting my modifications. Please post on the public forums instead.

Baldur's Gate Trilogy-WeiDU and Mods
Throne of Bhaal Extender (TobEx)

Contributions: (NWN2) A Deathstalker (voice acting) - (IWD2) IWD2 NPC Project (soundset editing) - (Misc) SHS PC Soundsets (voice acting)
Legacy: (BG/Tutu/BGT) Beregost Crash Fixer 1.9 (18 Jul 10) - (BG2) Enable conversations with charmed/dominated creatures (18 Jul 10) - (BG2) Experience Corrections (18 Jul 10) - (Misc) Platform Conversion Utility RC2 (13 Feb 10)


#79 i30817

i30817
  • Member
  • 611 posts

Posted 02 May 2012 - 02:42 AM

4) What's the reason you put in Types in the Eval function?

I am forcing the modder to give explicit types for everything. If a type mismatch occurs, TobEx will bail out and not assign anything. If bDebugVerbose is active, you will swamp your TobEx console with warnings/errors.

For the arguments, just consider TRIGGERS.IDS and ACTION.IDS, the information of the type of argument expected is already there, given the 3rd position parameter.

No, the argument is given by the Trigger construction. Assign will always expect an int in the 3rd position. That doesn't tell you whether I should put a int into the position or a string into it.


I don't understand this: if i understand correctly; the 3rd argument of Assign is the variable 'slot'. The 3rd argument of Eval is the actual argument position to replace in the next trigger.
I was refering to the eval 3rd argument. Given that position and the values on TRIGGERS.IDS, why not build a table with the expected argument types and compare the result of eval (from the evaluation library) with
the actual type expected, if you're wanting debug validation?
Of three results of Eval: typeerror, int, "boolean" or string (if the library supports strings), they can all be typechecked with such a table
Of course, maybe i'm expecting too much of the library...

More; i think making it obligatory to add a type to "Eval" will make the proposed WEIDU compiler trick harder to implement (since the_bigg has to care about the "expected" type), he would probably read it from trigger.ids to get a sane value to put there, you can do the same algorithm at runtime if debug mode is on (and will be able to actually typecheck since you'd then have the type of the expression to compare).

ie: the expected type is the type the function expects, not what the scripter thinks the Eval'd expression will output as a result (since who decides that is the library). And that value can be derived by the position and the trigger (which you can recognize when you get to it later right?)

5) it seems that assignments got a whole lot more complicated, when you start allowing the use of variables inside them.

Not really, variables are replaced first. As stated above, I will parse them myself rather than rely on the math expression library.

I'm mainly worried about strings: if you allow strings arguments to be passed to Eval (which you need to for them to be used) and the library doesn't support string, you need to do a pass over the string to see if it there is a single "#string_variable" (or similar) and do the substitutions and skip passing it to the library, since it will choke one it.
Note that this means that you can't use number arithmetic and concatenate strings and kinda turns into a hack. Maybe it's best for performance though.

Edited by i30817, 02 May 2012 - 03:45 AM.


#80 Ascension64

Ascension64
  • Modder
  • 5983 posts

Posted 02 May 2012 - 03:47 AM

It's pretty simple. If you Eval("something", STR, x), where x is the nth argument of type specified:
-First, I don't use the library at all
-Second, I check if the argument of type STR exists
-Third, if it exists, I replace it.

If you want Eval("something", y), where y is the argument number from the trigger to replace, and "something" is a string type:
-First, the library must parse the "something"
-Second, I have to search ahead
-Third, I need to check if the argument exists
-Fourth, I need to parse the trigger construction to check type
-Finally, if type is valid, I will modify the value

The first option, sounds so much simpler to me.
If I have to use the library, then if people try to do weird things, I can easily filter errors out before invoking the library on the expression "something".
For example:
-Eval("@1",INT,1) just doesn't do anything. Alternatively, an atoi() ends up convert to an integer. If it's a string atoi() ends up being 0.
-Eval("#1 + @1", STR,1) doesn't do anything either. Alternatively, if #1 = 6 and @1 = foo you end up with a string that reads "6 = foo" evaluated into the first string argument of the next valid trigger
-Eval("#1",STR,2): can just do nothing as well. I could possibly Format() to string this one, but I can't see the use of it at the moment, so what's the point?
Finally, if the library bails for any reason, Eval() just won't do anything at all.

Edited by Ascension64, 02 May 2012 - 03:55 AM.

--------------
Retired Modder
Note: I do not respond to profile comments/personal messages in regards to troubleshooting my modifications. Please post on the public forums instead.

Baldur's Gate Trilogy-WeiDU and Mods
Throne of Bhaal Extender (TobEx)

Contributions: (NWN2) A Deathstalker (voice acting) - (IWD2) IWD2 NPC Project (soundset editing) - (Misc) SHS PC Soundsets (voice acting)
Legacy: (BG/Tutu/BGT) Beregost Crash Fixer 1.9 (18 Jul 10) - (BG2) Enable conversations with charmed/dominated creatures (18 Jul 10) - (BG2) Experience Corrections (18 Jul 10) - (Misc) Platform Conversion Utility RC2 (13 Feb 10)