ProTRG v1.1

by poiuy_qwert


Table of Contents^

  1. Introduction
  2. Changes
  3. Installation
  4. Usage
  5. Coding
  6. Contact


Introduction^

ProTRG is an advanced trigger creation language built on top of Python that is very useful for generating lots of SCMDraft triggers in an easy and efficient way. ProTRG is a command line "compiler" which runs the code in a plain text file and outputs SCMDraft triggers to another file file. It also comes with Notepad++ support, in fact its meant to be used with Notepad++ for a much easier experience.

Changes^

ProTRG v1.1 () ProTRG v1.0 (Jan 10, 2010)

Installation^

  1. Unzip ProTRG somewhere on your computer
  2. If you don't have Python, get it from www.python.org
  3. If you are going to use Notepad++ to make your life easier:
    1. Download it from notepad-plus.sourceforge.net if you haven't already
    2. Navigate to the Notepad++ folder and open the userDefinedLang.xml there
    3. Open the userDefinedLang.xml that came with ProTRG
    4. If this is the first user defined language you are adding (or you just downloaded Notepad++), copy/paste the entire second file (from ProTRG) into the first, replacing all that was there. If this is the second or more language you add, simply copy everything from the ProTRG file starting at <UserLang...> to </UserLang> and paste it at the end of the userDefineLang.xml right before </NotepadPlus>
    5. Copy the ProTRG.xml file into the "Plugins\APIs" folder
    6. Open Notepad++ and press F6, then place this script in there (make sure you change C:\Path\To\ProTRG\ProTRG.py to the real path to PyTRG.py and C:\Python25\python.exe to the real python.exe):
      cd "$(CURRENT_DIRECTORY)"
      NPP_SAVE
      "C:\Python25\python.exe" "C:\Path\To\ProTRG\ProTRG.py" "$(FULL_CURRENT_PATH)"
      NPP_CLOSE "scmd_$(NAME_PART).txt"
      NPP_OPEN "scmd_$(NAME_PART).txt"
      
    7. Save the script with a name like ProTRG.
  4. And thats it!


Usage^

Write your code (more in the Coding Section) using standard Python syntax with the ProTRG classes intermingled, and save it to a file. You can use any file extension you want for your scripts, but .protrg is the default (if you are using Notepad++ the syntax highlighting and autocomplete also expect .protrg as the default file extension). Any erros in your script will be printed in the generated SCMD triggers file, internal errors (such as not being able to open your script and or the destination file, and any possible bugs) will be printed to the file stdeo.txt inside the ProTRG folder

Coding^

