You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

735 lines
16 KiB
Plaintext

//--------------------------------------
//--- 010 Editor v2.1.3 Binary Template
//
// File: H3M SoD Template
// Author: CrackedMind
// Revision: 019
// Purpose: just for fun :D
//
// History: 003 - add "player commands" interpretation
// 004 - fix map identification
// 005 - add "free heroes" block interpretation
// 006 - add "artefacts" block interpretation
// 007 - add "spells", "secondary skill" and "rumors" blocks
// 008 - add "hero options" block
// 009 - change some interpretation of some variables
// add landscape block
// 010 - add "objects" inerpretation
// 011 - add "artefact", "monster", "grail", "pandora box" attributes
// 012 - add "spell scroll", "resource" attributes
// 013 - add "dwellings", "shipyard", "scientist", "random artefacts", "random monsters" attributes
// change many "if" blocks to one big switch :)
// 014 - add "random dwellings", "shrines (1-3)"
// 015 - some refactoring
// add "town", "event", attributes
// 016 - some more refactoring (split to modules)
// add "ocean bottle", "sign", "prophet" (almost complete) attributes
// 017 - add "hero", "prison", "random hero", "prophet" (complete) attributes
// 018 - add "mine", "witch's hut", "hero placeholder" (almost complete) attributes
// fix "town", PLAYERS_ATTRIBUTES struct
// 019 - add global events
// add "lighthouse", "quest guard", "abandoned mine" (2 types)
// add "garrison", "special dwellings" (all types of golems & elementals)
// fix "random dwellings"
//--------------------------------------
// TODO: hero placeholder (defined hero), take more info about "junk" bytes
//
#include "heroes3/hstring.bt"
#include "heroes3/special_victory.bt"
#include "heroes3/secondaryskills.bt"
#include "heroes3/objects.bt"
struct BASIC_PARAMETRES {
int magic_header;
char junk;
uint32 size;
char under;
hstring name;
hstring description;
char difficult;
char levelLimit;
};
struct PLAYER_ATTRIBUTES {
char isHuman;
char isComputer;
char behavior; // 0-Random, 1-Warrior, 2-Builder, 3-Explorer
char isCityTypesOpt;
short cityTypes <format=binary>;;
char randomCity;
char mainCity;
if ( mainCity == 1 ) {
char generateHero;
uchar city[4]; // 0 - city type, 1-3 coords
}
uchar random_hero;
uchar hero_type;
if ( hero_type != 0xFF ) {
uchar hero_portret;
hstring hero_name;
}
char junk;
uint heroes_count;
if ( heroes_count > 0 ) {
struct Hero_tag {
uchar portret;
hstring name;
};
Hero_tag hero[heroes_count] <optimize=false>;
}
};
struct SpecialLossConditions {
uchar id;
if ( id != 0xFF ) {
if ( id == 0x00 || id == 0x01 ) {
uchar coord[3];
}
else if ( id == 0x02 )
ushort days;
}
};
struct Teams {
uchar commands_count;
if ( commands_count > 0 ) {
uchar commands[8];
}
};
struct FreeHeroes {
uchar free_heroes[20];
uchar junk[4];
uchar heroes_count;
if (heroes_count > 0) {
struct tuned_tag {
uchar heroID;
uchar heroPortrait;
hstring hero_name;
uchar players;
} tuned[heroes_count] <optimize=false>;
}
uchar junk2[31];
};
struct Artefacts {
uchar artefacts[18] <format=binary>;
};
struct Spells {
uchar spells[9] <format=binary>;
};
struct SecSkills {
uchar skills[4] <format=binary>;
};
struct Rumors {
uint32 total_rumors;
if ( total_rumors > 0 ) {
struct Rumor_tag {
hstring rumor_name;
hstring rumor_text;
} rumors[total_rumors] <optimize=false>;
}
};
struct HeroOptions_enabled {
uchar isExp;
if ( isExp == 1 )
uint32 exp;
uchar isSecSkill;
if ( isSecSkill == 1 ) {
uint32 skills_count;
secskill_tag secskills [skills_count];
}
uchar isArtefacts;
if ( isArtefacts == 1 ) {
ushort headID;
ushort shouldersID;
ushort neckID;
ushort rightHandID;
ushort leftHandID;
ushort trunkID;
ushort rightRingID;
ushort leftRingID;
ushort legsID;
ushort misc1ID;
ushort misc2ID;
ushort misc3ID;
ushort misc4ID;
ushort machine1ID;
ushort machine2ID;
ushort machine3ID;
ushort machine4ID;
ushort magicbook;
ushort misc5ID;
ushort knapsack_count;
if ( knapsack_count > 0 )
ushort knapsackID[knapsack_count];
}
uchar isBiography;
if (isBiography == 1)
hstring biography;
uchar gender <read=genderRead>;
uchar isSpells;
if ( isSpells == 1 )
uchar spells[9] <format=binary>;
uchar isPrimarySkills;
if ( isPrimarySkills == 1 ) {
uchar attack;
uchar defence;
uchar power;
uchar knowledge;
}
};
struct HeroOptions {
local int i;
for (i = 0; i < 156; i++) {
uchar enable;
if ( enable == 1 )
HeroOptions_enabled options;
}
};
struct LandCell {
uchar surfaceID;
uchar surfacePattern;
uchar riverID;
uchar riverPattern;
uchar roadID;
uchar roadPattern;
uchar mirroring <format=binary>;
};
struct Object {
hstring filename;
uchar passability[6];
uchar actions[6];
ushort landscape;
ushort land_edit_groups; // for editor
uint32 object_class;
uint32 object_number;
uchar object_group;
uchar isOverlay;
uchar junk[16];
};
struct ObjectOptions {
uchar coord[3]; // x, y, z;
uint32 objectID;
uchar junk[5];
};
struct ObjectShrine {
uint32 spellID;
};
struct ObjectEvent {
ObjectPandora event;
uchar players;
uchar isAICan;
uchar disableAfterFirstDay;
uint32 junk;
};
struct ObjectSign {
hstring text;
uint32 junk;
};
struct ObjectProphet {
uchar quest;
switch(quest) {
case 0:
break;
case 1:
uint32 level;
break;
case 2:
uchar offence;
uchar defence;
uchar power;
uchar knowledge;
break;
case 3:
uint32 heroID;
break;
case 4:
uint32 monsterID;
break;
case 5:
uchar art_quantity;
ushort arts[art_quantity];
break;
case 6:
uchar creatures_quantity;
if ( creatures_quantity > 0 ) {
GuardTag creatures[creatures_quantity];
}
break;
case 7:
uint32 resources[7];
break;
case 8:
uchar heroID;
break;
case 9:
uchar player_color;
break;
};
uint32 time_limit; // FF FF FF FF - no limit
hstring quest_begin;
hstring quest_inprocess;
hstring quest_end;
uchar reward;
switch(reward) {
case 0:
break;
case 1:
uint32 exp;
break;
case 2:
uint32 spell_points;
break;
case 3:
uchar morale;
break;
case 4:
uchar lucky;
break;
case 5:
uchar resID;
uint32 res_quantity;
break;
case 6:
uchar priSkillID;
uchar priSkillBonus;
break;
case 7:
uchar secSkillID;
uchar secSkillLevel;
break;
case 8:
ushort artID;
break;
case 9:
uchar spellID;
break;
case 10:
ushort creatureID;
ushort creatureQuantity;
break;
};
char junk[2];
};
struct ObjectHero {
uint32 heroID;
uchar color;
uchar hero; // FF - random
uchar isName;
if ( isName == 1 )
hstring name;
uchar isExp;
if ( isExp == 1 )
uint32 exp;
uchar isPortrait;
if ( isPortrait == 1)
uchar portrait;
uchar isSecondary;
if ( isSecondary == 1 ) {
uint32 skills_quantity;
if ( skills_quantity > 0 )
secskill_tag skills[skills_quantity];
}
uchar isCreature;
if ( isCreature == 1 )
GuardTag creatures[7];
uchar creaturesFormation;
uchar isArtefacts;
if ( isArtefacts == 1 ) {
ushort headID;
ushort shouldersID;
ushort neckID;
ushort rightHandID;
ushort leftHandID;
ushort trunkID;
ushort rightRingID;
ushort leftRingID;
ushort legsID;
ushort misc1ID;
ushort misc2ID;
ushort misc3ID;
ushort misc4ID;
ushort machine1ID;
ushort machine2ID;
ushort machine3ID;
ushort machine4ID;
ushort magicbook;
ushort misc5ID;
ushort knapsack_count;
if ( knapsack_count > 0 )
ushort knapsackID[knapsack_count];
}
uchar zoneRadius;
uchar isBiography;
if ( isBiography == 1 )
hstring biography;
uchar gender <read=genderRead>;
uchar isSpells;
if ( isSpells == 1 ) {
uchar spells[9] <format=binary>;
}
uchar isPrimary;
if ( isPrimary == 1 ) {
uchar offence;
uchar defence;
uchar power;
uchar knowledge;
}
uint32 unknown[4];
};
struct ObjectHeroPlaceholder {
uchar color;
uchar type;
};
struct ObjectMine {
uint32 color;
};
struct ObjectWitchHut {
uint32 secskills <format=binary>;
};
struct globalEvent {
hstring name;
hstring text;
int32 resources[7];
uchar players_affected;
uchar human_affected;
uchar ai_affected;
ushort day_of_first_event;
ushort event_iteration;
char junk[16];
};
struct ObjectQuestionGuard {
uchar quest;
switch(quest) {
case 0:
break;
case 1:
uint32 level;
break;
case 2:
uchar offence;
uchar defence;
uchar power;
uchar knowledge;
break;
case 3:
uint32 heroID;
break;
case 4:
uint32 monsterID;
break;
case 5:
uchar art_quantity;
ushort arts[art_quantity];
break;
case 6:
uchar creatures_quantity;
if ( creatures_quantity > 0 ) {
GuardTag creatures[creatures_quantity];
}
break;
case 7:
uint32 resources[7];
break;
case 8:
uchar heroID;
break;
case 9:
uchar player_color;
break;
};
uint32 time_limit; // FF FF FF FF - no limit
hstring quest_begin;
hstring quest_inprocess;
hstring quest_end;
};
struct ObjectGarrison {
uint32 color;
GuardTag guards[7];
uchar undeleteSoldiers;
uint32 junk[2];
};
struct ObjectAbandonedMine {
uchar resources <format=binary>;
uchar junk[3];
};
string genderRead(uchar &gend) {
string s;
if ( gend == 0 )
SPrintf(s, "%s", "male");
else if ( gend == 1 )
SPrintf(s, "%s", "female");
else if ( gend == 0xFF )
SPrintf(s, "%s", "by default");
return s;
}
//
// !!! entrypoint !!!
//
BASIC_PARAMETRES bp;
// Check for header
if( bp.magic_header != 0x0000001C )
{
Warning( "File is not a Heroes III SoD Map. Template stopped." );
return -1;
}
PLAYER_ATTRIBUTES red;
PLAYER_ATTRIBUTES blue;
PLAYER_ATTRIBUTES tan;
PLAYER_ATTRIBUTES green;
PLAYER_ATTRIBUTES orange;
PLAYER_ATTRIBUTES purple;
PLAYER_ATTRIBUTES teal;
PLAYER_ATTRIBUTES pink;
SpecialVictoryConditions svc <optimize=false>;
SpecialLossConditions slc <optimize=false>;
Teams cmd;
FreeHeroes fh;
Artefacts arts;
Spells sp;
SecSkills ss;
Rumors rumors;
HeroOptions options;
LandCell ground[bp.size*bp.size] <optimize=true>;
if ( bp.under == 1 )
LandCell underground[bp.size*bp.size];
uint32 objects_count;
if ( objects_count > 0 )
Object objects[objects_count] <optimize=false>;
uint32 tunedobj_count;
local int i;
if ( tunedobj_count > 0 ) {
for ( i = 0; i < tunedobj_count; i++ ) {
ObjectOptions obj;
switch(objects[obj.objectID].object_class)
{
case 5:
case 65:
case 66:
case 67:
case 68:
case 69:
ObjectArtefact artefact;
break;
case 6:
ObjectPandora pandora;
break;
case 17:
case 20:
case 42: //lighthouse
ObjectDwelling dwelling;
break;
case 26:
ObjectEvent localevent;
break;
case 33:
case 219:
ObjectGarrison garrison;
break;
case 34:
case 70:
ObjectHero hero;
break;
case 62:
ObjectHero hero;
break;
case 36:
ObjectGrail grail;
break;
case 53:
switch(objects[obj.objectID].object_number) {
case 7:
ObjectAbandonedMine abandoned; // bit0 - mercury, 1 - ore, 2 - sulfur,
break; // bit3 - crystal, 4 - gem, 5 - gold
default:
ObjectMine mine;
break;
}
break;
case 54:
case 71:
case 72:
case 73:
case 74:
case 75:
case 162:
case 163:
case 164:
ObjectMonster monster;
break;
case 76:
case 79:
ObjectResource res;
break;
case 81:
ObjectScientist scientist;
break;
case 83:
ObjectProphet prophet;
break;
case 87:
ObjectShipyard shipyard;
break;
case 88:
case 89:
case 90:
ObjectShrine shrine;
break;
case 91:
case 59:
ObjectSign sign;
break;
case 93:
ObjectSpell spell;
break;
case 98:
case 77:
ObjectTown town;
break;
case 113:
ObjectWitchHut whut;
break;
case 215:
ObjectQuestionGuard qguard;
break;
case 216:
ObjectGeneralRandomDwelling dwelling;
break;
case 217:
ObjectLevelRandomDwelling dwelling;
break;
case 218:
ObjectTownRandomDwelling dwelling;
break;
case 220:
ObjectAbandonedMine abandoned;
break;
};
}
}
uint32 gevents_quantity;
globalEvent gevents[gevents_quantity] <optimize=false>;
uchar main_junk[124];