Jump to content

EXE editing & programming issues


MrFlibble

Recommended Posts

Okay, I figured it out... I got code that works, but your logos are in the wrong order on the CPS: to correspond to H-A-O, they should be in the order F-S-M. They are in the order S-F-M though :P

[edit]

Here ya go:

You need to do 2 things... first, replace both occurrences of

cmp houseHumanID, 0 ; minimum house ID

[...]

cmp houseHumanID, 2 ; maximum house ID

by compares with 3 and 5 for the respective minimum and maximum. In a DB of your dunex.exe, they should be located at ovr207:0B56 and ovr207:0B9E

In your exe, that's offset 578EA and 578F1 for the first one, and 57932 and 57939 for the second.

Then there's the piece where I subtract 3 from the house ID (well, a copy of it)... this is a bit long, since I had to free up some space a bit further in the code, meaning the code in between is moved down a bit. Luckily, there was an opportunity to free up the required bytes only about 15 bytes further :)

At 578F7, replace the current code by these bytes:

EB14 A1383A BA3800 83E803 F7EA 050800 B103 D3F8 8BF8 B80200 50 50

In case you're interested, the actual new code of this is:


#eip=61A87 ; 578F7
EB14 jmp .skipHouseCode
A1383A mov ax, houseHumanID
BA3800 mov dx, 38h
83E803 sub ax, 3 ; NEW INSERTED COMMAND: subtraction to shift FSM to HAO
F7EA imul dx
050800 add ax, 8
B103 mov cl, 3
D3F8 sar ax, cl
8BF8 mov di, ax
skipHouseCode:
B80200 mov ax, 2
50 push ax
; REMOVED TO GET FREE SPACE: B80200 mov ax, 2
50 push ax

As you see, I removed a command there to free up space to be able to insert the "sub ax, 3" command earlier in the code. That second "mov ax, 2" command wasn't needed anyway, since ax was already put to "2" :)

So yeah, this code, and an adaption of your CPS to put the logos in the right order, and you're set. I attached a fixed CPS that worked for me :)

Hello all users,

I wanted to try playing a campaign Atreides, but using the modified game files DUNEX.exe.

I was able to restore the original texts of the missions and orders of mentats editing the yours EXPAND.PAK file...

but I can't get the original colors of the three houses (Atreides, Harkonnen and Ordos) in the hall of fame and scores (YOU:, ENEMY:) of the scores at the end of the missions!

For example: dune2comp.png

Nyerguds (or MrFibble if you know how to do), can you create another file FAME.CPS that can adapt to my DUNEX.exe modified?

Thanks & Reguards.

Link to comment
Share on other sites

I wanted to try playing a campaign Atreides, but using the modified game files DUNEX.exe.

I was able to restore the original texts of the missions and orders of mentats editing the yours EXPAND.PAK file...

but I can't get the original colors of the three houses (Atreides, Harkonnen and Ordos) in the hall of fame and scores (YOU:, ENEMY:) of the scores at the end of the missions!

For example: dune2comp.png

Nyerguds (or MrFibble if you know how to do), can you create another file FAME.CPS that can adapt to my DUNEX.exe modified?

Why don't you just use the original DUNE2.EXE to play the Atreides (or any other of the original Houses) missions? Editing the original stuff back in DUNEX is both a lot of work and quite pointless.

Link to comment
Share on other sites

I spoke in private also with Nyerguds... :happy:

basically because I wanted to play the campaign so that the new units (Fremen Warriors and Sardaukar Trooper) are present in the game. I try to change the original file DUNE2.exe, but is too complicated for my idea...

for example, I tried to change the Infrantry transforming the unit into Fremen Warriors with the editor d2editor, but I have found some problems, such as the fact that they non-fired mini-rocket missiles, rather with the machine gun...

For this reason (and more others) I decided to use the file DUNEX.exe and not the original DUNE2.exe, thus modifying only the .PAK files as EXPAND.PAK.

So, how can I change the bar-color in the hall of fame?

These is a image in game: http://desmond.image...jpg&res=landing

I played with the Atreides a my scenario and at the end of the mission the scores bar is colored violet (as Sardaukar faction!).

It's a shame because I lost hours of work to change almost everything, making the game visually acceptable. :unsure:

P.S. However I'm drnovice's brother, I see that also him has posted in this discussion! :)

Link to comment
Share on other sites

basically because I wanted to play the campaign so that the new units (Fremen Warriors and Sardaukar Trooper) are present in the game. I try to change the original file DUNE2.exe, but is too complicated for my idea...

for example, I tried to change the Infrantry transforming the unit into Fremen Warriors with the editor d2editor, but I have found some problems, such as the fact that they non-fired mini-rocket missiles, rather with the machine gun...

For this reason (and more others) I decided to use the file DUNEX.exe and not the original DUNE2.exe, thus modifying only the .PAK files as EXPAND.PAK.

So, how can I change the bar-color in the hall of fame?

Trust me, it's still a lot easier to make the changes you want in DUNE2.EXE rather than go through DUNEX.EXE to clean up all the changes you do not need.

The editor alone isn't enough for some things, like the machinegun/rocket combo for infantry. There's a piece of code that makes the Trooper weapon change to rockets from machinegun if the range is greater than 2:


