May 04, 2024, 12:32:40 PM

Username
Password

  Show Posts
Pages: [1] 2 3 4
1  Warhammer Dark Omen / Singleplayer / Re: Further CTL investigation on: April 27, 2017, 08:38:42 AM
Added now all known OpCodes to ctldis and type annotated all OpCodes (still without assembler, I add the assembling during the next days). Feel free to make suggestions.
...
Looking forward to use the new ctldis.py!!! It will make things a lot easyer!!!
2  Warhammer Dark Omen / Singleplayer / Re: Further CTL investigation on: April 26, 2017, 01:49:15 PM
Thanks for your observations. About search and attack enemy did you see my post in this thread from 2 years ago? Based on my latest findings I'm updating the table:

Code:
                             distfunc unittype vision nth  dist uflag1 attribs op
find_enemy_uflag_attrib      0        0        0      1    100  arg2   arg3    a2
find_enemy_visible           0        0        1      1    100  0      0       a3
find_enemy_simple            1        0        0      1    100  0      0       a4
find_enemy_simple_visible    1        0        1      1    100  0      0       a5
find_enemy_unittype          0        arg2     0      1    100  0      0       a6
find_enemy_unittype_2        0        arg2     0      1    100  0      0       a7
find_enemy_nth               0        0        0      arg2 100  0      0       a8
find_enemy_nth_visible       0        0        1      arg2 100  0      0       a9
find_enemy_unittype_nth      0        arg2     0      arg3 100  0      0       aa
find_enemy_unittype_nth_2    0        arg2     0      arg3 100  0      0       ab
find_enemy_distance_uflag    4        0        0      1    arg2 arg3   0       ac

All of them generate arg1 as an event.

- distfunc: Looks like 0 is the direct (diagonal) distance, 1 just considers x or y (bounding box I guess), 4 is some smart thing that considers terrain e.g. (probably useful for archers).
- unittype: Unittype that the searched unit MUST have.
- vision: When 1 the vision of the caller is considered (worse when walking or fighting), except if you have 360° vision (spider) they always find everything
- nth: Not completly sure, my guess is the list of found regiments is sorted and then the n-th regiment is picked (where 1 = the closest)
- distance: Search distance used for the distfunc (not sure how big a 100 is)
- uflag1_xtra: Unit Flag 1 bits that searched unit most NOT have, inactive/retreating and similiar units are never found
- attribute: Attributes that the searched unit must NOT have, e.g. 4096 = engine of war
This is absolutely GREAT
This improve my chance of create smarter units A LOT

Going on studying the rest of the post
3  Warhammer Dark Omen / Singleplayer / Re: Further CTL investigation on: April 26, 2017, 01:45:09 PM
I don't know python language
I only understood that the translation hex=>opcode and back is done reading the "opNames" array and thus I undestood that simply adding a line like "0x5b:"unit_rout," in that array will make the code translation.

Thanks anyway
4  Warhammer Dark Omen / Singleplayer / Re: Further CTL investigation on: April 26, 2017, 09:19:36 AM
Perfect, thanks
5  Warhammer Dark Omen / Singleplayer / Re: Further CTL investigation on: April 26, 2017, 08:54:31 AM
This new ctldis.py do not work for me
I tryed to decompile B102 and recived this

Code:
 File "C:\Users\rcoletta\Desktop\ctldis\ctldis-master\ctldis-master\ctldis.py", line 531
    decompiledFunc.lines.append([opName, *newLine])
                                         ^
SyntaxError: invalid syntax
6  Warhammer Dark Omen / Singleplayer / Re: Further CTL investigation on: April 26, 2017, 08:37:39 AM
AWESOME
Thanks everyone... I'll study it better
7  Warhammer Dark Omen / Singleplayer / Re: Further CTL investigation on: April 23, 2017, 10:49:41 AM
Last days I had several intense CTL/EVENTS testing sessions. Chaged the code forward and backward, adding “play_self” and “play_other” OpCodes here and there; commented, changed handlers, added and removed undocumented code a lot of time. It was hard and fun, sometimes frustrating.
I undestands things a bit better now, and I add my consideration for the good of the community. Feel free to correct, comment and eventually use any part of this in the way you think it's better.
This is a VERY long post, thus take your time if you're interested in deep CTL analysis

