Warhammer Dark Omen Forum

Warhammer Dark Omen => Singleplayer => Topic started by: cuthalion on March 05, 2012, 12:03:54 PM



Title: Enemy units in Campaign
Post by: cuthalion on March 05, 2012, 12:03:54 PM
Hi,

I played around with enemy units in pbat1 and figured out a few things:

1. If I change an infantry unit with archers, archers won't shoot but will only charge my units in melee.
2. If I change enemy artillery with archers, they won't shoot at all but will only sit at one place till I come and take them.
3. Some of the things don't work like: Substituting necromancer to bright wizard will halt the game once he's about to cast a spell.
A few others.

Is it all avoidable?
And are there other ways to vary enemy behaviour except for substituting units with the units of the same type but other nature? I don't mention altering unit quantity.


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 05, 2012, 12:17:21 PM
Looking through the forum, I found a few places where ppl discuss computer AI on the battle field.

I like that someone managed to change enemy starting points. I will play with it when I have more time for Dark Omen the next month.
Is it possible to add units to the list of enemies and then place them and give them AI instructions?

Thus far I only figured out, if I add a unit, and I set it the number of one of the existing enemy units on that missions, both default and "my" unit appear at a place and further on both attack me. I wonder if there are bugs about it...


Title: Re: Enemy units in Campaign
Post by: Ghabry on March 05, 2012, 06:46:36 PM
Hello, the only released mod that alters the enemy behaviour is Rise of the Dead (http://forum.dark-omen.org/campaigns/campaign-rotd-rise-of-the-dead-t614.0.html). But this does not change the script files but uses script files from different maps. So it's possible to get random crashes during the battle. I don't really know why, but often it works without any problems :D

I'm not sure if the tool was ever released, but the tool we use for editing the map scripts is called ctldis:
[attachment=1]

You have to install Python 2 (http://python.org/download/) (not 3!) to run it.
But at first open ctldis.py with a text editor
Change base_name = "b101" to the name of the ctl file (without extension).
Create a copy of the ctl-file you want to edit. The name must be b101_orig.ctl (= add _orig to the filename).
 
MODE = 0 # 0 == assemble, 1 == disassemble must be set to 1 if you want to dissasemble the ctl to a text-scriptfile. You must do this once to get a b101.txt. Now you can alter the txt-file and assemble the txt to ctl again by setting mode to 0.

Some information about CTL can find found in the wiki (http://wiki.dark-omen.org/do/DO/CTL) (see also the subpages listed in the box to the right). Our investigations on CTL-Scripts were never finished because we couldn't guess what most of the script commands are doing (even not by try and error). Feel free to experiment with them.

You will also need the tool BTB Edit (http://en.dark-omen.org/downloads/view-details/1.-modding-tools/1.-map-editor/btb-editor.html).
When you open the b101.txt you will see functions. All regiments start with the function defined by the value in <13> in their deployment zone circle. All regions are defined in <6000> in the BTB Editor. The deployment zones are assigned via the Unit Id (check in Wh32Edit), you can find the Id in <12>. <13> is the number of the script function that gets executed on start. Human controlled regiments always execute func 100 (can be altered), in multiplayer all regiments always execute func 100, <13> is ignored.

It's also possible to alter the script that is executed between the missions. It's a complete different script language and the script is hardcoded in engrel.exe. Their is currently no tool to alter it but you can find information in the wiki again (http://wiki.dark-omen.org/do/DO/WHMTG). All function names are available because the developers were so kind to put a string table containing all function names from WHMTG in the executable ;) (but none for CTL)

The last time I looked at CTL and WHMTG is already many months ago. Most work was actually done by other members but most of them are not around anymore. Feel free to ask me any questions about CTL or WHMTG and if you found out something cool: Post it! :)


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 05, 2012, 06:56:44 PM
I see.
Thank you very much for a detailed responce.
Today I heard for the first time about CTL and BTB so time is required to get acquainted with that all..
It shouldn't be very hard to understand the logic of BTB and xml files, about CTL - not sure yet, it's been a while since I looked at a Python code...Main problem is to find free time and enough inspiration. :)


Title: Re: Enemy units in Campaign
Post by: olly on March 05, 2012, 08:43:30 PM
Yes please do post any questions, as we love to help and encourage anyone interested in Dark Omen, especially modding the game. Progressing the CTL will be so cool and BTBEditor is a joy to use!

Black Pyramids BTB
(http://img40.imageshack.us/img40/8581/blackpyramidsbtb.jpg) (http://imageshack.us/photo/my-images/40/blackpyramidsbtb.jpg/)

Altered for my new Fortress Siege Map
(http://img192.imageshack.us/img192/2196/fortressbtb.jpg) (http://imageshack.us/photo/my-images/192/fortressbtb.jpg/)

(http://img26.imageshack.us/img26/2276/fortress3d.jpg) (http://imageshack.us/photo/my-images/26/fortress3d.jpg/)

:)


Title: Re: Enemy units in Campaign
Post by: Ghabry on March 06, 2012, 09:14:28 PM
I updated my post, forgot a step:
Create a copy of the ctl-file you want to edit. The name must be b101_orig.ctl (= add _orig to the filename) otherwise ctldis will not create the txt-file.


Title: Re: Enemy units in Campaign
Post by: olly on March 06, 2012, 10:12:56 PM
Been getting back into CTL editing with Ghabry's help and have also been finding all my CTL archived stuff from last time we investigated it all. Here is a good picture showing the relationship between the BTB and CTL files. It shows how the Necromancer retreats on B1_04 Map.

(http://img109.imageshack.us/img109/4404/ctlvampretreat.jpg) (http://imageshack.us/photo/my-images/109/ctlvampretreat.jpg/)

:)


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 07, 2012, 11:45:16 AM
Downloaded BTB Editor using Ghabry's link.
It says 'Blablabla is not a valid Win32 application'
I will try to run it on my Win64 at home this evening, but I actually only have time to look into it at work where I have 32bit XP.
Any ideas what can I reinstall/reassemble to make it work?

Another question is I read through a few Wiki notes on the matter. Yeah it's hard to raise the stuff from scratch, especially if you report several ppl tried that fail-success attempt method and it wasn't of much use.

10 mins talk to a Dark Omen developer would solve a lot if you are prepared to ask 'clever questions' :). I don't think it's a commercial project anymore so why wouldn't one of them give you a few insctructions? provided that they are still available in touch :D


Title: Re: Enemy units in Campaign
Post by: olly on March 07, 2012, 08:24:07 PM
install .net 4.0

:)


Title: Re: Enemy units in Campaign
Post by: HarlotsEvisceration on March 08, 2012, 04:06:43 PM
I've had a go at the btb editor, specifically regarding the mages. It's a very slow, trial and error process and honestly I didn't have much luck.

A quick fix is to always replace a mage with a mage, the mage will always use spells it is scripted to use though, so if you change the necromancer to a brightmage, if it's scripted to fly then cast death spasm, it will. However the mage will cast other spells seemingly at random, fireball, burning head, etc. Most of the time, this will crash the game.

To make progress, you'll have to find what line casts what spell, and alter it to what you need it to be. Needle in a haystack.

As for the dev's, I think they are flattered that people still love the game this far on, but their knowlege of the game is in peices, 14 years will do that to you.


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 18, 2012, 11:45:56 AM
Found a little time to start getting aqcuainted, started with BTB Editor.
1. A quick question. How do I load a background mission map to see coordinates of troops/triggers right on the map surface but not on a relative dark square?

Failed to find map files in the Dark Omen installed. Should I download decoded map files from somewhere to let BRB Editor 'eat' them?

2. Got from Wiki that Chunk <6000> is connected to troops and other triggers.
If to talk about B1_01, the first value there is 35 which looks like an amount of Subchunks.
I didn't understand how to add subchunks there. I don't know if all 35 are used but I dont want to touch existing ones. Is there a way?


Title: Re: Enemy units in Campaign
Post by: Ghabry on March 18, 2012, 01:29:26 PM
The editor has no functionality to add or remove stuff. You have to use BTBXML (http://en.dark-omen.org/downloads/view-details/1.-modding-tools/1.-map-editor/btbxml.html) instead. This converts BTB to XML so you can edit it with any text editor. This is again a python script.
btbxml.py converts btb to xml. The name of the btb can be changed in line 106. It generates a out.xml. Modify it and then convert it back to btb with xmlbtb.py. The name of the generated BTB file can be changed on line 86.
When you change the regions (5000) don't forget to update the count in the header of the BTB file. That's under 10000/2000/9 (value 21,136 for B1_01).
The wiki says:
2-TUPLE RECORD ( [Number of Regions in file, Number of line segments in all regions] ) type=9, size=16. Line segments are the entries starting with <10> and <502> under the Regions.

Some maps have a low quality bitmap of the map in their directory, e.g. B1_01.bmp. You can load these bitmaps instead if you want.


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 18, 2012, 07:43:03 PM
Thank you. I got more questions though :p

1. a short one:
By the way, in Olly's example of the Necromancer at Bandits' mission,
#97 16
seems that 16 means the sequence number of the subchunk even though the subchunks aren't enumerated?
This means that my chunks should be appended rather then inserted in the middle. And how is #97 interpreted? I saw #3 in B101 that I wasn't sure about already...

2. I opened ctl->txt file for B101 and it does contain scripts that are used in first mission.
But it wasn't easy to figure out everything. Probably, it would take more time than I could afford. But a few simple examples would help me get basic understanding, if it is possible :)

So, Enemy in first mission has 2 "waves". NG(131) and NGArchers(129) have scripts 0,2 and appear at once, archers go to a determined position.
a) where in the ctl files is that position defined?
Then NG(132) and NGArchers(130) have corresponding scripts 1,3. Triggering event is death of both units from wave-1, then trigger transfers them both to the right-top corner regardless of their initial position.
b) where are these right-top corner coordinates in ctl files? I'd like to split that transfer, one unit goes to right-top, the other to the left-bottom for example....for that I would have to add another script though...

c) I added a mage, assigned to it #133 and script 3. The mage wasn't seen at start but did appear in the right-top corner when the wave-2 started, but he didn't cast anything, only used magical staff of his.
I wonder if it is easy to copy-paste a casting script from another .ctl file and assign it to the mage in 1st mission.





Title: Re: Enemy units in Campaign
Post by: olly on March 18, 2012, 09:44:24 PM
You will have to check with Ghabry but looking at my Archived posts, he once said

[23:16] <Ghabry> the teleporting needs #94 followed by #98. the parameter of #94 is unimportant and #98 needs 66, whatever, whatever. So no idea
[23:16] <Ghabry> #97 <id> sets the target of the teleport

http://wiki.dark-omen.org/do/DO/CTL/OpCodes (http://wiki.dark-omen.org/do/DO/CTL/OpCodes)

97  init_teleport_spell node_id  Used by B1_04 Necromancer. Caller teleports to node_id  

I will post more of our rough old notes on Trading Post 1st Mission B1_01 CTL script....

[00:27] <Ghabry> func 4 5 and 6 are the 3 traders
[21:55] <Ghabry> First Archer is func 2

.func 2
#00 128
clear_ctrl_flag 32768
#3f 43970
#3c 240, 0
#3d 15
#3e 13, 31
wait_for_deploy
saveip
goto 7

[21:55] <Ghabry> at the end: goto 7
[21:55] <Ghabry> --> func 7
[21:55] <Ghabry> scroll to it

.func 7
reset_call_stack
saveip
set_r_i 0, 1
#28 9
reset_call_stack
saveip
do
    #b3 9
    iftrue
        #ac 58, 100, 512
    else
        #ac 58, 50, 512  
        iffalse
            #2e 16
            iftrue
                #28 9
            endif
        else
            #2b
            sleep
        endif
    endif
    set_wait_time 10
    wait
always

[21:55] <Ghabry> and you should see 9 three times
[21:56] <Ghabry> by changing it to another waypoint they move to it
[21:57] <Ghabry> try chaning it to 17
[21:57] <Ghabry> and see ingame what happens
[21:57] <Ghabry> (thats waypoint at 1153x492)
[22:03] <Ghabry> ok. so #28 is some waypoint thing
[22:04] <Ghabry> #28 <subchunk_id>
[22:05] <olly> yeah now got goto 7  
[22:05] <olly> so looking at func 7
[22:05] <Ghabry> good
[22:05] <Ghabry> yes
[22:05] <olly> thnx
[22:05] <olly> and 9  3 times
[22:05] <Ghabry> 2 times with #28
[22:06] <olly> so will change to 17   instead of  nines
[22:06] <Ghabry> they should move to the circle you found in the btb parser
[22:06] <olly> great :)  
[22:07] <olly> (document on wiki with screenshots>? or not just yet?)  
[22:07] <Ghabry> we should find out about some other waypoint things before
[22:07] <Ghabry> only one opcode is useless imo ;)
[22:07] <Ghabry> #b3 for example
[22:08] <Ghabry> maybe "Reached waypoint <subchunk_id>"?
[22:08] <Ghabry> because of the if-statement
[22:20] <Ghabry> the archers move to the next waypoint when the got enough damage
[22:21] <olly> ive just altered  9s to 17 and can see in BTB the 17th subchunk with x and y = (thats waypoint at 1153x492) so should see the idfference, brb at this chat my crash.. :)  
[22:22] <Ghabry> after they got enough damage at 9 they move to 17

