You must be logged in to post messages.
Please login or register

Scenario Design and Discussion
Moderated by Sebastien, Mr Wednesday

Hop to:    
loginhomeregisterhelprules
Bottom
Topic Subject: SCX format
posted 01-18-11 11:37 AM CT (US)   
AOK Scenario (SCN/SCX) format, by DiGiT
Tab-size: 4

The AOK scenario format is actually shared by Age of Empires I and Age of Empires II. Every file has a 4-byte version string at the very beginning which identifies the program that made the scenario. (See "Versions" table below.) After the reasonably short header, the scenario data is compressed using the DEFLATE method. I have not found any value to store the uncompressed length, so the data must be decompressed into some kind of expandable buffer.

Versions:
1.10Age of Empires I
1.18Age of Empires II
1.21Age of Empires II - TC expansion
- I've put comments next to data members that are version-specific.

The scenario data actually has room for 16 players, not the 9 that are needed by AOE and AOK (with GAIA). Beware when enabling more than 8 players, it has not been tested. Also, as far as I've seen, all the data in the scenario is treated as signed by AOK, which can lead to tricks such as negative tributes, but also opens up the possibility for easy crashing from overflows and the like. Any editor made to manipulate this format must take care with the data. AOK is very sensitive about this data being exactly how it likes it, so even seemingly harmless changes like zero-ing a useless data section can crash it.

