Author Topic: EventScript - Eventing 2.0  (Read 11577 times)


This is great! Something that should've been done years ago.

how do you activate it, nothing happens


how do you activate it, nothing happens

From the download page it tells this:
Download. Install. Set your shortcuts of copy/paste. Start scripting.

Edit: I added a more detailed explanation for clarity.
« Last Edit: November 15, 2017, 07:17:03 AM by mctwist »

Honest to God, I was thinking about something like this the other day. It's one of those things we've needed for a long time, but no one has bothered to release until now. I love how simple and embedded the interpretation is. I might actually do something with events now that it's this easy. Thank you!

I appreciate that the debug info gives the line number for the script, not the event ordering.

I do think the script should be case-insensitive, though. TorqueScript is already case-insensitive, so it should cause any conflicts. Hence, making things case-sensitive seems to add an unnecessary level of complexity. Any reason why you opted for case-sensitive?

Also, does EventScript currently have anything to simplify setEventEnabled and toggleEventEnabled? Event toggling has always been the most frustrating part about eventing for me. Could you add some sort of labeling feature (similar to labels in C)? For example, take this script for a simple lamp:
Code: [Select]
# Turn light on
[x][0]onActivate->Self->setLight("Player's Light")
[x][0]onActivate->Self->setEventEnabled("0 1 2", 0)
[x][0]onActivate->Self->setEventEnabled("3 4 5", 1)

# Turn light off
[][0]onActivate->Self->setLight("NONE")
[][0]onActivate->Self->setEventEnabled("3 4 5", 0)
[][0]onActivate->Self->setEventEnabled("0 1 2", 1)
With labels, it could instead be rewritten as
Code: [Select]
# Turn light on
onStart:
[x][0]onActivate->Self->setLight("Player's Light")
[x][0]onActivate->Self->setEventEnabled([offStart:offEnd], 1)
[x][0]onActivate->Self->setEventEnabled([onStart:onEnd], 0)
onEnd:

# Turn light off
offStart:
[][0]onActivate->Self->setLight("Player's Light")
[][0]onActivate->Self->setEventEnabled([onStart:onEnd], 1)
[][0]onActivate->Self->setEventEnabled([offStart:offEnd], 0)
offEnd:
Or
Code: [Select]
# Turn light on
onStart:
[x][0]onActivate->Self->setLight("Player's Light")
[x][0]onActivate->Self->setEventEnabled([offStart:offStart+2], 1)
[x][0]onActivate->Self->setEventEnabled([onStart:onStart+2], 0)

# Turn light off
offStart:
[][0]onActivate->Self->setLight("Player's Light")
[][0]onActivate->Self->setEventEnabled([onStart:onStart+2], 1)
[][0]onActivate->Self->setEventEnabled([offStart:offStart+2], 0)
Also
Code: [Select]
# Turn light on
on1:
[x][0]onActivate->Self->setLight("Player's Light")
on2:
[x][0]onActivate->Self->setEventEnabled([offStart:], 1)
on3:
[x][0]onActivate->Self->setEventEnabled([on1, on2, on3], 0)

# Turn light off
offStart:
[][0]onActivate->Self->setLight("Player's Light")
[][0]onActivate->Self->setEventEnabled([on1, on2, on3], 1)
[][0]onActivate->Self->setEventEnabled([offStart:], 0)

Labels have their own line and are followed by a colon, ":". Square brackets, "[]", enclose intervals. Colons fill in the gaps between two labels. A colon with nothing following it includes everything after. Likewise, a colon with nothing preceding includes everything before (think Python slices or MATLAB indexing). Labels can be incremented within an interval (e.g. onStart+2). Finally, commas separate separate labels. Each comma could include a separate sub-intervals (i.e. with colons). Hopefully that makes sense. Take it as a suggestion. Some cleaning up/reformatting is probably would probably be good.