(http://img513.imageshack.us/img513/7767/ctlwaypoint.jpg) (http://imageshack.us/photo/my-images/513/ctlwaypoint.jpg/)

(http://img20.imageshack.us/img20/7960/ctlbtbwaypoint9to17.jpg) (http://img20.imageshack.us/i/ctlbtbwaypoint9to17.jpg/)

(http://img130.imageshack.us/img130/ctlwaypoint.jpg/1/w940.png) (http://g.imageshack.us/img130/ctlwaypoint.jpg/1/)

(http://img41.imageshack.us/img41/1919/ctlwaypoint2.jpg) (http://img41.imageshack.us/i/ctlwaypoint2.jpg/)(http://img41.imageshack.us/img41/ctlwaypoint2.jpg/1/w1024.png) (http://g.imageshack.us/img41/ctlwaypoint2.jpg/1/)

22:42] <Ghabry> olly take a look at #ac 58, 50, 512
[22:43] <Ghabry> the archers move to the next waypoint when they got enough damage. If you reduce the 2nd parameter from 50 to 10 they will move with less damage
[22:43] <Ghabry> so this could be a percentage value

[21:19] <Rob> functions 100-148 are the standard functions in every ctl file. You can ignore them for now
[22:20] <Rob>.func 0 play 64   Get da Loot
[22:47] <Rob> "They're heading for the trading post" is triggered by "#af 1,63" I think
[22:51] <Rob> cool #af = #af <unit of head to show> <sound to play>   .func 14

.func 14
clear_ctrl_flag 8
do
    switch
        case 19
            #14 8, 4
            cbrk 6844
        case 20
            #14 8, 4
            cbrk 6844
        case 21
            #14 9, 4
            cbrk 6844
        case 5
            #14 5, -1
            iftrue
                #70 21
            endif
            cbrk 6844
        case 3
            #43
            #0d 128
            cbrk 6844
        case 85
            #47
            iftrue
                clear_unit_flag 16
                #48
                #0d 139
            endif
            cbrk 6844
        case 4
            #44
            #0d 127
            cbrk 6844
        case 27
            #69 25
            cbrk 6844
        case 71
            #d4
            iffalse
                #d1 240
                #0d 137
            endif
            cbrk 6844
        case 68
            #b9
            iftrue
                test_unit_flag 512
                iftrue
                    #cd 2048
                    iffalse
                        #64
                        #6b 16
                    endif
                endif
            endif
            cbrk 6844
        case 69
            #d3 58
            iftrue
                #b8
                iffalse
                    #25 1, 1
                    iffalse
                        play 66
                        #23 1, 1
                    endif
                endif
                #6e 17
            endif
            #d2
            iftrue
                #b8
                iftrue
                    #44
                    #0f 127
                else
                    #0c 134
                endif
            endif
            cbrk 6844
        case 70
            #c1 43968
            iftrue
                #c2 58
                iftrue
                    #0c 13
                else
                    #0c 134
                endif
            else
                #0c 134
            endif
            cbrk 6844
        case 29
            #25 0, 1
            iffalse
                #c1 43968
                iftrue
                    #af 1, 63
                    #23 0, 1
                endif
            endif
            cbrk 3567
        case 10
            #6e 17
            cbrk 3567
        case 12
            #6e 17
            cbrk 3567
        case 22
            #b8
            iffalse
                #6e 17
            endif
            cbrk 3567
        gosub 122
        @0xABC
    endswitch
while
#13


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 19, 2012, 09:18:31 AM
I see, thank you,
will try to look into it when I have a chance.

So far failing to run BTB Editor at my work computer under Windows XP :( it only works with Windows7 x64 on my home laptop.

Installed .NET 4.0 as Olly suggested but it still doesn't work.
I asked a programmer from our work to run it in his computer, he has newest possible .NET and Visual Studio and Windows XP. It still says 'Isn't a valid Win32 Application'.
Any ideas what else I can fix? I doubt I will have much chance to edit in BTB when at home :p

BTB Editor isn't a necessary tool as one can use BTB-XML, but seems very handy for placing enemy troops with right coordinates on the map.


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 19, 2012, 10:07:04 AM
1st Mission, an extract from 2nd NG Regiment script (unit id = 132)

    init_teleport 24
    teleport_to2

This code transfers them to right-top corner (subchunk 24)
If there a way to write an if-then-else construction, with checking unit_id, like:
if (unit_id == 132) - transfer to 24
else if (unit_id == 133) - transfer to 25
else transfer to 26
?
so far didn't fully understand how to check unit id.

Or is the logic of the script "1 Unit ID <=> 1 Script'? Then I would probably have to copy-paste script for NG-2 append it to the end of .ctl file and assign it to unit 133 that may appear in B1_01.btb?





Title: Re: Enemy units in Campaign
Post by: Ghabry on March 19, 2012, 05:15:53 PM
I will upload a 32bit version of BTB Edit later, must be a mistake in the build settings.
Btw, when you select the X-coordinate in the treeview and click on the map it will assign the values to X and Y, the same applies for Regions. Not documented anywhere, but quite useful.


For the initialisation of a unit it's recommended to assign an unique script function:

Quote
When you open the b101.txt you will see functions. All regiments start with the function defined by the value in <13> in their deployment zone circle. All regions are defined in <6000> in the BTB Editor. The deployment zones are assigned via the Unit Id (check in Wh32Edit), you can find the Id in <12>. <13> is the number of the script function that gets executed on start. Human controlled regiments always execute func 100 (can be altered), in multiplayer all regiments always execute func 100, <13> is ignored.

We don't really know how the initialisation works, but it seams that the following functions are usually called:

.func 2
    init_unit 128
    clear_ctrl_flag 32768
    set_label 43970 <-- Change this to a unique label
    set_event_handler 15 <-- Remove or write your own handler (but we don't really know what most events mean...)
    #3e 13, 31 <-- Looks like the 31 is incremented by 1 for any unit, but dunno
    wait_for_deploy
    saveip


The unique label you assigned can then be checked with test_unit_label 43970 followed by a conditional like iftrue or iffalse.

The Dark Omen Devs usually use the functions unique for one unit. Often with lots of copy paste. Only the event handlers are sometimes shared.


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 19, 2012, 06:30:48 PM
32bit BTBEditor would be great!

Yes it's better to assign 1 script to 1 unit. Just so far I didn't notice bugs when I assign the same behaviour script to different units. Probably for the sake of time it's ok to do it.

What I failed to do is I failed to force shaman cast :(

I copy-pasted a shaman script from a mission where he repops at start - like B2_02 ambush by goblins.
Adjusted what values I knew in the script, and didnt' touch 90% of main part. The shaman did pop but he behaved like an ordinary infantry unit.


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 19, 2012, 06:59:56 PM
#9d looks like a spells set for a mage.

For 1 of 4 mages in B5_01b we have:

    #9d 50
    #9d 55
    #9d 48
    #9d 54

A combo like this always goes 3-4 lines in a row, and is met only for mage scripts, never for other units.
Tomorrow I will try to pick up values for fire and ice mage.
If my assumption is true and the values are decimal, necro has range 48-55 (I counted 8 spells for them except Dispel), values for Orc shamans go around 42-47 or something.

Update:
Looked into db.xml for the Army editor, the spell numbers there coincide with these values. So if I fail to insert a mage into 'empty space', I will at least try to play with mages on the maps where they exist by default. My dream is to kill Luther and hear his thin squeky sriek :)

1 more update.
2 Conflagrations and Mr Schepke is fleeing alone leaving 19 of his boys burnt out on the ground. I liked it.
The only thing I doubt is that ice mage will have enough intellegence to use death frost + cloak in melee...but anyways.


Title: Re: Enemy units in Campaign
Post by: olly on March 19, 2012, 07:45:13 PM
Good progress, well done!

:)


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 20, 2012, 03:25:38 PM
Pity neither BTBEditor nor BTB-XML are indexing Subchunks in any way. It's pain in the ass to find say subchunk 34 in the list of 60 subchunks   :( and ther are a lot of such occasions even for 1 map.


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 22, 2012, 12:30:34 PM
I managed to place an artillery on a mission where it's not by default.

It happened so that my Unit-1 attacked that artillery, and the fight was going on for 40 mins: 1st minute artillery crew became 2/4, the next 39 minutes none died.

I referred it to some bug because of incorrectly transferred artillery ctl script.
I forced my unit to flee, and another bug occured: artillery remained in 'pursue' mode with red arrow even though my unit was far away. That kind of justified some bug with the artillery.

But then I reduced Artillery toughness from 7 to 3, and replayed. The artillery died alright within 2 minutes. My unit Str was 4, and I used 'here we go' and 'boost unit strength'.

I wonder if such things occured in the default campaign: I mean that sometimes artillery is too tough for units to break through it...does anyone know what's it about?


Title: Re: Enemy units in Campaign
Post by: Darkmancer on March 22, 2012, 11:07:54 PM
Leader sprites are immune to all forms of damage whilst there are squad mates alive.  Normally this is not noticable, but artilery has a v.large leader sprite (the machine itself).  Plus the leader has no attack.  So when attacking if your squad doesn't deploy itself correctly, it can end up with no contact with the arty crew and your unit.  In which case all attacks are lost, no one dies.

A possible work around is giving the artillery the skeleton flag.

It is possible to make units too tough to hurt, and generally its best to keep to 6 or below toughness.

I dunno about the arty chasing bug, maybe its unit type was wrong?


Title: Re: Enemy units in Campaign
Post by: olly on March 22, 2012, 11:14:17 PM
I agree with Darkmancer's advice on leader etc but could you document/post your CTL/BTB/WH32edit additions so I can follow and replicate them, to try and locate possible bug, as really interested about making a guide for adding more ai etc.. for future references.

:)



Title: Re: Enemy units in Campaign
Post by: cuthalion on March 23, 2012, 08:17:05 AM
Thank you very much for replies, I will pack and send you the files when I get back home.

By the way, Artillery can be destroyed prior to all its crew: it mayhap that the connon is down and 1-2 cannoneers flee but then can return and act as an infantry regiment. And what confused me is it was indestructible with toughness 7 but when I set toughness to 3 the artillery was destroyed alright...But maybe it's just a coincidence.


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 23, 2012, 08:31:51 AM
I started a new campaign with modified btb/ctl files, and encountered a nasty bug that spoils all the fun from the work.
Pretty please, help me to track it down or maybe someone already knows the answer. It is very important for the campaign.
Let me try to describe it in brief but with details.

1. It doesn't seem to occur on missions B101, B102, B104, but occurs on B103, B105, B107...maybe conneted to undead.
2. Let's take B107 (it has a regiment of enemy horsemen)
3. In Army Editor: overwrite 1st zombie regiment (that raises from the ground when you advance north) with those horsemen and adjust unit ID.
4. When you start playing the mission, the horsemen appear but they don't have a banner, and though they charge your units, combat doesn't start and you just 'pass through' each other.
5. It's almost certain the problem is in CTL. it can't be a bug with army unit, and the btb instructions are transparent and simple as well.
6. I tried to compare ctl scripts for buggy zombie-horsemen and non-buggy horsemen that appear later.
   They differ at a few points but I failed to adjust the script so that it worked alright. At some point the banner appeared but they anyway couldn't attack my regiments, and I couldn't attack them.

7. Now, the same happens if I substitute zombies with any cavalry - undead or alive, and unfortunately with majority other infantry as well, except for: mercenary infantry, imperial greatswords, skeleton warriors, maybe something else.
If I set Halberdiers, Dwarfs, Flagellants or whatever, the same bug occurs as with horsemen.

8. I believe it is connected to unit sprite types: what else differs imperial halberdiers and greatswords? their sprites have slightly different structure like having 5 'battle' movements vs 3, and something else.
Meanwhile, greatswords work alright as a substritution to any zombie, skeleon warrior or ghoul, while halberdiers provide that nasty bug I am talking about.

9. But be it sprites or not, I failed to adjust the script perfectly. I will try more as I can't advance in campaign building w/o it being fixxed, but I appretiate your help very much. Please.


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 23, 2012, 09:28:09 AM
Partially solved the problem. Why partially? because it is blind-walking and I am not sure if I didn't break anything else.

So there were 2 problems: 1) Inability to enter Melee combat with Horsemen 2) Absense of Banner on Horsemen

1) replace teleport_to with teleport_to2 helped to solve it. Horsemen attacked my defence line and the melee combat did start. A back-change in Army File horsemen->zombies: zombies can't work with teleport_to2, they behaved the same way as horsemen with teleport_to