I've written this file in pseudo-C so someone who is marginally familiar with C or a similar language will be able to quickly understand. For those of you that don't know any C, I'd suggest taking a look at cplusplus.com's tutorial on C/C++ variables, datatype, and constants (http://www.cplusplus.com/doc/tutorial/tut1-2.html). Below are a couple typedefs that I use as shorthand throughout the file.

typedef long BOOL;//most boolean values are stored as 4 bytes

struct POINT
{
long x, y;
};

struct String
{
short len;
char data[len];//this is not possible in C, of course. Thus pseudo-C. :-)
};


General layout:
Header -> Compressed Data
Compressed Data:
CHeader -> Messages/Cinematics -> Player Data2 -> Global Victory -> Map -> Units -> Player Data3 -> Triggers -> AI Files


**************** Scenario Starts Here ****************

struct Header
{
char version[4];
long length;//length of header (excluding version and self)
const long constant = 2;
time_t lastsave;
long instructions_len;
char instructions[instructions_len];
const long padding = 0;
long playerCount;//thanks iberico
} header;

**** Compression Starts Here ****

struct CHeader
{
long next_uid;
float ver2;
char player_names[0x10][0x100];
#if (VERSION >= 1.18)
long string_table_names[0x10];
#endif
struct PlayerData1
{
BOOL active;
BOOL human;
long civilization; //(see IDs at bottom)
const long constant = 0x00000004;
} player_data[0x10];
long u_long;//usually 1
char u_char;//always 0?
float unknown3;//always -1?
String orginial_filename;
} cheader;

struct M_and_C
{
#if ((VERSION == 1.18) || (VERSION == 1.21 && ver2 == 1.21))
const long strings[5];
#elif (VERSION == 1.21 && ver2 == 1.22)
const long strings[6];
#endif
String instructions, hints, victory, defeat, history;
#if (VERSION == 1.21 && ver2 == 1.22)
String scouts;
#endif
String pg_cinem, vict_cinem, loss_cinem, background;
BOOL bitmap_included;
long bitmap_x, bitmap_y;
short whocares;//seems to be -1 if there is a bitmap, 1 otherwise
BITMAP_INFO_HEADER bmp_info;
char bitmap[];//size must be calculated from bmp_info
} msgs_and_cinem;

struct PlayerData2
{
String unk[0x20];
String ai[0x10];

struct AIFile
{
const long nulls[2] = 0;
long length;
char file[length];
} ai_files[0x10];

char aitype[0x10];//thanks iberico
const long separator = 0xFFFFFF9D;
struct Resources
{
long gold, wood, food, stone, orex;
const long nulls = 0;
} resources[0x10];
} player_data_2;

struct Victory
{
const long seperator = 0xFFFFFF9D;
BOOL conquest;
const long zero1;
long relics;
const long zero2;
long explored;//0 if unused
const long zero3;
BOOL all;//all custom must be met?
long mode, score, time;//time in 10ths of a year
} victory;

struct Diplomacy
{
long diplomacy[0x10][0x10];
//this seems to be the diplomacy that AOK actually reads
//(00 = allied, 01 = neutral, 02 = ?, 03 = enemy)
char nulls[0x2D00] = 0;
const long separator = 0xFFFFFF9D;//why here?!

long AlliedVictory[0x10];
//also in PlayerData3, thanks iberico. AOK doesn't read this one.
}

struct Techs
{
long num_dtechs[0x10];
long disabled_techs[0x10][0x1E];
long num_dunits[0x10];
long disabled_units[0x10][0x1E];
long num_dbuildings[0x10];
long disabled_bldgs[0x10][0x14];
const long nulls2[2] = 0;
long all_techs;
long starting_age[0x10];//-1 = None selected, 0 = Dark, 1 = Feudal, 2 = Castle, 3 = Imperial, 4 = Post-Imperial
} disables;

struct Map
{
const long separator = 0xFFFFFF9D;
long player1_pos[2];//camera position for player 1 (see below)
long aitype;//only in TC?
long mapx, mapy;
Terrain[x][y][3];//ID, elevation, NULL;
} map;

*** Units ***
SizeValue
-------------------
409 00 00 00 (maybe number of players)
struct PlayerData4
{
float resources[6];
float pop_limit;
} player_data_4[8];
Var*10Unit Data (see below). Organized by player (GAIA first), with a 4-byte count preceding each section.

struct Unit
{
float x-pos, y-pos;
const float whoknows = 2; !--- or 3 ??
long id;
short constant; ! 451 ??? --- unit type actually
const char whocares = 2;
float rotation;//in radians
short frame;//initial animation frame
long garrison;
};

*** Player Data3 ***
SizeValue
-------------------
409 00 00 00
64*8Player Data3 (see below)
8Double: 1.6

struct PlayerData3
{
long length; !-- or short?
char constant_name[length]; //"Player #"
float camera[2]; //for player 1, this is the camera position in the editor.
short unknown[2];//something to do with camera? (close values)
bool allied_victory;
short count_diplomacy; !-- 9
char diplomacy[count_diplomacy]; //00 = allied, 01 = neutral, 02 = ?, 03 = enemy; GAIA is always enemy.
long diplomacy2[count_diplomacy]; //00 = GAIA, 01 = self, 02 = allied, 03 = neutral, 04 = enemy
long color;
float n; !-- 2
long nulls[n];
char nulls2[9];
static long end = -1; //in 1.21 only
};

*** Triggers ***
SizeValue
-------------------
100
4Number of triggers = N
V*NTriggers (see below)
4*NList Order

struct POINT
{
long x, y;
};

struct Trigger
{
BOOL enabled;
BOOL looping;
char unknown;
bool objective;//listed in objectives?
long desc_order;//order in objectives
long zeros;
long desc_len;
char description[desc_len];
long name_len;//max 44
char name[name_len];

long num_effects;
Effect effects[num_effects];//size varies with strings
long effect_order[num_effects];

long num_conditions;
Condition conditions[num_conditions];
long condition_order[num_conditions];
}

struct Effect
{
long type;//see constants below
long check;//always = 0x17. For internal use by AOK (and AOKTS).
long ai_goal;//AI Script goal
long amount;//used for resources, hp, attack
long resource;//resource type (stone = 2)
long diplomacy;//state for change diplomacy (see constants below)
long num_selected;//number of units selected
long location_unit;//Unit ID for location setting
long unit_type;//unit constant for create object, etc.
long player_source;
long player_target;
long technology;//see "Complete Constant Lists" in AOKH utilities
long stringid;//as in string table
long unknown;
long display_time;//for Display Instructions
long trigger;//trigger index for Activate/Deactivate Trigger
POINT location;
POINT area_ll;//lower-left corner of area
POINT area_ur;//upper-right corner
long unit_group;
long unit_type;//Civilian, Military, Building, Other
long instruction_panel;
long text_len;
char text[text_len];//Instructions/Chat
long sound_len;
char sound_file[sound_len];
long unit_ids[num_selected];
};

struct Condition
{
long type;//see constants below
long check;//always = 0x10 (for internal use)
long amount;//of objects, difficult level
long resource;//resource type (see constants below)
long unit_object;
long unit_location;
long unit_type;
long player;
long technology;//see "Complete Constant Lists" in AOKH utilities
long timer;
long unknown;
POINT area_ll;
POINT area_ur;
long unit_group;//see constants below
long unit_type;//Civilian, Military, Building, Other
long ai_signal;
};

*** AI Files ***
LengthValue
-------------------------
4Unknown (usually 0)
4Number of AI files included

*** Various Constants ***

enum Player_Colors
{
Blue,
Red,
Green,
Yellow,
Cyan,
Purple,
Gray,
Orange
};

enum Civilizations
{
Britons = 1,
Franks,
Goths,
Teutons,
Japanese,
Chinese,
Byzantines,
Persians,
Saracens,
Turks,
Vikings,
Mongols,
Celts,
Spanish,
Aztecs,
Mayans,
Huns,
Koreans
}

ConstValue
-------------------------
AI Map Types:
9Arabia
0AArchipelago
0BBaltic
0CBlack forest
0DCoastal
0EContinental
0FCrater lake
10Fortress
11Gold rush
12Highland
13Islands
14Mediterranean
15Migration
16Rivers
17Team islands
18
19Scandinavia
1A
1BYucatan
1CSalt marsh
1D
1EKing of the hill
1FOasis
21Nomad

Unit Groups:
0Archer
2Trade Boat
3Building
4Civilian
6Soldier
12Cavalry
13Siege Weapon
18Priest
20Transport Boat
21Fishing Boat
22War Boat
23Conquistador
27Walls
30Flags
36Cavalry Archer
39Gates
44Hand Cannoneer
452-handed Swordsman
46Pikeman
47Scout Cavalry
49Farm
50Spearman
51Packed Siege Weapon
52Tower
54Unpacked Siege Weapon
58Sheep
59King

Resource Type:
0BPopulation

Effects:
1Change Diplomacy
2Research Technology
3Send Chat
4Play Sound
5Send Tribute
6Unlock Gate
7Lock Gate
8Activate Trigger
9Deactivate Trigger
AAI Script Goal
BCreate Object
CTask Object
DDeclare Victory
EKill Object
FRemove Object
10Change View
11Unload
12Change Ownership
13Patrol
14Display Instructions
15Clear Instructions
16Freeze Unit
17Use Advanced Buttons
18Damage Object
19Place Foundation
1AChange Object Name
1BChange Object HP
1CChange Object Attack
1DStop Unit
1E Snap View
1F Unknown
20 Enable Tech
21 Disable Tech
22 Enable Unit
23 Disable Unit
24 Flash Objects

Conditions:
1Bring Object to Area
2Bring Object to Object
3Own Objects
4Own Fewer Objects
5Objects in Area
6Destroy Object
7Capture Object
8Accumulate Attribute
9Research Tehcnology
ATimer
BObject Selected
CAI Signal
DPlayer Defeated
EObject Has Target
FObject Visible
10Object Not Visible
11Researching Technology
12Units Garrisoned
13Difficulty Level
14 Own Fewer Foundations
15 Selected Objects in Area
16 Powered Objects in Area
17 Units Queued Past Pop Cap

enum ResourceTypes
{
RES_Food,
RES_Wood,
RES_Stone,
RES_Gold,
RES_Relics = 7,
RES_Population = 11,
RES_Kills = 20,
RES_Technologies,
RES_Villager Population = 37,
RES_Military Population = 40,
RES_Conversions,
RES_Razings = 43,
RES_Kill Ratio
};

enum DifficultyLevels
{
Easiest,
Standard,
Moderate,
Hard,
Hardest
};

,
Jatayu O===|¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯¯/
`
Battle of Saraighat, 1671|Atlantis, the Lost Realm|AOE Roman Modpack|My profile
ि
StormWind Studios
Replies:
posted 01-18-11 11:38 AM CT (US)     1 / 6  
For information purposes.

,
Jatayu O===|¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯¯/
`
Battle of Saraighat, 1671|Atlantis, the Lost Realm|AOE Roman Modpack|My profile
ि
StormWind Studios
posted 01-19-11 02:50 AM CT (US)     2 / 6  
Interesting. So, this is an example of a saved scenario code or a template for scenario code?

~`o´~|\  Join the fresh and exciting AI Ladder for its fourth season!
´ `  |_\
       |    Learn the joy of AI scripting in my guide: The World of AI Scripting
______|______
 \        /
   .....Hinga Dinga Durgen! - SpongeBob
  `-=<.__.>=-´
posted 01-19-11 09:17 AM CT (US)     3 / 6  
Ma brains like duuurhuuurrrrr, smoke coming out my ears
posted 03-03-11 04:13 AM CT (US)     4 / 6  
What is it? Source code of scx? I thought that C is used to programe .exe, .bin, .dll files - programs. Do you want to say this written in C or C++? So just keeping constants? I would like to see more source examples how the scenario works - does it use some functions? If yes they I want to see some simple functions with description what does it do. I didn't know I could to use C this way. AI instructions (AI - I understand like computer intelligence to play, defense and to fight) - maybe I am wrong) are also in C? Some article about it? I would like to have some program to decompile .scx , see, and compile back.

[This message has been edited by rumburak24 (edited 03-03-2011 @ 04:14 AM).]

posted 03-03-11 10:54 AM CT (US)     5 / 6  
This is the FILE FORMAT of .scx. This is for reference purposes, if you want to write your own programs for reading SCX files.

AokTS and TSE ( Trigger script editor ) both read and write .scx files. Both are open source, so you can get some pointers from them if you want.

,
Jatayu O===|¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯¯/
`
Battle of Saraighat, 1671|Atlantis, the Lost Realm|AOE Roman Modpack|My profile
ि
StormWind Studios
posted 03-05-11 04:53 AM CT (US)     6 / 6  
AI instructions (AI - I understand like computer intelligence to play, defense and to fight) - maybe I am wrong) are also in C?
No, the AI scripts are written in a special language developed for the game, usually with an "if this is true, do this" logic. There is a file called the CPSB on your AoK:TC disc that has good information about AI scripting, and of course you can hop over to the scripting forum here if you have questions.

~`o´~|\  Join the fresh and exciting AI Ladder for its fourth season!
´ `  |_\
       |    Learn the joy of AI scripting in my guide: The World of AI Scripting
______|______
 \        /
   .....Hinga Dinga Durgen! - SpongeBob
  `-=<.__.>=-´
Age of Kings Heaven » Forums » Scenario Design and Discussion » SCX format
Top
You must be logged in to post messages.
Please login or register
Hop to:    
Age of Kings Heaven | HeavenGames