seg030:16A6 loc_26D96: ; CODE XREF: scriptFunctionUnitAttack:loc_26D79j
seg030:16A6 ; scriptFunctionUnitAttack+250j
seg030:16A6 C4 1E 52 62 les bx, scriptUnitGamePtr ; Load Full Pointer to ES:xx
seg030:16AA 26 80 7F 02 03 cmp es:[bx+_unitGame.typeIndex], 3 ; Troopers
seg030:16AF 74 0B jz short distanceCheck ; Jump if Zero (ZF=1)
seg030:16B1 C4 1E 52 62 les bx, scriptUnitGamePtr ; Load Full Pointer to ES:xx
seg030:16B5 26 80 7F 02 05 cmp es:[bx+_unitGame.typeIndex], 5 ; Trooper
seg030:16BA 75 0C jnz short loc_26DB8 ; Jump if Not Zero (ZF=0)
seg030:16BC
seg030:16BC distanceCheck: ; CODE XREF: scriptFunctionUnitAttack+260j
seg030:16BC 81 7E EC 00 02 cmp [bp+objectDistance], 200h ; Compare Two Operands
seg030:16C1
seg030:16C1 loc_26DB1: ; Jump if Less or Equal (ZF=1 | SF!=OF)
seg030:16C1 7E 05 jle short loc_26DB8
seg030:16C3 C7 46 F8 16 00 mov [bp+weaponTypeIndex], 16h
seg030:16C8
seg030:16C8 loc_26DB8: ; CODE XREF: scriptFunctionUnitAttack+26Bj
seg030:16C8 ; scriptFunctionUnitAttack:loc_26DB1j
seg030:16C8 8B 5E F8 mov bx, [bp+weaponTypeIndex]
seg030:16CB 83 EB 13 sub bx, 13h ; switch 7 cases
seg030:16CE
seg030:16CE loc_26DBE: ; Compare Two Operands
seg030:16CE 83 FB 06 cmp bx, 6
seg030:16D1 76 03 jbe short loc_26DC6 ; Jump if Below or Equal (CF=1 | ZF=1)
seg030:16D3 E9 89 01 jmp loc_26F4F ; default

You can see that in the beginning, it checks if the current unit is a Trooper or a Trooper squad; otherwise it skips the code. To extend this to regular infantry, I had to change this part to check if the unit id is less or greater than the range that includes both Trooper and Infantry units' IDs.

So I suggest that you simply list what features from DUNEX you want in your Dune II besides the new units. Mind though that This change will also mean that the Atreides will either have no regular infantry at all or only Troopers, and that the infantry spawned from destroyed structures and vehicles should be either turned off completely or replaced by Troopers.

Link to comment
Share on other sites

Thanks MrFlibble you for your help, you're great... :)

I was able to modify the strings that concerned the ID as you suggested and now my Soldier/Infantry modified into Warrior/s firing mini-rockets. ;)

But Raider Trike changed into Sardaukar Trooper when I give orders to Attack it's blocked and don't fire!

Maybe it's about to change for them, but I was especially interested in the fact that you (and who helped you to do) have improved the AI in order to make the game more difficult and challenging (remember playing a scenario with the Sardaukar when the Fremen opponent attacked me with 4 Launchers for once!). For this reason I chosen to playing this campaign with modified DUNEX.exe.

Regarding the fact that the Soldiers survived out from vehicles exploded and destroyed bases, I saw that you put the odds of this happening to 0%, otherwise it would come out Warrior instead of Soldier and this would not make sense!

Link to comment
Share on other sites

But Raider Trike changed into Sardaukar Trooper when I give orders to Attack it's blocked and don't fire!

This is weird, are you sure you copied all the data from the Trooper correctly? (That's how I did that, just replicated data settings of a Trooper and only changed HP, attack, ROF and speed settings).

Maybe it's about to change for them, but I was especially interested in the fact that you (and who helped you to do) have improved the AI in order to make the game more difficult and challenging (remember playing a scenario with the Sardaukar when the Fremen opponent attacked me with 4 Launchers for once!). For this reason I chosen to playing this campaign with modified DUNEX.exe.

What I did with the AI doesn't have to do with editing the EXE, it's an original option that was build into the game but got never used, the so-called team bug. Basically, the AI did not use attack teams of vehicles in Dune II because the scripts for the teams (found in the scenario files) misspelled team types.

What I did though was change priority levels for Turrets and Rocket Turrets via Nyerguds' editor, which forces the AI to attack the player's base defences first (for some reason the priority levels for turrets was exceptionally low in the original game, maybe because turrets don't count as structures by the "all structures destroyed" win/lose trigger). This parameter is called "Threat level" in the editor IIRC. You can experiment with the parameters to accomplish interesting results, the AI in DUNEX is certainly harder because it doesn't ignore base defences which is coupled with attacking by groups of vehicles.

Regarding the fact that the Soldiers survived out from vehicles exploded and destroyed bases, I saw that you put the odds of this happening to 0%, otherwise it would come out Warrior instead of Soldier and this would not make sense!

Actually I think Segra found the part in the code responsible for what unit should spawn from what. However, with the missile fix you can also transform Infantry into Troopers and Troopers into Fremen to avoid the problem entirely.

Here's a chunk that might be responsible for spawning infantry, but I haven't tested it (might be the spawn from infantry squads code):

seg031:0D66                   loc_290C6:                                                  ; CODE XREF: unitTakeDamage+1DAj
seg031:0D66 C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xx
seg031:0D69 26 80 7F 02 03 cmp es:[bx+_unitGame.typeIndex], 3 ; Troopers
seg031:0D6E 74 0A jz short TrooperInfantry ; Jump if Zero (ZF=1)
seg031:0D70 C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xx
seg031:0D73 26 80 7F 02 02 cmp es:[bx+_unitGame.typeIndex], 2 ; Infantry
seg031:0D78 75 79 jnz short loc_29153 ; Jump if Not Zero (ZF=0)

Link to comment
Share on other sites

Very interesting... :)

I noticed that you have imported a different the value "Treat level for AI" with the d2editor. This actually makes the AI ​​more similar to human actions since it first hit the defense turret to avoid being decimated during an attack... simple and ingenious! ;)