I think this would be useful for many reasons. For one thing, the line number in your text editor would not necessarily correspond with each event's order number. If you had even one comment, it would put everything out of wack. Secondly, labels would make it a lot easier to reorganize events. This is something that is particularly frustrating and tedious to do with events in vanilla Blockland, and we should seek to make it more painless.

I would also recommend not including onActivate->Self->fireRelayNum in your example script, since it's a non-standard command. I was momentarily confused when I tried to paste your code, and it didn't work.
« Last Edit: November 16, 2017, 01:09:21 AM by Platypi »

Labeling was considered once while I was developing, but not something that was required. However, with your ideas I think it's entirely possible now. I've added an issue for it and will implement it while I'm redesigning the parsing algorithm. The redesign is important to solve several issues that was raised for the current design (Like: incorrect line numbering in certain cases; unable to locate certain errors).

If anyone is proficient in syntax highlighting, I would be thankful if they could implement it for Sublime Text or any other editor.

I do think the script should be case-insensitive, though. TorqueScript is already case-insensitive, so it should cause any conflicts. Hence, making things case-sensitive seems to add an unnecessary level of complexity. Any reason why you opted for case-sensitive?

Due to how the function findText works, that is not possible. However, if I can somehow use the event global variables myself, then I would find a way around to add this sort of functionality. Don't hold your breath, though, but I've already added it as an issue.

I would also recommend not including onActivate->Self->fireRelayNum in your example script, since it's a non-standard command. I was momentarily confused when I tried to paste your code, and it didn't work.

That is true. Would you mind to provide an example script? The current example is hastened just thrown together and does absolutely nothing of value and I'm not sure I can make a easy to understand event as possible.
« Last Edit: November 16, 2017, 10:43:20 AM by mctwist »


Will this work with Make Eventing Great Again?

Will this work with Make Eventing Great Again?

If it's the same as how events are currently working, it'll create scripts like normal. However, it wont magically make MEGA work by pasting scripts. I doubt I'll ever add such a functionality.

Edit: No, it will not work with it. MEGA does too much changes on the default structure, crippling my parser completely.
« Last Edit: November 25, 2017, 03:09:47 AM by mctwist »

Labels [...]

I just thought about an another way to add labels, by using existing syntax.

Code: [Select]
# Turn light on
[on1][x][0]onActivate->Self->setLight("Player's Light")
[on2][x][0]onActivate->Self->setEventEnabled([offStart:], 1)
[on3][x][0]onActivate->Self->setEventEnabled([on1, on2, on3], 0)

# Turn light off
[offStart][][0]onActivate->Self->setLight("Player's Light")
[][0]onActivate->Self->setEventEnabled([on1, on2, on3], 1)
[][0]onActivate->Self->setEventEnabled([offStart:], 0)

As long as names within the square brackets doesn't contain only one x or only numbers(Nothing bad, as labels starting with numbers are not supported anyway), then it's considered a label. As before, this can be placed anywhere before the input name. This solution will allow the following:
  • Labels are connected to the event, not confused to line, hence easier to read (Subjective)
  • Opts to the current semantic of optional starting arguments (Might be confusing to some)

Of course, it has it disadvantages:
  • Moving around events with labels might be more troublesome (Solved by placing it on its own line, wont break with semantic)
  • Loss of labels named x (Who even want that?)

This is just a possibility. I still might end up using C-like labeling like Platypi/SadBlobfish suggested.
« Last Edit: November 17, 2017, 04:32:12 AM by mctwist »

Labeling was considered once while I was developing, but not something that was required. However, with your ideas I think it's entirely possible now. I've added an issue for it and will implement it while I'm redesigning the parsing algorithm. The redesign is important to solve several issues that was raised for the current design (Like: incorrect line numbering in certain cases; unable to locate certain errors).
That's good to hear! Best of luck on the redesigning. Making parsers is a bitch.

Due to how the function findText works, that is not possible. However, if I can somehow use the event global variables myself, then I would find a way around to add this sort of functionality. Don't hold your breath, though, but I've already added it as an issue.
Looking at the relevant code, I can see that now.

