New 3.59 ERM (Triggers, Receivers, Commands, corrections and changes) - February 14, 2006: Hard coded bug: The bug with Arrow Towers in MP mode: ************* Also Tower Experience may work incorrect (different damage) if: - it is the first day of a week; - you attack another human player who's turn is after yours. The problem appears because for you the enemy towers get experience bonus of a new week but for your opponent they did not yet. This may be fixed with hard coded changes only. ************* Should be fixed now. 1. Now OB:H,M now should not add an internal object if you use a check/get syntax. Now if you check/get a hint zvar with OB:H for an object that has no hint settings, it returns -1 (and do not add the object to the table). The easiest way to check the fix is to use !!OB...:H?$; in long cycle (say 100000 times). You should not get the message that there is no more room in the internal table. 2. If you use in the third parameter in HE:C0 any variable index -1 or -2 (in your case y-1 or y-2) it is interpreted as -1 and -2 (some old code left) and so works as an upgrade/downgrade syntax. So until it is fixed in the next EXE, you may not use a negative indexes of variables in HE:C0 command at a third place. Example: !!HE-1:C0/0/?y-1/?y-4; incorrect (assumed C0/0/-1...) !!HE-1:C0/0/?y-2/?y-4; incorrect (assumed C0/0/-2...) !!HE-1:C0/0/?y-3/?y-4; correct !!HE-1:C0/0/?y-4/?y-1; correct !!HE-1:C0/0/?y-4/?y-2; correct !!HE-1:C0/0/?y-4/?y-3; correct ************* Should work correct way now. 3. TP> Here's an example: TP> !!HE-1:C0/0/d/d/?y1/12; TP> I believe y1 returns stack 0's experience and not the rank, ************* Now if the modifier is >=10 and you use C0 get syntax to get the stack experience, it returns an experience level. 4. New receiver !!TL Turn Limit Control. Commands: E$ - turn "show left time always" ON(1) or OFF (0). If you turn it ON, it will shows seconds left always but not the latest 10 seconds as usual. C# - control turn time run(0) or pause(1) The latest command works. So you can call "pause it" 10 times but call "continue" one time and it will run. So no calling stack present. T#/$ - time routine # = 0, $ = current time in ms (get/set/check) # = 1, $ = current time in s (get/set/check) # = 2, $ = turn start time in ms (get/set/check) # = 3, $ = turn start time in s (get/set/check) # = 4, $ = pause start time in ms (get/set/check) # = 5, $ = pause start time in s (get/set/check) # = 6, $ = turn length time in ms (get/set/check) # = 7, $ = turn length time in s (get/set/check) Now how it works. When a player gets control, the current time is stored in "turn start time". Then every second the engine checks that: current_time - turn_start_time < turn_length If it is false, the turn ends. Now if you go to battle, the timer is paused. At this moment the current time is stored in "pause start time". Until "pause start time" is not 0, the turn will continue. Hint: to check if the turn paused or not, get "pause start time" and if it is 0, the timer runs but if it is 0, the timer is paused. When the timer continues (the battle is finished) "turn start time" is modified to reduce spent time for a length of the pause: turn_start_time = current_time - pause_start_time + turn_start_time and pause_start_time is set to 0. 5. Bug fixed with new -1/-2 method of UN:U where an ERM error occurred if objects were in the far corners of the surface or underground. 6. I disabled one call to avoid opening minimap to the first human hero before it gets a control. In original SoD first you can see the latest AI hero location and then it moves to a new human hero or town location. The problem is that now we have a lot of ERM executable code between these two events and it looks a bit incorrect that you can see the latest AI location. Now the first minimap update should not appear. 7. I fixed a check/get syntax for OB:M It may return nonsense value if there is no this object setting before. 8. OB:H returns now 0 for check/get syntax if this object was not set before. 9. I added a control over structure building sequence in towns. New command CD:B Syntax: B0/town/struct/ENdis - global enable/disable structure B1/town/struct/$/$ - build dependence B2/town/struct/#/#/#... - build dependence B3/town/struct/$/$ - exclusion dependence B4/town/struct/#/#/#... - exclusion dependence Details: B0/#1/#2/$; Enable/disable #2 structure to build in any towns of #1 type. $ - flag (0=disabled, 1=enabled). B1/#1/#2/$1/$2; #2 structure of town #1 dependencies. Every set bit in $1 (dword 0) or in $2 (dword 1) means that this structure may be build only when a structure represented by this bit is built. Example: $1=0x00000024 means that this structure may be build only when Magic Guild Lvl 3 and Tavern both built. B2/#1/#2/#3/#4/#5... Another way to set dependencies (you cannot check or get it with this command, use B1 for it). #2 structure of town #1 may be built only when #3, #4, #5...structures are built. B3/#1/#2/$1/$2; Exclusive structures. It has the same syntax as B1 but this command means that if this structure is built all dependent structures will be removed from the town screen. Usually it is used for a specific structures like upgraded dwellings (when you build then non-upgraded dwellings are removed) and Magic Guild. I do not think that this command is really important but added for any case. B4/#1/#2/#3/#4/#5... Another way to set dependencies like in B3. The syntax is similar to B2 command. You may use command as instructions. Example: !#CD:B2/0/0/30/31/37; Make Magic Guild Level1 in Castle depends on Dwelling 1, Dwelling 2 and upgraded Dwelling 1. Structures list. I checked the help and found incorrect format (Format U) in my version. Perhaps it is yet wrong. So here is the list: ******************************* ? - unknown for me. #d - index of dword in CD:B1 and CD:B3 #b - bit reference in dword #d # - index of structure + - upgraded version or version for upgraded dwelling support value in parenthesis is town type indexes #d-#b--------#--description 0 00000001 0 Magic Guild Lvl 1 0 00000002 1 Magic Guild Lvl 2 0 00000004 2 Magic Guild Lvl 3 0 00000008 3 Magic Guild Lvl 4 0 00000010 4 Magic Guild Lvl 5,?(6,7) 0 00000020 5 Tavern 0 00000040 6 Shipyard(0,4,7,8),?(1,2,3,5,6) 0 00000080 7 Fort 0 00000100 8 Citadel 0 00000200 9 Castle 0 00000400 10 Village 0 00000800 11 Town Hall 0 00001000 12 City Hall 0 00002000 13 Capitol 0 00004000 14 Marketplace 0 00008000 15 Resource Silo 0 00010000 16 Blacksmith 0 00020000 17 Lighthouse(0),Mystic Pond(1),Artifact Merchants(2,5,8),?(3),Cover of Darkness(4),Escape Tunnel (6),Cage of Warlords(7) 0 00040000 18 Griffin Bastion(0),Miner's Guild(1),Sculptor's Wings(2),Birthing Pools(3),Unearthed Graves(4),Mushroom Rings(5),Mess Hall(6),Captain's Quarters(7),Garden of Life(8) 0 00080000 19 Griffin Bastion+(0),Miner's Guild+(1),Sculptor's Wings+(2),Birthing Pools+(3),Unearthed Graves+(4),Mushroom Rings+(5),Mess Hall+(6),Captain's Quarters+(7),Garden of Life+(8) 0 00100000 20 ?(0,1,2,3,4,5,6,7,8) 0 00200000 21 Stables(0),Fountain of Fortune(1),Lookout Tower(2),Brimstone Storm clouds(3),Necromancy amplifier(4),Mana Vortex(5),Freelance Guild (6),Glyphs of Fear(7),Magic University(8) 0 00400000 22 Brotherhood of the Sword(0),Treasure(1),Library(2),Castle Gate(3),Skeleton Transformer(4),Portal of Summoning(5),Ballista Yard(6),Blood Obelisk(7),?(8) 0 00800000 23 ?(0,1,4,7,8),Wall of Knowledge(2),Order of Fire(3),Battle Scholar Academy(5),Hall of Valhalla(6) 0 01000000 24 ?(0,2,4,5,6,7,8),Dendroid Saplings(1),Cages(3) 0 02000000 25 ?(0,2,4,5,6,7,8),Dendroid Saplings+(1),Cages+(3) 0 04000000 26 Grail 0 08000000 27 ?(x) 0 10000000 28 ?(x) 0 20000000 29 ?(x) 0 40000000 30 Dwelling 1 0 80000000 31 Dwelling 2 1 00000001 32 Dwelling 3 1 00000002 33 Dwelling 4 1 00000004 34 Dwelling 5 1 00000008 35 Dwelling 6 1 00000010 36 Dwelling 7 1 00000020 37 Dwelling 1+ 1 00000040 38 Dwelling 2+ 1 00000080 39 Dwelling 3+ 1 00000100 40 Dwelling 4+ 1 00000200 41 Dwelling 5+ 1 00000400 42 Dwelling 6+ 1 00000800 43 Dwelling 7+ ******************************* The internal structure keeps a two 32 bit values (that you can set or get with B1 command) and ever y bit there means one structure. Then if the bit is set, the structure may be built only after that structure (that bit is set). If the bit is 0, there is not dependence. So all mentioned in B2 structure bits are set to 1. Others are set to 0. If you want to modify the existing sequence, you need to use B1/?$/?$ syntax to get values, set or remove bits that you want and use B1/$/$ to set it back. Also, if you make this structure depends on X structure and X structure in its turn depends on Y structure, so this structure will depends not only on X but also on Y structure and you need not to set Y structure in the command. To reset all dependencies you need to use an "empty" syntax like this: !!CD:B2/town/struct; You see there is no parameters and thus all will be reset to 0, so the structure does not depend on any other structure. Then, perhaps, it was not clear but you can use up to 14 dependencies. The syntax keeps ... that means that you can more parameters like this: !!CD:B2/0/10/20/15/26/11/4/2/8; 10. New command. !!IF:L - add a string to a screen log. Syntax: !!IF:L^Message^; - direct !!IF:L$; - Z variable. You may use standard Z vars (z1...z1000), local z vars (z-1...z-10) and static z vars (Z1001...) Comment. It looks as though you press Tab, type a message and press Enter. The message pops up a previous message. You have up to 20 message on the screen. Every message stays on the screen for 20 seconds. It may work at adventure screen and in a battle. When you go to a battle or from a battle, the message should left on the screen. 11. New trigger. !?TL#; timer call # = 0 - period of call 1 second # = 1 - period of call 2 seconds # = 2 - period of call 5 seconds # = 3 - period of call 10 seconds # = 4 - period of call 60 seconds Timer is periodically called. Comment. To see how it works, you can use the next ERM code: !?TL0; !!IF:L^Tick 1 sec^; !?TL1; !!IF:L^Tick 2 sec^; !?TL2; !!IF:L^Tick 5 sec^; !?TL3; !!IF:L^Tick 10 sec^; !?TL4; !!IF:L^Tick 60 sec^; 12. Now you have if-else-endif functionality. To start IF section use the next receiver/instruction: !!if&condition:; Note that 'if' is in lower case. Condition is a standard AND and OR condition that you use now in any receiver. If during a script execution the condition evaluation is TRUE, the followed section is executed. If it is FALSE, the followed section is skipped until ELSE section begins or ENDIF found. Note that the ELSE section is optional and the ELSE part only occurs if the original IF condition is false. To start ELSE section use the next receiver/instruction: !!el:; 'el' is in lower case. No condition is evaluated even if present so this is unconditionally executed (if the original IF condition is false). ELSE section always expects IF part and linked to the latest found in the script IF. To end IF or IF-ELSE section use the next receiver/instruction: !!en:; 'en' is in lower case. No condition is evaluated even if present so this is unconditionally executed. ENDIF section always expects IF part or IF_ELSE part and linked to the latest found in the script IF or IF-ELSE. You may use included IF-ELSE-ENDIF sections but not deeper than 10 levels. Every trigger (and thus function) has its own set of IF-ELSE-ENDIF and so may have up to 10 levels of included IF-ELSE-ENDIF. When you call a function the caller IF-ELSE-ENDIF state stays active, so when you are back the local IF-ELSE-ENDIF set is used again (a similar way as local function variables). Example: ZVSE !?HM-1; !!VRv10:S5; !!if&v10=5:; !!IF:M^First IF^; !!VRv10:S10; !!if&v10<>10:; !!IF:M^Second IF^; !!el:; !!IF:M^Second ELSE^; !!en:; !!IF:M^Second IF finished^; !!el:; !!IF:M^First ELSE^; !!VRv10:S99; !!if&v10=99:; !!IF:M^Third IF^; !!el:; !!IF:M^Third ELSE^; !!en:; !!IF:M^Third IF finished^; !!en:; !!IF:M^First IF finished^; You should see the next messages: First IF Second ELSE Second IF finished First IF finished 13. The ERM parser searches for a specific sequences like !?,!#,!!. So if you use something like this: "!!!!!!!!!!!!!!!!", it loads the parser with extra work. To help script writers avoid this problem, an error check has been added that will alert you to these sequences so you can remove them. 14. New command HE:R7/$. In most cases, setting or clearing these bits won't change Luck, Morale, movement or spell points--they only set (or clear) the record of whether the hero has already visited a given type of structure in a given period, e.g., this week, for next battle, etc. However, it will set or clear any text associated with these structure if you click on the hero's Luck or Morale in the hero screen (e.g., "Temple Visited +1"), but you'll still have to set the hero's temporary Luck or Morale with the HE:R0 and HE:R1 commands. $ - modifiers word. Bits: 00000001 = 1 MAGIC WELL 00000002 = 2 stable 00000004 = 4 BOUY 00000008 = 8 swan pond 00000010 = 16 IDOL OF FORTUNE (DAY 1-6) 00000020 = 32 fountain of fortune (-1 LUCK) 00000040 = 64 WATERING HOLE 00000080 = 128 oasis 00000100 = 256 TEMPLE (DAY 1-6) 00000200 = 512 SHIPWRECK 00000400 = 1024 CRYPT 00000800 = 2048 DERELICT SHIP 00001000 = 4096 PYRAMID 00002000 = 8192 faerie ring 00004000 = 16384 FOUNTAIN OF YOUTH 00008000 = 32768 MERMAID 00010000 = 65536 RALLY FLAG 00020000 = 131072 ? (NO IDEA) 00040000 = 262144 in a boat (ONLY SET THIS IF HERO IS ON WATER OR IT CRASHES) 00080000 = 524288 ? (NO IDEA) 00100000 = 1048576 SIRENS 00200000 = 2097152 Warrior's Tomb 00400000 = 4194304 Maximum Luck (the same as HE:R6) 00800000 = 8388608 Maximum Moral (the same as HE:R5) 01000000 = 16772216 WOGSHADOWFAX (THIS RESETS MOVE TO ONE MILLION EACH TURN) 02000000 = 33554432 IDOL OF FORTUNE (DAY 7) 04000000 = 67108864 TEMPLE (DAY 7) 08000000 = 134217728 +1 LUCK FOUNTAIN OF FORTUNE 10000000 = 268435456 +2 LUCK FOUNTAIN OF FORTUNE 20000000 = 536870912 +3 LUCK FOUNTAIN OF FORTUNE 38000000 = 939524096 mask for a type of fountain of fortune (Total of the three above equals 939524096) Slava writes; I think it is correct for THIS current day. If you set a "affect a few days" like a Stable, I think the effect will be applied automatically on every next day until the effect ends up. 15. Now we have a new receiver/instruction DL. Syntax: !!DL#:... # - unique dialog Id (>0) Commands: N,S,E,H,C N# - parse dialog template # - template file name May be: ^filename^ - direct text z10 - global Z var z-5 - local Z var z100000 - static Z var The text is parsed before using. This command load template file (if not loaded already), searches the dialog (using dialog Id) in the file and parses it. It does not show the dialog. The main aim of it is to give you a chance to adjust loaded dialog settings before showing it. Results: Flag 1 = 1 if Ok Flag 1 = 0 if Error happens (no dialog template found) S$ - show dialog $ - return item (the active item when closed) Shows the dialog (with a specific Id) and wait until it is closed. This means that the followed command will be executed not immediately but when the dialog is closed by any means. You may use no parameter at all, it means that return code is ignored. E#1/#2 #1 - dialog Item Id (see below) #2 - enable (1) or disable (0) it H#1/#2 #1 - dialog Item Id (see below) #2 - hint text (appear when you move a mouse over the item) May be: z10 - global Z var z100000 - static Z var The text is parsed before showing (not setting). C# - set a specific callback action. # - type of action (will be extended) 1 - close dialog with current item return code For this command you need not to set a dialog Id in DL trigger part. It affect the active dialog and any item. Example: !!DL:C1; - close dialog A new trigger is added to control callback actions !?DL. It is called when a mouse and keyboard (not supported yet) action is taken at any dialog item. Syntax: !?DL...; When the trigger is called the next vars are set: v998 = Dialog Id v999 = Item Id v1000 = action Action for now: 12 - left mouse button push 13 - left mouse button release 14 - right mouse button push Also to simplify right mouse button info dialog, I extended a bit IF:M command. Now it may have three parameters: IF:M$/#1/#2 $ - variable to receive a reply item #1 - type of the dialog: = 1 - standard Ok = 2 - question Yes/No = 4 - right mouse click info = 7 - choice from two options (not supported yet) = 10- choice from two options with escape (not supported yet) Notes: # means that only set syntax may be used (direct value or variable) $ means that set/check/get syntax may be used You may show one dialog "from another" and the sequence may be unlimited but you may have only ONE dialog of the same type on the screen at the same moment. This means that you cannot call a dialog X from dialog X. Now the template layout. This is a standard Heroes 3 text table file. First two lines are ignored (may be filled with text or left empty) The most left column is also ignored (may be filled with text or left empty). The dialog starts with the next line items (in column order): 0: ignored 1: '#' sign - means new dialog template starts 2: xxx number - unique dialog Id 3: x pos number - X position of left top corner (-1=auto center) 4: y pos number - Y position of left top corner (-1=auto center) 5: dx number - hor. size of dialog 6: dy number - ver. size of dialog 7: xxx number - number of dialog items (you may have less but not more) 8: xxx number - player to adjust border color (-1 means current player) 9: text - background PCX file name 10: XXX number - Id of text item that is used as hint field Following lines are parsed as dialog items until the next '#' sign in the 1st column is found. This may be just an empty line with '#' sign or a line with a new dialog start. The most important thing is the first character in the first column. The next character is supported for now: ';' commented line - skipped 'P' - PCX picture item 'D' - DEF cadre picture item 'A' - Animated DEF item 'B' - Button item (specific DEF) 'T' - Text item 'S' - Text with vertical scroll bar item 'E' - Edited text item 'V' - SMK or BIK video item 'P' - PCX picture item columns: 0: ignored 1: 'P'... 2: xxx number - unique item Id 3: x pos number - X position in dialog of left top corner 4: y pos number - Y position in dialog of left top corner 5: dx number - hor. size of item 6: dy number - ver. size of item 7: text - PCX file name 8: flags - a specific value (not known completely yet) 'D' - DEF cadre picture item columns: 0: ignored 1: 'D'... 2: xxx number - unique item Id 3: x pos number - X position in dialog of left top corner 4: y pos number - Y position in dialog of left top corner 5: dx number - hor. size of item 6: dy number - ver. size of item 7: text - DEF file name 8: cadre - an image inside of DEF to show 9: flags - a specific value (not known completely yet) 'A' - Animated DEF item columns: not supported yet 'B' - Button item (specific DEF) 0: ignored 1: 'B'... 2: xxx number - unique item Id 3: x pos number - X position in dialog of left top corner 4: y pos number - Y position in dialog of left top corner 5: dx number - hor. size of item 6: dy number - ver. size of item 7: text - DEF file name 8: flags - a specific value (not known completely yet) 'T' - Text item columns: 0: ignored 1: 'T'... 2: xxx number - unique item Id 3: x pos number - X position in dialog of left top corner 4: y pos number - Y position in dialog of left top corner 5: dx number - hor. size of item 6: dy number - ver. size of item 7: text - text (may be empty and set later) 8: font - name of font file to show 9: color - color of text 10: bkcol - background text color 11: align - text align 12: flags - a specific value (not known completely yet) 'S' - Text with vertical scroll bar item columns: 0: ignored 1: 'S'... 2: xxx number - unique item Id 3: x pos number - X position in dialog of left top corner 4: y pos number - Y position in dialog of left top corner 5: dx number - hor. size of item 6: dy number - ver. size of item 7: text - text (may be empty and set later) 8: font - name of font file to show 9: color - color of text 10: col2 - color of scrollbar 11: align - text align 'E' - Edited text item columns: 0: ignored 1: 'E'... 2: xxx number - unique item Id 3: x pos number - X position in dialog of left top corner 4: y pos number - Y position in dialog of left top corner 5: dx number - hor. size of item 6: dy number - ver. size of item 7: text - text (may be empty and set later) 8: font - name of font file to show 'V' - SMK or BIK video item columns: 0: ignored 1: 'V'... 2: xxx number - unique item Id 3: x pos number - X position in dialog of left top corner 4: y pos number - Y position in dialog of left top corner Video item is shown over any other existing items, has no hint support. It should not go out of a dialog border or you will have problems with redrawing. Also you may have only one video per dialog. Notes: You may have more than one dialog in one template file. You may not use dialogs with identical Id in different template files, every dialog should have its own unique Id. This in particular means that we should reserve an Id range for WoG dialogs. Item with number 30721 is a default cancel item. So if a user press ESC button when a dialog is shown, it is closed. Now an example. Make a test map and put there the next ERM code: *********** ZVSE !?CM0; !!CM:R0; !!VRz-1:S^12345.txt^; !!DL666:Nz-1S?v1; !!IF:M^Dlg Closed, return item is %V1^; !?DL&v998=666/v999=49/v1000=14; !!IF:M0/4/^Right Mouse Pop Up Text for Item number 49^; !?DL&v998=666/v999=30722/v1000=14; !!IF:M0/4/^Right Mouse Pop Up Text for Item number 30722^; !?DL&v998=666/v999=35/v1000=13; !!DL:C1; *********** Now at any right mouse click at adventure screen you will see a customized dialog. You need to put to DATA folder the attached 12345.txt file with a dialog template. You see that a pop up hint dialog appear when you use right mouse click on a gold icon or "buy boat" button. Also a dialog is closed when you release left mouse button over a picture with a water surface. 16. New item commands for DL:A They may be called in !?DL trigger and so may be used to customize the dialog on a fly. - set text for text item cmd = 3, par = Z var with text example: !!VRz-5:S^Set New Text^; !!DL666:A22/3/z-5; - set PCX picture for picture item cmd = 11, par = Z var with text !!VRz-5:S^newpcx.pcx^; !!DL666:A33/11/z-5; - set displayed cadre in DEF cmd = 4, par = cadre !!DL666:A49/4/5; 17. New UN:J11 command (instruction or receiver) UN:J11/$ $ is a flag that allows to stay on a battle screen a right mouse click stack info dialog (0, default) or work a standard way like in SoD (1). This flag is stored in saved game, so you can set it once per a game. 18. MP ERM fix. When !?GM0 is called (load saved game) in MP game (network based or hot seat one) on a server side, the "player(s) at this PC" was not set properly. Now fixed. NOTE: The saved game format is modified, so you cannot load a saved with previous T1 game. 19. ERM Spell Control Now you have ERM access to Spell parameters. Receiver SS (may be used in instruction). SS# where # is a number of a spell (the left column in the attached spells.txt file). Commands: O$ - set/check/get a spell type: -1 = target is an enemy stack 1 = target is a friendly stack 0 = no direct target W$ - sound file name like "Visions.wav". The file should be in Heroes3.snd or in DATA folder directly. You may not get the default file name now but you can set it (and check later) through z vars. You may use a standard Z vars [1...1000] or a static Z vars from ERT file [>1000]. If you set the name and then check it, you will receive an index of Z var you set the name. If you did not set the name, you will get 0. X$ - DEF animation index. You may get the default index in the attached spells.txt. Now you can only change it to another existing one but later I will add a way to use a custom DEF file. F$ - spell flags. The default flags are in spells.txt file but I do not know all of them. N$ - name of a spell. Works similar to W$ way with Z var. A$ - abbreviation name. Works similar to W$ way with Z var. L$ - spell level (0...4) S$ - magic school bits (Air=1,Fire=2,Water=4,Earth=8) C#/$ - mana cost to cast at a skill level. # - skill level (0...3) $ - mana points P$ - spell power. May mean different things for spells. E#/$ - spell effect at a skill level # - skill level (0...3) $ - effect H#/$ - chance to get a spell by a town type # - town type (0...8) $ - chance (0...100) I#/$ - AI value. # - skill level (0...3) $ - value for AI to choose this spell D#/$ - description of a spell at a skill level # - skill level (0...3) $ - Z var index. Works similar to W$ way. All settings are stored in a saved game and thus you may script your spells for a particular map. Also I reserved spells for WoG up to 200. This is why you need to expand Sptraits.txt file or game will not start. I have attached a modified file. You may put it to the DATA folder. Example: *************** !#VRz123:S^New Spell Name^; !#VRz125:S^New {Spell} Description Basic^; !#SS15:Nz123 D0/z125; set new name to magic arrow *************** Set a Magic Arrow name and description for a basic skill level to custom. Also you may check how it work if start the attached map, go to town and check a magic arrow spell in a Magic Guild. 20. I added a way to simulate an adventure map spells. I think it is better to describe with an example: *************** [the object to activate the spell, only for example] !?OB8/11/0; [show the message] !!IF:M^Now move a mouse over enemy hero and click left mouse button to "sunk" them. Use right mouse click to finish^; [call the magic dialog] [12345 is a callback function number] !!DL:P12345; [since now you can move a mouse over a map and when you go to] [the next square a function 12345 will be called] [here you come only when the spell is finished] [show the message though you may take any other action] !!IF:M^Now spell has ended^; [callback function] [called at any click or move to another square] [on the entrance we have] [x1=action:] [ 0 - mouse move to another square] [ 12 - left mouse button push] [ 13 - left mouse button release] [ 14 - right mouse button push] [x2=x coordinate of a map square] [x3=y coordinate of a map square] [x4=level of a map square] !?FU12345; !!if&x1=0:; mouse move !!OBx2/x3/x4:T?y1; get object type at a square !!if&y1=34:; hero ? [you may use now DL:C command to set a mouse cursor for a dialog] !!DL:C1042; sunk boat cursor !!el:; !!DL:C1000; arrow cursor !!en:; !!FU:E; !!en:; !!if&x1=13:; left mouse release !!OBx2/x3/x4:T?y1 C?y2; !!if&y1=34:; hero !!HEy2:K; kill hero !!DL:C1000; arrow cursor !!en:; !!FU:E; !!en:; !!if&x1=14:; right mouse push !!DL:C1; !!en:; *************** You may see how it works on the attached map if try to pick up a pile of gold. Move then your mouse over enemy heros, left click to kill them and right click to end the spell. I hope that this example is detailed enough but ask me if you need more info. 1. Extended WoGification scripts support. I used Timothy's instruction: ******************** 1. A script named "library.erm" is always the FIRST wogify script to be loaded. This script would contain all scripted library functions (moved from script00.erm and other places) as well as global macros, etc. 2. A script named "wogify.erm" is always the SECOND wogify script to be loaded. This script would contain all code that must be loaded before most other code (aside from library functions) but that isn't specifically "wogification" code from script00.erm. In other words, all the miscellaneous bits and pieces need to occur but have nothing specifically to do with the wogification replacement of objects, etc. Alternatively, we could choose to move the wogification replacement code here, but anyway, that decision can be made later and won't affect the loading sequence. 3. All scripts named script00.erm through script99.erm load next (in order) as now. 4. All script named script100.erm through script999.erm load next (in order). 5. All custom scripts named custom00.erm through custom99.erm scripts load next, in alphabetical order. (Or optionally, you could use three numbers here too and go up to custom999.erm.) Of course, this ONLY applies to scripts in the Data\s folder. Scripts in the Maps folder would work the same as always (loading only if they matched a map name exactly). ******************** So first is loaded "alib.erm" and "alib.ert". Then "awogify.erm" and "awogify.ert". Then "script000.erm"..."script999.erm" and corresponding ert files. Then "wcustom00.erm"..."wcustom99.erm" and corresponding ert files. I used this order to keep them appear in the folder in alphabetical sequence as mentioned here. NOTE that now you must rename all "script##.erm" and "script##.ert" to "script0##.erm" and "script0##.ert". Otherwise the scripts will be not loaded. If any of these files are not present, they are just skipped without notice. Loading from alternative location is supported the same way as for 3.58f. Timothy also wrote: ******************** If you recall, I also asked if we could optionally specify which scripts should be loaded into memory through the wog.ini file, to make it easier to load only a custom range of scripts for testing or MP games, etc. ******************** The first draft is the next one. If you do not want for a particular script to be loaded, put the next line in the WOG.INI in [WoGification] section: alib = $ awogify = $ script### = $ wcustom## = $ where ### - script index and $=0 to load and $!=0 (say 1) to do NOT load. If there is no line, assumed $=0 (load the script). So to disable loading of script 345, put the next line: script345 = 1 Do not tested. 2. Now I added a way to have up to 100 local functions per script. The syntax is the same as for calling a global function but the index is negative like this. !?FU-5; start local function -5 ... !!FU-5:P...; call a local function -5 Index may be from -1 to -100. The difference between global and local functions is the scope. Local function is searched ONLY in the current (where the call found) script body. This means that you may have function -5 in many scripts but when the call is executed only functions -5 in the calling script will be executed. Also it gives a specific functionality. Say you have two scripts: 23 and 456. Script 23 has: !?FU-34; #1 ... !?FU657; !!FU-34:P...; ... !?FU-34; #2 ... Script 456 has: !?FU-34; #3 ... !?TM6; !!FU-34:P...; !!FU657:P...; ... !?FU-34; #4 ... Now say timer 6 executed. The ERM interpreter will find a trigger body (!?TM6) in the script 456. So first !?TM6 section is executed. Call to FU-34 will execute function #3 and then #4 because both of them are located in the script that call is executed (script 456). Then call to FU657 will move the current call scope to the script 23 because the body of the global function 657 is located there. So now call to FU-34 will execute functions #1 and #2. This means that all local functions are independent and may be cross referenced only through the global function calls. Not tested. 3. HE:A1/... fix. Now commands like: !!HE-1:A1/?y-2/y-1; [Check for weekly creature artifacts] will not produce an error message. 4. 3.58f bug fix. Minotaur King now should have positive moral always. 5. The last T1 bug fix. Crash on day 8 should not appear again. February 14, 2006 t1.exe 1. TP> Also, I would prefer the name "alibrary.erm" instead of TP> "alib.erm" if that's possible. I think it will be more obvious TP> with the full word. alibrary.erm now. 2. TP> The alib.erm and awogify.erm scripts NOT appear to load during WoGification. Check it now. 3. TP> Then when I went to make an actual script, I named it TP> wcustom01.erm and it didn't load. TP> I renamed it wcustom08.erm and it still didn't load. TP> Then I renamed it wcustom48.erm and it did load. Should work now. 4. Also wcustom##.erm and wcustom##.ers now should be located in the "custom" subfolder. So if we have the standard scripts at "DATA\S", so custom scripts should be here: "DATA\S\custom". If you use an alternative script location like here "alternate", so the standard scripts are located here: "alternate" and custom scripts are here: "alternate\custom". 5. TP> I think the best solution would be if ers files DO work for TP> all scripts but only if there's no script number entry in the TP> zsetup01.txt file for them. If there is an entry, the TP> corresponding ers file would be skipped. I don't know if that's TP> possible though. Now ers files should work for custom and standard scripts and no other limitations. So if there is an ers file, it will be loaded no matter what is written in zsetup01.txt file. 6. TP> One final comment about ers files. You may recall we had a TP> request to let them support more than one option number for a TP> single script (which means more than one line). Is this possible TP> to add? Should work correct. Just add another line with another option. 7. New command UN:J12 - get map file name. Syntax: !!UN:J12/z#; z# - z var to store the name (z-1...z-10, z1...z1000) Comments If you want to use a different INI file for different map, you may now check the map name. 8. Local function should work Ok now always. Hope that I have fixed the only bug that I found myself. 9. Now you can load and unload custom LOD files. First. We will have "h3wog.lod" file in DATA folder and I am going to move all WoG related files there. Then there will be "h3custom.lod" file also located in DATA folder. These two LODs will be loaded in any case (if they are present). To use any other LOD file (in WoGification script or in a specific map) use the next commands: !!LD:L?$1/$2/$3 - load a custom LOD file $1 - a variable to store index of the loaded LOD file (>=0) or -1 if mot loaded. $2 - a location folder for the file like in UN:J9. $3 - an index of Z variable that stores a name of the LOD file (may be local, global or static Z variable). !!LD:U$ - unload a custom LOD file $1 - a variable keeps an index of the loaded LOD file (>=0). Comments. Custom LOD file must have at least one text file: "filelist.txt" This file is an ordinary TXT file (as a table) with one column like this: filelist.txt aishield.pcx No comments or so. In general in this table you should add all your files that this LOD keeps. This is the simplest way. Though actually not all files should be there just those that are standard SoD file that you want to replace. If you do not add a file in the table, the WoG engine will not unload the resource that you want to replace and thus even if you load your LOD file successfully, no changes appear. So I repeat that the simplest way just to keep a complete list of all files in this LOD. Loaded LOD files will be unloaded if you start a new game or load a save. The list of loaded LOD files is stored in the saved game and thus all of them will be uploaded again if you load this save. This means that if the map uses a custom LOD file, you should have it if you want to load a saved game for this map. This also means that LODs are not stored in the saved game and it takes only a few bytes there :-) You can use a several load/unload sequence in one game. Say you can use a different environment for the adventure map, dialogs or anything else. Note though that standard TXT files (like crtraits.txt and so) in game are parsed at game start. so even if you modify it, it does not affect the game until you use "h3wog.lod" or "h3custom.lod". These two files are loaded at game start. Example. !#VRz35:S^my.lod^; !#LD:L?v3/2/35; This will load my.lod file from MAPS folder. 10. Horn asked me to supply some additional temporal variable set for a battle. I added an array that is not stored in the saved game. Get/Set variable: !!BG:V$1/$2/$3; $1 - stack index (0...99) $2 - variable index (0...99) $3 - variable to set/get the value Clean up the array: !!BG:C$; $ - stack to clean up (0...99) or -1 to clean up the whole array. Comments. You may keep there any integer value. It does not matter either a real stack is present in the battle or not. Example: !!BG:C-1; clean up the array !!BG:V2/3/33; set var 3 for "stack" 2 to 33 !!BG:V2/3/?v5; get this var to v5 11. Jake Hunter reported (long ago already :-) JH> the command '!!HE-1:L4/$' which is meant to re-set the portraits to a JH> specific hero-number, does what it is said to do, yet, if one were to save JH> the game after change a hero's portrait (like with my script that I sent JH> you) and reload it afterwards, the portrait gets screwed up. I found the bug and hope that it works now correct (I ran a quick test).