Page 1 of 1

Is it possible to make a trigger that allows you to create a trigger in-game, via JASS?

Posted: Mon Mar 04, 2013 4:43 pm
by EqualiseR
I am trying to see if it is possible to make a trigger that allows you to create a trigger in-game via JASS.

For example:

Player - Player 1 (Red) types a chat message containing -JASS (type jass here)
(No Condition)
Custom Script - [do something with the specified jass eh?]

Is this possible?

-Eq

Re: JASS Question

Posted: Mon Mar 04, 2013 5:19 pm
by 3ICE
Yes, it is entirely possible.

This is how you declare a trigger variable: trigger gg_trg_name = null
I usually put my custom built triggers in a trigger array so I can create many triggers at once, on the fly, without needing extra variable declarations. Which brings me to...
This is how you create a new trigger: set triggers[idx++] = CreateTrigger() idx++ might not be JASS, in that case just use set idx = idx + 1 on the previous (or following) line to keep track of your trigger count. (idx stands for index, because I don't like naming my variables TRIGGER_COUNT or the like.
If you plan to eventually destroy some triggers, you'll need to use a full blown indexing system instead of this weak "incrementing a counter" stuff. But an indexing system is something I'm not overly interested in as I've never needed one.

This is how you add events to it: TriggerRegister*Type*Event() As many as you like. Individual or combined events (combine via condition checks, you can also create separate triggers with the same actions but different events, for different event combination sets)
List of events List of events
TriggerRegisterDeathEvent TriggerRegisterDialogButtonEvent TriggerRegisterDialogEvent TriggerRegisterEnterRegion TriggerRegisterFilterUnitEvent TriggerRegisterGameEvent TriggerRegisterGameStateEvent TriggerRegisterLeaveRegion TriggerRegisterPlayerAllianceChange TriggerRegisterPlayerChatEvent TriggerRegisterPlayerEvent TriggerRegisterPlayerStateEvent TriggerRegisterPlayerUnitEvent TriggerRegisterStateEvent TriggerRegisterTimerEvent TriggerRegisterTimerExpireEvent TriggerRegisterTrackableHitEvent TriggerRegisterTrackableTrackEvent TriggerRegisterUnitEvent TriggerRegisterUnitInRange TriggerRegisterUnitStateEvent TriggerRegisterVariableEvent
This is how you add conditions to it: TriggerAddCondition()

And this is how you add actions to it: TriggerAddAction() You will need many dummy triggers that have the actions you plan to add. About one or two actions per trigger for generic triggers built on the fly or you can have a massive action if that's what's needed.

You can even edit the trigger that you just triggered: GetTriggeringTrigger() That one is really useful! For example we often do this: call DisableTrigger(GetTriggeringTrigger()) to turn off checkpoints in mazes.

You might need these too. Just In case...
TriggerExecute, ConditionalTriggerExecute to call triggers
code, boolexpr, handle, conditionfunc, filterfunc, triggeraction, triggercondition are types just like integer and boolean, but related to triggers
DisableTrigger, EnableTrigger do what they say they do
GetTriggerEvalCount, GetTriggerExecCount count calls to a trigger's condition and also how many times it was evaluated true (basically when the trigger got executed)
Similarly, GetTriggerEvalCount() - GetTriggerExecCount() is how many times a given trigger was triggered, but not executed because its conditions weren't met
And TriggerEvaluate is basically useless because you might as well just use an if/then/else block in most simple cases. And even if it's complicated, you can just call a function that returns a boolean...

That's all I remember, for now.

--3ICE

p.s.: Topic titles are important to me. And not just me... Google cares too. I want this post to be rank 1 and for that we need something better than "JASS Question". How about... "Is it possible to make a trigger that allows you to create a trigger in-game, via JASS?"
Fix'd.

Re: Is it possible to make a trigger that allows you to create a trigger in-game, via JASS?

Posted: Mon Mar 04, 2013 5:28 pm
by 3ICE
Note: The above post was heavily edited after you've read it. Please refresh and read again.
Hopefully this double post of mine successfully sends you an email notification...

Re: Is it possible to make a trigger that allows you to create a trigger in-game, via JASS?

Posted: Wed Mar 06, 2013 3:20 pm
by EqualiseR
Thanks for the elaborate reply. Would it be possible to create a trigger that when you type let's say "-jass (jass here)" it simply executes the jass you specify in an action? Not really creating a trigger via a trigger, but making the trigger do any action that you specify in jass.

For example:

-jass call AddSpecialEffectLocBJ( GetRectCenter(GetPlayableMapRect()), "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl" )

And then the "call AddSpecialEffectLocBJ( GetRectCenter(GetPlayableMapRect()), "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl" )" would be saved an executed via a "Custom Script: JASSHERE" GUI action or some other GUI / Jass action.


Thank you

-Eq

Re: Is it possible to make a trigger that allows you to create a trigger in-game, via JASS?

Posted: Wed Mar 06, 2013 5:01 pm
by 3ICE
That'd be a massive project. You'd need thousands of one liner triggers, and even then it'd only understand basic JASS.
I'm pretty sure at one point we had limited eval without parameter support. Can't dig up anything on it though.

It's better to think about what you'll need and implement only that.
e.g.: -specAtMid Abilities\Spells\Human\ThunderClap\ThunderClapCaster.mdl is much more feasible.

Re: Is it possible to make a trigger that allows you to create a trigger in-game, via JASS?

Posted: Wed Mar 06, 2013 5:08 pm
by EqualiseR
Okay then, thanks lol. I won't bother trying to go about doing that method (thousands of one line triggers) as this was just an interesting idea I thought of and served of little purpose.

-Eq

Re: Is it possible to make a trigger that allows you to create a trigger in-game, via JASS?

Posted: Wed Mar 06, 2013 5:32 pm
by 3ICE
Found it: ExecuteFunc
You'd basically need to have a separate trigger to wrap each jass function you want to work in game, load the parameters from the input string into globals and then ExecuteFunc the wrapper.

Oh, and if you use an invalid ExecuteFunc, your game crashes. So do full error-checking before calling ExecuteFunc on a string. Make sure the function exists.

Re: Is it possible to make a trigger that allows you to create a trigger in-game, via JASS?

Posted: Sat Mar 09, 2013 1:55 am
by EqualiseR
I'm not very fluent in JASS. And when I say I'm not very fluent I mean I never bothered to learn it. Can you give me the syntax of it being used with something such as "call AddSpecialEffectLocBJ( GetRectCenter(GetPlayableMapRect()), "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl" )"?

-eq

Re: Is it possible to make a trigger that allows you to create a trigger in-game, via JASS?

Posted: Sat Mar 09, 2013 8:47 am
by 3ICE
That's a nested jass function, which is something we don't want to bother supporting. (Way too much work.)
GetRectCenter(GetPlayableMapRect()) is basically the (0,0) coordinates. Much simpler in coordinate form.
I and many others even teach "BJ functions are bad, don't use them!"

So yes, we don't want to execute call AddSpecialEffectLocBJ( GetRectCenter(GetPlayableMapRect()), "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl")
Instead, we'll use native AddSpecialEffect takes string modelName, real x, real y returns effect, like so:

To execute call AddSpecialEffect(0, 0, "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl")
You'd type -jass AddSpecialEffect 0 0 Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl

Then the code that handles the -jass command would pick up your keywords in an array. We don't have split, so we use SubStr in a loop. Results:
split[0] = "AddSpecialEffect"
split[1] = "0"
split[2] = "0"
split[3] = "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl"

The first element in the array, "AddSpecialEffect" tells us what function you want to execute. We'll use that piece of information last. We do however need to do some error-checking first, to make sure we don't crash the game. (Basically: "Is AddSpecialEffect a valid keyword? If yes, the continue, else return with an error.")
The next two elements "0" and "0" get converted to 0.0 and 0.0 and get stored in global real variables real1 and real2: set real1 = S2R(split[1]), set real2 = S2R(split[2]), because we know that AddSpecialEffect's signature is always real, real, string.
The last element is a string, we store it in string1: set string1 = split[3] No error checking here as this wouldn't crash the game. Our only concern is a bad ExecuteFunc call. (To a non-existent function.)

Then we call our wrapper: call ExecuteFunc(split[0] + "Wrap") ("AddSpecialEffect" + "Wrap" = "AddSpecialEffectWrap")

AddSpecialEffectWrap knows it has to call AddSpecialEffect with the global parameters we've set previously, so it does just that:
call AddSpecialEffect(real1, real2, string1)

Done.

Re: Is it possible to make a trigger that allows you to create a trigger in-game, via JASS?

Posted: Tue Apr 23, 2013 7:30 am
by 3ICE
Re-reading this I just realized the whole saving parameters to globals and ExecuteFunc magic is unnecessary.
You can just call the wrapped function from the wrapper with the right arguments:

Again, we'll use -jass AddSpecialEffect 0 0 Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl as an example.
But the code that handles that command would listen for -jass AddSpecialEffect instead of just -jass, to make it simpler.
Split results are the same, except we can safely throw away the first (0th) part because we already know what to call:
split[0] = "AddSpecialEffect"
split[1] = "0"
split[2] = "0"
split[3] = "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl"

Since AddSpecialEffect's signature is real, real, string, the first two elements "0" and "0" will get converted from string to do real (to 0.0 and 0.0 in this example case): S2R(split[1]), S2R(split[2]). Of course only when we call AddSpecialEffect.
The last element is a string, we leave that alone: split[3]

Then we call AddSpecialEffect: call AddSpecialEffect( S2R(split[1]), S2R(split[2]), split[3] ) (Extra spaces for readability, they are not needed in actual code)

Done.

Oh, and just for fun, here is the whole thing in GUI. Just to prove to myself that I still remember how to use GUI after years of pure JASS: