Advanced Scripting Level. Scripts explained

Scripts:
1. Creating a *Creature Bank*
2. Creating a magical singing rock
3. Level 8 Dwelling Placer
4. Display when mithril is picked up
5. Mithril Display


 
1. Script:  CREATING A *CREATURE BANK*
by AsPiN

Making your own object - it is easy with ERM. Create a Creature Bank of your own.
In this tutorial you will learn how to program empty objects to become Creature Banks.
In this script we will use:


flag 1 Here is stored information if Hero's artifact slot is occupied or not.
flag 11 Here is stored information about visitation of object. If Hero wins the battle the value will become positive.
z123 string Here is stored hint of the object.
v10 variable Here is stored number of Ogres to fight.
flag 10 The value becomes positive if Hero enters the shelter and fights wint Ogres.
v5 variable, v100 variable These two variables store Hero owner's color (Used to check if Hero wins the battle).

Initialization:
!#IF:V11/0; Set flag 11 to 0.
!#VRz123:S^Ogre Magi shelter (Not Visited)^; Store text in ^ ^ to z123 string.
!#OB52/5/0:Hz123; Set object's hint to z123 string (Note: 52/5/0 is coordinates of my object. You must use coordinates of yellow square of your object).
!#VRv10:S0T3; Here random value will be stored in v10 variable. The value can be: 0, 1, 2 or 3.
!#VRv10:+4; Here we add 4 to v10 variable.

!#VRv10:*3; Here v10 variable is multiplied by 3.

This is used to generate random number of Ogres. We can get 12, 15, 18 or 21 Ogres. The number is stored in v10 variable.

Main part:
!?OB52/5/0&11;
!!IF&11:M^Ogre Magi shelter^; If Hero has won the battle visitor will get message: "Ogre Magi shelter".
!?OB52/5/0&-11; If Hero enters the shelter and he haven't beaten Ogres this trigger is activated.
!!IF:Q10^This is Ogre Magi shelter. Do you want to enter?^; Hero must answer if he wants to fight or not. Answer is stored in flag 10.

!!HE-1&10:O?v5; Store owner's color's number in v5 variable.
!!HE-1&10:T52/5/0/91/v10; Provoke a battle with random number of Ogres, store in v10 variable. (Note: 52/5/0 is coordinates of my object. You must use coordinates of yellow square of your object for terrain bonuses).
!!HE-1&10:O?v100; Store owner's color's number in v100 variable.
!!HE-1&10/v5=v100:A1/10/3; Give Ogre's Club of Havoc to Hero.
!!HE-1&10/v5=v100/-1:A10; If slot is occupied store Ogre's Club of Havoc in Hero's backpack.

!!HE-1&10/v5=v100:A1/16/4; Give Targ of the Rampaging Ogre to Hero.
!!HE-1&10/v5=v100/-1:A16; If slot is occupied store Give Targ of the Rampaging Ogre in Hero's backpack.
!!IF&10/v5=v100:V11/1; If Hero survived set flag 11 to positive.
!!IF&11:Q1/8/10/8/16/1^You have won the battle with %V10 Ogre Magi and received:^; If Hero survived he will receive a message with pictures of artifacts he received.
!!VRz123&11:S^Ogre Magi shelter (Visited)^; If Hero survived store text in ^ ^ to z123 string.

!!OB52/5/0&11:Hz123; If Hero survived set object's hint to z123 string (Note: 52/5/0 is coordinates of my object. You must use coordinates of yellow square of your object).

Other notes:
At this time we cannot provoke a battle like in Creature Banks. The battle will be like with standalone monsters.

WoG *empty* objects have no properties and mapmaker can program it with ERM. The most part of them can be found in the WoG Heroes map editor in the Map Editor section of this html help.
{AsPiN}



 


2. Script:  CREATING A MAGICAL SINGING ROCK
Stay Enchanted {Fnord the Wizard}

In this example, we'll make a magical singing rock that can be visited by a hero. The rock will sing to the hero, give the hero spell points equal to (knowledge x 40) and will reduce his movement to zero for the remainder of the turn.

1. Use the editor to place a nice looking rock on the map where you want it. For our example, let's use x=10, y=12, level=0 (surface).

