Rise of Nations Scripting FAQ version 0.7
Unofficial
To use the finder system, just hit Ctrl+F and enter the code of the chapter
(e.g. #1b).
Contents:
I. Legal crapola you probably won’t want to read about. #01
II. An intro to the RON scripting language. #1a
III. The basics #1b
IV. Advanced topics #1c
V. FAQ (Under construction) #1d
VI. Contact info/version history/where to get more info. #1e
------------------------------------------------
I. Legal stuff. #01
------------------------------------------------
Ok, first of all, if you’ve actually bothered to read this, I’m somewhat
surprised. Anyway, here goes:
This FAQ is written by me, Martin Chu, and can only be reproduced or copied for
your own personal use. Any other use or distribution of this document is
forbidden (unless you have my permission).
The sites allowed to host this FAQ are:
GameFAQs (you already know the site)
DLH.net (dlh.net)
If for some weird reason you want to host my FAQ on your site, just ask - it’s
not that hard. Please don’t plagiarize, it’s wrong and you know it.
Any copyrighted materials found in this document are reproduced with permission
from the copyright holders and credit is given when necessary . Rise of Nations
is a registered trademark of Microsoft and Big Huge Games. I’m not affiliated
in any way with either of the companies. I just write FAQs.
Also note: The jokes I’m going to insert in this document are made by me.
That’s why they’re lame.
--------------------------------------------------
II. An Introduction to Big Huge Script (the script language used in RON) #1a
--------------------------------------------------
Hello, and welcome to my Rise of Nations scripting FAQ. I wrote this because of
the small amount of decent documentation on the complex scripting language used
in RON scenarios.
This is aimed at beginners with little knowledge about scripting (but know at
least how to put in the { } characters). For those who are proficient, you
should do a search on the net for advanced guides.
Since this document is still in beta, there will probably be errors.
For those who do notice errors in this, please read the last chapter for
contact info.
Big Huge Script, which I’ll refer to as ‘BHS’ from now on, is a scripting
language (duh) that’s based on C/C++ (Mid-level and high-level programming
languages) and Javascript (another programming language). Since I don’t know
much about Javascript, I’ll just cover the C and C++ aspects.
A sample of code from a program I wrote:
int main()
{
char name[50], location[50];
int x;
cout<<”Hello! Welcome to my program!”;
Ok I think I’ll stop there. Anyway, here’s a breakdown of the code.
Int declares (creates) a variable (very important in BHS as well) which is a
factor that has a changeable value. Int variables store integer values (which
are non decimal or whole numbers like 1, 10 etc.), char isn’t used in BHS but
for your information, they are used to store strings (strings of letters,
example: Hello, this is a string.) and float variables which store decimal
numbers (1.234 etc.).
cout simply outputs text (which you wont use in BHS).
Fortunately, in BHS you don’t have to declare variables since it automatically
defines them when you assign a value to a variable. If you don’t declare a
variable in C/C++, you’ll get an error when compiling it.
Unlike most other RTS scenario editors which have hard-coded variables and
checks, BHS is a more flexible system, allowing for a large number of different
possible combinations (here’s one for you math experts) with approximately 500
different trigger functions.
--------------------------------------------------
III. Basics of scripting #1b
--------------------------------------------------
So you understand variables right? Good, but variables are only one of the many
different aspects of Big Huge Scripting. There are labels, operators, triggers
and other stuff I may have missed.
I’ll just go a little more in-depth about variables. As I stated above, you
don’t need to declare them as you do in C. So let’s say I wanted to create an
integer variable, x, that stored a value of 2. In C, I would have to say:
int x = 2, but in BHS I just need to say ‘x = 2’. Why would you need to store
numbers when you’re busy managing your army to take out your opponent’s capital
or defending your own wonder? Simple, maybe a trigger needs to count the number
of citizens you have, or maybe the number of buildings you’ve destroyed.
Variables are usually the heart of programming languages, but in BHS they
aren’t as important as triggers.
Labels. Labels are a set of constants (variables that remain unchanged
throughout the entire script) that have set values assigned to them. Labels are
usually denoted by a
labels {
}
block. Just enter whatever constants you want to define there. Another simple
example:
labels (
enemy_name = “Evil dude”
}
assigns the constant ‘enemy_name’ the string value of ‘Evil dude’. Notice that
you don’t have to define variable types, since they are automatically assigned
an ‘anytype’ type (more on that later) A piece of additional info from the BHS
scenario editor docs, if you don’t assign a value to the constants, they
automatically get an increasing value of 1, starting from 1. So if you wrote
labels {
number,
another_number,
yet_another_number,
}
it would assign ‘number’ the value of 1, ‘another_number’ the value of 2 and so
on.
Triggers and trigger blocks. Triggers are the most important aspect of BHS
since they get or create values, print messages on the screen, make you win or
lose or a number of other things. A trigger function is just a trigger command
(look in the trigger functions list of the Big Huge Script editor) and usually
isn’t used on its own since it keeps re-executing until the game ends or the
script stops executing. Randomly pulling an example from the script editor,
create_unit (its name says it all) on its own would keep creating units at
whatever location I specified indefinitely, and would severely lag the game or
crash it. That’s why we need to use trigger blocks. In the script editor, hit
F2 or click on edit and insert trigger block. Enter whatever you want for the
block name and you should see something in the main editor window that looks
like this:
trigger (whatever you typed in) (/*Conditions under which the trigger will
fire*/) {
/* Blah blah help text stuff.*/}
You can delete the help text (the stuff in green) since you have my expert
guidance *coughcough*. Anyway, the ( ) (normal brackets or parenthesis if you
want to be precise) contains the firing conditions.
Say you wanted a trigger that checked if nation 1 was in the information age.
In the parenthesis, you would type in ‘at_least_age(1, 8). A quick explanation
of the trigger function parameters, almost all trigger functions have definable
parameters (in this case, for the at_least_age function, the first character
(1) is the nation number. The second (8) is the age number. You can find out
what the parameters are in the trigger description in the trigger function list
(in case you’ve forgotten, F1 or Edit --> Insert Trigger Function).
In the trigger function menu, the ‘Return’ bit is simply the type of data the
function ‘tells’ or ‘returns’ the trigger block or whatever. In functions that
shouldn’t have returns (like the set_victory_message one) the return integer is
usually a ‘success report’ that returns a 1 if successful (in Boolean that
means True or ‘Yes’), 0 if false (False in Boolean or No), meaning that it did
not perform the operation or -1 if it failed to do so (as in it couldn’t for
some reason).
The stuff in the braces which are the { } characters, not ( ) brackets (braces
the ones you get by holding Shift and pressing the [ or ] key) are the firing
commands, or the things that are done when the trigger is enabled and the
firing conditions are met. The trigger automatically disables itself once
fired. So another example:
trigger test_trigger (at_least_age(1,8)) {
victory(1);
}
assuming it is enabled, checks to see if Nation 1 is in the info age and if so,
it declares victory for that nation. The semi-colon (;) is the character used
in both C/C++ and BHS that closes a line (only needed for trigger functions,
not for stuff like labels.
Semi-colons. The last paragraphs above pretty much sums it up, so I’ll just
provide some examples as to when to use semi-colons and when not to.
victory(1); OK
label { stuff = stuff} OK, no semi-colon needed.
trigger some_trigger (at_least_age(1,8);at_least_pop(1,50)) {Stuff}
OK, need a semi-colon to separate trigger funcs.
create_unit(1,100,100, “Infantry”, 3) Bad. No closing semi-colon. You’ll get a
compile error if you try to compile that line.
Boolean. In Boolean, ‘Yes’ is the equivalent of ‘True’ and ‘No’ is the same as
‘False’. You can also use operators such as AND, NOT and OR. A brief
description of each operator:
NOT: changes the return value. Say a trigger function returned a TRUE, NOT
would change that to FALSE and vice versa.
AND: Checks to see if all arguments are TRUE. If so, it returns TRUE, otherwise
it returns FALSE. So in the statement: at_least_pop(1,5) AND at_least_age(1,8)
(BTW, that’s not the correct syntax) assuming you were in the info age and you
had more than 5 citizens, military dudes or whatever, both arguments return
TRUE and thus make the AND operator return TRUE. But if the at_least_age
parameters were (1,500000) it would return FALSE since you can’t get to the
500000th age (though for some reason, it still compiles.)
OR: It checks if any of the arguments are TRUE. If one or more are TRUE, OR
returns TRUE, otherwise it returns FALSE.
In case you don’t know already, TRUE is the equivalent of ‘1’ and False is ‘0’
In BHS, you can’t write AND or NOT or whatever since they give compiler errors,
but instead use the symbols. Some of these may not be correct so please bear
with me.
AND = &&
NOT = !
OR = || (Those are ‘pipe’ characters, the shift version of the key usually
above the return key. They are not the I key.
I think there are XOR and NOR operators, don’t know if they are used in BHS)
If statements. If statements are the basic decision making statements of BHS
and many programming languages. In most of them, the format is pretty simple.
if ( Conditions to be met) { Stuff to do when the conditions are met}
if statements don’t need to be enabled, once they execute, they usually ‘shut
down’ and don’t run again. If statements are sometimes accompanied by else
statements (more common in programming, less so in BHS). Else statements
contain instructions on what to do if the commands in the if statement are not
met. So, if x doesn’t equal 10,
if (x == 10) {/* Do stuff */} else {do other stuff}
would execute the commands in the else bit, in this case, do other stuff. You
can also use else if statements that define other argument(s) and what to do
when those conditions have been met. So, following on from the above example:
if (x == 10) {/* Do stuff */}
else if(x == 100) {victory(1);}
else {defeat(1);}
Breakdown of the statement: if x is equal to 10, do stuff, if x equals 100,
victory for player, otherwise defeat for the player. An alternative to long
else if statements is the switch statement which I’ll cover in the Advanced
Topics chapter.
There are many operators like the plus sign, minus etc. but the function of
each of them might not be too clear. Again there might be errors in this so
please contact me if you find any.
+ Simply adds the value after the operator to the value before. Example:
n = 1 + 2 assigns n the value of 1+2 (which is three, if you didn’t know :).
- Same as above, only that it subtracts.
/ The equivalent of divide. I assume you’ve gone to a school and learnt basic
maths, so you should know this.
* Multiply.
= Ah, this is different. A single equals sign doesn’t check a value, it sets a
value. This is a problem encountered with most scripters – they want to do a
comparison check, but instead end up changing the test candidate. Example:
b = 2 assigns the value of 2 (you already knew that).
== This is the comparison check. It compares the value on the left side with
the one on the right.
++ Increases the value of the value on the left side by one each execution. Ex.
x++ increases the value of x by one every time its executed.
-- Likewise, only it decreases the value.
< You probably already know, it just sees if the right value is larger than the
left one.
> Vice versa.
<= Checks to see if the right value is the same or larger than the left one.
=> Same thing, reversed
More on its way.
--------------------------------------------------
IV. Advanced Topics #1c
--------------------------------------------------
If data has an anytype type, it does not have a set data type (obviously). This
is one of the things that makes the BHS language so easy to use (well easier
than C++ anyway). As I said somewhere in the last chapter, if you don’t define
a data type to a variable (I’ll just call them vars from now on), it
automatically gives an anytype type. Unlike integers or floats, anytype’s cover
all the data types in the scripting language. Another example (again, I’m not
using the correct syntax):
x = 22
If the x = 22 bit was not in a label block or trigger or whatever, just on its
own, the x would be assigned the anytype value of 22. At first look, it may not
seem to work, but put it this way: Say you were presented with two items. If
you were asked to see if the two items looked the same, you don’t need to know
what the items are; all you do is look at the items and see if they match. It’s
similar with anytype types. In an IF statement, you want to see if the anytype
variable ‘z’ is equal to two. The syntax for this would be
if (z == 2) {Do stuff}
it simply does a comparison check, it doesn’t need to know what type of data
it is looking at.
Loops can be used to run repeated comparison checks and repeatedly execute
commands while the conditions are met. The basic statement to loop stuff is the
while statement. Example:
while (a == 15) {
print_game_msg(“A currently equals 15”)}
keeps printing “A currently equals 15” until a gets changed by an outside
source and doesn’t equal 15. It’s generally not a good idea to use while
statements to print game text, since if the variable used to activate the
statement is not changed quickly, the game message window will fill up with the
same message and block out any other ones (I accidentally used a while
statement to set an objective and didn’t close it, I ended up getting an
overflow error after the same objective kept re-posting itself for about 1
minute or so (about 5 re-posts every second). You can also loop triggers like
in this code sample from the Scripting Tips guide on RON Oracle written by
Daleran;
trigger createunit() {
create_unit(1,4,39,"Rifleman");
set_timer("loop1",10);//Sets a timer, but also sets how often the trigger
loops, in this case, 10 seconds
enable_trigger("createunit_loop");
}
trigger createunit_loop(timer_expired("loop1")) {
enable_trigger("createunit");
Used with permission.
The trigger bit is self-explanatory. The set_timer function, well, sets a
timer. Params are simple. First is a string value and is the name of the timer
(in this example, loop1) the second is an integer value and holds the duration
of the timer in seconds. I’ll put it in a logic sentence.
If the timer named ‘loop1’ has expired, then activate trigger named
createunit_loop. createunit_loop should activate the trigger createunit.
createunit then does all the other stuff including re-activating the loop1
timer which activates createunit_loop which activates createunit etc. etc.
Of course, without any outside influences, this trigger will continue
re-activating until the script stops executing (usually when you exit the
game/scenario). As you could imagine, this might pose a problem if you only
want the trigger looping during a certain part of the scenario. In that case,
simply add another variable to the ‘conditions’ section of the loop trigger
(createunit_loop) that will stay at the required value until you want the
trigger to stop looping.
The switch statement. You know about else and else if statements and you also
know how long they can get in some scripts. Well, an alternative to continually
writing ‘else if (whatever) else if(whatever)’ and so on is to use the switch
statement. Syntax follows:
switch(name of variable to be checked)
case (name of answer, no brackets followed by full colon):
do stuff, no parenthesis or braces.
break;
Apologies if the above example was a bit vague. Here’s a more in-depth
explanation. After ‘switch’ type in the name of the variable to be checked
(let’s just call it x) then, you need to enter ‘cases’. So, if we wanted to see
if x equaled 1, we would type in:
case 1: (enter commands to be executed)
So, if x equaled 1, switch would look for the case statement with the name of 1
and execute whatever commands were within that case. This applies to C/C++, not
so sure about BHS though, but case statements are followed by a ‘break;’
command after all the commands etc. to prevent the script from ‘falling’
through to (i.e. executing) the next case of commands. I guess break should
also be used with BHS.
There is also a ‘default’ statement which is used when the variable value
doesn’t equal any of the case statements.
I’ll put this in the advanced section, even though it shouldn’t really be here.
It’s the ‘for’ statement.
Syntax:
for (variable(s);conditions;stuff to do on loop)
{
Stuff to do each loop
}
Again, apologies if that wasn’t too clear. There are three parameters of the
for loop. The first one contains the variables to be initialized, to create
multiple variables, use a regular comma to separate them. The next parameter is
separated from the first by a semi-colon ‘;’ and contains the looping
conditions. As before, to specify multiple conditions, use a regular comma. The
next parameter, also separated from the second by a semi-colon, are the
variable operators which edit the variable in some way, usually to increase or
decrease the variable value so it stops looping eventually. An example, if I
wanted to create 20 units belonging to nation 1 at co-ordinates X 200 and Y
200, I would use:
for (x = 1;x < 20;x++)
{
create_unit(1,200,200,”Assualt Infantry”,1);
}
Yes, I could simply specify 20 as the num_units parameter(the last one), but
for demonstration purposes, I’ll leave it as 1.
The ‘do’ loop is the same as the while loop, only that the variable is checked
at the end of the loop instead of the beginning, meaning that whatever code is
part of the do loop will always be executed at least once. A while statement
must follow the do statement to specify the conditions.
do { print_game_msg(“This is a do loop”); } while (x <= y);
Certain scenarios might require setting up of control groups for the AI. This
section I will copy directly from Daleran’s scripting tips FAQ so I take no
credit for this.
create_unit(2,28,97, "Riflemen",6);
NVA1_id = find_idle_military(2);
add_to_group(2, NVA1_id);
group_attack_to_order(2,130,110);
Let me explain this, one line at a time. "create_unit(2,28,97, "Riflemen",6);"
creates 6 riflemen for nation 2 at game coordinate 28, 97. "NVA1_id =
find_idle_military(2);" finds the any idle military unit for nation 2 and sets
them to the variable NVA1_id. "add_to_group(2, NVA1_id);" add all units in
NVA1_id to the current control group for nation 2.
"group_attack_to_order(2,130,110);" tells the current control group for nation
2 to attack-move to game coordinate 130,110. In order for you to realize how
this works you have to remember scripts run like a sequence. Line one plays,
then line 2 plays and so on. So I realized that the newly created unit would be
idle. In a split second the search function would find these newly created idle
riflemen and add it to a control group. Then it commands that group to carry
out a command. Now the group is no longer idle so it can't be added to the next
control group. Thats why you could add another command right after this one and
it wouldn't affect the last group. You must have the control group carry out
orders though in order for it to work. You might also want to disable combat AI
for the scenario so the computer doesn't move the newly created guys before the
NVA1_id is able to find the idle units.
You don't always have to do find_idle_military. BHG made it so it found all
military units for a certain nation then made them attack a coordinate as shown
in tutorial 6. This can be done with find_military command. Any search function
in the scripting to find units or buildings can be used to carry out commands.
Also, as long as you us a waypoint command you can have a unit carry out
multiple orders.
More to come.
--------------------------------------------------
V. Frequently Asked Questions #1d
--------------------------------------------------
None yet...
--------------------------------------------------
VI. Contact info / Version history / Sources for Additional information #1e
--------------------------------------------------
My e-mail address is:
the_coder *at* optusnet *dot* com *dot* au
New address:
kek_chu *at* curl *dot* aunz *dot* net
If you’re going to contact me, please follow these guidelines:
DO:
Send me major corrections (I’m not interested in the fact that I spelled ‘the’
as ‘teh’ unless it happens over 20 times.)
Send me contributions to this guide (i.e. Additional questions, Additional
sections, suggestions)
Check to see if the question you’re asking (if you’re asking one) has already
been answered.
Don’t:
Continuously spam me with messages that are either irrelevant or have already
been answered.
Send anything inappropriate (e.g. hate mail, racist/sexist comments, anything
with excessive coarse language)
Criticism with pointers on how to improve is okay, but direct flaming with no
reason as to why the aspect is bad will be ignored/deleted.
When you send me a message, please include in the subject line ‘FAQ Addition’
or something similar. If you don’t, I auto-assume it’s a virus or spam (yes,
I’m paranoid).
If I don’t reply to you immediately, don’t get annoyed. I get a lot of mail in
my inbox (not) and under certain circumstances, I may not have access to my PC.
If I don’t reply after something like a fortnight or so, then you can send it
again. If you really need to get in contact quickly for some reason, you can
contact me via MSN Messenger, address vchu@upnaway.com.au. That’s not my email
address, only my msn account, so don’t send email to that address (try mailing
that you lame spam bots!).
Some info about me if you don’t have anything better to do.
I live in Perth, Western Australia, currently in high school and studying
computer programming at home. All due respect to Churchlands Senior High, but
their standard computing classes cover nothing related to the technical aspects
of computing.
Top 5 favorite games are:
1. Deus Ex (love the action/rpg elements of the game)
2. Half Life 2 (most immersive game I’ve ever played, awesome graphics and
story)
3. Half Life and its mods (best pc game ever)
4. Rise of Nations + T&P (awesome rts, inspired me to learn programming in the
first place)
5. The Longest Journey (best adventure game ever)
I’m currently part of a mod team. We’re working on a Half-Life 2 mod at the
moment and we’re looking for new talent to help us. Coders, artists, voice
actors, modelers etc. You don’t need to be experienced. Drop by at
pone.incogdesign.org/forums
Version History:
V 0.7 (09/29/2004):
First publication of this guide.
V 0.8 (10/10/2004):
Updated allowed sites list.
Added info on ‘for’ and ‘do’ loops
Added stuff on operators.
Added Ai control groups info.
V 0.8.2 (12/03/2004):
Added the “About me” section.
Updated the info on the ‘do’ statement
Fixed some spelling errors in the AI control groups bit
Additional info:
RON Oracle (www.ronoracle.com)
Rise of Nations Planet (ronp.mednickonline.com)
Rise of Nations Heaven (ron.heavengames.com)
My dad: For purchasing my computer and paying the internet bill.
Big Huge Games: For making one of the best RTS games I’ve played yet and
writing the documentation for the scenario designer/script editor.
Microsoft: For publishing the above.
CJayC: For hosting the net’s best source for FAQ’s and walkthroughs and for
hosting my guide.
Daleran: For allowing me to use info (I’ve marked which code samples etc. are
his) from his extremely helpful Scripting Tips article on www.ronoracle.com.
You can visit his homepage at http://daleran.freeservers.com.
(Insert name of person you think discovered electricity, in my case Benjamin
Franklin.): Discovering electricity so other people could make computers and
games etc.