add some more things
This commit is contained in:
parent
12d1fcd2fa
commit
36d75698f1
22 changed files with 4228 additions and 0 deletions
70
decompress.py
Normal file
70
decompress.py
Normal file
|
@ -0,0 +1,70 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import zlib, os
|
||||
import struct
|
||||
|
||||
import Image, ImageDraw
|
||||
|
||||
lod = open("H3bitmap.lod")
|
||||
lod.seek(8)
|
||||
files_count = struct.unpack("i", lod.read(4))[0]
|
||||
files=[]
|
||||
for file in range(2745,2793):
|
||||
lod.seek(92+(file*32))
|
||||
name = lod.read(16).split("\0")[0]
|
||||
offset = struct.unpack("i", lod.read(4))[0] #offset
|
||||
size_orig = struct.unpack("i", lod.read(4))[0] #size_original
|
||||
type = struct.unpack("i", lod.read(4))[0] #type
|
||||
size_comp = struct.unpack("i", lod.read(4))[0] #size_compressed
|
||||
|
||||
lod.seek(offset)
|
||||
|
||||
if size_comp:
|
||||
pcx = zlib.decompress(lod.read(size_comp))
|
||||
else:
|
||||
pcx = lod.read(size_orig)
|
||||
|
||||
if type == 16:
|
||||
size = struct.unpack("i", pcx[:4])[0]
|
||||
width = struct.unpack("i", pcx[4:8])[0]
|
||||
height = struct.unpack("I", pcx[8:12])[0]
|
||||
print file, name, width, height
|
||||
|
||||
im = Image.new("RGBA", (width, height))
|
||||
draw = ImageDraw.Draw(im)
|
||||
bla=[]
|
||||
for i in range(256):
|
||||
bla.append((ord(pcx[12+size+i*3]),ord(pcx[12+size+i*3+1]),ord(pcx[12+size+i*3+2])))
|
||||
|
||||
for i in range(size):
|
||||
a =ord(pcx[12+i])
|
||||
if bla[a] == (0,255,255):
|
||||
draw.point((i-int(i/width)*width,int(i/width)), fill=(0,0,0,0))
|
||||
else:
|
||||
draw.point((i-int(i/width)*width,int(i/width)), fill=bla[a])
|
||||
im.save(' '.join([str(file),name]), "PNG")
|
||||
elif type == 17:
|
||||
size = struct.unpack("i", pcx[:4])[0]
|
||||
width = struct.unpack("i", pcx[4:8])[0]
|
||||
height = struct.unpack("I", pcx[8:12])[0]
|
||||
print file, name, width, height
|
||||
|
||||
im = Image.new("RGB", (width, height))
|
||||
draw = ImageDraw.Draw(im)
|
||||
|
||||
for i in range(size/3):
|
||||
if ord(pcx[12+i*3]) == 0 and ord(pcx[13+i*3]) == 255 and ord(pcx[14+i*3]) == 255:
|
||||
draw.point((i-int(i/width)*width,int(i/width)), fill=(0,0,0,0))
|
||||
else:
|
||||
draw.point((i-int(i/width)*width,int(i/width)), fill=(ord(pcx[12+i*3]),ord(pcx[13+i*3]),ord(pcx[14+i*3])))
|
||||
im.save(' '.join([str(file),name]), "PNG")
|
||||
elif type in (1, 2, 64, 65, 66, 67, 68, 69, 70, 71, 73, 79, 80, 96):
|
||||
print file, name
|
||||
file = open(' '.join([str(file),name]), "w")
|
||||
file.write(pcx)
|
||||
file.close()
|
||||
else:
|
||||
print i, name, type
|
||||
sys.exit("not supported %d"%type)
|
||||
|
||||
lod.close()
|
143
h3c_and_h3m_formats/H3C_SoD_Template.bt
Normal file
143
h3c_and_h3m_formats/H3C_SoD_Template.bt
Normal file
|
@ -0,0 +1,143 @@
|
|||
//--------------------------------------
|
||||
//--- 010 Editor v2.1.3 Binary Template
|
||||
//
|
||||
// File: H3C SoD Template
|
||||
// Author: crackedmind
|
||||
// Revision: 001
|
||||
// Purpose: just for fun :)
|
||||
//--------------------------------------
|
||||
#include "heroes3/hstring.bt"
|
||||
#include "heroes3/secondaryskills.bt"
|
||||
|
||||
struct Header {
|
||||
uint32 magic; // 05 00 00 00 - AB
|
||||
// 06 00 00 00 - SoD
|
||||
// ?? ?? ?? ?? - RoE
|
||||
|
||||
uchar map_number; // CampText.txt
|
||||
hstring name;
|
||||
hstring description;
|
||||
uchar canPlayerChooseDifficult;
|
||||
uchar whatMusic; // CmpMusic.txt, start from 0
|
||||
};
|
||||
|
||||
struct ScenarioTravel {
|
||||
uchar whatHeroKeep; // bit 1 - expirience
|
||||
// bit 2 - primary skills
|
||||
// bit 3 - secondary skills
|
||||
// bit 4 - spells
|
||||
// bit 5 - artefacts
|
||||
|
||||
uchar whatMonstresHeroKeep[19];
|
||||
uchar whatArtifactsHeroKeep[18];
|
||||
|
||||
uchar startOptions; // 01 - start bonus
|
||||
// 02 - traveling hero
|
||||
// 03 - hero options
|
||||
|
||||
if ( startOptions == 1 ) {
|
||||
uchar playerColor;
|
||||
uchar bonusCount;
|
||||
local int i;
|
||||
for ( i = 0; i < bonusCount; i++ ) {
|
||||
uchar bonusType;
|
||||
|
||||
switch(bonusType){
|
||||
case 0: //spell
|
||||
uint16 heroName; //0xFDFF - most powerfull hero
|
||||
// other names from hotraits.txt
|
||||
uchar spell;
|
||||
break;
|
||||
case 1: // monster
|
||||
uint16 heroName; //0xFDFF - most powerfull hero
|
||||
// other names from hotraits.txt
|
||||
|
||||
uint16 monsterType;
|
||||
uint16 count;
|
||||
case 2: // building
|
||||
// TODO
|
||||
break;
|
||||
case 3:
|
||||
uint16 heroName; //0xFDFF - most powerfull hero
|
||||
// other names from hotraits.txt
|
||||
|
||||
uint16 artefact;
|
||||
break;
|
||||
case 4: // spell scroll
|
||||
uint16 heroName; //0xFDFF - most powerfull hero
|
||||
// other names from hotraits.txt
|
||||
|
||||
uchar spell;
|
||||
break;
|
||||
case 5: // primary skills
|
||||
uint16 heroName; //0xFDFF - most powerfull hero
|
||||
// other names from hotraits.txt
|
||||
|
||||
uchar primarySkills[4];
|
||||
break;
|
||||
case 6: // secondary skills
|
||||
uint16 heroName; //0xFDFF - most powerfull hero
|
||||
// other names from hotraits.txt
|
||||
|
||||
secskill_tag secskill;
|
||||
break;
|
||||
case 7: // resource
|
||||
uchar type; // 0 - wood, 1 - Mercury
|
||||
// 2 - ore, 3 - sulfur
|
||||
// 4 - crystal, 5 - gem
|
||||
// 6 - gold, FD - wood+ore
|
||||
// FE - mercury+sulfur+crystal+gem
|
||||
uint32 count;
|
||||
break;
|
||||
};
|
||||
}
|
||||
} else if ( startOptions == 2 ) {
|
||||
uchar count;
|
||||
|
||||
local uchar i;
|
||||
for ( i = 0; i < count; i++) {
|
||||
uchar whichPlayer; // player color
|
||||
uchar fromWhatScenario;
|
||||
}
|
||||
} else if ( startOptions == 3 ) {
|
||||
uchar heroesCount; // max is 3
|
||||
local uchar i;
|
||||
|
||||
for (i =0; i < heroesCount; i++ ) {
|
||||
uchar playerColor;
|
||||
uint16 hero; // FF FF is random
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct Scenario {
|
||||
hstring map_name;
|
||||
uint32 packedMapSize;
|
||||
uchar preconditionRegion; // if equal to 0, then no region
|
||||
uchar regionColor;
|
||||
uchar difficult;
|
||||
|
||||
hstring regionText;
|
||||
|
||||
struct ScenarioProlog {
|
||||
uchar isProlog;
|
||||
if ( isProlog == 1 ) {
|
||||
uchar prologVideo; // from CmpMovie.txt
|
||||
uchar prologMusic; // from CmpMusic.txt
|
||||
hstring prologText;
|
||||
}
|
||||
} prolog;
|
||||
ScenarioProlog epilog;
|
||||
|
||||
ScenarioTravel travel;
|
||||
};
|
||||
|
||||
Header header;
|
||||
|
||||
if ( header.magic != 0x00000006 ) {
|
||||
Warning( "File is not a Heroes III SoD Company file. Template stopped." );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// here must be a loop, iterations == map regions number, but it's hardcoded feature :(
|
||||
Scenario scenario;
|
734
h3c_and_h3m_formats/H3M_SoD_Template.bt
Normal file
734
h3c_and_h3m_formats/H3M_SoD_Template.bt
Normal file
|
@ -0,0 +1,734 @@
|
|||
//--------------------------------------
|
||||
//--- 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];
|
15
h3c_and_h3m_formats/Heroes3/hstring.bt
Normal file
15
h3c_and_h3m_formats/Heroes3/hstring.bt
Normal file
|
@ -0,0 +1,15 @@
|
|||
typedef struct {
|
||||
uint32 str_len;
|
||||
|
||||
if ( str_len > 0 )
|
||||
char str[str_len];
|
||||
}hstring <read=hstringRead>;
|
||||
|
||||
string hstringRead (hstring &str) {
|
||||
string s;
|
||||
if ( str.str_len > 0 )
|
||||
SPrintf( s, "%s", str.str );
|
||||
else
|
||||
return "empty";
|
||||
return s;
|
||||
}
|
18
h3c_and_h3m_formats/Heroes3/object/artefact.bt
Normal file
18
h3c_and_h3m_formats/Heroes3/object/artefact.bt
Normal file
|
@ -0,0 +1,18 @@
|
|||
struct ObjectArtefact {
|
||||
uchar isText;
|
||||
|
||||
if ( isText == 1 ) {
|
||||
hstring text;
|
||||
|
||||
|
||||
uchar isGuards;
|
||||
|
||||
if ( isGuards == 1 ) {
|
||||
struct GuardTag {
|
||||
ushort GuardID;
|
||||
ushort GuardCount;
|
||||
} Guards[7];
|
||||
}
|
||||
uchar junk[4];
|
||||
}
|
||||
};
|
30
h3c_and_h3m_formats/Heroes3/object/dwellings.bt
Normal file
30
h3c_and_h3m_formats/Heroes3/object/dwellings.bt
Normal file
|
@ -0,0 +1,30 @@
|
|||
struct ObjectDwelling {
|
||||
uint32 owner; // FF - nobody
|
||||
};
|
||||
|
||||
struct ObjectShipyard {
|
||||
ObjectDwelling shipyard;
|
||||
};
|
||||
|
||||
struct ObjectGeneralRandomDwelling {
|
||||
uint32 owner;
|
||||
uint32 junk;
|
||||
if (junk == 0 )
|
||||
ushort towns;
|
||||
|
||||
uchar minlevel;
|
||||
uchar maxlevel;
|
||||
};
|
||||
|
||||
struct ObjectLevelRandomDwelling {
|
||||
uint32 owner;
|
||||
uint32 junk;
|
||||
if ( junk == 0 )
|
||||
ushort towns;
|
||||
};
|
||||
|
||||
struct ObjectTownRandomDwelling {
|
||||
uint32 owner;
|
||||
uchar minlevel;
|
||||
uchar maxlevel;
|
||||
};
|
4
h3c_and_h3m_formats/Heroes3/object/grail.bt
Normal file
4
h3c_and_h3m_formats/Heroes3/object/grail.bt
Normal file
|
@ -0,0 +1,4 @@
|
|||
struct ObjectGrail {
|
||||
char radius;
|
||||
uchar junk2[3];
|
||||
};
|
24
h3c_and_h3m_formats/Heroes3/object/monster.bt
Normal file
24
h3c_and_h3m_formats/Heroes3/object/monster.bt
Normal file
|
@ -0,0 +1,24 @@
|
|||
struct ObjectMonster {
|
||||
uint32 monsterID;
|
||||
ushort monsters_count; // if 0, then random
|
||||
uchar mood;
|
||||
uchar isTreasureOrText;
|
||||
|
||||
if ( isTreasureOrText == 1 ) {
|
||||
hstring text;
|
||||
|
||||
uint32 wood;
|
||||
uint32 mercury;
|
||||
uint32 ore;
|
||||
uint32 sulfur;
|
||||
uint32 crystal;
|
||||
uint32 gem;
|
||||
uint32 gold;
|
||||
ushort artefactID;
|
||||
}
|
||||
|
||||
uchar monsterNeverRunAway; // 1 - yes, 0 - no
|
||||
uchar monsterDontGrowUp; // 1 - yes, 0 - no
|
||||
|
||||
uchar junk2[2];
|
||||
};
|
44
h3c_and_h3m_formats/Heroes3/object/pandorabox.bt
Normal file
44
h3c_and_h3m_formats/Heroes3/object/pandorabox.bt
Normal file
|
@ -0,0 +1,44 @@
|
|||
struct ObjectPandora {
|
||||
ObjectArtefact art;
|
||||
uint32 exp;
|
||||
int32 spell_points;
|
||||
char morals;
|
||||
char luck;
|
||||
|
||||
int32 wood;
|
||||
int32 mercury;
|
||||
int32 ore;
|
||||
int32 sulfur;
|
||||
int32 crystal;
|
||||
int32 gem;
|
||||
int32 gold;
|
||||
|
||||
uchar offence;
|
||||
uchar defence;
|
||||
uchar power;
|
||||
uchar knowledge;
|
||||
|
||||
uchar secskills;
|
||||
|
||||
if ( secskills > 0 ) {
|
||||
secskill_tag sec_skills [secskills];
|
||||
}
|
||||
|
||||
uchar artefacts;
|
||||
|
||||
if ( artefacts > 0 ) {
|
||||
ushort artID[artefacts];
|
||||
}
|
||||
|
||||
uchar spells;
|
||||
if ( spells > 0 ) {
|
||||
uchar spellID[spells];
|
||||
}
|
||||
|
||||
uchar monstres_count;
|
||||
|
||||
if ( monstres_count > 0 ) {
|
||||
GuardTag monstres[monstres_count];
|
||||
}
|
||||
uchar junk3[8];
|
||||
};
|
5
h3c_and_h3m_formats/Heroes3/object/resource.bt
Normal file
5
h3c_and_h3m_formats/Heroes3/object/resource.bt
Normal file
|
@ -0,0 +1,5 @@
|
|||
struct ObjectResource {
|
||||
ObjectArtefact res;
|
||||
uint32 quantity;
|
||||
uchar junk[4];
|
||||
};
|
9
h3c_and_h3m_formats/Heroes3/object/scientist.bt
Normal file
9
h3c_and_h3m_formats/Heroes3/object/scientist.bt
Normal file
|
@ -0,0 +1,9 @@
|
|||
struct ObjectScientist {
|
||||
uchar bonus_type; // FF - Random
|
||||
union {
|
||||
uint32 primaryID;
|
||||
uint32 secondaryID;
|
||||
uint32 spellID;
|
||||
} bonus;
|
||||
uchar junk2[3];
|
||||
};
|
4
h3c_and_h3m_formats/Heroes3/object/spellscroll.bt
Normal file
4
h3c_and_h3m_formats/Heroes3/object/spellscroll.bt
Normal file
|
@ -0,0 +1,4 @@
|
|||
struct ObjectSpell {
|
||||
ObjectArtefact spell;
|
||||
uint32 spellID;
|
||||
};
|
57
h3c_and_h3m_formats/Heroes3/object/town.bt
Normal file
57
h3c_and_h3m_formats/Heroes3/object/town.bt
Normal file
|
@ -0,0 +1,57 @@
|
|||
struct ObjectTown {
|
||||
char junk[4];
|
||||
uchar owner;
|
||||
|
||||
uchar isName;
|
||||
|
||||
if ( isName == 1 )
|
||||
hstring name;
|
||||
|
||||
uchar isGuard;
|
||||
|
||||
if (isGuard == 1 )
|
||||
GuardTag guards[7];
|
||||
|
||||
uchar formation; // 00 - standalone, 01 - group
|
||||
|
||||
uchar isBuildings;
|
||||
|
||||
if ( isBuildings == 1 ) {
|
||||
uchar built[6];
|
||||
uchar active[6];
|
||||
} else {
|
||||
uchar isFort;
|
||||
}
|
||||
|
||||
uchar mustSpells[9];
|
||||
uchar canSpells[9];
|
||||
|
||||
uint32 event_quantity;
|
||||
|
||||
if ( event_quantity > 0 ) {
|
||||
struct TownEvent {
|
||||
hstring event_name;
|
||||
hstring event_text;
|
||||
|
||||
int32 wood;
|
||||
int32 mercury;
|
||||
int32 ore;
|
||||
int32 sulfur;
|
||||
int32 crystal;
|
||||
int32 gem;
|
||||
int32 gold;
|
||||
|
||||
uchar players_affected;
|
||||
uchar human_affected;
|
||||
uchar ai_affected;
|
||||
|
||||
ushort day_of_first_event;
|
||||
ushort event_iteration;
|
||||
uint32 junk[4];
|
||||
uchar buildings[6];
|
||||
ushort creatures[7];
|
||||
uint32 junk2;
|
||||
} events[event_quantity] <optimize=false>;
|
||||
}
|
||||
uint32 junk3;
|
||||
};
|
9
h3c_and_h3m_formats/Heroes3/objects.bt
Normal file
9
h3c_and_h3m_formats/Heroes3/objects.bt
Normal file
|
@ -0,0 +1,9 @@
|
|||
#include "heroes3/object/monster.bt"
|
||||
#include "heroes3/object/artefact.bt"
|
||||
#include "heroes3/object/grail.bt"
|
||||
#include "heroes3/object/pandorabox.bt"
|
||||
#include "heroes3/object/spellscroll.bt"
|
||||
#include "heroes3/object/resource.bt"
|
||||
#include "heroes3/object/town.bt"
|
||||
#include "heroes3/object/dwellings.bt"
|
||||
#include "heroes3/object/scientist.bt"
|
4
h3c_and_h3m_formats/Heroes3/secondaryskills.bt
Normal file
4
h3c_and_h3m_formats/Heroes3/secondaryskills.bt
Normal file
|
@ -0,0 +1,4 @@
|
|||
struct secskill_tag {
|
||||
uchar skillID;
|
||||
uchar skillLevel;
|
||||
};
|
39
h3c_and_h3m_formats/Heroes3/special_victory.bt
Normal file
39
h3c_and_h3m_formats/Heroes3/special_victory.bt
Normal file
|
@ -0,0 +1,39 @@
|
|||
struct SpecialVictoryConditions {
|
||||
uchar id;
|
||||
|
||||
if ( id != 0xFF ) {
|
||||
char canStandardEnd;
|
||||
char canComputer;
|
||||
}
|
||||
|
||||
if ( id == 0x00 ) {
|
||||
struct svc_acqSpecArt_tag {
|
||||
char artID;
|
||||
} svc_acqSpecArt;
|
||||
} else if ( id == 0x01 ) {
|
||||
struct svc_accCreatures_tag {
|
||||
ushort creatureID;
|
||||
DWORD creatureCount;
|
||||
}svc_accCreatures;
|
||||
} else if ( id == 0x02 ) {
|
||||
struct svc_accRes_tag {
|
||||
char resID;
|
||||
DWORD resCount;
|
||||
} svc_accRes;
|
||||
} else if ( id == 0x03 ) {
|
||||
struct svc_upgSpecTown_tag {
|
||||
uchar coord[3];
|
||||
char hall_level;
|
||||
char castle_level;
|
||||
} svc_upgSpecTown;
|
||||
} else if ( id == 0x04 || id == 0x05 || id == 0x06 || id == 0x07 ) {
|
||||
uchar coord[3];
|
||||
} else if ( id == 0x08 || id == 0x09) {
|
||||
// no more data
|
||||
} else if ( id == 0x0A ) {
|
||||
struct svc_tranSpecArt_tag {
|
||||
uchar artID;
|
||||
uchar coord[3];
|
||||
} svc_tranSpecArt;
|
||||
}
|
||||
};
|
1005
h3c_and_h3m_formats/h3m_description.TXT
Normal file
1005
h3c_and_h3m_formats/h3m_description.TXT
Normal file
File diff suppressed because it is too large
Load diff
40
image_viewer.py
Executable file
40
image_viewer.py
Executable file
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import pyglet
|
||||
|
||||
images = [
|
||||
pyglet.image.load("puzzle/cas/%d PuzCas%02d.pcx"%(i+2745, i)) for i in xrange(20)
|
||||
]
|
||||
|
||||
bin = pyglet.image.atlas.TextureBin()
|
||||
images = [bin.add(image) for image in images]
|
||||
|
||||
window = pyglet.window.Window(800,600)
|
||||
image = pyglet.resource.image('interface/3178 Puzzle.pcx')
|
||||
image1 = pyglet.resource.image('interface/153 AResBar.pcx')
|
||||
|
||||
@window.event
|
||||
def on_draw():
|
||||
window.clear()
|
||||
image.blit(0, 0)
|
||||
image1.blit(3, 3)
|
||||
images[0].blit(7,414)
|
||||
images[1].blit(7,402)
|
||||
images[2].blit(7,412)
|
||||
images[3].blit(7,359)
|
||||
images[4].blit(7,264)
|
||||
images[5].blit(7,49)
|
||||
images[6].blit(16,527)
|
||||
images[7].blit(22,49)
|
||||
images[8].blit(70,49)
|
||||
images[9].blit(72,285)
|
||||
|
||||
@window.event
|
||||
def on_key_press(symbol, modifiers):
|
||||
if symbol == pyglet.window.key.Q:
|
||||
pyglet.app.exit()
|
||||
|
||||
pyglet.gl.glEnable(pyglet.gl.GL_BLEND)
|
||||
pyglet.gl.glBlendFunc(pyglet.gl.GL_SRC_ALPHA, pyglet.gl.GL_ONE_MINUS_SRC_ALPHA)
|
||||
|
||||
pyglet.app.run()
|
52
lodextract.py
Normal file
52
lodextract.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import zlib, os
|
||||
import struct
|
||||
|
||||
import Image, ImageDraw
|
||||
import StringIO
|
||||
|
||||
lod = open("H3bitmap.lod")
|
||||
lod.seek(8)
|
||||
files_count = struct.unpack("i", lod.read(4))[0]
|
||||
files=[]
|
||||
for file in range(32,33):
|
||||
lod.seek(92+(file*32))
|
||||
name = lod.read(16).split("\0")[0]
|
||||
offset = struct.unpack("i", lod.read(4))[0] #offset
|
||||
size_orig = struct.unpack("i", lod.read(4))[0] #size_original
|
||||
type = struct.unpack("i", lod.read(4))[0] #type
|
||||
size_comp = struct.unpack("i", lod.read(4))[0] #size_compressed
|
||||
|
||||
lod.seek(offset)
|
||||
|
||||
if size_comp:
|
||||
pcx = zlib.decompress(lod.read(size_comp))
|
||||
else:
|
||||
pcx = lod.read(size_orig)
|
||||
|
||||
if type == 16:
|
||||
size = struct.unpack("i", pcx[:4])[0]
|
||||
width = struct.unpack("i", pcx[4:8])[0]
|
||||
height = struct.unpack("I", pcx[8:12])[0]
|
||||
print size, width, height
|
||||
im = Image.fromstring("L", (width, height), pcx[12:12+size])
|
||||
im.putpalette(pcx[12+size:12+size+768])
|
||||
im.save(' '.join([str(file),name]), "PNG")
|
||||
if type == 17:
|
||||
size = struct.unpack("i", pcx[:4])[0]
|
||||
width = struct.unpack("i", pcx[4:8])[0]
|
||||
height = struct.unpack("I", pcx[8:12])[0]
|
||||
print size, width, height
|
||||
im = Image.fromstring("RGB", (width, height), pcx[12:12+size])
|
||||
im.save(' '.join([str(file),name]), "PNG")
|
||||
elif type in (1, 2, 64, 65, 66, 67, 68, 69, 70, 71, 73, 79, 80, 96):
|
||||
print file, name
|
||||
file = open(' '.join([str(file),name]), "w")
|
||||
file.write(pcx)
|
||||
file.close()
|
||||
else:
|
||||
print i, name, type
|
||||
sys.exit("not supported %d"%type)
|
||||
|
||||
lod.close()
|
19
lodlist.py
Normal file
19
lodlist.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import struct
|
||||
from sys import argv
|
||||
|
||||
lod = open(argv[1])
|
||||
lod.seek(8)
|
||||
files_count = struct.unpack("i", lod.read(4))[0]
|
||||
files=[]
|
||||
for file in xrange(files_count):
|
||||
lod.seek(92+(file*32))
|
||||
name = lod.read(16).split("\0")[0]
|
||||
offset = struct.unpack("i", lod.read(4))[0] #offset
|
||||
size_orig = struct.unpack("i", lod.read(4))[0] #size_original
|
||||
type = struct.unpack("i", lod.read(4))[0] #type
|
||||
size_comp = struct.unpack("i", lod.read(4))[0] #size_compressed
|
||||
print name
|
||||
|
||||
lod.close()
|
1801
logo.svg
Normal file
1801
logo.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 711 KiB |
102
logo_alt.svg
Normal file
102
logo_alt.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 28 KiB |
Loading…
Reference in a new issue