That is true. Would you mind to provide an example script? The current example is hastened just thrown together and does absolutely nothing of value and I'm not sure I can make a easy to understand event as possible.
Sure. How about this?
Code: [Select]
# Makes a brick change colors on a loop when toggled

# Start color changing (start with events enabled)
[x][0]onActivate->Self->playSound("Beep_Checkout.wav")
[x][33]onActivate->Self->fireRelay

# Stop color changing (start with events disabled)
[ ][0]onActivate->Self->playSound("Beep_Denied.wav")
[ ][0]onActivate->Self->cancelEvents

# Alternate between starting and stopping color changing
[x][0]onActivate->Self->toggleEventEnabled("0 1 2 3")

# Change colors
[x][0]onRelay->Self->setColor("0.898039 0.000000 0.000000 1.000000")
[x][500]onRelay->Self->setColor("0.898039 0.898039 0.000000 1.000000")
[x][1000]onRelay->Self->setColor("0.000000 0.498039 0.247059 1.000000")
[x][1500]onRelay->Self->setColor("0.200000 0.000000 0.800000 1.000000")

# Loop color changing
onRelay->Self->fireRelay

# Stop color changing when brick is blown up
onBlownUp->Self->cancelEvents

Please note that I couldn't get the latter code to import to a brick. In fact, I tried pasting
Code: [Select]
[ ][500]onBlownUp->Player->Kill
from your example, and it gave me an error. It tells me I have an invalid amount of parameters.

Also, copying code from in-game does not seem to work. For instance, when I copy the aforementioned events from a brick, it gives me
Code: [Select]
[ ][0]  -> "" ->
[ ][0] 0 -> 0 -> 0(0, 0, 0, "onActivate", "Self", "playSound", "Beep_Checkout.wav")
[ ][0] 0 -> 0 -> 0(0, 0, 33, "onActivate", "Self", "fireRelay")
[ ][0] 0 -> 0 -> 0(0, 1, 0, "onActivate", "Self", "playSound", "Beep_Denied.wav")
[ ][0] 0 -> 0 -> 0(0, 1, 0, "onActivate", "Self", "cancelEvents")
[ ][0] 0 -> 0 -> 0(0, 1, 0, "onActivate", "Self", "toggleEventEnabled", "0 1 2 3")
[ ][0] 0 -> 0 -> 0(0, 1, 0, "onRelay", "Self", "setColor", "0.898039 0.000000 0.000000 1.000000")
[ ][0] 0 -> 0 -> 0(0, 1, 500, "onRelay", "Self", "setColor", "0.898039 0.898039 0.000000 1.000000")
[ ][0] 0 -> 0 -> 0(0, 1, 1000, "onRelay", "Self", "setColor", "0.000000 0.498039 0.247059 1.000000")
[ ][0] 0 -> 0 -> 0(0, 1, 1500, "onRelay", "Self", "setColor", "0.200000 0.000000 0.800000 1.000000")
[ ][0] 0 -> 0 -> 0(0, 1, 2000, "onRelay", "Self", "fireRelay")
[ ][0] 0 -> 0 -> 0(0, 1, 0, "onBlownUp", "Self", "cancelEvents")
which can not be pasted into another brick.

I just thought about an another way to add labels, by using existing syntax.

Code: [Select]
# Turn light on
[on1][x][0]onActivate->Self->setLight("Player's Light")
[on1][x][0]onActivate->Self->setEventEnabled([offStart:], 1)
[on1][x][0]onActivate->Self->setEventEnabled([on1, on2, on3], 0)

# Turn light off
[offStart][][0]onActivate->Self->setLight("Player's Light")
[][0]onActivate->Self->setEventEnabled([on1, on2, on3], 1)
[][0]onActivate->Self->setEventEnabled([offStart:], 0)