EVENTS HANDLING
All units use the same way to handle events.
There is a “base” function (.func 121) that handles some events (66, 68, 69, 61, 65, 78, 48, 54, 1, 25, 57, 26, 9, 14, 22, 24, 48, 2, 5, 11, 10, 8, 16, 28, 29, 17) in the same way for all units.
There is a “specialized” function for each unit type (Ground units 122, Artillery 123, Wizards 124, Archers 125... didn't verified it there are other functions like “monster” or the like) that handles other events in a different way for for each unit type. The specialized function always call the “.func 121” base function after doing his event handling.
Each unit has his “personal” event handler, that can “override or complete” events controlled by “base” and “specialized” functions (or handle events unhandled) and then simply “call” the specialized function
An example of event handler for an infantry or cavalry is
Code:
.func 14
clear_ctrl_flag 8
do
get_event
on_event 4
#44
set_return_func_iftrue 127
end_event 6844
call 122
@0xABC
test_more_events
while
return_from_event_handler
In this simple handler example, we want the troup to do something different from “standard” for event 4 (the event generated by “search_and_attack_enemy 4, 0, 4096”) and then “call 122” to make the rest of the events to be handled in “standard way”.
If you use “end_event 6844”, this particular event (in our example “event 4”) will not be handled by other handlers, the script will jump to the 0xABC label and the next event will be handled. If you use “end_event 3567”,  the event will be eventually handled by other “on_event 4” statements in “base” and “specialized” functions.

This is the way events for enemy troups are handled in all  maps and thus the way we can do for our campaigns. Make an handler to manage some events, using “ end_event 6844” to completely ovveride en event or “ end_event 3567” to make some things happens before standard handling, and then call the correct specialized function (122, 123, 124, 125) to handle “standard” event actions.

I looked for event understanding since I started to make my personal campaign, because I felt immediatley that is the place where the secret of the perfect AI live.
This were all my “discoveries”

EVENTS
 - 61. Hit by ranged attack (spell too). The event seems to fire only if at least one shot landed (no matter if no casuality done because the unit is saved by armor or shield of plotos). Thus if a unit is under fire but for that round not a single hit reach the target, the event isn'f fired.
 - 5. Event fired when unit is being charged, in the moment the charge start (before the actual fight start, but after the “Charge!” cry is sent)
 - 10. The actual hand to hand fight started (no matter who was the charger)
 - 12. “Lost a hand to hand fight round or charged in the flank/rear” AND “failed the leadership test”. Usually this send back to “.func 126” (Artillery) or “.func 132” (all other unit type) that contains istruction to make the unit rout.
 - 22. Friendly unit completely destroyed
 - 52. Some heavy damage sustained by ranged attacks. I cannot say the correct value, but if a unit loses something around 25% of its alive members, this event fire up.
 - 79. Hit by a spell (fired before event 61).
 - 15. Enemy flee the hand to hand combat (rout)
 - 16. Unit succesfully regroup after routing
 - 25. Regroup after pursuing an enemy.
 
CTL OPCODES
 - #5b and #5d. This codes send the unit routing no matter what (I tried immune to fear and will never rout, but the code still send the unit retreating. I will try to update my “ctldis.py” and call this cod “unit_always_rout1” and “unit_always_rout1”.
 - test_self_afraid. First I thought this was a “test if the unit fail a fear test”, while it simply means that the unit is “vulnerable to fear”. Unit with “Will never rout” and/or “immune to fear”, always pass this test, while all other units always fail the test
 - search_and_attack_enemy. Big issue here. This opcode, diffently from what I thought and undestood at first read, DO NOT make the unit really start to go to the fight, but only verify if there is some possible enemy in sight, set the conditional flag to true and fire the arg1 event for the unit. Thus “search_and_attack_enemy 4, 0, 4096” will fire event 4 for this unit if there is an enemy in sight to fight, but the unit will stand still and go on doing what it was doing.  The event handler, for event “4”, usually contains “#44” and “set_return_func_iftrue 127”. In this “.func 127” there are these opcodes: “#14 4, -1”, “#48”, and finally “#4f”. This three codes will make the unit move versus the designed enemy and fight if they “contact”. To make the unit “charge” when at range, it is first tested that the enemy unit is at the right range to be charged (#58) and then (if true) the charge action is launched (#59). A better name for “search_and_attack_enemy” could be "test_enemy_to_attack_in_sight".
All this, in B101.CTL, this is performed by this code.
In “.func 0” there is this:
Code:
search_and_attack_enemy 4, 0, 4096
that fire the event “4” that is handled by “.func 14” with this code:
Code:
            on_event 4
                #44
                set_return_func_iftrue 127
                end_event 6844
And then all the functions called starting from ".func 127"
Code:
.func 127
    #14 4, -1
    send_event_to_stored_unit 20
    wait_unit_flag1_clear 16392
    play_self 1
    #48
    #4f
   ;now the unit start to walk toward the enemy
    do
        for 2
            set_timer 10
            #58
            ;#58 => test if the enemy is in range for charging
            goto_iftrue 129
            wait_for_timer
            test_unit_flag1 16
            iftrue
                restore_ip
            endif
        next
        #49
    always


.func 129
    #59
    ; #59 => Charge
    iftrue
        play_self 2
        #14 19, -1
        do
            sleep
            #b0 0
            test_unit_flag1 16
        whilenot
    endif
    goto 134


.func 134
    hold
    sleep
    wait_unit_flag1_clear 8
    #50
    restore_ip
   “.func 134” seems to be the end of the battle and is fired if the charge failed (#59 returned false) or the “unit_flag1 16” is 0 (I think this mean the unit is still fighting, pursuing or locked to attack an enemy).
 - search_and_shot_enemy. Apply the same consideration made on "search_and_attack_enemy". A better name could be "test_enemy_to_shot_in_sight"
 - #44. It's used to make some test and always followed by some sort of “set_return_func” statement to make the unit start a fight (usually .func 127). I'm sure the test is failed if the unit is routing. I can reasonably suppose that “#44” is a test for being sure the unit is “able to fight” (unit alive and not routing/fleeing/paralyzed/pursuing). I will try to update my “ctldis.py” and call this opcode “test_unit_can_fight”
 - #14. This is probably the not-documented opcode most used out there... being able to understand what this damn code do, could be an big improvement of CTL understanding
 - return. What's the meaning of any istruction after a “return” statement? It look like “wasted code”, isn't it? As an example, in B101, you find in “.func 122” a “return” statement followed by some othere statemens that I do not see how they can be executed and thus I cannot see their pourpose.
 - #58. Verify if the enmy unit is at the right range to be charged. I will try to update my “ctldis.py” and call this opcode “test_charge_range”
 - #59. Charge. I will try to update my “ctldis.py” and call this opcode “charge2” (because there still is another “charge” OpCode)
UNIT FLAGS
I find that a lot of “test_unit_flagX n” and “wait_unit_flagX_clear n” are made without apparently being any “set_unit_flagX n” (or clear) being anywhere. Is it possible that some of these flag are set/cleared by default in some situations?
There are “wait_unit_flag3_clear, wait_unit_flag3_set, test_unit_flag3”, but there isn't any “set” or “clear” for flag3... What does this mean? In B101.CTL there is “wait_unit_flag3_clear 8192”... this means that flag3 update is hardcoded in the game. This make manipulation of flags a bit dangerous if not perfectly understood, and thus I suggest to use “unit registers” instead of “unit_flags”, unless you know what you're doing

Hope this hepls someone to improve in CTL understanding
8  Modifications / Maps / Re: Moving Buildings/Huts/Objects around MAPS on: April 18, 2017, 03:32:41 PM
Looking forward to start  Grin
9  Modifications / Maps / Re: Moving Buildings/Huts/Objects around MAPS on: April 18, 2017, 11:15:11 AM
I didn't undestand everything you wrote, but I think it will be better when I got all the "files" and play with them for a while... Once I did some experiments, I can put down a list of "questions" if needed.

I played a lot with CTL, thus I can create now a map with an "immobile" enemy. This will allow me to walk the map all around to verify all object are correctly placed, blocking movement and eventyally line of sight.

I think that after an initial slow start, we will push ahead with all the maps very quickly

We will need a good "file send/recive" method... I can send you my private email by PM if files aren't too big.
10  Modifications / Maps / Re: Moving Buildings/Huts/Objects around MAPS on: April 18, 2017, 09:58:50 AM
Hey Olly

I'm still here, ready to work on btb files
I though the better way to do this:

1) You send me the "original" .bmp file
2) You send me a "modified" .bmp file with indication about where to put things (like a simple colored "circle" on the image: green circle is a "tree", red circle is a "big rock" and so on...)
3) If needed, you send me the sprites too (if the object to be put is not a "standard" object but a new object not included in original Dark Omen)

