Jump to content

Recommended Posts

Posted (edited)

The campaign map (also known in the game as 'Globe') had always fascinated me. Today I try to decipher what makes it work.

When you first start a new campaign, you see the campaign map evolve from a globe of Arrakis (or if you did not have a working cutscene file, just the map). Then the following occur:

  • The game announcer (SFX voice) opens the campaign with three statements. One for Atreides, one for Harkonnen, one for Ordos. The order depends on which house you chose to play as.

Let's say you picked Atreides. In fact, we may use this video as reference: https://www.youtube.com/watch?v=-x9MahcVn7k

  • The game announcer opens with the first statement about Atreides. Concurrently, the map animates, and some regions are colored blue, left to right.
  • The game announcer delivers a second statement about the Ordos. Concurrently, the map animates, and some regions are colored green, left to right.
  • The game announcer delivers a second statement about the Harkonnen. Concurrently, the map animates, and some regions are colored red, left to right.
  • Two Atreides icons appear on the map.
  • The game releases control to the player. The player may select the regions where the icons are, or perform other actions (Save, Load, Quit).
  • If the player selects a playable region, the game takes the player to the briefing for that mission.

For the most part, these actions are controlled by the campaign.uib file, I have found out roughly how it works, and other interesting tidbits related to the single-player campaign. 

My findings are summarized in the image below:

4iy2Hox.png

------------------------------

Text copy of the image description:

Quote

Campaign.uib
3 Houses x 10 Missions x 104 bytes = 3120 bytes

Offsets

00 / 0x00 (byte): Version 1 Region ID. Determines which region can be clicked to load version 1 of the mission. Awarded to the player's house when won. If set to 00, disables Version 1.
01 / 0x01 (byte): Version 2 Region ID. Determines which region can be clicked to load version 2 of the mission. Awarded to the player's house when won. If set to 00, disables Version 2.
02 / 0x02 (5 bytes, null-terminated string): Version 1 Mission ID. Technically a null-terminated string, but only 5 bytes (thus 4 characters, are available) 
07 / 0x07 (5 bytes, null-terminated string): Version 2 Mission ID. Technically a null-terminated string, but only 5 bytes (thus 4 characters, are available) 
12 / 0x0c (int): Unused. Takes in values from 00 to 07. EXE has some parser suggesting this is related to the 8 directions (N,NE,E,SE,S,SW,W,NW), but it does not appear to be used in the executable.
16 / 0x10 (int): Same as Offset 12 / 0x0c. This could be the equivalent for Version 2.
20 / 0x14 (int): Version 1 Icon X Position. The X position of the animated icon. This is for visual purposes and the icon is not the clickable hitbox.
24 / 0x18 (int): Version 1 Icon Y Position. The Y position of the animated icon. 
28 / 0x1c (int): Version 2 Icon X Position. The X position of the animated icon. 
32 / 0x20 (int): Version 2 Icon Y Position. The Y position of the animated icon. 
36 / 0x24 (3 bytes): Regions awarded to Atreides. Up to 3 region IDs will be transferred to Atreides ownership after successfully completing this mission. 00 values are ignored.
39 / 0x27 (3 bytes): Regions awarded to Harkonnen. 
42 / 0x2a (3 bytes): Regions awarded to Ordos. 
48 / 0x30 (float): Score multipler for the mission. Base score (multiplier 1x) is 200 points. 
52 / 0x34 (int): Animation order of map regions, the first House to update the map. The map after initializing to the previous mission state, plays audio tracks as 'storytelling', and animates the maps.
56 / 0x38 (int): Animation order of map regions, the second House to update the map.
60 / 0x3c (int): Animation order of map regions, the third House to update the map.
64 / 0x40 (null-terminated string): The first SFX to be played. If set to NONE, skip the SFX.
124 / 0x7c (null-terminated string): The second SFX to be played. If set to NONE, skip the SFX.
184 / 0xB8 (null-terminated string): The third SFX to be played. If set to NONE, skip the SFX.
224 / 0xF4 (8 bytes): The initial theme to play when starting the mission.
256 / 0x100 (4 bytes): Unknown, related to house. Appears to be main enemy house for this mission?