As long as names within the square brackets doesn't contain only one x or only numbers(Nothing bad, as labels starting with numbers are not supported anyway), then it's considered a label. As before, this can be placed anywhere before the input name. This solution will allow the following:
  • Labels are connected to the event, not confused to line, hence easier to read (Subjective)
  • Opts to the current semantic of optional starting arguments (Might be confusing to some)

Of course, it has it disadvantages:
  • Moving around events with labels might be more troublesome (Solved by placing it on its own line, wont break with semantic)
  • Loss of labels named x (Who even want that?)

This is just a possibility. I still might end up using C-like labeling like Platypi suggested.
While this would be simpler to parse, it's a bit clunkier, as per the disadvantages you listed. It's probably a bad idea to have labels attached to events. Granted, your label could always be listed like this
Code: [Select]
# Turn light on
[on1]
[x][0]onActivate->Self->setLight("Player's Light")
[on1]
[x][0]onActivate->Self->setEventEnabled([offStart:], 1)
[on1]
[x][0]onActivate->Self->setEventEnabled([on1, on2, on3], 0)

# Turn light off
[offStart]
[][0]onActivate->Self->setLight("Player's Light")
[][0]onActivate->Self->setEventEnabled([on1, on2, on3], 1)
[][0]onActivate->Self->setEventEnabled([offStart:], 0)
which would solve that problem. However, it doesn't change the weird naming problem. To fix that, you could simply pre-parse the square brackets at the beginning of an event listing, and allow the first to be named anything if 3 sets of square brackets are present instead of 2. It still feels a tad dirty from a coding perspective, though.

That's good to hear! Best of luck on the redesigning. Making parsers is a bitch.

And I just finished rewriting most of it. There's only the one thing with output events and its parameters that needs to be adjusted so you may put the parenthesis on a new line, which you cannot do now.

Sure. How about this?
Code: [Select]
# Makes a brick change colors on a loop when toggled

# Start color changing (start with events enabled)
[x][0]onActivate->Self->playSound("Beep_Checkout.wav")
[x][33]onActivate->Self->fireRelay

# Stop color changing (start with events disabled)
[ ][0]onActivate->Self->playSound("Beep_Denied.wav")
[ ][0]onActivate->Self->cancelEvents

# Alternate between starting and stopping color changing
[x][0]onActivate->Self->toggleEventEnabled("0 1 2 3")

# Change colors
[x][0]onRelay->Self->setColor("0.898039 0.000000 0.000000 1.000000")
[x][500]onRelay->Self->setColor("0.898039 0.898039 0.000000 1.000000")
[x][1000]onRelay->Self->setColor("0.000000 0.498039 0.247059 1.000000")
[x][1500]onRelay->Self->setColor("0.200000 0.000000 0.800000 1.000000")

# Loop color changing
onRelay->Self->fireRelay

# Stop color changing when brick is blown up
onBlownUp->Self->cancelEvents

I ran your script and it parsed perfectly. However, it will display a warning for the colors if they don't exist in the colorset. Also, I noticed that on line 21 it didn't have any delay, which will destroy the whole purpose. I've put 2000 delay on it and will update all my examples to this instead and credit you.

Please note that I couldn't get the latter code to import to a brick. In fact, I tried pasting
Code: [Select]
[ ][500]onBlownUp->Player->Kill
from your example, and it gave me an error. It tells me I have an invalid amount of parameters.

Is fixed in next version.

Also, copying code from in-game does not seem to work. For instance, when I copy the aforementioned events from a brick, it gives me
Code: [Select]
-snip code-
which can not be pasted into another brick.

Looks like you are using an Add-On that might modify the default layout so when I read it I get bogus data. If so, please tell me and I'll find a fix around it.

While this would be simpler to parse, it's a bit clunkier, as per the disadvantages you listed. It's probably a bad idea to have labels attached to events. Granted, your label could always be listed like this
Code: [Select]
# Turn light on
[on1]
[x][0]onActivate->Self->setLight("Player's Light")
[on1]
[x][0]onActivate->Self->setEventEnabled([offStart:], 1)
[on1]
[x][0]onActivate->Self->setEventEnabled([on1, on2, on3], 0)