Thanks for the advice for spawning Infantry, I will try also this...

Besides MrFlibble do you know this fantastic scenario editor?

http://dunemaps.sourceforge.net/

Link to comment
Share on other sites

I still don't understand this function:


seg023:0F78 loc_231A8: ; CODE XREF: isFriendly?:loc_231A4j
seg023:0F78 83 FA 03 cmp dx, 3 ; DX = object
seg023:0F7B 74 05 jz short isFremen ; Jump if Zero (ZF=1)
seg023:0F7D 83 FB 03 cmp bx, 3 ; BX = human
seg023:0F80
seg023:0F80 loc_231B0: ; Jump if Not Zero (ZF=0)
seg023:0F80 75 0E jnz short notFremen
seg023:0F82
seg023:0F82 isFremen: ; CODE XREF: isFriendly?+20j
seg023:0F82 83 FA 01 cmp dx, 1 ; Compare Two Operands
seg023:0F85
seg023:0F85 loc_231B5: ; Jump if Zero (ZF=1)
seg023:0F85 74 05 jz short isAtreides
seg023:0F87
seg023:0F87 loc_231B7: ; Compare Two Operands
seg023:0F87 83 FB 01 cmp bx, 1
seg023:0F8A
seg023:0F8A loc_231BA: ; if object is Fremen, and Human is Atreides, Ret True
seg023:0F8A 75 02 jnz short notAtreides
seg023:0F8C
seg023:0F8C isAtreides: ; CODE XREF: isFriendly?:loc_231B5j
seg023:0F8C EB 10 jmp short retTrue ; Jump
seg023:0F8E ; ---------------------------------------------------------------------------
seg023:0F8E
seg023:0F8E notAtreides: ; CODE XREF: isFriendly?:loc_231BAj
seg023:0F8E EB DE jmp short retFalse ; Jump
seg023:0F90 ; ---------------------------------------------------------------------------
seg023:0F90
seg023:0F90 notFremen: ; CODE XREF: isFriendly?:loc_231B0j
seg023:0F90 3B 16 2C 3A cmp dx, houseHumanID ; Compare Two Operands
seg023:0F94
seg023:0F94 loc_231C4: ; Jump if Zero (ZF=1)
seg023:0F94 74 06 jz short objectIsHuman
seg023:0F96
seg023:0F96 loc_231C6: ; Compare Two Operands
seg023:0F96 3B 1E 2C 3A cmp bx, houseHumanID
seg023:0F9A
seg023:0F9A loc_231CA: ; if object is not human, and house is not human, ret true
seg023:0F9A 75 02 jnz short retTrue
seg023:0F9C
seg023:0F9C objectIsHuman: ; CODE XREF: isFriendly?:loc_231C4j
seg023:0F9C EB D0 jmp short retFalse ; Jump

In the case where dx=1 (object is Atreides) and bx=1 (human is Atreides) function jump to "notFremen" point, that check if dx and houseHumanID are equal and then if bx is equal to houseHumanID.

So if houseHumanID=1 and also dx=1 (object is Atreides) then jump to "objectIsHuman" point, so why return false? It should another check (for example if dx not equal bx) first to return false (non-friendly unit)

Link to comment
Share on other sites

I managed to adjust number of Sandworm eating before disappearing! :laugh: Now if you want, you can set 4, 5, 6, ... even 9 or more eating, both to pre-placed or spawned Sandworms.

Do you remember this chunk of code:


seg015:0532 83 7E 08 19 cmp [bp+TypeIndex], 19h ; Sandworm
seg015:0536 75 08 jnz short notWorm ; Jump if Not Zero (ZF=0)
seg015:0538 C4 5E FC les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xx
seg015:053B 26 C6 47 58 03 mov es:[bx+_unitGame.HarvesterSpiceCapacity], 3

it's reported to capacity of pre-placed Sandworms only, while those spawned have 0 capacity (don't ask me why or even where it's indicated), so:


seg030:178C 26 FE 4F 58 dec es:[bx+_unitGame.HarvesterSpiceCapacity]
seg030:1790
seg030:1790 loc_26E80:
seg030:1790 8B 46 08 mov ax, word ptr [bp+scriptData+2]
seg030:1793 8B 56 06 mov dx, word ptr [bp+scriptData]
seg030:1796 89 46 DC mov word ptr [bp+var_26+2], ax
seg030:1799 89 56 DA mov word ptr [bp+var_26], dx
seg030:179C 83 6E DA 02 sub word ptr [bp+var_26], 2 ; Integer Subtraction
seg030:17A0 C4 5E DA les bx, [bp+var_26] ; Load Full Pointer to ES:xx
seg030:17A3 26 C7 07 0C 00 mov word ptr es:[bx], 0Ch
seg030:17A8 C4 1E 52 62 les bx, scriptUnitGamePtr ; Load Full Pointer to ES:xx
seg030:17AC 26 80 7F 58 01 cmp es:[bx+_unitGame.HarvesterSpiceCapacity], 1 ; Compare Two Operands
seg030:17B1 7D 13 jge short loc_26EB6 ; Jump if Greater or Equal (SF=OF)
seg030:17B3 B8 0A 00 mov ax, 0Ah ; die
seg030:17B6 50 push ax ; action
seg030:17B7 FF 36 54 62 push word ptr scriptUnitGamePtr+2
seg030:17BB FF 36 52 62 push word ptr scriptUnitGamePtr ; unitGamePtr
seg030:17BF 0E push cs
seg030:17C0 E8 42 E8 call near ptr unitActionstart ; Call Procedure
seg030:17C3 83 C4 06 add sp, 6 ; Add
seg030:17C6
seg030:17C6 loc_26EB6: ; CODE XREF: scriptFunctionUnitAttack+362j
seg030:17C6 A1 54 62 mov ax, word ptr scriptUnitGamePtr+2
seg030:17C9 8B 16 52 62 mov dx, word ptr scriptUnitGamePtr
seg030:17CD 89 46 FE mov word ptr [bp+unitGamePtr+2], ax
seg030:17D0 89 56 FC mov word ptr [bp+unitGamePtr], dx
seg030:17D3 E9 8B 00 jmp loc_26F51 ; Jump