RegionID: hardcoded to 27 entries, 0x01-0x1B. Corresponds to the map regional graphics in /data/UI_GFX/Regions. 00 indicates a null region.
The entire campaign.uib contents is loaded into the game at address 0x00795708. This loading occurs at game initialization.
The region hitboxes are hardcoded as what appears to be POINT structures (int x, int y) from addresses 0x004be3fc to 0x004beb84.

------------------------------

More detailed explanation:

  • The campaign.uib file is divided into 3 Houses, each House with 10 104-byte sections. Each section represents a mission 0 to 9. Mission 0 appears to be a setup performed before animating Mission 1.
  • The campaign.uib file is loaded into the game memory (0x00795708) at startup, like other uib files. If changes are made to the file while the game is in progress, the game has to be restarted for the changes to apply.
  • The executable has hardcoded the following limits: 3 supported Houses, 9 supported missions, each mission having 2 supported versions (V1 and V2), and 27 map regions. Changing those require modifying the executable.
  • The campaign map is split into 27 map regions. 
    • The background piece is DUNEMAP2. 
    • The graphics for each map piece lies in /data/UI_GFX/regions. 
    • The position and polygon hitbox are hardcoded in the game. The polygon points appear to be a POINT (int x, int y) array in executable addresses 0x004be3fc to 0x004beb84.

 

Reference Flow: Atreides Mission 4 -  https://www.youtube.com/watch?v=_3hZzNg9TrA

  • When the player enters the campaign map, the game first notes which mission the player is going to play. (If the player just completed Mission 3, then the next mission is Mission 4)
  • The game notes which House the player is playing as. (E.g. this is an Atreides campaign)
  • The game will then load up the regions for all previous missions for the player's house. Specifically, it begins from a blank map, and starts awarding regions to each houses for each mission up to the previous mission map (right before the previous mission):
    • Atreides Setup (or 'Mission 0'): Atreides is awarded regions 2, 3, 4. Harkonnen is awarded regions 12, 18, 22. Ordos is awarded regions 21, 25, 27.
    • Atreides after Mission 1: Mission reward: regions 7, 8 to player House (Atreides). Atreides is awarded region 1. Harkonnen is awarded regions 13, 16, 19. Ordos is awarded regions 15, 17, 20.
    • Subtotal: A = 1,2,3,4,7,8. H = 12,13,16,18,19,22. O = 15,17,20,21,25,27.
    • Atreides after Mission 2: Mission reward: regions 5, 6 to player House (Atreides). Atreides is awarded nothing. Harkonnen is awarded regions 9, 26. Ordos is awarded regions 24, 11.
    • Subtotal: A = 1,2,3,4,5,6,7,8. H = 9,12,13,16,18,19,22,26. O = 11,15,17,20,21,24,25,27.
    • Player's previous mission was mission 3. Stop here.
  • The game renders this map.
  • The game begins the first SFX / Animation cycle:
    • The first SFX for Atreides Mission 4 is C_A4a. Announcer plays the corresponding speech (AI_MAP4A.AUD)
    • Concurrently, the first house to be animated is House ID 0 - Atreides. Since House Atreidies is also the player's house, the Mission 3 reward (regions 10, 11) and Atreides' own advancement (nothing) shall be given to House Atreides.
      • The map animates the colors of regions 10 (unoccupied) and 11 (Ordos) changing to the Atreides blue. (while the speech is ongoing)
    • First SFX / animation cycle end.
  • The game begins the second SFX / Animation cycle:
    • The second SFX for Atreides Mission 4 is NONE. Nothing is played
    • The second house to be animated is House ID 1 - Harkonnen.  Region 14 shall be given to House Harkonnen.
      • The map animates the colors of region 14 (unoccupied) changing to the Harkonnen red.
    • Second SFX / animation cycle end.
  • The game begins the third SFX / Animation cycle:
    • The third SFX for Atreides Mission 4 is NONE. Nothing is played
    • The third house to be animated is House ID 2 - Ordos.  Region 23 shall be given to House Ordos.
      • The map animates the colors of region 23 (unoccupied) changing to the Ordos green.
    • Third SFX / animation cycle end.
  • The game looks at the mission versions for Atreides Mission 4:
    • Version 1: Region 9, Mission: A4V1, Atreides Icon (AT_POINT) rendered at point 193, 75
    • Version 2: Region 0... Skip.
  • The game renders the animated Atreides icon, and activates the hardcoded polygon for Region 9 and links it to mission A4V1.
  • The game releases control to the player.
    • If the player hovers over Region 9, he'll get an attack cursor.
    • If the player clicks Region 9, he will be taken to the briefing for A4V1.
  • The player starts playing the mission
    • The initial music is indicated to be FREMEN. This will be first music that is played on starting the mission.
    • The mission score multiplier is 2.5 (byteform 00 00 20 40). If he wins the mission, the score screen will divide 2.5 x 200 = 500 points between the player and the enemy AI.
    • If the player wins the mission, the next campaign map will see Region 9 animated to turn to Atreides control.

 