# Turn light off
[offStart]
[][0]onActivate->Self->setLight("Player's Light")
[][0]onActivate->Self->setEventEnabled([on1, on2, on3], 1)
[][0]onActivate->Self->setEventEnabled([offStart:], 0)
which would solve that problem. However, it doesn't change the weird naming problem. To fix that, you could simply pre-parse the square brackets at the beginning of an event listing, and allow the first to be named anything if 3 sets of square brackets are present instead of 2. It still feels a tad dirty from a coding perspective, though.

I think that labels at all is dirty. It's frowned upon in all languages but where it came from. It is sometimes a necessity, though. In our case, we're not using it like others are using it, so adding labels in such a fashion might confuse people, or make it obvious to them. Keep in mind, that when labeling is used with indexing [from:to], it's not obvious that it's to-1. By having it at the event, it might make it more apparent that we are aiming at the event, instead of the event after it.

I ran your script and it parsed perfectly. However, it will display a warning for the colors if they don't exist in the colorset. Also, I noticed that on line 21 it didn't have any delay, which will destroy the whole purpose. I've put 2000 delay on it and will update all my examples to this instead and credit you.
Woops! I was trying to demonstrate how you don't need brackets, but I forgot what my own events were supposed to do lol.

Looks like you are using an Add-On that might modify the default layout so when I read it I get bogus data. If so, please tell me and I'll find a fix around it.
I am using Make Events Great Again. I'll make sure to disable it if I do any more testing in the future.

I think that labels at all is dirty. It's frowned upon in all languages but where it came from. It is sometimes a necessity, though. In our case, we're not using it like others are using it, so adding labels in such a fashion might confuse people, or make it obvious to them.
Yes. Labels are typically considered bad practice in C. They are really only present for historical purposes. But, as you said, our use case is different. Eventing is not C. It's more like an instruction set. So for a more apt brown townog to event, look at any assembly language. In assembly, labeling and jumping is quite common (e.g. labels in x86 Assembly). In fact, it's pretty much necessary.

Keep in mind, that when labeling is used with indexing [from:to], it's not obvious that it's to-1. By having it at the event, it might make it more apparent that we are aiming at the event, instead of the event after it.
This is actually a bit of an oversight on my part. It hit me earlier what I had done wrong. It might be better to not auto-decrement the second value in an interval like I did implicitly. Rather, [from:to] should be written like [from:to-1] to avoid confusion. This would be more intuitive to programmers (who will probably be familiar with MATLAB and Python slices) and non-programmers.

I get what you're saying about aiming labels at an event. It makes more sense in the context of the auto-decrement critique. But of course, people could always choose to write labels as
Code: [Select]
# Turn light on
onStart: [x][0]onActivate->Self->setLight("Player's Light")
[x][0]onActivate->Self->setEventEnabled([offStart:offEnd], 1)
onEnd: [x][0]onActivate->Self->setEventEnabled([onStard:onEnd], 0)

# Turn light off
offStart: [][0]onActivate->Self->setLight("Player's Light")
[][0]onActivate->Self->setEventEnabled([onStard:onEnd], 1)
offEnd: [][0]onActivate->Self->setEventEnabled([offStart:offEnd], 0)

Another benefit of explicit, non-bracketed labels is that it might actually make code a bit more intuitive, and hence make parsing easier to a certain extent. If we go with bracket notation, we have to consider four different cases:
  • no brackets - default behavior
  • 1 bracket - label (?)
  • 2 brackets - no label, enabled and delay
  • 3 brackets - label, enabled, and delay
This would require you to pre-parse each set of brackets, and then decide how to treat each of them.

But with labels declared separately with colons, we only have to consider two cases for brackets:
  • no brackets - default behavior
  • 2 brackets - enabled and delay
I imagine this would require less (or no) pre-parsing, as the presence of a forward brackets indicates that the second case is the one to consider.