game subtract 1 to the capacity and new value is compared to 1: if greater or equal ( >= ) then jump to "loc_26EB6" point, so no action "Die" is performed if value isn't less than 1 (=zero).

But if capacity of spawned Sandworms start to 0, you just add 1 to capacity (instead of subtract) and swap jge to jl check so can obtain:

seg030:178C 26 FE 47 58 inc es:[bx+_unitGame.HarvesterSpiceCapacity]

setting number of eating:

seg030:17AC 26 80 7F 58 06 cmp es:[bx+_unitGame.HarvesterSpiceCapacity], 6 ; Compare Two Operands

seg030:17B1 7C 13 jl short loc_26EB6 ; Jump if Less

et voilà le jeux sont fait! ;)

Now if we want have the same for pre-placed Sandworms just reset to 0 start of capacity:

seg015:053B 26 C6 47 58 00 mov es:[bx+_unitGame.HarvesterSpiceCapacity], 0

About control ingame of Sandworms I advice to set these command buttons:

Attack: the only command that can redirect Sandworm in a precise point choose by human player

Hunt: it will attack anything (enemy or friendly) closer and precious

Die: to remove a worm in an area not required

Area Guard: less aggressive, it will attack only enemy units approaching to own base

post-2188-0-27123100-1344289938_thumb.jp

  • Upvote 1
Link to comment
Share on other sites

Yes I thought to change possibility of single Warrior into Sandworm. If object should be placed into rock, simply it doesn't appear in the map. Same thing if there are already TWO Sandworms in the map.

Note that Fremen Palace-created units are set to Hunt, so also Sandworm do this.

Now I'm looking for the other complex issue: how the Fremen AI works respect Atreides Human.

I noticed that "shared visions" doesn't depend (or doesn't only depend) about "AtreFre" chunk of code, because if you change only on isFriendly? function 03 Fremen ID to another faction (e.g. 02 Ordos ID), "shared visions" swap into new faction and Atreides Human no more sees Fremen units, but can see new faction units.

I tested a scenario with 03 Fremen ID changing in 02 Ordos ID on isFriendly? function and Ordos units in Hunt/Area Guard command attack Fremen units (now enemy of human) as well. So this can tell us that there isn't a specific chunk of code that change Fremen AI when isFriendly? is refered to their, but it works for all factions, admitted that second 01 Atreides ID checks are set.

But the curiosity is that if after you change on "AtreFre" chunk of code, 03 Fremen ID to 02 Ordos ID, Ordos friendly units don't attack more Fremen units, simply do nothing (like when you control Fremen and Atreides AI do nothing).

Link to comment
Share on other sites

lol, so worms effectively 'harvest' units they eat, then? :laugh:

I still don't understand this function:

...

In the case where dx=1 (object is Atreides) and bx=1 (human is Atreides) function jump to "notFremen" point, that check if dx and houseHumanID are equal and then if bx is equal to houseHumanID.

So if houseHumanID=1 and also dx=1 (object is Atreides) then jump to "objectIsHuman" point, so why return false? It should another check (for example if dx not equal bx) first to return false (non-friendly unit)

That's probably just related to internal handling. All stuff from the human-played side is friendly to each other anyway, so I doubt it's normally handled in this function.

Link to comment
Share on other sites

The problem is:

; if object is Fremen, and Human is Atreides, Ret True

and

; if object is not human, and house is not human, ret true

Apparently it seems that all factions are checked and different non-Fremen&non-Atreides AI also needs to check if isFriendly to others AI in the map.

But "return true" to funcion means set ax=1 ? So "return false" is ax=0 ?

I'm looking for all times isFriendly? function is invoked but I saw that sometimes if code expects friendly faction check is made on jz, other times check is made on jnz...

e.g. 1


seg002:012C 9A 2A 36 36 28 call unitGameHouseIDGet
seg002:0131 59 pop cx
seg002:0132 59 pop cx
seg002:0133 50 push ax ; objectHouseID
seg002:0134 9A 5B 0F 23 22 call isFriendly? ; Call Procedure
seg002:0139 59 pop cx
seg002:013A 59 pop cx
seg002:013B 0B C0 or ax, ax ; Logical Inclusive OR
seg002:013D 74 03 jz short loc_15142 ; Jump if Zero (ZF=1)
seg002:013F
seg002:013F loc_1513F: ; Jump
seg002:013F E9 AC 01 jmp unitNext
seg002:0142 ; ---------------------------------------------------------------------------
seg002:0142
seg002:0142 loc_15142: ; CODE XREF: sub_15008+135j
seg002:0142 FF 76 F2 push word ptr [bp+unitGamePtr+2]
seg002:0145 FF 76 F0 push word ptr [bp+unitGamePtr]
seg002:0148 9A 32 06 ED 1D call unitGetTeamPtr ; Call Procedure
seg002:014D 59 pop cx
seg002:014E 59 pop cx