2. Create a timed event where you can put the ERM code. Change the event day to 500 (so it won't pop up like a normal event) and name it "Singing Rock". Start it off with a ZVSE instruction at the top.

3. Use an immediate instruction to make the rock square passable:
!#TR10/12/0:P1;

4. Use an immediate instruction to make the rock square a yellow trigger square:
!#TR10/12/0:E0;

5. Use an immediate instruction to turn the rock into another object (this is important!), say, a magic well:
!#OB10/12/0:T49;

6. Use an immediate instruction to *disable* the normal function of the (magic well) object: !#OB10/12/0:S;

7. Use an immediate instruction to change the right-click hint text of the new object:
!#VRz1:S^Singing Rock^; [assign text to string variable z1]
!#OB10/12/0:H1; [set right-click text to variable z1]

8. Use an object trigger, set for the location of the new object:
!?OB10/12/0;

9. Display a message:
!!IF:M^The rock entrances you for the rest of the day with a sweet and magical melody.^;

10. Set hero's spell points:
!!HE-1:Fd0/d0/d0/?v1; [assigns knowledge skill to v1 variable]
!!VRv1:*40; [multiply v1 by 40]
!!HE-1:Iv1; [set spell points to v1]
!!IF:Q1/35/v1/1^^; [Display picture of spell point bonus]

11. Reduce hero's movement to zero:
!!HE-1:W0;

And there you have it! :-)

If you don't include steps 5 and 6, you'll find that when you move the mouse to that square, it will change into the rearing horse (like a normal yellow trigger square) but when you move your hero to the square nothing will happen..*unless* you press the SPACEBAR to revisit the square. This is great if you want to make players work harder for something, but for a new object to work like a NORMAL object does, activating immediately upon entering the trigger square, you'll have to include steps 5 and 6.

Here's a summary of the code:

ZVSE
!#TR10/12/0:P1;
!#TR10/12/0:E0;
!#OB10/12/0:T49;
!#OB10/12/0:S;
!#VRz1:S^Singing Rock^;
!#OB10/12/0:H1;
!?OB10/12/0;
!!IF:M^The singing rock entrances you for the rest of the day with a sweet and magical melody.^;
!!HE-1:Fd0/d0/d0/?v1;
!!VRv1:*40;
!!HE-1:Iv1;
!!IF:Q1/35/v1/1^^;
!!HE-1:W0;


 


3. Script:  LEVEL 8 DWELLING PLACER
by Anders

 This example will place a level 8 dwelling at a chosen spot, as if  there were a red blob there. The dwelling will be linked to a chosen town.
 
 First, start with opening up the editor, and place a town (preferably  random), at x=2, Y=4, z=0(surface).
 
 Then, open up map properties and create the usual timed event, set the  date to a large number, name it "Level 8 Dwelling", or whatever you  like, and start with the normal ZVSE line.
 
 NOTE: This script will only use immediate instructions so that the dwelling will be present even before the player can see anything of the  map. Keep that in mind, since it wont be stated anymore.
 
 Now, start with check what subtype the town we want to connect the dwelling to is (all towns are the same type of object, but have different subtypes depending on their alignment. For example, Castle has the subtype 0, and Inferno 4) and store it into the v1 variable:
 !#OB2/4/0:U?v1;

 
 Then add 80 to that number to get the correct subtype of the dwelling:
  !#VRv1:+80;
 
 (You could make a list to store the correct number depending on the town type, like this:
 !#VRv1&v1=0:S80;
 !#VRv1&v1=1:S81;
 ...
 !#VRv1&v1=8:S88;
 but that's rather long and doesn't make any real difference in the end)
 
 Now, define where you want the dwelling to appear. Store the spot in variables, because different dwellings are of different size- you can see this if you open up the editor, place them next to each other and click on each once so the "frames" appears around them. In this example store the x location(27) in v2, the y location(3) in v3 and the level(0, or surface) in v4:
 !#VRv2:S27;
 !#VRv3:S3;
 !#VRv4:S0;
 
 Now you must compensate for the different sizes of dwellings. If it's NOT a Lord of Thunder(tower) or Antichrist(Inferno) dwelling, it should be placed one step further to the right in order for it to appear at the correct spot:
 !#VRv2&v1<>82/v1<>83:+1;

 
 Then, all that remains is to actually place the dwelling: 
 !#UN:Iv2/v3/v4/17/v1;
 
 The full script would thus be:
 
 ZVSE
 !#OB13/20/0:U?v1;
 !#VRv1:+80;
 !#VRv2:S27;
 !#VRv3:S3;
 !#VRv4:S0;
 !#VRv2&v1<>82/v1<>83:+1;
 !#UN:Iv2/v3/v4/17/v1;
 
 It can of course be repeated again and again if you want to link more dwellings to the map. If you want to link more than one dwelling to the same town, you only need to copy the last five lines and place them right after the rest, and then change the coordinates where it will appear. If you want to link a dwelling to another town, copy everything except the ZVSE part, and make sure to change the coordinates of both the town and dwelling.
 

 
 