2)     set_unit_flag1 536870912         /* = 2^29 */
       After I removed this instruction, the horsemen received the banner. I don't know what's checked in bit with sequence number 29, maybe there is something else important...
Let's see what happens further.


Title: Re: Enemy units in Campaign
Post by: Darkmancer on March 23, 2012, 04:54:44 PM
Are you sure the bug doesnt occur with Ghouls?  All the troops you listed it works with have 95 frames of animation.

Ghouls and all the others you listed have other amounts.

Also yes your correct the cannon can be destroyed before losing its crew, it's the fleeing thats the important part and that only occurs when the crew get hit, the cannon itself remains immune to damage.


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 23, 2012, 05:39:42 PM
Sure about Zombies and Skeletons, not sure about Ghouls - just I remember I had similar problems on mission b103.


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 25, 2012, 06:49:50 AM
Hi, I have a few questions.

1. Is there a known way to edit phrases units exchange during the missions? Like "Protect your flag, undead horsen chariots approach!" or others?

2. I didn't find enough information where to look for inter-mission scripts, but I have a specific question:
   Is there a known way to remove or change artifacts that drop from buildings, like Book of Ashur or Horn of Urgok.
   The problem is that having the full set of "building" artifacts vs not having them influences the balance crucially, and I want all who may try my upcoming campaign not depend on whether they remember everything or not.

