drnovice Posted March 6, 2013 Share Posted March 6, 2013 I found another missionNumber exception about "Enemy/[House] Unit Approaching":seg023:0AD7 loc_22D07: ; CODE XREF: sub_22B24+1D4jseg023:0AD7 83 3E A4 38 03 cmp missionNumber, 3 ; Compare Two Operandsseg023:0ADC 73 68 jnb short loc_22D76 ; Jump if Not Below (CF=0)seg023:0ADE B8 08 00 mov ax, 8 ; Const Yardseg023:0AE1 50 push ax ; typeIndexFindseg023:0AE2 FF 36 2C 3A push houseHumanID ; houseIDseg023:0AE6 33 C0 xor ax, ax ; Logical Exclusive ORseg023:0AE8 33 D2 xor dx, dx ; Logical Exclusive ORseg023:0AEA 50 push axseg023:0AEB 52 push dx ; houseGamePtrseg023:0AEC 9A FD 00 8B 1E call buildingGameFind ; Call Procedureseg023:0AF1 83 C4 08 add sp, 8 ; Addseg023:0AF4 89 56 F4 mov word ptr [bp+buildingHumanConstYardGamePtr+2], dxseg023:0AF7seg023:0AF7 loc_22D27:seg023:0AF7 89 46 F2 mov word ptr [bp+buildingHumanConstYardGamePtr], axseg023:0AFA 8B 46 F2 mov ax, word ptr [bp+buildingHumanConstYardGamePtr]seg023:0AFD 0B 46 F4 or ax, word ptr [bp+buildingHumanConstYardGamePtr+2] ; Logical Inclusive ORseg023:0B00 74 38 jz short loc_22D6A ; Jump if Zero (ZF=1)seg023:0B02 C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xxseg023:0B05 26 FF 77 0C push es:[bx+_unitGame.mapTileY] ; posY2seg023:0B09 26 FF 77 0A push es:[bx+_unitGame.mapTileX] ; posX2seg023:0B0D C4 5E F2 les bx, [bp+buildingHumanConstYardGamePtr] ; Load Full Pointer to ES:xxseg023:0B10seg023:0B10 loc_22D40: ; posYseg023:0B10 26 FF 77 0C push es:[bx+_buildingGame.positionY]seg023:0B14 26 FF 77 0A push es:[bx+_buildingGame.positionX] ; posXseg023:0B18seg023:0B18 loc_22D48: ; Get the angle to point, from this position > that positionseg023:0B18 9A 25 01 48 1D call angleBetweenseg023:0B1D 83 C4 08 add sp, 8 ; Addseg023:0B20 50 push axseg023:0B21 9A 7F 00 D0 42 call j_AngleAdjust ; Call Procedureseg023:0B26 59 pop cxseg023:0B27 8B F0 mov si, axseg023:0B29 46 inc si ; Increment by 1seg023:0B2A 83 E6 07 and si, 7 ; Logical ANDseg023:0B2D 8B C6 mov ax, siseg023:0B2F D1 E8 shr ax, 1 ; Shift Logical Rightseg023:0B31 8B F0 mov si, axseg023:0B33 8B C6 mov ax, siseg023:0B35 05 02 00 add ax, 2 ; Addseg023:0B38 EB 03 jmp short loc_22D6D ; Jumpseg023:0B3A ; ---------------------------------------------------------------------------seg023:0B3Aseg023:0B3A loc_22D6A: ; CODE XREF: sub_22B24+20Cjseg023:0B3A B8 01 00 mov ax, 1 ; Warning: Enemy Unit Approachingseg023:0B3Dseg023:0B3D loc_22D6D: ; CODE XREF: sub_22B24+244jseg023:0B3D 50 push axseg023:0B3E 9A 2A 00 86 42 call j_soundTableLoad ; Call Procedureseg023:0B43 59 pop cxseg023:0B44 EB 12 jmp short loc_22D88 ; Jumpseg023:0B46 ; ---------------------------------------------------------------------------seg023:0B46seg023:0B46 loc_22D76: ; CODE XREF: sub_22B24+1E8jseg023:0B46 C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xxseg023:0B49 26 8A 47 08 mov al, es:[bx+_unitGame.houseID]seg023:0B4D 98 cbw ; AL -> AX (with sign)seg023:0B4E 05 06 00 add ax, 6 ; Addseg023:0B51 50 push axseg023:0B52 9A 2A 00 86 42 call j_soundTableLoad ; Call Procedureseg023:0B57 59 pop cx If missionNumber is below 3, then check Enemy Unit position respect your CY position and identified this position (N, S, W or E) it plays Mentat alert "Enemy unit approaching from the [identified position]". Of course if you don't have a CY Mentat alert say only "Enemy unit approaching" and stop. Over missionNumber 3 (if is not below 3) it jumps directly on last location (loc_22D76) that loads only HouseID so Mentat alert is "[House] unit approaching" and stop, having bypass the part relative to the positioning (N, S, W or S). 1 Quote Link to comment Share on other sites More sharing options...
dynasty Posted March 6, 2013 Share Posted March 6, 2013 BTW, the "enemy unit approaching from the <direction>" calculation here is wrong. It announces unit coming from the south as "from the north". Since you've identified it, you may as well fix it up. From seg023:0B29 onwards: Increment by 1, Logical AND 0x7, Shift Logical Right 1 should instead be: Increment by 1, Logical AND 0xF, Shift Logical Right 2. Edit: hmm, now I can't reproduce it. Maybe it was an OpenDUNE conversion error. Quote Link to comment Share on other sites More sharing options...
drnovice Posted March 6, 2013 Share Posted March 6, 2013 I was looking for a way to put Mentat alert so: "[HOUSE] unit approaching from the [N/S/W/E]"But it seems that if loads pointer to use HouseID, it losts other position references (N/S/W/E) calculated above. 1 Quote Link to comment Share on other sites More sharing options...
MrFlibble Posted March 6, 2013 Author Share Posted March 6, 2013 drnovice, nice find! As a matter of fact, I only played around with the "Enemy unit approaching" exception in DuneX because it is relevant for the non-ENglish language speech. At some point DuneX used the German language setup (for a variety of reasons that are no longer in effect thanks to segra's and OpenDUNE team's efforts) - of course, all speech that was used was generated from English Harkonnen pack (as you know, German and French use a much smaller set of speech lines). In this mode, I noticed that the game would play the clip "Unit destroyed" when the player lost a unit, and "Enemy unit destroyed" if an enemy unit was destroyed (obviously) - but only when the "Enemy unit approaching" exception was in effect (i.e. in the first two missions). After that, the game would use the "Unit destroyed" clip indiscriminately for both the player's and enemy AI's unit losses, which of course was confusing. So I hacked the EXE to extend the exception from the first two missions to all missions in the campaign. When I switched back to the regular English speech, I decided to just nix the "Enemy unit" stuff at all, and inverted the exception, making it non-functional for all playable missions in the game. Quote Link to comment Share on other sites More sharing options...
drnovice Posted March 7, 2013 Share Posted March 7, 2013 It's very odd, because to my tests without changes, English languages in Dune2.exe v1.07-EU (the same for DuneX.exe) in previous missions Mentat alerts said "Enemy Unit Destroyed" for AI units (even Fremen units that are "allies"), instead "[HOUSE-Human] Unit Destroyed" for Human units. I'll do further testing without hacking about successive missions for Mentat alerts.However hacking the .exe about [HOUSE] pronunciation for enemy units destroyed should be preserved "[HOUSE] Unit Destroyed" for proper Human units. Regarding the 'approaching' Mentat alerts I'm thinking to set "Enemy unit approaching from the [position]" for ALL missions because it's more accurate respect only "[HOUSE] unit approaching" and stop. Also because these alerts aren't used for own Human units. Soon I'll test "Enemy construction destroyed" Mentat alerts to change in "[HOUSE] construction destroyed", although could remain as it is, because scenario can't manage AI allies about building and teams production. Quote Link to comment Share on other sites More sharing options...
drnovice Posted March 8, 2013 Share Posted March 8, 2013 I managed "Enemy Structure Destroyed" chunk code:seg010:12EA C4 5E 06 les bx, [bp+buildingGamePtr] ; Load Full Pointer to ES:xxseg010:12ED 26 8A 47 08 mov al, es:[bx+_buildingGame.houseID]seg010:12F1 98 cbw ; AL -> AX (with sign)seg010:12F2 3B 06 2C 3A cmp ax, houseHumanID ; Compare Two Operandsseg010:12F6 75 38 jnz short loc_1B760 ; Jump if Not Zero (ZF=0)seg010:12F8 BF FF FF mov di, 0FFFFhseg010:12FB C4 5E 06 les bx, [bp+buildingGamePtr] ; Load Full Pointer to ES:xxseg010:12FEseg010:12FE loc_1B72E:seg010:12FE 26 8A 47 08 mov al, es:[bx+_buildingGame.houseID]seg010:1302 98 cbw ; AL -> AX (with sign)seg010:1303seg010:1303 loc_1B733: ; Logical Inclusive ORseg010:1303 0B C0 or ax, axseg010:1305 74 0C jz short Hark ; Jump if Zero (ZF=1)seg010:1307 3D 01 00 cmp ax, 1 ; Compare Two Operandsseg010:130A 74 0C jz short Atre ; Jump if Zero (ZF=1)seg010:130C 3D 02 00 cmp ax, 2 ; Compare Two Operandsseg010:130F 74 0C jz short Ordos ; Jump if Zero (ZF=1)seg010:1311 EB 0F jmp short Other ; Jumpseg010:1313 ; ---------------------------------------------------------------------------seg010:1313seg010:1313 Hark: ; CODE XREF: structureDamageTake+EFjseg010:1313 BF 16 00 mov di, 16hseg010:1316 EB 0F jmp short loc_1B757 ; Jumpseg010:1318 ; ---------------------------------------------------------------------------seg010:1318seg010:1318 Atre: ; CODE XREF: structureDamageTake+F4jseg010:1318 BF 17 00 mov di, 17hseg010:131B EB 0A jmp short loc_1B757 ; Jumpseg010:131D ; ---------------------------------------------------------------------------seg010:131Dseg010:131D Ordos: ; CODE XREF: structureDamageTake+F9jseg010:131D BF 18 00 mov di, 18hseg010:1320 EB 05 jmp short loc_1B757 ; Jumpseg010:1322 ; ---------------------------------------------------------------------------seg010:1322seg010:1322 Other: ; CODE XREF: structureDamageTake+FBjseg010:1322 BF FF FF mov di, 0FFFFhseg010:1325 EB 00 jmp short 2 ; Jumpseg010:1327seg010:1327 loc_1B757: ; CODE XREF: structureDamageTake+100jseg010:1327 ; structureDamageTake+105j ...seg010:1327 57 push diseg010:1328 9A 2A 00 86 42 call j_soundTableLoad ; Call Procedureseg010:132D 59 pop cxseg010:132E EB 0A jmp short loc_1B76A ; Jumpseg010:1330 ; ---------------------------------------------------------------------------seg010:1330seg010:1330 loc_1B760: ; CODE XREF: structureDamageTake+E0jseg010:1330 B8 15 00 mov ax, 15h ; Hark Struct Destroyedseg010:1333 50 push axseg010:1334 9A 2A 00 86 42 call j_soundTableLoad ; Call Procedureseg010:1339 59 pop cxIf Human HouseID is different to Bulding HouseID (jnz) it jumps into loc_1B760 that just play "Enemy Structure Destroyed" (15h) because it's an opponent AI building to be destroyed.Instead if jnz isn't occurred then check which House declare by ID (00: Harkonnen -> 16h, 01: Atreides -> 17h, 02: Ordos -> 18h, else FFFFh that it's no sound!). Originally it manages only original Houses so if you play as Fremen or Sardaukar you don't heard any Mentat alert about own building destroyed. Try to change (Dune 2 v1.07-EU):0x01031A: C4 5E 06 26 8A 470x010320: 08 98 3B 06 38 3A 75 38 BF FF FF C4 5E 06 26 8A0x010330: 47 08 98 0B C0 74 0C 3D 01 00 74 0C 3D 02 00 740x010340: 0C EB 0F BF 16 00 EB 0F BF 17 00 EB 0A BF 18 000x010350: EB 05 BF FF FF EB 00 57 9A 2A 00 8C 32 59 EB 0A0x010360: B8 15 00 50 9A 2A 00 8C 32 59to: WRONG 0x01031A: BF FF FF C4 5E 06 0x010320: 26 8A 47 08 98 0B C0 74 19 3D 01 00 74 19 3D 02 0x010330: 00 74 19 3D 03 00 74 19 3D 04 00 74 19 3D 05 00 0x010340: 74 19 BF 16 00 EB 1C BF 17 00 EB 17 BF 18 00 EB 0x010350: 12 BF 19 00 EB 0D BF 20 00 EB 08 BF 21 00 EB 03 0x010360: 90 90 90 57 9A 2A 00 8C 32 59 So we can have Mentat alerts, that manage ALL 6 factions, saying "[HOUSE] Structure Destroyed". ;) EDITED: I was wrong about Sardaukar & Mercenary IDs sound references, 'cause are 1A & 1B (not 20 & 21).I had to change a little the code because using 0x01035B zone to Mercenary exception it did crash game, so I set them on first 3 bytes (replacing BF FF FF that is null):0x01031A: BF 1B 00 C4 5E 060x010320: 26 8A 47 08 98 0B C0 74 19 3D 01 00 74 19 3D 020x010330: 00 74 19 3D 03 00 74 19 3D 04 00 74 19 3D 05 000x010340: 74 21 BF 16 00 EB 1C BF 17 00 EB 17 BF 18 00 EB0x010350: 12 BF 19 00 EB 0D BF 1A 00 EB 08 90 90 90 90 900x010360: 90 90 90 57 9A 2A 00 8C 32 59last jz (74 21) goes directly to 0x010363 position. Now I would like understand why Mentat alerts "Sardaukar Unit Destroyed" and "Sardaukar Unit Deployed" are heard "Sardaukar ... Destroyed" and "Sardaukar ... Deployed". In particular it refers to %cUNIT.VOC file, it happens for all ATRE.PAK, HARK.PAK and ORDOS.PAK files (thus regardless the voice). 1 Quote Link to comment Share on other sites More sharing options...
MrFlibble Posted March 8, 2013 Author Share Posted March 8, 2013 Great findings, thanks!BTW, I never really paid attention while playing, does the game announce the destruction of both the player's and the AI's structures? I'm only sure of the fact that in non-English versions, the game just has a clip for "Enemy structure destroyed".Now I would like understand why Mentat alerts "Sardaukar Unit Destroyed" and "Sardaukar Unit Deployed" are heard "Sardaukar ... Destroyed" and "Sardaukar ... Deployed". In particular it refers to %cUNIT.VOC file, it happens for all ATRE.PAK, HARK.PAK and ORDOS.PAK files (thus regardless the voice).This was probably done on purpose, since I guess originally the Sardaukar were supposed to be represented by powerful infantry units (maybe a unique version of Trooper or something).The Mentat says "Sardaukar destroyed" instead of "Sardaukar unit destroyed" because this is how the relevant phrase is structured. As a matter of fact, there is no single "syntactic model" for the announcements in which only the House names are changed. Rather, each event (such as the construction of a new Atreides unit) is associated with its own sequence of files to be played, and a text string that is displayed if no speech is enabled in the settings.There's a "speech table" of sorts that lists all the sequences. Here's what it looks like the in segra's database:dseg:0312 2B 00 FF FF FF FF+soundPlayTableEnglish _soundPlay <2Bh, 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh, 33h, 3Ch>; 0dseg:0312 FF FF FF FF 33 00+ ; DATA XREF: soundTableLoad:loc_4D83Erdseg:0312 3C 00 ; soundTableLoad+93r ...dseg:0320 31 00 1D 00 24 00+stru_43740 _soundPlay <31h, 1Dh, 24h, 37h, 0FFFFh, 34h, 0FFFFh>; 0dseg:032E 31 00 1D 00 24 00+stru_4374E _soundPlay <31h, 1Dh, 24h, 37h, 39h, 34h, 0FFFFh>; 0 ; Warning: Enemy Unit Approaching Northdseg:033C 31 00 1D 00 24 00+stru_4375C _soundPlay <31h, 1Dh, 24h, 37h, 3Ah, 34h, 0FFFFh>; 0dseg:034A 31 00 1D 00 24 00+stru_4376A _soundPlay <31h, 1Dh, 24h, 37h, 3Bh, 34h, 0FFFFh>; 0dseg:0358 31 00 1D 00 24 00+stru_43778 _soundPlay <31h, 1Dh, 24h, 37h, 3Ch, 34h, 0FFFFh>; 0dseg:0366 31 00 1E 00 24 00+stru_43786 _soundPlay <31h, 1Eh, 24h, 37h, 0FFFFh, 35h, 0FFFFh>; 0 ; Warning: Harkdseg:0374 31 00 1F 00 24 00+stru_43794 _soundPlay <31h, 1Fh, 24h, 37h, 0FFFFh, 36h, 0FFFFh>; 0 ; Warning: Atredseg:0382 31 00 20 00 24 00+stru_437A2 _soundPlay <31h, 20h, 24h, 37h, 0FFFFh, 37h, 0FFFFh>; 0dseg:0390 31 00 21 00 24 00+stru_437B0 _soundPlay <31h, 21h, 24h, 37h, 0FFFFh, 38h, 0FFFFh>; 0dseg:039E 31 00 22 00 37 00+stru_437BE _soundPlay <31h, 22h, 37h, 0FFFFh, 0FFFFh, 39h, 0FFFFh>; 0dseg:03AC 31 00 23 00 24 00+stru_437CC _soundPlay <31h, 23h, 24h, 37h, 0FFFFh, 3Ah, 0FFFFh>; 0dseg:03BA 31 00 32 00 37 00+stru_437DA _soundPlay <31h, 32h, 37h, 0FFFFh, 0FFFFh, 3Bh, 0FFFFh>; 0 ; Sabotdseg:03C8 1D 00 24 00 35 00+stru_437E8 _soundPlay <1Dh, 24h, 35h, 0FFFFh, 0FFFFh, 0, 0FFFFh>; 0 ; Enemy Unit Destroyeddseg:03D6 1E 00 24 00 35 00+stru_437F6 _soundPlay <1Eh, 24h, 35h, 0FFFFh, 0FFFFh, 3Ch, 0FFFFh>; 0 ; Hark Unit Destroyeddseg:03E4 1F 00 24 00 35 00+stru_43804 _soundPlay <1Fh, 24h, 35h, 0FFFFh, 0FFFFh, 3Dh, 0FFFFh>; 0dseg:03F2 20 00 24 00 35 00+stru_43812 _soundPlay <20h, 24h, 35h, 0FFFFh, 0FFFFh, 3Eh, 0FFFFh>; 0dseg:0400 21 00 24 00 35 00+stru_43820 _soundPlay <21h, 24h, 35h, 0FFFFh, 0FFFFh, 3Fh, 0FFFFh>; 0dseg:040E 22 00 35 00 FF FF+stru_4382E _soundPlay <22h, 35h, 0FFFFh, 0FFFFh, 0FFFFh, 40h, 0FFFFh>; 0dseg:041C 23 00 24 00 35 00+stru_4383C _soundPlay <23h, 24h, 35h, 0FFFFh, 0FFFFh, 41h, 0FFFFh>; 0dseg:042A 32 00 35 00 FF FF+stru_4384A _soundPlay <32h, 35h, 0FFFFh, 0FFFFh, 0FFFFh, 0, 0FFFFh>; 0 ; Sab Destroyeddseg:0438 1D 00 25 00 35 00+stru_43858 _soundPlay <1Dh, 25h, 35h, 0FFFFh, 0FFFFh, 0, 0FFFFh>; 0dseg:0438 FF FF FF FF 00 00+ ; DATA XREF: miniMapDrawPiece:loc_17652rdseg:0438 FF FF ; miniMapDrawPiece:loc_1764Drdseg:0438 ; Hark Structure Destroyeddseg:0446 1E 00 25 00 35 00+stru_43866 _soundPlay <1Eh, 25h, 35h, 0FFFFh, 0FFFFh, 42h, 0FFFFh>; 0dseg:0454 1F 00 25 00 35 00+stru_43874 _soundPlay <1Fh, 25h, 35h, 0FFFFh, 0FFFFh, 43h, 0FFFFh>; 0dseg:0462 20 00 25 00 35 00+stru_43882 _soundPlay <20h, 25h, 35h, 0FFFFh, 0FFFFh, 44h, 0FFFFh>; 0dseg:0470 21 00 25 00 35 00+stru_43890 _soundPlay <21h, 25h, 35h, 0FFFFh, 0FFFFh, 45h, 0FFFFh>; 0dseg:0470 FF FF FF FF 45 00+ ; DATA XREF: sub_58280:loc_5836Drdseg:0470 FF FF ; sub_58280+E8rdseg:047E 22 00 35 00 FF FF+stru_4389E _soundPlay <22h, 35h, 0FFFFh, 0FFFFh, 0FFFFh, 46h, 0FFFFh>; 0dseg:048C 23 00 25 00 35 00+stru_438AC _soundPlay <23h, 25h, 35h, 0FFFFh, 0FFFFh, 47h, 0FFFFh>; 0dseg:049A 2C 00 2E 00 FF FF+stru_438BA _soundPlay <2Ch, 2Eh, 0FFFFh, 0FFFFh, 0FFFFh, 0, 0FFFFh>; 0dseg:04A8 2C 00 2D 00 FF FF+stru_438C8 _soundPlay <2Ch, 2Dh, 0FFFFh, 0FFFFh, 0FFFFh, 0, 0FFFFh>; 0dseg:04B6 1E 00 24 00 36 00+stru_438D6 _soundPlay <1Eh, 24h, 36h, 0FFFFh, 0FFFFh, 48h, 0FFFFh>; 0dseg:04C4 1F 00 24 00 36 00+stru_438E4 _soundPlay <1Fh, 24h, 36h, 0FFFFh, 0FFFFh, 49h, 0FFFFh>; 0dseg:04D2 20 00 24 00 36 00+stru_438F2 _soundPlay <20h, 24h, 36h, 0FFFFh, 0FFFFh, 4Ah, 0FFFFh>; 0dseg:04E0 21 00 24 00 36 00+stru_43900 _soundPlay <21h, 24h, 36h, 0FFFFh, 0FFFFh, 4Bh, 0FFFFh>; 0dseg:04EE 22 00 36 00 FF FF+stru_4390E _soundPlay <22h, 36h, 0FFFFh, 0FFFFh, 0FFFFh, 4Ch, 0FFFFh>; 0dseg:04FC 23 00 24 00 36 00+stru_4391C _soundPlay <23h, 24h, 36h, 0FFFFh, 0FFFFh, 4Dh, 0FFFFh>; 0dseg:050A 34 00 38 00 FF FF+stru_4392A _soundPlay <34h, 38h, 0FFFFh, 0FFFFh, 0FFFFh, 0, 0FFFFh>; 0 ; Bloom Locateddseg:0518 31 00 44 00 FF FF+stru_43938 _soundPlay <31h, 44h, 0FFFFh, 0FFFFh, 0FFFFh, 4Eh, 17h>; 0 ; Warning Wormydseg:0526 2F 00 30 00 FF FF+stru_43946 _soundPlay <2Fh, 30h, 0FFFFh, 0FFFFh, 0FFFFh, 50h, 0FFFFh>; 0dseg:0534 31 00 33 00 37 00+stru_43954 _soundPlay <31h, 33h, 37h, 0FFFFh, 0FFFFh, 51h, 0FFFFh>; 0dseg:0542 3D 00 FF FF FF FF+stru_43962 _soundPlay <3Dh, 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh, 0, 0FFFFh>; 0dseg:0550 3E 00 FF FF FF FF+stru_43970 _soundPlay <3Eh, 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh, 0, 0FFFFh>; 0dseg:055E 33 00 3F 00 FF FF+stru_4397E _soundPlay <33h, 3Fh, 0FFFFh, 0FFFFh, 0FFFFh, 0, 0FFFFh>; 0dseg:056C 26 00 FF FF FF FF+stru_4398C _soundPlay <26h, 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh, 0, 2Eh>; 0dseg:057A 27 00 FF FF FF FF+stru_4399A _soundPlay <27h, 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh, 0, 2Eh>; 0dseg:0588 28 00 FF FF FF FF+stru_439A8 _soundPlay <28h, 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh, 0, 2Eh>; 0dseg:0596 29 00 FF FF FF FF+stru_439B6 _soundPlay <29h, 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh, 0, 2Eh>; 0dseg:05A4 2A 00 FF FF FF FF+stru_439C4 _soundPlay <2Ah, 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh, 0, 2Eh>; 0dseg:05B2 40 00 FF FF FF FF+ _soundPlay <40h, 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh, 5Ah, 17h>; 0dseg:05C0 1E 00 24 00 3F 00+stru_439E0 _soundPlay <1Eh, 24h, 3Fh, 0FFFFh, 0FFFFh, 9Ah, 0FFFFh>; 0dseg:05CE 1F 00 24 00 3F 00+stru_439EE _soundPlay <1Fh, 24h, 3Fh, 0FFFFh, 0FFFFh, 9Bh, 0FFFFh>; 0dseg:05DC 20 00 24 00 3F 00+stru_439FC _soundPlay <20h, 24h, 3Fh, 0FFFFh, 0FFFFh, 9Ch, 0FFFFh>; 0dseg:05EA 21 00 24 00 3F 00+stru_43A0A _soundPlay <21h, 24h, 3Fh, 0FFFFh, 0FFFFh, 9Dh, 0FFFFh>; 0dseg:05F8 22 00 24 00 3F 00+stru_43A18 _soundPlay <22h, 24h, 3Fh, 0FFFFh, 0FFFFh, 9Eh, 0FFFFh>; 0dseg:0606 23 00 24 00 3F 00+stru_43A26 _soundPlay <23h, 24h, 3Fh, 0FFFFh, 0FFFFh, 9Fh, 0FFFFh>; 0dseg:0614 1E 00 41 00 42 00+stru_43A34 _soundPlay <1Eh, 41h, 42h, 0FFFFh, 0FFFFh, 0A2h, 0FFFFh>; 0dseg:0622 1F 00 41 00 42 00+stru_43A42 _soundPlay <1Fh, 41h, 42h, 0FFFFh, 0FFFFh, 0A3h, 0FFFFh>; 0dseg:0630 20 00 41 00 42 00+stru_43A50 _soundPlay <20h, 41h, 42h, 0FFFFh, 0FFFFh, 0A4h, 0FFFFh>; 0dseg:063E 21 00 41 00 42 00+stru_43A5E _soundPlay <21h, 41h, 42h, 0FFFFh, 0FFFFh, 0A5h, 0FFFFh>; 0dseg:064C 22 00 41 00 42 00+stru_43A6C _soundPlay <22h, 41h, 42h, 0FFFFh, 0FFFFh, 0A6h, 0FFFFh>; 0dseg:065A 23 00 41 00 42 00+stru_43A7A _soundPlay <23h, 41h, 42h, 0FFFFh, 0FFFFh, 0A7h, 0FFFFh>; 0dseg:0668 46 00 47 00 FF FF+stru_43A88 _soundPlay <46h, 47h, 0FFFFh, 0FFFFh, 0FFFFh, 0, 0FFFFh>; 0dseg:0676 1E 00 FF FF FF FF+stru_43A96 _soundPlay <1Eh, 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh, 0, 0FFFFh>; 0dseg:0684 1F 00 FF FF FF FF+stru_43AA4 _soundPlay <1Fh, 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh, 0, 0FFFFh>; 0dseg:0692 20 00 FF FF FF FF+stru_43AB2 _soundPlay <20h, 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh, 0, 0FFFFh>; 0dseg:06A0 21 00 FF FF FF FF+stru_43AC0 _soundPlay <21h, 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh, 0, 0FFFFh>; 0dseg:06AE 22 00 FF FF FF FF+stru_43ACE _soundPlay <22h, 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh, 0, 0FFFFh>; 0dseg:06BC 23 00 FF FF FF FF+stru_43ADC _soundPlay <23h, 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh, 0, 0FFFFh>; 0dseg:06CA 1E 00 43 00 36 00+stru_43AEA _soundPlay <1Eh, 43h, 36h, 0FFFFh, 0FFFFh, 93h, 0FFFFh>; 0dseg:06D8 1F 00 43 00 36 00+stru_43AF8 _soundPlay <1Fh, 43h, 36h, 0FFFFh, 0FFFFh, 94h, 0FFFFh>; 0dseg:06E6 20 00 43 00 36 00+stru_43B06 _soundPlay <20h, 43h, 36h, 0FFFFh, 0FFFFh, 95h, 0FFFFh>; 0dseg:06F4 21 00 43 00 36 00+stru_43B14 _soundPlay <21h, 43h, 36h, 0FFFFh, 0FFFFh, 96h, 0FFFFh>; 0dseg:0702 22 00 43 00 36 00+stru_43B22 _soundPlay <22h, 43h, 36h, 0FFFFh, 0FFFFh, 97h, 0FFFFh>; 0dseg:0710 23 00 43 00 36 00+stru_43B30 _soundPlay <23h, 43h, 36h, 0FFFFh, 0FFFFh, 98h, 0FFFFh>; 0dseg:071E FF FF FF FF FF FF+stru_43B3E _soundPlay <0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh, 1, 0FFFFh> ; Dunedseg:072C FF FF FF FF FF FF+stru_43B4C _soundPlay <0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh, 0, 0FFFFh> ; BuildingThis one is BTW for the English version, other languages use a different table with less speech clips.And this is what it looks like in the EU version (without any comments):31 00 1D 00 24 00 37 00 FF FF 34 00 FF FF 31 00 1D 00 24 00 37 00 39 00 34 00 FF FF 31 00 1D 00 24 00 37 00 3A 00 34 00 FF FF 31 00 1D 00 24 00 37 00 3B 00 34 00 FF FF 31 00 1D 00 24 00 37 00 3C 00 34 00 FF FF 31 00 1E 00 24 00 37 00 FF FF 35 00 FF FF 31 00 1F 00 24 00 37 00 FF FF 36 00 FF FF 31 00 20 00 24 00 37 00 FF FF 37 00 FF FF 31 00 21 00 24 00 37 00 FF FF 38 00 FF FF 31 00 22 00 37 00 FF FF FF FF 39 00 FF FF 31 00 23 00 24 00 37 00 FF FF 3A 00 FF FF 31 00 32 00 37 00 FF FF FF FF 3B 00 FF FF 1D 00 24 00 35 00 FF FF FF FF 00 00 FF FF 1E 00 24 00 35 00 FF FF FF FF 3C 00 FF FF 1F 00 24 00 35 00 FF FF FF FF 3D 00 FF FF 20 00 24 00 35 00 FF FF FF FF 3E 00 FF FF 21 00 24 00 35 00 FF FF FF FF 3F 00 FF FF 22 00 35 00 FF FF FF FF FF FF 40 00 FF FF 23 00 24 00 35 00 FF FF FF FF 41 00 FF FF 32 00 35 00 FF FF FF FF FF FF 00 00 FF FF 1D 00 25 00 35 00 FF FF FF FF 00 00 FF FFAs you can see, each two bytes represent either a sound clip, or a text string. For example, the 31 00 in the beginning is the "Warning!" speech clip. The first sequences are for "Enemy unit approaching from <direction>":31 00 1D 00 24 00 37 00 FF FF 34 00 FF FF 31 00 1D 00 24 00 37 00 39 00 34 00 FF FF 31 00 1D 00 24 00 37 00 3A 00 34 00 FF FF 31 00 1D 00 24 00 37 00 3B 00 34 00 FF FF 31 00 1D 00 24 00 37 00 3C 00 34 00 FF FFThe first one lacks any direction, so there's an empty space (FF FF) between the last sound bit (37 00 "approaching" and the ID of the text string (34 00). The text string ID is the same in all cases, as there is only one text string, "Enemy unit approaching". I think the string ID is the same as its hex number in the string table file, counting from 0.As for the Sardaukar, here's the part of the table:1D 00 24 00 35 00 FF FF FF FF 00 00 FF FF ; "Enemy unit destroyed"1E 00 24 00 35 00 FF FF FF FF 3C 00 FF FF ; "Harkonnen unit destroyed"1F 00 24 00 35 00 FF FF FF FF 3D 00 FF FF ; "Atreides unit destroyed"20 00 24 00 35 00 FF FF FF FF 3E 00 FF FF ; "Ordos unit destroyed"21 00 24 00 35 00 FF FF FF FF 3F 00 FF FF ; "Fremen unit destroyed"22 00 35 00 FF FF FF FF FF FF 40 00 FF FF ; "Sardaukar destroyed"23 00 24 00 35 00 FF FF FF FF 41 00 FF FF ; "Mercenary unit destroyed"32 00 35 00 FF FF FF FF FF FF 00 00 FF FF ; "Saboteur destroyed"The Sardaukar line only has two speech clips, ID22 "Sardaukar" and ID35 "destroyed". You can easily edit that to get the "unit" ID24 back there. Quote Link to comment Share on other sites More sharing options...
drnovice Posted March 8, 2013 Share Posted March 8, 2013 Oh great! Thanks to explain.Yes, I've read this TableSound, but at the wrong location (from dseg:0836, that I think it's the Intro Voice because of an unique big block of code).Now I know what sound is played each time. :) I found out also a very interesting thing that could change the gameplay longevity:seg023:0387 83 3E A6 38 09 cmp missionNumberPrevious, 9 ; Compare Two Operandsseg023:038C 75 35 jnz short hasAnotherMission ; Jump if Not Zero (ZF=0)seg023:038Eseg023:038E loc_225BE: ; Call Procedureseg023:038E 9A 31 01 71 39 call sub_39841seg023:0393 B8 0F 00 mov ax, 0Fhseg023:0396 50 push axseg023:0397 FF 36 2C 3C push word_4704Cseg023:039B FF 36 2A 3C push word_4704Aseg023:039F 9A 00 00 A3 33 call screenFadeOut ; Call Procedureseg023:03A4 83 C4 06 add sp, 6 ; Addseg023:03A7 33 C0 xor ax, ax ; Logical Exclusive ORseg023:03A9 50 push axseg023:03AA 9A 0E 00 DE 32 call sub_32DEE ; Call Procedureseg023:03AF 59 pop cxseg023:03B0 9A 20 00 AE 42 call j_gameEndingPlay ; Call Procedureseg023:03B5 9A 20 00 03 43 call j_gameShutdown ; Call Procedureseg023:03BA 33 C0 xor ax, ax ; Logical Exclusive ORseg023:03BC 50 push ax ; statusseg023:03BDseg023:03BD loc_225ED: ; Call Procedureseg023:03BD 9A 77 03 00 10 call _exitseg023:03C2 ; ---------------------------------------------------------------------------seg023:03C2 59 pop cxseg023:03C3seg023:03C3 hasAnotherMission: ; CODE XREF: gameCheckStatus+E3jseg023:03C3 9A 31 01 71 39 call sub_39841 ; Call Procedureseg023:03C8 9A 20 00 B1 42 call sub_42B30 ; Call Procedureseg023:03CDseg023:03CD loc_225FD: ; Call Procedureseg023:03CD 9A 63 01 71 39 call sub_39873seg023:03D2 33 C0 xor ax, ax ; Logical Exclusive ORseg023:03D4seg023:03D4 loc_22604:seg023:03D4 BA 00 03 mov dx, 300hseg023:03D7 50 push ax ; intseg023:03D8 52 push dx ; fileSizeseg023:03D9seg023:03D9 loc_22609: ; intseg023:03D9 FF 36 28 3C push word ptr src+2seg023:03DD FF 36 26 3C push word ptr src ; intseg023:03E1 1E push dsseg023:03E2 B8 C9 60 mov ax, offset aIbm_pal_2 ; "IBM.PAL"seg023:03E5 50 push ax ; fileNameseg023:03E6seg023:03E6 loc_22616: ; Call Procedureseg023:03E6 9A 0A 00 41 33 call fileLoad_1seg023:03EB 83 C4 0C add sp, 0Ch ; Addseg023:03EEseg023:03EE loc_2261E:seg023:03EE B8 01 00 mov ax, 1seg023:03F1 50 push axseg023:03F2 FF 36 A6 38 push missionNumberPreviousseg023:03F6 9A 20 00 06 43 call j_missionMapScreen ; Call Procedureseg023:03FB 59 pop cxseg023:03FC 59 pop cxseg023:03FD A3 A4 38 mov missionNumber, axseg023:0400seg023:0400 loc_22630:seg023:0400 B8 0F 00 mov ax, 0Fhseg023:0403 50 push axseg023:0404seg023:0404 loc_22634:seg023:0404 FF 36 2C 3C push word_4704Cseg023:0408seg023:0408 loc_22638:seg023:0408 FF 36 2A 3C push word_4704Aseg023:040Cseg023:040C loc_2263C: ; Call Procedureseg023:040C 9A 00 00 A3 33 call screenFadeOutseg023:0411 83 C4 06 add sp, 6 ; AddMaybe changing 09 on cmp check you can play more Scenarios... I'll test soon! EDITED:And finally I tested it... we can increase the longevity of Dune 2!! Yes we can! :P To try:1) I changed 09 Mission Number to 1B (hex value of 11 decimal) at 0x017247 (Dune 2 v1.07-EU)2) I added [GROUP9] & [GROUP10] into REGIONA.INI (tested with Atreides)3) I created SCENA024.INI & SCENA025.INI for Mission 10 (because after Missions 8, Mission 9 has scenarios numbers increment only to 2 and not 3, the same for Mission after Mission 9, then it returns normal +3 increment)4) and so on... and it incredibly works! 8) Note: in Mission 10 Mentat briefing are read all SCEN?###.INI written rows, so I must check about TEXTA.ENG if there is additional space to other briefing over Mission 9.EDITED #2: ok I successfully added new strings for Mission 10 & 11 (4 strings for mission, 1st Briefing, 2nd Win text, 3rd Lose text & 4th Advices) on TEXTA.ENG by SSTEditor. 1 Quote Link to comment Share on other sites More sharing options...
MrFlibble Posted March 11, 2013 Author Share Posted March 11, 2013 EDITED:And finally I tested it... we can increase the longevity of Dune 2!! Yes we can! :P To try:1) I changed 09 Mission Number to 1B (hex value of 11 decimal) at 0x017247 (Dune 2 v1.07-EU)2) I added [GROUP9] & [GROUP10] into REGIONA.INI (tested with Atreides)3) I created SCENA024.INI & SCENA025.INI for Mission 10 (because after Missions 8, Mission 9 has scenarios numbers increment only to 2 and not 3, the same for Mission after Mission 9, then it returns normal +3 increment)4) and so on... and it incredibly works! 8) Note: in Mission 10 Mentat briefing are read all SCEN?###.INI written rows, so I must check about TEXTA.ENG if there is additional space to other briefing over Mission 9.EDITED #2: ok I successfully added new strings for Mission 10 & 11 (4 strings for mission, 1st Briefing, 2nd Win text, 3rd Lose text & 4th Advices) on TEXTA.ENG by SSTEditor.Actually, I think the possibility of playing beyond mission 9 has already been discussed here somewhere, although I have been unable to track the relevant posts down yet. What I do remember is that some time ago (quite some time ago, actually!) I experimented with this, and managed to play mission 10 right after mission 9. All it required was to disable the ending movie after mission 9, and some additions to the REGION#.INI file. Quote Link to comment Share on other sites More sharing options...
drnovice Posted March 11, 2013 Share Posted March 11, 2013 How to remove copy protection:seg023:0414 loc_22644: ; Compare Two Operandsseg023:0414 83 3E A6 38 01 cmp missionNumberPrevious, 1seg023:0419 74 07 jz short copyProtection ; Jump if Zero (ZF=1)seg023:041Bseg023:041B loc_2264B: ; Compare Two Operandsseg023:041B 83 3E A6 38 07 cmp missionNumberPrevious, 7seg023:0420 75 69 jnz short ProtectionSkipped ; Jump if Not Zero (ZF=0)seg023:0422seg023:0422 copyProtection: ; CODE XREF: gameCheckStatus+170jseg023:0422 B8 D2 3B mov ax, seg seg152seg023:0425 50 push axseg023:0426seg023:0426 loc_22656:seg023:0426 B8 40 04 mov ax, 440hseg023:0429seg023:0429 loc_22659:seg023:0429 50 push axseg023:042Aseg023:042A loc_2265A:seg023:042A B8 07 00 mov ax, 7seg023:042D 50 push axseg023:042Eseg023:042E loc_2265E:seg023:042E B8 01 00 mov ax, 1seg023:0431 50 push axseg023:0432 9A 34 00 BB 42 call sub_42BE4 ; Call Procedureseg023:0437 83 C4 08 add sp, 8 ; Addseg023:043Aseg023:043A loc_2266A: ; Logical Exclusive ORseg023:043A 33 C0 xor ax, axseg023:043Cseg023:043C loc_2266C:seg023:043C 50 push axseg023:043Dseg023:043D loc_2266D:seg023:043D B8 02 00 mov ax, 2seg023:0440seg023:0440 loc_22670:seg023:0440 50 push axseg023:0441seg023:0441 loc_22671:seg023:0441 B8 C8 00 mov ax, 0C8h ; '+'seg023:0444 50 push axseg023:0445seg023:0445 loc_22675:seg023:0445 B8 28 00 mov ax, 28h ; '('seg023:0448 50 push axseg023:0449 33 C0 xor ax, ax ; Logical Exclusive ORseg023:044B 50 push axseg023:044C 33 C0 xor ax, ax ; Logical Exclusive ORseg023:044E 50 push axseg023:044F 33 C0 xor ax, ax ; Logical Exclusive ORseg023:0451 50 push axseg023:0452seg023:0452 loc_22682: ; Logical Exclusive ORseg023:0452 33 C0 xor ax, axseg023:0454seg023:0454 loc_22684:seg023:0454 50 push axseg023:0455 9A 07 00 D5 32 call inGameMenuDraw_0 ; Call Procedureseg023:045A 83 C4 10 add sp, 10h ; Addseg023:045Dseg023:045D loc_2268D: ; Call Procedureseg023:045D 9A 39 00 DD 42 call j_ProtectionScreenseg023:0462seg023:0462 loc_22692: ; Logical Inclusive ORseg023:0462 0B C0 or ax, axseg023:0464 75 0E jnz short ProtectionPassed ; Jump if Not Zero (ZF=0)seg023:0466 9A 20 00 03 43 call j_gameShutdown ; Call Procedureseg023:046B 33 C0 xor ax, ax ; Logical Exclusive ORseg023:046D 50 push ax ; statusseg023:046E 9A 77 03 00 10 call _exit ; Call Procedureseg023:0473 ; ---------------------------------------------------------------------------seg023:0473 59 pop cxseg023:0474seg023:0474 glb_226A4: ; CODE XREF: gameCheckStatus+1BBjseg023:0474 ProtectionPassed:seg023:0474 B8 D2 3B mov ax, seg seg152seg023:0477 50 push axseg023:0478seg023:0478 loc_226A8:seg023:0478 B8 40 04 mov ax, 440hseg023:047B 50 push axseg023:047Cseg023:047C loc_226AC:seg023:047C B8 07 00 mov ax, 7seg023:047F 50 push axseg023:0480seg023:0480 loc_226B0: ; Logical Exclusive ORseg023:0480 33 C0 xor ax, axseg023:0482seg023:0482 loc_226B2:seg023:0482 50 push axseg023:0483seg023:0483 loc_226B3: ; Call Procedureseg023:0483 9A 34 00 BB 42 call sub_42BE4seg023:0488seg023:0488 loc_226B8: ; Addseg023:0488 83 C4 08 add sp, 8seg023:048Bseg023:048B ProtectionSkipped: ; CODE XREF: gameCheckStatus+177jseg023:048B EB 3D jmp short loc_226FA ; intSet directly an unconditional jump (jmp) on ProtectionSkipped location and noped first 2 compare (cmp) on top EDITED: Only now I saw that segra already posted it. Sorry! Quote Link to comment Share on other sites More sharing options...
MrFlibble Posted March 12, 2013 Author Share Posted March 12, 2013 Set directly an unconditional jump (jmp) on ProtectionSkipped location and noped first 2 compare (cmp) on topMy preferred method is to simply change the mission numbers after which the copy protection routine is called to non-existent missions like 10 and 11 (0A and 0B in hexadecimal respectively). Quote Link to comment Share on other sites More sharing options...
drnovice Posted March 13, 2013 Share Posted March 13, 2013 Actually, I think the possibility of playing beyond mission 9 has already been discussed here somewhere, although I have been unable to track the relevant posts down yet. What I do remember is that some time ago (quite some time ago, actually!) I experimented with this, and managed to play mission 10 right after mission 9. All it required was to disable the ending movie after mission 9, and some additions to the REGION#.INI file.I think that it could be a good point about mods the possibility to change the "9 missions schema" on the campaigns. Quote Link to comment Share on other sites More sharing options...
drnovice Posted March 14, 2013 Share Posted March 14, 2013 Dune 2 original:dseg:2B91 54 4F 54 41 4C 20+aTotalRegions db 'TOTAL REGIONS',0 ; DATA XREF: sub_5F1A7+1Fodseg:2B9F 00 align 2dseg:2BA0 10 00 word_45FC0 dw 10h ; DATA XREF: selectTeam:loc_60A08rdseg:2BA2 38 00 word_45FC2 dw 38h ; DATA XREF: selectTeam+8Brdseg:2BA4 1F 00 word_45FC4 dw 1Fh ; DATA XREF: selectTeam+A5rdseg:2BA6 70 00 word_45FC6 dw 70hdseg:2BA8 38 00 word_45FC8 dw 38hdseg:2BAA 19 00 word_45FCA dw 19hdseg:2BAC D0 00 word_45FCC dw 0D0hdseg:2BAE 38 00 word_45FCE dw 38hdseg:2BB0 24 00 dw 24hdseg:2BB2 DF 2B 42 43 houseLogoPtrs dd aFhark_wsa_1 ; DATA XREF: selectTeam:loc_60D16rDuneX:dseg:2B91 54 4F 54 41 4C 20+aTotalRegions db 'TOTAL REGIONS',0 ; DATA XREF: sub_5F1A7+1Fodseg:2B9F 00 align 2dseg:2BA0 10 00 word_45FC0 dw 10h ; DATA XREF: selectTeam:loc_60A08rdseg:2BA2 38 00 word_45FC2 dw 38h ; DATA XREF: selectTeam+8Brdseg:2BA4 34 00 word_45FC4 dw 34h ; DATA XREF: selectTeam+A5rdseg:2BA6 70 00 word_45FC6 dw 70hdseg:2BA8 38 00 word_45FC8 dw 38hdseg:2BAA 22 00 word_45FCA dw 22hdseg:2BAC D0 00 word_45FCC dw 0D0hdseg:2BAE 38 00 word_45FCE dw 38hdseg:2BB0 20 00 dw 20hdseg:2BB2 DF 2B 42 43 houseLogoPtrs dd aFhark_wsa_1 ; DATA XREF: selectTeam:loc_60D16rI can't undestand what are these dword values. Quote Link to comment Share on other sites More sharing options...
MrFlibble Posted March 17, 2013 Author Share Posted March 17, 2013 Now I can't be sure but I think those are codes for keyboard keys that you press to select a House on the Select your House screen. Those were quite hard to track down and I figured them out almost by chance. In DuneX, you press M, F or S to select your sides, hence the different codes. These codes somehow reflect the position of keys on a standard keyboard. The original codes are as follows: 1Fh = A 24h = H 19h = O Now if you count the number of keys on the keyboard in the row between A and H, there are four keys (S, D, F and G). Unsurprisingly, there are also four values between 1Fh and 24h. When I realized that, it was easy to calculate that F should be 22h, and S 20h. IIRC this method also counts keys like Return and Shift, but eventually I figured out what the code for M should be too. Quote Link to comment Share on other sites More sharing options...
drnovice Posted March 18, 2013 Share Posted March 18, 2013 Alright...thanks! Last week I started analysis about all difference between two EXE, just to know what to modify and where to make it with hex editing. MrFlibble if you want, I can posted an attached with all documentation about it. Anyway making other tests about AI alliance, I sadly noticed that my changes (posted some time ago) work only on units but AI allied no longer takes care of enemy structures. :( Let's recap:I just read you already had that code, and its not what your after.. so i assume these pieces may have some effecttheres a few bits specific to atreides / fremensrc/unit.cif (houseID == HOUSE_ATREIDES && unit->o.type != UNIT_SANDWORM) {houseIDBit |= (1 << HOUSE_FREMEN);}if (unit->o.houseID == g_playerHouseID || (unit->o.houseID == HOUSE_FREMEN && g_playerHouseID == HOUSE_ATREIDES)) {unit->o.seenByHouses = 0xFF;} else {unit->o.seenByHouses |= houseIDBit;}not sure of the disassembly location atm, but it shouldnt be too hard to findI think that respective asm about this is:seg023:0912 loc_22B42:seg023:0912 89 46 F8 mov word ptr [bp+houseGamePtr], axseg023:0915 B8 01 00 mov ax, 1seg023:0918 8A 4E 0A mov cl, byte ptr [bp+houseIndex]seg023:091B D3 E0 shl ax, cl ; Shift Logical Leftseg023:091D 89 46 F6 mov [bp+houseRevealed], axseg023:0920 83 7E 0A 01 cmp [bp+houseIndex], 1 ; Compare Two Operandsseg023:0924 75 0E jnz short notAtreOrWorm ; Jump if Not Zero (ZF=0)seg023:0926 C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xxseg023:0929 26 80 7F 02 19 cmp es:[bx+_unitGame.typeIndex], 19h ; sandwormseg023:092E 74 04 jz short notAtreOrWorm ; Jump if Zero (ZF=1)seg023:0930seg023:0930 loc_22B60: ; Logical Inclusive ORseg023:0930 83 4E F6 08 or [bp+houseRevealed], 8seg023:0934seg023:0934 notAtreOrWorm: ; CODE XREF: sub_22B24+30jseg023:0934 ; sub_22B24+3Ajseg023:0934 C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xxseg023:0937 26 8A 47 09 mov al, es:[bx+_unitGame.houseRevealed]seg023:093B B4 00 mov ah, 0seg023:093D 85 46 F6 test [bp+houseRevealed], ax ; Logical Compareseg023:0940seg023:0940 loc_22B70: ; Jump if Zero (ZF=1)seg023:0940 74 18 jz short loc_22B8Aseg023:0942 C4 5E F8 les bx, [bp+houseGamePtr] ; Load Full Pointer to ES:xxseg023:0945 26 F7 47 04 08 00 test es:[bx+_houseGame.IndexLastFound], 8 ; Logical Compareseg023:094B 74 0D jz short loc_22B8A ; Jump if Zero (ZF=1)seg023:094D C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xxseg023:0950seg023:0950 loc_22B80:seg023:0950 8A 46 F6 mov al, byte ptr [bp+houseRevealed]seg023:0953 26 08 47 09 or es:[bx+_unitGame.houseRevealed], al ; Logical Inclusive ORseg023:0957 E9 94 02 jmp Done ; Jumpseg023:095A ; ---------------------------------------------------------------------------seg023:095Aseg023:095A loc_22B8A: ; CODE XREF: sub_22B24:loc_22B70jseg023:095A ; sub_22B24+57j[...]seg023:0BBB checkHouseID: ; CODE XREF: sub_22B24+2A9jseg023:0BBB ; sub_22B24+2B3jseg023:0BBB C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xxseg023: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 Operandsseg023:0BC7 74 11 jz short AtreFre ; Jump if Zero (ZF=1)seg023:0BC9seg023:0BC9 loc_22DF9: ; Load Full Pointer to ES:xxseg023:0BC9 C4 5E 06 les bx, [bp+unitGamePtr]seg023:0BCC 26 80 7F 08 03 cmp es:[bx+_unitGame.houseID], 3 ; Fremenseg023:0BD1 75 11 jnz short loc_22E14 ; Jump if Not Zero (ZF=0)seg023:0BD3 83 3E 2C 3A 01 cmp houseHumanID, 1 ; Atreseg023:0BD8 75 0A jnz short loc_22E14 ; Jump if Not Zero (ZF=0)seg023:0BDAseg023:0BDA AtreFre: ; CODE XREF: sub_22B24+2D3jseg023:0BDA C4 5E 06 les bx, [bp+unitGamePtr] ; unit = fremen and human = atreseg023:0BDD 26 C6 47 09 FF mov es:[bx+_unitGame.houseRevealed], 0FFhseg023:0BE2 EB 0A jmp short Done ; Jumpseg023:0BE4 ; ---------------------------------------------------------------------------seg023:0BE4seg023:0BE4 loc_22E14: ; CODE XREF: sub_22B24+2DDjseg023:0BE4 ; sub_22B24+2E4jseg023:0BE4 C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xxseg023:0BE7 8A 46 F6 mov al, byte ptr [bp+houseRevealed]seg023:0BEA 26 08 47 09 or es:[bx+_unitGame.houseRevealed], al ; Logical Inclusive ORseg023:0BEEseg023:0BEE Done: ; CODE XREF: sub_22B24+Fjseg023:0BEE ; sub_22B24+63j ...seg023:0BEE 5E pop siseg023:0BEF 8B E5 mov sp, bpseg023:0BF1 5D pop bpMaybe here (the first piece of chunk code) is the key to make hostile AI allied respect other AI not allied. Quote Link to comment Share on other sites More sharing options...
MrFlibble Posted March 18, 2013 Author Share Posted March 18, 2013 Alright...thanks! Last week I started analysis about all difference between two EXE, just to know what to modify and where to make it with hex editing. MrFlibble if you want, I can posted an attached with all documentation about it.That would actually be very nice if you did that, it would also help new people to quickly find useful information, rather than plough through all the posts in the modding threads. I'd really appreciate it if you summarized the information that is scattered throughout the forums here in a single document.As for the AT/FR alliance stuff, unfortunately I have no idea. I'm sure you'll figure it out eventually, seeing as how you found out so much about this feature already :) Quote Link to comment Share on other sites More sharing options...
drnovice Posted March 18, 2013 Share Posted March 18, 2013 I found something very similar to the problem that I described: https://github.com/OpenDUNE/OpenDUNE/issues/100https://github.com/rofl0r/OpenDUNE/commit/75a5c94bf690e9adb029b9e5acb8be98d039c4baWhen a structure is scouted by houseID, Map_UnveilTile marks the structure's seenByHouses field for AI targetting purposes. When the scouting house is Atreides, Fremen should also gain that knowledge. However, there was an error in commit d085bb3 regarding this special case:s->o.seenByHouses |= 1 << houseID;if (s->o.houseID == HOUSE_ATREIDES) s->o.seenByHouses |= 1 << HOUSE_FREMEN;should instead be:s->o.seenByHouses |= 1 << houseID;if (houseID == HOUSE_ATREIDES) s->o.seenByHouses |= 1 << HOUSE_FREMEN; It should match this chunk of code:ovr194:1305 FF 76 08 push [bp+HouseID] ; HouseIDovr194:1308ovr194:1308 loc_57818: ; mapPositionovr194:1308 56 push siovr194:1309 0E push csovr194:130A E8 E1 FD call near ptr unitGameGetPtrByMapPos ; Call Procedureovr194:130D 59 pop cxovr194:130E 52 push dxovr194:130F 50 push ax ; unitGamePtrovr194:1310 9A F4 08 23 22 call sub_22B24 ; Call Procedureovr194:1315ovr194:1315 loc_57825: ; Addovr194:1315 83 C4 06 add sp, 6ovr194:1318 56 push si ; mapPositionovr194:1319 0E push csovr194:131A E8 16 FE call near ptr buildingGameGetPtrByMapPos ; Call Procedureovr194:131D 59 pop cxovr194:131E 89 56 FA mov word ptr [bp+buildingGamePtr+2], dxovr194:1321 89 46 F8 mov word ptr [bp+buildingGamePtr], axovr194:1324 8B 46 F8 mov ax, word ptr [bp+buildingGamePtr]ovr194:1327 0B 46 FA or ax, word ptr [bp+buildingGamePtr+2] ; Logical Inclusive ORovr194:132A 74 1C jz short loc_57858 ; Jump if Zero (ZF=1)ovr194:132C C4 5E F8 les bx, [bp+buildingGamePtr] ; Load Full Pointer to ES:xxovr194:132F B0 01 mov al, 1ovr194:1331 8A 4E 08 mov cl, byte ptr [bp+HouseID]ovr194:1334 D2 E0 shl al, cl ; 1 << houseIDovr194:1336 26 08 47 09 or es:[bx+_buildingGame.housesRevealed], al ; Logical Inclusive ORovr194:133A 83 7E 08 01 cmp [bp+HouseID], 1 ; Atrediesovr194:133E 75 08 jnz short loc_57858 ; Jump if Not Zero (ZF=0)ovr194:1340 C4 5E F8 les bx, [bp+buildingGamePtr] ; Load Full Pointer to ES:xxovr194:1343 26 80 4F 09 08 or es:[bx+_buildingGame.housesRevealed], 8 ; Logical Inclusive ORovr194:1348ovr194:1348 loc_57858: ; CODE XREF: mapGamePieceReveal+C1jovr194:1348 ; mapGamePieceReveal+D5jI'll try to change ovr194:133A as advised. EDITED: Yes! Indeed the key of all is:or es:[bx+_buildingGame.housesRevealed], 8In other words, it puts a 1 in bit position regarding Fremen, that is XXXX 1XXX But If you already play Fremen, you must put the 1 in bit position regarding Atreides: XXXX XX1X.So I think that houseRevealed values is 0000 1010 on starting when you play Atreides with Fremen allied, but it should be the same if you play Fremen with Atreides allied. However I don't know why the operation is completely unilateral, so you must swap ALL Atreides/Fremen ID, including those about isFriendly function, otherwise don't work! P.S. More details in attached documentation upcoming. ;) Quote Link to comment Share on other sites More sharing options...
MrFlibble Posted March 20, 2013 Author Share Posted March 20, 2013 Awesome find, congrats! :D Quote Link to comment Share on other sites More sharing options...
dynasty Posted March 20, 2013 Share Posted March 20, 2013 drnovice, something related. If you can find the isFriendly function, it should look something like this: bool House_AreAllied(uint8 houseID1, uint8 houseID2){ if (houseID1 == HOUSE_INVALID || houseID2 == HOUSE_INVALID) return false; if (houseID1 == houseID2) return true; if (houseID1 == HOUSE_FREMEN || houseID2 == HOUSE_FREMEN) { return (houseID1 == HOUSE_ATREIDES || houseID2 == HOUSE_ATREIDES); } return (houseID1 != g_playerHouseID && houseID2 != g_playerHouseID);} Can you spot the bug? Quote Link to comment Share on other sites More sharing options...
drnovice Posted March 20, 2013 Share Posted March 20, 2013 Yes, the "bug" (if we can call it so) is that this function was designed only to have Atreides human, so it doesn't care to take exception to check the behavior between Atreides AI respect other AI if you should play Fremen.It's a bit complicate but absolutely logical. Let's analyse the function on 5 cases, assuming that we're playing Atreides (bold is Human, italic is human Ally):1) if HouseID1 is Fremen and HouseID2 is Atreides -> return true => OK2) if HouseID1 is Atreides and HouseID2 is Fremen -> return true => OK3) if HouseID1 is Fremen and HouseID2 is Harkonnen -> return false => OK4) if HouseID1 is Harkonnen and HouseID2 is Atreides -> return false => OK5) if HouseID1 is Harkonnen and HouseID2 is Ordos -> return true => OK Recap (bold is Human, italic is human Ally):1) F <=> A true2) A <=> F true3) F <=> H false4) H <=> A false5) H <=> O true Indeed it's alright, no wrong behaviours. Now let's analyse the function on the 5 cases, assuming that we're playing Fremen (bold is Human, italic is human Ally):1) if HouseID1 is Fremen and HouseID2 is Atreides -> return true => OK2) if HouseID1 is Atreides and HouseID2 is Fremen -> return true => OK3) if HouseID1 is Fremen and HouseID2 is Harkonnen -> return false => OK4) if HouseID1 is Harkonnen and HouseID2 is Atreides -> return true => to FIX5) if HouseID1 is Harkonnen and HouseID2 is Ordos -> return true => OK Recap (bold is Human, italic is human Ally):1) F <=> A true2) A <=> F true3) F <=> H false4) H <=> A true -> to FIX5) H <=> O true Here shown why Atreides AI apparently don't work: because Atreides in case 4) see and they are seen by all other Houses as friendly and never as enemy.Why all this? Because of the missing exception described above. So to fix this part (it's not enough to make bilateral alliance, soon I'll show what else to change over this) just add: bool House_AreAllied(uint8 houseID1, uint8 houseID2){ if (houseID1 == HOUSE_INVALID || houseID2 == HOUSE_INVALID) return false; if (houseID1 == houseID2) return true; if (houseID1 == HOUSE_FREMEN || houseID2 == HOUSE_FREMEN) { return (houseID1 == HOUSE_ATREIDES || houseID2 == HOUSE_ATREIDES); } if (houseID1 == HOUSE_ATREIDES || houseID2 == HOUSE_ATREIDES) { return (houseID1 == HOUSE_FREMEN || houseID2 == HOUSE_FREMEN); } return (houseID1 != g_playerHouseID && houseID2 != g_playerHouseID);} Quote Link to comment Share on other sites More sharing options...
drnovice Posted March 20, 2013 Share Posted March 20, 2013 An extract regarding what I'll publish.This is asm reference about c++ function described in previous post:seg023:0F5B ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦seg023:0F5Bseg023:0F5B ; Attributes: bp-based frameseg023:0F5Bseg023:0F5B ; int __cdecl far isFriendly?(int objectHouseID,int HumanHouseID)seg023:0F5B isFriendly? proc far ; CODE XREF: sub_15008+12CPseg023:0F5B ; scriptFunctionBuildingGetTarget+65P ...seg023:0F5Bseg023:0F5B objectHouseID = word ptr 6seg023:0F5B HumanHouseID = word ptr 8seg023:0F5Bseg023:0F5B 55 push bpseg023:0F5C 8B EC mov bp, spseg023:0F5Eseg023:0F5E loc_2318E:seg023:0F5E 8B 56 06 mov dx, [bp+objectHouseID]seg023:0F61seg023:0F61 loc_23191:seg023:0F61 8B 5E 08 mov bx, [bp+HumanHouseID]seg023:0F64 83 FA FF cmp dx, 0FFFFh ; Compare Two Operandsseg023:0F67seg023:0F67 loc_23197: ; Jump if Zero (ZF=1)seg023:0F67 74 05 jz short retFalseseg023:0F69seg023:0F69 loc_23199: ; Compare Two Operandsseg023:0F69 83 FB FF cmp bx, 0FFFFhseg023:0F6C 75 04 jnz short loc_231A2 ; no human house?seg023:0F6Eseg023:0F6E retFalse: ; CODE XREF: isFriendly?:loc_23197jseg023:0F6E ; isFriendly?:notAtreidesj ...seg023:0F6E 33 C0 xor ax, ax ; Logical Exclusive ORseg023:0F70seg023:0F70 loc_231A0: ; CODE XREF: isFriendly?:loc_231D1jseg023:0F70 EB 31 jmp short loc_231D3 ; Jumpseg023:0F72 ; ---------------------------------------------------------------------------seg023:0F72seg023:0F72 loc_231A2: ; CODE XREF: isFriendly?+11jseg023:0F72 3B D3 cmp dx, bx ; Compare Two Operandsseg023:0F74seg023:0F74 loc_231A4: ; Jump if Not Zero (ZF=0)seg023:0F74 75 02 jnz short loc_231A8seg023:0F76 EB 26 jmp short retTrue ; Jumpseg023:0F78 ; ---------------------------------------------------------------------------seg023:0F78seg023:0F78 loc_231A8: ; CODE XREF: isFriendly?:loc_231A4jseg023:0F78 83 FA 03 cmp dx, 3 ; DX = objectseg023:0F7B 74 05 jz short isFremen ; Jump if Zero (ZF=1)seg023:0F7D 83 FB 03 cmp bx, 3 ; BX = humanseg023:0F80seg023:0F80 loc_231B0: ; Jump if Not Zero (ZF=0)seg023:0F80 75 0E jnz short notFremenseg023:0F82seg023:0F82 isFremen: ; CODE XREF: isFriendly?+20jseg023:0F82 83 FA 01 cmp dx, 1 ; Compare Two Operandsseg023:0F85seg023:0F85 loc_231B5: ; Jump if Zero (ZF=1)seg023:0F85 74 05 jz short isAtreidesseg023:0F87seg023:0F87 loc_231B7: ; Compare Two Operandsseg023:0F87 83 FB 01 cmp bx, 1seg023:0F8Aseg023:0F8A loc_231BA: ; if object is Fremen, and Human is Atreides, Ret Trueseg023:0F8A 75 02 jnz short notAtreidesseg023:0F8Cseg023:0F8C isAtreides: ; CODE XREF: isFriendly?:loc_231B5jseg023:0F8C EB 10 jmp short retTrue ; Jumpseg023:0F8E ; ---------------------------------------------------------------------------seg023:0F8Eseg023:0F8E notAtreides: ; CODE XREF: isFriendly?:loc_231BAjseg023:0F8E EB DE jmp short retFalse ; Jumpseg023:0F90 ; ---------------------------------------------------------------------------seg023:0F90seg023:0F90 notFremen: ; CODE XREF: isFriendly?:loc_231B0jseg023:0F90 3B 16 2C 3A cmp dx, houseHumanID ; Compare Two Operandsseg023:0F94seg023:0F94 loc_231C4: ; Jump if Zero (ZF=1)seg023:0F94 74 06 jz short objectIsHumanseg023:0F96seg023:0F96 loc_231C6: ; Compare Two Operandsseg023:0F96 3B 1E 2C 3A cmp bx, houseHumanIDseg023:0F9Aseg023:0F9A loc_231CA: ; if object is not human, and house is not human, ret trueseg023:0F9A 75 02 jnz short retTrueseg023:0F9Cseg023:0F9C objectIsHuman: ; CODE XREF: isFriendly?:loc_231C4jseg023:0F9C EB D0 jmp short retFalse ; Jumpseg023:0F9E ; ---------------------------------------------------------------------------seg023:0F9Eseg023:0F9E retTrue: ; CODE XREF: isFriendly?+1Bjseg023:0F9E ; isFriendly?:isAtreidesj ...seg023:0F9E B8 01 00 mov ax, 1seg023:0FA1seg023:0FA1 loc_231D1: ; Jumpseg023:0FA1 EB CD jmp short loc_231A0seg023:0FA3 ; ---------------------------------------------------------------------------seg023:0FA3seg023:0FA3 loc_231D3: ; CODE XREF: isFriendly?:loc_231A0jseg023:0FA3 5D pop bpseg023:0FA4seg023:0FA4 locret_231D4: ; Return Far from Procedureseg023:0FA4 CB retfseg023:0FA4 isFriendly? endpNote that HumaHouseID pointer/parameter creates misunderstandings because of the HouseID can be even NOT human, simply it's a 2nd HouseID slot parameter... indeed we have seen above the cases that function can be called, even to check 2 HouseID that it doesn't regard Human.I choose to remove "HOUSE_INVALID" checks because I think that parameters are always valued when function House_AreAllied (isFriendly? on asm) is called.... UPDATE: ON NEXT THREAD PAGE. Quote Link to comment Share on other sites More sharing options...
drnovice Posted March 20, 2013 Share Posted March 20, 2013 This is complete documentation about manage AI alliance. [1 of 4] & [2 of 4]: manage activation of allied AI regard other AI Units. [3 of 4]: manage function about hostility between Houses. [4 of 4]: manage activation of allied AI regard other AI Structures. UPDATE: Available on http://forum.dune2k.com/topic/24707-dune-2-hex-editing-collection-on-exe/ 1 Quote Link to comment Share on other sites More sharing options...
drnovice Posted March 20, 2013 Share Posted March 20, 2013 [1 of 4] is asm reference about c++ chunk of code:src/unit.chp = House_Get_ByIndex(g_playerHouseID); ui = &g_table_unitInfo[unit->o.type]; h = House_Get_ByIndex(houseID); houseIDBit = (1 << houseID); if (houseID == HOUSE_ATREIDES && unit->o.type != UNIT_SANDWORM) { houseIDBit |= (1 << HOUSE_FREMEN); } if ((unit->o.seenByHouses & houseIDBit) != 0 && h->flags.isAIActive) { unit->o.seenByHouses |= houseIDBit; return; }This affected about Allied AI Units behaviour against other AI Units.Here it does Left Shift of 1 to N positions where N is HouseID (0, 1, 2, 3, 4, 5 = H, A, O, F, S, M): 1 << houseID.Left Shift corresponds to multiply value (1 in this case) by 2 every N times that you have specify in second operand.Then it does Bitwise OR of -> Left Shift of 1 to 3 positions (Fremen ID) that is 8h (1000 binary).Bitwise OR put the ones (1) binaries that find in second operator to give them in final result.example: 00001110| 00011000= 00011110Changes:hp = House_Get_ByIndex(g_playerHouseID);ui = &g_table_unitInfo[unit->o.type];h = House_Get_ByIndex(houseID);houseIDBit = (1 << houseID);if ((houseID == HOUSE_ATREIDES || houseID == HOUSE_FREMEN) && unit->o.type != UNIT_SANDWORM) {houseIDBit |= (1 << HOUSE_FREMEN)+(1 << HOUSE_ATREIDES);}if ((unit->o.seenByHouses & houseIDBit) != 0 && h->flags.isAIActive) {unit->o.seenByHouses |= houseIDBit;return;} [2 of 4] is asm reference about c++ chunk of code:src/unit.cif (unit->o.houseID == g_playerHouseID || (unit->o.houseID == HOUSE_FREMEN && g_playerHouseID == HOUSE_ATREIDES)) { unit->o.seenByHouses = 0xFF; } else { unit->o.seenByHouses |= houseIDBit; }Here it does check if object is human, or if object is Fremen and human is Atreides, then set to 1111 1111 (FFh) binary the object unit variable.Else it does Bitwise OR with houseIDBit mask to give the ones to the object unit variable.Changes:if (unit->o.houseID == g_playerHouseID || (unit->o.houseID == HOUSE_FREMEN && g_playerHouseID == HOUSE_ATREIDES) || (unit->o.houseID == HOUSE_ATREIDES && g_playerHouseID == HOUSE_FREMEN)) {unit->o.seenByHouses = 0xFF;} else {unit->o.seenByHouses |= houseIDBit;} [3 of 4] is asm reference about c++ chunk of code:src/house.cbool House_AreAllied(uint8 houseID1, uint8 houseID2){ if (houseID1 == HOUSE_INVALID || houseID2 == HOUSE_INVALID) return false; if (houseID1 == houseID2) return true; if (houseID1 == HOUSE_FREMEN || houseID2 == HOUSE_FREMEN) { return (houseID1 == HOUSE_ATREIDES || houseID2 == HOUSE_ATREIDES); } return (houseID1 != g_playerHouseID && houseID2 != g_playerHouseID);}Changes explained some post above.[4 of 4] is asm reference about c++ chunk of code:src/map.cs = Structure_Get_ByPackedTile(packed); if (s != NULL) { s->o.seenByHouses |= 1 << houseID; if (s->o.houseID == HOUSE_ATREIDES) s->o.seenByHouses |= 1 << HOUSE_FREMEN; }This affected about Allied AI Units behaviour against other AI Structures.Here it does Left Shift of 1 to N positions where N is HouseID (0, 1, 2, 3, 4, 5 = H, A, O, F, S, M): 1 << houseID.Then IF object is Atreides it does Bitwise OR of -> Left Shift of 1 to 3 positions (Fremen ID) that is 8h (1000 binary).Changes:s = Structure_Get_ByPackedTile(packed);if (s != NULL) {s->o.seenByHouses |= 1 << houseID;if (s->o.houseID == HOUSE_ATREIDES || s->o.houseID == HOUSE_FREMEN) s->o.seenByHouses |= (1 << HOUSE_FREMEN)+(1 << HOUSE_ATREIDES);} Quote Link to comment Share on other sites More sharing options...
dynasty Posted March 21, 2013 Share Posted March 21, 2013 That wasn't what I had in mind, but okay. If you don't have the player playing both Atreides and Fremen, you could always just swap the two around. If you play against Fremen and another non-Atreides house (say Harkonnen), the current logic causes H and F to not be considered allies. I think this can cause H tanks to run over Fremen. In Dune 2 eXtended, in one of the final levels, Harkonnen will launch deathhand missiles at the Fremen. Quote Link to comment Share on other sites More sharing options...
drnovice Posted March 21, 2013 Share Posted March 21, 2013 It could be right, since by background, Fremen & Atreides never can be allied to Harkonnen, even if you have them in same Scenario level against your Human House! :) However I think no, because:src/unit.cint16 Unit_GetTargetUnitPriority(Unit *unit, Unit *target){ const UnitInfo *targetInfo; const UnitInfo *unitInfo; uint16 distance; uint16 priority; if (unit == NULL || target == NULL) return 0; if (unit == target) return 0; if (!target->o.flags.s.allocated) return 0; if ((target->o.seenByHouses & (1 << Unit_GetHouseID(unit))) == 0) return 0; if (House_AreAllied(Unit_GetHouseID(unit), Unit_GetHouseID(target))) return 0; unitInfo = &g_table_unitInfo[unit->o.type]; targetInfo = &g_table_unitInfo[target->o.type]; if (!targetInfo->o.flags.priority) return 0; if (targetInfo->movementType == MOVEMENT_WINGER) { if (!unitInfo->o.flags.targetAir) return 0; if (target->o.houseID == g_playerHouseID && !Map_IsPositionUnveiled(Tile_PackTile(target->o.position))) return 0; } if (!Map_IsValidPosition(Tile_PackTile(target->o.position))) return 0; distance = Tile_GetDistanceRoundedUp(unit->o.position, target->o.position); if (!Map_IsValidPosition(Tile_PackTile(unit->o.position))) { if (targetInfo->fireDistance >= distance) return 0; } priority = targetInfo->o.priorityTarget + targetInfo->o.priorityBuild; if (distance != 0) priority = (priority / distance) + 1; if (priority > 0x7D00) return 0x7D00; return priority;}If you play Ordos, and you have against Fremen & Harkonnen in Scenario mission, the check: if ((target->o.seenByHouses & (1 << Unit_GetHouseID(unit))) == 0) return 0; always return 0 if target is Fremen and Unit is Harkonnen, because of o.seenByHouses variable, it's set to FFh (1111 1111 binary) to Fremen ONLY if you play Atreides: if (unit->o.houseID == g_playerHouseID || (unit->o.houseID == HOUSE_FREMEN && g_playerHouseID == HOUSE_ATREIDES)) {unit->o.seenByHouses = 0xFF;} else {unit->o.seenByHouses |= houseIDBit;} The first check is done before the other check: if (House_AreAllied(Unit_GetHouseID(unit), Unit_GetHouseID(target))) return 0; So if first check isn't 0, then it checks this other one. Indeed if we think to Original Dune 2 game, enemy AI when spawning Fremen Troopers by Atreides Palace, always they go against Human Player and other enemy AI Houses never attack them. I'll do some more tests about this... Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.