4. Script:  DISPLAY WHEN MITHRIL IS PICKED UP
by Anders

 This script will make a dialogue box pop up whenever a human picks up a pile of Mithril on the map, showing how much Mithril it was in the pile and how much mithril that player has now.
 
  Start with placing some mithril bars on the map, then make the standard day 500 timed event with ZVSE in the beginning.
 
 Then you need to make sure that the Mithril piles act as Mithril and not gold. This should be done with an immediate instruction: 
 !#UN:B0/1;         
 
 Then, a trigger for all piles of Mithril, but not any other resource:
 !?OB79/7;
 
 Then check which hero it was that picked up the Mithril, and store the name in z1:
 !!HE-1:B0/?z1;
 
 Now, check how much Mithril there is in the pile(the script triggers before it is actually picked up and added to the total amount). Store it in y1: 
 !!ARv998/v999/v1000:V?y1;
 
 Now check how much Mithril the current colour has before it will pick up the pile, and add the amount there were in the pile to that:
 !!OW:R-1/7/?y2; [Store current player's previous total Mithril in v2]
 !!VRy2&-10:+y1; [Add new Mithril to previous Mithril - store in v2]
 
 Now, a few lines to have a correct grammar in the message- if the pile contained 1 bar, store " bar" in z2. Otherwise, store "bars". The same goes for total Mithril, but in z3. Then, if there were only 1 bar in
 the pile, z4 will store "a", otherwise, it'll store the total number:
 !!VRz2&y2=1:S^bar ^;
 !!VRz2&y2>1:S^bars ^;
 !!VRz3&y1=1:S^bar ^;
 !!VRz3&y1>1:S^bars ^;
 !!VRz4:S^%Y1^;
 !!VRz4&y1=1:S^a^;
 
 Now, all there is left to do is to display the full message, if the current player isn't AI controlled.
 !!IF1000:Q1/7/y1/1^{Mithril}
 
 %Z1 picks up %Z4 shimmering %Z3of magical Mithril.
 
 {You now have %Y2 %Z2of Mithril altogether.}^;
 
 And here's the full script:
 
 ZVSE
 !#UN:B0/1;
 !?OB79/7;
 !!HE-1:B0/?z1;
 !!ARv998/v999/v1000:V?y1;
 !!OW:R-1/7/?y2;
 !!VRy2&-10:+y1;
 !!VRz2&y2=1:S^bar ^;
 !!VRz2&y2>1:S^bars ^;
 !!VRz3&y1=1:S^bar ^;
 !!VRz3&y1>1:S^bars ^;
 !!VRz4:S^%Y1^;
 !!VRz4&y1=1:S^a^;
 
 !!IF1000:Q1/7/y1/1^{Mithril}
 
 %Z1 picks up %Z4 shimmering %Z3of magical Mithril.
 
 {You now have %Y2 %Z2of Mithril altogether.}^;
 


 


5. Script:  MITHRIL DISPLAY
by Anders

 This script will display the current player's total amount of Mithril when he right-clicks on the Kingdom Overview button.
 
 Start with the normal timed event with ZVSE. Then, a right-click trigger: 
 !?CM;
 
 Now, check where exactly the right-click was, and store it into y1:
 !!CM:I?y1;
 
 Then, we check who the current player is and how much Mithril he has:
 !!OW:C?y3; [Store number of current player in y3]
 !!OW:Ry3/7/?y2; [Store current player's Mithril in y2]
 
 Then the temporary z-1 variable should hold "bar." or "bars.", depending on how much Mithril the player had.
 !!VRz-1:S^bars.^;
 !!VRz-1&y2=1:S^bar.^;
 
 Now we check if the current player is the same that right-clicked (this is only for multiplayer).
 !!OW:Gy3/?y4;
 
 Now, if everything is correct, we display the message:
 !!IF&y1=3/y3=y4:Q1/7/y2/4^{Mithril}
 
 %Y2 shimmering %Z-1^;
 
 Then all that remains is to disabled the normal right-click message for the Kingdom overview button:
 !!CM&y1=3/y3=y4:R0;
 
 The full script is thus:
 
 ZVSE
 !?CM;
 !!CM:I?y1;
 !!OW:C?y3;
 !!OW:Ry3/7/?y2;
 !!VRz-1:S^bars.^;
 !!VRz-1&y2=1:S^bar.^;
 !!OW:Gy3/?y4;
 !!IF&y1=3/y3=y4:Q1/7/y2/4^{Mithril}
 
 %Y2 shimmering %Z-1^;
 !!CM&y1=3/y3=y4:R0;

 

 


Expert Scripting Level. Key information

1. Multiplayer (MP) and Synchronization
2. Instructions for multiplayer (MP) script supporting

3. Script Localization Suport

4. Secondary skills parameter table.
 

1. Multiplayer  MULTIPLAYER (MP) AND SYNCHRONISATION
(Slava)

Now if we have a MP battle at the defending side we have not !?BA0
and !?BA1 triggers but !?BA50 and !?BA51 instead.
  This brings almost no changes for:
- non MP battle goes as before !?BA0...!?BA1.
- H vs H battle goes this way:
    A           D
  !?BA0
    ---data--->
              !?BA50
  .....battle.....
    <---data---  (if defender wins)
  !?BA1       !?BA51

  !?BA51 is not needed actually except some cases for the control is
passed to the Attacker PC.
- AI vs H battle goes this way:
    A           D
  !?BA0
    ---data--->
              !?BA50
              battle
              !?BA51
    <---data---
  !?BA1

  You see that now we can synchronize many things on a battlefield.

  Then at attacker's side you can use !!HE# without any problem but as
I wrote at the defender's side we have copies of hero's and you cannot
control them with ordinary !!HE#. So I have added a specific syntax
for defender's side only(!)
  !!HE-10:... apply changes to the copy of attacker hero info
  !!HE-20:... apply changes to the copy of attacker hero info
  You can get hero's number but make all changes with this syntax.
  Once again. This works ONLY during a battle and only at defending
(non-active) side.

  Example. Let us set the attacking hero's attack skill to 3 and
increase an attack skill every battle turn by the current day value.
So if the battle takes place at day 2, he will have 5 at the first
round (3+2), 7 at the second (3+2+2), 9 at the third (3+2+2+2) and
so on.

  Our script:

!?BA0; [battle begins at attacker side]
!!HE-1:F3/d/d/d; [set attacker attack to 3]
  [NOTE that this need to be set only at attacker's side]
  [then Hero's statistics will be transferred to defender's side]
!!VRv9001:Sc; [set v9001 to a current day (just an example)]
  [v10 is a flag for us; if it is 1, this is the attacker's side]
  [if it is 0, this is the defender's side]
!!VRv10:S1;   [set v10 to 1 - attacker's side]

!?BA50; [battle begins at defender's side]
  [NOTE both heroes info is transferred here already]
  [also v9001...v10000 transferred here also]
!!VRv10:S0; [set v10 to 0 - defender's side]

  [now increase attacker hero's attack by v9001 every turn]
!?BR&v10=1; [this runs at attacker's side]
!!HE-1:Fdv9001/d/d/d; [set attack for hero -1 (attacker)]

!?BR&v10=0; [this run at defender's side]
!!HE-10:Fdv9001/d/d/d; [set attack for hero -10 (attacker)]

  Note that if you delete one of !?BR section, there will be a problem
for changes takes place at only one side.
  And then in this example you change just a Hero's statistics that
can be checked by right mouse click on him on the battlefield but the
changes are not applied to the army (this is just a simple example :-)

1. Multiplayer  INSTRUCTIONS FOR MULTIPLAYER (MP) SCRIPT SUPPORTING
(Slava)

1. There are two different ways when script may cause problems in a battle:
- Human attacks Human battle (through a network);
- AI attacks Human on another PC (a battle runs at that PC).
These two cases are different.
Let us see it.

2. Human (PCA) attacks a Human on other PC (PCD).

The sequence is the next:

1. PCA: a hero runs up to an enemy hero/town and attack.
2. PCA: !?BA0; trigger section runs.
3. PCA: !?IP0; trigger section runs.
4. PCA: data transferred to PCD side including:
- Attacking Defending Heros info (SoD);
- Both Heroes' Commanders info (WoG);
- Changed Monsters statistics (WoG);
- v9001...v10000 vars values (WoG).
5. PCA: goes to a battle screen.
6. PCD: Meantime the sent info arrived:
- Attacking Defending Hero info (SoD);

- Both Heroes' Commanders info (WoG);
- Changed Monsters statistics (WoG);
- v9001...v10000 vars values (WoG).
7. PCD: !?IP1; trigger section runs.
8. PCD: !?BA50; trigger section runs.
9. PCD: goes to a battle screen.
10. ***** Now the battle runs *****
If Attacker wins:
11. PCA: !?BA1; trigger section runs.
12. PCD: !?BA51; trigger section runs.
If Defender wins:
11. PCD: !?IP2; trigger section runs.
12. PCD: data transferred to PCA side including:

- Defending Hero only info (SoD);
- Defending Hero's Commander info (WoG);
- v9001...v10000 vars values (WoG).
13. PCD: !?BA51; trigger section runs.
14. PCA: Meantime the sent info arrived:
- Defending Hero only info (SoD);
- Defending Hero's Commander info (WoG);
- v9001...v10000 vars values (WoG).
15. PCA: !?IP3; trigger section runs.
16. PCA: !?BA1; trigger section runs.

This may look very complex, though, here is the sketch:

--------------------------------------
Attacker Defender
Human Human
--------------------------------------
!?BA0;
!?IP0;
---HA,CA,HD,CD,v9001-v10000-->
!?IP1;
!?BA50;
********** Battle *************
Win Lost
!?BA1; !?BA51;
--------------------------------------
or:
--------------------------------------
Attacker Defender

Human Human
--------------------------------------
!?BA0;
!?IP0;
---HA,CA,HD,CD,v9001-v10000-->
!?IP1;
!?BA50;
********** Battle *************
Lost Win
!?IP2;
<---HD,CD,v9001-v10000--------
!?IP3; !?BA51;
!?BA1;
--------------------------------------

2. AI (PCA) attacks a Human on other PC (PCD).

The sequence is the next:
1. PCA: an AI hero runs up to an enemy hero/town and attack.
2. PCA: !?BA0; trigger section runs.
3. PCA: !?IP0; trigger section runs.
4. PCA: data transferred to PCD side including:
- Attacking Defending Heros info (SoD);
- Both Heroes' Commanders info (WoG);
- Changed Monsters statistics (WoG);
- v9001...v10000 vars values (WoG).
5. PCA: goes to "wait until battle ends" screen.
6. PCD: Meantime the sent info arrived:

- Attacking Defending Hero info (SoD);
- Both Heroes' Commanders info (WoG);
- Changed Monsters statistics (WoG);
- v9001...v10000 vars values (WoG).
7. PCD: !?IP1; trigger section runs.
8. PCD: !?BA50; trigger section runs.
9. PCD: goes to a battle screen.
10. ***** Now the battle runs at PCD side only *****
No mater who wins:
11. PCD: !?BA51; trigger section runs.
12. PCD: !?IP0; trigger section runs.
13. PCD: data transferred to PCA side including:

- Attacking Defending Heros info (SoD);
- Both Heroes' Commanders info (WoG);
- Changed Monsters statistics (WoG);
- v9001...v10000 vars values (WoG).
14. PCA: Meantime the sent info arrived:
- Attacking Defending Heros info (SoD);
- Both Heroes' Commanders info (WoG);
- Changed Monsters statistics (WoG);
- v9001...v10000 vars values (WoG).
15. PCA: !?IP3; trigger section runs.
16. PCA: !?BA1; trigger section runs.

The sketch:
--------------------------------------
Attacker Defender
AI Human
--------------------------------------
!?BA0;
!?IP0;
---HA,CA,HD,CD,v9001-v10000-->
!?IP1;
!?BA50;
********** Battle *************
Win/Lost Win/Lost
!?BA51;
!?IP0;
<---HA,CA,HD,CD,v9001-v10000---

!?IP3;
!?BA1;
 


2. ERT-ifying  SCRIPT LOCALIZATION SUPPORT
(Slava)

I was asked to simplify a way to localize scripts.
The point is that if an author change something in his script, it takes
much time to check all script and change all massages to other language.
I was proposed to make a separate file for every script (optional) that
will keep all texts from the script.
Now you can make a file Script##.ert that has a specific format:
Index(integer) [tab delimiter] Text [tab delimiter] Any Comments ...
Two columns are obligatory, others - optional (Comments are not loaded
and saved to the game).
One line - one Item.
Index means an index that will be used in the script to access the text.
Index may be from 0 to 1000000.
If Index is 0 (or empty), the line is ignored and will not be loaded.
If Index is between 1 and 1000, the text will be automatically copied to
corresponding z variables at script loading (before executing any
instruction in the script).
So if you have the next line:
123[tab]This is a Text[tab]Any Comments
and in your script there is the next instruction:
!#IF:M1/z123;
you will see the message at load time "This is a Text"
This is the way to move your z vars initialisations out of the
script to the file.
It was:
!#VRz321:S^Hello, stranger!^;
...
Now you delete this line of the script and add a line to the ert file:
321[tab]Hello, stranger![tab]Start up message when a Hero enter to...
To get access to the text you should use the same way as for z vars but
the number is higher than 1000.
If you have in your script a z var that is used for storing a constant
name or text, you can free this z var and does not use it at all if you add
a line to the ert file with higher than 1000 number and change your code.
Then, if you have something like this:
!#IF:M^You are not ready yet.^;
you should change your script to something like this:
!#IF:M1/z123456;
and add a line to the ert file:
123456[tab]You are not ready yet.[tab]Any Comments
You cannot use this constant extra z vars for changing any default text
in the game (artifact name and so). This is the same limitation that is
used for local z vars (z-1...z-10). With one exception. You can use the
static extra z vars as a hint text in HT:T,P,Z,V, OB:H, HO:H. The only
restriction is that the index should be not higher than 32000 in this case.
You may compare constant extra z vars in & and | sections.
You can use a formatted string also:
3333[tab]Hello, %Z55555![tab]...
55555[tab]Orin[tab]...
You can include static extra z vars as %Z format item.
As for loading. ert file is loaded only if there is a corresponding erm
file and only if it is loaded correctly.
All extra static z vars are common for every ert file. So if you use
the same number in one or different ert files, you will have the
corresponding message and the map will not be loaded.
I recommend to divide the space of extra z vars the next vay:
Index 1000...10000 reserved yet
Index 10000...20000 (100 vars per script for hint purposes).
Script00 10000...10099,
Script01 10100...10199...
(index is 1##00 ... 1##99, where ## is a script number)
Index 20000...100000 reserved yet.
Index 100000...200000 (1000 vars per script for non-hint purposes).
Script00 100000...100999,
Script01 101000...101999,
(index is 1##000 ... 1##999, where ## is a script number)
 


3. Script Hazard  SECONDARY SKILLS PARAMETER TABLE
(Warning: Scripting Hazard: don't do  this at home)

The skill parameters are listed in a table and that by setting the skill to a value other than 0-3, the game will read the parameters of neighbouring skills.

Here is the table of skill level parameters used in the game (for skills that use a % value).
There are four values for each skill: 0-none, 1-basic 2-advanced, 3-expert
If you set a skill to a higher (or lower value) the game will look at what is next on the list.

i.e.  If Archery is set to skill level 7, the game will read the value in Offence level 3 and grant a 30% bonus.

The only problem is that this will cause the skill to display wrong in the hero screen or
crash.

One can use another skill's values with battle skills by applying an offset with a !?BA0 (pre-battle) trigger and removing it with a !?BG1 (post-action) trigger after checking for the end of the battle (with !!BU:C).
This avoids the display error and allows for normal skill advancement if you level up after a battle.



NOTE: * denotes the associated skill was guessed at by looking at the values and not actually tested.
 

1.
0 Necromancy
10
20
30
2.
0 ?
0
0
0
3.
 0 ?
0
0
0
4.
0 Archery
10
25
50
5.
0 Offence
10
20
30
6.
0 Armorer
5
10
15
7.
0 ?
0
0
0
8.
0 Eagle Eye*
40
50
60
9.
0 Diplomacy*
20
40
60
10.
0 Resistance
5
10
20
11.
0 Learning
5
10
15
12.
0 Logistics*
10
20
30
13.
0 Sorcery
5
10
15
14.
0 Intelligence*
25
50
100
15.
0 First Aid*
100
200
300
     
The rest doesn't seem to be part of the table but does contain a few usable values
16.
0 ?
0
0
0
17.
0 ?
0
0
0
18.
0 ?
0
0
0
19.
0 ?
0
105
5
20.
0 ?
0
0
0
21.
0 ?
0
0
0
22.
0 ?
0
0
0
23.
0 ?
0
0
30
24.
15 ?
90
150
0
25.
0 ?
0
0
0
26.
0 ?
0
25
50
27.
75 ?
100
100
100
28.
0 ?
0
0
0
29.
0 ?
0
0
0
 

This is as far as it has been tested, there may be more usable values.