3. Speaking again of those phrases during the missions. Though in default campaign all units speak with their own voices, after I change both my and enemy units, they seem to speak the phrases with random voices instead of their own.
Except for undead maybe...Is there a way to specify it? sounds funny when Treemen speak with squeaky goblin voices. :)


Title: Re: Enemy units in Campaign
Post by: Ghabry on March 25, 2012, 01:08:32 PM
You can convert the phrases (which are stored in MAD and SAD files) with the SAD-MAD-Audio converter (http://en.dark-omen.org/downloads/view-details/1.-modding-tools/4.-miscellaneous-tools/sad/mad-audio-converter.html) to wav. The record your own voice and convert it back to MAD/SAD :). The CTL commands are play and play_other_unit. But there is no list what number plays which file. Must be somewhere in the exe.

The items that are dropped from building can be altered. It is stored in the PRJ file. In the multiplayer maps I e.g. replaced all magic items with treasures.
The PRJ files can be edited with the command line tool SPARTAAn (http://en.dark-omen.org/downloads/view-details/1.-modding-tools/1.-map-editor/spaartan-command-line-battle-editor.html) (Just uploaded it because I couldnt find it anywhere).
I guess olly has a tutorial somewhere how to edit items. Lets wait for him.


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 25, 2012, 06:59:17 PM
Thank you indeed for the reply! I wonder if Olly as a native speaker would record tracks to my campaign ;)
Also, by tutorial for items edit do you mean turorial that helps with that command line editor or tutorial how to edit item properties? :)


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 25, 2012, 07:08:08 PM
I still can't defeat that bug with enemy artillery in my campaign.

99% of the times the artillery is in 'god mode'. My units quickly down crew to 2/4 (or to 2/6 if I increase its crew) and then 40 mins nothing happens.
If after that moment of crew 2/4 I order my troops to flee, the artillery doesn't drop off combat and the game crashes in some 30 seconds. Within those 30 seconds I can defeat it with magic though.

The .arm and .btb files are alright, and as for .ctl - Enemy artillery scripts are simply copy-pasted throughout the whole campaign except for 3 fields:
-Unit Label
-some insifnificant field  like #3e 13, 35 (please correct me if it does influence something)
-Event Handler. The last field seems important even though I don't fully understand its connection with other scripts with numbers 100+
If I set a handler to my unit that is not one of other enemy troops' handlers in that mission, the game crashes right after units deploy.
However I noticed that in ctl scripts for missions where Artillery exists, all artillery units have the same Event Handler and no other unit in that mission has the same.

After reading all my compains, could anyone help me to spill light on my problem? W/o enemy artillery varying of missions is very limited. And I have already failed to insert mages to non-mage missions. :(



Title: Re: Enemy units in Campaign
Post by: olly on March 25, 2012, 07:09:04 PM
Audio guide - > http://wiki.dark-omen.org/do/DO/Audio (http://wiki.dark-omen.org/do/DO/Audio)  and  http://wiki.dark-omen.org/do/DO/SFX (http://wiki.dark-omen.org/do/DO/SFX)

CLI Editor example -> will do proper guide on wiki soon but have never yet modded where items are placed

open B1_01
prj
FURN
FURN>list  (lists 0-10 records)

FURN>add house2.m3d
list        (shows new record, 11 now)

INST
INST>list livemodels   (shows record eg 36)

add

list livemodels (shows the new record eg 37)

INST>37

INST37>set livemodel 11

INST37>list livemodels    (should show 37: hosue2.m3d)

INST37>get pos

INST37>[0.00,0.00,0.00]
INST37>14                 (to see pos of existing object as reference)

INST14>get pos
INST14>[164.50,9.00,150.00]

INST14>37
INST37>set pos [166.00,9.00,155.00]
INST37>get pos
[166.00,9.00,155.00]

INST37>save
INST37>y

exit
exit


INST>help inst

INST37>get min
INST37>get max
INST37>set min [0.00,0.00,0.00]
INSt37>get max [0.00,0.00,0.00]

(Bounding box for solid buidlings)


INST>list ex_walk
INST37>set ex_walk 1
INST37>list ex_walk

exit

INST37>list deadmodel
INSt37>set deadmodel 8     (same as hut dead model)

save


INST37>list burning
INST37>set burn 1
INST37>list burning

save


INST37>list wounds
INST37>set wounds 6

INST37>list toughness
INST37>set toughness 1
INST37>

Save
Save


INST  info

INST> list livemodels

INST> remove 19

INST> remove 18  etc...

INST> save

INST> y

exit
exit



*Mikademus added macros to the CLI editor to help you repeat tasks much more effeciently, which i will include in my guide*


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 25, 2012, 07:22:03 PM
Thx, I will try to learn it. Though I don't need to place items on the missions. I rather feel like removing items from 'hidden' places and giving all I need to enemy troops. Or replacing them with 'potions of strength' or Coin Chests. That will be more than enough for me. If it can be done easily...
Even though it's somewhat less diverse, it's easier for game balancing, and I am not sure ppl enjoy shooting all the houses and stones on every mission


Title: Re: Enemy units in Campaign
Post by: olly on March 25, 2012, 07:36:01 PM
yep, i've received your B104 mod and am currently checking with Wh32Edit, BTB Editor and CTL script. I will post screenshots of each for others to follow.

:)



