I had a short conversation with jjf about making a small extension to Chkdraft. I wanted to make some sort of trigger creator, as I do remember how terribly slow creating triggers through a GUI is. I have a little bit of experience with the Lua programming language, and I was lucky enough to have Kaias create OreoTriggers to give me some ideas. Building off of the idea of OreoTriggers I decided to make a similar utility to be used with Chkdraft.
The idea is to give Chkdraft the name of a text file with Lua code inside. Chkdraft will then use a tool called
Lua Interpreted Triggers (LIT) to generate triggers and place them directly into your map. This would happen inside Chkdraft itself, and perhaps require little more than clicking a button. LIT as a proof of concept is already finished. The proof of concept only took 2.5 hours to complete in total, so I imagine completing a fully featured and tested LIT will be a pretty small project! This means LIT will be easily completed and supported by myself.
OreoTriggers, although good looking, does run from PHP which requires server stuff to be set up. I recall in the past this was too difficult for me to figure out. MacroTriggers by Wormer looks pretty similar to LIT as well, but was much too complex to install and use properly. I aim for LIT to be simpler to use and setup than the aforementioned trigger creators, and have integration with Chkdraft directly.
LIT runs code from top to bottom, so control over the order of all triggers can be explicit. Example LIT file (here's a link with
syntax highlighting):
LIT code
-- Comments have two dashes before them, and usually look green
-- Create a players group, pass in players
p1 = players( 1 )
-- Create a death counter for a specific type
dc = deathcounter( "Alan Schezar (Goliath)" )
-- The player of a death counter can be changed at any time
dc:setplayer( 1 )
-- Example of creating a trigger
-- The user (users of LIT, meaning you) must always manually call
-- conditions( ) and actions( ) upon a player object
p1:conditions( )
always( )
p1:actions( )
dc:add( 1 )
-- Create another trigger
p1:conditions( )
dc:exactly( 64 )
p1:actions( )
text( "print this" )
dc:setto( 0 )
-- Create a new players group
p34 = players( 3, 4 )
acc = accumulate( 1 )
-- Another simple trigger example
p34:conditions( )
acc:exactly( 1, ore )
p34:actions( )
centerview( "Anywhere" )
-- Example of making a Lua function to do some slightly
-- heavier lifting! Original idea from Kaias
function cleartext( )
for i = 0, 11 do
text( "" )
end
end
p34:conditions( )
always( )
p34:actions( )
cleartext( )
-- Hyper triggers with looping example
p78 = players( 7, 8 )
for i = 0, 3 do
p78:conditions( )
always( )
p78:actions( )
for i = 0, 64 do
preserve( )
end
end
I ran this file and generated:
Trigger Code
Trigger("Player 1"){
Conditions:
Always();
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Add, 1);
}
//-----------------------------------------------------------------//
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", Exactly, 64);
Actions:
Display Text Message(Always Display, "print this");
Set Deaths("Player 1", "Alan Schezar (Goliath)", Seto To, 0);
}
//-----------------------------------------------------------------//
Trigger("Player 3", "Player 4"){
Conditions:
Accumulate("Player 1", Exactly, 1, ore);
Actions:
Center View("Anywhere");
}
//-----------------------------------------------------------------//
Trigger("Player 3", "Player 4"){
Conditions:
Always();
Actions:
Display Text Message(Always Display, "");
Display Text Message(Always Display, "");
Display Text Message(Always Display, "");
Display Text Message(Always Display, "");
Display Text Message(Always Display, "");
Display Text Message(Always Display, "");
Display Text Message(Always Display, "");
Display Text Message(Always Display, "");
Display Text Message(Always Display, "");
Display Text Message(Always Display, "");
Display Text Message(Always Display, "");
Display Text Message(Always Display, "");
}
//-----------------------------------------------------------------//
Trigger("Player 7", "Player 8"){
Conditions:
Always();
Actions:
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
}
//-----------------------------------------------------------------//
Trigger("Player 7", "Player 8"){
Conditions:
Always();
Actions:
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
}
//-----------------------------------------------------------------//
Trigger("Player 7", "Player 8"){
Conditions:
Always();
Actions:
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
}
//-----------------------------------------------------------------//
Trigger("Player 7", "Player 8"){
Conditions:
Always();
Actions:
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
Preserve Trigger();
}
//-----------------------------------------------------------------//
One of the biggest problems with a GUI for trigger creation, besides the annoying clicking, is the inability to use a tree hierarchy for organization. Although this tree feature will likely be created by jjf himself, there's also going to be a great feature for writing LIT code called
include. LIT lets you include another file into the middle of any other file. This will let LIT copy/paste entire files around. This lets you organize LIT files in whatever manner you wish, and is exactly the same as the
#include directive from C and C++. The file system on modern operating systems is actually organized through a tree itself
. Here's an example:
(in main.lua)
p1 = players( 1 )
p1:conditions( )
always( )
p1:actions( )
text( "print this" )
include( "otherFile.lua" )
(in otherFile.lua)
p1:conditions( )
always( )
p1:actions( )
text( "print a different thing here" )
The entire final LIT file, after the include operation is performed, looks like:
(in main.lua)
p1 = players( 1 )
p1:conditions( )
always( )
p1:actions( )
text( "print this" )
p1:conditions( )
always( )
p1:actions( )
text( "print a different thing here" )
Binary Countoff LIT Example
-- Create a group of players
p1 = players( 1 )
-- Create death counters
dc1 = deathcounter( "Alan Schezar (Goliath)" )
dc1:setplayer( 1 )
dc2 = deathcounter( "Zerg Queen" )
dc2:setplayer( 2 )
-- Create a custom function with Lua, converts the dc
-- from a into dc of b
function BinaryCountoff_AtoB( players, a, b )
for i = 0, 20 do
x = math.pow( 2, i )
p1:conditions( )
a:atleast( x )
p1:actions( )
a:subtract( x )
b:add( x )
end
end
-- Run the custom Lua function to make many triggers
-- use p1, dc1 and dc2 within the function
BinaryCountoff_AtoB( p1, dc1, dc2 )
Binary Countoff Triggers
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", At Least, 1);
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Subtract, 1);
Set Deaths("Player 2", "Zerg Queen", Add, 1);
}
//-----------------------------------------------------------------//
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", At Least, 2);
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Subtract, 2);
Set Deaths("Player 2", "Zerg Queen", Add, 2);
}
//-----------------------------------------------------------------//
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", At Least, 4);
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Subtract, 4);
Set Deaths("Player 2", "Zerg Queen", Add, 4);
}
//-----------------------------------------------------------------//
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", At Least, 8);
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Subtract, 8);
Set Deaths("Player 2", "Zerg Queen", Add, 8);
}
//-----------------------------------------------------------------//
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", At Least, 16);
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Subtract, 16);
Set Deaths("Player 2", "Zerg Queen", Add, 16);
}
//-----------------------------------------------------------------//
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", At Least, 32);
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Subtract, 32);
Set Deaths("Player 2", "Zerg Queen", Add, 32);
}
//-----------------------------------------------------------------//
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", At Least, 64);
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Subtract, 64);
Set Deaths("Player 2", "Zerg Queen", Add, 64);
}
//-----------------------------------------------------------------//
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", At Least, 128);
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Subtract, 128);
Set Deaths("Player 2", "Zerg Queen", Add, 128);
}
//-----------------------------------------------------------------//
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", At Least, 256);
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Subtract, 256);
Set Deaths("Player 2", "Zerg Queen", Add, 256);
}
//-----------------------------------------------------------------//
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", At Least, 512);
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Subtract, 512);
Set Deaths("Player 2", "Zerg Queen", Add, 512);
}
//-----------------------------------------------------------------//
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", At Least, 1024);
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Subtract, 1024);
Set Deaths("Player 2", "Zerg Queen", Add, 1024);
}
//-----------------------------------------------------------------//
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", At Least, 2048);
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Subtract, 2048);
Set Deaths("Player 2", "Zerg Queen", Add, 2048);
}
//-----------------------------------------------------------------//
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", At Least, 4096);
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Subtract, 4096);
Set Deaths("Player 2", "Zerg Queen", Add, 4096);
}
//-----------------------------------------------------------------//
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", At Least, 8192);
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Subtract, 8192);
Set Deaths("Player 2", "Zerg Queen", Add, 8192);
}
//-----------------------------------------------------------------//
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", At Least, 16384);
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Subtract, 16384);
Set Deaths("Player 2", "Zerg Queen", Add, 16384);
}
//-----------------------------------------------------------------//
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", At Least, 32768);
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Subtract, 32768);
Set Deaths("Player 2", "Zerg Queen", Add, 32768);
}
//-----------------------------------------------------------------//
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", At Least, 65536);
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Subtract, 65536);
Set Deaths("Player 2", "Zerg Queen", Add, 65536);
}
//-----------------------------------------------------------------//
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", At Least, 131072);
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Subtract, 131072);
Set Deaths("Player 2", "Zerg Queen", Add, 131072);
}
//-----------------------------------------------------------------//
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", At Least, 262144);
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Subtract, 262144);
Set Deaths("Player 2", "Zerg Queen", Add, 262144);
}
//-----------------------------------------------------------------//
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", At Least, 524288);
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Subtract, 524288);
Set Deaths("Player 2", "Zerg Queen", Add, 524288);
}
//-----------------------------------------------------------------//
Trigger("Player 1"){
Conditions:
Deaths("Player 1", "Alan Schezar (Goliath)", At Least, 1048576);
Actions:
Set Deaths("Player 1", "Alan Schezar (Goliath)", Subtract, 1048576);
Set Deaths("Player 2", "Zerg Queen", Add, 1048576);
}
//-----------------------------------------------------------------//
Anyways, I'm excited for Chkdraft to continue finishing up, and I believe the trigger format is identical to SCMDraft 2, so LIT will be able to be used to generate text files directly, which allows users to use LIT with SCMDraft 2 if they so wish. In the future I'll be posting some more about this to try to coax people into trying it all out to provide feedback. Currently I'll be just finishing up all of the different conditions/actions, and I think it would be cool to try to create a fancy syntax highlighter/auto complete thing for Notepad++.
If you already have suggestions please do post them up in this thread. If you can convince me that your suggestion is a good one I'll implement it. Here's a list of suggestions that I will complete with the names of who suggested them:
- LoveLess - Preserve trigger goes in all triggers by default. The user specifies a "nopreserve( )" line manually.
- LoveLess - dcauto( ) will create a death counter and pick a useless unit type. Each subsequent use of dcauto would pick a different player number until all useless units and player numbers are exhausted, and an error message will be produced.
- LoveLess - Create a function called hypertrigger( ) that people can use so they don't have to write their own loops!
Post has been edited 10 time(s), last time on May 21 2014, 8:26 am by CecilSunkure.
None.