Another option could be blocking instead of labeling, e.g.
Code: [Select]
# Turn light on
lightOn {
[x][0]onActivate->Self->setLight("Player's Light")
[x][0]onActivate->Self->setEventEnabled({lightOn}, 1)
[x][0]onActivate->Self->setEventEnabled({lightOff}, 0)
}

# Turn light off
offStart {
[][0]onActivate->Self->setLight("Player's Light")
[][0]onActivate->Self->setEventEnabled({lightOff}, 1)
[][0]onActivate->Self->setEventEnabled({lightOn}, 0)
}
Albeit less flexibly, this feels more intuitive, and it looks a bit nicer to me. If we want to increase the flexibility of this method, we could allow for the inclusion of multiple blocks in a block reference, i.e. {label1, label2, label3}. And as the cherry on top, this method would probably be the easiest to code up, as it doesn't allow/encourage the use of arithmetic inside intervals/block references.

I would say, too, that the ability to nest blocks need-not and should-not be implemented with this. Eventing is more 1-dimensional than most programming languages, and hence doesn't need such complexities. Plus, nesting would add a whole other layer of complexity to the code.
« Last Edit: November 17, 2017, 06:06:25 AM by Platypi »

I am using Make Events Great Again. I'll make sure to disable it if I do any more testing in the future.

I wont deal with them, as they need to make their own adapter toward my parser. It's quite easy, as it's just a list with the events.I wont have time to contact them, so feel free to do so.

Another benefit of explicit, non-bracketed labels is that it might actually make code a bit more intuitive, and hence make parsing easier to a certain extent. If we go with bracket notation, we have to consider four different cases:
  • no brackets - default behavior
  • 1 bracket - label (?)
  • 2 brackets - no label, enabled and delay
  • 3 brackets - label, enabled, and delay
This would require you to pre-parse each set of brackets, and then decide how to treat each of them.

But with labels declared separately with colons, we only have to consider two cases for brackets:
  • no brackets - default behavior
  • 2 brackets - enabled and delay
I imagine this would require less (or no) pre-parsing, as the presence of a forward brackets indicates that the second case is the one to consider.

Actually, I said that both are optional, but in fact, I'll take this example as a show of what's valid:
Code: [Select]
[x][0]onActivate->Self->setLight("Player's Light")
[0][x]onActivate->Self->setLight("Player's Light")
[0]onActivate->Self->setLight("Player's Light")
[x]onActivate->Self->setLight("Player's Light")
onActivate->Self->setLight("Player's Light")

Yes, all five are valid. My parser will figure out what is correct, hence why adding a label to it wouldn't be such a problem. Just a couple more checks.

Another option could be blocking instead of labeling, e.g.
Code: [Select]
# Turn light on
lightOn {
[x][0]onActivate->Self->setLight("Player's Light")
[x][0]onActivate->Self->setEventEnabled({lightOn}, 1)
[x][0]onActivate->Self->setEventEnabled({lightOff}, 0)
}

# Turn light off
offStart {
[][0]onActivate->Self->setLight("Player's Light")
[][0]onActivate->Self->setEventEnabled({lightOff}, 1)
[][0]onActivate->Self->setEventEnabled({lightOn}, 0)
}
Albeit less flexibly, this feels more intuitive, and it looks a bit nicer to me. If we want to increase the flexibility of this method, we could allow for the inclusion of multiple blocks in a block reference, i.e. {label1, label2, label3}. And as the cherry on top, this method would probably be the easiest to code up, as it doesn't allow/encourage the use of arithmetic inside intervals/block references.

I would say, too, that the ability to nest blocks need-not and should-not be implemented with this. Eventing is more 1-dimensional than most programming languages, and hence doesn't need such complexities. Plus, nesting would add a whole other layer of complexity to the code.

As you say, this is not a way to go. And I will never make such a thing because it adds too much complexity to an easy problem. I would say that for now we'll go for the C-like labeling and I'll check with a few more if it's the best route.