Title: Re: Enemy units in Campaign
Post by: cuthalion on March 25, 2012, 07:55:20 PM
[attachment=1]

Didn't quite get how to insert screenshots..I attached one of the Mortar and just posted extracts from btb/ctl scripts...
It's an ordinary mortar copied from 2PARM, its Unit Id is 257, Evil Alignment.

Then, the btb contains the following record:

         <SUBRECORD type="503">
             <INT type="5"> 16387 </INT>
             <INT type="1"> 525 </INT>
             <INT type="2"> 615 </INT>
             <INT type="6"> 48 </INT>
             <INT type="7"> 125 </INT>
             <INT type="11"> 0 </INT>
             <INT type="12"> 257 </INT>
             <INT type="13"> 3 </INT>
         </SUBRECORD>

Corresponding CTL script, as I posted above is the same for all enemy artillery throughout the campaign:

.func 3
    init_unit 128
    clear_ctrl_flag 32768
    set_label 43971
    #3c 240, 0
    set_event_handler 14
    #3e 13, 32
    wait_for_deploy
    saveip
    do
        test_unit_class 32
        iftrue
            #d6 128
            iffalse
                #d6 0
                iffalse
                    #cf 1
                    #ce 1024
                    send_event_to_this 12
                    sleep1
                endif
            endif
            search_and_shoot_enemy 58, 100, 512
        else
            search_and_attack_enemy 4, 0, 4096
        endif
        set_timer 10
        wait_for_timer
    always




Title: Re: Enemy units in Campaign
Post by: olly on March 25, 2012, 08:01:44 PM
Not sure if it matters (early investigations) but you could try putting the mortar in the top slot of Wh32Edit as it has the lowest ID maybe (257 and Halbediers have 259) and maybe even make them func 0 in CTL list rather than .func3 with #3e 13, 29

:)

(If still a problem with BTB Editor try .net 2.0)


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 25, 2012, 08:26:20 PM
BTB Editor: At home atm with Win-7 so it works. Will try .NET 2.0 tomorrow morning.

As for your advice: there are enemy armies where Ids aren't in ascending sequence, and same for btbs.
Anyway I tried it and its about the same. The artillery behaves alright which means the script works: it shoots, and if I flee before it's 2/4 it shoots again alright.

I want to try set a unique event handler to artillery, but Im not sure how to pick up one so that it didn't crash on battle start.


Title: Re: Enemy units in Campaign
Post by: olly on March 26, 2012, 12:36:33 AM
If you added a new BTB section for the mortar, did u have to update the header by +1?

http://forum.dark-omen.org/singleplayer/enemy-units-in-campaign-t1094.0.html;msg11188#msg11188 (http://forum.dark-omen.org/singleplayer/enemy-units-in-campaign-t1094.0.html;msg11188#msg11188)

Or that might only be required when you add new regions and boundaries.


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 26, 2012, 05:48:15 AM
I have to increase the first field in the CHUNK 6000 by 1, yes.
The thing is if I don't do such stuff, it just won't deploy. If it IS deployed in a right position, if it shoots my troops, this means that .ARM and BTB are unlikely to be a problem, and CTL is correct to the most part. But in CTL at least there are points with unknown meaning.
 Will try a further investigation. Maybe it's my army that is buggy...I will try to test the things on B2_05, where default enemy artillery is deployed, and also will try default mercenary army instead of my own.


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 26, 2012, 09:03:00 AM
Seem to have solved it. At least on the first approach. So if the information is of any use for someone:

I was on a right track that the problem is with that line in ctl: set_event_handler
   but I wasn't sure until now what exactly it meant. The answer is very simple, even though when I was wandering in darkness of unknown functions it didn't look so.

set_event_handler XX simply sets the .func XX from CTL file as handler of events for that particular unit.
   So there are 2 ways for the artillery: either copy-paste that artillery handler from any script where artillery exists, or modify the handler for archers on this mission and use it.

Artillery handler has a peculiar item: (example is given for B205, event handler  .func 26 for orc artillery)

            on_event 23
                clear_unit_flag2 1
                #bd 8
                set_event_handler 24
                test_unit_flag1 8192

The thing is on some event the handler is set to a different one. For mission B205 event handler 24 stands for Infantry units. The assumption then is that when artillery loses its Leader it becomes an infantry and works as infantry from that moment on.

I added this instruction to Archers event handler and the enemy Mortar died quickly to my guys. The bug had occured when my troops did kill the Leader (the mortar itself) but the game didn't know how to handle that situation.

2 further things to do:

1) I will have to test if enemy archers behave correctly with that fix in the Handler. It mayhap that their leader becomes mortal before the unit dies.  This won't do.

2) Probably, copy-pasting Wizard event handler together with the Wizard script function will make casting wizards on a missions where wizards didn't exist. I will test that thing on missions like B301 or other 'late' missions that don't have default wizards.





Title: Re: Enemy units in Campaign
Post by: Ghabry on March 26, 2012, 10:05:43 AM
Yes set_event_handler assigns the .func as an event handler. Isn't that mentioned anywhere? :D
At least the OpCode-Table (http://wiki.dark-omen.org/do/DO/CTL/OpCodes) says "set_event_handler func Registers func as an event handler" ;)

Let's also take a look at the player artillery. They get event handler 103. (they pass the test_unit_class 32-test). The test looks at the Unit Type and removes the first 3 bits. So for artillery this will be 32 after unsetting the first 3 bits. (see also events (http://wiki.dark-omen.org/do/DO/CTL/Events)).

Okay so event 23 is probably regroup. Good to know. Now I wonder how the cannon gets destroyed on retreat. MUst be also some event function. But I just tested it and couldn't trigger event 23 by regrouping a cannon. Strange.

Just for reference:
.func 120 checks test_unit_class 56 in on_event 23. That's a (undead) chariot. Have to check if undead chariots use this function because funcs >= 100 are usually not used by the map AI.



Title: Re: Enemy units in Campaign
Post by: cuthalion on March 26, 2012, 11:02:52 AM
Well, when you aren't familiar with overall structure of the ctl file it's not evident where to seek the problem, while when you've been working with it for quite a while, things become more evident.  :-[
After I localized my problem should be in event_handler, I figured out its meaning relatively easy.

Now I have a few questions.

1) I don't quite understand what you mean by 'player artillery' with event handler 103. I thought all human troops have func 100. What file are you speaking of? is it some multiplayer stuff or?..

Modified my post: got it - seems I'm slightly overloaded. in func 100 there are event handlers for human troops depending on their class, and artillery has handler 103.

2) Also, why do you think 23 is Regroup?
Artillery never routs unless the leader is dead, but then they rout with chance=100%.
Event 23 should describe that very moment when the leader dies and the crew routs.

And a few more questions:

3) Where can I find table of unit classes with values? I figured out Class 32 is artillery but that's about it.

4) Im interested in undead chariots. But again you say '.func 120' - in what file? at least in the file I've been editing now .func 120 has nothing of the kind.
I remember I saw a post where someone complained that Chariots can't be added to the campaign as human troops because they become buggy after the mission. Is there a way to solve it by editing ctl func 100 or something?..

Thank you for replies.


Title: Re: Enemy units in Campaign
Post by: Ghabry on March 26, 2012, 12:25:11 PM
2) Also, why do you think 23 is Regroup?
Artillery never routs unless the leader is dead, but then they rout with chance=100%.
Event 23 should describe that very moment when the leader dies and the crew routs.

No idea was just a theory. ;). I tested it by adding play 64 to the function. Then the unit should say "get the loot" when the event happens. But the unit didn't say it.

3) Where can I find table of unit classes with values? I figured out Class 32 is artillery but that's about it.