With these three things, I can try to copy a .prj file from a similar dimension map, add and remove objects in the prj file and then edit a btb.xml file to create the correct boundaries for all object on the map

I need only some explanation about the region chunks in BTB file that I didn't understand completely
11  Modifications / Campaigns / Re: New Campaigns: Questions and suggestions on: April 13, 2017, 09:50:19 AM
Another event consideration
On b1_01, there is this code
Code:
on_event 66
        play_self 4
        #95 0
        iftrue
             play_self 5
            #8e
        endif
        end_event 6844
play_self 4 is "Retreat!"
play_self 5 i "We fear the enemy"

Thus, it look like event 66 is "route during battle" and #95 0 is something to do with "fear" (return true if the route reason is fear?)
12  Modifications / Campaigns / Re: New Campaigns: Questions and suggestions on: April 12, 2017, 09:59:46 PM
CTL EVENTS
By now I'm good confident about these
6   Charge button clicked (one way to charge, not the only one)
9   Target selected (spell or fire)
16   Regroup
25   Regroup after pursuing
61   Hit by ranged fire or spell
73   Spell cast
71   Seems to be enemy in range or approaching. Fire multiple times until the unit start to fire or is engaged
52   Unit suffered loss from range (do not fire always, probably when the loss are of some minimum value)
79   Hit by spell (Spells fire both this event and event 61)
58   Enemy approaching/charghing
65   Target lost/Enemy lost (ranged/melee)
64   Charged