e.g. 2


seg023:0B8E 26 8A 47 08 mov al, es:[bx+_unitGame.houseID]
seg023:0B92 98 cbw ; AL -> AX (with sign)
seg023:0B93 50 push ax ; objectHouseID
seg023:0B94 90 nop ; No Operation
seg023:0B95 0E push cs
seg023:0B96 E8 C2 03 call near ptr isFriendly? ; Call Procedure
seg023:0B99 59 pop cx
seg023:0B9A 59 pop cx
seg023:0B9B 0B C0 or ax, ax ; Logical Inclusive OR
seg023:0B9D 75 1C jnz short checkHouseID ; Jump if Not Zero (ZF=0)
seg023:0B9F
seg023:0B9F loc_22DCF: ; unit not friendly
seg023:0B9F C4 5E 06 les bx, [bp+unitGamePtr]
seg023:0BA2 26 80 7F 4F 08 cmp es:[bx+_unitGame.actionCurrent], 8 ; Compare Two Operands
seg023:0BA7 75 12 jnz short checkHouseID ; Jump if Not Zero (ZF=0)
seg023:0BA9 B8 0B 00 mov ax, 0Bh ; Hunt
seg023:0BAC 50 push ax ; action
seg023:0BAD FF 76 08 push word ptr [bp+unitGamePtr+2]
seg023:0BB0 FF 76 06 push word ptr [bp+unitGamePtr] ; unitGamePtr
seg023:0BB3 9A 05 00 6F 25 call unitActionstart ; Call Procedure
seg023:0BB8 83 C4 06 add sp, 6 ; Add
seg023:0BBB
seg023:0BBB checkHouseID: ; CODE XREF: sub_22B24+2A9j
seg023:0BBB ; sub_22B24+2B3j
seg023:0BBB C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xx
seg023:0BBE 26 8A 47 08 mov al, es:[bx+_unitGame.houseID]
seg023:0BC2 98 cbw ; AL -> AX (with sign)
seg023:0BC3 3B 06 2C 3A cmp ax, houseHumanID ; Compare Two Operands
seg023:0BC7 74 11 jz short AtreFre ; Jump if Zero (ZF=1)
seg023:0BC9
seg023:0BC9 loc_22DF9: ; Load Full Pointer to ES:xx
seg023:0BC9 C4 5E 06 les bx, [bp+unitGamePtr]
seg023:0BCC 26 80 7F 08 03 cmp es:[bx+_unitGame.houseID], 3 ; Fremen
seg023:0BD1 75 11 jnz short loc_22E14 ; Jump if Not Zero (ZF=0)
seg023:0BD3 83 3E 2C 3A 01 cmp houseHumanID, 1 ; Atre
seg023:0BD8 75 0A jnz short loc_22E14 ; Jump if Not Zero (ZF=0)
seg023:0BDA
seg023:0BDA AtreFre: ; CODE XREF: sub_22B24+2D3j
seg023:0BDA C4 5E 06 les bx, [bp+unitGamePtr] ; unit = fremen and human = atre
seg023:0BDD 26 C6 47 09 FF mov es:[bx+_unitGame.houseRevealed], 0FFh
seg023:0BE2 EB 0A jmp short Done ; Jump

Link to comment
Share on other sites

BTW regarding the sandworms I remember a curious situation that happened when I was testing something (I think it was v1.07) and needed to lose mission 9 (again, can't remember which House but I think it doesn't matter). So I started that mission, used the units I had to destroy the construction yard, and since you have to wait some time after the beginning of the mission (I think one minute or so) for the lose trigger to kick in, instead of doing nothing I sent all my units upwards to the enemy base. As you remember, there's a sandworm halfway to the Sardaukar base there. When one fo the units bumped into it, the sandworms naturally started eating up all of them that were on the sand. The curious thing here is that it did not disappear after eating three, I think it ate all of the units (six starting units plus some infantry from the destroyed conyard), and then the missions was over.

Meaning that some of the gameplay mechanics were no longer in effect after either the destruction of the player's structures, or after the lose trigger conditions were met.

Link to comment
Share on other sites

Maybe Lose Flag was already set, but loop has a timeout of every 1 minute; so check to appear message box is made every 1 minute or whatever is set, but in that time some counters (like harvestCapacity used for Sandworms) are expired.

I tried to set to Die a personal Sandworm in my test scenario (in starting pre-placed units info of .ini) and it is like Destruct command (do you remeber a my previous post?) apart the fact that it was freezed (no movement and no eating). Because of some events don't provide precisely all situations (so much so that Die is a command called from other events and doesn' t selectable by player or usable from the start as it would be Area Guard or Hunt).

Link to comment
Share on other sites

Finally I understand how manage allied AI faction respect human faction! :P

In isFriendly? function definition:


seg023:0F78 loc_231A8: ; CODE XREF: isFriendly?:loc_231A4j
seg023:0F78 83 FA 03 cmp dx, 3 ; DX = object
seg023:0F7B 74 05 jz short isFremen ; Jump if Zero (ZF=1)
seg023:0F7D 83 FB 03 cmp bx, 3 ; BX = human
seg023:0F80
seg023:0F80 loc_231B0: ; Jump if Not Zero (ZF=0)
seg023:0F80 75 0E jnz short notFremen
seg023:0F82
seg023:0F82 isFremen: ; CODE XREF: isFriendly?+20j
seg023:0F82 83 FA 01 cmp dx, 1 ; Compare Two Operands
seg023:0F85
seg023:0F85 loc_231B5: ; Jump if Zero (ZF=1)
seg023:0F85 74 05 jz short isAtreides
seg023:0F87
seg023:0F87 loc_231B7: ; Compare Two Operands
seg023:0F87 83 FB 01 cmp bx, 1
seg023:0F8A
seg023:0F8A loc_231BA: ; if object is Fremen, and Human is Atreides, Ret True
seg023:0F8A 75 02 jnz short notAtreides