There isn't really an article about this, but you can find a list in the ARM Talk Section (http://wiki.dark-omen.org/do/Talk:DO/ARM#Unit_Type_Bitfield) ;).

4) Im interested in undead chariots. But again you say '.func 120' - in what file? at least in the file I've been editing now .func 120 has nothing of the kind.
I remember I saw a post where someone complained that Chariots can't be added to the campaign as human troops because they become buggy after the mission. Is there a way to solve it by editing ctl func 100 or something?..

Chariots sometimes crash the unit editor in Dark Omen because it was never intended that you can control chariots. But their is a book description for chariots. Maybe they wanted to add it but reached the deadline ^^. And in multiplayer they cause disconnects. I talk about .func 120 in B1_01. I never really checked this but thought that all funcs >= 100 are identical for all CTL-files.


.func 120
    clear_ctrl_flag 8
    do
        get_event
            on_event 19
                #14 8, 4
                end_event 6844
            on_event 23
                test_unit_class 56
                iftrue
                    #88
                endif
                end_event 6844



Title: Re: Enemy units in Campaign
Post by: cuthalion on March 26, 2012, 02:12:38 PM
I see,
Undead Chariots are Type 61 there btw.


Title: Re: Enemy units in Campaign
Post by: Ghabry on March 26, 2012, 03:47:27 PM
Yes but as I said "The test looks at the Unit Type and removes the first 3 bits." And first three bits unset on 61 makes 56.


Title: Re: Enemy units in Campaign
Post by: Ghabry on March 26, 2012, 05:24:13 PM
In the meanwhile I figured out how to change magic items:
Open the CLI Editor and then


> open (you get a list of map folders)
> open b1_05
> prj
b1_05.PRJ> inst
b1_05.PRJ: INST> help inst (you get a list of commands)
b1_05.PRJ: INST> list magic (everything in help under field codes can be listed)
# magic
...
12: 21
... (12 seams to be the house with the green smoke, 21 is book of ashur)
b1_05.PRJ: INST> 12 (select inst entry 12)
b1_05.PRJ: INST 12> set magic 0 (or whatever magic item you want)
b1_05.PRJ: INST 12> save
[yN] > y


I guess this can be used to add items to any game object, never tried it. For a free magic item (that is not in a building) take a look at SPARE9 (that's the tutorial). The Grudgebringer Sword is lying around their.


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 26, 2012, 05:50:06 PM
Cool, thank you! I will try to use it.

By the way, I got yet another question.
Skeleton horsemen and black grail in .ARM files have armor 16, 17 or something. What is it about?


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 26, 2012, 06:26:09 PM
Couldn't help sharing fun...I wanted to add a neutral-aligned mage to fight at my enemies. The result was the mage destroyed 3 enemy units of cavalry within 5 seconds. He seems to have infinite mana and can cast 10 fireballs a second.


Title: Re: Enemy units in Campaign
Post by: olly on March 26, 2012, 06:39:46 PM
Again, great progress being made that will benefit the whole community.

Many Thanks

:)

(Glad the BTB that I sent you works on your Win XP)


Title: Re: Enemy units in Campaign
Post by: Ghabry on March 27, 2012, 08:51:34 AM
Couldn't help sharing fun...I wanted to add a neutral-aligned mage to fight at my enemies. The result was the mage destroyed 3 enemy units of cavalry within 5 seconds. He seems to have infinite mana and can cast 10 fireballs a second.
That must be the real Dread king :) (or Volkmar on Killing Spree)

If you give an enemy twice the same magic item they can use it infinitly too btw (funny with hellfire sword)


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 27, 2012, 01:45:09 PM
send_event_to_labelled 43971, 84

            on_event 84
                #99 66, 32768, 1
                end_event 6844

This forces a mage cast dispel magic.
I wonder what 66 stands for, dispel magic seems to be 56.
And I wonder what happens if to set it to an enemy infantry (provided that the infantry is set 'dispel magic' in the list of spells). This might work.

Also, there are similar events 81, 82 that trigger the following:

    on_event 82
        test_unit_flag2 2048
        iffalse
            #9b 0, 0
            iffalse
                #99 66, 512, 3
            endif
        endif
        end_event 6844
    on_event 81
        test_unit_flag2 2048
        iffalse
            #9b 0, 0
            iffalse
                #99 66, 1024, 3
            endif
        endif
        end_event 6844

#9b might be amount of mana check, and the events occur when a mage is attacked by spells or magical items. Or maybe this involves casting 'dispel magic' on friendly troops that might endure magic attacks.


Title: Re: Enemy units in Campaign
Post by: Ghabry on March 27, 2012, 03:01:43 PM
Bit of topic, but because there is so much CTL testing in this topic:
#d7 n (used in B5_01 and B5_01B, thats black pyramide) checks your game if you defeated Carstein (n = 1), Hand of Nagash (n = 2) or Black Grail (n = 3). (Thats used to disable these units, but n = 1 is not used)

[And just for my reference: Dread King is func 10 + eventhandler 41]


#99 is an interesting find. I have a guess what the last parameter could be...


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 27, 2012, 03:33:26 PM
This isn't an offtopic, it will definitely be of value once I get my way to the last mission scripts :)
Though I already have a feeling that tough missions require only minor tweaks. If to add a lot of stuff to such missions, they become 'overloaded' and may seem even boring.


Title: Re: Enemy units in Campaign
Post by: Darkmancer on March 27, 2012, 04:01:12 PM
ya that #d3 is interestesting.  Presumeably it'll go to 0x1b0  in the save game and add n  * 4 bytes and check to see if its a 1 or 0.

That hopefully means you could use n=7 to see if you met lorean etc.

http://wiki.dark-omen.org/do/DO/ARM (http://wiki.dark-omen.org/do/DO/ARM)

I've heard people say you get more units in the hand of nagash level if you go the long route.  Anyone confirmed this?  The codes from that be interesting if true.

PS
The Armour question.  Nobody knows, dues to the dice rolling nature of armour checks its impossible to check.  Supposedly to beat a 15 you'd have to roll a 6,6,then a 4.  Clearly this is not the case they arn't that tough. In the fourth edition i believe im correect in saying armour is limited to lvl5, which you only need three bits for, maybe the rest of the byte stands for something else?  It's the only vaguely sensible thing i could come up with, i originally thought it might be an anti-strength thing but the numbers dont make sense.


Title: Re: Enemy units in Campaign
Post by: Ghabry on March 27, 2012, 04:12:26 PM
Okay, no idea what the arguments for #99 do. A call adds 1 dispel (up to 3) to the caller, that's all I could find out. And it crashes the game if its called outside of an event handler ;)

