ERM for dummies
- Gaidal Cain
- Round Table Hero
- Posts: 6972
- Joined: 26 Nov 2005
- Location: Solna
ERM for dummies
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
- Gaidal Cain
- Round Table Hero
- Posts: 6972
- Joined: 26 Nov 2005
- Location: Solna
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: Select all
ZVSE
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: Select all
!?BA0&v1321=1; [start of battle]
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: Select all
!!BA:E?v1331; [check for multiplayer]
Finally, instructions are just like receivers, except that they run only one time- when the map begins. They always begin with !#
For example:
Code: Select all
!#UN:P34/?v1321; [is script active?]
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: Select all
ZVSE
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: Select all
!#VRv1:S0;
!#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: Select all
!?LE0/0/0;
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: Select all
!!VRv1:+1;
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: Select all
!!IF:M^You are visitor number %V1 to the Northwest corner of the surface!^;
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: Select all
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]
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).
- Gaidal Cain
- Round Table Hero
- Posts: 6972
- Joined: 26 Nov 2005
- Location: Solna
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: Select all
!!VRy1:Sv1%10; [is v1 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: Select all
!!IF&y1<>0:M^You are visitor number %V1 to the Northwest corner of the surface!^; [show message if nothing else happens]
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: Select all
!!VRy2:Sv1:10%3; [find magic change type]
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: Select all
!!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, ...]
Now we need to display the new message:
Code: Select all
!!IF&y1=0:M^You are visiter number %V1, you feel the world's magic power %Z-1.^; [show change message]
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: Select all
** in-battle effects routine starts here
Code: Select all
!?BA0;
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: Select all
!!BA:E?y1; [is this a network battle?]
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: Select all
!!FU1&y1=0:Pv1; [if not, continue the script]
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: Select all
** start of pre-battle
!?FU1;
Code: Select all
!!BA:H0/?v5; [get attacking hero's hero number]
!!BA:H1/?v6; [get defending hero's hero number]
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: Select all
!!VRx1::10%3; [get magic change type]
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: Select all
!!HEv5:F?y5/?y6/?y3/?y7; [get attacker's stats]
!!HEv6&v6>=0:F?y5/?y6/?y4/?y7; [get defender's stats]
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: Select all
!!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]
Now we just need to make the changes:
Code: Select all
!!HEv5&x1>0:Fd0/d0/dv3/d0; [modify spell power]
!!HEv6&x1>0/v6>=0:Fd0/d0/dv4/d0; [same for defender]
We have now finished the before-battle function!
To recap, our script now looks like:
Code: Select all
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&x1>0:Fd0/d0/dv3/d0; [modify spell power]
!!HEv6&x1>0/v6>=0:Fd0/d0/dv4/d0; [same for defender]
Now, after the battle, we need to undo the changes. First, we do a post-battle trigger:
Code: Select all
** post-battle starts here
!?BA1;
!!BA:E?y1; [network battle?]
!!FU2&y1=0:Pv1; [if not, undo changes]
Let's start the clean-up:
Code: Select all
!?FU2;
!!VRx1::10%3; [get change type]
!!VRv3:*-1; [negate attacker's changed stat]
!!VRv4:*-1; [negate defender's changed stat]
Code: Select all
!!HEv5&x1>0:Fd0/d0/dv3/d0; [restore attacker's power]
!!HEv6&x1>0/v6>=0:Fd0/d0/dv4/d0; [restore defender's power]
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!
- Gaidal Cain
- Round Table Hero
- Posts: 6972
- Joined: 26 Nov 2005
- Location: Solna
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: Select all
CCCCC
CRCRC
RCYCR
CCRCC
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: Select all
!?LE0/0/0; [when event at NW corner of surface is visited]
Code: Select all
!?OB2/2/0; [when object at (2,2,0) is visited]
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: Select all
!$OB2/2/0; [AFTER object at (2,2,0) is visited]
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: Select all
!?OB2/2/0; [When object at (2,2,0) is 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: Select all
!!OW:C?y1; [get current player color]
!!OW:Iy1/?y2; [is current player an AI?]
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: Select all
!!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!"^;
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: Select all
!!OW:R-1/6/?y3; [find out how much gold the current player has]
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: Select all
!!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: Select all
!!VRy4:S0 R1; [coin flip]
!!IF&y2=1:V1/y4; [set the flag to the flip]
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: Select all
!!OW&1/y3>=100:R-1/6/d-100; [deduct 100 gold, if appropriate]
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: Select all
!!VRv2:S0; [initialize v2 to 0]
!!VRv2&1/y3>=100:+4; [set v2 to 4 if payment was made]
Recall the following lines from the start of the script:
Code: Select all
!!VRv1:+1; [add 1 to v1]
!!VRy1:Sv1%10; [is v1 a multiple of 10?]
Code: Select all
!!VRv1:+1+v2; [add 1+v2 to v1]
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.
Added 3/6/2007: I have reconstructed the missing code line! it now appears here and in the completed code fragment below. -QQD
Code: Select all
!!VRy1&y1<=v2:S0; [if payment causes a change, note it]
So now, after a slight change to the text messages, are entire script now reads:
Code: Select all
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<=v2:S0; [if payment causes a change, note it]
!!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]
- Gaidal Cain
- Round Table Hero
- Posts: 6972
- Joined: 26 Nov 2005
- Location: Solna
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: Select all
Month: !!VRv1:Sc+27:28;
Week: !!VRv1:Sc+6:7;
Week of the month: !!VRv1:Sc-1:7%4+1;
Day of the week: !!VRv1:Sc%7+1;
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: Select all
!!VRv1:S3 T5 T5 T5;
Code: Select all
!!VRv1:S3 R5 R5 R5;
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: Select all
!!VRv1:S0+5+6*3+2;
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: Select all
!!VRz1:H1;
Copying from the help file:
Code: Select all
!!VRz100:S^Hello!^;
!!VRz101:S^^;
!!VRz102:S^ ^;
!!VRz100:H300; flag300=1
!!VRz101:H301; flag301=0
!!VRz102:H302; flag302=0
- Gaidal Cain
- Round Table Hero
- Posts: 6972
- Joined: 26 Nov 2005
- Location: Solna
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: Select all
!?OB17;
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: Select all
!?OB17/81;
With three numbers, only the object at the (x,y,level) location will trigger the code. Example:
Code: Select all
!?OB2/2/0;
---------------
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: Select all
!!OB#1/#2/#3:XXXX;
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: Select all
!!OB4/5/1:T?y1;
Code: Select all
!!OB4/5/1:T2;
U$
This sets the subtype of the object. Thus, if we left the type as 17, and gave the command:
Code: Select all
!!OB4/5/1:U?24;
- Gaidal Cain
- Round Table Hero
- Posts: 6972
- Joined: 26 Nov 2005
- Location: Solna
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: Select all
!!HE4/7/0:XXXX
To address a hero directly, you use just the hero number:
Code: Select all
!!HE5:XXXX
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: Select all
!!HE5:A26;
Code: Select all
!!HE5:A-7;
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: Select all
!!HE5:A1/26/5;
Code: Select all
!!HE5:A1/?y1/5;
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: Select all
!!HEv1300:A2/47/0/?v1301; [Attacker has Cards of Prophecy equipped?]
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: Select all
!!VRz1:S^Sara^; [store text]
!!HE5:B0/z1; [set new 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: Select all
!!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]
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: Select all
!!HE-1:C0/0/139/d;
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: Select all
!!HE-1:C1/132/139/d;
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: Select all
!!HE37:C132/1/133/1/134/1/135/1/-1/0/-1/0/-1/0;
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: Select all
!!HE-1:Ed1000;
Code: Select all
!!HE-1:E?y1/d2;
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: Select all
!!HE0:H0/?y1/1/1;
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: Select all
!!HE-1:A2/0/0/?y1;
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: Select all
!!HEx1:S24/?y9;
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.
- Gaidal Cain
- Round Table Hero
- Posts: 6972
- Joined: 26 Nov 2005
- Location: Solna
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: Select all
!!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/;
to set up the dialog, and
Code: Select all
!!IF:E5/1;
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.
- Gaidal Cain
- Round Table Hero
- Posts: 6972
- Joined: 26 Nov 2005
- Location: Solna
Today's script is going to create a sphinx-like object similar to the heroes 2 version. A question will be asked- actually several questions- and if you give the correct answer to a given question, you get a reward. Failure to answer correctly results in death. The hero will also be allowed to back out- but only before seeing the question.
To do this example, I am going to assume that we are using an unscripted object, located at (2,2,0). I am going to modify the classic riddle of the sphinx.
For those who do not know it, the Riddle of the Sphinx goes like this:
"What walks on four legs at dawn, two legs at noon, and three legs at dusk?"
The answer is "a man," since at the dawn of his life- as an infant- a person crawls on all fours (legs+arms). In the middle of his life, he walks upright on two legs. In the dusk of his life -as an elderly person- he walks on three (2 legs+ a cane).
Instead of this question, we are going to ask the player how many legs he walks on. He will have three choices- morning, noon, or evening- and will have to type in the correct answer- 4, 2, or 3. We correlate these to the early, middle, and end stages of the game. In the early game, you need mostly resources to build structures, so the morning question will give a reward of 20 of each resource. In the middle game, you generally need gold to buy all those creatures and heroes to build an army, so we will give 20000 gold for the noon question. In the late game, you generally need to have movement to clean up the map, so we will give the Boots of Speed to the hero. If you disagree with my reasoning, then you can easily change the rewards as you want. This is only an example!
Now, we don't want anyone to be able to answer the same question correctly more than once. I am going to use flags 11, 12, and 13 to keep track of which questions were answered.
Let's begin:
Code: Select all
ZVSE [script begins]
!#IF:V11/0; [set flag 11 to false]
!#IF:V12/0; [set flag 12 to false]
!#IF:V13/0; [set flag 13 to false]
!?OB2/2/0; [when sphinx is visited]
Code: Select all
!!IF&1000:Q1^As you approach the sphinx, a voice echoes around you:
{whoever approaches me can get a great reward, but your life is forfeit if you do not pass my challenge!}
Do you approach?^; [The hero may back out. Flag 1 holds the response. Note that flag 1000 is used so only a human player gets asked.]
Code: Select all
!!IF&-1/1000:M^Fearing the mighty sphinx, you back away.^; [message if player declines to risk it]
!!FU1&1/1000:P; [call function 1 if player agrees to so so]
!?FU1; [beginning of main function]
** The next 13 lines sets up the dialogue for the sphinx.
!!VRz101:S^How many legs do you walk on?^;
!!VRz102:S^The time of day.^;
!!VRz103:S^The number of legs (digits only).^;
!!VRz104:S^Sunrise.bmp^;
!!VRz105:S^Noon.bmp^;
!!VRz106:S^Sunset.bmp^;
!!VRz108:S^Morning^;
!!VRz109:S^Afternoon^;
!!VRz110:S^Evening^;
!!VRz112:S^It is morning^;
!!VRz113:S^It is afternoon^;
!!VRz114:S^It is evening^;
!!IF:D1/z101/z102/z103/z104/z105/z106//z108/z109/z110//z112/z113/z114/;
Code: Select all
!!IF:E1/1; [ask the question, and save the choice in v1.]
Next, so the number typed in can be passed to a function, I need to convert it to a number, from the text character. However, a command such as !!VRy1&z1=^2^:S2; does not work, so we need to set up a few extra variables. In general, you need to do this to check each valid answer for a text-comparison. It is best if you make the question specific enough to only allow a very few answers.
Code: Select all
!!VRz2:S^2^;
!!VRz3:S^3^;
!!VRz4:S^4^;
Code: Select all
!!VRy1:S0; [initialize y1]
!!VRy1&z1=z2:S2; [if the answer was "2"]
!!VRy1&z1=z3:S3; [if the answer was "3"]
!!VRy1&z1=z4:S4; [if the answer was "4"]
Code: Select all
!!FU2&v1=1:Py1; [If morning question]
!!FU3&v1=2:Py1; [If afternoon question]
!!FU4&v1=3:Py1; [If evening question]
Code: Select all
!!IF&v1=-1:M^The sphinx booms:
{You insult me by refusing to answer! DIE!}^;
!!HE-1&v1=-1:K; [if answer is refused, kill the current hero]
Code: Select all
!?FU2; [morning question routine]
!!IF&x1=4/-11:M^{You are the first to answer that quesion correctly. As a reward, take 20 of each of your construction materials!}^;
!!OW&x1=4/-11:R-1/0/d20; [give wood]
!!OW&x1=4/-11:R-1/1/d20; [give mercury]
!!OW&x1=4/-11:R-1/2/d20; [give ore]
!!OW&x1=4/-11:R-1/3/d20; [give sulfur]
!!OW&x1=4/-11:R-1/4/d20; [give crystal]
!!OW&x1=4/-11:R-1/5/d20; [give gems]
!!IF&x1=4/11:M^{You are correct, but the reward has already been given. Too bad for you.}^;
!!IF&x1<>4:M^{You have answered incorrectly. Your life is mine!}^;
!!HE-1&x1<>4:K; [kill hero if a wrong answer was given]
!!IF&x1=4:V11/1; [if the question was answered correctly, set flag 11 to true]
Code: Select all
!?FU3; [afternoon question]
!!IF&x1=2/-12:M^{That is correct! I shall bestow riches upon you!}^;
!!OW&x1=2/-12:R-1/6/d20000; [give gold]
!!IF&x1=2/12:M^{You are correct, but the reward has already been given. Too bad for you.}^;
!!IF&x1<>2:M^{You have answered incorrectly. Your life is mine!}^;
!!HE-1&x1<>2:K; [kill hero if a wrong answer was given]
!!IF&x1=2:V12/1; [if the question was answered correctly, set flag 12 to true]
Code: Select all
!?FU4; [evening question]
!!IF&x1=3/-13:M^{You have answered correctly. As the elderly tend to move more slowly, take these boots to increase your speed.}^;
!!HE-1&x1=3/-13:A98; [give boots of speed to active hero]
!!IF&x1=3/13:M^{You are correct, but the reward has already been given. Too bad for you.}^;
!!IF&x1<>3:M^{You have answered incorrectly. Your life is mine!}^;
!!HE-1&x1<>3:K; [kill hero if a wrong answer was given]
!!IF&x1=3:V13/1; [if the question was answered correctly, set flag 13 to true]
Notice that we did not use a single command that I have not already covered. That is why, for the most part, I simply placed comments in the code, rather than full explanations.
If you really wanted to be nasty, you could even remove the killed heroes from the allowed hero list- thereby truely killing the hero. To do this, use the HE:R command to set hero-pool availability of the hero.
Some other ideas you could use is to have only a single question, but offer several rewards. You can use a different dialogue box to ask a different type of question. There are lots of things you can try.
- Gaidal Cain
- Round Table Hero
- Posts: 6972
- Joined: 26 Nov 2005
- Location: Solna
The next thing that most people want to do is modify a battle setup. Whether something simple, such as a new artifact effect, or something more involved, such as modifying creature statistics for all monsters on the battlefield.
First, I will cover the battle TRIGGERS. There are several of them, and each have a specific use. One thing they have in common is the first letter of the triggers are all "B" (for battle)
Battle scripts have three main sections: before battle, during battle, and after battle.
The before battle script is activated by use of the !?BA0 trigger. Any commands after this trigger will run as soon as a battle begins- before the battlefield even appears on the map. In fact, if you have a message displayed during this phase, it will appear while still on the adventure map screen.
Actions to be taken at the END of battle use the !?BA1 trigger. These actions take place after returning to the map screen.
If you look at the cards script I wrote (script34.erm), you will see that it has these two sections only. That is because it only changes things at the start of battle, and changes them back at the end.
If you are looking in the script editor, take a look at the help for the !?BR trigger. It contains a chart showing the order of execution of battle triggers. I am going to go over the remaining triggers in the order they appear on this list.
After BA0, the next trigger is !?BR- this is the Battle Round trigger, This activates at the beginning of every round of combat, as well as during the pre-battle setup (round -1), and tactics phases (rounds -2 and -3).
If you want something to occur only during certain rounds, then note that the current battle round is kept in variable v997. For example, if you only want something to happen every third round (such as automatically casting a spell in a manner similar to enchanters), then you would code:
Code: Select all
!?BR;
!!VRy1:Sv997%3; [set y1 to be the round number, mod 3]
!!FU1&v997>=0/y1=0:P;
You would then put whatever you wanted to happen inside function 1.
Next is the BF (BattleField) trigger. This is used to set up a custom battlefield- in case you don't want the default. How to set up a custom battlefied will be covered in the !!BF receiver section below.
Finally are the paired triggers BG0 and BG1. These triggers activate before (0) and after (1) every action a monster takes. You can use these if you want to have something happen whenever a certain creature takes an action. The various receivers are used to manipulate these things.
If you are looking in the help file, you will note that there are also !?BA50 and !?BA51 triggers. See below, in the E option for the !!BA receiver, for more information about these.
Now that we know how to identify what is going on, it is time to see what can be done.
!!BA
This lets you set up a battle. For the most part, these commands make no sense in any portion of a script other than the !?BA0 section. The options here are:
B#
Use this to choose the background picture for the battle. Note that this does NOT set the terrain the battle is on, it only changes the picture.
Instead of a background number, you can use ^picture.pcx^ to use a custom background. As with hero portraits, the filename must be under 12 characters. The picture location is relative to the data folder- so it is best to keep the pictures there, so you have enough characters to name the file :-)
D#
Use this to enable or disable a battle. If it is set to 1, the battle is automatically won.
E?$
This command checks what sort of battle is taking place. It returns a value of 1 if the battle is between two human players sitting at different computers- that is, a network-multiplayer battle. The value is 2 for battles that the AI initiates against a remote player. The value is 0 otherwise.
Why do we need this command? It is because when a battle is done between two different computers, information can become unsynchronized- causing unpredictable problems. This problem is due to random effects- including but not limited to morale and luck boosts. This problem was even seen from time to time in heroes 3 before WoG.
How do things become different? Slava was able to give me a good example:
"Let's say you have a script causing a random spell to be cast. On the attacker's side, one spell is cast, but when the script runs on the defender's computer, a different random number is chosen- and so a different spell is cast. Now the two computers have different battle states.
What you need to do is generate the random effect on one side, and then pass the random value to the other side. Note that in battles, only variables v9001 through v10000 are passed. If you are not working with random effects, then this will not cause a problem- since the script itself is the same on both sides."
To help alleviate this problem, the BA50 and BA51 triggers were recently added. These triggers are used to help align the two sides in a battle. The basic idea is this:
Code: Select all
!?BA0; [start-of-battle trigger]
** here goes whatever you want to happen at the start of battle. You should use a variable that is NOT passed to be set to a specific value (in the help-file example, v10 is set to 0).
!?BA50; [start-of-battle, at defender's side]
** here, you should set the variable that was chosen above to another value (in the help-file example, v10 is set to 1).
In the triggers, check for which side is going. Your script will look something like this:
Code: Select all
!?BG0&v10=0; [before creature action, only on attacker's side]
!!VRv9001:S0R9; [get a random number between 0 and 9]
*** code for stuff that happens using the random number
!?BG0&v10=1; [before creature action, only on defender's side]
*** same code as above, but WITHOUT the VR9001 line.
Something similar will need to be done for each battle trigger that involves any randomness. To be safest, any combat script should duplicate as much as possible. Many of the "official" WoG scripts were written before these commands were available, which is why they tend to use the BA:E command, and deactivate in multi-computer battles.
Note that you cannot access heroes directly on the defender's side. Instead, use hero numbers -10 and -20 for the attacker's and defender's heroes.
Changes on the defender's side are not kept after the battle is done, so except in very rare cases you do not need to use !?BA51 to undo changes that were done.
H#/$
This lets you set or check the hero that is taking part in the battle. Most likely, you will use this only to check the heroes involved, but there are exceptions- for example the Hourglass of Asmodeus script.
M#1/#2/$3/$4
This option lets you check the creatures fighting in the battle. #1 is the player: Attacker is 0, defender is 1. #2 is the slot number, 0 through 6. Note that this only checks the standard 7 army slots, and does not include commanders, automatically summoned creatures, and so on. 3 and 4 are the type and quantity of creatures, respectively. They can be read in or set. Thus, !!BA:M0/0/?v1/?v2;
reads the type and number of creatures in the attacker's first army slot into v1 and v2. !!BA:M1/4/24/5; changes the 5th creature stack in the defender's army into 5 unicorns (creature 24)
O$1/$2
This gets the player who owns the attacker's (1) and defender's (2) forces. Although you will not get an error if you try to set these values, Setting them will not have any effect- so you cannot "pass control" of a battle to another player.
P#1/#2/#3
This gets the terrain type at position ($1,$2,$3) on the map, and sets the background and terrain bonuses for the battle to that of the given location.
-----------------
Next, we have the BF or Battlefield receiver. This one is used to customize the battlefield for combat. The BF commands should only appear in the BF trigger section of a script.
This receiver only has three options: C, O, and M.
C
This option is used to get a battlefield with NO obstacles on it.
O#1/#2
This command is used to place a specific obsticle (#1) in a specific location (#2) on the battlefield.
In the scripter help for the BF receiver, there is a link to a chart showing you exactly how the locations correspond to the battlefield. You will note that there are locations one space off the left and right ends of each row. Since some obstacles are more than one space wide, you may need to place things there as well. In the pictured example, one-unit wide obstacles are placed there to "frame" the battlefield. Also note in that picture that some troops appear on top of obstacles- there is nothing preventing you from doing this. However, be certain that you do not place a creature in such a way that it cannot move, or an impossible battle may result.
M#1/#2/.../#11/#12
This lets you place an obstacle of type #12 in every location indicated by #1 through #11.
Each number (1 through 11) is a single value for the corresponding row in the battlefield. You need to find the "bitimage" value for the locations. The position to the left of the row is valued as 1, the first battlefield space is 2, then 4, 8, 16, and so on until the last space in the row is 32768, and the space to the right of the row is 65536. Add the values to get a number between 0 and 131071.
If #12 is omitted, a simple rock is used for the obstacle image.
Note that you do NOT need to use the C option, if you are going to use M- the M option assumes that you want only the obstacles you specify.
For an amusing battle, try setting up a fight with no shooters, and this battlefield command:
Code: Select all
!!BF:M2184/10920/10920/10920/10920/10920/10920/10920/10920/10920/8376;
2184 is the pattern: ...X...X...X.....
10920 is the pattern:...X.X.X.X.X.X...
8376 is the pattern: .....X...X...X...
Note that the first 3 spaces are left blank- this way any troops that start out on the field will not be immobilizied. You should leave the 2, 4, 16384, and 32768 locations open, unless you are repositioning the troops as well.
Try making a maze if you want to be VERY annoying.
Next is the BG receiver. As you would expect, !!BG commands can only be used within a !?BG trigger.
The BG commands deal with the actions of an individual creature. Remember that there are two BG triggers- one before a creature acts, and one after.
BG options:
A$
Use this command to determine the type of action the creature stack will take. The value of the number gives the type of action:
0: Cancel. Note that you may not be able to force the stack to do something, even with proper ERM code.
1: Have the hero cast a spell.
2: Move to a new location
3: Defend
4: Have the hero retreat
5: Have the hero surrender
6: Move and attack
7: Shoot (if it can)
8: Wait
10: Have the monster cast a spell.
Note that many of these require targeting. This brings us to:
D$
This is the target location for the creature's action (or hero's spell)
E$
This gets the monster stack at the destination. It returns -1 if there is no stack there. You can use this in combination with D and a loop to locate targets for a move and attack or a spell.
H$
This gets the owning hero number (-1 if no hero)
N$
This gets the stack number of the current creature. There are 21 stacks for each side. The attacker's stacks are numbered 0 through 20, and the defender's are 21 through 41
Q?$
Get the side of the creature (0=left/attacker; 1=right/defender)
S$
This is to set the number of a spell to cast.
Note that automatic effects on a creature's turn (such as the enchanters casting a spell every 3rd turn, or the regeneration of a creature) occure BEFORE the !?BG0 trigger.
-----------------
Similarly, you can also give instructions to the hero, using the !!BH or Battle Hero receiver.
This has four options of its own:
C#1/#2/#3/#4
This has the hero cast spell #1 with magic skill level #3 at position #2. #4 is a check for valid target (creature exists at the target)
M$
This lets you disable (1) or enable (0) the hero to cast a spell. Note that if the hero already cast a spell in the round, re-enabling it will not take effect until the next creature turn (which includes the current stack getting a free turn via morale). Obviously, if the next creature belongs to the other side, the hero needs to wait until a creature s/he owns gets another turn.
N?$
Get the hero number.
Q#1/#2/#3
This places a hex of quicksand (#1=0) or a land mine (#1=1) at position #2.
#3 is a flag for redrawing (1=yes, 0=no), as we have seen for several other commands.
WoG automatically will check for a valid placement using this command.
I will go over the remaining batle receivers in the next post.
I realize that going through all the commands the way I have been can be a bit overwhelming- but it is the best way to be certain I didn't skip anything. However, once the battle commands are done, then all the most important commands will have been covered.So, I will start analyzing various scripts, line-by-line, so you can see exactly how all this stuff comes together. I will start with my scripts- The cards of prophecy, and possibly the creature affinities (I haven't finished that script, so I don't know if I will present it or not- it is currently in debugging).
- Gaidal Cain
- Round Table Hero
- Posts: 6972
- Joined: 26 Nov 2005
- Location: Solna
Continuing with the battle commands, the BM or Battle Monster receiver lets you manipulate the attribtes of a single monster stack. Changes made to a monster stack with this command are only for that specific stack of monsters, as opposed to all creatures of that type. Also, the effects do not carry over to the next battle.
Some examples of when you would want to use this would be:
1) giving a new ability to an artifact that modifies creature abilities
2) bonuses from scripted map objects
3) creating your own hero specialties.
The format for this receiver is:
Code: Select all
!!BM#:[options];
BM options:
A$
This is to get or set the attack skill of the creature, including all bonuses.
B$
This is to get the number of creatures that were in the stack at the start of battle- very useful if you want to have ressurrection-like effects.
C#1/#2/#3/#4/#5
This is to have a spell cast, similar to the like command in my last post.
This has the monster cast spell #1 at location #2, with skill level #3. #5 is again a check for a target existing.
D$
This is like A, but for defense skill value, rather than attack skill.
E$
This gets or sets the number of spells the creature has left to cast. FOr example, if the creature stack is a supreme archangel, this will give a value of 2 at the start of battle, and 1 after the resurrection skill has been used once, and 0 after the second use. You can set this to give more or fewer castings to a creature.
F$
This is used to check the flags associated with a monster stack. If you want to check the flags, you must use one of the single-letter variables (f..t), as v-variables will not hold the values properly.
Each attribue of a creature corresponds to a specific bit:
for this chart, we have [bit number]/[decimal value]/[meaning if set]
0/1/creature is 2-hexes wide
1/2/creature can fly
2/4/creature can shoot
3/8/creature has a 2-hex (breath) attack in melee
4/16/creature is alive (and can be affected by things that affect living creatures)
5/32/creature is a catapult
6/64/creature is a seige weapon (and so has no movement)
7/128/creature can be affected by any level slayer spell (if attacked by a stack with slayer active, the attacking creature gets the bonuses)
8/256/creature can be affected by only an ADVANCED or higher slayer spell
9/512/creature can only be affected by an EXPERT slayer spell
10/1024/creature is immune to mind spells
11/2048/creature is a shooter, and has no obstacle penalty.
12/4096/creature has no melee penalty
14/16384/creature is immune to fire-school spells
15/32768/creature has two attacks (melee unit or ranged unit *if shooting*)
16/65536/creature is not retaliated against
17/131072/creature has no morale
18/262144/creature is undead (and can be affected by things that affect undead)
19/524288/creature attacks all adjacent creatures.
20/1048576/creature has an area-effect shot (such as magogs). This bit has no effect if set manually.
22 and 23/12582912/creature stack is a clone
24/16777216/creature has had a free turn due to morale this round
25/33554432/creature is waiting
26/67108864/creature has finished this round's actions
27/134217728/creature is defending
31/2147483648/creature is a dragon
You can set individual bits with the | operator in a VR command. You can clear individual bits with the & operator in a VR command. For example, you can remove the fly skill and add mind spell immunity to creature stack 2 by these commands:
Code: Select all
!!BM2:F?i; [load bits into variable i]
!!VRi:|1024; [add mind-spell immunity]
!!VRi:&2; [remove flying]
!!BM2:Fi; [set new bits]
Code: Select all
!!BM22:F?i; [load bits]
!!VRi::33554432; [divide by the value of bit 25- waiting]
!!VRi:%2; [find i (mod2)]
Some bits are not listed- they either do not do anything, are their functions are unknown at this time. Leave them alone.
G#/$1/$2
This is used to set or check if a spell (#) is active on the creature, for how long ($1), and at what power level ($2). Duration ($1) is 0 if the spell is not active.
H$
Set or check the hit points of the stack. This is the hit points for each creature- not the current "top" one.
I?$
Check which side the creature is on (left-0 or right-1)
J?$
Check how many spells are active on the creature.
K#
Inflict # damage to the creature stack.
L$
Hit points lost by the top monster in the stack. (for example, if an azure dragon has 875 hit points left, this value is 125.)
M#1/#2/#3
Apply spell #1 for duration #2 at skill level #3.
There are several comments on this in the scripter help- be certain to read over them. Of particular note is that although you can use the G option for most things, this command will allow you to cast dispel or cure on a creature- removing the need to check for every active spell on the monster.
Spells which are not normally permanent on a creature (or even spells that aren't combat spells!) can be used here as well. Of course, if you do not script a meaning for them, it will merely be confusing to the player.
N$
This gets or sets the current number of creatures in the stack. There is a comment on vampire lords in the help file about this number. Simply put, vampire lords will only regenerate if this number is less than the value in the B command. Therefore, if you make the stack grow larger than it started, the vampire lords will not recover.
O$
This is the army slot that the stack comes from (and returns to). (0..6) If the stack is in slot -1, then it was not in the army before the battle. This includes summoned creatures, clones, santa gremlin guards, and so on.
P$
This gets the position of the stack on the battlefield (0..186)
Q#1/#2/#3
This is identical to the BH command to place quick sand or a land mine on the field (except this is a creature triggering the spell, rather than the hero)
R$
This sets or checks the number of times a creature can retaliate. For most creatures, it starts each round at 1, and counts down after a retaliation. Griffin have it set to 2. Royal Griffin have it set to 5000 (so it isn't REALLY unlimited retaliations, but scripting a situation to let it be attacked 5000 times in one round of combat is really long!) Note that the counterstrike spell can increase this number as well as an ERM command.
S$
This is the creature's speed.
T$
This gets the creature type.
The last of the battle commands is the BU receiver. This controls a lot of the general aspects of the battle (as opposed to a specific part of it)
It has the standard form:
Code: Select all
!!BU:[options];
This is used to check if the battle finished this round (1=yes, 0=no)
There may be times when you need something done at the end of battle, but before the BA1 trigger is called. This is the way to check for this situation.
D#/?$
This checks for a dead creature stack at position #. $ contains the stack number (0..41) if there is a dead stack there (but no live stack on top of it). It is -1 for an empty hex, and -2 if a living stack is there.
E#/?$
This checks for an alive stack at position #. $ is -1 for an empty stack, otherwise it is the stack number.
O#/?$
This checks for an obstacle at position #. It is a bit-mask, to determine the type of obstacle:
$ is 0 if there is no obstacle.
the 1 bit is set if there is a magic obstacle
the 2 bit is set if there is an obstacle (not necessarily magic)
the 4 bit is set if there is quicksand (magic obstacle)
The 8 bit is set if there is a land mine (magic obstacle)
R
Redraw the battle screen.
S#1/#2/#3/#4/#5/#6
Summon a creature stack of type #1 and quantity #2 to position #3 on the #4 side of battle (0=left, 1=right). After battle, place these creatures in the hero's army slot #5 (-1 if it will disappear after battle), and redraw the battlefield (#6=1- yes, #6=0- no)
Remember that you cannot have more than 20 creature stacks on either side of a battle.
T?$
Check to see if there is a tactics phase to this battle (1=yes, 0=no)
- Gaidal Cain
- Round Table Hero
- Posts: 6972
- Joined: 26 Nov 2005
- Location: Solna
This next lesson is going to take an official script- my Cards of Prophecy script- and break it down, line by line. Many comment lines will be removed, but in-line comments will be left. New commands and specific values will be explained when needed.
Note: Some of the lines of codes are pretty large. In the original post, QQD included hard line breaks along with a notation for this, since Forumplanet didn't introduce linebreaks in code. These forums do that, however, and the hard line breaks have been discarded. There might still be a couple of soft breaks here and there, but since comments generally are in hard brackets ([]) and all code lines should begin with !!, !? or !#, this shouldn't be a problem. GC
Code: Select all
ZVSE
!#UN:P34/?v1321; [is script active?]
Note that I almost always use (permanent) v-variables in the 1300's this is because in the WoG team, we do not want to use the same variables in multiple scripts. Thus, we claim sets of variables. Similarly, all my functions are in the 13,500's.
Code: Select all
!#VRz698:Sz134001;
Note that the z-variable index is much larger than what is normally allowed. This indicates that it is in an ERT file. The first 1 indicates and ERT file, the 34 indicates the file is script34.ert, and 001 is the index of the text. All ERT z-variables will be six digits.
z134001 contains the following text:
Code: Select all
{Cards of Prophecy}
When entering battle, a card will emerge from the deck. Each card has a different effect.
It will also bestow a +1 bonus to the luck of your army.
Code: Select all
!#HT5/47&v1321=1:T698; [set new artifact text if active]
Code: Select all
!?BA0&v1321=1; [start of battle]
Code: Select all
!!BA:E?v1331; [check for multiplayer]
Code: Select all
!!FU13502&v1331=0:P; [if it isn't, then continue with the rest of the script.]
Code: Select all
!?FU13502; [start of main script]
Code: Select all
!!BA:H0/?v1300; [get attacking hero's number]
!!BA:H1/?v1310; [get defending hero's number]
!!HEv1300:A2/47/0/?v1301; [Attacker has Cards of Prophecy equipped?]
Code: Select all
!!HEv1310&v1310>=0:A2/47/0/?v1311; [Defender has Cards of Prophecy equipped?]
Code: Select all
!!FU13500&v1301>0/v1300>=0:Pv1300; [if any equipped, generate bonus for attacker]
!!FU13500&v1311>0/v1310>=0:Pv1310; [if any equipped, generate bonus for defender]
Code: Select all
!?BA1&v1321=1/v1331=0; [end of battle]
!!FU13501&v1301>0/v1300>=0/v1307<=23: Pv1300/v1302/v1303/v1304/v1305/v1306/v1307/v1307; [undo attacker bonus]
!!FU13501&v1311>0/v1310>=0/v1317<=23: Pv1310/v1312/v1313/v1314/v1315/v1316/v1317/v1317; [undo defender bonus]
!!FU13507&v1301>0/v1300>=0/v1307>=24/v1307<=30: Pv1300/v1308/v1309/v1328/v1326/v1306/v1307/v1307; [undo attacker 1.3]
!!FU13507&v1311>0/v1310>=0/v1317>=24/v1317<=30:Pv1310/v1318/v1319/v1320/v1327/v1316/v1317/v1317;
[undo defender 1.3]
The "1.3" lines refers to the additional cards that I added in for version 1.3 of the script- v1307 and v1317 contain the card numbers drawn, and that indicates which function is called.
Code: Select all
** function to generate card and apply its effect
!?FU13500;
!!VRv1307&x1=v1300:S0T30; [choose card number, if attacker]
!!VRv1317&x1=v1310:S0T30; [choose card number, if defender]
Code: Select all
!!HEx1&x1=v1300:F?v1302/?v1303/?v1304/?v1305; [if attacker, get hero statistics]
!!HEx1&x1=v1310:F?v1312/?v1313/?v1314/?v1315; [if defender, get hero statistics]
!!HEx1:I?y10; [get hero's current spell points]
!!VRv1306&x1=v1300:Sy10; [if attacker's hero, store current spell points]
!!VRv1316&x1=v1310:Sy10; [if defender's hero, store current spell points]
In retrospect, the spell points storage could have been done in two HE:I commands, rather than an HE:I and two VRs, but this is how I wrote it. I may change this in the future, but only if I am doing other changes to the script. As the adage says, "If it ain't broke, don't fix it."
Code: Select all
!!FU13504&v1307<=23/x1=v1300:Px1/v1307/v1307; [if card is an original bonus/penalty]
!!FU13504&v1317<=23/x1=v1310:Px1/v1317/v1317; [if card is an original bonus/penalty]
!!FU13505&v1307>=24/v1307<=30/x1=v1300:Px1/v1302/v1303/v1304/v1305/v1306/v1307; [if v1.3 card]
!!FU13505&v1317>=24/v1317<=30/x1=v1310:Px1/v1312/v1313/v1314/v1315/v1316/v1317; [if v1.3 card]
Code: Select all
!!HEx1:F?y1/?y2/?y3/?y4; [get modified stats]
!!VRv1308&x1=v1300:Sv1302-y1; [get -attacker's attack change]
!!VRv1309&x1=v1300:Sv1303-y2; [get -attacker's defense change]
!!VRv1328&x1=v1300:Sv1304-y3; [get -attacker's spell power change]
!!VRv1326&x1=v1300:Sv1305-y4; [get -attacker's knowledge change]
!!VRv1318&x1=v1310:Sv1302-y1; [get -defender's attack change]
!!VRv1319&x1=v1310:Sv1303-y2; [get -defender's defense change]
!!VRv1320&x1=v1310:Sv1304-y3; [get -defender's spell power change]
!!VRv1327&x1=v1310:Sv1305-y4; [get -defender's knowledge change]
** End of function 13500
I realized this problem after the original script writing, and that is why the variable numbers aren't nicely ordered here. This is another reason why it is important to keep records of what your variables do.
This applies mostly to battle scripts, or any script supposed to "wear off" (like the magic mushrooms). I the case of a script that doesn't work just in direct connection with battle(i.e. it's not triggered at battle start and end), I'd recommend using a w variable to keep track of the change. Also note that it's not just scripts that can interfere, level ups and other kind of "normal" bonuses can as well, so always keep the relative change, even if it's only for a map-specific script. GC
Code: Select all
** Function to apply bonus, if it is a statistic bonus.
!?FU13504;
!!VRx2:%4; [calculate hero primary stat]
!!VRx3::4; [calculate bonus to stat]
Code: Select all
!!VRx3&x3=0:S-1; [if random bonus is 0, then make it -1]
Code: Select all
!!VRy1&x2=0:Sx3; [If primary stat is 0, set y1 to bonus]
!!VRy2&x2=1:Sx3; [If primary stat is 1, set y2 to bonus]
!!VRy3&x2=2:Sx3; [If primary stat is 2, set y3 to bonus]
!!VRy4&x2=3:Sx3; [If primary stat is 3, set y4 to bonus]
!!HEx1:Fdy1/dy2/dy3/dy4; [add bonus]
Code: Select all
!!HEx1:S24/?y9; [get level of hero's intelligence skill. Specialty is ignored]
I don't think the extra code would be that much(2 or 5 lines, I'm not sure how the bonus works), but I still don't think it's improtant enough to write it.
Code: Select all
** calculate bonus spell points, if any
!!VRy4&x2=3/y9=0:*10; [bonus spell points with no intelligence]
!!VRy4&x2=3/y9=1:*25; [bonus spell points with basic intelligence, part 1]
!!VRy4&x2=3/y9=1::2; [bonus spell points with basic intelligence, part 2]
!!VRy4&x2=3/y9=2:*15; [bonus spell points with advanced intelligence]
!!VRy4&x2=3/y9=3:*20; [bonus spell points with expert intelligence]
!!HEx1:I?y10; [get hero's current spell points]
!!VRy10:+y4; [add bonus spell points]
!!VRy10&y10<0:S0; [if spell points somehow became negative, set to zero]
!!HEx1:Iy10; [set hero spell points to new level]
Code: Select all
** z1, z2, and z3 contain words needed for the start-of-battle message.
** Check script34.ert for actual text.
!!VRz2&x3=-1:Sz134002;
!!VRz2&x3=1:Sz134003;
!!VRz2&x3=2:Sz134004;
!!VRz2&x3=3:Sz134005;
!!VRz2&x3=4:Sz134006;
!!VRz2&x3=5:Sz134007;
!!VRz2&x2=0:+z134008;
!!VRz2&x2=1:+z134009;
!!VRz2&x2=2:+z134010;
!!VRz2&x2=3:+z134011;
!!VRz3&x2=0:Sz134012;
!!VRz3&x2=1:Sz134013;
!!VRz3&x2=2:Sz134014;
!!VRz3&x2=3:Sz134015;
!!VRz5:Sz134016;
!!VRz5&x3=-1:Sz134017;
!!HEx1:B0/?z4; [get hero name]
These, in addition to the hero name, contain all the words that change based on the drawn card.
Code: Select all
!!HEx1:O?y6; [get hero owner]
!!OW:Iy6/?y7; [is owner an AI?- if so, message will not display]
!!IF&y7=0:M1/z134018;
z134018 contains the following:
Code: Select all
As battle begins, the %Z2 emerges from the Cards of Prophecy.
%Z4's %Z3 %Z5 by %X3 for this battle.
Code: Select all
** version 1.3 cards
!?FU13505;
!!VRy1:Sx2+x3+x4+x5-2; [set y1 to sum of hero stats, less 2]
!!VRy1&x7=26|x7=27:+1; [add one to y1 if Hermit or Magician card]
!!HEx1&x7=24:Fy1/0/1/1; [If Emperor, shift all primary stats to attack]
!!HEx1&x7=25:F0/y1/1/1; [If Empress, shift all primary stats to defense]
!!HEx1&x7=26:F0/0/y1/1; [If Magician, shift all primary stats to power]
!!HEx1&x7=27:F0/0/1/y1; [If Hermit, shift all primary stats to knowledge]
!!HEx1&x7=30:F0/0/1/1; [If Inverted Fool, remove all primary stats]
Code: Select all
!!VRy1&x7=28:+5;
!!VRy1&x7=28::4; [Get average of primary stats, rounded up, if Hierophant]
Code: Select all
!!HEx1&x7=28:Fy1/y1/y1/y1; [If Hierophant, balance statistics]
!!FU13506&x7=29:Px1/x2/x3/x4/x5; [If Fool, call stat shuffle routine]
!!HEx1&x1=v1300:F?v1322/?v1323/?v1324/?v1325; [store new stats for attacker]
!!HEx1&x1=v1310:F?v1332/?v1333/?v1334/?v1335; [store new stats for defender]
Code: Select all
!!VRy5&x1=v1300:Sv1325; [set v5 to new knowledge skill (attacker)]
!!VRy5&x1=v1310:Sv1335; [set v5 to new knowledge skill (defender)]
!!HEx1:S24/?y9; [get level of hero's intelligence skill. Specialty is ignored]
!!VRy5&y9=0:*10; [spell points with no intelligence]
!!VRy5&y9=1:*25; [spell points with basic intelligence, part 1]
!!VRy5&y9=1::2; [spell points with basic intelligence, part 2]
!!VRy5&y9=2:*15; [spell points with advanced intelligence]
!!VRy5&y9=3:*20; [spell points with expert intelligence]
!!HEx1:Iy5; [set hero spell points to new level]
!!VRv1329&x1=v1300:Sy5-v1306; [store spell point change for attacker]
!!VRv1330&x1=v1310:Sy5-v1316; [store spell point change for defender]
Code: Select all
!!HEx1:B0/?z1; [get hero name]
!!HEx1:O?y6; [get hero owner]
!!OW:Iy6/?y7; [is owner an AI?- if so, message will not display]
!!IF&y7=0/x7=24:M1/z134019;
!!IF&y7=0/x7=25:M1/z134020;
!!IF&y7=0/x7=26:M1/z134021;
!!IF&y7=0/x7=27:M1/z134022;
!!IF&y7=0/x7=28:M1/z134023;
!!IF&y7=0/x7=30:M1/z134024;
!!IF&y7=0/x7=29:M1/z134025;
Code: Select all
** Fool stat-shuffle
!?FU13506;
!!VRy1:S0T22; [choose a permutation. Next 23 lines sets it. No-change permutation is not allowed]
!!HEx1&y1=0:Fx2/x3/x5/x4;
!!HEx1&y1=1:Fx2/x4/x3/x5;
!!HEx1&y1=2:Fx2/x4/x5/x3;
!!HEx1&y1=3:Fx2/x5/x3/x4;
!!HEx1&y1=4:Fx2/x5/x4/x3;
!!HEx1&y1=5:Fx3/x2/x4/x5;
!!HEx1&y1=6:Fx3/x2/x5/x4;
!!HEx1&y1=7:Fx3/x4/x2/x5;
!!HEx1&y1=8:Fx3/x4/x5/x2;
!!HEx1&y1=9:Fx3/x5/x2/x4;
!!HEx1&y1=10:Fx3/x5/x4/x2;
!!HEx1&y1=11:Fx4/x2/x3/x5;
!!HEx1&y1=12:Fx4/x2/x5/x3;
!!HEx1&y1=13:Fx4/x3/x2/x5;
!!HEx1&y1=14:Fx4/x3/x5/x2;
!!HEx1&y1=15:Fx4/x5/x2/x3;
!!HEx1&y1=16:Fx4/x5/x3/x2;
!!HEx1&y1=17:Fx5/x2/x3/x4;
!!HEx1&y1=18:Fx5/x2/x4/x3;
!!HEx1&y1=19:Fx5/x3/x2/x4;
!!HEx1&y1=20:Fx5/x3/x4/x2;
!!HEx1&y1=21:Fx5/x4/x2/x3;
!!HEx1&y1=22:Fx5/x4/x3/x2;
Now comes the stat restoring functions.
Code: Select all
** function to remove card effect
!?FU13501;
!!VRx7:%4; [calculate stat effected]
!!VRx8::4; [calculate bonus given]
!!VRx8&x8=0:S-1;
!!VRx8:*-1; [invert bonus amount]
!!VRy1&x7=0:Sx8; [If primary stat is 0, set y1 to -bonus]
!!VRy2&x7=1:Sx8; [If primary stat is 1, set y2 to -bonus]
!!VRy3&x7=2:Sx8; [If primary stat is 2, set y3 to -bonus]
!!VRy4&x7=3:Sx8; [If primary stat is 3, set y4 to -bonus]
!!HEx1:Fdy1/dy2/dy3/dy4; [reset primary skills]
Code: Select all
!!HEx1:I?y9; [get hero's final spell points]
Code: Select all
!!HEx1:S24/?y8; [get level of hero's intelligence skill. Specialty is ignored]
!!VRy4&x7=3/y8=0:*10; [bonus spell points with no intelligence]
!!VRy4&x7=3/y8=1:*25; [bonus spell points with basic intelligence, part 1]
!!VRy4&x7=3/y8=1::2; [bonus spell points with basic intelligence, part 2]
!!VRy4&x7=3/y8=2:*15; [bonus spell points with advanced intelligence]
!!VRy4&x7=3/y8=3:*20; [bonus spell points with expert intelligence]
Code: Select all
!!VRy9&x1=v1300/x7=3/x8=-1:-y4; [If there was a knowledge penalty, restore lost spell points]
!!VRy9&y9&>v1306/x1=v1300/x7=3:Sv1306; [If attacker has more spell points than at start, and knowledge was changed, reset it]
!!VRy9&y9>v1316/x1=v1310/x7=3:Sv1316; [If defender has more spell points than at start, and knowledge was changed, reset it]
!!HEx1:Iy9; [set spell points for hero]
** end of function 13501
If you were observant, you may have noticed that only parameters x1, x7, and x8 were used here. That is because originally this function checked to see if a level was gained, and then reset the statistics, possibly with the one extra point for a level added in. However, once I reworked the script to use relative changes, this was no longer needed. However, removing the parameters would have involved going through this section of code to change all the x-variable indeces- and if one was missed, it could cause problems.
Code: Select all
** 1.3 undo routine
!?FU13507;
!!HEx1:Fdx2/dx3/dx4/dx5; [restore hero stats to pre-battle levels]
!!HEx1:I?y1; [get final spell-point total]
!!VRy1&x1=v1300:-v1329; [remove change for attacker's spell points]
!!VRy1&x1=v1310:-v1330; [remove change for defender's spell points]
!!VRy1&y1>x6:Sx6; [if spell points are more than before battle, reduce to that level]
!!VRy1&y1<0:S0; [if spell points are somehow negative, set to 0]
!!HEx1:Iy1; [set hero spell points to correct total]
That is the entire script. Notice that except for two lines (UN:P and HT) it only uses commands that I have covered. As my comments indicate, several parts are unnecessarily complicated or lengthy. It is important to remember, however, that you want the routine to work properly first. You can simplify and pretty it up again at some later time.
- Gaidal Cain
- Round Table Hero
- Posts: 6972
- Joined: 26 Nov 2005
- Location: Solna
- Gaidal Cain
- Round Table Hero
- Posts: 6972
- Joined: 26 Nov 2005
- Location: Solna
- Gaidal Cain
- Round Table Hero
- Posts: 6972
- Joined: 26 Nov 2005
- Location: Solna
- Gaidal Cain
- Round Table Hero
- Posts: 6972
- Joined: 26 Nov 2005
- Location: Solna
- Qurqirish Dragon
- Genie
- Posts: 1011
- Joined: 06 Jan 2006
- Location: Flying the skies of Ohlam
ERM
![proud :proud:](/forums/images/smilies/proud.gif)
I have a little qestion about ERM: i'm trying to do the script now and have a problem. The script:
Code: Select all
!?FU22362;
!!VRv2725:S0;
!!VRv2726:S0;
!!VRv2727:S0;
!!VRv2728:S0;
!!VRi:S0;
!!VRf:S0;
!!VRv2732:S0;
!!VRv2733:S0;
!!VRv2734:S0;
!!VRv2750:S0;
!!VRv2752:S0;
!!UN:X?i/?f; get a size of a map
!!VRv2726:S0;
!!VRv2727:S0;
!!VRv2728:S0;
!!DO22364/0/1/1&f=0:P1;
!!DO22364/0/2/1&f=1:P1; call a function
!?FU22364; set a function
!!DO22363/0/1296/1&i=36:P; call a function
!!DO22363/0/5184/1&i=72:P;
!!DO22363/0/11664/1&i=108:P;
!!DO22363/0/20736/1&i=144:P;
!!VRv2728:+1;
!?FU22363; set a function
!!TRv2726/v2727/v2728:E?v2725;
!!OBv2726/v2727/v2728&v2725=0:T?v2733;
!!OBv2726/v2727/v2728&v2725=0:U?v2734;
!!CAv2726/v2727/v2728&v2733=98/v2725=0:O?v2732;
!!OW&v2644=0:C?v2759;
!!VRv2750&v2725=0/v2733=98/v2734=0/v2732=v2759:+1;
!!VRv2752&v2725=0/v2733=98/v2734=1/v2732=v2759:+1;
!!VRv2751&v2725=0/v2732=v2759:Sv2750;
!!VRv2751&v2725=0/v2732=v2759:+v2752;
!!VRv2751&v2725=0/v2732=v2759:*3;
!!VRv2726:+1;
!!VRv2727&v2726=i:+1;
!!VRv2726&v2726=i:S0;
How i can to do script faster. Thanks...
![smile :)](/forums/images/smilies/smile9.gif)
![smile :)](/forums/images/smilies/smile9.gif)
Re: ERM
There's a function "UN:U" that searches for specific objects. It's much faster (especially when using the "fast syntax").Fly wrote:I'm from Russia so i'm very sorry for my english...![]()
I have a little qestion about ERM: i'm trying to do the script now and have a problem. The script:
This script should check for Castles and Ramparts existing. If this castles belong to player, the var should grow up in 1. But this script is too slow.
How i can to do script faster. Thanks...![]()
Code: Select all
!?FU22362;
!!VRv2750:S0; [Initialize v2750 to 0]
!!VRv2751:S0; [Initialize v2751 to 0]
!!OW:C?y1; [Current player: y1]
!!UN:U98/-1/?y2; [Count towns on map: y2]
!!VRv1:S-1; [Initialize v1 to -1 for fast UN:U searching]
!!DO22363/1/y2/1&y2>0:Py1; [Loop through all towns on map]
!?FU22363;
!!UN:U98/-1/-1/1; [Town coordinates in v1/v2/v3]
!!CAv1/v2/v3:T?y1 O?y2; [Town type: y1, Owner: y2]
!!VRv2750&y1=0/y2=x1:+1; [Add 1 to v2750 if it's a Castle and current player owns it]
!!VRv2751&y1=1/y2=x1:+1; [Add 1 to v2750 if it's a Rampart and current player owns it]
Who is online
Users browsing this forum: Semrush [Bot] and 1 guest