first two IDs should indicate allied AI faction, and second two IDs the human faction.

So you can change this, e.g. if you want play Harkonnen as human with Sardaukar AI that is allied so:

seg023:0F78 83 FA 04 cmp dx, 4 ; DX = object

seg023:0F7B 74 05 jz short isFremen ; Jump if Zero (ZF=1)

seg023:0F7D 83 FB 04 cmp bx, 4 ; BX = human

and so:

seg023:0F82 83 FA 00 cmp dx, 0 ; Compare Two Operands

seg023:0F85

seg023:0F85 loc_231B5: ; Jump if Zero (ZF=1)

seg023:0F85 74 05 jz short isAtreides

seg023:0F87

seg023:0F87 loc_231B7: ; Compare Two Operands

seg023:0F87 83 FB 00 cmp bx, 0

you can see that when you play Harkonnen as human, Sardaukar are your allied and AI works, but is hostile ONLY against Fremen!

Why?

Because of the first jnz check on "AtreFre" chunk of code:


seg023:0BC9 loc_22DF9: ; Load Full Pointer to ES:xx
seg023:0BC9 C4 5E 06 les bx, [bp+unitGamePtr]
seg023:0BCC 26 80 7F 08 03 cmp es:[bx+_unitGame.houseID], 3 ; Fremen
seg023:0BD1 75 11 jnz short loc_22E14 ; Jump if Not Zero (ZF=0)
seg023:0BD3 83 3E 2C 3A 01 cmp houseHumanID, 1 ; Atre
seg023:0BD8 75 0A jnz short loc_22E14 ; Jump if Not Zero (ZF=0)
seg023:0BDA
seg023:0BDA AtreFre: ; CODE XREF: sub_22B24+2D3j
seg023:0BDA C4 5E 06 les bx, [bp+unitGamePtr] ; unit = fremen and human = atre
seg023:0BDD 26 C6 47 09 FF mov es:[bx+_unitGame.houseRevealed], 0FFh
seg023:0BE2 EB 0A jmp short Done ; Jump
seg023:0BE4 ; ---------------------------------------------------------------------------
seg023:0BE4
seg023:0BE4 loc_22E14: ; CODE XREF: sub_22B24+2DDj
seg023:0BE4 ; sub_22B24+2E4j
seg023:0BE4 C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xx
seg023:0BE7 8A 46 F6 mov al, byte ptr [bp+houseRevealed]
seg023:0BEA 26 08 47 09 or es:[bx+_unitGame.houseRevealed], al ; Logical Inclusive OR

to make allied AI hostile to ALL other AI factions just change jnz check to jz, specifing only human faction:

seg023:0BCC 26 80 7F 08 00 cmp es:[bx+_unitGame.houseID], 0 ; Fremen

seg023:0BD1 74 11 jz short loc_22E14 ; Jump if Zero (ZF=1)

seg023:0BD3 83 3E 2C 3A 00 cmp houseHumanID, 0 ; Atre

However I don't know anyway why only with human set to 01 Atreides and allied AI set to 03 Fremen that jnz check worked...

But the important is that I reached my goal: play Fremen as human with Atreides allied AI working! ;)

Enjoy!

  • Upvote 1
Link to comment
Share on other sites

Wow, this is incredibly cool! ^_^ Great find!

This can make for some neat Fremen Palace weapon combinations. I was thinking alongside the lines of "reinforcements" as either Atreides Sonic Tanks or 'thopters ;) ( >2 'thopters can really do some damage to the enemy bases, even if protected by turrets, and if they're from an allied faction they don't count in the score if you lose 'em).

BTW, I remember that the Fremen AI never builds anything if you're playing as Atreides, so a fully functional allied AI with a base is not possible. Have you addressed this issue yet?

Link to comment
Share on other sites

Yes I know about no production of allied AI faction, I think that it is located in "missionloadIni" function (overlays) but I'm not sure.

We should ask to segra or trueBrain about this if possible, looking for createUnit function or something similar.

Even if I think that giving a Base to allied AI faction will limit operations and resources of human faction, therefore playability and fun in my opinion.

MrFibble, now you can use Atreides allied AI in your Fremen campaign of Dune2 eXtended project. ;)

P.S. About Palace combo, I like set Fremen/Sandworm spawned to the same faction of human player, so you can control them, and capture enemy turrets, while they are busy to own Sandworms! :P

Link to comment
Share on other sites

Any news about Saboteur bugs?

In particular:

More info on the Saboteur detonation: it is also triggered if the tile of the destination point is concrete' date=' wall, mountain or mountain/rock border, sometimes also spice. Plain rock, sand and sand dunes seem not to cause this problem.