Some theories about other commands (don't guarantee the correctness)
#94 n Adds n magic points to the enemies global magic pool
#93 n Checks if the enemy has at least n magic points

Now, 14 years after release of the game, I can also finally answer what the purpose of the jewel of morslib is (If you lose against Carstein a different map is loaded at the end that contains the jewel):

test_unit_at_node 56 ; Is near the jewel (node only exists on map with jewel)
iftrue
    play 90 ; "Jewel, give me power"
    #94 3
else
    #94 1
endif

The jewel adds three magic points.


@Darkmancer:
Nope I would say the code only handles 1, 2 and 3. Returns 0 for 0 and -59?? for all other values.

And I wrote done the wrong code. It's actually #d7. I corrected it in my old post.


Title: Re: Enemy units in Campaign
Post by: Darkmancer on March 27, 2012, 04:30:05 PM
The Jewel also adds desire to punch level designer in face.

Shame about the check thou.  I suppose you might be able to hijack those 3 flags thou, and with a bit a luck be able to reset them to zero at various stages.

It's acually weird those flags even exist at all, I can't see any way of accidently losing a battle which wouldn't be totally devastating to your army. 


Title: Re: Enemy units in Campaign
Post by: Ghabry on March 27, 2012, 04:50:42 PM
Good point.
Because you don't need to alter the content during the mission you could use WHMTG (campaign script executed between missions) commands WH_ReadVariable and WH_SetVariable to read/write values from/to these three slots on mission start (and recover the settings on end).

Yes the flags are a bit nonsense. The fastest way to lose is losing Morgan, but that is a game over. I would say everybody reloads after losing a mission anyway. And the last mission is already hard enough with Hand + Grail it would be even worse. But never tried it.

Edit:
Remember the Hand of Nagash mission. Klaus tells you that when you do sidequests you are losing important time. But I just checked the Hand of Nagash mission CTL script and there isn't really any check anywhere to disable an enemy unit.


Title: Re: Enemy units in Campaign
Post by: cuthalion on March 29, 2012, 07:44:50 PM
I have a question about Campaign script, the flow between the battles.
I saw that page in Wiki and saw that long script, but didn't quite understand in what file it is situated and if there is an editor or xml format for it.

In particular, I have 2 ideas, maybe someone knows if they are possible or not.

1. Activate/deactivate my troops, like, allow Helmgart bowmen stay with me after I took the fortress, or something like this.

2. Change the game flow to capture all alternative missions. Like help Elrod, then help Treeman, then jump to Knights of the Realm branch. This can make the campaign longer.


Title: Re: Enemy units in Campaign
Post by: Ghabry on March 29, 2012, 08:41:16 PM
The campaign script is hardcoded in EngRel.exe. It starts at 0x0C1C20 (when you look at the dump thats 0x4C3C20 - 0x402000, the script was dumped while the game was running, the offset defined somewhere in the header of the exe file) (not human readable so you won't see much). It's basicly 4 bytes adress of a function (can be any function that takes 0 arguments) followed by arguments (4 bytes each).
There is currently no tool to edit (or extract) it. Can't find the tool anymore I used to dump it. And nobody ever showed real interest in editing the campaign script. Changing strings e.g. would be also a bit problematic because they are referenced via a pointer.
I could try to write one but also have lots of other things to do so it would take at least a month ^^.


Title: Re: Enemy units in Campaign
Post by: olly on March 29, 2012, 09:49:27 PM
Such a tool would be greatly appreciated, especially in preparation for any future mod maps that will really tie together the advancements in CTL scripts and make truly new campaigns for all the new DOE2 sprite races.

:)



Title: Re: Enemy units in Campaign
Post by: cuthalion on April 02, 2012, 05:47:42 PM
I am curious how exactly Mork's War Banner works. (never played in multiplayer) I know it instantly destroys mages in melee.
But who are considered mages? Unit type = Dark/Orc/Goblin/Human Wizard?
Or any unit that has a spellbook? In particular, would it destroy Hand of Nagash and Dread King?


Title: Re: Enemy units in Campaign
Post by: Ghabry on April 02, 2012, 07:56:28 PM
I guess it checks for the mage type but I don't think that this was ever tested. The easiest way to test it would be to give it to any unit in singleplayer (with wh32edit) and then go close combat with the Dread King.


Title: Re: Enemy units in Campaign
Post by: cuthalion on April 03, 2012, 11:53:03 AM
Indeed,
at least the Dread King feel comfortable in Melee vs Orcs.

Another question I have,
I'm interested in setting up a randomizer - something that would pick up one of 2 or several ways at Random.
I didn't quite get how exactly all those registers - global, unit, - work. and how many private registers may a unit have.
I saw that function set_unit_r_random1to10.

Shall I write something like

blablabla...
set_unit_r_random1to10

test_unit_r_eq_i 1
iftrue
 bla1
else
 test_unit_r_eq_i 2
 iftrue
   bla2
 else
   bla3
 endif
endif

Would it give me 10 options, in first I get 'bla1', in second 'bla2', in all the others - bla3?


Title: Re: Enemy units in Campaign
Post by: Ghabry on April 03, 2012, 12:56:35 PM
We don't know how many private registers a unit has. Under the assumption that only set_unit_r and similiar functions can write unit registers you can use any register that is not referenced in the CTL. There should be at least 6 registers available per unit, but could be also more (if the number is too high you will overwrite other data).

The set_unit_r_random1to10-command is actually not really random. You don't get a new random number every call. It's actually a counter that is increased from 1-10 and then reset to 1 again. One increment takes around 1 second (not measured) so make sure to have a long delay with e.g. a timer.

Your code looks correct from the structure (bla1 or bla2 are executed in 10% of the cases, bla3 in 80%). But your function calls are wrong.
set_unit_r_random1to10 takes as an argument the register that receives the "random" value.
test_unit_r_eq_i takes two argument (register and value that will be written in the register).

Note that there is no way to compare a range so if you want to do bla when r is 1 or 2 you should write:

test_unit_r_eq_i 1 1
iftrue
 call 42
else
 test_unit_r_eq_i 1 2
 iftrue
   call 42
 else
   test_unit_r_eq_i 1 3
   iftrue
     bla2
   else
     bla3
 endif
endif

And then implement the logic for bla in .func 42 (end the function with a return).


Title: Re: Enemy units in Campaign
Post by: cuthalion on April 03, 2012, 01:34:25 PM
I see,

What happens if I write

set_unit_r_random1to10 5

and then w/o any delays

test_unit_r_eq_i 5 1
iftrue
 bla1
else
 bla2
endif

do you know if random1to10 start always with 1 and then changes 2,3,4, etc?
If so, then bla1 will be always executed and bla2 - never.
Or can it start say with 6, and then go 7,8,9,10,1,2 etc

Let me explain what exactly I'd like to achieve.
When I finish my campaign, I am unlikely to force myself into another unique campaign like that.
But I'd like to play with own army, and supply it with 1-2 unique units.

As an example, a unit that gets 1-2 spells each mission, but isn't a mage.
I've already checked the possibility and it works fine: it's enough to write a unique CTL script for that unit instead of .func 100, and it will have and will cast those spells I assign to it.
The only problem is to have it pick up that spell at random from a pre-defined list. So is it achievable with that randomizer?


Title: Re: Enemy units in Campaign
Post by: Ghabry on April 03, 2012, 01:53:29 PM
The (bad) randomizer is always starting with 1 when the map was loaded. But I'm not sure if it's already incrementing the value when you are in deployment phase (test it).
If it is then you can use the time when the player clicked "start game" as a "random" value. (that means make your check after wait_for_deploy and assign the spell there). As long as the player does not use a stop watch to get the perfect click moment this randomness should be enough ;).
If the randomizer is not incrementing it's value in the deployment phase I don't know how you can generate randomness directly after the deployment phase.

Edit:
For randomness at mission start I guess you will need some clever WHMTG script that generates a random value for you (no idea yet how to do this but should be somehow possible; The game must store the random seed for magic items somewhere in the savefile, when you reload your mage gets the same spells)) and then sets the savegame values for Carstein, Hand of Nagash and Black Grail to 1 or 0. Then you can check it with #d7 at mission start (give you 8 possible combinations (3 fields, value 1 or 0, 2^3 = 8 )).


Title: Re: Enemy units in Campaign
Post by: cuthalion on April 03, 2012, 03:58:05 PM
OK, I got it thank you.

I will try the 1st plan when I finish the campaign, and if it fails, let's see what can be done about general game script.


Title: Re: Enemy units in Campaign
Post by: cuthalion on April 05, 2012, 04:38:06 PM
Ghabry I need your help :) once again.

It seemed to me that it's enough to set for 1 of my units start script different from 100 (say 99 or the last enemy script+1 or whatever) and that particular unit will be handled by that script.

But seems I was mistaken and my previous tests were wrong.
Regardless btb value in <13>, all 'my' units start with script 100. They ****ing ignore that value!

So I need means to distinguish between my units (except for unit class that may be the same for 2 or more units) in func 100, if I want a specific logic for my units out there.
For "Unit Id" I found only 'test_unit_alive' which won't help.
As for test_unit_label, all units from func 100 would have the same label.
Maybe there a way to enforce a unique ctl function in btb for units. I've no idea thus far.
Maybe there are other unique flags for each unit?..


Title: Re: Enemy units in Campaign
Post by: Ghabry on April 05, 2012, 05:41:16 PM
Hm, I only noticed in multiplayer that the script handler is overwritten with .func 100. Didn't knew that singleplayer has the same problem.
We don't know of any function yet that can check the Unit Id or similiar.

