- 积分
- 1497
- 威望
- 0
- 魅力
- 0
- 经验
- 0
- 热心度
- 0
- 注册时间
- 2005-11-10
- 最后登录
- 2016-9-26
- 主题
- 27
- 回帖
- 197
- 精华
- 4
- 阅读权限
- 80
该用户从未签到
绘图大师
- 积分
- 1497
|
Author: Gaidal Cain
URL:http://www.celestialheavens.com/forums/viewtopic.php?t=35
PostPosted: Sat Dec 31, 2005 1:11 pm
Post subject: [wiki]ERM[/wiki] for dummies
This is intended as a repost of Qurqirish Dragons' old thread , in which he tried to explain ERM so that people who've never coded before would be able to use it. Unfortunately, Forumplanet's code has messed up some of the code below, which might make it unclear on some points (this is generally true when the comparators < and > (lesser than and greater than) are used. If you see something like > or <, it's these operators). If there's something that seems incomplete in this way, please report and we'll try fixing it or at least put in a note about it.
Since ERM also isn't static, it's possible there are better ways to do some things described here, that it sin't complete or that some of the things described here no longer works at all. To avoid this causing trouble, refer to your documentation. None of it should should prevent this from being a useful introduction to ERM, though.
This thread is also intended as a good place to ask questions about ERM, and to make this easy to use, the whole first page will only contain the lessons, and not any 'general stuff'. This is why there is some "empty" posts at the bottom. Otherwise, one would have to scroll through these long lessons just to get to the discussion.
Lastly, I've marked up parts of the lessons with blue. These are either code parts in the middle of some text, or something that's being explained in the present part. This should help when you're searching for an explanation of something. However, this markup is by no way complete. I've also added some comments of my own in certain parts. They are all in dark blue. I've also taken the freedom of correcting some spelling mistakes and to add some headers for easier use, as well as clearifying one or two passages. There has also been created an index below to help finding help on a specific subject. One problem with this index is that it right now opens the link in a new window, but it might still be of some use.
We hope you'll find this useful, and help populate or sqript directories with many new, interesting scripts!
Index
Lesson 1: Introduction
Lesson 2: Time for Battle!
Lesson 3: More on messages
Lesson 4: Variables!
Lesson 5: Objects
Lesson 6: Heroes
Lesson 7: Even More Messages!
Lesson 8: The sphinx
Lesson 9: To the Battlefield!
Lesson 10: The struggle continues
Lesson 11: The Cards of Prophecy
Lesson 1: Introduction
The first thing to know is that any script you place in a map must be placed in a timed event. That is, in the map editor, go to the Tool menu, then select Map Specifications, and click on the Timed Events tab.
Since you generally will not want the script to appear as a timed event, be certain to uncheck the box that says Apply event to Human players.
Also, since you will often want to have timed events that do appear to the player, it is strongly recommended that you use a high day number- days 500+ are suggested, since maps seldom take over a year game time to finish, and so it is very unlikely that timed events will be needed here. This conveniently gathers all your scripts at the end of the event list.
Finally, you should give the event a name that describes the script.
Now, put the script in the message portion of the event. You can type the event directly in here, or you can (and this is how I suggest you do it) write the script in the script editor, and copy it into the event.
If you do use the script editor, then be certain to follow the following procedure- this will avoid a very common source of errors:
1) If you have made any changes to the script since you last saved it, then save it again.
2) Select the whole script (ctrl-A does this), and copy it (ctrl-C)
3) Go to the map editor, and paste the script (ctrl-V)
If you used any other editor (such as notepad) to write the script, then open the script editor, copy the script into it, and re-save. Many editors- particularly Wordpad and word processors- place non-printing characters and visual formatting codes in the file, and these will cause ERM errors.
----------------------
Now, on to actual scripting. I will assume here, and in all future installments, that you are using a recent version of the ERM script editor, and you have the highlighter ON (that's the H button at the bottom of the scripter window). Other than that, I will not assume you know ANYTHING but what I have discussed in these posts.
First, whenever you are working on a script, I suggest you first write down on a separate sheet of paper- and I actually mean to write, not use a text editor- what you want the script to do. Do some brainstorming to see how you like it to be, and do a general sketch of the script's flow.
For example, I wrote a script that modifies the Card of Prophecy (this is script34.erm in your /data/s folder) to play around with a hero's stats, when entering battle. Fortunately, I kept my notes on the script, and can share them here. Note that when I first started this, I had NEVER EVEN LOOKED at ERM scripting before.
I started by writing the following:
Artifact that gives, at start of battle, a random primary stat of -1 to +4. Attach to any given artifact for testing.
That was the whole idea. Seems simple right? I thought so too. Next, I wrote the basic steps down:
Start of battle - check if art. is equipped
no - end
yes- set flag, choose random number (1,2,3,4) for stat
And so on. Just a general sketch. I will not go into any more detail here, I just wanted to show what I did before sitting down at the scripter. Believe me, if you do this first, things will go a lot more smoothly.
-------------------------
Now, time to write code!
The first line of any script is:
Code:
ZVSE
This tells [wiki]WoG[/wiki] that the timed event is a script. Without it, all your hard work will be ignored by the game.
All commands are four characters long, and are one of three basic types, not including ZVSE. In the script editor, commands are displayed in dark red.
Triggers are commands that say "If something occurs in the game, start executing the script that follows". Almost all Triggers begin with the characters !?
For example, take this line of code from my Cards script (again, that is script34.erm if you are following along there):
Code:
!?BA0&v1321=1; [start of battle]
This is the first trigger in my script. Don't worry about what the command does yet- I'll explain that later. However, do note the semicolon. All ERM commands END with a semicolon. Anything after that is considered a comment. In the scripter, anything that is a comment is shown in green.
Receivers are commands that set, check, or modify something in the game. They are not executed, unless they follow a trigger. All receivers begin with !!
For example:
Code:
!!BA:E?v1331; [check for multiplayer]
Again, note the semicolon to end the command. From the comment you can tell what this command is for, but that is for later.
Finally, instructions are just like receivers, except that they run only one time- when the map begins. They always begin with !#
For example:
Code:
!#UN:P34/?v1321; [is script active?]
For those looking at the script, note all the green lines that start with ** I use a double-asterisk to introduce a comment line. This is not necessary, and other script writers use other commenting methods. As long as you do not begin a line with a command, the line is ignored by ERM. I like to force comment lines to be recognized as such, so they stand out in green.
To wrap up this first installmanet, I will explain a couple simple commands, so you can do SOMETHING. The second installment will give you a bit more to work with- but feel free to experiment.
This script will simply count how often any hero has visited the upper-left corner of the map's surface layer- coordinates (0,0,0). Whenever I introduce a command, feel free to look it up in the ERM help.
The first line is, of course:
Code:
ZVSE
Next, we need to set a counter to 0. Since we want the counter to start at 0, and not wait for a hero to visit (0,0,0), we use an instruction. The instruction to assign a value to a variable is !#VR
Before we can go further, we need to choose a variable to hold the count. Normally, you should consult the List of the Claimed, easily found in the ERM help file- just choose it off the index, and choose a variable that is free. For purposes of my tutorials, however, I will always use low-numbered v variables. v variables are the ones you will use most often. I will introduce the other types as needed.
So, now use the command:
Code:
!#VRv1:S0;
This, broken down, says:
!#VR ...
Perform a variable command at the start of the map
... v1 ...
operating on variable v1
... : ...
Any command which does anything uses a colon to separate the command from the action being taken. Triggers will not have them, but other commands will.
... S0 ...
The S option for VR says you want to Set the value of the variable. In this case, we are setting it to 0.
... ;
As I mentioned above, a semicolon ends the command.
Now, we need to set an event trigger. In the map, place an event at (0,0,0). It does not need to have anything in it, you just need it to be there, and allow all players to activate it, and allow it to be used multiple times.
Now, we set the trigger:
Code:
!?LE0/0/0;
The LE trigger says "When the event at the given map coordinates activates..." The three numbers are the x,y, and z coordinates of the event, in that order.
If you are looking at the ERM help for the !?LE trigger, you will notice there is also a !$LE trigger (a dollar-sign instead of a question-mark). This says "After the event at the given coordinates is finished..." If the map event does something without ERM, you may want the script to run after it, instead of before. In this example, it doesn't matter which one we use, since the event is blank.
Next, we need to add one to the counter. This uses another VR command, but this time we use a receiver (!! instead of!#):
Code:
!!VRv1:+1;
ERM uses a + to indicate addition, as you would expect. So this command says "add 1 to variable v1." The other math operators are:
subtraction uses - (a minus sign)
multiplication uses * (an asterisk)
division uses : (a colon)
modulus (remainder when dividing) uses % (a percent sign)
Note that except when using an e variable, all arithmatic is done as integers, so 7 divided by 4 is 1, not 1.75.
Finally, we need to show a message to the player saying how often anyone has come to this spot:
Code:
!!IF:M^You are visitor number %V1 to the Northwest corner of the surface!^;
IF is the command to open an interface with the player. This can be as simple as displaying a message- as I have done here- or to ask questions, give dialogues, display images, and so on.
The M option says "Display the message between the carats." There are only a few restrictions with what can be in a message. You cannot use a carat or a semicolon. You also need to be careful with a percent- it is special. If you want to display a %, you need to type %%.
You probably noticed I have a single % in the message. If you use a single %, then the next thing is something special you need. In this case, %V1 (note that the V is capitalized, even though the variable uses a lower-case v) shows the value of variable v1. If you look at the help for !!IF, you will see the list of % commands.
That's it for the script. So, placing it all together in one place, we have, with comments added:
Code:
ZVSE
!#VRv1:S0; [set variable v1 to 0]
!?LE0/0/0; [when event at NW corner of surface is visited]
!!VRv1:+1; [add 1 to v1]
!!IF:M^You are visitor number %V1 to the Northwest corner of the surface!^; [show message]
In the next installment, I will cover the FU, BA, and HE commands, and show how to do a simple battle script.
Questions/answers on lesson 1
Question: When I uncheck the "Apply event to human players" box, the box labled "Apply event to computer players" is checked. It wants one of the boxes to be checked. Is this right? I can't get both boxes unchecked.
Answer: That's OK. The only reason you do not want the player to see the event is that, well, it would look rather odd, wouldn't it?
Question: When you say the ERM help file, I assume you are talking about running erm_help\index.html. I can't find anything labled "List of the Claimed". Where is this easily found list?
Answer: There's a button "Claimed" at the top. There you'll find all claimed variables, flags, timers and fuctions(these are for pre-made scripts only! If you're making a map on your own, and don't plan to use someone else's script, please ignore the list).
Lesson 2: Time for Battle!
Whenever possible, I am going to state the goal of a lesson before it begins- this way if you already know how to do what I have listed, you can feel free to skim or skip the lesson.
In this segment, I am going to take the 5-line script developed at the end of part 1, and expand it. What the script will do is make it so that every 10 times anyone visits the NW corner of the map, the world become magically strong, weak, or normal, cyclicly. In other words, after 10 heroes have visited, all heroes' spell powers, in combat, will be doubled. After 20, combat spell power will be set to 1, and after 30, spell power will be reset to normal. The cycle then repeats.
First, we are going to insert a new line, between the !!VR and !!IF commands. This line will check to see if you are the (10*n)th visitor to the site. Since this value is not needed to be kept after the script runs, I will use a temporary variable. The temporary variables in ERM are the y variables. They are not saved between scripts, so you cannot use them for permanent storage. However, you can also rest assured that you will not mess up other's scripts when using them. So let's add the line:
Code:
!!VRy1:Sv1%10; [is v1 a multiple of 10?]
This command uses two operators in one statement. All math is done from left to right in ERM. Remember that if you have several operations to perform- it may be easier to split it into several lines. In this case, we first set variable y1 to the value of v1, and then find the remainder when divided by 10. If y1 is 0, then we know that v1 is a multiple of 10.
Now, if it isn't a multiple of 10, then nothing will happen, and we can just display the message that we had before. However, a small change needs to be made:
Code:
!!IF&y1<>0:M^You are visitor number %V1 to the Northwest corner of the surface!^; [show message if nothing else happens]
Aside from a change in the comment, I have added, before the colon, the condition &y1<>0. The ampersand (&) says "only do this command if the following is true." The rest says that y1 is not equal to 0. Thus, this message will only be displayed if nothing else happens, other than the counter increasing.
Now, if v1 *IS* a multiple of ten, we want to have the message indicate that magic as been shuffled around. But for this, we need to find out which change is being made. So, we will use another y-variable to check this:
Code:
!!VRy2:Sv1:10%3; [find magic change type]
This takes v1 and divides it by 10, then finds the remainder when this is divided by 3. This will give variable y2 the value of 0 if v1 is less than 10, between 30 and 39, between 60 and 69, and so on. y2 will be 1 if v1 is between 10 and 19, 40 and 49, etc. y2 will be 2 in the other areas. Note that even if v1 is NOT a multiple of 10, this is being calculated.
Now we need three more IF commands- one for each type of change. However, I can introduce a few more concepts by taking a slightly longer route.
We want to have a message that says "You are visiter number [whatever], you feel the world's magic power strengthen."
We want to have another message that says "You are visiter number [whatever], you feel the world's magic power weaken."
We want to have a third message that says "You are visiter number [whatever], you feel the world's magic power return to normal."
Notice that these three things say almost the exact same sentence- only a couple words change. We really don't want to do all that typing. This is particularly true if we later want to add more possibilities.
For this, we are going to use a z variable. z variables are the only ones that can store actual text values. Just like v variables, z variables are permanently kept. However there are a few z variables that are temporary, like the y variables. A quick look at Flags and Variables in the ERM help shows that the temporary z's are z-1 through z-10. Let's use variable z-1 to hold that little bit of text that changes. This will take three lines:
Code:
!!VRz-1&y2=0:S^return to normal.^; [for visit 30, 60, 90, ...]
!!VRz-1&y2=1:S^strengthen.^; [for visit 10, 40, 70,...]
!!VRz-1&y2=2:S^weaken.^; [for visit 20, 50, 80, ...]
At this point you should be able to understand these lines completely. Together, they set variable z-1 to the appropriate end of the message we want to display. Note that the rules for placing text in a z variable are identical to the rules for placing text in an IF:M command: You can use % commands to use other variables within them, if you need to, and you need to type %% for a percent character. Carats and semicolons are still not allowed.
Now we need to display the new message:
Code:
!!IF&y1=0:M^You are visiter number %V1, you feel the world's magic power %Z-1.^; [show change message]
This time, the condition is that y1 equals 0. We only want this message to appear if a change is happening.
We have now gotten all of our messages out of the way. Next comes the code to modify hero statistics in battle.
I am going to add a comment line here- remember that in the script editor this will appear in green:
Code:
** in-battle effects routine starts here
We need to check for a battle starting. This means we need a new trigger- for the start of a battle:
Code:
!?BA0;
Since we have used a new trigger, the previous code will stop running when it gets here. The BA trigger looks for battles. BA0 (that's a zero, not an o) is the trigger for the start of a battle. We will need another trigger for the end of the battle as well.
Now, as many of you will know from reading other threads, battle scripts often have problems in human-vs.-human, network multiplayer battles. Although this script should not have a problem here, I am going to check for this case, and not allow the script to run in this case. There is a special command for this check:
Code:
!!BA:E?y1; [is this a network battle?]
This is a BA receiver. The E option says "find out what kind of battle is occuring." ?y1 says take the result of the BA:E command and store it in y1. Note that I am reusing y1 from before- that is the advantage of temporary variables: you don't have to worry about old contents when you want to use them.
Checking the ERM help will tell you what values y1 may now have:
If the battle is between an AI hero and a human player, on the AIs turn, at a computer other than the host, then y1 is set to 2.
If it is between two humans, other than hot-seat, y1 is set to 1.
Otherwise, y1 is set to 0.
Now, we only want the script to run in the last case. Until you learn what types of battle scripts work in cases 1 and 2, it is safest to do this. We now had the next line:
Code:
!!FU1&y1=0:Pv1; [if not, continue the script]
This is a new receiver. The FU receiver calls another script function, in this case function 1. Again, we have the condition that y1 is 0. If not, the function will not start. The option P means that the following parameters need to be passed into the function. Although it is not necessary in this case, I have passed in variable v1. This will let me manipulate v1 inside the function, without changing the stored value.
We do not need to do anything else at the start of a battle, so we can now go right on to the function.
We start by using a function trigger, to indicate a new code section, along with a comment:
Code:
** start of pre-battle
!?FU1;
Since we want to modify the spell power of any heroes in the battle, we need to know which heroes are fighting, if any, on both the attacking and defending sides. This is done with two battle receivers:
Code:
!!BA:H0/?v5; [get attacking hero's hero number]
!!BA:H1/?v6; [get defending hero's hero number]
The H option asks for a hero number. H0 refers to the attacker, H1 refers to the defender. If there is NO defending hero, then BA:H1 returns a value of -2. All the hero numbers are listed in the ERM help file under format H, but since we are applying this routine to all heroes, we don't care about specific numbers. I chose to use v5 and v6 to hold these numbers, because I have a special purpose intended for v3 and v4 later, and I wanted the hero numbers in adjacent variables, for my bookkeeping.
Now, we need to find out what kind of spell power change to apply. Since we stored that in a y variable above, we may not still have the value in memory- and we should assume not. However, we do have the counter in v1. So, let's get the change type again:
Code:
!!VRx1::10%3; [get magic change type]
This looks familiar, but there have been a few changes. First, note that I used variable x1, not v1. This is because this statement is changing the value of the variable, but we do not want to change the counter. x variables are numbered from x1 through x15, and they contain the parameters that were passed into the function from the FU receiver. Since I passed in v1, x1 has that value. There is also an x16, and you can pass in a 16th variable, but x16 has a special purpose (which will be dealt with later), and so you should avoid using it if possible. Also note that x variables can only hold integer values, so you cannot pass in a z-variable to a function.
Also, do not be worried about the double colon. The first colon separates the VR receiver from the options. The second is the division operator. Now, x1 contains the value that y2 did in the first part of the script.
We are almost ready now. We simply need to find out what the heroes' spell powers are.
Code:
!!HEv5:F?y5/?y6/?y3/?y7; [get attacker's stats]
!!HEv6&v6>=0:F?y5/?y6/?y4/?y7; [get defender's stats]
The HE receiver is used to modify any and all aspects of a hero. The first line looks at the hero whose number is in v5, the second line at v6. In the second line, we add in the check v6>=0, so that if there is no defender, WoG doesn't try to look for hero -2. This would cause an error when the script ran.
The F option says to look at the hero's primary skills. the next four numbers are separated by slashes, and are the attack, defense, spell power, and knowledge skills, in that order. If you just place a number or variable there, it changes the hero's stat to that value. If you place a ? before a variable name, then it takes the current value and stores it in the variable. In this case, variables y3 and y4 will contain the spell powers for the heroes. variables y5, y6, and y7 are only there as place-holders, and so I could reuse them.
At this point, I should note that it is a good idea to keep track on a separate paper what every variable holds. This will help if you should forget.
Now, we need to set up the changes- specifically, figure out exactly how much of a change will be done to the spell power. Since we will need to know what the change is later (when we restore the old values), we will store these in two more v-variables. I will use variables v3 and v4, corresponding to y3 and y4. This is why I skipped them earlier.
Code:
!!VRv3&x1=1:Sy3; [if magic strengthened, spell power increases]
!!VRv3&x1=2:S1-y3; [if magic is weakened, spell power reduces to 1]
!!VRv4&x1=1/v6>=0:Sy4; [if magic strengthened, spell power increases]
!!VRv4&x1=2/v6>=0:S1-y4; [if magic is weakened, spell power reduces to 1]
The new thing seen here is in the 3rd and 4th lines. The slash in the conditions is the same as a logical "and". So, &x1=1/v6>=0 says "if x1=1 and v6>=0, then do the command."
Now we just need to make the changes:
Code:
!!HEv5&x1>0:Fd0/d0/dv3/d0; [modify spell power]
!!HEv6&x1>0/v6>=0:Fd0/d0/dv4/d0; [same for defender]
Here, we are modifying the heroes' stats, but only if x1 is not 0. Remember that if x1 is 0, then our counter indicated that there is no change to magic power. Again, we use the HE:F command. The d before any number or variable says that the number or variable should be ADDED to the current stat. d0 leaves the statistic alone.
We have now finished the before-battle function!
To recap, our script now looks like:
Code:
ZVSE
!#VRv1:S0; [set variable v1 to 0]
!?LE0/0/0; [when event at NW corner of surface is visited]
!!VRv1:+1; [add 1 to v1]
!!VRy1:Sv1%10; [is v1 a multiple of 10?]
!!IF&y1<>0:M^You are visitor number %V1 to the Northwest corner of the surface!^; [show message if nothing else happens]
!!VRy2:Sv1:10%3; [find magic change type]
!!VRz-1&y2=0:S^return to normal.^; [for visit 30, 60, 90, ...]
!!VRz-1&y2=1:S^strengthen.^; [for visit 10, 40, 70,...]
!!VRz-1&y2=2:S^weaken.^; [for visit 20, 50, 80, ...]
!!IF&y1=0:M^You are visiter number %V1, you feel the world's magic power %Z-1.^; [show change message]
** in-battle effects routine starts here
!?BA0;
!!BA:E?y1; [is this a network battle?]
!!FU1&y1=0:Pv1; [if not, continue the script]
** start of pre-battle
!?FU1;
!!BA:H0/?v5; [get attacking hero's hero number]
!!BA:H1/?v6; [get defending hero's hero number]
!!VRx1::10%3; [get magic change type]
!!HEv5:F?y5/?y6/?y3/?y7; [get attacker's stats]
!!HEv6&y2>0:F?y5/?y6/?y4/?y7; [get defender's stats]
!!VRv3&x1=1:Sy3; [if magic strengthened, spell power increases]
!!VRv3&x1=2:S1-y3; [if magic is weakened, spell power reduces to 1]
!!VRv4&x1=1/v6>=0:Sy4; [if magic strengthened, spell power increases]
!!VRv4&x1=2/v6>=0:S1-y4; [if magic is weakened, spell power reduces to 1]
!!HEv5&x1gt;0:Fd0/d0/dv3/d0; [modify spell power]
!!HEv6&x1gt;0/v6>=0:Fd0/d0/dv4/d0; [same for defender]
Note how the comment lines help see the sections.
Now, after the battle, we need to undo the changes. First, we do a post-battle trigger:
Code:
** post-battle starts here
!?BA1;
!!BA:E?y1; [network battle?]
!!FU2&y1=0:Pv1; [if not, undo changes]
Looks familiar, right? well, the only changes are in the trigger, and the function number. The trigger is now BA1, this means this triggers at the END of battle. And, since we want to change the stats back, we need a separate function. Fortunately, we stored the hero numbers and changes in v-variables, so we don't need to calculate them again.
Let's start the clean-up:
Code:
!?FU2;
!!VRx1::10%3; [get change type]
!!VRv3:*-1; [negate attacker's changed stat]
!!VRv4:*-1; [negate defender's changed stat]
Since v3 and v4 have the changes to spell power, we multiply by -1. Now, if we add them as we did before, it will undo our change.
Code:
!!HEv5&x1gt;0:Fd0/d0/dv3/d0; [restore attacker's power]
!!HEv6&x1gt;0/v6>=0:Fd0/d0/dv4/d0; [restore defender's power]
Again, we have the check that spell power was altered, and that there was a defender in the second line.
We had to store the hero numbers because if a hero was beaten, it will be in the hero pool, not the battlefield at this time- we would not be able to get the number at this point.
Our script is now done!
Lesson 3: More on messages
Up to now, the script that we have been designing only activates when someone visits the NW corner of the map. Why would anyone send his hero over there? Well, you could always place an event on the map (either as a site or a timed event), notifying the player of the special place, but I won't do that, as you don't use ERM for that. Instead, I am going to create an attraction for a player. I'll do this by placing a new object on the map. If you are following along with the map editor, look at the Towns page. If you haven't looked here before, you will find there are a lot of objects here after the 10 towns you are used to seeing (9 town types, and random). Most of these objects are unscripted- that means that if you place them on a map, even if you wogify the map, they do not do anything. We are going to use one of them.
For this script, I am going to use the 4th object in the 3rd row. It looks like a pentagram with small obelisks on the points, and a large obelisk in the middle. Place this on the map, as close to the corner as you can, without cutting amy of the image off. If you do not normally have it on, turn on the passibility tool- this places red and yellow squares on the map. Any red square cannot be passed by a hero. Any yellow square is a trigger square for the object.
If C=no block, R=red, and Y=yellow, then this object, to the editor, looks like:
Code:
CCCCC
CRCRC
RCYCR
CCRCC
Placed as I suggested, the yellow square should be located at (2,2,0).
Now, let's modify the script to use this object, instead of the event we placed. If you have been actually doing these tutorials, you can delete the site event from the map- I will not be using it again.
Now, we are going to replace the !?LE line, to attach our script to the yellow square. Recall, the old line was:
Code:
!?LE0/0/0; [when event at NW corner of surface is visited]
Now, we simply change the location to the yellow square (2,2,0), and change the command from LE to OB:
Code:
!?OB2/2/0; [when object at (2,2,0) is visited]
Notice that the OB trigger is exactly the same as an LE trigger in format. If you had no problems with what LE did, then you'll have no problems with OB. Just remember that LE stands for Local Event, and OB stands for OBject, and you will know when to use each one.
Now the script will work just as it did before, except now the site we just placed will activate it. However, I am going to make one more change to the line:
Code:
!$OB2/2/0; [AFTER object at (2,2,0) is visited]
I have changed this from a pre-visit trigger (!?), to a post-visit trigger (!$). Currently, this doesn't have any effect on the script, but it will after we add something else to the script- we are going to add in a resident to the site, who will give you the option to advance the magic counter by five if you pay 100 gold, otherwise it will count only one. Further, we are going to place an existing object there- since it makes sense, remove the pentagram, and replace it with a star-axis. This is just my choice- if you want, replace it with any Shadow of Death site that has a function. Just be certain to only place an object that has only one yellow square, and place that square at (2,2,0).
If you ran the map now, then when you visit this star axis (and only THIS star axis), you will get your usual +1 spell power (or nothing if your hero was there previously), and then the counter will increase.
Now, let us script in a creature with a "mystical magic stand" set up outside the star axis. I think that due to the nature of the script, a faerie dragon proprieter is best.
Anyway, let's start scripting:
Code:
!?OB2/2/0; [When object at (2,2,0) is visited]
This is simply the pre-visit trigger, just as the post-visit trigger looked, since the same object is being visited.
Now, we need to code in a yes/no question.
The first thing we have to realize is that we are going to ask a question that needs to be answered. This causes a problem if the AI sends a hero to visit the site. So, we need to see if the current player is human or AI. We do this with the OW receiver. OW lets you check or set almost anything having to do with a player (rather than a hero). So, we script:
Code:
!!OW:C?y1; [get current player color]
!!OW:Iy1/?y2; [is current player an AI?]
The C? option checks the color of the current player. You cannot change the current player, so the ? is part of the option here. I am storing this color in y1. The next line uses the I option. This lets you check a color to see if it is an AI player. The first number is the color being checked- in this case, the color we want is that of the current player, so I placed y1 there. The second number is the value 1 for an AI, or 0 for a human. You can actually set this to add or remove a human player from a map! For now, we just want to read this in. So now, if it is an AI's turn, y2 will get the value 1, otherwise y2 will be 0.
Note that there's another, mayhaps easier way to check human/AI, when you're sure you're dealing with the current player(if it's a script attached to an object, for example, the only color that CAN trigger it is the current)- the flag 1000. This flag is automatically set by WoG
to 1 if the current player is a human, and to 0 if the current player is AI. It does have a different meaning in combat triggers, but it is the easiest way to check things in object scripts. GC
Now, we can ask the question.
Since this involves interfacing with the player, we again will need to use an IF receiver:
Code:
!!IF&y2=0:Q1/6/0/21/134/33/0/2^You notice a small stand set up near the star axis. A faerie dragon
calls out to you, "Have fun with the nature of magic! Only 100 gold will advance the magic counter five
times as much as it normally would when visiting the axis!"^;
As you see, I added the condition y2=0 here. If the AI visits the site, it will NOT ask the question!
Anyway, there are a LOT of numbers in this command, aren't there? There are eight of them. I am going to break this down into several parts. If you have the ERM script editor open, go to the !!IF command, and click on options and scroll down to Q#1/#2/#3/#4/#5/#6/#7/#8^Text^ to see similar information.
First is the option, Q. This stands for Question. Next is the number 1. This is the flag that will hold your answer. Flags are like variables, but they can only hold two values: 0 (false) and 1 (true). Unlike variables, there is no letter to indicate a variable type. For instance, v-variable 1 is written as "v1", z-variable 1 is "z1", flag 1, however, is just 1. I'll come back to this when we use the flag later.
The next six numbers add pictures to the dialogue, under the text that is written. Each pair of numbers refers to a single picture. The first one is the object TYPE, and the second is the object SUBTYPE. What each type and subtype is can be found by going to Type and subtype of Pictures using the IF:Q command.
In this case we have the first image listed as 6/0. Type 6 is a resource- specifically gold. The subtype for a resource is the amount you want displayed underneath. Since I made it subtype 0, there is no amount displayed- just the picture of the gold resource.
The second image is 21/134. Type 21 is a monster picture. The subtype is the type of monster. If you click on the link in the help file, you will be given a list of them. In this case, subtype 134 is a faerie dragon.
The third image is 33/0. Type 33 is for a primary statistic, in this case spell power. Again, the subtype is the amount, and by using 0, no amount is shown. So, when this script runs, under the text will be the images of gold, a faerie dragon, and the spell-power icon.
The final number, 2, says that we want a yes/no question asked. When run, below the pictures will the the familiar accept and cancel buttons. If you select accept, the flag is set to true (1), if you select cancel, the flag is set to 0.
Now, we need to check to see if the player has the 100 gold to spend! Again, we do this with the OW receiver. So, we code the next line:
Code:
!!OW:R-1/6/?y3; [find out how much gold the current player has]
The R option means that we want to do something with a player's resources. The first number is the player color that we want to check. This value is 0 for red, 1 for blue, and so on. Check the format E1 for all the colors, but basically they are numbered 0 through 7, and go in the order they are listed in the game. For this script, however, I have the player color set as -1. This means that we want to check the currently active color, whoever it is. We already checked the active player's color above (it is stored in y1, remember), but I chose to use this to illustrate a possibility. You need to check the syntax for each option to see if -1 can be used for the current player. It sometimes has other uses. For instance, -1 sometimes refers to the neutral (unowned) color.
The 6 is the resource we want to check, in this case gold. The final number is what we want to set the gold to. In this case, we are using the variable y3, and as before the use of a ? means we are reading in the amount, rather than setting it.
Next, we check to see what the player's answer was, and if he could afford the price. We will display an appropriate response for each case. This needs 3 IF commands- one for a no answer, one for yes and the player can afford it, and one for yes and the player cannot afford it.:
Code:
!!IF&y2=0/-1:M^Disappointed, the dragon turns to another potential customer.^;
!!IF&y2=0/1/y3>=100:M^"Very good! I knew you'd want to do it!"^;
!!IF&y2=0/1/y3<100:M^Disappointed, the dragon turns to another potential customer.^;
Here, the condition that it is a human player is is in all three. The second condition checks the flag- flag number 1- which we set based on the player's answer. In the first line, the flag number is negative. That means that we want the the flag to be FALSE for the condition to be met. In the other lines, the flag is positive, meaning we need the flag to be TRUE. In the third line, we have an additional check- do you have enough cash?
Before we actually deduct the 100 gold from the player's treasury, we need to decide what the AI will do. Let us make the AI flip a coin- a 50% chance that it will spend the money. We do this with two commands:
Code:
!!VRy4:S0 R1; [coin flip]
!!IF&y2=1:V1/y4; [set the flag to the flip]
You will recognize the first line, but with a new option that we haven't used before- the R option. The R option generates a random number between 0 and the value after R (in this case 1), and adds that to the previous value. So, this VR receiver sets y4 to 0, and then adds either 0 or 1 to it. Effectively, this is the coin flip that we wanted.
The next line is our old friend, IF again. This time, the condition is that it IS an AI's turn. The V option is used to set a flag's value. In this case, flag 1 is set to the result of the coin flip.
Now that we are done with the decisions, we code in the deduction, using the OW command from above.
Code:
!!OW&1/y3>=100:R-1/6/d-100; [deduct 100 gold, if appropriate]
The two conditions here should be clear, but just to recap, the first condition is for the flag to be set- either by the coin toss for the AI, or by the player saying "yes." The second condition is that the player has enough gold. As with the spell power commands from before, we use the d operator to subtract 100 from the current value of the gold amount (well, technically we are adding -100).
We only need to do one more thing, and that is note that the payment was made. Since we haven't used variable v2 yet, I will do that here:
Code:
!!VRv2:S0; [initialize v2 to 0]
!!VRv2&1/y3>=100:+4; [set v2 to 4 if payment was made]
Note that although the player's gold has changed, y3 still has the amount from before the payment. Thus, the same check that we had in the OW command will work here. This part of the code is now done. However, we need to modify the part of the code we already wrote, since we need to make the counter jump, and still give the proper message.
Recall the following lines from the start of the script:
Code:
!!VRv1:+1; [add 1 to v1]
!!VRy1:Sv1%10; [is v1 a multiple of 10?]
In this part of the script, y1 is the units digit of the counter. Which message displayed depends on whether or not y1 is 0. First, we modify the first line to read:
Code:
!!VRv1:+1+v2; [add 1+v2 to v1]
If payment was made, then this will add 5 to v1, otherwise it will only add 1.
Next, we add a line after the y1 calculation:
Note: the line that was added is only partially complete in QQD's original post (probably a fault of forumplanets), and it doesn't appear in the full code listing below. I therefore omit it here. GC.
If the addition of 5 caused v1 to skip over a multiple of 10, then it means that v2 was 4, and so y1 is between 1 and 4. So, if y1 is less than or equal to v2, it means that the magic status should flip- so we set y1 to 0. The rest of the code can stay as it is!
So now, after a slight change to the text messages, are entire script now reads:
Code:
ZVSE
!#VRv1:S0; [set variable v1 to 0]
** post-visit trigger
!$OB2/2/0; [AFTER object at (2,2,0) is visited]
!!VRv1:+1+v2; [add 1+v2 to v1]
!!VRy1:Sv1%10; [is v1 a multiple of 10?]
!!VRy1&y1<>0:M^Welcome to the star axis. The magic counter is now %V1^; [show message if nothing else happens]
!!VRy2:Sv1:10%3; [find magic change type]
!!VRz-1&y2=0:S^return to normal.^; [for visit 30, 60, 90, ...]
!!VRz-1&y2=1:S^strengthen.^; [for visit 10, 40, 70,...]
!!VRz-1&y2=2:S^weaken.^; [for visit 20, 50, 80, ...]
!!IF&y1=0:M^The magic counter is now %V1 you feel the world's magic power %Z-1.^; [show change message]
** in-battle effects routine starts here
!?BA0;
!!BA:E?y1; [is this a network battle?]
!!FU1&y1=0:Pv1; [if not, continue the script]
** start of pre-battle
!?FU1;
!!BA:H0/?v5; [get attacking hero's hero number]
!!BA:H1/?v6; [get defending hero's hero number]
!!VRx1::10%3; [get magic change type]
!!HEv5:F?y5/?y6/?y3/?y7; [get attacker's stats]
!!HEv6&v6>0:F?y5/?y6/?y4/?y7; [get defender's stats]
!!VRv3&x1=1:Sy3; [if magic strengthened, spell power increases]
!!VRv3&x1=2:S1-y3; [if magic is weakened, spell power reduces to 1]
!!VRv4&x1=1/v6>=0:Sy4; [if magic strengthened, spell power increases]
!!VRv4&x1=2/v6>=0:S1-y4; [if magic is weakened, spell power reduces to 1]
!!HEv5&x1??0:Fd0/d0/dv3/d0; [modify spell power]
!!HEv6&x1??0/v6>=0:Fd0/d0/dv4/d0; [same for defender]
** post-battle starts here
!?BA1;
!!BA:E?y1; [network battle?]
!!FU2&y1=0:Pv1; [if not, undo changes]
!?FU2;
!!VRx1::10%3; [get change type]
!!VRv3:*-1; [negate attacker's changed stat]
!!VRv4:*-1; [negate defender's changed stat]
!!HEv5&x1gt;0:Fd0/d0/dv3/d0; [restore attacker's power]
!!HEv6&x1gt;0/v6>=0:Fd0/d0/dv4/d0; [restore defender's power]
** pre-visit trigger
!?OB2/2/0; [When object at (2,2,0) is visited]
!!OW:C?y1; [get current player color]
!!OW:Iy1/?y2; [is current player an AI?]
!!IF&y2=0:Q1/6/0/21/134/33/0/2^You notice a small stand set up near the star axis. A faerie dragon calls
out to you, "Have fun with the nature of magic! Only 100 gold will advance the magic counter five
times as much as it normally would when visiting the axis!"^;
!!OW:R-1/6/?y3; [find out how much gold the current player has]
!!IF&y2=0/-1:M^Disappointed, the dragon turns to another potential customer.^;
!!IF&y2=0/1/y3>=100:M^"Very good! I knew you'd want to do it!"^;
!!IF&y2=0/1/y3gt;=100:R-1/6/d-100; [deduct 100 gold, if appropriate]
!!VRv2:S0; [initialize v2 to 0]
!!VRv2&1/y3>=100:+4; [set v2 to 4 if payment was made]
Lesson 4: Variables!
I have introduced a lot of commands in the last script. If you were looking in the script editor's help file, you almost certainly noticed that many of the commands have many more options than I have introduced. I am therefore going to elaborate on some of the commands in more detail.
Please note that I wil be following along with the help file within the editor, and so if a command is documented well enough in there, then I will only mention what an option does, but not go into the details.
Going in order through the script, the first command seen is VR.
In the help file, you will see the syntax at the first line:
!!VR@:XXXX
Any place you see an @ in the help is a place for a variable name- specifically the one that the command is working with. XXXX always indicates that there are options that can be used with the command. If you click on Options, you will get a list of them.
Most of the variables are well explained here, but I will elaborate on a few:
c stores the current day- it does not store month/week/day. Thus, the 4th day of month 2 week 3 is stored as 46, as it is the 46th day of the game. If you need the month or week of the map, you can find them this way (and store in v1):
Code:
Month: !!VRv1:Sc+27:28;
Week: !!VRv1:Sc+6:7;
Week of the month: !!VRv1:Sc+6:7%4+1;
Day of the week: !!VRv1:Sc%7+1;
d is used to modify a value. You can add or subtract a number, but you can only ADD a variable. So, if you wanted to subtract variable v1, you would first need to negate it, in a separate instruction. In most cases, it is best to use another, temporary variable to hold the negation, so you do not change what you are holding onto. If you keep good records of your permanent variables when scripting, then do whatever you are more comfortable with.
e variables are the only ones that can hold a floating point value. In most cases, you won't need to use one, as the numeric range of the variables is very large, and so you can multiply by a fraction simply by multiplying by the numerator, and then dividing by the denominator. Only if you are going to use very large numbers in a fraction will you need these. When displayed in a message, an e-variable only gives the first three decimal places, but the stored precision is much more.
w variables are actually 155 variables each- one for each hero in the game. Thus, variable w1 holds 155 values- one for each hero. w2 holds 155 values, and so on. You must use the IF:W command to tell ERM which of the 155 values you want.
Not listed in the help file are the ERT z-variables. These are special variables that take in text from a supplementary file. They were introduced to make regionalization of scripts easier. In general, you should not need to worry about them, and this is all I will say on them, as it doesn't apply to basic scripting.
Options for VR:
In the options, if you see a $, it means that you can either set the value (by putting a number or variable in the position) or you can read in the value to a variable by prefixing the variable name with a ?.
If you see ?$, then you can only read in the variable.
If you see #, then you can only set a value. Most of the time common sense will tell you what is allowed. For example, !!VRv1:+?v2; makes no sense- you can't add a number that will be stored; the number must already be available to be added.
Going through the list, we have:
C$1/$2/.../$16
This allows you to read in and/or set multiple values in one statement. Up to 16 consecutive v-variables can be worked with. Thus, if you have 6 numbers in the list, and the VR command is operating on variable 57, then this will set or read variables 57 through 62.
Rx
This generates a random integer between 0 and x, and ADDS it to the variable in the VR command. Note that in the help file, this should read R#, as you can use any stored value for the limit or the random number.
If you want to generate a number between 1 and 10, you would code it as !!VRv1:S1 R9; This sets v1 to 1, and adds a number between 0 and 9 to it.
S#
This sets the variable to the number given.
T$
This is another random number routine. Again, it should read T#, as it makes no sense to set a random number- it isn't random then, is it? There is an advantage and a disadvantage to using T instead of R. The T option is a time-based generator. This makes the numbers more random than the R option, which isn't. However, if you need to generate multiple random numbers without any delay (such as showing a message), then it is likely that the system clock of your computer will not have advanced enough to give a truely random number. You may even get the same number multiple times. Thus,
Code:
!!VRv1:S3 T5 T5 T5;
will not generate a number between 3 and 18 (simulating a roll of three dice), but rather give a random number from the choice of 3,6,9,12,15,18. If you need any number between 3 and 18 (with the adjusted chances that are implied by having several "dices" -GC), then
Code:
!!VRv1:S3 R5 R5 R5;
is the better choice.
Logical operators:
These are actually used anywhere you want to use a conditional expression, but since they are explained here in the help and are very useful to know in general, I will list them here. They are explained quite well in the help file.
Use & to indicate a logical AND in your conditions
Use | to indicate a logical OR
Use X to indicate a logical XOR (exclusive or)
Use / to indicate the same operator as previously used.
You must have all AND conditions first, and ll OR conditions next. Note that if you have both, All the ANDs are counted together first, and then the ORs, so if at least one OR is true, the whole statement is true. This is because ERM evaluates expressions left-to-right. This also makes multiple XORs very hard, if at all possible, to code.
Arithmetic operators
These were covered above, but in summary,
+ is addition
- is subtraction
* is multiplication
: is division
% is modulus
Again, all math is done left-to-right. Thus,
Code:
!!VRv1:S0+5+6*3+2;
gives v1 the value of 35 (5+6=11; 11*3=33; 33+2=35) and not 25, as algebraic order would say (6*3=18; 5+18+2=25)
String operators
H#
Set flag # to true if the z-variable is empty, and false if not.
S^TEXT^
Set the z-variable to the text between the carats. Remember that ^ and ; cannot be used in the text.
Within the text string, you can show the contents of a variable by using a % followed by the variable name, using a capitol letter instead of a lower-case one. For flags, which have no letter normally, use an F. For common variables that have no numbers, prefix them with a V. Although not listed in the help file, %Z can be used for z-variables. To display a percent-sign, use %%.
+
When working with strings, + is used to concatenate two strings. Either string may be a z-variable or text (within carats).
Questions and Answers
Question: I'm not sure what you mean when you're talking about the H# command. You're talking about flags and variables in the same statement?
Answer: There is a very nicely described example of the H option in the help file, but I will give a simple example here.
Code:
!!VRz1:H1;
This takes a look at (text) variable z1. If it is a null string (say you set it with !!VRz1:S^^;), then flag number 1 is set to false (0). If there are only spaces, tabs, new lines, etc. in z1, flag 1 wil also be 0. If there is actual text in z1, then flag 1 will be set to 1.
Copying from the help file:
Code:
!!VRz100:S^Hello!^;
!!VRz101:S^^;
!!VRz102:S^ ^;
!!VRz100:H300; flag300=1
!!VRz101:H301; flag301=0
!!VRz102:H302; flag302=0
Note that anything after the ; in any given line is a comment.
Lesson 5: Objects
One of the things that most people want to do is to create or change a map site. This is because sometimes there is something you want to do on a map, but there is no way to do it. Take the script from earlier in this thread. There is no map site that lets you alter the global effect of spell power, so we had to create one.
In this lesson, I am going to start with the OB commands.
First, the trigger:
As with all triggers, the command begins with !?. Since map objects often have hard-coded effects, such as the star axis, there are two forms of the trigger.
!?OB is a trigger for a script that will run before the normal effect of the map object.
!$OB is a trigger for a script that will run after the normal effect of the map object.
If you use an object which has no hard-coded effect, then either form will work. However, consider that other scripts may use the site also, and so all pre-visit scripts will run before any post-visit scripts.
Both the pre-visit and post-visit triggers work the same, so I will only explain the pre-visit trigger's format. The only difference in post-visit is using !$ instead of !?
You can have up to three numbers follow the trigger, each form has a different meaning:
With one number, all objects of the same type as the number will cause the script to run. For example:
Code:
!?OB17;
Will trigger any time a creature dwelling (type 17) is visited. For a list of map objects, look at the Format OB list.
With two numbers, all objects of the same type as the first number, and the same subtype of the second number will cause the script to run. On the OB format page, anything which has subtypes has a link to the appropriate list. Example:
Code:
!?OB17/81;
Will trigger whenever a Diamond Dragon dwelling (type 17, subtype 81) is visited.
With three numbers, only the object at the (x,y,level) location will trigger the code. Example:
Code:
!?OB2/2/0;
Will trigger only when the object at (2,2) on the surface layer is visited. Note that in this last case, the location must be seen in the map editor as a yellow square when the passability feature is turned on. (Note: it's also possible to create a trigger square through ERM, but this is something for later. GC)
---------------
The OB receiver has a different use. It is used to check or modify the attributes of an existing object. The general form for this command is:
Code:
!!OB#1/#2/#3:XXXX;
The three numbers indicate the location (x,y,level) of the object. Note that some objects have more than one yellow square, so if you are working with one of those, you need to duplicate your instructions for each such place. Of course, you could make an object with two yellow squares do different things at each. (say an "entrance" and an "exit" space). As always, XXXX indicates that there are options that can be used with this command.
Finally, before I describe the options, note that some map objects have special receivers, and have additional options that are not part of the general OB formats.
Check the list of Miscellaneous object receivers to see if there are extra functions available for the object you are scripting. In general, these are objects that give resources, artifacts, or secondary skills. They have commands to let you specify more exactly what you want. There are 23 of these special object receivers. Note that these are only extra receivers. For a trigger, the OB trigger is always sufficient, regardless of the object type.
Now, the general !!OB options. Note that I skip the C option, as I am uncertain of its function.:
B
This removes a description hint for the object. If the objects has a default hint text, this option will restore it to this message. Thus, if you make an object revert to its normal function, you can restore the hint text without manually replacing it.
D#
This prevents a particular player from using this object. You may find this more convenient than hiding something behind a border guard.
E#
This allows a particular player to use the object. Note that by combining D and E commands, you can create your own style of quests, which may not be available for a seer's hut. Simply prevent a player from using an object (with D), and then when certain conditions are met, you can re-enable it (with E). This will also allow you to have multiple players able to complete the same quest.
H$
Read or set the hint text for an object to/from a z-variable. Remember that you do not need to store the default text- the B option lets you restore that.
M$1/$2/$3
This command lets you automatically force an answer of "no" to a yes/no type question. As the help file indicates, this command is still in testing, so you can check there if you want the full details. In general, if you want to force a particular action at a site that normally has a question, it would be best to disable the object, and code in what you want to happen in an OB trigger command.
R and S
These are, respectively, enable and disable commands which apply to all players. This way you don't have to use eight D or E commands to completely turn an object on or off.
T$
This is to get or set the type of object visited. For example, if you had a diamond dragon dwelling at (4,5,1), then:
Code:
!!OB4/5/1:T?y1;
would set variable y1 to 17.
Code:
!!OB4/5/1:T2;
Would leave the graphics the same, but change the dwelling into an Altar of Sacrifice (object type 2)
U$
This sets the subtype of the object. Thus, if we left the type as 17, and gave the command:
Code:
!!OB4/5/1:U?24;
Would change it into a green-dragon dwelling. Again, it leaves the graphic as it was.
Lesson 6: Heroes
The next thing that most people want to do, is to be able to manipulate the attributes of a hero. This can be to add new skills- or remove them! Make them faster, change their specialty skills, and so on. Most of these changes are gathered together in the extremely powerful !!HE receiver. I only used a small fraction of this command's ability in the sample script above.
There are three ways to identify a hero with this receiver. You can identify a hero by location, by hero number or by a trigger.
To identify a hero by location, you can use the standard three-number method, as we have used before:
Code:
!!HE4/7/0:XXXX
This says to do XXXX to the hero located at (4,7) on the surface.
To address a hero directly, you use just the hero number:
Code:
!!HE5:XXXX
will apply the options (remember that XXXX is a placeholder!) to hero number 5 (Sorsha)
You can find all the hero numbers by checking Format H- there is a link on the !!HE receiver help page.
If a hero has triggered some code, then you can identify him or her by using the direct format, with the hero number being -1. This is most useful if you want to make multiple sites do something, or if you want to have an artifact do something when equipped or removed- so you cannot tell where a hero wil be when a script is activated.
Now for the options, and there are a lot of them!
There are four options dealing with artifacts.
A#
This is used to give or take an artifact from a hero. To take an artifact, make it negative. Check format list A1 for the artifact numbers. For example,
Code:
!!HE5:A26;
Will give Sorsha a rib cage (artifact #26)
Code:
!!HE5:A-7;
Will remove any Centaur's Axes (artifact #7) from her backpack and from her hand, if equipped. Any artifact that is given this way will be placed in the hero's pack.
A1/$1/$2;
This command equips an artifact on the hero. $1 is the artifact number, and $2 is the location to be equipped. Format AP has the list of positions.
If we wanted Sorsha to equip that rib cage we just gave her, we would code:
Code:
!!HE5:A1/26/5;
Equipment position #5 is the torso, the place that the rib cage should be placed. If there is already an artifact equipped there, then flag number 1 will be set to 0, otherwise it will be set to 1. You may want to have a script do something special if an artifact is already equipped where you want to place another. This also helps for equipping a miscellaneous artifact, as there are five places it can go, and some may be used. You may want to check if a slot is open first by coding:
Code:
!!HE5:A1/?y1/5;
y1 will have the number of the artifact on the torso.
A2/$1/$2/$3;
This checks to see if an artifact is owned or equipped. the first number is the artifact number, the second number is the quantity of that artifact owned, and the third is the number equipped. These numbers cannot be set- if you try, ERM will ignore you.
An example from my Cards of Prophecy script:
Code:
!!HEv1300:A2/47/0/?v1301; [Attacker has Cards of Prophecy equipped?]
This checks to see if the hero, whose number is stored in variable v1300, has any Cards (artifact 47) equipped, with the result placed in v1301. It turns out that this command runs in a battle, so my comment reflects this- the attacking hero number was stored in v1300. The 0 for the quantity owned is purely a place-holder. As I said, you cannot set this number.
A3/$1/$2/$3
This command is to remove some (but not necessarily all) copies of an artifact. Again, the first number is the artifact number. The second number says how many of these to remove, and the third number is a flag. If the flag is 1, then an equipped artifact will be removed before ones in the packpack. If it is 0, then ones in the packback go first.
B0/$
This is to get or change the name of a hero. For example,
Code:
!!VRz1:S^Sara^; [store text]
!!HE5:B0/z1; [set new name]
Will change Sorsha's name to Sara for the remainder of the map (or, of course, until changed again). This is useful if you wanta story map, but allow the player to choose a starting hero- at the start of the map, you change the name of the hero at the place this one starts, and change his/her name.
B1/$
This command will change the biography of a hero. Maybe after a major battle, you want to acknowledge this in the hero's bio. For example:
Code:
!!HE5:B1/?z1; [store old bio]
!!VRz2:S^ She has conquered the Lich King's armies.^; [store text]
!!VRz1:+z2; [add text to old bio]
!!HE5:B1/z1; [set new bio]
I think the comments explain this well enough.
Next are a set of monster commands. After all, a hero will usually be accompanied by one to seven monster stacks- it would be nice to be able to work with them. There are four such options.
C0/#1/$2/$3
This will take the monster stack (or lack thereof) in the hero's army slot numbered #1 and set or check the type ($2) and quantity ($3) of those creatures.
The hero's army slots are numbered 0 though 6. Let's say we want to change all the creatures in the current hero's first army slot into peasants. Yes, this is a nasty thing to do in general, but why not? We code this as:
Code:
!!HE-1:C0/0/139/d;
Recall that for hero numbers, -1 means the hero that triggered whatever is happening. the 0 refers to the first slot. 139 is the monster number for a peasant. The d in the last position is a placeholder, leaving it alone- since we do not wish to change the quantity. Remember that the value d is used to add whatever number follows the d to the number in that position. Since there is no number after the d, no change is made. d0 would have had the same (lack of) effect.
C1/#1/$2/$3
This works similar to C0, but instead of looking at creatures in slot #1, is changes all creatures of type #1 to type $2. So,
Code:
!!HE-1:C1/132/139/d;
Will change all of a hero's azure dragons (type 132) into peasants. (This is not an action a map designer should take lightly, as you may find nobody will play your maps anymore! :-)
C2/#1/#2/#3
This gives a stack of monsters of type #1 and quantitiy #2 to the hero. #3 is an instruction for what to do if there are no open army slots. If #3 is 1, then the player will get the "make room for these creatures" dialogue. If it is 2, then the AI will make the choice automatically. Most of the time, you will want to check if the hero is owned by a human or the AI, and set the flag accordingly.
C#1/#2/.../#14
This is similar to C2, but gives up to 7 extra stacks of monsters. You must supply all 14 parameters. The odd numbered positions are the creature types, and the even numbered positions are the quantities. Use -1 to indicate no creature (so you can give less than 7 stacks.
For instance, if you want to offer one of each of the Armageddon's Blade dragons to Fafnir (hero 37), you would code:
Code:
!!HE37:C132/1/133/1/134/1/135/1/-1/0/-1/0/-1/0;
For all remaining examples, I will be using hero -1 (current hero), if it is allowed.
D
This calls an upgrade dialogue- similar to the one you get at a hill fort.
E$
E$1/$2
These are used to check or modify a hero's experience. If you have two numbers, the first number is for experience total, the second is for the hero level. Do NOT set both of them. I strongly suggest that you only use the one-number version if you are changing a hero's experience total, and use the two-number form to check the hero's level. In the two-number form, you can also add a /1 to the end, which will prevent the game from redrawing the screen. In some cases, this may prevent graphical artifacts from appearing on the screen when the script runs. Several other options also have a no-redraw command. Check the help file for which ones do.
Thus, to give 1000 experience, you would code:
Code:
!!HE-1:Ed1000;
To increase the hero's level by 2:
Code:
!!HE-1:E?y1/d2;
F$1/$2/$3/$4
This command gets or changes the hero's attack ($1), defense ($2), spell power ($3), and knowledge ($4). If you are checking the statistics only, then you can use the /1 option at the end. This will give you the hero's base statistics, rather than their values after artifacts are included. You may recall this one being used in our spell-power script.
H$1/$2/$3/$4
This lets you set the monsters for new heroes in the hero pool, when they appear in the tavern. This sets the monsters in slot $1 to type $2, with a range of $3 through $4. You can only set the first three slots (0,1,2) for these heroes. Also, the game randomly decides if there will be 2 or 3 monster stacks for new heroes, so you can force a hero to have 2 monster stacks by setting slot 2 to creature type -1, but you cannot force a hero to get three creature stacks. You can, of course, set slot 1 to -1 also to force only one stack.
Also note that any heroes that are currently available in any player's taverns will not have his or her armies modified until the next week.
Also, note that the examples in the help file may be missing the colons in the syntax (it may be fixed in an update I haven't installed yet). Otherwise they are correct.
For example, to have Orrin start with only one creature in slot 1, you would code:
Code:
!!HE0:H0/?y1/1/1;
I read in the creature type, so it is not altered.
I$
I$/1
Similar to the F option, this options lets you change the spell point total. Note that it is possible to give a hero negative spell points with this command. It won't cause a problem, but it can be confusing to the player to see spell points listed as -6/30 or something similar. Obviously, you cannot cast spells if you have less than 0 spell points.
K
This command kills the hero, immediately. I don't think further explanation is needed here.
L#^path\filename.pcx^
This lets you change the portraits of the hero. If # is 1, then you are setting the small portrait- such as the one in the hero list. If the # is 2, you are setting the large portrait- like the one in the hero screen. Inside the carats is the location of the pcx file, relative to the DATA directory in the heroes3 folder.
The total length of the path+filename can only be 12 characters, so it is best to have these files in the data directory, rather than elsewhere. For instance, if you have the pictures in the maps directory, the filename would have to start with "..\maps\" this already uses eight of your 12 characters.
L3
This restores the portraits to the defaults.
L#/$
If # is 0, the portrait of the hero is set to portrait number $; IF # is 4, both the large and small portraits are set.
I am uncertain of the use for the L5 option, and of the indexing in L0 and L4 (although I believe portrait number $ is the portrait of hero number $)
M#1/$2
This checks or sets a spell inside a hero's spellbook. #1 is the spell- format SP lists all the spell codes, and $2 is a flag. If the flag is 0, the spell is not in the book (or will be removed if you set it). If the flag is 1, then the spell is in the book (or will be added). You should check to see that a hero has a spellbook equipped first- easily done with the following:
Code:
!!HE-1:A2/0/0/?y1;
This checks to see if a spellbook (artifact 0) is equipped. y1 will be 1 if there is a spellbook, and it will be 0 if not.
N?$
This gets the hero number for the hero. This is good if you want a site to work differently for different heroes. You can use the hero-location, or triggering hero form of the !!HE receiver for the script, and get the hero number with this option.
O$
This sets or checks the owner of a hero. -1 indicates no owner, and 0 through 7 indicates the various colors. You can use this command to have a script only effect certain players, or even to cause heroes to change allegence. You can even add a new player into the game by setting to an unused color!
P$1/$2/$3
This command moves the hero to location ($1,$2,$3). You can use this to teleport a hero without a lith, or to bring a hero out of the hero pool, directly onto the map. Of course, moving an unowned hero onto the map should be followed by an HE:O command, to give ownership of the hero to one of the players.
If you want a teleport sound when moving a hero, then you can add an additional /$ to the end of the option. if $ is not 0, you will get a sound. According to the help file, you cannot use this option with the active player's hero. I have not tested this, so cannot confirm or deny this.
R#/$
This sets or checks various small parameters for a hero. If # is 0, then you are setting or checking the hero's morale. This is, of course, only guaranteed to be accurate until a battle. If # is 1, you are setting or checking luck. If # is 2, you are checking the hero gender (male is 0, female 1. Settings it to something other than these would most likely result in a crash. GC). Some dialogues will sound better if you check this first, and modify the text to get pronouns correct. If # is 4, then you are checking the tactics control of the hero. -1 indicates it is enabled, 0 indicates disabled.
R3/$1/$2
This sets the availability of a hero to be hired. If $1 is 1, the hero can be hired. If it is 0, then the hero cannot. If $2 is left out, this is for all players. If $2 is present, it is checking for individual players. This uses the bit-notation value, so red=1, blue=2, tan=4, green=8, and so on. Add the numbers for all the colors you want to set.
Disabling an active hero will kill it.
S#1/$2
This option is used to set or check what secondary skills a hero has. The first number is the skill number (format SS lists them), and the second number is the skill level, with 0 being no skill, 1 being basic, 2 being advanced, and 3 being expert.
If a hero is given more than 8 secondary skills, s/he will still gain the benefits of all of them, but only the first 8 will be seen on the hero screen. For example, in my Cards script, if knowledge is changed, I need to adjust the spell points as well. To do this, I need to check if the hero has the intelligence skill (skill 24), so I used this line:
Code:
!!HEx1:S24/?y9;
Here, x1 is the first parameter passed into a function- my script sends the hero number for the effected hero this way.
T$1/$2/$3/$4/$5
This forces a hero into a battle against monsters of type $4, and quantity $5. The battle will take place on the terrain of the type found at location ($1,$2,$3) on the map. The hero will not move to that place- the location is only to get things such as native terrain bonuses, and the background picture.
U$1/$2/$3
This command will check or alter the patrol area for an AI hero. Although the patrol cannot be moved to another level, the x and y location for the center of the patrol can be set to ($1,$2), with a radius of $3. A patrol radius of -1 frees the hero from patrolling.
V#1/$2
V#1/#2/$3
This is used to set or check if a map site has been visited. This is specifically for 10 objects- they are all listed in the scripter help file. For both forms, the first number is the type of map site.
In the first form, the second number is the bit-value of all 32 sites. (you cannot have more than 32 of certain objects on the map). Thus, 1=the first site, 2= the second, 4=the third, and so on, up to 2,147,483,648 for the 32nd site. Add the numbers to set all of them- if the site has been visited, add in its value, if not skip it. Obviously, if you only have a few sites on the map, you don't need to worry about the high-powers of 2 that appear. Use the calculator that comes with Windows to type the number in binary, and convert to decimal if you don't want to chance making an error by hand.
If you don't want to check or set all of them- and usually you will only be interested in one at a time, then you use the second form. In this form, the second number is a number from 0 through 31- indicating which of the sites you want to set. $3 is a flag value, set to 1 if the hero has visiter the site, and set to 0 if not. By use of this, you can allow heroes to revisit sites that are normally one-time only.
The help file has several good examples, so check them out if you need them.
W$
This lets you check or modify the hero's movement points. 100 movement points is roughly equal to one step horizontally or vertically, on terrain with no penalty or road. Note that if a hero has movement changed, then even if the hero has not moved that day, s/he will be unable to dig for the grail. The double-movement Wogify option used to have this problem.
X
All the X options deal with hero specializations.
X0/$
This sets the hero's specialy to the secondary skill with number $. Not all secondary skills make sense for a specialty- but of course you could always write a script that does make, say, a wisdom specialist have meaning.
X1/$
This makes the hero a creature master, of creature type $, and if the creature is upgradable, also the upgrade. This involves giving all creatures of that type +1 speed, and an attack and defense bonus proportional to the hero level divided by the creature level. (always at least 1 bonus point to each)
X2/$
This makes the hero generate resource of type $ daily.
X3/$
This makes the hero specialty spell number $. Again, not all spells make sense- for instance what does a specialization in dispel do?
X4$1/$2/$3/$4
This gives the hero a creature specialty in creature type $1, giving a flat bonus of $2 attack, $3 defense, and $4 damage. Again, if the creature has an upgrade, it will gain the bonus also.
X5/2
This is to set the specialty to Sir Mullich's specialty (+2 creature speed to all creatures).
X6/$1/$2/$3
This allows the hero to upgrade creatures of types $1 and $2 (and possibly their upgrades, if any) to type $3. Cost will be the difference in purchase price between the base and upgraded forms.
X7/$1/$2
This makes the hero's specialty a flat attack ($1) and defense ($2) bonus to all dragons.
X8/1
This causes the hero to spread a shroud of darkness wherever s/he travels.
X8/2
This allows the hero to rebuild towns that have been destroyed as any town type (rather than just the old type or the hero's type)
Y$1/$2/$3/$4
This sets or changes a blessing or curse that has been placed on the hero. The blessing or curse type is type $1- and there is a list of them in the scripter help. The link is in the HE:Y description. $2 is the power of the curse or blessing (how severe it is). $4 says what to do with the curse. If $4 is 0, then the blessing or curse is removed. If $4 is 1, then the curse or blessing is to last for $3 days. If $4 is 2, then the duration of the curse or blessing will be extended by the amount $3. A negative value in $3 will reduce the duration of an existing blessing or curse of the same type (if one is present)
Y2/$2/$3/#
Curse type 2 prevents a hero from using a particular artifact slot. $2 is which slot is sealed. If $2 is -1, then a random slot is chosen. $3 is the duration, as above, and # is the set/remove/extend option, as $4 in the other curses.
Lesson 7: Even More Messages!
In this section, I am going to cover the IF command. This command is for maintenance of certain variables, and dialogue boxes.
We have already seen a few of these in use, and in other threads I have explained other uses (don't worry, you won't have to search for them, I am going over all of it here)
As with the other commands I have covered in detail, IF has many options. Please look at the help within the script editor for more information. I will will only be elaborating and clarifying things here. If the help file is clear, then I will only describe things in brief.
Without further delay, here come the options for !!IF:
B#/$1/$2
This command is used to prepare an image or animation for display. You can have up to 100 prepared dialogs, and they can be in BMP, GIF, JPG or AVI formats.
Before using the command, you need to store the filename of the image in a z-variable. The index of this image (for use in other IF commands) goes in the #, and is between 1 and 100. The z-variable is placed at $1. If it is an AVI file, then $2 is a flag (1=yes, 0=no) to determine if the video should loop.
Note that this command DOES NOT show the graphic you have selected. It only prepares the graphic for later use.
D#/$1...$15
The D command is to set up (again, as with B, this does not display the dialog- it only sets it up) a dialog with a multiple-choice question. The choices to be listed are with checkboxes.
The #, again, is the index of the dialog that is being prepared (from 1 to 100). Check the help file for what all 15 parameters are- they are listed right there, and are easy to read.
Note that unlike the command for hero images (see my description of the HE command), you can have a full 256-character filename for any images used here. There is no minimum size for images, but they must be SMALLER than 100x100.
As another note, which I will reemphasize here, prepared dialogs are NOT save in a saved game file. Be certain to code in any setups immediately before you use them. Since z-variables ARE saved, you only need to store the filenames once.
E$1/$2
This command is to activate a dialog set up by IF:D
$1 is a v-variable to hold the choice made in the dialog, and $2 is the identifier of the dialog. variable z1 will always hold the text response- so do not use z1 in the setup. Of course, you should use higher-numbered z-variables anyway (check the used variable list to avoid conflicts)
As an example for the setup and use of a dialog, let's say you have images of a pile of gold (gold.bmp), a dragon (dragon.bmp) and a vampire (vamp.bmp)- all in the MAPS directory. You want to ask the player which (if any) of these things he likes- perhaps to modify later aspects of the map based on his preferences.
Then, we would code:
Code:
!!VRz104:S^gold.bmp^;
!!VRz105:S^dragon.bmp^;
!!VRz106:S^vamp.bmp^;
!!VRz101:S^What do you like?^;
!!VRz102:S^Choose wisely^;
!!VRz103:S^Who are you?^;
!!VRz108:S^gold^;
!!VRz109:S^dragons^;
!!VRz110:S^vampires^;
!!VRz112:S^Do you like gold?^;
!!VRz113:S^Do you like dragons?^;
!!VRz114:S^Do you like vampires?^;
!!IF:D1/z101/z102/z103/z104/z105/z106//z108/z109/z110//z112/z113/z114/;
Note that parameters 7, 11, and 15 have been skipped- this is because there are only 3 choices, and we do not want a fourth to appear.
to set up the dialog, and
Code:
!!IF:E5/1;
to save the choice made in IF:D to variable v5.
When run, a message box will appear with "What do you like?" in the title area. Under that will be the three pictures, evenly spaced. Below that will be two columns- the left will have the header "Who are you?", with a text-entry box underneath. The right column will have the header "choose wisely", with the three questions underneath. When you move the mouse pointer over an image, the description will appear in the bottom of the dialog box. When you click on a right-menu option, a checkmark will appear next to it (and disappear from the other options)
Variable v5 will have the value of -1, 1, 2, or 3. -1 will be if no choice is made when the dialog is closed. 1, 2, or 3 corresponds to the first, second, or third choices. Variable z1 will have whatever was typed in the "who are you" question box.
What you do with this information is up to you. Perhaps change the name of the player's main hero to what was typed in. Maybe give a reward of gold, dragons, or vampires later on for doing something.
F$1/../$6
Use this to add hint-text for the options in the right menu of a dialog displayed with the E command. $1 is the dialog, $2..$5 is the hint text for the four options, and $6 lets you deactivate the "cancel" button in the dialog.
G#1/../#16
Use this command to give a list of options (up to 12) You have a choice of either using a radio-button list (so only one option can be selected), or a checklist (so you can choose multiple answers).
#1 chooses the type of list. #2 is the v-variable number that will hold the result. Since there is a chance for multiple choices, this is a bit-added number. Choice 1 is valued at 1, choice 2 is 2, choice 3 is 4, and so on up to choice 12 being 2048. #3 is the default choices, set the same way. #4 is the z-variable with the window header. #5 through 16 are the indices for the z-variables containing the text for the choices.
You may recall seeing this dialog whenever you WoGify a map, with the optional map rules script active- so if you want to know how it looks, just start up a random map and look.
M
We've already used this several times. The M option lets you simply display a message.
P$
The P option displays an image that was set up with an IF:B command earlier.
Q#1/../#8^TEXT^
Again, we have already used this command. It can give a yes/no quesion, and save the result in a flag, from 1 to 10, specified in #1. The last option (which may be #4, #6, or #8) determines the type of dialogue. For just displaying a message, it should be 1. For a message with no buttons, choose 4- this is best used for messages that appear when right-clicking on something, or other similar cases. Most likely, you will use the value of 2- which asks the yes/no question. The middle numbers- 2,4, or 6 of them are the types and subtypes of up to 3 images to display. In the script we wrote above, there were 3 images. If you want fewer, simply remove the options entirely (as opposed to leaving them blank as in the example above).
In one case- the case with 2 pictures, you can also make the last option (#6) have the value 7, which lets the player choose one of the pictures (instead of a yes/no question). This only works with two pictures, since the result is still simply a flag (and so cannot choose from among 3 objects, and is pointless for only 1)
V#1/#2
This says to set flag #1 to the value #2. Remember that IF:V is used for flags, and VR is used for all other variables.
W$
Every hero in the game has 100 variables specifically for him or her. These are the w-variables, w1 through w100. Before you use one of them, however, WoG needs to know WHICH hero's w-variables you are refering to. That is where IF:W comes in. The number $ is the hero number for the hero whose w-variables you want to use. once this is used, w1 through w100 will be for the hero specified, until another IF:W command is used. If you want to refer to the hero that triggered the script, use -1 for the hero number.
X$
This calls up a sphinx riddle, use -1 for a random riddle, or another number to choose a specific one. An exact match to the riddle answer is needed for a correct response to be logged. Flag number 1 will hold the result (right (1) or wrong(0))
If you are looking at the script editor's help, there should be a link titled "Dialogue boxes" Click on it for more graphical examples of most of these interfaces. |
|