The values covered in green are values taken from campaign.uib.

 

How moddable is this file?

Alas, not very... Although you can change the values in campaign,uib as you like, the game logic imposes some rather arbitrary restrictions:

  • Hardcodes: 3 Houses, 9 Missions, 2 Versions of one mission, 27 map regions
  • Hardcodes: The region polygons for mouse selection. You can draw new regions however you want, the clickable region is still the same. The house icon is only for show.
  • Region changes are cumulative. Campaign maps further down the campaign depend on the maps before it.
  • You cannot return a region to a neutral color.
  • Between any two missions, a non-player house can be awarded a maximum of 3 regions. The player house has the same limit, except that it is also awarded the player's targets from the prior mission, potentially bringing up the number to 5 (3 + v1 and v2 of previous mission).
  • You cannot chose not to award the player's targets to the player's house. For example, A1V1 is Region 7, A1V2 is Region 10. Both regions will be Atreides after mission 1; you cannot make the house take only one region. However, I believe another house could take Region 7 from House Atreides during their animation phase.
  • 1 Mission, 1 Campaign map. Doesn't look like it supports diverging paths and story branches. Only a linear march to victory.

However, you can...

  • Enable missions and define them on the campaign map, which were disabled by the original devs (A4V2, A5V2, A7V2...), provided you have made the missions for them.
  • Change how the regions move around. With creativity you could make very interesting map progress with the 27 regions given to you.
  • If you have new icons, this file can help you adjust their placement on the map. If you have new regions, you might have to look at the executable instead.

 

This is quite the lengthy explanation, but I hope this is a start to understanding one of the more elusive UIBs we have in Dune 2000.

 

EDIT: Fix typos.

EDIT2: It appears I was wrong. Byte 56 / 0x38 (int) is indeed used during the second animation cycle, not the third. Updated the image and text to match.

 

Edited by lovalmidas
  • Upvote 1
  • 2 weeks later...
Posted (edited)

As part of an ongoing effort to collate research into an open-source code, I have created an editor that allows you to edit and preview the campaign map.

The link to the project is here: https://github.com/nguoiyoujie/Spice2k

(pre-built executables in /build/debug and /build/release)

oNPAAbs.png

 

Preview:

VOHxVdB.png

Discovered descriptions of the campaign.uib file format is here (may be moved in the future ) (Edit:) https://github.com/nguoiyoujie/Spice2k/blob/master/doc/spec/uibCampaign.md

 

 

Edited by lovalmidas
  • Upvote 1
Posted

There are times when I think "ok, we reached the pinnacle, I doub people will go even more far than this", and then appears people like you, Klofkack and Azimov and prove me wrong.

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...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.