On the other hand, the Saboteur sometimes does not detonate when ordered to move into an enemy unit: it just occupies the same cell as the unit it targeted, and can't be selected or given orders unless that unit moves away to another spot. In this stance, the Saboteur can be attacked by either enemy friendly fire, and its explosion will destroy the enemy unit in that cell. Saboteurs can also occupy the same cell as any of the player's own units without destroying them (unless the player's unit occupies a cell that causes the Saboteur to detonate, i.e. concrete).

An important thing to note is that this terrain-triggered detonation of the Saboteur is the cause to the bug where the cell the Saboteur exploded can't be built upon or occupied by another unit anymore, and is still marked by a House-colored dot on the minimap. Moreover, the player's units can be ordered to attack this "trace" of the Saboteur, and if another Saboteur is already spawned from the Palace, the player's units will proceed to attack it (even if it is out of sight, in an unrevealed portion of the map).

[/quote']

Is there anything to fix that can be found into the .exe?

Link to comment
Share on other sites

Is there anything to fix that can be found into the .exe?

Sometime ago I've picked some pieces of code in Segra's DB that he marked as related to Saboteur stuff, but haven't really done anything with them.

Here's one bit that seems to have something to do with the Saboteur's movement on tiles:

seg031:1749                   tileCheck:                                                  ; CODE XREF: unitMoveToTile+C1j
seg031:1749 FF 76 FE push [bp+mapPosition] ; mapPosition
seg031:174C 9A 61 00 D0 42 call j_mapTileTypeGet ; Call Procedure
seg031:1751 59 pop cx
seg031:1752 89 46 F8 mov [bp+tileType], ax
seg031:1755 83 7E F8 0C cmp [bp+tileType], 0Ch ; building
seg031:1759 75 05 jnz short loc_29AC0 ; Jump if Not Zero (ZF=0)
seg031:175B C7 46 F8 0A 00 mov [bp+tileType], 0Ah ; concrete
seg031:1760
seg031:1760 loc_29AC0: ; CODE XREF: unitMoveToTile+D6j
seg031:1760 8B 46 F8 mov ax, [bp+tileType]
seg031:1763 BA 1C 00 mov dx, 1Ch
seg031:1766 F7 EA imul dx ; Signed Multiply
seg031:1768
seg031:1768 loc_29AC8: ; Load Full Pointer to ES:xx
seg031:1768 C4 5E FA les bx, [bp+unitDataPtr]
seg031:176B 26 03 47 3C add ax, es:[bx+_unitData.MovementType] ; Add
seg031:176F 8B D8 mov bx, ax
seg031:1771 8A 87 36 3A mov al, movementTileData[bx]
seg031:1775 B4 00 mov ah, 0
seg031:1777 8B F8 mov di, ax
seg031:1779 C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xx
seg031:177C 26 80 7F 02 06 cmp es:[bx+_unitGame.typeIndex], 6 ; Saboteur
seg031:1781 75 09 jnz short loc_29AEC ; Jump if Not Zero (ZF=0)
seg031:1783 83 7E F8 0B cmp [bp+tileType], 0Bh ; Compare Two Operands
seg031:1787 75 03 jnz short loc_29AEC ; Jump if Not Zero (ZF=0)
seg031:1789 BF FF 00 mov di, 0FFh
seg031:178C
seg031:178C loc_29AEC: ; CODE XREF: unitMoveToTile+FEj
seg031:178C ; unitMoveToTile+104j
seg031:178C C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xx
seg031:178F 26 81 67 04 7F FF and es:[bx+_unitGame.unitState], 0FF7Fh ; Logical AND
seg031:1795 8B 46 F8 mov ax, [bp+tileType]
seg031:1798 BA 1C 00 mov dx, 1Ch
seg031:179B F7 EA imul dx ; Signed Multiply
seg031:179D 8B D8 mov bx, ax
seg031:179F 83 BF 3C 3A 00 cmp word ptr unk_46E5C[bx], 0 ; Compare Two Operands
seg031:17A4 74 09 jz short loc_29B0F ; Jump if Zero (ZF=1)
seg031:17A6
seg031:17A6 loc_29B06: ; Load Full Pointer to ES:xx
seg031:17A6 C4 5E 06 les bx, [bp+unitGamePtr]
seg031:17A9
seg031:17A9 loc_29B09: ; Logical Inclusive OR
seg031:17A9 26 81 4F 04 80 00 or es:[bx+_unitGame.unitState], _emcState_OnRock?
seg031:17AF
seg031:17AF loc_29B0F: ; CODE XREF: unitMoveToTile+121j
seg031:17AF C4 5E FA les bx, [bp+unitDataPtr] ; Load Full Pointer to ES:xx
seg031:17B2 26 8B 47 10 mov ax, es:[bx+_unitData.HitPoints]
seg031:17B6 D1 F8 sar ax, 1 ; Shift Arithmetic Right
seg031:17B8 C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xx
seg031:17BB
seg031:17BB loc_29B1B: ; Compare Two Operands
seg031:17BB 26 3B 47 0E cmp ax, es:[bx+_unitGame.HitPoints]
seg031:17BF 7E 12 jle short loc_29B33 ; Jump if Less or Equal (ZF=1 | SF!=OF)
seg031:17C1 C4 5E FA les bx, [bp+unitDataPtr] ; Load Full Pointer to ES:xx
seg031:17C4
seg031:17C4 loc_29B24: ; Compare Two Operands
seg031:17C4 26 83 7F 3C 04 cmp es:[bx+_unitData.MovementType], 4
seg031:17C9 74 08 jz short loc_29B33 ; Jump if Zero (ZF=1)
seg031:17CB 8B C7 mov ax, di
seg031:17CD B1 02 mov cl, 2
seg031:17CF D3 F8 sar ax, cl ; Shift Arithmetic Right
seg031:17D1 2B F8 sub di, ax ; Integer Subtraction
seg031:17D3
seg031:17D3 loc_29B33: ; CODE XREF: unitMoveToTile+13Cj
seg031:17D3 ; unitMoveToTile+146j
seg031:17D3 57 push di ; speed2
seg031:17D4 FF 76 08 push word ptr [bp+unitGamePtr+2]
seg031:17D7 FF 76 06 push word ptr [bp+unitGamePtr] ; unitGamePtr
seg031:17DA 90 nop ; No Operation
seg031:17DB 0E push cs
seg031:17DC E8 74 08 call near ptr unitMoveReset ; Call Procedure
seg031:17DF 83 C4 06 add sp, 6 ; Add
seg031:17E2 C4 5E FA les bx, [bp+unitDataPtr] ; Load Full Pointer to ES:xx
seg031:17E5 26 83 7F 3C 05 cmp es:[bx+_unitData.MovementType], 5 ; Underground
seg031:17EA 74 45 jz short setMoveDest ; Jump if Zero (ZF=1)
seg031:17EC C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xx
seg031:17EF
seg031:17EF loc_29B4F:
seg031:17EF 26 8B 47 0C mov ax, es:[bx+_unitGame.mapTileY]
seg031:17F3 26 8B 57 0A mov dx, es:[bx+_unitGame.mapTileX]
seg031:17F7 89 46 F2 mov [bp+oldY], ax
seg031:17FA 89 56 F0 mov [bp+oldX], dx
seg031:17FD C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xx
seg031:1800 8B 46 F6 mov ax, [bp+posY]
seg031:1803 8B 56 F4 mov dx, [bp+posX]
seg031:1806 26 89 47 0C mov es:[bx+_unitGame.mapTileY], ax
seg031:180A 26 89 57 0A mov es:[bx+_unitGame.mapTileX], dx
seg031:180E FF 76 08 push word ptr [bp+unitGamePtr+2]
seg031:1811 FF 76 06 push word ptr [bp+unitGamePtr] ; unitGamePtr
seg031:1814 B8 01 00 mov ax, 1
seg031:1817 50 push ax ; funcPtrIndex
seg031:1818
seg031:1818 loc_29B78: ; Call Procedure
seg031:1818 9A 8E 00 D0 42 call j_sub_566CF
seg031:181D
seg031:181D loc_29B7D: ; Add
seg031:181D 83 C4 06 add sp, 6
seg031:1820
seg031:1820 loc_29B80: ; Load Full Pointer to ES:xx
seg031:1820 C4 5E 06 les bx, [bp+unitGamePtr]
seg031:1823
seg031:1823 loc_29B83:
seg031:1823 8B 46 F2 mov ax, [bp+oldY]
seg031:1826 8B 56 F0 mov dx, [bp+oldX]
seg031:1829 26 89 47 0C mov es:[bx+_unitGame.mapTileY], ax
seg031:182D 26 89 57 0A mov es:[bx+_unitGame.mapTileX], dx
seg031:1831
seg031:1831 setMoveDest: ; CODE XREF: unitMoveToTile+167j
seg031:1831 C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xx
seg031:1834 8B 46 F6 mov ax, [bp+posY]
seg031:1837 8B 56 F4 mov dx, [bp+posX]
seg031:183A 26 89 47 4B mov es:[bx+_unitGame.mapDestY], ax
seg031:183E 26 89 57 49 mov es:[bx+_unitGame.mapDestX], dx
seg031:1842 B8 0A 00 mov ax, 0Ah
seg031:1845 50 push ax ; checkHouseID
seg031:1846
seg031:1846 loc_29BA6:
seg031:1846 FF 76 08 push word ptr [bp+unitGamePtr+2]
seg031:1849
seg031:1849 loc_29BA9: ; unitGamePtr
seg031:1849 FF 76 06 push word ptr [bp+unitGamePtr]
seg031:184C 90 nop ; No Operation
seg031:184D 0E push cs
seg031:184E E8 F5 00 call near ptr sub_29CA6 ; Call Procedure
seg031:1851 83 C4 06 add sp, 6 ; Add
seg031:1854 B8 01 00 mov ax, 1
seg031:1857
seg031:1857 loc_29BB7: ; Jump
seg031:1857 E9 3B FE jmp loc_299F5
seg031:185A ; ---------------------------------------------------------------------------
seg031:185A
seg031:185A loc_29BBA: ; CODE XREF: unitMoveToTile:loc_299F5j
seg031:185A 5F pop di
seg031:185B 5E pop si
seg031:185C 8B E5 mov sp, bp
seg031:185E
seg031:185E loc_29BBE:
seg031:185E 5D pop bp
seg031:185F CB retf ; Return Far from Procedure
seg031:185F unitMoveToTile endp

Link to comment
Share on other sites

Yes I'm looking for research "saboteur" key.

I'll try to change some code to remove Saboteur Movement Bug. I also noticed that Sabouter explodes (even on sand!) if last movement tile to arrive to destination is a diagonal movement... this is really bizarre! :blink:

MrFibble, about to fix decay of the structures, I send you a private message for this topic:

http://forum.opendun...ic.php?f=9&t=25

In particular can you explain me which of three steps do you change to fix only structures?

Thanks

Link to comment
Share on other sites

IIRC the code

C4 5E 06 ; les bx, [bp+06]
26 81 4F 04 00 04 ; or es:[bx+4],0400
C4 5E FC ; les bx, [bp-04]

appears only once in the EXE. I was referring to the line

26 81 4F 04 00 04 ; or es:[bx+4],0400

which indeed appears thrice (TrueBrain explains why in this post).

So you just have to search for the code

C4 5E 06 26 81 4F 04 00 04 C4 5E FC

and repalce it with

C4 5E 06 90 90 90 90 90 90 C4 5E FC

I think the code is the same across all known versions of DUNE2.EXE.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...