ProTRG uses standard Python syntax with some custom classes to work with triggers. You start a new trigger by creating a new Trigger instance like:
Trigger(<players>)
<players> is a list of the players it applies to, for example:
Trigger(Player1, Player2)
This creates a new Trigger instance and adds it to the bottom of the internal trigger list. Any conditions or actions will be added to the last trigger created this way. For example, this is our first valid trigger in ProTRG:
Trigger(1, 2)
Always()
PreserveTrigger()
You might have noticed in the first example I used Player1 and Player2 but in the second I just used 1 and 2. This demonstrates once of the useful features of ProTRG, variables. Player1 and Player2 are really just Python variables holding the values 1 and 2. I could have also done something like:
someplayer = 1
Trigger(someplayer, someplayer+1, random.randint(3,8))
ProTRG is also very accepting of its arguments. For example the integer 1 can be used to represent a player, a location, a quantity, and a unit:
myvalue = 1
CreateUnit(myvalue, myvalue, myvalue, myvalue)
This is the exact same thing as:
CreateUnit(Player1, Ghost, 1, "Location 1")
This is a very powerfull feature of ProTRG, but it can also lead to some confusing errors if you misplace your arguments. If you accidentaly put your player in the location argument, ProTRG wont complain because they both accept integers. To help catch these problems, ProTRG has a collection of containers that can be used to tell ProTRG "hey, this is meant to be a ____". For example this code is valid, but probably isn't what is intended:
myPlayer = Player2
myLocation = 1
CreateUnit(myLocation, Ghost, 1, myPlayer)
In this example the LOCATION (myLocation) and PLAYER (myPlayer) arguments were switched, so a Ghosts will be created for player 1 in location 2 instead of a Ghost for player 2 in location 1. For ProTRG to be able to catch this error, we would put our player and location in their respective containers:
myPlayer = PLAYER(Player2)
myLocation = LOCATION(1)
CreateUnit(myLocation, Ghost, 1, myLocation)
ProTRG will now report that there was an error interpreting the PLAYER argument since it was passed a LOCATION. These ProTRG types are just containers, they dont do any error checking on the values (thats all done by the conditions/actions). They emulate a numeric type, so if they are holding an integer you can do math with them, but if they hold a string you must use the value member to access its value:
myString = STRING("This string will be printed to the SCMD triggers file")
print myString.value
The ProTRG types are just basic Python classes, but they arn't the only ones, Trigger and all conditions and actions are actually Python Classes, and can be treated as such. For example, this results in the same thing as the first valid trigger we made above, just in a different way (and technically useless way. this is just for demonstration):
the_trigger = Trigger(1, 2, add=False)
Always(add=the_trigger)
preserve = PreserveTrigger(add=False)
the_trigger.add(preserve)
the_trigger.addTrigger()
This also demonstrates the "add" keyword parameter. It must always come last in the parameters, but can be useful. For Trigger's the add keyword parameter can be either True (1) or False (0) which defines if the Trigger is automatically added to the end of the internal trigger list or not. In the example above we chose to add the trigger later with the addTrigger method on our Trigger object. For conditions or actions, the add keyword can either be True (1) or False (0) to decide if the condition/action should be automatically added to the last trigger or not. If you supply a trigger object, like what the example does for the Always condition, the condition/action is added to that trigger. Another thing you can do since the Trigger's/conditions/actions are basic Python classes, is add them multiple times and to multiple triggers. For example, to create basic hyper triggers, you can create three Triggers with a Always condition and 63 Wait actions each like so:
Trigger(Player8)
Always()
Wait(0)
..61 Waits..
Wait(0)
PreserveTrigger()

..Copied Twice..
Or you can make it using 1 Trigger instance, 1 Always instance, 1 Wait instance, and 1 PreserveTrigger instance, like so:
trig = Trigger(Player8)
trig.addTrigger()
trig.addTrigger()
Always()
wait = Wait(0)
for _ in range(63):
	trig.add(wait)
PreserveTrigger()
This example also introduces you to one of the biggest advantages of ProTRG, the control statements from Python like if/then/else, while, and for statements. To demonstrate them all, we'll take the hyper triggers we just created and turn them into an easy function we can call from any of our later scripts.
def hyperTriggers(computerPlayer, debug=False):
	if debug:
		print "// Hyper Triggers generated for computer player: %s" % computerPlayer
	trig = Trigger(computerPlayer)
	trig.addTrigger()
	trig.addTrigger()
	Always()
	wait = Wait(0)
	for _ in range(63):
		trig.add(wait)
	PreserveTrigger()
Now that we have our function, we can save it to a seperate file (like Hypers.protrg) and then use it in any other script:
@include Hypers.protrg

hyperTriggers(Player8)
The @include keyword looks for a file matching the specified filename (first in the same folder as the script with the keyword, then the ProTRG folder) and practically copies its contents into your script (it is very much like Pythons own import keyword). Python also supports arrays (or lists as their called in Python). With this you can go through a list of numbers/units/players/strings/conditions/actions easily. For an example:
Trigger(1)
values = [Always, 1, "String"]
for value in values:
	if isinstance(value, Condition):
		value()
	elif isinstance(value, int):
		Wait(value)
	else:
		Comment(value)
The above code is the same as doing:
Trigger(1)
Always()
Wait(1)
Comment("String")
For more info, check out:

Contact^

You can find me at these sites with the nickname poiuy_qwert: If you must, my email is p.q.poiuy.qwert@gmail.com but I don't check it very regularly. Your best bet is to post or PM me at the sites above.