Because all unit scripts are executed sequential you could try to assign a label to every unit with a branch:

test_global_r_eq_i 1 0
iftrue
  set_unit_label 12345
  set_global_r_i 1 1
else
  test_global_r_eq_i 1 1
  iftrue
    set_unit_label 12346
    set_global_r_i 1 2

and so on 15 times ;)

As usual untested.
The following assumptions must be correct to get this working:
- The execution order of the unit script must be always the same (otherwise the labels are wrong).
- The default global register value must be 0 (not random)


Title: Re: Enemy units in Campaign
Post by: cuthalion on April 05, 2012, 05:55:18 PM
I see, will try this out.

Execution order might be the same in all missions or correspond their sequence in BTB file. It may be different but adjustable.

There is no way to check unit flags like 'goblin flag', 'will never toute' etc is there?

BTW You suggest that I use this or that register. Are there 'untouchable' registers that are usually used in other scripts and shouldn't be altered by me?



Title: Re: Enemy units in Campaign
Post by: Ghabry on April 05, 2012, 06:08:06 PM
BTW You suggest that I use this or that register. Are there 'untouchable' registers that are usually used in other scripts and shouldn't be altered by me?
Our current theory is that all registers that are not referenced in the CTL file are save to use. Nobody proofed this wrong yet...

And nope we don't know how to read the unit flags.


Title: Re: Enemy units in Campaign
Post by: cuthalion on April 05, 2012, 06:24:25 PM
Found a few ways around but nothing fully satisfactory yet.

   test_other_unit_selected 2
   iftrue
    #9d 30
   endif

If set in func 100 prior to deploy, gives Conflagration to Gunther Schepke if I order them a command before deployment (move or attack)
If set in func 100 right after deploy, gives Conflagration to Gunther Schepke, but only if he is selected by the moment I click Deploy.


Title: Re: Enemy units in Campaign
Post by: cuthalion on April 05, 2012, 06:38:51 PM

test_global_r_eq_i 1 0
iftrue
  set_unit_label 12345
  set_global_r_i 1 1
else
  test_global_r_eq_i 1 1
  iftrue
    set_unit_label 12346
    set_global_r_i 1 2

and so on 15 times ;)


This works, at least on B101.

The sequence doesn't depend on btb file, and always returns the same order: Cavalry, Infantry, Xbows, Cannon.

I will test it further in order to realise if the order equals to the order of troops in the Army Roster, or if it equals to ascending Unit Ids. That is about the same though. So probably it will be more or less the same throughout the campaign and thus can be copy-pasted from ctl to ctl. Will report further.

It won't work if I lose a unit though. And my favourite tactics of destroying Black Grail is find an unhappy infantry like Night Goblins in Goblin Adventures and give it Defiance+Heart of Woe :)

Modify Message
Yes it's simple troop roster sequence.
Imperial Tank before the last mission breaks in in the middle, and there is also a problem if a unit is lost. The rest of the campaign will be screwed up.


Title: Re: Enemy units in Campaign
Post by: Ghabry on April 05, 2012, 11:20:55 PM
Hm right. Completly forgot about the case that a unit can die...

But in the meanwhile I found a much better solution. I don't know the official way to get the Unit Id within a CTL script, but this here works too:
test_unit_r_eq_i -278, n
n is the Unit Id you want to check.

Of course you can also overwrite the Unit Id with set_unit_r...

I don't guarantee that this still works during the battle because the UnitId is only 2 byte and the registers are 4 byte. If you are lucky the 2 other bytes are unused (and stay 0) :).


Title: Re: Enemy units in Campaign
Post by: cuthalion on April 06, 2012, 06:07:50 AM
Yes, this solution works, at least before unit deploy. That's good as it's enough time to set a label to the unit anyway.
Thank you :)

What is bad though is that randomizer doesn't work. It always returns 1 regardless of the time passed or I don't understand how to use it.

    test_unit_r_eq_i -278, 2
   iftrue
       set_unit_r_random1to10 5
   endif

    wait_for_deploy
   
    saveip
   set_global_r_i 3 1
      
   test_unit_r_eq_i -278, 2
   iftrue

      set_timer 150
      wait_for_timer
      
      test_unit_r_eq_i 5 1
      iftrue
       #9d 28 (blast)
                else
                 #9d 30 (conflagration)
      endif
        endif

This piece of code always sets blast to Infantry a short period after deployment.
Same happens if I 'randomize' the register after deployment, or if I set the spell before deployment.
Same happens if I use any other register (tried 1, 5, 6)


Title: Re: Enemy units in Campaign
Post by: Ghabry on April 06, 2012, 01:23:03 PM
I just noticed that the "random" number generator does start when you finished deployment. So this can't be even used for random values after startup...
So for now I have no idea how to get a good random seed. Guess you will have to stick to a check which regiment is selected when deployment is finished for now...


Title: Re: Enemy units in Campaign
Post by: cuthalion on April 06, 2012, 01:47:03 PM
Well in my tests it didn't ever start, after or before startup. As it always seemed  to return 1.
But anyway, your verdict is clear :)
OK it's not a biggie, I will most likely manually define spells for missions. Im now more worried that I can't find them sprites everyone is talking around on the forum, and I've no idea what DOC111 is and such :)

worst thing to be a newbie at something :)


Title: Re: Enemy units in Campaign
Post by: Ghabry on April 06, 2012, 02:01:04 PM
DOC111 (http://en.dark-omen.org/downloads/view-details/1.-modding-tools/4.-miscellaneous-tools/doc111.html) is a very old mod collection from around 2000. Also contains lots of sprites.


Title: Re: Enemy units in Campaign
Post by: cuthalion on April 06, 2012, 06:51:10 PM
Would the following logic work (sorry for pseudo-language):

after deploy in func 100:

if (user id == my id)
{
 randomize_reg(5)
 reg(6) = 1
}
 
saveip
do
        set_timer 100
        wait_for_timer
  
 if (unit_id == my_id && reg(6) == 1)
 {
   reg(6) = 0
   and here goes logic depending on randomized reg 5
 }

        sleep1
always

I implemented something of the kind but it would give my unit the spell each time I give it a command, I don't know why - maybe the register was automatically set to 1, not sure. After it received like 8 fire blasts, the game crashed.





Title: Re: Enemy units in Campaign
Post by: Ghabry on April 06, 2012, 10:00:33 PM
The random value is assigned when you call set_unit_r_random1to10. So to get a random number later you have to call the function again.
The code looks correct but it's possible that reg6 get's written somewhere. Try it with a different register (8 is the highest).


Title: Re: Enemy units in Campaign
Post by: cuthalion on April 07, 2012, 07:18:05 AM
The random value is assigned when you call set_unit_r_random1to10. So to get a random number later you have to call the function again.

Didn't quite understand that part.
Do you mean that I should use it in the following way.

Somewhere
set_unit_r_random1to10 7
.....
Then
set_unit_r_random1to10 7
test_unit_r_eq_i 7 5

So before testing that register I have to call random again?


Title: Re: Enemy units in Campaign
Post by: Ghabry on April 07, 2012, 05:27:13 PM
Everytime you call set_unit_r_random1to10 it gives you a (new) "random" number.

So for a large if-branch you have to call set_unit_r_random1to10 once before the branch:
set_unit_r_random1to10 7
test_unit_r_eq_i
iftrue
...
Then
test_unit_r

and so on.


Title: Re: Enemy units in Campaign
Post by: cuthalion on April 12, 2012, 07:06:32 PM
Is it known if there exists (and known number) event "You are charged by enemy"?

An idea about intelligent enemy archers came to my mind. Take horsen archers, they shoot you but if you charge them they flee, then regroup and shoot again. Pursuing them may be dangerous as it might discharge a new wave of enemies, and anyway it's hard to pursue cavalry.
 Amount of such regroups can be limited by registers, and also by the fact that they may fail to regroup and flee the battle.


Title: Re: Enemy units in Campaign
Post by: kilowic on April 12, 2012, 08:33:51 PM
That would be extra annoying unit!