It's very difficult to follow the path of those damn absurd function calling eachother on and back... I will like to meet these "great" programmers and ask them WHY LIKE THIS?

By the way

Event 3
Goblin archer event 3 change the return function to 110, where there are some "play_self 23" ("target recived"), conditioned to some unknown tests (probably somethig that always fail, like testing it's a player unit, because goblin never say "Target recived" with human voice). Does it means event 3 is "target recived" like event?

Event 4
Goblin infantry event 4 send back to 139 with some test that can send to 129 where it "play_self 2" (charge!) after a test (probably verify that it's a player and not an enemy)
I think event 4 can be the start of a charge obtained not clicking the charge button (that is event 6) but clicking on opponent banner or by a "search_and_attack_enemy"

Event 69
Goblin archers event 69 has the chance to send back to 111 that send to 115 where there are some "play_self 10" (Open Fire). 69 is probably the start firing event for archers

I think I've to give up on this... I cannot do more than this... too many nested and conditioned  calls (undocumented/untranslated conditions istructions)...

 Undecided

13  Modifications / Campaigns / Re: New Campaigns: Questions and suggestions on: April 12, 2017, 08:39:25 PM
hahahahah
Great, thanks. Problem solved!
14  Modifications / Campaigns / Re: New Campaigns: Questions and suggestions on: April 12, 2017, 04:41:54 PM
Trying to figure out how to lessen the starting gold, I decided to include only 1 member to all starting units, thus the player will be forced to spend all coins for initial replenish
In this issue, I had to discover the right price for each unit and finally I come out with the right formula.
You probablyl already discovered this, but I didn't find the proper topic and didn't want to bother you with this
Here is my discover

1) Each unit type has a basic “Multiplier” that we will call “M”
Infantry: M = 1
Ranged Unit: M = 1,5
Cavalry Unit: M = 2,5
Didn't worked other units types, but i should not be too difficult

2) Each armor value add cost to the unit with this forumula. Only the "base armor" enter in the formula, thus if you buy an upgrade to the unit, the value stay unchanged at the Win32edit "Base armor" value
AV(0) = 0
AV(n) = AV(n-1) +  n*10
Thus we have these results
AV(0) = 0
AV(1) = 10
AV(2) = 30
AV(3) = 60
AV(4) = 100
AV(5) = 150

3) In Wh32Edit we can change the “Point Value”
It's a bit tricky, because it seems that in the unit cost calculation, this value is set to the closer value between 0, 10, 20 or 30. Thus, if you put 22, it will be 20, if you put 8, it will be 10
We call this PV

4) The final cost of a unit follow this formula
T = Unit type (Infantry, Ranged unit, Cavalry)
AL=Armor level
PV=Point Value (0, 10, 20 or 30)
Price(T,AL,P) = 10*M + PV*M + AV(AL)

Example:
A cavalry unit, with “Armor Level” equals to 4 (mounted to not change this value) with Point Value 28 (that will be converted to 30)
Price(Cavalry, 4, 30 ) = 10*2,5 + 30*2,5 + 100 = 25 + 75 + 100 = 200
15  Modifications / Maps / Re: Moving Buildings/Huts/Objects around MAPS on: April 12, 2017, 04:39:21 PM
Oh... that can be done
If you send me the .BTB file and .BMP file and clear me a bit better what to do (how to correctly create the boundary in out.xml) I can give it some try until you're satisfied

If I remember correctly, boundaries are in "Region Chunk" but I sincerly didn't understand what it exactly contains... If you explain me and help me verifying my work on the first maps, I can try the job
Pages: [1] 2 3 4